Messages in this thread Patch in this message | | | Date | Wed, 22 Mar 2000 15:16:05 +0300 | From | Andrey Panin <> | Subject | [PATCH] Generic detection of ISA PnP serail devices |
| |
Hi all,
attached patch provides generic detection for ISA PnP modems not listed in pnp_devices[] table.
This patch adds serial_pnp_guess_board(dev, board) function which tries to recognize modems, using some fingerprints: - device must not be activated; - dev->name or dev->bus->name must contain "modem" substring; - device must have only one IO region (8 byte long) with base adress 0x2e8, 0x3e8, 0x2f8 or 0x3f8.
Such detection looks ugly, but it can detect at least some of numerous ISA PnP modems, alternatively we must hardcode all modems in pnp_devices[] table :((
Best wishes, Andreydiff -u -r -N /mnt/d/linux/drivers/char/serial.c /linux/drivers/char/serial.c --- /mnt/d/linux/drivers/char/serial.c Tue Mar 21 00:53:42 2000 +++ /linux/drivers/char/serial.c Tue Mar 21 20:09:14 2000 @@ -4209,8 +4209,8 @@ * guess what the configuration might be, based on the pitiful PCI * serial specs. Returns 0 on success, 1 on failure. */ -static int _INLINE_ serial_guess_board(struct pci_dev *dev, - struct pci_board *board) +static int _INLINE_ serial_pci_guess_board(struct pci_dev *dev, + struct pci_board *board) { int num_iomem = 0, num_port = 0, first_port = -1; int i; @@ -4289,7 +4289,7 @@ break; } - if (board->vendor == 0 && serial_guess_board(dev, board)) + if (board->vendor == 0 && serial_pci_guess_board(dev, board)) continue; start_pci_pnp_board(dev, board); @@ -4328,7 +4328,11 @@ /* Generic 16550A-compatible COM port */ { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0x0501), 0, 0, SPCI_FL_BASE0 | SPCI_FL_PNPDEFAULT, 1, 115200 }, - { 0, } + + /* Generic ISA PnP serial board */ + { 0, 0, 0, 0, + SPCI_FL_BASE0 | SPCI_FL_NO_SHIRQ | SPCI_FL_PNPDEFAULT, + 1, 115200 }, }; static void inline avoid_irq_share(struct pci_dev *dev) @@ -4349,6 +4353,49 @@ irq->map = map; } +/* + * Given a complete unknown ISA PnP device, try to use some hueristics to + * detect modems. Currently use such heuristic set: + * - dev->name or dev->bus->name must contain "modem" substring; + * - device must have only one resource record; + * - device must have IO region (8 byte long) with base adress + * 0x2e8, 0x3e8, 0x2f8 or 0x3f8 as one of alternate resource records. + * + * Such detection looks very ugly, but can detect at least some of numerous + * ISA PnP modems, alternatively we must hardcode all modems in pnp_devices[] + * table. + */ +static int _INLINE_ serial_pnp_guess_board(struct pci_dev *dev, + struct pci_board *board) +{ + if (dev->active) + return 1; + + if (strstr(dev->name, "modem") || strstr(dev->name, "Modem") || + strstr(dev->name, "MODEM") || strstr(dev->bus->name, "modem") || + strstr(dev->bus->name, "Modem") || strstr(dev->bus->name, "MODEM")) { + + struct isapnp_resources *res = (struct isapnp_resources *)dev->sysdata; + struct isapnp_resources *resa; + + if (res->next) + return 1; + + for (resa = res->alt; resa; resa = resa->alt) { + struct isapnp_port *port; + for (port = res->port; port; port = port->next) + if ((port->size == 8) && + ((port->min == 0x2f8) || + (port->min == 0x3f8) || + (port->min == 0x2e8) || + (port->min == 0x3e8))) + return 0; + } + } + + return 1; +} + static void __init probe_serial_pnp(void) { struct pci_dev *dev = NULL; @@ -4364,14 +4411,19 @@ return; } - for (board = pnp_devices; board->vendor; board++) { - while ((dev = isapnp_find_dev(NULL, board->vendor, - board->device, dev))) { - if (board->flags & SPCI_FL_NO_SHIRQ) - avoid_irq_share(dev); - start_pci_pnp_board(dev, board); - } - } + isapnp_for_each_dev(dev) { + for (board = pnp_devices; board->vendor; board++) + if ((dev->vendor == board->vendor) && + (dev->device == board->device)) + break; + + if (board->vendor == 0 && serial_pnp_guess_board(dev, board)) + continue; + + if (board->flags & SPCI_FL_NO_SHIRQ) + avoid_irq_share(dev); + start_pci_pnp_board(dev, board); + } #ifdef SERIAL_DEBUG_PNP printk("Leaving probe_serial_pnp() (probe finished)\n"); | |