diff -urdpNX dontdiff linux-2.6.24.vanilla/drivers/serial/8250_pci.c linux-2.6.24/drivers/serial/8250_pci.c --- linux-2.6.24.vanilla/drivers/serial/8250_pci.c 2007-10-28 13:00:14.000000000 +0300 +++ linux-2.6.24/drivers/serial/8250_pci.c 2007-10-28 18:15:12.000000000 +0300 @@ -610,45 +610,49 @@ static int pci_netmos_init(struct pci_de /* enable IO_Space bit */ #define ITE_887x_POSIO_ENABLE (1 << 31) -static int pci_ite887x_init(struct pci_dev *dev) +static int pci_ite_887x_allocate_io(struct pci_dev *dev) { - /* inta_addr are the configuration addresses of the ITE */ - static const short inta_addr[] = { 0x2a0, 0x2c0, 0x220, 0x240, 0x1e0, - 0x200, 0x280, 0 }; - int ret, i, type; - struct resource *iobase = NULL; - u32 miscr, uartbar, ioport; + static const short inta_addr[] = { + 0x2a0, 0x2c0, 0x220, 0x240, 0x1e0, 0x200, 0x280, 0 + }; + int ret, i; - /* search for the base-ioport */ - i = 0; - while (inta_addr[i] && iobase == NULL) { - iobase = request_region(inta_addr[i], ITE_887x_IOSIZE, - "ite887x"); - if (iobase != NULL) { + for (i = 0; i < ARRAY_SIZE(inta_addr); i++) { + int iobase = inta_addr[i]; + + if (request_region(iobase, ITE_887x_IOSIZE, "ite887x")) { /* write POSIO0R - speed | size | ioport */ pci_write_config_dword(dev, ITE_887x_POSIO0, ITE_887x_POSIO_ENABLE | ITE_887x_POSIO_SPEED | - ITE_887x_POSIO_IOSIZE_32 | inta_addr[i]); + ITE_887x_POSIO_IOSIZE_32 | iobase); + /* write INTCBAR - ioport */ - pci_write_config_dword(dev, ITE_887x_INTCBAR, inta_addr[i]); - ret = inb(inta_addr[i]); + pci_write_config_dword(dev, ITE_887x_INTCBAR, iobase); + ret = inb(iobase); if (ret != 0xff) { /* ioport connected */ - break; + return iobase; } - release_region(iobase->start, ITE_887x_IOSIZE); - iobase = NULL; + release_region(iobase, ITE_887x_IOSIZE); } - i++; } - if (!inta_addr[i]) { + return 0; +} + +static int pci_ite887x_init(struct pci_dev *dev) +{ + int i, ret, type, iobase; + u32 miscr, uartbar, ioport; + + iobase = pci_ite_887x_allocate_io(dev); + if (!iobase) { printk(KERN_ERR "ite887x: could not find iobase\n"); return -ENODEV; } /* start of undocumented type checking (see parport_pc.c) */ - type = inb(iobase->start + 0x18) & 0x0f; + type = inb(iobase + 0x18) & 0x0f; switch (type) { case 0x2: /* ITE8871 (1P) */ @@ -697,7 +701,7 @@ static int pci_ite887x_init(struct pci_d if (ret <= 0) { /* the device has no UARTs if we get here */ - release_region(iobase->start, ITE_887x_IOSIZE); + release_region(iobase, ITE_887x_IOSIZE); } return ret; @@ -712,6 +716,57 @@ static void __devexit pci_ite887x_exit(s release_region(ioport, ITE_887x_IOSIZE); } +#define ITE_887x_IRR0 0 +#define ITE_887x_IRR1 1 +#define ITE_887x_IRR2 2 +#define ITE_887x_IMR0 4 +#define ITE_887x_IMR1 5 +#define ITE_887x_IMR2 6 +#define ITE_887x_IER0 8 +#define ITE_887x_IER1 9 +#define ITE_887x_IER2 10 +#define ITE_887x_ITR0 12 +#define ITE_887x_ITR1 13 +#define ITE_887x_ITR2 14 + +static int pci_syba_ite887x_init(struct pci_dev *dev) +{ + int iobase = pci_ite_887x_allocate_io(dev); + + if (!iobase) { + printk(KERN_ERR "ite887x: could not find iobase\n"); + return -ENODEV; + } + + /* DEBUG */ + printk(KERN_INFO "ite887x: io base at %#x\n", iobase); + printk(KERN_INFO "ite887x: IRR0=%02x IMR0=%02x IER0=%02x\n", + inb(iobase + ITE_887x_IRR0), inb(iobase + ITE_887x_IMR0), inb(iobase + ITE_887x_IER0)); + printk(KERN_INFO "ite887x: IRR1=%02x IMR1=%02x IER1=%02x\n", + inb(iobase + ITE_887x_IRR1), inb(iobase + ITE_887x_IMR1), inb(iobase + ITE_887x_IER1)); + printk(KERN_INFO "ite887x: IRR2=%02x IMR2=%02x IER2=%02x\n", + inb(iobase + ITE_887x_IRR2), inb(iobase + ITE_887x_IMR2), inb(iobase + ITE_887x_IER2)); + + /* Clear s/w interrupt genaration register (just in case) */ + outb(0, iobase + ITE_887x_IER0); + outb(0, iobase + ITE_887x_IER1); + outb(0, iobase + ITE_887x_IER2); + + /* Clear IRQ latches */ + outb(0, iobase + ITE_887x_IRR0); + outb(0, iobase + ITE_887x_IRR1); + outb(0, iobase + ITE_887x_IRR2); + + /* Mask interrupts from on-chip devices (unused on this card) */ + outb(0xf, iobase + ITE_887x_IMR2); + + /* Set external IRQ mode to level-triggered */ + outb(0xff, iobase + ITE_887x_IER0); + outb(0xff, iobase + ITE_887x_IER1); + + return 8; +} + static int pci_default_setup(struct serial_private *priv, struct pciserial_board *board, struct uart_port *port, int idx) @@ -797,6 +852,18 @@ static struct pci_serial_quirk pci_seria .exit = __devexit_p(pci_ite887x_exit), }, /* + * Syba + */ + { + .vendor = PCI_VENDOR_ID_PLX, + .device = 0x9016, + .subvendor = 0x544e, + .subdevice = 0x0008, + .init = pci_syba_ite887x_init, + .setup = pci_default_setup, + .exit = __devexit_p(pci_ite887x_exit), + }, + /* * Panacom */ { @@ -2527,6 +2594,11 @@ static struct pci_device_id serial_pci_t PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_b3_8_115200 }, + /* Syba PCI8871-PR8 8-port serial card */ + { PCI_VENDOR_ID_PLX, 0x9016, + 0x544e, 0x0008, 0, 0, + pbn_b0_8_115200 }, + /* * Exar Corp. XR17C15[248] Dual/Quad/Octal UART */