X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fserial%2F8250_pci.c;h=851e4839d6d97c0ad7501dea1798af815f5a00cb;hb=16c70f8c1b54b61c3b951b6fb220df250fe09b32;hp=cf42b9d0c2fa623d2f937cd584b65fadc63320cf;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c index cf42b9d0c..851e4839d 100644 --- a/drivers/serial/8250_pci.c +++ b/drivers/serial/8250_pci.c @@ -22,46 +22,16 @@ #include #include #include -#include #include #include +#include -#include #include -#include #include #include "8250.h" -/* - * Definitions for PCI support. - */ -#define FL_BASE_MASK 0x0007 -#define FL_BASE0 0x0000 -#define FL_BASE1 0x0001 -#define FL_BASE2 0x0002 -#define FL_BASE3 0x0003 -#define FL_BASE4 0x0004 -#define FL_GET_BASE(x) (x & FL_BASE_MASK) - -/* Use successive BARs (PCI base address registers), - else use offset into some specified BAR */ -#define FL_BASE_BARS 0x0008 - -/* do not assign an irq */ -#define FL_NOIRQ 0x0080 - -/* Use the Base address register size to cap number of ports */ -#define FL_REGION_SZ_CAP 0x0100 - -struct pci_board { - unsigned int flags; - unsigned int num_ports; - unsigned int base_baud; - unsigned int uart_offset; - unsigned int reg_shift; - unsigned int first_offset; -}; +#undef SERIAL_DEBUG_PCI /* * init function returns: @@ -75,16 +45,17 @@ struct pci_serial_quirk { u32 subvendor; u32 subdevice; int (*init)(struct pci_dev *dev); - int (*setup)(struct pci_dev *dev, struct pci_board *board, - struct serial_struct *req, int idx); + int (*setup)(struct serial_private *, struct pciserial_board *, + struct uart_port *, int); void (*exit)(struct pci_dev *dev); }; #define PCI_NUM_BAR_RESOURCES 6 struct serial_private { + struct pci_dev *dev; unsigned int nr; - void *remapped_bar[PCI_NUM_BAR_RESOURCES]; + void __iomem *remapped_bar[PCI_NUM_BAR_RESOURCES]; struct pci_serial_quirk *quirk; int line[0]; }; @@ -101,34 +72,36 @@ static void moan_device(const char *str, struct pci_dev *dev) } static int -setup_port(struct pci_dev *dev, struct serial_struct *req, +setup_port(struct serial_private *priv, struct uart_port *port, int bar, int offset, int regshift) { - struct serial_private *priv = pci_get_drvdata(dev); - unsigned long port, len; + struct pci_dev *dev = priv->dev; + unsigned long base, len; if (bar >= PCI_NUM_BAR_RESOURCES) return -EINVAL; + base = pci_resource_start(dev, bar); + if (pci_resource_flags(dev, bar) & IORESOURCE_MEM) { - port = pci_resource_start(dev, bar); len = pci_resource_len(dev, bar); if (!priv->remapped_bar[bar]) - priv->remapped_bar[bar] = ioremap(port, len); + priv->remapped_bar[bar] = ioremap(base, len); if (!priv->remapped_bar[bar]) return -ENOMEM; - req->io_type = UPIO_MEM; - req->iomap_base = port + offset; - req->iomem_base = priv->remapped_bar[bar] + offset; - req->iomem_reg_shift = regshift; + port->iotype = UPIO_MEM; + port->iobase = 0; + port->mapbase = base + offset; + port->membase = priv->remapped_bar[bar] + offset; + port->regshift = regshift; } else { - port = pci_resource_start(dev, bar) + offset; - req->io_type = UPIO_PORT; - req->port = port; - if (HIGH_BITS_OFFSET) - req->port_high = port >> HIGH_BITS_OFFSET; + port->iotype = UPIO_PORT; + port->iobase = base + offset; + port->mapbase = 0; + port->membase = NULL; + port->regshift = 0; } return 0; } @@ -138,8 +111,8 @@ setup_port(struct pci_dev *dev, struct serial_struct *req, * Not that ugly ;) -- HW */ static int -afavlab_setup(struct pci_dev *dev, struct pci_board *board, - struct serial_struct *req, int idx) +afavlab_setup(struct serial_private *priv, struct pciserial_board *board, + struct uart_port *port, int idx) { unsigned int bar, offset = board->first_offset; @@ -151,7 +124,7 @@ afavlab_setup(struct pci_dev *dev, struct pci_board *board, offset += (idx - 4) * board->uart_offset; } - return setup_port(dev, req, bar, offset, board->reg_shift); + return setup_port(priv, port, bar, offset, board->reg_shift); } /* @@ -161,7 +134,7 @@ afavlab_setup(struct pci_dev *dev, struct pci_board *board, * and Keystone have one Diva chip with 3 UARTs. Some later machines have * one Diva chip, but it has been expanded to 5 UARTs. */ -static int __devinit pci_hp_diva_init(struct pci_dev *dev) +static int pci_hp_diva_init(struct pci_dev *dev) { int rc = 0; @@ -179,6 +152,7 @@ static int __devinit pci_hp_diva_init(struct pci_dev *dev) rc = 4; break; case PCI_DEVICE_ID_HP_DIVA_POWERBAR: + case PCI_DEVICE_ID_HP_DIVA_HURRICANE: rc = 1; break; } @@ -191,13 +165,13 @@ static int __devinit pci_hp_diva_init(struct pci_dev *dev) * some serial ports are supposed to be hidden on certain models. */ static int -pci_hp_diva_setup(struct pci_dev *dev, struct pci_board *board, - struct serial_struct *req, int idx) +pci_hp_diva_setup(struct serial_private *priv, struct pciserial_board *board, + struct uart_port *port, int idx) { unsigned int offset = board->first_offset; unsigned int bar = FL_GET_BASE(board->flags); - switch (dev->subsystem_device) { + switch (priv->dev->subsystem_device) { case PCI_DEVICE_ID_HP_DIVA_MAESTRO: if (idx == 3) idx++; @@ -214,13 +188,13 @@ pci_hp_diva_setup(struct pci_dev *dev, struct pci_board *board, offset += idx * board->uart_offset; - return setup_port(dev, req, bar, offset, board->reg_shift); + return setup_port(priv, port, bar, offset, board->reg_shift); } /* * Added for EKF Intel i960 serial boards */ -static int __devinit pci_inteli960ni_init(struct pci_dev *dev) +static int pci_inteli960ni_init(struct pci_dev *dev) { unsigned long oldval; @@ -242,9 +216,10 @@ static int __devinit pci_inteli960ni_init(struct pci_dev *dev) * seems to be mainly needed on card using the PLX which also use I/O * mapped memory. */ -static int __devinit pci_plx9050_init(struct pci_dev *dev) +static int pci_plx9050_init(struct pci_dev *dev) { - u8 *p, irq_config; + u8 irq_config; + void __iomem *p; if ((pci_resource_flags(dev, 0) & IORESOURCE_MEM) == 0) { moan_device("no memory in bar 0", dev); @@ -252,8 +227,10 @@ static int __devinit pci_plx9050_init(struct pci_dev *dev) } irq_config = 0x41; - if (dev->vendor == PCI_VENDOR_ID_PANACOM) + if (dev->vendor == PCI_VENDOR_ID_PANACOM || + dev->subsystem_vendor == PCI_SUBVENDOR_ID_EXSYS) { irq_config = 0x43; + } if ((dev->vendor == PCI_VENDOR_ID_PLX) && (dev->device == PCI_DEVICE_ID_PLX_ROMULUS)) { /* @@ -273,12 +250,12 @@ static int __devinit pci_plx9050_init(struct pci_dev *dev) p = ioremap(pci_resource_start(dev, 0), 0x80); if (p == NULL) return -ENOMEM; - writel(irq_config, (unsigned long)p + 0x4c); + writel(irq_config, p + 0x4c); /* * Read the register back to ensure that it took effect. */ - readl((unsigned long)p + 0x4c); + readl(p + 0x4c); iounmap(p); return 0; @@ -286,7 +263,7 @@ static int __devinit pci_plx9050_init(struct pci_dev *dev) static void __devexit pci_plx9050_exit(struct pci_dev *dev) { - u8 *p; + u8 __iomem *p; if ((pci_resource_flags(dev, 0) & IORESOURCE_MEM) == 0) return; @@ -308,8 +285,8 @@ static void __devexit pci_plx9050_exit(struct pci_dev *dev) /* SBS Technologies Inc. PMC-OCTPRO and P-OCTAL cards */ static int -sbs_setup(struct pci_dev *dev, struct pci_board *board, - struct serial_struct *req, int idx) +sbs_setup(struct serial_private *priv, struct pciserial_board *board, + struct uart_port *port, int idx) { unsigned int bar, offset = board->first_offset; @@ -324,7 +301,7 @@ sbs_setup(struct pci_dev *dev, struct pci_board *board, } else /* we have only 8 ports on PMC-OCTALPRO */ return 1; - return setup_port(dev, req, bar, offset, board->reg_shift); + return setup_port(priv, port, bar, offset, board->reg_shift); } /* @@ -337,9 +314,9 @@ sbs_setup(struct pci_dev *dev, struct pci_board *board, /* global control register offset for SBS PMC-OctalPro */ #define OCT_REG_CR_OFF 0x500 -static int __devinit sbs_init(struct pci_dev *dev) +static int sbs_init(struct pci_dev *dev) { - u8 * p; + u8 __iomem *p; p = ioremap(pci_resource_start(dev, 0),pci_resource_len(dev,0)); @@ -363,7 +340,7 @@ static int __devinit sbs_init(struct pci_dev *dev) static void __devexit sbs_exit(struct pci_dev *dev) { - u8 * p; + u8 __iomem *p; p = ioremap(pci_resource_start(dev, 0),pci_resource_len(dev,0)); if (p != NULL) { @@ -390,6 +367,12 @@ static void __devexit sbs_exit(struct pci_dev *dev) * - 10x cards have control registers in IO and/or memory space; * - 20x cards have control registers in standard PCI configuration space. * + * Note: all 10x cards have PCI device ids 0x10.. + * all 20x cards have PCI device ids 0x20.. + * + * There are also Quartet Serial cards which use Oxford Semiconductor + * 16954 quad UART PCI chip clocked by 18.432 MHz quartz. + * * Note: some SIIG cards are probed by the parport_serial object. */ @@ -398,7 +381,8 @@ static void __devexit sbs_exit(struct pci_dev *dev) static int pci_siig10x_init(struct pci_dev *dev) { - u16 data, *p; + u16 data; + void __iomem *p; switch (dev->device & 0xfff8) { case PCI_DEVICE_ID_SIIG_1S_10x: /* 1S */ @@ -416,8 +400,8 @@ static int pci_siig10x_init(struct pci_dev *dev) if (p == NULL) return -ENOMEM; - writew(readw((unsigned long) p + 0x28) & data, (unsigned long) p + 0x28); - readw((unsigned long)p + 0x28); + writew(readw(p + 0x28) & data, p + 0x28); + readw(p + 0x28); iounmap(p); return 0; } @@ -442,35 +426,43 @@ static int pci_siig20x_init(struct pci_dev *dev) return 0; } -int pci_siig10x_fn(struct pci_dev *dev, int enable) +static int pci_siig_init(struct pci_dev *dev) { - int ret = 0; - if (enable) - ret = pci_siig10x_init(dev); - return ret; + unsigned int type = dev->device & 0xff00; + + if (type == 0x1000) + return pci_siig10x_init(dev); + else if (type == 0x2000) + return pci_siig20x_init(dev); + + moan_device("Unknown SIIG card", dev); + return -ENODEV; } -int pci_siig20x_fn(struct pci_dev *dev, int enable) +static int pci_siig_setup(struct serial_private *priv, + struct pciserial_board *board, + struct uart_port *port, int idx) { - int ret = 0; - if (enable) - ret = pci_siig20x_init(dev); - return ret; -} + unsigned int bar = FL_GET_BASE(board->flags) + idx, offset = 0; -EXPORT_SYMBOL(pci_siig10x_fn); -EXPORT_SYMBOL(pci_siig20x_fn); + if (idx > 3) { + bar = 4; + offset = (idx - 4) * 8; + } + + return setup_port(priv, port, bar, offset, 0); +} /* * Timedia has an explosion of boards, and to avoid the PCI table from * growing *huge*, we use this function to collapse some 70 entries * in the PCI table into one, for sanity's and compactness's sake. */ -static unsigned short timedia_single_port[] = { +static const unsigned short timedia_single_port[] = { 0x4025, 0x4027, 0x4028, 0x5025, 0x5027, 0 }; -static unsigned short timedia_dual_port[] = { +static const unsigned short timedia_dual_port[] = { 0x0002, 0x4036, 0x4037, 0x4038, 0x4078, 0x4079, 0x4085, 0x4088, 0x4089, 0x5037, 0x5078, 0x5079, 0x5085, 0x6079, 0x7079, 0x8079, 0x8137, 0x8138, 0x8237, 0x8238, 0x9079, @@ -478,35 +470,34 @@ static unsigned short timedia_dual_port[] = { 0xD079, 0 }; -static unsigned short timedia_quad_port[] = { +static const unsigned short timedia_quad_port[] = { 0x4055, 0x4056, 0x4095, 0x4096, 0x5056, 0x8156, 0x8157, 0x8256, 0x8257, 0x9056, 0x9156, 0x9157, 0x9158, 0x9159, 0x9256, 0x9257, 0xA056, 0xA157, 0xA158, 0xA159, 0xB056, 0xB157, 0 }; -static unsigned short timedia_eight_port[] = { +static const unsigned short timedia_eight_port[] = { 0x4065, 0x4066, 0x5065, 0x5066, 0x8166, 0x9066, 0x9166, 0x9167, 0x9168, 0xA066, 0xA167, 0xA168, 0 }; -static struct timedia_struct { +static const struct timedia_struct { int num; - unsigned short *ids; + const unsigned short *ids; } timedia_data[] = { { 1, timedia_single_port }, { 2, timedia_dual_port }, { 4, timedia_quad_port }, - { 8, timedia_eight_port }, - { 0, 0 } + { 8, timedia_eight_port } }; -static int __devinit pci_timedia_init(struct pci_dev *dev) +static int pci_timedia_init(struct pci_dev *dev) { - unsigned short *ids; + const unsigned short *ids; int i, j; - for (i = 0; timedia_data[i].num; i++) { + for (i = 0; i < ARRAY_SIZE(timedia_data); i++) { ids = timedia_data[i].ids; for (j = 0; ids[j]; j++) if (dev->subsystem_device == ids[j]) @@ -520,8 +511,8 @@ static int __devinit pci_timedia_init(struct pci_dev *dev) * Ugh, this is ugly as all hell --- TYT */ static int -pci_timedia_setup(struct pci_dev *dev, struct pci_board *board, - struct serial_struct *req, int idx) +pci_timedia_setup(struct serial_private *priv, struct pciserial_board *board, + struct uart_port *port, int idx) { unsigned int bar = 0, offset = board->first_offset; @@ -538,7 +529,7 @@ pci_timedia_setup(struct pci_dev *dev, struct pci_board *board, break; case 3: offset = board->uart_offset; - bar = 1; + /* FALLTHROUGH */ case 4: /* BAR 2 */ case 5: /* BAR 3 */ case 6: /* BAR 4 */ @@ -546,15 +537,16 @@ pci_timedia_setup(struct pci_dev *dev, struct pci_board *board, bar = idx - 2; } - return setup_port(dev, req, bar, offset, board->reg_shift); + return setup_port(priv, port, bar, offset, board->reg_shift); } /* * Some Titan cards are also a little weird */ static int -titan_400l_800l_setup(struct pci_dev *dev, struct pci_board *board, - struct serial_struct *req, int idx) +titan_400l_800l_setup(struct serial_private *priv, + struct pciserial_board *board, + struct uart_port *port, int idx) { unsigned int bar, offset = board->first_offset; @@ -570,19 +562,28 @@ titan_400l_800l_setup(struct pci_dev *dev, struct pci_board *board, offset = (idx - 2) * board->uart_offset; } - return setup_port(dev, req, bar, offset, board->reg_shift); + return setup_port(priv, port, bar, offset, board->reg_shift); } -static int __devinit pci_xircom_init(struct pci_dev *dev) +static int pci_xircom_init(struct pci_dev *dev) { - __set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ/10); + msleep(100); return 0; } +static int pci_netmos_init(struct pci_dev *dev) +{ + /* subdevice 0x00PS means

parallel, serial */ + unsigned int num_serial = dev->subsystem_device & 0xf; + + if (num_serial == 0) + return -ENODEV; + return num_serial; +} + static int -pci_default_setup(struct pci_dev *dev, struct pci_board *board, - struct serial_struct *req, int idx) +pci_default_setup(struct serial_private *priv, struct pciserial_board *board, + struct uart_port *port, int idx) { unsigned int bar, offset = board->first_offset, maxnr; @@ -592,13 +593,13 @@ pci_default_setup(struct pci_dev *dev, struct pci_board *board, else offset += idx * board->uart_offset; - maxnr = (pci_resource_len(dev, bar) - board->first_offset) / - (8 << board->reg_shift); + maxnr = (pci_resource_len(priv->dev, bar) - board->first_offset) >> + (board->reg_shift + 3); if (board->flags & FL_REGION_SZ_CAP && idx >= maxnr) return 1; - return setup_port(dev, req, bar, offset, board->reg_shift); + return setup_port(priv, port, bar, offset, board->reg_shift); } /* This should be in linux/pci_ids.h */ @@ -620,7 +621,7 @@ pci_default_setup(struct pci_dev *dev, struct pci_board *board, */ static struct pci_serial_quirk pci_serial_quirks[] = { /* - * AFAVLAB cards. + * AFAVLAB cards - these may be called via parport_serial * It is not clear whether this applies to all products. */ { @@ -676,6 +677,15 @@ static struct pci_serial_quirk pci_serial_quirks[] = { /* * PLX */ + { + .vendor = PCI_VENDOR_ID_PLX, + .device = PCI_DEVICE_ID_PLX_9050, + .subvendor = PCI_SUBVENDOR_ID_EXSYS, + .subdevice = PCI_SUBDEVICE_ID_EXSYS_4055, + .init = pci_plx9050_init, + .setup = pci_default_setup, + .exit = __devexit_p(pci_plx9050_exit), + }, { .vendor = PCI_VENDOR_ID_PLX, .device = PCI_DEVICE_ID_PLX_9050, @@ -704,7 +714,7 @@ static struct pci_serial_quirk pci_serial_quirks[] = { .subdevice = PCI_SUBDEVICE_ID_OCTPRO232, .init = sbs_init, .setup = sbs_setup, - .exit = sbs_exit + .exit = __devexit_p(sbs_exit), }, /* * SBS Technologies, Inc., PMC-OCTALPRO 422 @@ -716,7 +726,7 @@ static struct pci_serial_quirk pci_serial_quirks[] = { .subdevice = PCI_SUBDEVICE_ID_OCTPRO422, .init = sbs_init, .setup = sbs_setup, - .exit = sbs_exit + .exit = __devexit_p(sbs_exit), }, /* * SBS Technologies, Inc., P-Octal 232 @@ -728,7 +738,7 @@ static struct pci_serial_quirk pci_serial_quirks[] = { .subdevice = PCI_SUBDEVICE_ID_POCTAL232, .init = sbs_init, .setup = sbs_setup, - .exit = sbs_exit + .exit = __devexit_p(sbs_exit), }, /* * SBS Technologies, Inc., P-Octal 422 @@ -740,155 +750,18 @@ static struct pci_serial_quirk pci_serial_quirks[] = { .subdevice = PCI_SUBDEVICE_ID_POCTAL422, .init = sbs_init, .setup = sbs_setup, - .exit = sbs_exit + .exit = __devexit_p(sbs_exit), }, - /* - * SIIG cards. - * It is not clear whether these could be collapsed. + * SIIG cards - these may be called via parport_serial */ { .vendor = PCI_VENDOR_ID_SIIG, - .device = PCI_DEVICE_ID_SIIG_1S_10x_550, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .init = pci_siig10x_init, - .setup = pci_default_setup, - }, - { - .vendor = PCI_VENDOR_ID_SIIG, - .device = PCI_DEVICE_ID_SIIG_1S_10x_650, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .init = pci_siig10x_init, - .setup = pci_default_setup, - }, - { - .vendor = PCI_VENDOR_ID_SIIG, - .device = PCI_DEVICE_ID_SIIG_1S_10x_850, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .init = pci_siig10x_init, - .setup = pci_default_setup, - }, - { - .vendor = PCI_VENDOR_ID_SIIG, - .device = PCI_DEVICE_ID_SIIG_2S_10x_550, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .init = pci_siig10x_init, - .setup = pci_default_setup, - }, - { - .vendor = PCI_VENDOR_ID_SIIG, - .device = PCI_DEVICE_ID_SIIG_2S_10x_650, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .init = pci_siig10x_init, - .setup = pci_default_setup, - }, - { - .vendor = PCI_VENDOR_ID_SIIG, - .device = PCI_DEVICE_ID_SIIG_2S_10x_850, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .init = pci_siig10x_init, - .setup = pci_default_setup, - }, - { - .vendor = PCI_VENDOR_ID_SIIG, - .device = PCI_DEVICE_ID_SIIG_4S_10x_550, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .init = pci_siig10x_init, - .setup = pci_default_setup, - }, - { - .vendor = PCI_VENDOR_ID_SIIG, - .device = PCI_DEVICE_ID_SIIG_4S_10x_650, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .init = pci_siig10x_init, - .setup = pci_default_setup, - }, - { - .vendor = PCI_VENDOR_ID_SIIG, - .device = PCI_DEVICE_ID_SIIG_4S_10x_850, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .init = pci_siig10x_init, - .setup = pci_default_setup, - }, - { - .vendor = PCI_VENDOR_ID_SIIG, - .device = PCI_DEVICE_ID_SIIG_1S_20x_550, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .init = pci_siig20x_init, - .setup = pci_default_setup, - }, - { - .vendor = PCI_VENDOR_ID_SIIG, - .device = PCI_DEVICE_ID_SIIG_1S_20x_650, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .init = pci_siig20x_init, - .setup = pci_default_setup, - }, - { - .vendor = PCI_VENDOR_ID_SIIG, - .device = PCI_DEVICE_ID_SIIG_1S_20x_850, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .init = pci_siig20x_init, - .setup = pci_default_setup, - }, - { - .vendor = PCI_VENDOR_ID_SIIG, - .device = PCI_DEVICE_ID_SIIG_2S_20x_550, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .init = pci_siig20x_init, - .setup = pci_default_setup, - }, - { .vendor = PCI_VENDOR_ID_SIIG, - .device = PCI_DEVICE_ID_SIIG_2S_20x_650, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .init = pci_siig20x_init, - .setup = pci_default_setup, - }, - { - .vendor = PCI_VENDOR_ID_SIIG, - .device = PCI_DEVICE_ID_SIIG_2S_20x_850, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .init = pci_siig20x_init, - .setup = pci_default_setup, - }, - { - .vendor = PCI_VENDOR_ID_SIIG, - .device = PCI_DEVICE_ID_SIIG_4S_20x_550, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .init = pci_siig20x_init, - .setup = pci_default_setup, - }, - { - .vendor = PCI_VENDOR_ID_SIIG, - .device = PCI_DEVICE_ID_SIIG_4S_20x_650, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .init = pci_siig20x_init, - .setup = pci_default_setup, - }, - { - .vendor = PCI_VENDOR_ID_SIIG, - .device = PCI_DEVICE_ID_SIIG_4S_20x_850, + .device = PCI_ANY_ID, .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, - .init = pci_siig20x_init, - .setup = pci_default_setup, + .init = pci_siig_init, + .setup = pci_siig_setup, }, /* * Titan cards @@ -936,6 +809,17 @@ static struct pci_serial_quirk pci_serial_quirks[] = { .init = pci_xircom_init, .setup = pci_default_setup, }, + /* + * Netmos cards - these may be called via parport_serial + */ + { + .vendor = PCI_VENDOR_ID_NETMOS, + .device = PCI_ANY_ID, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_netmos_init, + .setup = pci_default_setup, + }, /* * Default "match everything" terminator entry */ @@ -966,8 +850,8 @@ static struct pci_serial_quirk *find_quirk(struct pci_dev *dev) return quirk; } -static _INLINE_ int -get_pci_irq(struct pci_dev *dev, struct pci_board *board, int idx) +static inline int get_pci_irq(struct pci_dev *dev, + struct pciserial_board *board) { if (board->flags & FL_NOIRQ) return 0; @@ -982,12 +866,15 @@ get_pci_irq(struct pci_dev *dev, struct pci_board *board, int idx) * driver_data member. * * The makeup of these names are: - * pbn_bn{_bt}_n_baud + * pbn_bn{_bt}_n_baud{_offsetinhex} + * + * bn = PCI BAR number + * bt = Index using PCI BARs + * n = number of serial ports + * baud = baud rate + * offsetinhex = offset for each sequential port (in hex) * - * bn = PCI BAR number - * bt = Index using PCI BARs - * n = number of serial ports - * baud = baud rate + * This table is sorted by (in order): bn, bt, baud, offsetindex, n. * * Please note: in theory if n = 1, _bt infix should make no difference. * ie, pbn_b0_1_115200 is the same as pbn_b0_bt_1_115200 @@ -1004,6 +891,17 @@ enum pci_board_num_t { pbn_b0_2_921600, pbn_b0_4_921600, + pbn_b0_2_1130000, + + pbn_b0_4_1152000, + + pbn_b0_2_1843200, + pbn_b0_4_1843200, + + pbn_b0_2_1843200_200, + pbn_b0_4_1843200_200, + pbn_b0_8_1843200_200, + pbn_b0_bt_1_115200, pbn_b0_bt_2_115200, pbn_b0_bt_8_115200, @@ -1027,13 +925,17 @@ enum pci_board_num_t { pbn_b1_4_921600, pbn_b1_8_921600, + pbn_b1_2_1250000, + pbn_b1_bt_2_921600, + pbn_b1_1_1382400, pbn_b1_2_1382400, pbn_b1_4_1382400, pbn_b1_8_1382400, pbn_b2_1_115200, + pbn_b2_2_115200, pbn_b2_8_115200, pbn_b2_1_460800, @@ -1052,6 +954,7 @@ enum pci_board_num_t { pbn_b2_bt_2_921600, pbn_b2_bt_4_921600, + pbn_b3_2_115200, pbn_b3_4_115200, pbn_b3_8_115200, @@ -1061,6 +964,7 @@ enum pci_board_num_t { pbn_panacom, pbn_panacom2, pbn_panacom4, + pbn_exsys_4055, pbn_plx_romulus, pbn_oxsemi, pbn_intel_i960, @@ -1070,6 +974,9 @@ enum pci_board_num_t { pbn_computone_6, pbn_computone_8, pbn_sbsxrsio, + pbn_exar_XR17C152, + pbn_exar_XR17C154, + pbn_exar_XR17C158, }; /* @@ -1082,7 +989,7 @@ enum pci_board_num_t { * see first lines of serial_in() and serial_out() in 8250.c */ -static struct pci_board pci_boards[] __devinitdata = { +static struct pciserial_board pci_boards[] __devinitdata = { [pbn_default] = { .flags = FL_BASE0, .num_ports = 1, @@ -1133,6 +1040,52 @@ static struct pci_board pci_boards[] __devinitdata = { .uart_offset = 8, }, + [pbn_b0_2_1130000] = { + .flags = FL_BASE0, + .num_ports = 2, + .base_baud = 1130000, + .uart_offset = 8, + }, + + [pbn_b0_4_1152000] = { + .flags = FL_BASE0, + .num_ports = 4, + .base_baud = 1152000, + .uart_offset = 8, + }, + + [pbn_b0_2_1843200] = { + .flags = FL_BASE0, + .num_ports = 2, + .base_baud = 1843200, + .uart_offset = 8, + }, + [pbn_b0_4_1843200] = { + .flags = FL_BASE0, + .num_ports = 4, + .base_baud = 1843200, + .uart_offset = 8, + }, + + [pbn_b0_2_1843200_200] = { + .flags = FL_BASE0, + .num_ports = 2, + .base_baud = 1843200, + .uart_offset = 0x200, + }, + [pbn_b0_4_1843200_200] = { + .flags = FL_BASE0, + .num_ports = 4, + .base_baud = 1843200, + .uart_offset = 0x200, + }, + [pbn_b0_8_1843200_200] = { + .flags = FL_BASE0, + .num_ports = 8, + .base_baud = 1843200, + .uart_offset = 0x200, + }, + [pbn_b0_bt_1_115200] = { .flags = FL_BASE0|FL_BASE_BARS, .num_ports = 1, @@ -1245,6 +1198,12 @@ static struct pci_board pci_boards[] __devinitdata = { .base_baud = 921600, .uart_offset = 8, }, + [pbn_b1_2_1250000] = { + .flags = FL_BASE1, + .num_ports = 2, + .base_baud = 1250000, + .uart_offset = 8, + }, [pbn_b1_bt_2_921600] = { .flags = FL_BASE1|FL_BASE_BARS, @@ -1253,6 +1212,12 @@ static struct pci_board pci_boards[] __devinitdata = { .uart_offset = 8, }, + [pbn_b1_1_1382400] = { + .flags = FL_BASE1, + .num_ports = 1, + .base_baud = 1382400, + .uart_offset = 8, + }, [pbn_b1_2_1382400] = { .flags = FL_BASE1, .num_ports = 2, @@ -1278,6 +1243,12 @@ static struct pci_board pci_boards[] __devinitdata = { .base_baud = 115200, .uart_offset = 8, }, + [pbn_b2_2_115200] = { + .flags = FL_BASE2, + .num_ports = 2, + .base_baud = 115200, + .uart_offset = 8, + }, [pbn_b2_8_115200] = { .flags = FL_BASE2, .num_ports = 8, @@ -1361,6 +1332,12 @@ static struct pci_board pci_boards[] __devinitdata = { .uart_offset = 8, }, + [pbn_b3_2_115200] = { + .flags = FL_BASE3, + .num_ports = 2, + .base_baud = 115200, + .uart_offset = 8, + }, [pbn_b3_4_115200] = { .flags = FL_BASE3, .num_ports = 4, @@ -1403,6 +1380,13 @@ static struct pci_board pci_boards[] __devinitdata = { .reg_shift = 7, }, + [pbn_exsys_4055] = { + .flags = FL_BASE2, + .num_ports = 4, + .base_baud = 115200, + .uart_offset = 8, + }, + /* I think this entry is broken - the first_offset looks wrong --rmk */ [pbn_plx_romulus] = { .flags = FL_BASE2, @@ -1490,7 +1474,30 @@ static struct pci_board pci_boards[] __devinitdata = { .base_baud = 460800, .uart_offset = 256, .reg_shift = 4, - } + }, + /* + * Exar Corp. XR17C15[248] Dual/Quad/Octal UART + * Only basic 16550A support. + * XR17C15[24] are not tested, but they should work. + */ + [pbn_exar_XR17C152] = { + .flags = FL_BASE0, + .num_ports = 2, + .base_baud = 921600, + .uart_offset = 0x200, + }, + [pbn_exar_XR17C154] = { + .flags = FL_BASE0, + .num_ports = 4, + .base_baud = 921600, + .uart_offset = 0x200, + }, + [pbn_exar_XR17C158] = { + .flags = FL_BASE0, + .num_ports = 8, + .base_baud = 921600, + .uart_offset = 0x200, + }, }; /* @@ -1499,7 +1506,7 @@ static struct pci_board pci_boards[] __devinitdata = { * serial specs. Returns 0 on success, 1 on failure. */ static int __devinit -serial_pci_guess_board(struct pci_dev *dev, struct pci_board *board) +serial_pci_guess_board(struct pci_dev *dev, struct pciserial_board *board) { int num_iomem, num_port, first_port = -1, i; @@ -1564,7 +1571,8 @@ serial_pci_guess_board(struct pci_dev *dev, struct pci_board *board) } static inline int -serial_pci_matches(struct pci_board *board, struct pci_board *guessed) +serial_pci_matches(struct pciserial_board *board, + struct pciserial_board *guessed) { return board->num_ports == guessed->num_ports && @@ -1574,58 +1582,13 @@ serial_pci_matches(struct pci_board *board, struct pci_board *guessed) board->first_offset == guessed->first_offset; } -/* - * Probe one serial board. Unfortunately, there is no rhyme nor reason - * to the arrangement of serial ports on a PCI card. - */ -static int __devinit -pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent) +struct serial_private * +pciserial_init_ports(struct pci_dev *dev, struct pciserial_board *board) { + struct uart_port serial_port; struct serial_private *priv; - struct pci_board *board, tmp; struct pci_serial_quirk *quirk; - struct serial_struct serial_req; - int base_baud, rc, nr_ports, i; - - if (ent->driver_data >= ARRAY_SIZE(pci_boards)) { - printk(KERN_ERR "pci_init_one: invalid driver_data: %ld\n", - ent->driver_data); - return -EINVAL; - } - - board = &pci_boards[ent->driver_data]; - - rc = pci_enable_device(dev); - if (rc) - return rc; - - if (ent->driver_data == pbn_default) { - /* - * Use a copy of the pci_board entry for this; - * avoid changing entries in the table. - */ - memcpy(&tmp, board, sizeof(struct pci_board)); - board = &tmp; - - /* - * We matched one of our class entries. Try to - * determine the parameters of this board. - */ - rc = serial_pci_guess_board(dev, board); - if (rc) - goto disable; - } else { - /* - * We matched an explicit entry. If we are able to - * detect this boards settings with our heuristic, - * then we no longer need this entry. - */ - memcpy(&tmp, &pci_boards[pbn_default], sizeof(struct pci_board)); - rc = serial_pci_guess_board(dev, &tmp); - if (rc == 0 && serial_pci_matches(board, &tmp)) - moan_device("Redundant entry in serial pci_table.", - dev); - } + int rc, nr_ports, i; nr_ports = board->num_ports; @@ -1643,8 +1606,10 @@ pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent) */ if (quirk->init) { rc = quirk->init(dev); - if (rc < 0) - goto disable; + if (rc < 0) { + priv = ERR_PTR(rc); + goto err_out; + } if (rc) nr_ports = rc; } @@ -1653,35 +1618,32 @@ pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent) sizeof(unsigned int) * nr_ports, GFP_KERNEL); if (!priv) { - rc = -ENOMEM; - goto deinit; + priv = ERR_PTR(-ENOMEM); + goto err_deinit; } memset(priv, 0, sizeof(struct serial_private) + sizeof(unsigned int) * nr_ports); + priv->dev = dev; priv->quirk = quirk; - pci_set_drvdata(dev, priv); - base_baud = board->base_baud; - if (!base_baud) { - moan_device("Board entry does not specify baud rate.", dev); - base_baud = BASE_BAUD; - } + memset(&serial_port, 0, sizeof(struct uart_port)); + serial_port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ; + serial_port.uartclk = board->base_baud * 16; + serial_port.irq = get_pci_irq(dev, board); + serial_port.dev = &dev->dev; + for (i = 0; i < nr_ports; i++) { - memset(&serial_req, 0, sizeof(serial_req)); - serial_req.flags = UPF_SKIP_TEST | UPF_AUTOPROBE | - UPF_RESOURCES | UPF_SHARE_IRQ; - serial_req.baud_base = base_baud; - serial_req.irq = get_pci_irq(dev, board, i); - if (quirk->setup(dev, board, &serial_req, i)) + if (quirk->setup(priv, board, &serial_port, i)) break; + #ifdef SERIAL_DEBUG_PCI printk("Setup PCI port: port %x, irq %d, type %d\n", - serial_req.port, serial_req.irq, serial_req.io_type); + serial_port.iobase, serial_port.irq, serial_port.iotype); #endif - priv->line[i] = register_serial(&serial_req); + priv->line[i] = serial8250_register_port(&serial_port); if (priv->line[i] < 0) { printk(KERN_WARNING "Couldn't register serial port %s: %d\n", pci_name(dev), priv->line[i]); break; @@ -1690,58 +1652,152 @@ pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent) priv->nr = i; - return 0; + return priv; - deinit: + err_deinit: if (quirk->exit) quirk->exit(dev); - disable: - pci_disable_device(dev); - return rc; + err_out: + return priv; } +EXPORT_SYMBOL_GPL(pciserial_init_ports); -static void __devexit pciserial_remove_one(struct pci_dev *dev) +void pciserial_remove_ports(struct serial_private *priv) { - struct serial_private *priv = pci_get_drvdata(dev); + struct pci_serial_quirk *quirk; + int i; - pci_set_drvdata(dev, NULL); + for (i = 0; i < priv->nr; i++) + serial8250_unregister_port(priv->line[i]); - if (priv) { - struct pci_serial_quirk *quirk; - int i; + for (i = 0; i < PCI_NUM_BAR_RESOURCES; i++) { + if (priv->remapped_bar[i]) + iounmap(priv->remapped_bar[i]); + priv->remapped_bar[i] = NULL; + } - for (i = 0; i < priv->nr; i++) - unregister_serial(priv->line[i]); + /* + * Find the exit quirks. + */ + quirk = find_quirk(priv->dev); + if (quirk->exit) + quirk->exit(priv->dev); - for (i = 0; i < PCI_NUM_BAR_RESOURCES; i++) { - if (priv->remapped_bar[i]) - iounmap(priv->remapped_bar[i]); - priv->remapped_bar[i] = NULL; - } + kfree(priv); +} +EXPORT_SYMBOL_GPL(pciserial_remove_ports); + +void pciserial_suspend_ports(struct serial_private *priv) +{ + int i; + + for (i = 0; i < priv->nr; i++) + if (priv->line[i] >= 0) + serial8250_suspend_port(priv->line[i]); +} +EXPORT_SYMBOL_GPL(pciserial_suspend_ports); + +void pciserial_resume_ports(struct serial_private *priv) +{ + int i; + /* + * Ensure that the board is correctly configured. + */ + if (priv->quirk->init) + priv->quirk->init(priv->dev); + + for (i = 0; i < priv->nr; i++) + if (priv->line[i] >= 0) + serial8250_resume_port(priv->line[i]); +} +EXPORT_SYMBOL_GPL(pciserial_resume_ports); + +/* + * Probe one serial board. Unfortunately, there is no rhyme nor reason + * to the arrangement of serial ports on a PCI card. + */ +static int __devinit +pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent) +{ + struct serial_private *priv; + struct pciserial_board *board, tmp; + int rc; + + if (ent->driver_data >= ARRAY_SIZE(pci_boards)) { + printk(KERN_ERR "pci_init_one: invalid driver_data: %ld\n", + ent->driver_data); + return -EINVAL; + } + + board = &pci_boards[ent->driver_data]; + + rc = pci_enable_device(dev); + if (rc) + return rc; + + if (ent->driver_data == pbn_default) { /* - * Find the exit quirks. + * Use a copy of the pci_board entry for this; + * avoid changing entries in the table. */ - quirk = find_quirk(dev); - if (quirk->exit) - quirk->exit(dev); + memcpy(&tmp, board, sizeof(struct pciserial_board)); + board = &tmp; - pci_disable_device(dev); + /* + * We matched one of our class entries. Try to + * determine the parameters of this board. + */ + rc = serial_pci_guess_board(dev, board); + if (rc) + goto disable; + } else { + /* + * We matched an explicit entry. If we are able to + * detect this boards settings with our heuristic, + * then we no longer need this entry. + */ + memcpy(&tmp, &pci_boards[pbn_default], + sizeof(struct pciserial_board)); + rc = serial_pci_guess_board(dev, &tmp); + if (rc == 0 && serial_pci_matches(board, &tmp)) + moan_device("Redundant entry in serial pci_table.", + dev); + } - kfree(priv); + priv = pciserial_init_ports(dev, board); + if (!IS_ERR(priv)) { + pci_set_drvdata(dev, priv); + return 0; } + + rc = PTR_ERR(priv); + + disable: + pci_disable_device(dev); + return rc; } -static int pciserial_suspend_one(struct pci_dev *dev, u32 state) +static void __devexit pciserial_remove_one(struct pci_dev *dev) { struct serial_private *priv = pci_get_drvdata(dev); - if (priv) { - int i; + pci_set_drvdata(dev, NULL); - for (i = 0; i < priv->nr; i++) - serial8250_suspend_port(priv->line[i]); - } + pciserial_remove_ports(priv); + + pci_disable_device(dev); +} + +static int pciserial_suspend_one(struct pci_dev *dev, pm_message_t state) +{ + struct serial_private *priv = pci_get_drvdata(dev); + + if (priv) + pciserial_suspend_ports(priv); + + pci_save_state(dev); + pci_set_power_state(dev, pci_choose_state(dev, state)); return 0; } @@ -1749,17 +1805,16 @@ static int pciserial_resume_one(struct pci_dev *dev) { struct serial_private *priv = pci_get_drvdata(dev); - if (priv) { - int i; + pci_set_power_state(dev, PCI_D0); + pci_restore_state(dev); + if (priv) { /* - * Ensure that the board is correctly configured. + * The device may have been disabled. Re-enable it. */ - if (priv->quirk->init) - priv->quirk->init(dev); + pci_enable_device(dev); - for (i = 0; i < priv->nr; i++) - serial8250_resume_port(priv->line[i]); + pciserial_resume_ports(priv); } return 0; } @@ -1821,6 +1876,70 @@ static struct pci_device_id serial_pci_tbl[] = { PCI_SUBVENDOR_ID_CONNECT_TECH, PCI_SUBDEVICE_ID_CONNECT_TECH_BH041101V1, 0, 0, pbn_b1_4_921600 }, + { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351, + PCI_SUBVENDOR_ID_CONNECT_TECH, + PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_20MHZ, 0, 0, + pbn_b1_2_1250000 }, + { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI954, + PCI_SUBVENDOR_ID_CONNECT_TECH, + PCI_SUBDEVICE_ID_CONNECT_TECH_TITAN_2, 0, 0, + pbn_b0_2_1843200 }, + { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI954, + PCI_SUBVENDOR_ID_CONNECT_TECH, + PCI_SUBDEVICE_ID_CONNECT_TECH_TITAN_4, 0, 0, + pbn_b0_4_1843200 }, + { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI954, + PCI_VENDOR_ID_AFAVLAB, + PCI_SUBDEVICE_ID_AFAVLAB_P061, 0, 0, + pbn_b0_4_1152000 }, + { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C152, + PCI_SUBVENDOR_ID_CONNECT_TECH, + PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_2_232, 0, 0, + pbn_b0_2_1843200_200 }, + { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C154, + PCI_SUBVENDOR_ID_CONNECT_TECH, + PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_4_232, 0, 0, + pbn_b0_4_1843200_200 }, + { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C158, + PCI_SUBVENDOR_ID_CONNECT_TECH, + PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_8_232, 0, 0, + pbn_b0_8_1843200_200 }, + { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C152, + PCI_SUBVENDOR_ID_CONNECT_TECH, + PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_1_1, 0, 0, + pbn_b0_2_1843200_200 }, + { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C154, + PCI_SUBVENDOR_ID_CONNECT_TECH, + PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_2_2, 0, 0, + pbn_b0_4_1843200_200 }, + { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C158, + PCI_SUBVENDOR_ID_CONNECT_TECH, + PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_4_4, 0, 0, + pbn_b0_8_1843200_200 }, + { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C152, + PCI_SUBVENDOR_ID_CONNECT_TECH, + PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_2, 0, 0, + pbn_b0_2_1843200_200 }, + { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C154, + PCI_SUBVENDOR_ID_CONNECT_TECH, + PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_4, 0, 0, + pbn_b0_4_1843200_200 }, + { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C158, + PCI_SUBVENDOR_ID_CONNECT_TECH, + PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_8, 0, 0, + pbn_b0_8_1843200_200 }, + { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C152, + PCI_SUBVENDOR_ID_CONNECT_TECH, + PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_2_485, 0, 0, + pbn_b0_2_1843200_200 }, + { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C154, + PCI_SUBVENDOR_ID_CONNECT_TECH, + PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_4_485, 0, 0, + pbn_b0_4_1843200_200 }, + { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C158, + PCI_SUBVENDOR_ID_CONNECT_TECH, + PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_8_485, 0, 0, + pbn_b0_8_1843200_200 }, { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_U530, PCI_ANY_ID, PCI_ANY_ID, 0, 0, @@ -1840,6 +1959,9 @@ static struct pci_device_id serial_pci_tbl[] = { { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_COMM8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_b2_8_115200 }, + { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_UCOMM8, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b2_8_115200 }, { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_GTEK_SERIAL2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, @@ -1890,6 +2012,10 @@ static struct pci_device_id serial_pci_tbl[] = { PCI_SUBVENDOR_ID_CHASE_PCIRAS, PCI_SUBDEVICE_ID_CHASE_PCIRAS8, 0, 0, pbn_b2_8_460800 }, + { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, + PCI_SUBVENDOR_ID_EXSYS, + PCI_SUBDEVICE_ID_EXSYS_4055, 0, 0, + pbn_exsys_4055 }, /* * Megawolf Romulus PCI Serial Card, from Mike Hudson * (Exoray@isys.ca) @@ -1912,6 +2038,19 @@ static struct pci_device_id serial_pci_tbl[] = { { PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_OXSEMI_16PCI954, PCI_VENDOR_ID_SPECIALIX, PCI_SUBDEVICE_ID_SPECIALIX_SPEED4, 0, 0, pbn_b0_4_921600 }, + { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI954, + PCI_SUBVENDOR_ID_SIIG, PCI_SUBDEVICE_ID_SIIG_QUARTET_SERIAL, 0, 0, + pbn_b0_4_1152000 }, + + /* + * The below card is a little controversial since it is the + * subject of a PCI vendor/device ID clash. (See + * www.ussg.iu.edu/hypermail/linux/kernel/0303.1/0516.html). + * For now just used the hex ID 0x950a. + */ + { PCI_VENDOR_ID_OXSEMI, 0x950a, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_2_1130000 }, { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI954, PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_b0_4_115200 }, @@ -2026,6 +2165,15 @@ static struct pci_device_id serial_pci_tbl[] = { { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_20x_850, PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_b0_bt_4_921600 }, + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_8S_20x_550, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_bt_8_921600 }, + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_8S_20x_650, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_bt_8_921600 }, + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_8S_20x_850, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_bt_8_921600 }, /* * Computone devices submitted by Doug McNash dmcnash@computone.com @@ -2088,6 +2236,20 @@ static struct pci_device_id serial_pci_tbl[] = { PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_b0_bt_1_460800 }, + /* + * Dell Remote Access Card 4 - Tim_T_Murphy@Dell.com + */ + { PCI_VENDOR_ID_DELL, PCI_DEVICE_ID_DELL_RAC4, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b1_1_1382400 }, + + /* + * Dell Remote Access Card III - Tim_T_Murphy@Dell.com + */ + { PCI_VENDOR_ID_DELL, PCI_DEVICE_ID_DELL_RACIII, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b1_1_1382400 }, + /* * RAStel 2 port modem, gerg@moreton.com.au */ @@ -2133,6 +2295,9 @@ static struct pci_device_id serial_pci_tbl[] = { /* * HP Diva card */ + { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_DIVA, + PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_DIVA_RMP3, 0, 0, + pbn_b1_1_115200 }, { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_DIVA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_b0_5_115200 }, @@ -2147,6 +2312,9 @@ static struct pci_device_id serial_pci_tbl[] = { PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_nec_nile4 }, + { PCI_VENDOR_ID_DCI, PCI_DEVICE_ID_DCI_PCCOM2, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b3_2_115200 }, { PCI_VENDOR_ID_DCI, PCI_DEVICE_ID_DCI_PCCOM4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_b3_4_115200 }, @@ -2154,6 +2322,36 @@ static struct pci_device_id serial_pci_tbl[] = { PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_b3_8_115200 }, + /* + * Exar Corp. XR17C15[248] Dual/Quad/Octal UART + */ + { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C152, + PCI_ANY_ID, PCI_ANY_ID, + 0, + 0, pbn_exar_XR17C152 }, + { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C154, + PCI_ANY_ID, PCI_ANY_ID, + 0, + 0, pbn_exar_XR17C154 }, + { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C158, + PCI_ANY_ID, PCI_ANY_ID, + 0, + 0, pbn_exar_XR17C158 }, + + /* + * Topic TP560 Data/Fax/Voice 56k modem (reported by Evan Clarke) + */ + { PCI_VENDOR_ID_TOPIC, PCI_DEVICE_ID_TOPIC_TP560, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_1_115200 }, + + /* + * IntaShield IS-200 + */ + { PCI_VENDOR_ID_INTASHIELD, PCI_DEVICE_ID_INTASHIELD_IS200, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, /* 135a.0811 */ + pbn_b2_2_115200 }, + /* * These entries match devices with class COMMUNICATION_SERIAL, * COMMUNICATION_MODEM or COMMUNICATION_MULTISERIAL @@ -2184,7 +2382,7 @@ static struct pci_driver serial_pci_driver = { static int __init serial8250_pci_init(void) { - return pci_module_init(&serial_pci_driver); + return pci_register_driver(&serial_pci_driver); } static void __exit serial8250_pci_exit(void)