[PATCH] ISA Plug-n-Play support for the serial driver (2.3.29)

Andrey Panin (pazke@orbita.don.sitek.net)
Mon, 29 Nov 1999 17:21:38 +0300


Hi all !

This is new ISA Plug-n-Play support patch for the serial driver.
The previous one was horribly ugly :(

Changes:
1) used isapnp_find_dev() instead of direct search in PNP device list;
2) added compatibility ID's to the list of supported devices;
3) request_irq()/free_irq() removed.

I hope it will be usefull.

Andrey.

--- /mnt/c/linux/drivers/char/serial.c Sun Nov 28 11:02:29 1999
+++ /linux/drivers/char/serial.c Sun Nov 28 11:00:26 1999
@@ -99,6 +99,12 @@
#endif
#endif

+#ifdef CONFIG_ISAPNP
+#ifndef ENABLE_SERIAL_PNP
+#define ENABLE_SERIAL_PNP
+#endif
+#endif
+
/* Set of debugging defines */

#undef SERIAL_DEBUG_INTR
@@ -200,6 +206,9 @@
#ifdef ENABLE_SERIAL_PCI
#include <linux/pci.h>
#endif
+#ifdef ENABLE_SERIAL_PNP
+#include <linux/isapnp.h>
+#endif

/*
* All of the compatibilty code so we can compile serial.c against
@@ -294,7 +303,7 @@

#define NR_PORTS (sizeof(rs_table)/sizeof(struct serial_state))

-#ifdef ENABLE_SERIAL_PCI
+#if (defined(ENABLE_SERIAL_PCI) || defined(ENABLE_SERIAL_PNP))
#define NR_PCI_BOARDS 8
static struct pci_board_inst serial_pci_board[NR_PCI_BOARDS];
static int serial_pci_board_idx = 0;
@@ -4109,7 +4118,7 @@
dev->irq, port, board->flags & SPCI_FL_IOMEM ?
"iomem" : "port", board->num_ports);
#endif
-
+
for (k=0; k < board->num_ports; k++) {
if (board->flags & SPCI_FL_BASE_TABLE) {
port = PCI_BASE_ADDRESS(dev, base_idx++);
@@ -4146,6 +4155,133 @@

#endif /* ENABLE_SERIAL_PCI */

+#ifdef ENABLE_SERIAL_PNP
+
+static struct pci_board pnp_devices[] __initdata = {
+ /* Rockwell 56K ACF II Fax+Data+Voice Modem */
+ { ISAPNP_VENDOR('A', 'K', 'Y'), ISAPNP_DEVICE(0x1021), 0, 0,
+ SPCI_FL_BASE0, 1, 115200 },
+ /* Boca Research 33,600 ACF Modem */
+ { ISAPNP_VENDOR('B', 'R', 'I'), ISAPNP_DEVICE(0x1400), 0, 0,
+ SPCI_FL_BASE0, 1, 115200 },
+ /* Best Data Products Inc. Smart One 336F PnP Modem */
+ { ISAPNP_VENDOR('B', 'D', 'P'), ISAPNP_DEVICE(0x3336
), 0, 0,
+ SPCI_FL_BASE0, 1, 115200 },
+ /* These ID's are taken from M$ documentation */
+ /* Compaq 14400 Modem */
+ { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC000), 0, 0,
+ SPCI_FL_BASE0, 1, 115200 },
+ /* Compaq 2400/9600 Modem */
+ { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0xC001), 0, 0,
+ SPCI_FL_BASE0, 1, 115200 },
+ /* Generic standard PC COM port
*/
+ { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0x0500), 0, 0,
+ SPCI_FL_BASE0, 1, 115200 },
+ /* Generic 16550A-compatible COM port
*/
+ { ISAPNP_VENDOR('P', 'N', 'P'), ISAPNP_DEVICE(0x0501), 0, 0,
+ SPCI_FL_BASE0, 1, 115200 },
+ { 0, }
+};
+
+static void __init printk_pnp_dev_id(unsigned short vendor, unsigned short
device)
+{
+ printk("%c%c%c%x%x%x%x",
+ 'A' + ((vendor >> 2) & 0x3f) - 1,
+ 'A' + (((vendor & 3) << 3) | ((vendor >> 13) & 7)) - 1,
+ 'A' + ((vendor >> 8) & 0x1f) - 1,
+ (device >> 4) & 0x0f,
+ device & 0x0f,
+ (device >> 12) & 0x0f,
+ (device >> 8) & 0x0f);
+}
+
+/* Code in this function is mainly stolen from probe_serial_pci() */
+static void __init probe_serial_pnp(void)
+{
+ int k, line;
+ struct pci_dev *dev = NULL;
+ struct pci_board *board;
+ struct serial_struct fake_state;
+ int uart_offset, base_baud, base_idx, base_irq;
+ unsigned long port;
+
+#ifdef SERIAL_DEBUG_PNP
+ printk("Entered probe_serial_pnp()\n");
+#endif
+ if (!isapnp_present()) {
+#ifdef SERIAL_DEBUG_PNP
+ printk("Leaving probe_serial_pnp() (no isapnp)\n");
+#endif
+ return;
+ }
+
+ for (board = pnp_devices; board->vendor; board++) {
+ while ((dev = isapnp_find_dev(NULL, board->vendor,
board->device, dev))) {
+
+ if (dev->prepare(dev) < 0) {
+ printk("SERIAL: PNP device '");
+ printk_pnp_dev_id(board->vendor, board->device);
+ printk("' prepare failed\n");
+ continue;
+ }
+
+ if (dev->activate(dev) < 0) {
+ printk("SERIAL: PNP device '");
+ printk_pnp_dev_id(board->vendor, board->device);
+ printk("' activate failed\n");
+ continue;
+ }
+
+ if (board->init_fn)
+ if ((board->init_fn)(dev, board, 1) != 0)
+ continue;
+#ifdef MODULE
+ if (serial_pci_board_idx >= NR_PCI_BOARDS)
+ continue;
+ serial_pci_board[serial_pci_board_idx].board = board;
+ serial_pci_board[serial_pci_board_idx].dev = dev;
+ serial_pci_board_idx++;
+#endif
+ base_idx = board->flags & SPCI_FL_BASE_MASK;
+ base_irq = PNP_IRQ_BASE(board->flags);
+ port = PCI_BASE_ADDRESS(dev, base_idx);
+
+ uart_offset = board->uart_offset;
+ if (!uart_offset)
+ uart_offset = 8;
+ base_baud = board->base_baud;
+ if (!base_baud)
+ base_baud = BASE_BAUD;
+
+ memset(&fake_state, 0, sizeof(fake_state));
+
+ for (k=0; k < board->num_ports; k++) {
+
+ if (board->flags & SPCI_FL_BASE_TABLE)
+ port = PCI_BASE_ADDRESS(dev,
base_idx++);
+ fake_state.port = port;
+ port += uart_offset;
+ fake_state.irq =
dev->irq_resource[base_irq].start;
+ if (board->flags & SPNP_FL_IRQ_TABLE)
+ base_irq++;
+ fake_state.flags = ASYNC_SKIP_TEST;
+ line = register_serial(&fake_state);
+ if (line < 0)
+ break;
+ rs_table[line].baud_base = base_baud;
+ }
+ }
+ }
+
+
+#ifdef SERIAL_DEBUG_PNP
+ printk("Leaving probe_serial_pnp() (probe finished)\n");
+#endif
+ return;
+}
+
+#endif /* ENABLE_SERIAL_PNP */
+
/*
* The serial driver boot-time initialization code!
*/
@@ -4301,6 +4437,9 @@
#ifdef ENABLE_SERIAL_PCI
probe_serial_pci();
#endif
+#ifdef ENABLE_SERIAL_PNP
+ probe_serial_pnp();
+#endif
return 0;
}

@@ -4423,12 +4562,16 @@
iounmap(rs_table[i].iomem_base);
#endif
}
-#ifdef ENABLE_SERIAL_PCI
+#if defined(ENABLE_SERIAL_PCI) || defined(ENABLE_SERIAL_PNP)
for (i=0; i < serial_pci_board_idx; i++) {
struct pci_board_inst *brd = &serial_pci_board[i];

if (brd->board->init_fn)
(brd->board->init_fn)(brd->dev, brd->board, 0);
+#ifdef ENABLE_SERIAL_PNP
+ if (brd->dev->deactivate)
+ brd->dev->deactivate(brd->dev);
+#endif
}
#endif
if (tmp_buf) {
--- /mnt/c/linux/include/linux/serialP.h Sat Nov 20 18:21:18 1999
+++ /linux/include/linux/serialP.h Mon Nov 22 13:12:49 1999
@@ -182,4 +182,13 @@
#define SPCI_FL_IOMEM 0x0008 /* Use I/O mapped memory */
#define SPCI_FL_BASE_TABLE 0x0010 /* Use base address table for UART */

+#define SPNP_FL_IRQ_TABLE 0x0020 /* Use irq table */
+#define SPNP_FL_IRQ_MASK (7 << 6)
+#define SPCI_FL_IRQBASE0 0x0000
+#define SPCI_FL_IRQBASE1 (0x0001 << 6)
+#define SPCI_FL_IRQBASE2 (0x0002 << 6)
+#define SPCI_FL_IRQBASE3 (0x0003 << 6)
+#define SPCI_FL_IRQBASE4 (0x0004 << 6)
+#define PNP_IRQ_BASE(x) ((x & SPNP_FL_IRQ_MASK) >> 6)
+
#endif /* _LINUX_SERIAL_H */

-
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/