[PATCH] Generic detection of ISA PnP modems (newest)

From: Andrey Panin (pazke@orbita.don.sitek.net)
Date: Thu Mar 30 2000 - 07:37:30 EST


Hi all,

This is new (and last, I hope) patch for ISA PnP modem detection.
Added some new strings as suggested by Jamie Lokier.
IMHO this patch can detect almost all ISA PnP modems now :))

Best wishes,
                    Andrey

diff -urN /mnt/h/linux/drivers/char/serial.c /linux/drivers/char/serial.c
--- /mnt/h/linux/drivers/char/serial.c Tue Mar 28 19:18:50 2000
+++ /linux/drivers/char/serial.c Wed Mar 29 18:38:17 2000
@@ -4225,12 +4225,12 @@
 };

 /*
- * Given a complete unknown PCI device, try to use some hueristics to
+ * Given a complete unknown PCI device, try to use some heuristics to
  * 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;
@@ -4309,7 +4309,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);
@@ -4374,7 +4374,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)
@@ -4395,6 +4399,65 @@
                        irq->map = map;
 }

+static char *modem_names[] = {
+ "MODEM", "Modem", "modem", "FAX", "Fax", "fax",
+ "56K", "56k", "K56", "33.6", "28.8", "14.4",
+ "33,600", "28,800", "14,400", "33.600", "28.800", "14.400",
+ "33600", "28800", "14400", "V.90", "V.34", "V.32", 0
+};
+
+static int check_name(char *name)
+{
+ char **tmp = modem_names;
+
+ while (*tmp) {
+ if (strstr(name, *tmp))
+ return 1;
+ tmp++;
+ }
+ return 0;
+}
+
+/*
+ * Given a complete unknown ISA PnP device, try to use some heuristics to
+ * detect modems. Currently use such heuristic set:
+ * - 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 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)
+{
+ struct isapnp_resources *res = (struct isapnp_resources *)dev->sysdata;
+ struct isapnp_resources *resa;
+
+ if (dev->active)
+ return 1;
+
+ if (!(check_name(dev->name) || check_name(dev->bus->name)))
+ return 1;
+
+ 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;
@@ -4410,14 +4473,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 : Fri Mar 31 2000 - 21:00:27 EST