Add support for Oxford PCI Express Expresso family devices.
For these devices, the number of supported ports is read from a register in BAR 0. PR: kern/134878 Submitted by: David Wood david of wood2 org uk MFC after: 1 week
This commit is contained in:
parent
41b1c25960
commit
6e9f075a26
@ -56,6 +56,7 @@ static puc_config_f puc_config_syba;
|
||||
static puc_config_f puc_config_siig;
|
||||
static puc_config_f puc_config_timedia;
|
||||
static puc_config_f puc_config_titan;
|
||||
static puc_config_f puc_config_oxford_pcie;
|
||||
|
||||
const struct puc_cfg puc_pci_devices[] = {
|
||||
|
||||
@ -619,7 +620,7 @@ const struct puc_cfg puc_pci_devices[] = {
|
||||
* Boards with an Oxford Semiconductor chip.
|
||||
*
|
||||
* Oxford Semiconductor provides documentation for their chip at:
|
||||
* <URL:http://www.oxsemi.com/products/uarts/index.html>
|
||||
* <URL:http://www.plxtech.com/products/uart/>
|
||||
*
|
||||
* As sold by Kouwell <URL:http://www.kouwell.com/>.
|
||||
* I/O Flex PCI I/O Card Model-223 with 4 serial and 1 parallel ports.
|
||||
@ -679,6 +680,63 @@ const struct puc_cfg puc_pci_devices[] = {
|
||||
PUC_PORT_4S, 0x10, 0, 8,
|
||||
},
|
||||
|
||||
/*
|
||||
* Oxford Semiconductor PCI Express Expresso family
|
||||
*
|
||||
* Found in many 'native' PCI Express serial boards such as:
|
||||
*
|
||||
* eMegatech MP954ER4 (4 port) and MP958ER8 (8 port)
|
||||
* <URL:http://www.emegatech.com.tw/pdrs232pcie.html>
|
||||
*
|
||||
* Lindy 51189 (4 port)
|
||||
* <URL:http://www.lindy.com> <URL:http://tinyurl.com/lindy-51189>
|
||||
*
|
||||
* StarTech.com PEX4S952 (4 port) and PEX8S952 (8 port)
|
||||
* <URL:http://www.startech.com>
|
||||
*/
|
||||
|
||||
{ 0x1415, 0xc158, 0xffff, 0,
|
||||
"Oxford Semiconductor OXPCIe952 UARTs",
|
||||
DEFAULT_RCLK * 0x22,
|
||||
PUC_PORT_NONSTANDARD, 0x10, 0, -1,
|
||||
.config_function = puc_config_oxford_pcie
|
||||
},
|
||||
|
||||
{ 0x1415, 0xc15d, 0xffff, 0,
|
||||
"Oxford Semiconductor OXPCIe952 UARTs (function 1)",
|
||||
DEFAULT_RCLK * 0x22,
|
||||
PUC_PORT_NONSTANDARD, 0x10, 0, -1,
|
||||
.config_function = puc_config_oxford_pcie
|
||||
},
|
||||
|
||||
{ 0x1415, 0xc208, 0xffff, 0,
|
||||
"Oxford Semiconductor OXPCIe954 UARTs",
|
||||
DEFAULT_RCLK * 0x22,
|
||||
PUC_PORT_NONSTANDARD, 0x10, 0, -1,
|
||||
.config_function = puc_config_oxford_pcie
|
||||
},
|
||||
|
||||
{ 0x1415, 0xc20d, 0xffff, 0,
|
||||
"Oxford Semiconductor OXPCIe954 UARTs (function 1)",
|
||||
DEFAULT_RCLK * 0x22,
|
||||
PUC_PORT_NONSTANDARD, 0x10, 0, -1,
|
||||
.config_function = puc_config_oxford_pcie
|
||||
},
|
||||
|
||||
{ 0x1415, 0xc308, 0xffff, 0,
|
||||
"Oxford Semiconductor OXPCIe958 UARTs",
|
||||
DEFAULT_RCLK * 0x22,
|
||||
PUC_PORT_NONSTANDARD, 0x10, 0, -1,
|
||||
.config_function = puc_config_oxford_pcie
|
||||
},
|
||||
|
||||
{ 0x1415, 0xc30d, 0xffff, 0,
|
||||
"Oxford Semiconductor OXPCIe958 UARTs (function 1)",
|
||||
DEFAULT_RCLK * 0x22,
|
||||
PUC_PORT_NONSTANDARD, 0x10, 0, -1,
|
||||
.config_function = puc_config_oxford_pcie
|
||||
},
|
||||
|
||||
{ 0x14d2, 0x8010, 0xffff, 0,
|
||||
"VScom PCI-100L",
|
||||
DEFAULT_RCLK * 8,
|
||||
@ -1252,6 +1310,81 @@ puc_config_timedia(struct puc_softc *sc, enum puc_cfg_cmd cmd, int port,
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
static int
|
||||
puc_config_oxford_pcie(struct puc_softc *sc, enum puc_cfg_cmd cmd, int port,
|
||||
intptr_t *res)
|
||||
{
|
||||
const struct puc_cfg *cfg = sc->sc_cfg;
|
||||
int idx;
|
||||
struct puc_bar *bar;
|
||||
uint8_t value;
|
||||
|
||||
switch (cmd) {
|
||||
case PUC_CFG_SETUP:
|
||||
device_printf(sc->sc_dev, "%d UARTs detected\n",
|
||||
sc->sc_nports);
|
||||
|
||||
/* Set UARTs to enhanced mode */
|
||||
bar = puc_get_bar(sc, cfg->rid);
|
||||
if (bar == NULL)
|
||||
return (ENXIO);
|
||||
|
||||
for (idx = 0; idx < sc->sc_nports; idx++) {
|
||||
value = bus_read_1(bar->b_res, 0x1000 + (idx << 9)
|
||||
+ 0x92);
|
||||
bus_write_1(bar->b_res, 0x1000 + (idx << 9) + 0x92,
|
||||
value | 0x10);
|
||||
}
|
||||
|
||||
return (0);
|
||||
case PUC_CFG_GET_LEN:
|
||||
*res = 0x200;
|
||||
return (0);
|
||||
case PUC_CFG_GET_NPORTS:
|
||||
/*
|
||||
* Check if we are being called from puc_bfe_attach()
|
||||
* or puc_bfe_probe(). If puc_bfe_probe(), we cannot
|
||||
* puc_get_bar(), so we return a value of 16. This has cosmetic
|
||||
* side-effects at worst; in PUC_CFG_GET_DESC,
|
||||
* (int)sc->sc_cfg_data will not contain the true number of
|
||||
* ports in PUC_CFG_GET_DESC, but we are not implementing that
|
||||
* call for this device family anyway.
|
||||
*
|
||||
* The check is for initialisation of sc->sc_bar[idx], which is
|
||||
* only done in puc_bfe_attach().
|
||||
*/
|
||||
idx = 0;
|
||||
do {
|
||||
if (sc->sc_bar[idx++].b_rid != -1) {
|
||||
sc->sc_cfg_data = 16;
|
||||
*res = sc->sc_cfg_data;
|
||||
return (0);
|
||||
}
|
||||
} while (idx < PUC_PCI_BARS);
|
||||
|
||||
bar = puc_get_bar(sc, cfg->rid);
|
||||
if (bar == NULL)
|
||||
return (ENXIO);
|
||||
|
||||
value = bus_read_1(bar->b_res, 0x04);
|
||||
if (value == 0)
|
||||
return (ENXIO);
|
||||
|
||||
sc->sc_cfg_data = value;
|
||||
*res = sc->sc_cfg_data;
|
||||
return (0);
|
||||
case PUC_CFG_GET_OFS:
|
||||
*res = 0x1000 + (port << 9);
|
||||
return (0);
|
||||
case PUC_CFG_GET_TYPE:
|
||||
*res = PUC_TYPE_SERIAL;
|
||||
return (0);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
static int
|
||||
puc_config_titan(struct puc_softc *sc, enum puc_cfg_cmd cmd, int port,
|
||||
intptr_t *res)
|
||||
|
Loading…
Reference in New Issue
Block a user