lkml.org 
[lkml]   [2003]   [Mar]   [6]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    SubjectRe: 2.5.64 - xircom realport no workie well
    On Fri, Mar 07, 2003 at 12:03:40AM +1100, CaT wrote:
    > With the 2.5.x series of kernels I've lost serial port functionality of
    > my xircom pcmcia card and the network port, whilst working, does give
    > errors on eject. The dmesg from an insert/eject sequence is:
    >
    > cs: cb_alloc(bus 2): vendor 0x115d, device 0x0003
    > PCI: Enabling device 02:00.0 (0000 -> 0003)
    > PCI: Setting latency timer of device 02:00.0 to 64
    > eth1: Xircom cardbus revision 3 at irq 10
    > PCI: Enabling device 02:00.1 (0000 -> 0003)
    > ttyS15 at I/O 0x1880 (irq = 10) is a 16550A

    Ok, we found the modem.

    > Trying to free nonexistent resource <00001880-00001887>

    I've been working in the 8250_pci area recently, and already found that.

    Can you check whether the attached patch fixes this for you? It's more
    a cleanup of 8250_pci.c than anything else - I'll split it up when I
    send it towards Linus though.

    > When accessing the serial port (ttyS15) all I get is:
    >
    > 13 [23:58:06] root@theirongiant:/usr/src/linux>> cat /dev/ttyS15
    > cat: /dev/ttyS15: Input/output error

    Argh, this is probably a side effect of the way IRQ sharing now works.
    Thanks for this report - it should also be fixed by this patch. We
    weren't explicitly allowing PCI-based ports to share IRQs with anything
    else.

    --- orig/drivers/serial/8250_pci.c Tue Feb 25 10:57:53 2003
    +++ linux/drivers/serial/8250_pci.c Thu Mar 6 13:27:35 2003
    @@ -20,8 +20,10 @@
    #include <linux/string.h>
    #include <linux/kernel.h>
    #include <linux/slab.h>
    +#include <linux/tty.h>
    #include <linux/serial.h>
    #include <linux/serialP.h>
    +#include <linux/serial_core.h>

    #include <asm/bitops.h>
    #include <asm/byteorder.h>
    @@ -30,174 +32,181 @@

    #include "8250.h"

    -
    -#ifndef IS_PCI_REGION_IOPORT
    -#define IS_PCI_REGION_IOPORT(dev, r) (pci_resource_flags((dev), (r)) & \
    - IORESOURCE_IO)
    -#endif
    -#ifndef IS_PCI_REGION_IOMEM
    -#define IS_PCI_REGION_IOMEM(dev, r) (pci_resource_flags((dev), (r)) & \
    - IORESOURCE_MEM)
    -#endif
    -#ifndef PCI_IRQ_RESOURCE
    -#define PCI_IRQ_RESOURCE(dev, r) ((dev)->irq_resource[r].start)
    -#endif
    -
    -#ifndef pci_get_subvendor
    -#define pci_get_subvendor(dev) ((dev)->subsystem_vendor)
    -#define pci_get_subdevice(dev) ((dev)->subsystem_device)
    -#endif
    -
    -struct serial_private {
    - unsigned int nr;
    - struct pci_board *board;
    - int line[0];
    +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;
    };

    /*
    - * init_fn returns:
    + * init function returns:
    * > 0 - number of ports
    * = 0 - use board->num_ports
    * < 0 - error
    */
    -struct pci_board {
    - int flags;
    - int num_ports;
    - int base_baud;
    - int uart_offset;
    - int reg_shift;
    - int (*init_fn)(struct pci_dev *dev, int enable);
    - int first_uart_offset;
    +struct pci_serial_quirk {
    + u32 vendor;
    + u32 device;
    + 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);
    + void (*exit)(struct pci_dev *dev);
    };

    -static int
    -get_pci_port(struct pci_dev *dev, struct pci_board *board,
    - struct serial_struct *req, int idx)
    +#define PCI_NUM_BAR_RESOURCES 6
    +
    +struct serial_private {
    + unsigned int nr;
    + void *remapped_bar[PCI_NUM_BAR_RESOURCES];
    + struct pci_serial_quirk *quirk;
    + int line[0];
    +};
    +
    +static void moan_device(const char *str, struct pci_dev *dev)
    {
    - unsigned long port;
    - int base_idx;
    - int max_port;
    - int offset;
    + printk(KERN_WARNING "%s: %s\n"
    + KERN_WARNING "Please send the output of lspci -vv, this\n"
    + KERN_WARNING "message (0x%04x,0x%04x,0x%04x,0x%04x), the\n"
    + KERN_WARNING "manufacturer and name of serial board or\n"
    + KERN_WARNING "modem board to rmk+serial@arm.linux.org.uk.\n",
    + dev->slot_name, str, dev->vendor, dev->device,
    + dev->subsystem_vendor, dev->subsystem_device);
    +}

    - base_idx = SPCI_FL_GET_BASE(board->flags);
    - if (board->flags & SPCI_FL_BASE_TABLE)
    - base_idx += idx;
    +static int
    +setup_port(struct pci_dev *dev, struct serial_struct *req,
    + int bar, int offset, int regshift)
    +{
    + struct serial_private *priv = pci_get_drvdata(dev);
    + unsigned long port, len;

    - if (board->flags & SPCI_FL_REGION_SZ_CAP) {
    - max_port = pci_resource_len(dev, base_idx) / 8;
    - if (idx >= max_port)
    - return 1;
    + 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);
    + if (!priv->remapped_bar[bar])
    + return -ENOMEM;
    +
    + req->io_type = UPIO_MEM;
    + req->iomap_base = port;
    + req->iomem_base = priv->remapped_bar[bar] + offset;
    + req->iomem_reg_shift = 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;
    }
    -
    - offset = board->first_uart_offset;
    + return 0;
    +}

    - /*
    - * Timedia/SUNIX uses a mixture of BARs and offsets
    - * Ugh, this is ugly as all hell --- TYT
    - */
    - if (dev->vendor == PCI_VENDOR_ID_TIMEDIA)
    - switch(idx) {
    - case 0:
    - base_idx = 0;
    - break;
    - case 1:
    - base_idx = 0;
    - offset = 8;
    - break;
    - case 2:
    - base_idx = 1;
    - break;
    - case 3:
    - base_idx = 1;
    - offset = 8;
    - break;
    - case 4: /* BAR 2 */
    - case 5: /* BAR 3 */
    - case 6: /* BAR 4 */
    - case 7: /* BAR 5 */
    - base_idx = idx - 2;
    - }
    +/*
    + * AFAVLAB uses a different mixture of BARs and offsets
    + * Not that ugly ;) -- HW
    + */
    +static int
    +afavlab_setup(struct pci_dev *dev, struct pci_board *board,
    + struct serial_struct *req, int idx)
    +{
    + unsigned int bar, offset = board->first_offset;
    +
    + bar = SPCI_FL_GET_BASE(board->flags);
    + if (idx < 4)
    + bar += idx;
    + else
    + offset += (idx - 4) * board->uart_offset;

    - /* AFAVLAB uses a different mixture of BARs and offsets */
    - /* Not that ugly ;) -- HW */
    - if (dev->vendor == PCI_VENDOR_ID_AFAVLAB && idx >= 4) {
    - base_idx = 4;
    - offset = (idx - 4) * 8;
    - }
    + return setup_port(dev, req, bar, offset, board->reg_shift);
    +}

    - /* Some Titan cards are also a little weird */
    - if (dev->vendor == PCI_VENDOR_ID_TITAN &&
    - (dev->device == PCI_DEVICE_ID_TITAN_400L ||
    - dev->device == PCI_DEVICE_ID_TITAN_800L)) {
    - switch (idx) {
    - case 0: base_idx = 1;
    - break;
    - case 1: base_idx = 2;
    - break;
    - default:
    - base_idx = 4;
    - offset = 8 * (idx - 2);
    - }
    - }
    +/*
    + * HP's Remote Management Console. The Diva chip came in several
    + * different versions. N-class, L2000 and A500 have two Diva chips, each
    + * with 3 UARTs (the third UART on the second chip is unused). Superdome
    + * 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)
    +{
    + int rc = 0;

    - /* HP's Diva chip puts the 4th/5th serial port further out, and
    - * some serial ports are supposed to be hidden on certain models.
    - */
    - if (dev->vendor == PCI_VENDOR_ID_HP &&
    - dev->device == PCI_DEVICE_ID_HP_DIVA) {
    - switch (dev->subsystem_device) {
    - case PCI_DEVICE_ID_HP_DIVA_MAESTRO:
    - if (idx == 3)
    - idx++;
    - break;
    - case PCI_DEVICE_ID_HP_DIVA_EVEREST:
    - if (idx > 0)
    - idx++;
    - if (idx > 2)
    - idx++;
    - break;
    - }
    - if (idx > 2) {
    - offset = 0x18;
    - }
    + switch (dev->subsystem_device) {
    + case PCI_DEVICE_ID_HP_DIVA_TOSCA1:
    + case PCI_DEVICE_ID_HP_DIVA_HALFDOME:
    + case PCI_DEVICE_ID_HP_DIVA_KEYSTONE:
    + case PCI_DEVICE_ID_HP_DIVA_EVEREST:
    + rc = 3;
    + break;
    + case PCI_DEVICE_ID_HP_DIVA_TOSCA2:
    + rc = 2;
    + break;
    + case PCI_DEVICE_ID_HP_DIVA_MAESTRO:
    + rc = 4;
    + break;
    + case PCI_DEVICE_ID_HP_DIVA_POWERBAR:
    + rc = 1;
    + break;
    }

    - port = pci_resource_start(dev, base_idx) + offset;
    + return rc;
    +}

    - if ((board->flags & SPCI_FL_BASE_TABLE) == 0)
    - port += idx * (board->uart_offset ? board->uart_offset : 8);
    +/*
    + * HP's Diva chip puts the 4th/5th serial port further out, and
    + * 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)
    +{
    + unsigned int offset = board->first_offset;
    + unsigned int bar = SPCI_FL_GET_BASE(board->flags);

    - if (IS_PCI_REGION_IOPORT(dev, base_idx)) {
    - req->port = port;
    - if (HIGH_BITS_OFFSET)
    - req->port_high = port >> HIGH_BITS_OFFSET;
    - else
    - req->port_high = 0;
    - return 0;
    + switch (dev->subsystem_device) {
    + case PCI_DEVICE_ID_HP_DIVA_MAESTRO:
    + if (idx == 3)
    + idx++;
    + break;
    + case PCI_DEVICE_ID_HP_DIVA_EVEREST:
    + if (idx > 0)
    + idx++;
    + if (idx > 2)
    + idx++;
    + break;
    }
    - req->io_type = SERIAL_IO_MEM;
    - req->iomap_base = port;
    - req->iomem_base = ioremap(port, board->uart_offset);
    - if (req->iomem_base == NULL)
    - return -ENOMEM;
    - req->iomem_reg_shift = board->reg_shift;
    - req->port = 0;
    - return 0;
    + if (idx > 2)
    + offset = 0x18;
    +
    + offset += idx * board->uart_offset;
    +
    + return setup_port(dev, req, bar, offset, board->reg_shift);
    }

    -static _INLINE_ int
    -get_pci_irq(struct pci_dev *dev, struct pci_board *board, int idx)
    +/*
    + * Added for EKF Intel i960 serial boards
    + */
    +static int __devinit pci_inteli960ni_init(struct pci_dev *dev)
    {
    - int base_idx;
    + unsigned long oldval;

    - if ((board->flags & SPCI_FL_IRQRESOURCE) == 0)
    - return dev->irq;
    + if (!(dev->subsystem_device & 0x1000))
    + return -ENODEV;

    - base_idx = SPCI_FL_GET_IRQBASE(board->flags);
    - if (board->flags & SPCI_FL_IRQ_TABLE)
    - base_idx += idx;
    -
    - return PCI_IRQ_RESOURCE(dev, base_idx);
    + /* is firmware started? */
    + pci_read_config_dword(dev, 0x44, (void*) &oldval);
    + if (oldval == 0x00001000L) { /* RESET value */
    + printk(KERN_DEBUG "Local i960 firmware missing");
    + return -ENODEV;
    + }
    + return 0;
    }

    /*
    @@ -206,26 +215,29 @@
    * seems to be mainly needed on card using the PLX which also use I/O
    * mapped memory.
    */
    -static int __devinit pci_plx9050_fn(struct pci_dev *dev, int enable)
    +static int __devinit pci_plx9050_init(struct pci_dev *dev)
    {
    - u8 *p, irq_config = 0;
    + u8 *p, irq_config;

    - if (enable) {
    - irq_config = 0x41;
    - if (dev->vendor == PCI_VENDOR_ID_PANACOM)
    - irq_config = 0x43;
    - if ((dev->vendor == PCI_VENDOR_ID_PLX) &&
    - (dev->device == PCI_DEVICE_ID_PLX_ROMULUS)) {
    - /*
    - * As the megawolf cards have the int pins active
    - * high, and have 2 UART chips, both ints must be
    - * enabled on the 9050. Also, the UARTS are set in
    - * 16450 mode by default, so we have to enable the
    - * 16C950 'enhanced' mode so that we can use the
    - * deep FIFOs
    - */
    - irq_config = 0x5b;
    - }
    + if ((pci_resource_flags(dev, 0) & IORESOURCE_MEM) == 0) {
    + moan_device("no memory in bar 0", dev);
    + return 0;
    + }
    +
    + irq_config = 0x41;
    + if (dev->vendor == PCI_VENDOR_ID_PANACOM)
    + irq_config = 0x43;
    + if ((dev->vendor == PCI_VENDOR_ID_PLX) &&
    + (dev->device == PCI_DEVICE_ID_PLX_ROMULUS)) {
    + /*
    + * As the megawolf cards have the int pins active
    + * high, and have 2 UART chips, both ints must be
    + * enabled on the 9050. Also, the UARTS are set in
    + * 16450 mode by default, so we have to enable the
    + * 16C950 'enhanced' mode so that we can use the
    + * deep FIFOs
    + */
    + irq_config = 0x5b;
    }

    /*
    @@ -245,6 +257,27 @@
    return 0;
    }

    +static void __devexit pci_plx9050_exit(struct pci_dev *dev)
    +{
    + u8 *p;
    +
    + if ((pci_resource_flags(dev, 0) & IORESOURCE_MEM) == 0)
    + return;
    +
    + /*
    + * disable interrupts
    + */
    + p = ioremap(pci_resource_start(dev, 0), 0x80);
    + if (p != NULL) {
    + writel(0, p + 0x4c);
    +
    + /*
    + * Read the register back to ensure that it took effect.
    + */
    + readl(p + 0x4c);
    + iounmap(p);
    + }
    +}

    /*
    * SIIG serial cards have an PCI interface chip which also controls
    @@ -270,23 +303,20 @@
    #define PCI_DEVICE_ID_SIIG_1S_10x (PCI_DEVICE_ID_SIIG_1S_10x_550 & 0xfffc)
    #define PCI_DEVICE_ID_SIIG_2S_10x (PCI_DEVICE_ID_SIIG_2S_10x_550 & 0xfff8)

    -int pci_siig10x_fn(struct pci_dev *dev, int enable)
    +static int pci_siig10x_init(struct pci_dev *dev)
    {
    u16 data, *p;

    - if (!enable)
    - return 0;
    -
    switch (dev->device & 0xfff8) {
    - case PCI_DEVICE_ID_SIIG_1S_10x: /* 1S */
    - data = 0xffdf;
    - break;
    - case PCI_DEVICE_ID_SIIG_2S_10x: /* 2S, 2S1P */
    - data = 0xf7ff;
    - break;
    - default: /* 1S1P, 4S */
    - data = 0xfffb;
    - break;
    + case PCI_DEVICE_ID_SIIG_1S_10x: /* 1S */
    + data = 0xffdf;
    + break;
    + case PCI_DEVICE_ID_SIIG_2S_10x: /* 2S, 2S1P */
    + data = 0xf7ff;
    + break;
    + default: /* 1S1P, 4S */
    + data = 0xfffb;
    + break;
    }

    p = ioremap(pci_resource_start(dev, 0), 0x80);
    @@ -294,22 +324,18 @@
    return -ENOMEM;

    writew(readw((unsigned long) p + 0x28) & data, (unsigned long) p + 0x28);
    + readw((unsigned long)p + 0x28);
    iounmap(p);
    return 0;
    }

    -EXPORT_SYMBOL(pci_siig10x_fn);
    -
    #define PCI_DEVICE_ID_SIIG_2S_20x (PCI_DEVICE_ID_SIIG_2S_20x_550 & 0xfffc)
    #define PCI_DEVICE_ID_SIIG_2S1P_20x (PCI_DEVICE_ID_SIIG_2S1P_20x_550 & 0xfffc)

    -int pci_siig20x_fn(struct pci_dev *dev, int enable)
    +static int pci_siig20x_init(struct pci_dev *dev)
    {
    u8 data;

    - if (!enable)
    - return 0;
    -
    /* Change clock frequency for the first UART. */
    pci_read_config_byte(dev, 0x6f, &data);
    pci_write_config_byte(dev, 0x6f, data & 0xef);
    @@ -323,28 +349,25 @@
    return 0;
    }

    -EXPORT_SYMBOL(pci_siig20x_fn);
    -
    -/* Added for EKF Intel i960 serial boards */
    -static int __devinit pci_inteli960ni_fn(struct pci_dev *dev, int enable)
    +int pci_siig10x_fn(struct pci_dev *dev, int enable)
    {
    - unsigned long oldval;
    -
    - if (!(pci_get_subdevice(dev) & 0x1000))
    - return -ENODEV;
    + int ret = 0;
    + if (enable)
    + ret = pci_siig10x_init(dev);
    + return ret;
    +}

    - if (!enable) /* is there something to deinit? */
    - return 0;
    -
    - /* is firmware started? */
    - pci_read_config_dword(dev, 0x44, (void*) &oldval);
    - if (oldval == 0x00001000L) { /* RESET value */
    - printk(KERN_DEBUG "Local i960 firmware missing");
    - return -ENODEV;
    - }
    - return 0;
    +int pci_siig20x_fn(struct pci_dev *dev, int enable)
    +{
    + int ret = 0;
    + if (enable)
    + ret = pci_siig20x_init(dev);
    + return ret;
    }

    +EXPORT_SYMBOL(pci_siig10x_fn);
    +EXPORT_SYMBOL(pci_siig20x_fn);
    +
    /*
    * Timedia has an explosion of boards, and to avoid the PCI table from
    * growing *huge*, we use this function to collapse some 70 entries
    @@ -385,78 +408,450 @@
    { 0, 0 }
    };

    -static int __devinit pci_timedia_fn(struct pci_dev *dev, int enable)
    +static int __devinit pci_timedia_init(struct pci_dev *dev)
    {
    - int i, j;
    unsigned short *ids;
    -
    - if (!enable)
    - return 0;
    + int i, j;

    for (i = 0; timedia_data[i].num; i++) {
    ids = timedia_data[i].ids;
    for (j = 0; ids[j]; j++)
    - if (pci_get_subdevice(dev) == ids[j])
    + if (dev->subsystem_device == ids[j])
    return timedia_data[i].num;
    }
    return 0;
    }

    /*
    - * HP's Remote Management Console. The Diva chip came in several
    - * different versions. N-class, L2000 and A500 have two Diva chips, each
    - * with 3 UARTs (the third UART on the second chip is unused). Superdome
    - * and Keystone have one Diva chip with 3 UARTs. Some later machines have
    - * one Diva chip, but it has been expanded to 5 UARTs.
    + * Timedia/SUNIX uses a mixture of BARs and offsets
    + * Ugh, this is ugly as all hell --- TYT
    */
    -static int __devinit pci_hp_diva(struct pci_dev *dev, int enable)
    +static int
    +pci_timedia_setup(struct pci_dev *dev, struct pci_board *board,
    + struct serial_struct *req, int idx)
    {
    - int rc = 0;
    -
    - if (!enable)
    - return 0;
    + unsigned int bar = 0, offset = board->first_offset;

    - switch (dev->subsystem_device) {
    - case PCI_DEVICE_ID_HP_DIVA_TOSCA1:
    - case PCI_DEVICE_ID_HP_DIVA_HALFDOME:
    - case PCI_DEVICE_ID_HP_DIVA_KEYSTONE:
    - case PCI_DEVICE_ID_HP_DIVA_EVEREST:
    - rc = 3;
    + switch (idx) {
    + case 0:
    + bar = 0;
    break;
    - case PCI_DEVICE_ID_HP_DIVA_TOSCA2:
    - rc = 2;
    + case 1:
    + offset = board->uart_offset;
    + bar = 0;
    break;
    - case PCI_DEVICE_ID_HP_DIVA_MAESTRO:
    - rc = 4;
    - break;
    - case PCI_DEVICE_ID_HP_DIVA_POWERBAR:
    - rc = 1;
    + case 2:
    + bar = 1;
    break;
    + case 3:
    + offset = board->uart_offset;
    + bar = 1;
    + case 4: /* BAR 2 */
    + case 5: /* BAR 3 */
    + case 6: /* BAR 4 */
    + case 7: /* BAR 5 */
    + bar = idx - 2;
    }

    - return rc;
    + return setup_port(dev, req, 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)
    +{
    + unsigned int bar, offset = board->first_offset;
    +
    + switch (idx) {
    + case 0:
    + bar = 1;
    + break;
    + case 1:
    + bar = 2;
    + break;
    + default:
    + bar = 4;
    + offset = (idx - 2) * board->uart_offset;
    + }
    +
    + return setup_port(dev, req, bar, offset, board->reg_shift);
    +}

    -static int __devinit pci_xircom_fn(struct pci_dev *dev, int enable)
    +static int __devinit pci_xircom_init(struct pci_dev *dev)
    {
    __set_current_state(TASK_UNINTERRUPTIBLE);
    schedule_timeout(HZ/10);
    return 0;
    }

    +static int
    +pci_default_setup(struct pci_dev *dev, struct pci_board *board,
    + struct serial_struct *req, int idx)
    +{
    + unsigned int bar, offset = board->first_offset;
    +
    + bar = SPCI_FL_GET_BASE(board->flags);
    + if (board->flags & SPCI_FL_BASE_TABLE)
    + bar += idx;
    + else
    + offset += idx * board->uart_offset;
    +
    + if (board->flags & SPCI_FL_REGION_SZ_CAP &&
    + idx >= pci_resource_len(dev, bar) / 8)
    + return 1;
    +
    + return setup_port(dev, req, bar, offset, board->reg_shift);
    +}
    +
    +/*
    + * Master list of serial port init/setup/exit quirks.
    + * This does not describe the general nature of the port.
    + * (ie, baud base, number and location of ports, etc)
    + *
    + * This list is ordered alphabetically by vendor then device.
    + * Specific entries must come before more generic entries.
    + */
    +static struct pci_serial_quirk pci_serial_quirks[] = {
    + /*
    + * AFAVLAB cards.
    + * It is not clear whether this applies to all products.
    + */
    + {
    + .vendor = PCI_VENDOR_ID_AFAVLAB,
    + .device = PCI_ANY_ID,
    + .subvendor = PCI_ANY_ID,
    + .subdevice = PCI_ANY_ID,
    + .setup = afavlab_setup,
    + },
    + /*
    + * HP Diva
    + */
    + {
    + .vendor = PCI_VENDOR_ID_HP,
    + .device = PCI_DEVICE_ID_HP_DIVA,
    + .subvendor = PCI_ANY_ID,
    + .subdevice = PCI_ANY_ID,
    + .init = pci_hp_diva_init,
    + .setup = pci_hp_diva_setup,
    + },
    + /*
    + * Intel
    + */
    + {
    + .vendor = PCI_VENDOR_ID_INTEL,
    + .device = PCI_DEVICE_ID_INTEL_80960_RP,
    + .subvendor = 0xe4bf,
    + .subdevice = PCI_ANY_ID,
    + .init = pci_inteli960ni_init,
    + .setup = pci_default_setup,
    + },
    + /*
    + * Panacom
    + */
    + {
    + .vendor = PCI_VENDOR_ID_PANACOM,
    + .device = PCI_DEVICE_ID_PANACOM_QUADMODEM,
    + .subvendor = PCI_ANY_ID,
    + .subdevice = PCI_ANY_ID,
    + .init = pci_plx9050_init,
    + .setup = pci_default_setup,
    + .exit = __devexit_p(pci_plx9050_exit),
    + },
    + {
    + .vendor = PCI_VENDOR_ID_PANACOM,
    + .device = PCI_DEVICE_ID_PANACOM_DUALMODEM,
    + .subvendor = PCI_ANY_ID,
    + .subdevice = PCI_ANY_ID,
    + .init = pci_plx9050_init,
    + .setup = pci_default_setup,
    + .exit = __devexit_p(pci_plx9050_exit),
    + },
    + /*
    + * PLX
    + */
    + {
    + .vendor = PCI_VENDOR_ID_PLX,
    + .device = PCI_DEVICE_ID_PLX_9050,
    + .subvendor = PCI_SUBVENDOR_ID_KEYSPAN,
    + .subdevice = PCI_SUBDEVICE_ID_KEYSPAN_SX2,
    + .init = pci_plx9050_init,
    + .setup = pci_default_setup,
    + .exit = __devexit_p(pci_plx9050_exit),
    + },
    + {
    + .vendor = PCI_VENDOR_ID_PLX,
    + .device = PCI_DEVICE_ID_PLX_ROMULUS,
    + .subvendor = PCI_VENDOR_ID_PLX,
    + .subdevice = PCI_DEVICE_ID_PLX_ROMULUS,
    + .init = pci_plx9050_init,
    + .setup = pci_default_setup,
    + .exit = __devexit_p(pci_plx9050_exit),
    + },
    + /*
    + * SIIG cards.
    + * It is not clear whether these could be collapsed.
    + */
    + {
    + .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,
    + .subvendor = PCI_ANY_ID,
    + .subdevice = PCI_ANY_ID,
    + .init = pci_siig20x_init,
    + .setup = pci_default_setup,
    + },
    + /*
    + * Titan cards
    + */
    + {
    + .vendor = PCI_VENDOR_ID_TITAN,
    + .device = PCI_DEVICE_ID_TITAN_400L,
    + .subvendor = PCI_ANY_ID,
    + .subdevice = PCI_ANY_ID,
    + .setup = titan_400l_800l_setup,
    + },
    + {
    + .vendor = PCI_VENDOR_ID_TITAN,
    + .device = PCI_DEVICE_ID_TITAN_800L,
    + .subvendor = PCI_ANY_ID,
    + .subdevice = PCI_ANY_ID,
    + .setup = titan_400l_800l_setup,
    + },
    + /*
    + * Timedia cards
    + */
    + {
    + .vendor = PCI_VENDOR_ID_TIMEDIA,
    + .device = PCI_DEVICE_ID_TIMEDIA_1889,
    + .subvendor = PCI_VENDOR_ID_TIMEDIA,
    + .subdevice = PCI_ANY_ID,
    + .init = pci_timedia_init,
    + .setup = pci_timedia_setup,
    + },
    + {
    + .vendor = PCI_VENDOR_ID_TIMEDIA,
    + .device = PCI_ANY_ID,
    + .subvendor = PCI_ANY_ID,
    + .subdevice = PCI_ANY_ID,
    + .setup = pci_timedia_setup,
    + },
    + /*
    + * Xircom cards
    + */
    + {
    + .vendor = PCI_VENDOR_ID_XIRCOM,
    + .device = PCI_DEVICE_ID_XIRCOM_X3201_MDM,
    + .subvendor = PCI_ANY_ID,
    + .subdevice = PCI_ANY_ID,
    + .init = pci_xircom_init,
    + .setup = pci_default_setup,
    + },
    + /*
    + * Default "match everything" terminator entry
    + */
    + {
    + .vendor = PCI_ANY_ID,
    + .device = PCI_ANY_ID,
    + .subvendor = PCI_ANY_ID,
    + .subdevice = PCI_ANY_ID,
    + .setup = pci_default_setup,
    + }
    +};
    +
    +static inline int quirk_id_matches(u32 quirk_id, u32 dev_id)
    +{
    + return quirk_id == PCI_ANY_ID || quirk_id == dev_id;
    +}
    +
    +static struct pci_serial_quirk *find_quirk(struct pci_dev *dev)
    +{
    + struct pci_serial_quirk *quirk;
    +
    + for (quirk = pci_serial_quirks; ; quirk++)
    + if (quirk_id_matches(quirk->vendor, dev->vendor) &&
    + quirk_id_matches(quirk->device, dev->device) &&
    + quirk_id_matches(quirk->subvendor, dev->subsystem_vendor) &&
    + quirk_id_matches(quirk->subdevice, dev->subsystem_device))
    + break;
    + return quirk;
    +}
    +
    +static _INLINE_ int
    +get_pci_irq(struct pci_dev *dev, struct pci_board *board, int idx)
    +{
    + int base_idx;
    +
    + if ((board->flags & SPCI_FL_IRQRESOURCE) == 0)
    + return dev->irq;
    +
    + base_idx = SPCI_FL_GET_IRQBASE(board->flags);
    + if (board->flags & SPCI_FL_IRQ_TABLE)
    + base_idx += idx;
    +
    + return dev->irq_resource[base_idx].start;
    +}
    +
    /*
    * This is the configuration table for all of the PCI serial boards
    * which we support. It is directly indexed by the pci_board_num_t enum
    * value, which is encoded in the pci_device_id PCI probe table's
    * driver_data member.
    + *
    + * The makeup of these names are:
    + * pbn_bn{_bt}_n_baud
    + *
    + * bn = PCI BAR number
    + * bt = Index using PCI BARs
    + * n = number of serial ports
    + * baud = baud rate
    + *
    + * 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
    */
    enum pci_board_num_t {
    - pbn_b0_1_115200,
    pbn_default = 0,

    + pbn_b0_1_115200,
    pbn_b0_2_115200,
    pbn_b0_4_115200,
    + pbn_b0_5_115200,

    pbn_b0_1_921600,
    pbn_b0_2_921600,
    @@ -465,171 +860,465 @@
    pbn_b0_bt_1_115200,
    pbn_b0_bt_2_115200,
    pbn_b0_bt_8_115200,
    +
    pbn_b0_bt_1_460800,
    pbn_b0_bt_2_460800,

    + pbn_b0_bt_1_921600,
    + pbn_b0_bt_2_921600,
    + pbn_b0_bt_4_921600,
    + pbn_b0_bt_8_921600,
    +
    pbn_b1_1_115200,
    pbn_b1_2_115200,
    pbn_b1_4_115200,
    pbn_b1_8_115200,

    + pbn_b1_1_921600,
    pbn_b1_2_921600,
    pbn_b1_4_921600,
    pbn_b1_8_921600,

    + pbn_b1_bt_2_921600,
    +
    pbn_b1_2_1382400,
    pbn_b1_4_1382400,
    pbn_b1_8_1382400,

    pbn_b2_1_115200,
    pbn_b2_8_115200,
    +
    + pbn_b2_1_460800,
    pbn_b2_4_460800,
    pbn_b2_8_460800,
    pbn_b2_16_460800,
    +
    + pbn_b2_1_921600,
    pbn_b2_4_921600,
    pbn_b2_8_921600,

    pbn_b2_bt_1_115200,
    pbn_b2_bt_2_115200,
    pbn_b2_bt_4_115200,
    +
    pbn_b2_bt_2_921600,
    + pbn_b2_bt_4_921600,
    +
    + pbn_b3_4_115200,
    + pbn_b3_8_115200,

    + /*
    + * Board-specific versions.
    + */
    pbn_panacom,
    pbn_panacom2,
    pbn_panacom4,
    pbn_plx_romulus,
    pbn_oxsemi,
    - pbn_timedia,
    pbn_intel_i960,
    pbn_sgi_ioc3,
    - pbn_hp_diva,
    pbn_nec_nile4,
    -
    - pbn_dci_pccom4,
    - pbn_dci_pccom8,
    -
    - pbn_xircom_combo,
    -
    - pbn_siig10x_0,
    - pbn_siig10x_1,
    - pbn_siig10x_2,
    - pbn_siig10x_4,
    - pbn_siig20x_0,
    - pbn_siig20x_2,
    - pbn_siig20x_4,
    -
    pbn_computone_4,
    pbn_computone_6,
    pbn_computone_8,
    };

    static struct pci_board pci_boards[] __devinitdata = {
    + [pbn_default] = {
    + .flags = SPCI_FL_BASE0,
    + .num_ports = 1,
    + .base_baud = 115200,
    + .uart_offset = 8,
    + },
    + [pbn_b0_1_115200] = {
    + .flags = SPCI_FL_BASE0,
    + .num_ports = 1,
    + .base_baud = 115200,
    + .uart_offset = 8,
    + },
    + [pbn_b0_2_115200] = {
    + .flags = SPCI_FL_BASE0,
    + .num_ports = 2,
    + .base_baud = 115200,
    + .uart_offset = 8,
    + },
    + [pbn_b0_4_115200] = {
    + .flags = SPCI_FL_BASE0,
    + .num_ports = 4,
    + .base_baud = 115200,
    + .uart_offset = 8,
    + },
    + [pbn_b0_5_115200] = {
    + .flags = SPCI_FL_BASE0,
    + .num_ports = 5,
    + .base_baud = 115200,
    + .uart_offset = 8,
    + },
    +
    + [pbn_b0_1_921600] = {
    + .flags = SPCI_FL_BASE0,
    + .num_ports = 1,
    + .base_baud = 921600,
    + .uart_offset = 8,
    + },
    + [pbn_b0_2_921600] = {
    + .flags = SPCI_FL_BASE0,
    + .num_ports = 2,
    + .base_baud = 921600,
    + .uart_offset = 8,
    + },
    + [pbn_b0_4_921600] = {
    + .flags = SPCI_FL_BASE0,
    + .num_ports = 4,
    + .base_baud = 921600,
    + .uart_offset = 8,
    + },
    +
    + [pbn_b0_bt_1_115200] = {
    + .flags = SPCI_FL_BASE0|SPCI_FL_BASE_TABLE,
    + .num_ports = 1,
    + .base_baud = 115200,
    + .uart_offset = 8,
    + },
    + [pbn_b0_bt_2_115200] = {
    + .flags = SPCI_FL_BASE0|SPCI_FL_BASE_TABLE,
    + .num_ports = 2,
    + .base_baud = 115200,
    + .uart_offset = 8,
    + },
    + [pbn_b0_bt_8_115200] = {
    + .flags = SPCI_FL_BASE0|SPCI_FL_BASE_TABLE,
    + .num_ports = 8,
    + .base_baud = 115200,
    + .uart_offset = 8,
    + },
    +
    + [pbn_b0_bt_1_460800] = {
    + .flags = SPCI_FL_BASE0|SPCI_FL_BASE_TABLE,
    + .num_ports = 1,
    + .base_baud = 460800,
    + .uart_offset = 8,
    + },
    + [pbn_b0_bt_2_460800] = {
    + .flags = SPCI_FL_BASE0|SPCI_FL_BASE_TABLE,
    + .num_ports = 2,
    + .base_baud = 460800,
    + .uart_offset = 8,
    + },
    +
    + [pbn_b0_bt_1_921600] = {
    + .flags = SPCI_FL_BASE0|SPCI_FL_BASE_TABLE,
    + .num_ports = 1,
    + .base_baud = 921600,
    + .uart_offset = 8,
    + },
    + [pbn_b0_bt_2_921600] = {
    + .flags = SPCI_FL_BASE0|SPCI_FL_BASE_TABLE,
    + .num_ports = 2,
    + .base_baud = 921600,
    + .uart_offset = 8,
    + },
    + [pbn_b0_bt_4_921600] = {
    + .flags = SPCI_FL_BASE0|SPCI_FL_BASE_TABLE,
    + .num_ports = 4,
    + .base_baud = 921600,
    + .uart_offset = 8,
    + },
    + [pbn_b0_bt_8_921600] = {
    + .flags = SPCI_FL_BASE0|SPCI_FL_BASE_TABLE,
    + .num_ports = 8,
    + .base_baud = 921600,
    + .uart_offset = 8,
    + },
    +
    + [pbn_b1_1_115200] = {
    + .flags = SPCI_FL_BASE1,
    + .num_ports = 1,
    + .base_baud = 115200,
    + .uart_offset = 8,
    + },
    + [pbn_b1_2_115200] = {
    + .flags = SPCI_FL_BASE1,
    + .num_ports = 2,
    + .base_baud = 115200,
    + .uart_offset = 8,
    + },
    + [pbn_b1_4_115200] = {
    + .flags = SPCI_FL_BASE1,
    + .num_ports = 4,
    + .base_baud = 115200,
    + .uart_offset = 8,
    + },
    + [pbn_b1_8_115200] = {
    + .flags = SPCI_FL_BASE1,
    + .num_ports = 8,
    + .base_baud = 115200,
    + .uart_offset = 8,
    + },
    +
    + [pbn_b1_1_921600] = {
    + .flags = SPCI_FL_BASE1,
    + .num_ports = 1,
    + .base_baud = 921600,
    + .uart_offset = 8,
    + },
    + [pbn_b1_2_921600] = {
    + .flags = SPCI_FL_BASE1,
    + .num_ports = 2,
    + .base_baud = 921600,
    + .uart_offset = 8,
    + },
    + [pbn_b1_4_921600] = {
    + .flags = SPCI_FL_BASE1,
    + .num_ports = 4,
    + .base_baud = 921600,
    + .uart_offset = 8,
    + },
    + [pbn_b1_8_921600] = {
    + .flags = SPCI_FL_BASE1,
    + .num_ports = 8,
    + .base_baud = 921600,
    + .uart_offset = 8,
    + },
    +
    + [pbn_b1_bt_2_921600] = {
    + .flags = SPCI_FL_BASE1|SPCI_FL_BASE_TABLE,
    + .num_ports = 2,
    + .base_baud = 921600,
    + .uart_offset = 8,
    + },
    +
    + [pbn_b1_2_1382400] = {
    + .flags = SPCI_FL_BASE1,
    + .num_ports = 2,
    + .base_baud = 1382400,
    + .uart_offset = 8,
    + },
    + [pbn_b1_4_1382400] = {
    + .flags = SPCI_FL_BASE1,
    + .num_ports = 4,
    + .base_baud = 1382400,
    + .uart_offset = 8,
    + },
    + [pbn_b1_8_1382400] = {
    + .flags = SPCI_FL_BASE1,
    + .num_ports = 8,
    + .base_baud = 1382400,
    + .uart_offset = 8,
    + },
    +
    + [pbn_b2_1_115200] = {
    + .flags = SPCI_FL_BASE2,
    + .num_ports = 1,
    + .base_baud = 115200,
    + .uart_offset = 8,
    + },
    + [pbn_b2_8_115200] = {
    + .flags = SPCI_FL_BASE2,
    + .num_ports = 8,
    + .base_baud = 115200,
    + .uart_offset = 8,
    + },
    +
    + [pbn_b2_1_460800] = {
    + .flags = SPCI_FL_BASE2,
    + .num_ports = 1,
    + .base_baud = 460800,
    + .uart_offset = 8,
    + },
    + [pbn_b2_4_460800] = {
    + .flags = SPCI_FL_BASE2,
    + .num_ports = 4,
    + .base_baud = 460800,
    + .uart_offset = 8,
    + },
    + [pbn_b2_8_460800] = {
    + .flags = SPCI_FL_BASE2,
    + .num_ports = 8,
    + .base_baud = 460800,
    + .uart_offset = 8,
    + },
    + [pbn_b2_16_460800] = {
    + .flags = SPCI_FL_BASE2,
    + .num_ports = 16,
    + .base_baud = 460800,
    + .uart_offset = 8,
    + },
    +
    + [pbn_b2_1_921600] = {
    + .flags = SPCI_FL_BASE2,
    + .num_ports = 1,
    + .base_baud = 921600,
    + .uart_offset = 8,
    + },
    + [pbn_b2_4_921600] = {
    + .flags = SPCI_FL_BASE2,
    + .num_ports = 4,
    + .base_baud = 921600,
    + .uart_offset = 8,
    + },
    + [pbn_b2_8_921600] = {
    + .flags = SPCI_FL_BASE2,
    + .num_ports = 8,
    + .base_baud = 921600,
    + .uart_offset = 8,
    + },
    +
    + [pbn_b2_bt_1_115200] = {
    + .flags = SPCI_FL_BASE2|SPCI_FL_BASE_TABLE,
    + .num_ports = 1,
    + .base_baud = 115200,
    + .uart_offset = 8,
    + },
    + [pbn_b2_bt_2_115200] = {
    + .flags = SPCI_FL_BASE2|SPCI_FL_BASE_TABLE,
    + .num_ports = 2,
    + .base_baud = 115200,
    + .uart_offset = 8,
    + },
    + [pbn_b2_bt_4_115200] = {
    + .flags = SPCI_FL_BASE2|SPCI_FL_BASE_TABLE,
    + .num_ports = 4,
    + .base_baud = 115200,
    + .uart_offset = 8,
    + },
    +
    + [pbn_b2_bt_2_921600] = {
    + .flags = SPCI_FL_BASE2|SPCI_FL_BASE_TABLE,
    + .num_ports = 2,
    + .base_baud = 921600,
    + .uart_offset = 8,
    + },
    + [pbn_b2_bt_4_921600] = {
    + .flags = SPCI_FL_BASE2|SPCI_FL_BASE_TABLE,
    + .num_ports = 4,
    + .base_baud = 921600,
    + .uart_offset = 8,
    + },
    +
    + [pbn_b3_4_115200] = {
    + .flags = SPCI_FL_BASE3,
    + .num_ports = 4,
    + .base_baud = 115200,
    + .uart_offset = 8,
    + },
    + [pbn_b3_8_115200] = {
    + .flags = SPCI_FL_BASE3,
    + .num_ports = 8,
    + .base_baud = 115200,
    + .uart_offset = 8,
    + },
    +
    + /*
    + * Entries following this are board-specific.
    + */
    +
    /*
    - * PCI Flags, Number of Ports, Base (Maximum) Baud Rate,
    - * Offset to get to next UART's registers,
    - * Register shift to use for memory-mapped I/O,
    - * Initialization function, first UART offset
    - */
    -
    - /* Generic serial board, pbn_b0_1_115200, pbn_default */
    - { SPCI_FL_BASE0, 1, 115200 }, /* pbn_b0_1_115200,
    - pbn_default */
    -
    - { SPCI_FL_BASE0, 2, 115200 }, /* pbn_b0_2_115200 */
    - { SPCI_FL_BASE0, 4, 115200 }, /* pbn_b0_4_115200 */
    -
    - { SPCI_FL_BASE0, 1, 921600 }, /* pbn_b0_1_921600 */
    - { SPCI_FL_BASE0, 2, 921600 }, /* pbn_b0_2_921600 */
    - { SPCI_FL_BASE0, 4, 921600 }, /* pbn_b0_4_921600 */
    -
    - { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 115200 }, /* pbn_b0_bt_1_115200 */
    - { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 115200 }, /* pbn_b0_bt_2_115200 */
    - { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 8, 115200 }, /* pbn_b0_bt_8_115200 */
    - { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 1, 460800 }, /* pbn_b0_bt_1_460800 */
    - { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 460800 }, /* pbn_b0_bt_2_460800 */
    -
    - { SPCI_FL_BASE1, 1, 115200 }, /* pbn_b1_1_115200 */
    - { SPCI_FL_BASE1, 2, 115200 }, /* pbn_b1_2_115200 */
    - { SPCI_FL_BASE1, 4, 115200 }, /* pbn_b1_4_115200 */
    - { SPCI_FL_BASE1, 8, 115200 }, /* pbn_b1_8_115200 */
    -
    - { SPCI_FL_BASE1, 2, 921600 }, /* pbn_b1_2_921600 */
    - { SPCI_FL_BASE1, 4, 921600 }, /* pbn_b1_4_921600 */
    - { SPCI_FL_BASE1, 8, 921600 }, /* pbn_b1_8_921600 */
    -
    - { SPCI_FL_BASE1, 2, 1382400 }, /* pbn_b1_2_1382400 */
    - { SPCI_FL_BASE1, 4, 1382400 }, /* pbn_b1_4_1382400 */
    - { SPCI_FL_BASE1, 8, 1382400 }, /* pbn_b1_8_1382400 */
    -
    - { SPCI_FL_BASE2, 1, 115200 }, /* pbn_b2_1_115200 */
    - { SPCI_FL_BASE2, 8, 115200 }, /* pbn_b2_8_115200 */
    - { SPCI_FL_BASE2, 4, 460800 }, /* pbn_b2_4_460800 */
    - { SPCI_FL_BASE2, 8, 460800 }, /* pbn_b2_8_460800 */
    - { SPCI_FL_BASE2, 16, 460800 }, /* pbn_b2_16_460800 */
    - { SPCI_FL_BASE2, 4, 921600 }, /* pbn_b2_4_921600 */
    - { SPCI_FL_BASE2, 8, 921600 }, /* pbn_b2_8_921600 */
    -
    - { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 1, 115200 }, /* pbn_b2_bt_1_115200 */
    - { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 2, 115200 }, /* pbn_b2_bt_2_115200 */
    - { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 4, 115200 }, /* pbn_b2_bt_4_115200 */
    - { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 2, 921600 }, /* pbn_b2_bt_2_921600 */
    -
    - { SPCI_FL_BASE2, 2, 921600, /* IOMEM */ /* pbn_panacom */
    - 0x400, 7, pci_plx9050_fn },
    - { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 2, 921600, /* pbn_panacom2 */
    - 0x400, 7, pci_plx9050_fn },
    - { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 4, 921600, /* pbn_panacom4 */
    - 0x400, 7, pci_plx9050_fn },
    - { SPCI_FL_BASE2, 4, 921600, /* pbn_plx_romulus */
    - 0x20, 2, pci_plx9050_fn, 0x03 },
    + * Panacom - IOMEM
    + */
    + [pbn_panacom] = {
    + .flags = SPCI_FL_BASE2,
    + .num_ports = 2,
    + .base_baud = 921600,
    + .uart_offset = 0x400,
    + .reg_shift = 7,
    + },
    + [pbn_panacom2] = {
    + .flags = SPCI_FL_BASE2|SPCI_FL_BASE_TABLE,
    + .num_ports = 2,
    + .base_baud = 921600,
    + .uart_offset = 0x400,
    + .reg_shift = 7,
    + },
    + [pbn_panacom4] = {
    + .flags = SPCI_FL_BASE2|SPCI_FL_BASE_TABLE,
    + .num_ports = 4,
    + .base_baud = 921600,
    + .uart_offset = 0x400,
    + .reg_shift = 7,
    + },
    +
    + /* I think this entry is broken - the first_offset looks wrong --rmk */
    + [pbn_plx_romulus] = {
    + .flags = SPCI_FL_BASE2,
    + .num_ports = 4,
    + .base_baud = 921600,
    + .uart_offset = 8 << 2,
    + .reg_shift = 2,
    + .first_offset = 0x03,
    + },

    /*
    * This board uses the size of PCI Base region 0 to
    * signal now many ports are available
    */
    - { SPCI_FL_BASE0 | SPCI_FL_REGION_SZ_CAP, 32, 115200 }, /* pbn_oxsemi */
    - { SPCI_FL_BASE_TABLE, 1, 921600, /* pbn_timedia */
    - 0, 0, pci_timedia_fn },
    - /* EKF addition for i960 Boards form EKF with serial port */
    - { SPCI_FL_BASE0, 32, 921600, /* max 256 ports */ /* pbn_intel_i960 */
    - 8<<2, 2, pci_inteli960ni_fn, 0x10000},
    - { SPCI_FL_BASE0 | SPCI_FL_IRQRESOURCE, /* pbn_sgi_ioc3 */
    - 1, 458333, 0, 0, 0, 0x20178 },
    - { SPCI_FL_BASE0, 5, 115200, 8, 0, pci_hp_diva, 0 },/* pbn_hp_diva */
    + [pbn_oxsemi] = {
    + .flags = SPCI_FL_BASE0|SPCI_FL_REGION_SZ_CAP,
    + .num_ports = 32,
    + .base_baud = 115200,
    + .uart_offset = 8,
    + },

    /*
    - * NEC Vrc-5074 (Nile 4) builtin UART.
    + * EKF addition for i960 Boards form EKF with serial port.
    + * Max 256 ports.
    */
    - { SPCI_FL_BASE0, 1, 520833, /* pbn_nec_nile4 */
    - 64, 3, NULL, 0x300 },
    + [pbn_intel_i960] = {
    + .flags = SPCI_FL_BASE0,
    + .num_ports = 32,
    + .base_baud = 921600,
    + .uart_offset = 8 << 2,
    + .reg_shift = 2,
    + .first_offset = 0x10000,
    + },
    + [pbn_sgi_ioc3] = {
    + .flags = SPCI_FL_BASE0|SPCI_FL_IRQRESOURCE,
    + .num_ports = 1,
    + .base_baud = 458333,
    + .uart_offset = 8,
    + .reg_shift = 0,
    + .first_offset = 0x20178,
    + },

    - { SPCI_FL_BASE3, 4, 115200, 8 }, /* pbn_dci_pccom4 */
    - { SPCI_FL_BASE3, 8, 115200, 8 }, /* pbn_dci_pccom8 */
    -
    - { SPCI_FL_BASE0, 1, 115200, /* pbn_xircom_combo */
    - 0, 0, pci_xircom_fn },
    + /*
    + * NEC Vrc-5074 (Nile 4) builtin UART.
    + */
    + [pbn_nec_nile4] = {
    + .flags = SPCI_FL_BASE0,
    + .num_ports = 1,
    + .base_baud = 520833,
    + .uart_offset = 8 << 3,
    + .reg_shift = 3,
    + .first_offset = 0x300,
    + },

    - { SPCI_FL_BASE2, 1, 460800, /* pbn_siig10x_0 */
    - 0, 0, pci_siig10x_fn },
    - { SPCI_FL_BASE2, 1, 921600, /* pbn_siig10x_1 */
    - 0, 0, pci_siig10x_fn },
    - { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 2, 921600, /* pbn_siig10x_2 */
    - 0, 0, pci_siig10x_fn },
    - { SPCI_FL_BASE2 | SPCI_FL_BASE_TABLE, 4, 921600, /* pbn_siig10x_4 */
    - 0, 0, pci_siig10x_fn },
    - { SPCI_FL_BASE0, 1, 921600, /* pbn_siix20x_0 */
    - 0, 0, pci_siig20x_fn },
    - { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 2, 921600, /* pbn_siix20x_2 */
    - 0, 0, pci_siig20x_fn },
    - { SPCI_FL_BASE0 | SPCI_FL_BASE_TABLE, 4, 921600, /* pbn_siix20x_4 */
    - 0, 0, pci_siig20x_fn },
    -
    - { SPCI_FL_BASE0, 4, 921600, /* IOMEM */ /* pbn_computone_4 */
    - 0x40, 2, NULL, 0x200 },
    - { SPCI_FL_BASE0, 6, 921600, /* IOMEM */ /* pbn_computone_6 */
    - 0x40, 2, NULL, 0x200 },
    - { SPCI_FL_BASE0, 8, 921600, /* IOMEM */ /* pbn_computone_8 */
    - 0x40, 2, NULL, 0x200 },
    + /*
    + * Computone - uses IOMEM.
    + */
    + [pbn_computone_4] = {
    + .flags = SPCI_FL_BASE0,
    + .num_ports = 4,
    + .base_baud = 921600,
    + .uart_offset = 0x40,
    + .reg_shift = 2,
    + .first_offset = 0x200,
    + },
    + [pbn_computone_6] = {
    + .flags = SPCI_FL_BASE0,
    + .num_ports = 6,
    + .base_baud = 921600,
    + .uart_offset = 0x40,
    + .reg_shift = 2,
    + .first_offset = 0x200,
    + },
    + [pbn_computone_8] = {
    + .flags = SPCI_FL_BASE0,
    + .num_ports = 8,
    + .base_baud = 921600,
    + .uart_offset = 0x40,
    + .reg_shift = 2,
    + .first_offset = 0x200,
    + },
    };

    /*
    @@ -640,8 +1329,7 @@
    static int __devinit
    serial_pci_guess_board(struct pci_dev *dev, struct pci_board *board)
    {
    - int num_iomem = 0, num_port = 0, first_port = -1;
    - int i;
    + int num_iomem, num_port, first_port = -1, i;

    /*
    * If it is not a communications device or the programming
    @@ -655,36 +1343,63 @@
    (dev->class & 0xff) > 6)
    return -ENODEV;

    - for (i = 0; i < 6; i++) {
    - if (IS_PCI_REGION_IOPORT(dev, i)) {
    + num_iomem = num_port = 0;
    + for (i = 0; i < PCI_NUM_BAR_RESOURCES; i++) {
    + if (pci_resource_flags(dev, i) & IORESOURCE_IO) {
    num_port++;
    if (first_port == -1)
    first_port = i;
    }
    - if (IS_PCI_REGION_IOMEM(dev, i))
    + if (pci_resource_flags(dev, i) & IORESOURCE_MEM)
    num_iomem++;
    }

    /*
    - * If there is 1 or 0 iomem regions, and exactly one port, use
    - * it.
    + * If there is 1 or 0 iomem regions, and exactly one port,
    + * use it. We guess the number of ports based on the IO
    + * region size.
    */
    if (num_iomem <= 1 && num_port == 1) {
    board->flags = first_port;
    + board->num_ports = pci_resource_len(dev, first_port) / 8;
    return 0;
    }
    +
    + /*
    + * Now guess if we've got a board which indexes by BARs.
    + * Each IO BAR should be 8 bytes, and they should follow
    + * consecutively.
    + */
    + first_port = -1;
    + num_port = 0;
    + for (i = 0; i < PCI_NUM_BAR_RESOURCES; i++) {
    + if (pci_resource_flags(dev, i) & IORESOURCE_IO &&
    + pci_resource_len(dev, i) == 8 &&
    + (first_port == -1 || (first_port + num_port) == i)) {
    + num_port++;
    + if (first_port == -1)
    + first_port = i;
    + }
    + }
    +
    + if (num_port > 1) {
    + board->flags = first_port | SPCI_FL_BASE_TABLE;
    + board->num_ports = num_port;
    + return 0;
    + }
    +
    return -ENODEV;
    }

    static inline int
    -serial_pci_matches(struct pci_board *board, int index)
    +serial_pci_matches(struct pci_board *board, struct pci_board *guessed)
    {
    return
    - board->base_baud == pci_boards[index].base_baud &&
    - board->num_ports == pci_boards[index].num_ports &&
    - board->uart_offset == pci_boards[index].uart_offset &&
    - board->reg_shift == pci_boards[index].reg_shift &&
    - board->first_uart_offset == pci_boards[index].first_uart_offset;
    + board->num_ports == guessed->num_ports &&
    + board->base_baud == guessed->base_baud &&
    + board->uart_offset == guessed->uart_offset &&
    + board->reg_shift == guessed->reg_shift &&
    + board->first_offset == guessed->first_offset;
    }

    /*
    @@ -696,6 +1411,7 @@
    {
    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;

    @@ -732,74 +1448,76 @@
    * 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, pbn_default)) {
    - printk(KERN_INFO
    - "Redundant entry in serial pci_table. Please send the output\n"
    - "of lspci -vv, this message (0x%04x,0x%04x,0x%04x,0x%04x),\n"
    - "the manufacturer and name of serial board or modem board to\n"
    - "rmk@arm.linux.org.uk.\n",
    - dev->vendor, dev->device,
    - pci_get_subvendor(dev), pci_get_subdevice(dev));
    - }
    + if (rc == 0 && serial_pci_matches(board, &tmp))
    + moan_device("Redundant entry in serial pci_table.", dev);
    }

    nr_ports = board->num_ports;

    /*
    - * Run the initialization function, if any. The initialization
    - * function returns:
    + * Find an init and setup quirks.
    + */
    + quirk = find_quirk(dev);
    +
    + /*
    + * Run the new-style initialization function.
    + * The initialization function returns:
    * <0 - error
    * 0 - use board->num_ports
    * >0 - number of ports
    */
    - if (board->init_fn) {
    - rc = board->init_fn(dev, 1);
    + if (quirk->init) {
    + rc = quirk->init(dev);
    if (rc < 0)
    goto disable;
    -
    if (rc)
    nr_ports = rc;
    }

    priv = kmalloc(sizeof(struct serial_private) +
    - sizeof(unsigned int) * nr_ports,
    - GFP_KERNEL);
    + sizeof(unsigned int) * nr_ports,
    + GFP_KERNEL);
    if (!priv) {
    rc = -ENOMEM;
    goto deinit;
    }

    + memset(priv, 0, sizeof(struct serial_private) +
    + sizeof(unsigned int) * nr_ports);
    +
    + priv->quirk = quirk;
    + pci_set_drvdata(dev, priv);
    +
    base_baud = board->base_baud;
    if (!base_baud)
    base_baud = BASE_BAUD;
    - memset(&serial_req, 0, sizeof(serial_req));
    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 (get_pci_port(dev, board, &serial_req, i))
    + if (quirk->setup(dev, board, &serial_req, 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);
    #endif
    - serial_req.flags = ASYNC_SKIP_TEST | ASYNC_AUTOPROBE;
    - serial_req.baud_base = base_baud;

    priv->line[i] = register_serial(&serial_req);
    if (priv->line[i] < 0)
    break;
    }

    - priv->board = board;
    priv->nr = i;

    - pci_set_drvdata(dev, priv);
    -
    return 0;

    deinit:
    - if (board->init_fn)
    - board->init_fn(dev, 0);
    + if (quirk->exit)
    + quirk->exit(dev);
    disable:
    pci_disable_device(dev);
    return rc;
    @@ -808,16 +1526,28 @@
    static void __devexit pci_remove_one(struct pci_dev *dev)
    {
    struct serial_private *priv = pci_get_drvdata(dev);
    - int i;

    pci_set_drvdata(dev, NULL);

    if (priv) {
    + struct pci_serial_quirk *quirk;
    + int i;
    +
    for (i = 0; i < priv->nr; i++)
    unregister_serial(priv->line[i]);

    - if (priv->board->init_fn)
    - priv->board->init_fn(dev, 0);
    + for (i = 0; i < PCI_NUM_BAR_RESOURCES; i++) {
    + if (priv->remapped_bar[i])
    + iounmap(priv->remapped_bar[i]);
    + priv->remapped_bar[i] = NULL;
    + }
    +
    + /*
    + * Find the exit quirks.
    + */
    + quirk = find_quirk(dev);
    + if (quirk->exit)
    + quirk->exit(dev);

    pci_disable_device(dev);

    @@ -825,6 +1555,40 @@
    }
    }

    +static int pci_suspend_one(struct pci_dev *dev, u32 state)
    +{
    +#ifdef not_yet
    + struct serial_private *priv = pci_get_drvdata(dev);
    + int i;
    +
    + if (priv)
    + for (i = 0; i < priv->nr; i++)
    + serial8250_suspend_port(priv->line[i]);
    +#endif
    + return 0;
    +}
    +
    +static int pci_resume_one(struct pci_dev *dev)
    +{
    +#ifdef not_yet
    + struct serial_private *priv = pci_get_drvdata(dev);
    + int i;
    +
    + if (priv) {
    + /*
    + * We may need to ensure that the board is correctly
    + * configured. This is just a guess. --rmk
    + */
    + if (priv->quirk->init)
    + priv->quirk->init(dev);
    +
    + for (i = 0; i < priv->nr; i++)
    + serial8250_resume_port(priv->line[i]);
    + }
    +#endif
    + return 0;
    +}
    +
    static struct pci_device_id serial_pci_tbl[] __devinitdata = {
    { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960,
    PCI_SUBVENDOR_ID_CONNECT_TECH,
    @@ -908,7 +1672,9 @@
    { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_SPCOM200,
    PCI_ANY_ID, PCI_ANY_ID, 0, 0,
    pbn_b2_bt_2_921600 },
    - /* VScom SPCOM800, from sl@s.pl */
    + /*
    + * VScom SPCOM800, from sl@s.pl
    + */
    { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_SPCOM800,
    PCI_ANY_ID, PCI_ANY_ID, 0, 0,
    pbn_b2_8_921600 },
    @@ -949,8 +1715,10 @@
    PCI_SUBVENDOR_ID_CHASE_PCIRAS,
    PCI_SUBDEVICE_ID_CHASE_PCIRAS8, 0, 0,
    pbn_b2_8_460800 },
    - /* Megawolf Romulus PCI Serial Card, from Mike Hudson */
    - /* (Exoray@isys.ca) */
    + /*
    + * Megawolf Romulus PCI Serial Card, from Mike Hudson
    + * (Exoray@isys.ca)
    + */
    { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_ROMULUS,
    0x10b5, 0x106a, 0, 0,
    pbn_plx_romulus },
    @@ -976,16 +1744,24 @@
    PCI_ANY_ID, PCI_ANY_ID, 0, 0,
    pbn_b0_2_115200 },

    - /* Digitan DS560-558, from jimd@esoft.com */
    + /*
    + * Digitan DS560-558, from jimd@esoft.com
    + */
    { PCI_VENDOR_ID_ATT, PCI_DEVICE_ID_ATT_VENUS_MODEM,
    PCI_ANY_ID, PCI_ANY_ID, 0, 0,
    pbn_b1_1_115200 },

    - /* 3Com US Robotics 56k Voice Internal PCI model 5610 */
    + /*
    + * 3Com US Robotics 56k Voice Internal PCI model 5610
    + */
    { PCI_VENDOR_ID_USR, 0x1008,
    - PCI_ANY_ID, PCI_ANY_ID, },
    + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
    + pbn_b0_1_115200 },

    - /* Titan Electronic cards */
    + /*
    + * Titan Electronic cards
    + * The 400L and 800L have a custom setup quirk.
    + */
    { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_100,
    PCI_ANY_ID, PCI_ANY_ID, 0, 0,
    pbn_b0_1_921600 },
    @@ -999,120 +1775,76 @@
    PCI_ANY_ID, PCI_ANY_ID, 0, 0,
    pbn_b0_4_921600 },
    { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_100L,
    - PCI_ANY_ID, PCI_ANY_ID,
    - SPCI_FL_BASE1, 1, 921600 },
    + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
    + pbn_b1_1_921600 },
    { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200L,
    - PCI_ANY_ID, PCI_ANY_ID,
    - SPCI_FL_BASE1 | SPCI_FL_BASE_TABLE, 2, 921600 },
    - /* The 400L and 800L have a custom hack in get_pci_port */
    + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
    + pbn_b1_bt_2_921600 },
    { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_400L,
    - PCI_ANY_ID, PCI_ANY_ID,
    - SPCI_FL_BASE_TABLE, 4, 921600 },
    + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
    + pbn_b0_bt_4_921600 },
    { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800L,
    - PCI_ANY_ID, PCI_ANY_ID,
    - SPCI_FL_BASE_TABLE, 8, 921600 },
    + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
    + pbn_b0_bt_8_921600 },

    { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_10x_550,
    PCI_ANY_ID, PCI_ANY_ID, 0, 0,
    - pbn_siig10x_0 },
    + pbn_b2_1_460800 },
    { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_10x_650,
    PCI_ANY_ID, PCI_ANY_ID, 0, 0,
    - pbn_siig10x_0 },
    + pbn_b2_1_460800 },
    { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_10x_850,
    PCI_ANY_ID, PCI_ANY_ID, 0, 0,
    - pbn_siig10x_0 },
    - { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_550,
    - PCI_ANY_ID, PCI_ANY_ID, 0, 0,
    - pbn_siig10x_1 },
    - { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_650,
    - PCI_ANY_ID, PCI_ANY_ID, 0, 0,
    - pbn_siig10x_1 },
    - { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_10x_850,
    - PCI_ANY_ID, PCI_ANY_ID, 0, 0,
    - pbn_siig10x_1 },
    + pbn_b2_1_460800 },
    { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_10x_550,
    PCI_ANY_ID, PCI_ANY_ID, 0, 0,
    - pbn_siig10x_2 },
    + pbn_b2_bt_2_921600 },
    { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_10x_650,
    PCI_ANY_ID, PCI_ANY_ID, 0, 0,
    - pbn_siig10x_2 },
    + pbn_b2_bt_2_921600 },
    { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_10x_850,
    PCI_ANY_ID, PCI_ANY_ID, 0, 0,
    - pbn_siig10x_2 },
    - { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_10x_550,
    - PCI_ANY_ID, PCI_ANY_ID, 0, 0,
    - pbn_siig10x_2 },
    - { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_10x_650,
    - PCI_ANY_ID, PCI_ANY_ID, 0, 0,
    - pbn_siig10x_2 },
    - { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_10x_850,
    - PCI_ANY_ID, PCI_ANY_ID, 0, 0,
    - pbn_siig10x_2 },
    + pbn_b2_bt_2_921600 },
    { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_10x_550,
    PCI_ANY_ID, PCI_ANY_ID, 0, 0,
    - pbn_siig10x_4 },
    + pbn_b2_bt_4_921600 },
    { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_10x_650,
    PCI_ANY_ID, PCI_ANY_ID, 0, 0,
    - pbn_siig10x_4 },
    + pbn_b2_bt_4_921600 },
    { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_10x_850,
    PCI_ANY_ID, PCI_ANY_ID, 0, 0,
    - pbn_siig10x_4 },
    + pbn_b2_bt_4_921600 },
    { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_20x_550,
    PCI_ANY_ID, PCI_ANY_ID, 0, 0,
    - pbn_siig20x_0 },
    + pbn_b0_1_921600 },
    { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_20x_650,
    PCI_ANY_ID, PCI_ANY_ID, 0, 0,
    - pbn_siig20x_0 },
    + pbn_b0_1_921600 },
    { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_20x_850,
    PCI_ANY_ID, PCI_ANY_ID, 0, 0,
    - pbn_siig20x_0 },
    - { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_20x_550,
    - PCI_ANY_ID, PCI_ANY_ID, 0, 0,
    - pbn_siig20x_0 },
    - { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_20x_650,
    - PCI_ANY_ID, PCI_ANY_ID, 0, 0,
    - pbn_siig20x_0 },
    - { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S1P_20x_850,
    - PCI_ANY_ID, PCI_ANY_ID, 0, 0,
    - pbn_siig20x_0 },
    - { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P1S_20x_550,
    - PCI_ANY_ID, PCI_ANY_ID, 0, 0,
    - pbn_siig20x_0 },
    - { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P1S_20x_650,
    - PCI_ANY_ID, PCI_ANY_ID, 0, 0,
    - pbn_siig20x_0 },
    - { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2P1S_20x_850,
    - PCI_ANY_ID, PCI_ANY_ID, 0, 0,
    - pbn_siig20x_0 },
    + pbn_b0_1_921600 },
    { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_20x_550,
    PCI_ANY_ID, PCI_ANY_ID, 0, 0,
    - pbn_siig20x_2 },
    + pbn_b0_bt_2_921600 },
    { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_20x_650,
    PCI_ANY_ID, PCI_ANY_ID, 0, 0,
    - pbn_siig20x_2 },
    + pbn_b0_bt_2_921600 },
    { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_20x_850,
    PCI_ANY_ID, PCI_ANY_ID, 0, 0,
    - pbn_siig20x_2 },
    - { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_20x_550,
    - PCI_ANY_ID, PCI_ANY_ID, 0, 0,
    - pbn_siig20x_2 },
    - { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_20x_650,
    - PCI_ANY_ID, PCI_ANY_ID, 0, 0,
    - pbn_siig20x_2 },
    - { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S1P_20x_850,
    - PCI_ANY_ID, PCI_ANY_ID, 0, 0,
    - pbn_siig20x_2 },
    + pbn_b0_bt_2_921600 },
    { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_20x_550,
    PCI_ANY_ID, PCI_ANY_ID, 0, 0,
    - pbn_siig20x_4 },
    + pbn_b0_bt_4_921600 },
    { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_20x_650,
    PCI_ANY_ID, PCI_ANY_ID, 0, 0,
    - pbn_siig20x_4 },
    + pbn_b0_bt_4_921600 },
    { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_20x_850,
    PCI_ANY_ID, PCI_ANY_ID, 0, 0,
    - pbn_siig20x_4 },
    + pbn_b0_bt_4_921600 },

    - /* Computone devices submitted by Doug McNash dmcnash@computone.com */
    + /*
    + * Computone devices submitted by Doug McNash dmcnash@computone.com
    + */
    { PCI_VENDOR_ID_COMPUTONE, PCI_DEVICE_ID_COMPUTONE_PG,
    PCI_SUBVENDOR_ID_COMPUTONE, PCI_SUBDEVICE_ID_COMPUTONE_PG4,
    0, 0, pbn_computone_4 },
    @@ -1124,18 +1856,22 @@
    0, 0, pbn_computone_6 },

    { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI95N,
    - PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_oxsemi },
    + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
    + pbn_oxsemi },
    { PCI_VENDOR_ID_TIMEDIA, PCI_DEVICE_ID_TIMEDIA_1889,
    - PCI_VENDOR_ID_TIMEDIA, PCI_ANY_ID, 0, 0, pbn_timedia },
    + PCI_VENDOR_ID_TIMEDIA, PCI_ANY_ID, 0, 0,
    + pbn_b0_bt_1_921600 },

    - { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_DSERIAL,
    - PCI_ANY_ID, PCI_ANY_ID, 0, 0,
    - pbn_b0_bt_2_115200 },
    - /* AFAVLAB serial card, from Harald Welte <laforge@gnumonks.org> */
    + /*
    + * AFAVLAB serial card, from Harald Welte <laforge@gnumonks.org>
    + */
    { PCI_VENDOR_ID_AFAVLAB, PCI_DEVICE_ID_AFAVLAB_P028,
    PCI_ANY_ID, PCI_ANY_ID, 0, 0,
    pbn_b0_bt_8_115200 },

    + { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_DSERIAL,
    + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
    + pbn_b0_bt_2_115200 },
    { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUATRO_A,
    PCI_ANY_ID, PCI_ANY_ID, 0, 0,
    pbn_b0_bt_2_115200 },
    @@ -1158,26 +1894,40 @@
    PCI_ANY_ID, PCI_ANY_ID, 0, 0,
    pbn_b0_bt_1_460800 },

    - /* RAStel 2 port modem, gerg@moreton.com.au */
    + /*
    + * RAStel 2 port modem, gerg@moreton.com.au
    + */
    { PCI_VENDOR_ID_MORETON, PCI_DEVICE_ID_RASTEL_2PORT,
    PCI_ANY_ID, PCI_ANY_ID, 0, 0,
    pbn_b2_bt_2_115200 },

    - /* EKF addition for i960 Boards form EKF with serial port */
    - { PCI_VENDOR_ID_INTEL, 0x1960,
    + /*
    + * EKF addition for i960 Boards form EKF with serial port
    + */
    + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_80960_RP,
    0xE4BF, PCI_ANY_ID, 0, 0,
    pbn_intel_i960 },

    - /* Xircom Cardbus/Ethernet combos */
    + /*
    + * Xircom Cardbus/Ethernet combos
    + */
    { PCI_VENDOR_ID_XIRCOM, PCI_DEVICE_ID_XIRCOM_X3201_MDM,
    PCI_ANY_ID, PCI_ANY_ID, 0, 0,
    - pbn_xircom_combo },
    + pbn_b0_1_115200 },
    + /*
    + * Xircom RBM56G cardbus modem - Dirk Arnold (temp entry)
    + */
    + { PCI_VENDOR_ID_XIRCOM, PCI_DEVICE_ID_XIRCOM_RBM56G,
    + PCI_ANY_ID, PCI_ANY_ID, 0, 0,
    + pbn_b0_1_115200 },

    /*
    * Untested PCI modems, sent in from various folks...
    */

    - /* Elsa Model 56K PCI Modem, from Andreas Rath <arh@01019freenet.de> */
    + /*
    + * Elsa Model 56K PCI Modem, from Andreas Rath <arh@01019freenet.de>
    + */
    { PCI_VENDOR_ID_ROCKWELL, 0x1004,
    0x1048, 0x1500, 0, 0,
    pbn_b1_1_115200 },
    @@ -1186,10 +1936,12 @@
    0xFF00, 0, 0, 0,
    pbn_sgi_ioc3 },

    - /* HP Diva card */
    + /*
    + * HP Diva card
    + */
    { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_DIVA,
    PCI_ANY_ID, PCI_ANY_ID, 0, 0,
    - pbn_hp_diva },
    + pbn_b0_5_115200 },
    { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_DIVA_AUX,
    PCI_ANY_ID, PCI_ANY_ID, 0, 0,
    pbn_b2_1_115200 },
    @@ -1203,10 +1955,10 @@

    { PCI_VENDOR_ID_DCI, PCI_DEVICE_ID_DCI_PCCOM4,
    PCI_ANY_ID, PCI_ANY_ID, 0, 0,
    - pbn_dci_pccom4 },
    + pbn_b3_4_115200 },
    { PCI_VENDOR_ID_DCI, PCI_DEVICE_ID_DCI_PCCOM8,
    PCI_ANY_ID, PCI_ANY_ID, 0, 0,
    - pbn_dci_pccom8 },
    + pbn_b3_8_115200 },

    /*
    * These entries match devices with class
    @@ -1232,7 +1984,12 @@
    .name = "serial",
    .probe = pci_init_one,
    .remove = __devexit_p(pci_remove_one),
    + .suspend = pci_suspend_one,
    + .resume = pci_resume_one,
    .id_table = serial_pci_tbl,
    + .driver = {
    + .devclass = &tty_devclass,
    + },
    };

    static int __init serial8250_pci_init(void)
    --
    Russell King (rmk@arm.linux.org.uk) The developer of ARM Linux
    http://www.arm.linux.org.uk/personal/aboutme.html

    -
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

    \
     
     \ /
      Last update: 2005-03-22 13:33    [W:0.130 / U:90.180 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site