patch-1.3.42 linux/drivers/net/3c503.c
Next file: linux/drivers/net/8390.c
Previous file: linux/drivers/char/cyclades.c
Back to the patch index
Back to the overall index
- Lines: 206
- Date:
Tue Nov 14 07:48:52 1995
- Orig file:
v1.3.41/linux/drivers/net/3c503.c
- Orig date:
Thu Nov 9 11:23:49 1995
diff -u --recursive --new-file v1.3.41/linux/drivers/net/3c503.c linux/drivers/net/3c503.c
@@ -25,6 +25,7 @@
Changelog:
Paul Gortmaker : add support for the 2nd 8kB of RAM on 16 bit cards.
+ Paul Gortmaker : multiple card support for module users.
*/
@@ -182,16 +183,24 @@
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("3c503.c: Passed a NULL device.\n");
+ dev = init_etherdev(0, 0);
+ }
if (ei_debug && version_printed++ == 0)
printk(version);
dev->base_addr = ioaddr;
- ethdev_init(dev);
- printk("%s: 3c503 at i/o base %#3x, node address", dev->name, ioaddr);
+ /* Allocate dev->priv and fill in 8390 specific dev fields. */
+ if (ethdev_init(dev)) {
+ printk ("3c503: unable to allocate memory for dev->priv.\n");
+ return -ENOMEM;
+ }
+
+ printk("%s: 3c503 at i/o base %#3x, node ", dev->name, ioaddr);
/* Retrieve and print the ethernet address. */
for (i = 0; i < 6; i++)
@@ -220,6 +229,7 @@
#else
ei_status.interface_num = dev->mem_end & 0xf;
#endif
+ printk(", using %sternal xcvr.\n", ei_status.interface_num == 0 ? "in" : "ex");
if ((membase_reg & 0xf0) == 0) {
dev->mem_start = 0;
@@ -241,7 +251,7 @@
writel(test_val, mem_base + i);
if (readl(mem_base) != 0xba5eba5e
|| readl(mem_base + i) != test_val) {
- printk(" memory failure or memory address conflict.\n");
+ printk("3c503.c: memory failure or memory address conflict.\n");
dev->mem_start = 0;
ei_status.name = "3c503-PIO";
break;
@@ -292,7 +302,7 @@
if (dev->irq == 2)
dev->irq = 9;
else if (dev->irq > 5 && dev->irq != 9) {
- printk("\n3c503: configured interrupt %d invalid, will use autoIRQ.\n",
+ printk("3c503: configured interrupt %d invalid, will use autoIRQ.\n",
dev->irq);
dev->irq = 0;
}
@@ -304,7 +314,7 @@
dev->stop = &el2_close;
if (dev->mem_start)
- printk("\n%s: %s - %dkB RAM, 8kB shared mem window at %#6lx-%#6lx.\n",
+ printk("%s: %s - %dkB RAM, 8kB shared mem window at %#6lx-%#6lx.\n",
dev->name, ei_status.name, (wordlength+1)<<3,
dev->mem_start, dev->mem_end-1);
@@ -344,8 +354,11 @@
return -EAGAIN;
}
}
+
el2_init_card(dev);
- return ei_open(dev);
+ ei_open(dev);
+ MOD_INC_USE_COUNT;
+ return 0;
}
static int
@@ -356,9 +369,8 @@
irq2dev_map[dev->irq] = NULL;
outb(EGACFR_IRQOFF, E33G_GACFR); /* disable interrupts. */
- NS8390_init(dev, 0);
- dev->start = 0;
-
+ ei_close(dev);
+ MOD_DEC_USE_COUNT;
return 0;
}
@@ -526,56 +538,69 @@
}
outb_p(ei_status.interface_num == 0 ? ECNTRL_THIN : ECNTRL_AUI, E33G_CNTRL);
}
+
+
#ifdef MODULE
-static struct device el2_drv =
-{"3c503", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, el2_probe };
-
-static struct device el2pio_drv =
-{"3c503pio", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, el2_pio_probe };
-
-static int io = 0x300;
-static int irq = 0;
-
-static int no_pio = 1;
-int init_module(void)
-{
- int rc1, rc2;
- el2_drv.base_addr = io;
- el2_drv.irq = irq;
- el2pio_drv.base_addr = io;
- el2pio_drv.irq = irq;
-
- if (io == 0)
- printk("3c503: You should not use auto-probing with insmod!\n");
-
- rc2 = 0;
- no_pio = 1;
- rc1 = register_netdev(&el2_drv);
- if (rc1 != 0) {
- rc2 = register_netdev(&el2pio_drv);
- no_pio = 0;
+#define MAX_EL2_CARDS 4 /* Max number of EL2 cards per module */
+#define NAMELEN 8 /* # of chars for storing dev->name */
+static char namelist[NAMELEN * MAX_EL2_CARDS] = { 0, };
+static struct device dev_el2[MAX_EL2_CARDS] = {
+ {
+ NULL, /* assign a chunk of namelist[] below */
+ 0, 0, 0, 0,
+ 0, 0,
+ 0, 0, 0, NULL, NULL
+ },
+};
+
+static int io[MAX_EL2_CARDS] = { 0, };
+static int irq[MAX_EL2_CARDS] = { 0, };
+static int xcvr[MAX_EL2_CARDS] = { 0, }; /* choose int. or ext. xcvr */
+
+/* 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_EL2_CARDS; this_dev++) {
+ struct device *dev = &dev_el2[this_dev];
+ dev->name = namelist+(NAMELEN*this_dev);
+ dev->irq = irq[this_dev];
+ dev->base_addr = io[this_dev];
+ dev->mem_end = xcvr[this_dev]; /* low 4bits = xcvr sel. */
+ dev->init = el2_probe;
+ if (io[this_dev] == 0) {
+ if (this_dev != 0) break; /* only autoprobe 1st one */
+ printk(KERN_NOTICE "3c503.c: Presently autoprobing (not recommended) for a single card.\n");
+ }
+ if (register_netdev(dev) != 0) {
+ printk(KERN_WARNING "3c503.c: No 3c503 card found (i/o = 0x%x).\n", io[this_dev]);
+ if (found != 0) return 0; /* Got at least one. */
+ return -ENXIO;
+ }
+ found++;
}
- if (rc1 != 0 && rc2 != 0)
- return -EIO;
return 0;
}
void
cleanup_module(void)
{
- int ioaddr;
+ int this_dev;
- if (no_pio) {
- ioaddr = el2_drv.base_addr;
- unregister_netdev(&el2_drv);
- } else {
- ioaddr = el2pio_drv.base_addr;
- unregister_netdev(&el2pio_drv);
+ for (this_dev = 0; this_dev < MAX_EL2_CARDS; this_dev++) {
+ struct device *dev = &dev_el2[this_dev];
+ if (dev->priv != NULL) {
+ /* NB: el2_close() handles free_irq + irq2dev map */
+ kfree(dev->priv);
+ dev->priv = NULL;
+ release_region(dev->base_addr, EL2_IO_EXTENT);
+ unregister_netdev(dev);
+ }
}
-
- /* If we don't do this, we can't re-insmod it later. */
- release_region(ioaddr, EL2_IO_EXTENT);
}
#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