patch-1.3.42 linux/drivers/net/hp-plus.c

Next file: linux/drivers/net/hp.c
Previous file: linux/drivers/net/e2100.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v1.3.41/linux/drivers/net/hp-plus.c linux/drivers/net/hp-plus.c
@@ -150,14 +150,21 @@
 	unsigned char checksum = 0;
 	const char *name = "HP-PC-LAN+";
 	int mem_start;
+	static unsigned version_printed = 0;
 
 	/* Check for the HP+ signature, 50 48 0x 53. */
 	if (inw(ioaddr + HP_ID) != 0x4850
 		|| (inw(ioaddr + HP_PAGING) & 0xfff0) != 0x5300)
 		return ENODEV;
 
-    if (dev == NULL)
-		dev = init_etherdev(0, sizeof(struct ei_device));
+	/* We should have a "dev" from Space.c or the static module table. */
+	if (dev == NULL) {
+		printk("hp-plus.c: Passed a NULL device.\n");
+		dev = init_etherdev(0, 0);
+	}
+
+	if (ei_debug  &&  version_printed++ == 0)
+		printk(version);
 
 	printk("%s: %s at %#3x,", dev->name, name, ioaddr);
 
@@ -181,6 +188,12 @@
 		printk(" ID %4.4x", inw(ioaddr + 12));
 	}
 
+	/* Allocate dev->priv and fill in 8390 specific dev fields. */
+	if (ethdev_init(dev)) {
+		printk ("hp-plus.c: unable to allocate memory for dev->priv.\n");
+		return -ENOMEM;
+	 }
+
 	/* Grab the region so we can find another board if something fails. */
 	request_region(ioaddr, HP_IO_EXTENT,"hp-plus");
 
@@ -200,18 +213,14 @@
 		}
 	}
 
-	printk( "%s%s", KERN_INFO, version);
-
 	/* Set the wrap registers for string I/O reads.   */
 	outw((HP_START_PG + TX_2X_PAGES) | ((HP_STOP_PG - 1) << 8), ioaddr + 14);
 
 	/* Set the base address to point to the NIC, not the "real" base! */
 	dev->base_addr = ioaddr + NIC_OFFSET;
 
-	ethdev_init(dev);
-
-    dev->open = &hpp_open;
-    dev->stop = &hpp_close;
+	dev->open = &hpp_open;
+	dev->stop = &hpp_close;
 
 	ei_status.name = name;
 	ei_status.word16 = 0;		/* Agggghhhhh! Debug time: 2 days! */
@@ -267,7 +276,9 @@
 	/* Select the operational page. */
 	outw(Perf_Page, ioaddr + HP_PAGING);
 
-    return ei_open(dev);
+	ei_open(dev);
+	MOD_INC_USE_COUNT;
+	return 0;
 }
 
 static int
@@ -276,13 +287,14 @@
 	int ioaddr = dev->base_addr - NIC_OFFSET;
 	int option_reg = inw(ioaddr + HPP_OPTION);
 
-    free_irq(dev->irq);
-    irq2dev_map[dev->irq] = NULL;
-    NS8390_init(dev, 0);
+	free_irq(dev->irq);
+	irq2dev_map[dev->irq] = NULL;
+	ei_close(dev);
 	outw((option_reg & ~EnableIRQ) | MemDisable | NICReset | ChipReset,
 		 ioaddr + HPP_OPTION);
 
-    return 0;
+	MOD_DEC_USE_COUNT;
+	return 0;
 }
 
 static void
@@ -396,39 +408,67 @@
 	return;
 }
 
+
 #ifdef MODULE
-static char devicename[9] = { 0, };
-static struct device dev_hp = {
-	devicename, /* device name is inserted by linux/drivers/net/net_init.c */
-	0, 0, 0, 0,
-	0, 0,
-	0, 0, 0, NULL, hp_plus_probe };
-
-static int io = 0x200;
-static int irq = 0;
-
-int init_module(void)
-{
-	if (io == 0)
-		printk("HP-plus: You should not use auto-probing with insmod!\n");
-	dev_hp.base_addr = io;
-	dev_hp.irq       = irq;
-	if (register_netdev(&dev_hp) != 0) {
-		printk("HP-plus: register_netdev() returned non-zero.\n");
-		return -EIO;
+#define MAX_HPP_CARDS	4	/* Max number of HPP cards per module */
+#define NAMELEN		8	/* # of chars for storing dev->name */
+static char namelist[NAMELEN * MAX_HPP_CARDS] = { 0, };
+static struct device dev_hpp[MAX_HPP_CARDS] = {
+	{
+		NULL,		/* assign a chunk of namelist[] below */
+		0, 0, 0, 0,
+		0, 0,
+		0, 0, 0, NULL, NULL
+	},
+};
+
+static int io[MAX_HPP_CARDS] = { 0, };
+static int irq[MAX_HPP_CARDS]  = { 0, };
+
+/* This is set up so that only a single autoprobe takes place per call.
+ISA device autoprobes on a running machine are not recommended. */
+int
+init_module(void)
+{
+	int this_dev, found = 0;
+
+	for (this_dev = 0; this_dev < MAX_HPP_CARDS; this_dev++) {
+		struct device *dev = &dev_hpp[this_dev];
+		dev->name = namelist+(NAMELEN*this_dev);
+		dev->irq = irq[this_dev];
+		dev->base_addr = io[this_dev];
+		dev->init = hp_plus_probe;
+		if (io[this_dev] == 0)  {
+			if (this_dev != 0) break; /* only autoprobe 1st one */
+			printk(KERN_NOTICE "hp-plus.c: Presently autoprobing (not recommended) for a single card.\n");
+		}
+		if (register_netdev(dev) != 0) {
+			printk(KERN_WARNING "hp-plus.c: No HP-Plus card found (i/o = 0x%x).\n", io[this_dev]);
+			if (found != 0) return 0;	/* Got at least one. */
+			return -ENXIO;
+		}
+		found++;
 	}
+
 	return 0;
 }
 
 void
 cleanup_module(void)
 {
-	int ioaddr = dev_hp.base_addr - NIC_OFFSET;
+	int this_dev;
 
-	unregister_netdev(&dev_hp);
-
-	/* If we don't do this, we can't re-insmod it later. */
-	release_region(ioaddr, HP_IO_EXTENT);
+	for (this_dev = 0; this_dev < MAX_HPP_CARDS; this_dev++) {
+		struct device *dev = &dev_hpp[this_dev];
+		if (dev->priv != NULL) {
+			/* NB: hpp_close() handles free_irq + irq2dev map */
+			int ioaddr = dev->base_addr - NIC_OFFSET;
+			kfree(dev->priv);
+			dev->priv = NULL;
+			release_region(ioaddr, HP_IO_EXTENT);
+			unregister_netdev(dev);
+		}
+	}
 }
 #endif /* MODULE */
 

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov with Sam's (original) version
of this