patch-1.3.42 linux/drivers/net/e2100.c
Next file: linux/drivers/net/hp-plus.c
Previous file: linux/drivers/net/ac3200.c
Back to the patch index
Back to the overall index
- Lines: 188
- Date:
Tue Nov 14 07:48:52 1995
- Orig file:
v1.3.41/linux/drivers/net/e2100.c
- Orig date:
Thu Nov 9 11:23:49 1995
diff -u --recursive --new-file v1.3.41/linux/drivers/net/e2100.c linux/drivers/net/e2100.c
@@ -139,6 +139,7 @@
{
int i, status;
unsigned char *station_addr = dev->dev_addr;
+ static unsigned version_printed = 0;
/* First check the station address for the Ctron prefix. */
if (inb(ioaddr + E21_SAPROM + 0) != 0x00
@@ -160,6 +161,15 @@
inb(ioaddr + E21_MEDIA); /* Point to media selection. */
outb(0, ioaddr + E21_ASIC); /* and disable the secondary interface. */
+ if (ei_debug && version_printed++ == 0)
+ printk(version);
+
+ /* We should have a "dev" from Space.c or the static module table. */
+ if (dev == NULL) {
+ printk("e2100.c: Passed a NULL device.\n");
+ dev = init_etherdev(0, 0);
+ }
+
printk("%s: E21** at %#3x,", dev->name, ioaddr);
for (i = 0; i < 6; i++)
printk(" %02X", station_addr[i]);
@@ -178,14 +188,18 @@
} else if (dev->irq == 2) /* Fixup luser bogosity: IRQ2 is really IRQ9 */
dev->irq = 9;
+ /* Allocate dev->priv and fill in 8390 specific dev fields. */
+ if (ethdev_init(dev)) {
+ printk (" unable to get memory for dev->priv.\n");
+ return -ENOMEM;
+ }
+
/* Grab the region so we can find a different board if IRQ select fails. */
request_region(ioaddr, E21_IO_EXTENT, "e2100");
/* The 8390 is at the base address. */
dev->base_addr = ioaddr;
- ethdev_init(dev);
-
ei_status.name = "E2100";
ei_status.word16 = 1;
ei_status.tx_start_page = E21_TX_START_PG;
@@ -223,9 +237,6 @@
printk(", IRQ %d, %s media, memory @ %#lx.\n", dev->irq,
dev->if_port ? "secondary" : "primary", dev->mem_start);
- if (ei_debug > 0)
- printk(version);
-
ei_status.reset_8390 = &e21_reset_8390;
ei_status.block_input = &e21_block_input;
ei_status.block_output = &e21_block_output;
@@ -241,7 +252,6 @@
e21_open(struct device *dev)
{
short ioaddr = dev->base_addr;
- int rc;
if (request_irq(dev->irq, ei_interrupt, 0, "e2100")) {
return EBUSY;
@@ -257,8 +267,7 @@
inb(ioaddr + E21_MEM_BASE);
outb(0, ioaddr + E21_ASIC + ((dev->mem_start >> 17) & 7));
- rc = ei_open(dev);
- if (rc != 0) return rc;
+ ei_open(dev);
MOD_INC_USE_COUNT;
return 0;
}
@@ -338,8 +347,8 @@
if (ei_debug > 1)
printk("%s: Shutting down ethercard.\n", dev->name);
- free_irq(dev->irq);
- dev->irq = ei_status.saved_irq;
+ free_irq(dev->irq);
+ dev->irq = ei_status.saved_irq;
/* Shut off the interrupt line and secondary interface. */
inb(ioaddr + E21_IRQ_LOW);
@@ -347,9 +356,9 @@
inb(ioaddr + E21_IRQ_HIGH); /* High IRQ bit, and if_port. */
outb(0, ioaddr + E21_ASIC);
- irq2dev_map[dev->irq] = NULL;
+ irq2dev_map[dev->irq] = NULL;
- NS8390_init(dev, 0);
+ ei_close(dev);
/* Double-check that the memory has been turned off, because really
really bad things happen if it isn't. */
@@ -365,37 +374,70 @@
{"e21", e21_probe1, E21_IO_EXTENT, e21_probe_list};
#endif
+
#ifdef MODULE
-static char devicename[9] = { 0, };
-static struct device dev_e2100 = {
- devicename, /* device name is inserted by linux/drivers/net/net_init.c */
- 0, 0, 0, 0,
- 0, 0,
- 0, 0, 0, NULL, e2100_probe };
-
-static int io = 0x300;
-static int irq = 0;
-
-int init_module(void)
+#define MAX_E21_CARDS 4 /* Max number of E21 cards per module */
+#define NAMELEN 8 /* # of chars for storing dev->name */
+static char namelist[NAMELEN * MAX_E21_CARDS] = { 0, };
+static struct device dev_e21[MAX_E21_CARDS] = {
+ {
+ NULL, /* assign a chunk of namelist[] below */
+ 0, 0, 0, 0,
+ 0, 0,
+ 0, 0, 0, NULL, NULL
+ },
+};
+
+static int io[MAX_E21_CARDS] = { 0, };
+static int irq[MAX_E21_CARDS] = { 0, };
+static int mem[MAX_E21_CARDS] = { 0, };
+static int xcvr[MAX_E21_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)
{
- if (io == 0)
- printk("e2100: You should not use auto-probing with insmod!\n");
- dev_e2100.base_addr = io;
- dev_e2100.irq = irq;
- if (register_netdev(&dev_e2100) != 0) {
- printk("e2100: register_netdev() returned non-zero.\n");
- return -EIO;
+ int this_dev, found = 0;
+
+ for (this_dev = 0; this_dev < MAX_E21_CARDS; this_dev++) {
+ struct device *dev = &dev_e21[this_dev];
+ dev->name = namelist+(NAMELEN*this_dev);
+ dev->irq = irq[this_dev];
+ dev->base_addr = io[this_dev];
+ dev->mem_start = mem[this_dev];
+ dev->mem_end = xcvr[this_dev]; /* low 4bits = xcvr sel. */
+ dev->init = e2100_probe;
+ if (io[this_dev] == 0) {
+ if (this_dev != 0) break; /* only autoprobe 1st one */
+ printk(KERN_NOTICE "e2100.c: Presently autoprobing (not recommended) for a single card.\n");
+ }
+ if (register_netdev(dev) != 0) {
+ printk(KERN_WARNING "e2100.c: No E2100 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)
{
- unregister_netdev(&dev_e2100);
+ int this_dev;
- /* If we don't do this, we can't re-insmod it later. */
- release_region(dev_e2100.base_addr, E21_IO_EXTENT);
+ for (this_dev = 0; this_dev < MAX_E21_CARDS; this_dev++) {
+ struct device *dev = &dev_e21[this_dev];
+ if (dev->priv != NULL) {
+ /* NB: e21_close() handles free_irq + irq2dev map */
+ kfree(dev->priv);
+ dev->priv = NULL;
+ release_region(dev->base_addr, E21_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