[PATCH] Generic detection of ISA PnP serail devices

From: Andrey Panin (pazke@orbita.don.sitek.net)
Date: Wed Mar 22 2000 - 07:16:05 EST


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,
                Andrey

diff -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");

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



This archive was generated by hypermail 2b29 : Thu Mar 23 2000 - 21:00:36 EST