Commit 4eb1b94b authored by Stephen Hemminger's avatar Stephen Hemminger

[PATCH] (1/42) ewrk3

Convert ewrk3 to dynamic allocation
	* get rid of private device allocation method
	* fix deeply nested function
parent 5d40d90f
...@@ -56,7 +56,7 @@ extern int at1700_probe(struct net_device *); ...@@ -56,7 +56,7 @@ extern int at1700_probe(struct net_device *);
extern int fmv18x_probe(struct net_device *); extern int fmv18x_probe(struct net_device *);
extern int eth16i_probe(struct net_device *); extern int eth16i_probe(struct net_device *);
extern struct net_device *i82596_probe(int unit); extern struct net_device *i82596_probe(int unit);
extern int ewrk3_probe(struct net_device *); extern struct net_device *ewrk3_probe(int unit);
extern struct net_device *el1_probe(int unit); extern struct net_device *el1_probe(int unit);
extern struct net_device *wavelan_probe(int unit); extern struct net_device *wavelan_probe(int unit);
extern struct net_device *arlan_probe(int unit); extern struct net_device *arlan_probe(int unit);
...@@ -255,14 +255,14 @@ static struct devprobe isa_probes[] __initdata = { ...@@ -255,14 +255,14 @@ static struct devprobe isa_probes[] __initdata = {
#endif #endif
#ifdef CONFIG_EEXPRESS_PRO /* Intel EtherExpress Pro/10 */ #ifdef CONFIG_EEXPRESS_PRO /* Intel EtherExpress Pro/10 */
{eepro_probe, 0}, {eepro_probe, 0},
#endif
#ifdef CONFIG_EWRK3 /* DEC EtherWORKS 3 */
{ewrk3_probe, 0},
#endif #endif
{NULL, 0}, {NULL, 0},
}; };
static struct devprobe2 isa_probes2[] __initdata = { static struct devprobe2 isa_probes2[] __initdata = {
#ifdef CONFIG_EWRK3 /* DEC EtherWORKS 3 */
{ewrk3_probe, 0},
#endif
#if defined(CONFIG_APRICOT) || defined(CONFIG_MVME16x_NET) || defined(CONFIG_BVME6000_NET) /* Intel I82596 */ #if defined(CONFIG_APRICOT) || defined(CONFIG_MVME16x_NET) || defined(CONFIG_BVME6000_NET) /* Intel I82596 */
{i82596_probe, 0}, {i82596_probe, 0},
#endif #endif
......
...@@ -324,25 +324,14 @@ static int Read_EEPROM(u_long iobase, u_char eaddr); ...@@ -324,25 +324,14 @@ static int Read_EEPROM(u_long iobase, u_char eaddr);
static int Write_EEPROM(short data, u_long iobase, u_char eaddr); static int Write_EEPROM(short data, u_long iobase, u_char eaddr);
static u_char get_hw_addr(struct net_device *dev, u_char * eeprom_image, char chipType); static u_char get_hw_addr(struct net_device *dev, u_char * eeprom_image, char chipType);
static void isa_probe(struct net_device *dev, u_long iobase); static int ewrk3_probe1(struct net_device *dev, u_long iobase, int irq);
static void eisa_probe(struct net_device *dev, u_long iobase); static int isa_probe(struct net_device *dev, u_long iobase);
static struct net_device *alloc_device(struct net_device *dev, u_long iobase); static int eisa_probe(struct net_device *dev, u_long iobase);
static int ewrk3_dev_index(char *s);
static struct net_device *insert_device(struct net_device *dev, u_long iobase, int (*init) (struct net_device *));
static u_char irq[MAX_NUM_EWRK3S+1] = {5, 0, 10, 3, 11, 9, 15, 12};
#ifdef MODULE
static int autoprobed = 1, loading_module = 1;
#else
static u_char irq[] =
{5, 0, 10, 3, 11, 9, 15, 12};
static int autoprobed, loading_module;
#endif /* MODULE */
static char name[EWRK3_STRLEN + 1]; static char name[EWRK3_STRLEN + 1];
static int num_ewrk3s, num_eth; static int num_ewrks3s;
/* /*
** Miscellaneous defines... ** Miscellaneous defines...
...@@ -352,38 +341,50 @@ static int num_ewrk3s, num_eth; ...@@ -352,38 +341,50 @@ static int num_ewrk3s, num_eth;
mdelay(1);\ mdelay(1);\
} }
int __init ewrk3_probe(struct net_device *dev) struct net_device * __init ewrk3_probe(int unit)
{ {
int tmp = num_ewrk3s, status = -ENODEV; struct net_device *dev = alloc_etherdev(sizeof(struct ewrk3_private));
u_long iobase = dev->base_addr; int err;
if (!dev)
return ERR_PTR(-ENOMEM);
if (unit >= 0) {
sprintf(dev->name, "eth%d", unit);
netdev_boot_setup_check(dev);
}
SET_MODULE_OWNER(dev); SET_MODULE_OWNER(dev);
if ((iobase == 0) && loading_module) { err = ewrk3_probe1(dev, dev->base_addr, dev->irq);
printk("Autoprobing is not supported when loading a module based driver.\n"); if (err)
status = -EIO; goto out;
} else { /* First probe for the Ethernet */ return dev;
/* Address PROM pattern */ out:
isa_probe(dev, iobase); free_netdev(dev);
eisa_probe(dev, iobase); return ERR_PTR(err);
if ((tmp == num_ewrk3s) && (iobase != 0) && loading_module) { }
printk("%s: ewrk3_probe() cannot find device at 0x%04lx.\n", dev->name,
iobase);
}
/*
** Walk the device list to check that at least one device
** initialised OK
*/
for (; (dev->priv == NULL) && (dev->next != NULL); dev = dev->next);
if (dev->priv) static int __init ewrk3_probe1(struct net_device *dev, u_long iobase, int irq)
status = 0; {
if (iobase == 0) int err;
autoprobed = 1;
}
return status; dev->base_addr = iobase;
dev->irq = irq;
/* Address PROM pattern */
err = isa_probe(dev, iobase);
if (err != 0)
err = eisa_probe(dev, iobase);
if (err)
return err;
err = register_netdev(dev);
if (err)
release_region(dev->base_addr, EWRK3_TOTAL_SIZE);
return err;
} }
static int __init static int __init
...@@ -396,8 +397,8 @@ ewrk3_hw_init(struct net_device *dev, u_long iobase) ...@@ -396,8 +397,8 @@ ewrk3_hw_init(struct net_device *dev, u_long iobase)
u_char eeprom_image[EEPROM_MAX], chksum, eisa_cr = 0; u_char eeprom_image[EEPROM_MAX], chksum, eisa_cr = 0;
/* /*
** Stop the EWRK3. Enable the DBR ROM. Disable interrupts and remote boot. ** Stop the EWRK3. Enable the DBR ROM. Disable interrupts and remote boot.
** This also disables the EISA_ENABLE bit in the EISA Control Register. ** This also disables the EISA_ENABLE bit in the EISA Control Register.
*/ */
if (iobase > 0x400) if (iobase > 0x400)
eisa_cr = inb(EISA_CR); eisa_cr = inb(EISA_CR);
...@@ -409,232 +410,210 @@ ewrk3_hw_init(struct net_device *dev, u_long iobase) ...@@ -409,232 +410,210 @@ ewrk3_hw_init(struct net_device *dev, u_long iobase)
icr &= 0x70; icr &= 0x70;
outb(icr, EWRK3_ICR); /* Disable all the IRQs */ outb(icr, EWRK3_ICR); /* Disable all the IRQs */
if (nicsr == (CSR_TXD | CSR_RXD)) { if (nicsr == (CSR_TXD | CSR_RXD))
return -ENXIO;
/* Check that the EEPROM is alive and well and not living on Pluto... */
for (chksum = 0, i = 0; i < EEPROM_MAX; i += 2) {
union {
short val;
char c[2];
} tmp;
tmp.val = (short) Read_EEPROM(iobase, (i >> 1)); /* Check that the EEPROM is alive and well and not living on Pluto... */
eeprom_image[i] = tmp.c[0]; for (chksum = 0, i = 0; i < EEPROM_MAX; i += 2) {
eeprom_image[i + 1] = tmp.c[1]; union {
chksum += eeprom_image[i] + eeprom_image[i + 1]; short val;
} char c[2];
} tmp;
if (chksum != 0) { /* Bad EEPROM Data! */ tmp.val = (short) Read_EEPROM(iobase, (i >> 1));
printk("%s: Device has a bad on-board EEPROM.\n", dev->name); eeprom_image[i] = tmp.c[0];
status = -ENXIO; eeprom_image[i + 1] = tmp.c[1];
} else { chksum += eeprom_image[i] + eeprom_image[i + 1];
EthwrkSignature(name, eeprom_image); }
if (*name != '\0') { /* found a EWRK3 device */
dev->base_addr = iobase;
if (iobase > 0x400) { if (chksum != 0) { /* Bad EEPROM Data! */
outb(eisa_cr, EISA_CR); /* Rewrite the EISA CR */ printk("%s: Device has a bad on-board EEPROM.\n", dev->name);
} return -ENXIO;
lemac = eeprom_image[EEPROM_CHIPVER]; }
cmr = inb(EWRK3_CMR);
EthwrkSignature(name, eeprom_image);
if (((lemac == LeMAC) && ((cmr & CMR_NO_EEPROM) != CMR_NO_EEPROM)) || if (*name == '\0')
((lemac == LeMAC2) && !(cmr & CMR_HS))) { return -ENXIO;
printk("%s: %s at %#4lx", dev->name, name, iobase);
hard_strapped = 1; dev->base_addr = iobase;
} else if ((iobase & 0x0fff) == EWRK3_EISA_IO_PORTS) {
/* EISA slot address */ if (iobase > 0x400) {
printk("%s: %s at %#4lx (EISA slot %ld)", outb(eisa_cr, EISA_CR); /* Rewrite the EISA CR */
dev->name, name, iobase, ((iobase >> 12) & 0x0f)); }
} else { /* ISA port address */ lemac = eeprom_image[EEPROM_CHIPVER];
printk("%s: %s at %#4lx", dev->name, name, iobase); cmr = inb(EWRK3_CMR);
}
if (((lemac == LeMAC) && ((cmr & CMR_NO_EEPROM) != CMR_NO_EEPROM)) ||
((lemac == LeMAC2) && !(cmr & CMR_HS))) {
printk("%s: %s at %#4lx", dev->name, name, iobase);
hard_strapped = 1;
} else if ((iobase & 0x0fff) == EWRK3_EISA_IO_PORTS) {
/* EISA slot address */
printk("%s: %s at %#4lx (EISA slot %ld)",
dev->name, name, iobase, ((iobase >> 12) & 0x0f));
} else { /* ISA port address */
printk("%s: %s at %#4lx", dev->name, name, iobase);
}
if (!status) { printk(", h/w address ");
printk(", h/w address "); if (lemac != LeMAC2)
if (lemac != LeMAC2) DevicePresent(iobase); /* need after EWRK3_INIT */
DevicePresent(iobase); /* need after EWRK3_INIT */ status = get_hw_addr(dev, eeprom_image, lemac);
status = get_hw_addr(dev, eeprom_image, lemac); for (i = 0; i < ETH_ALEN - 1; i++) { /* get the ethernet addr. */
for (i = 0; i < ETH_ALEN - 1; i++) { /* get the ethernet addr. */ printk("%2.2x:", dev->dev_addr[i]);
printk("%2.2x:", dev->dev_addr[i]); }
} printk("%2.2x,\n", dev->dev_addr[i]);
printk("%2.2x,\n", dev->dev_addr[i]);
if (status) {
printk(" which has an EEPROM CRC error.\n");
return -ENXIO;
}
if (status) { if (lemac == LeMAC2) { /* Special LeMAC2 CMR things */
printk(" which has an EEPROM CRC error.\n"); cmr &= ~(CMR_RA | CMR_WB | CMR_LINK | CMR_POLARITY | CMR_0WS);
status = -ENXIO; if (eeprom_image[EEPROM_MISC0] & READ_AHEAD)
} else { cmr |= CMR_RA;
if (lemac == LeMAC2) { /* Special LeMAC2 CMR things */ if (eeprom_image[EEPROM_MISC0] & WRITE_BEHIND)
cmr &= ~(CMR_RA | CMR_WB | CMR_LINK | CMR_POLARITY | CMR_0WS); cmr |= CMR_WB;
if (eeprom_image[EEPROM_MISC0] & READ_AHEAD) if (eeprom_image[EEPROM_NETMAN0] & NETMAN_POL)
cmr |= CMR_RA; cmr |= CMR_POLARITY;
if (eeprom_image[EEPROM_MISC0] & WRITE_BEHIND) if (eeprom_image[EEPROM_NETMAN0] & NETMAN_LINK)
cmr |= CMR_WB; cmr |= CMR_LINK;
if (eeprom_image[EEPROM_NETMAN0] & NETMAN_POL) if (eeprom_image[EEPROM_MISC0] & _0WS_ENA)
cmr |= CMR_POLARITY; cmr |= CMR_0WS;
if (eeprom_image[EEPROM_NETMAN0] & NETMAN_LINK) }
cmr |= CMR_LINK; if (eeprom_image[EEPROM_SETUP] & SETUP_DRAM)
if (eeprom_image[EEPROM_MISC0] & _0WS_ENA) cmr |= CMR_DRAM;
cmr |= CMR_0WS; outb(cmr, EWRK3_CMR);
}
if (eeprom_image[EEPROM_SETUP] & SETUP_DRAM) cr = inb(EWRK3_CR); /* Set up the Control Register */
cmr |= CMR_DRAM; cr |= eeprom_image[EEPROM_SETUP] & SETUP_APD;
outb(cmr, EWRK3_CMR); if (cr & SETUP_APD)
cr |= eeprom_image[EEPROM_SETUP] & SETUP_PS;
cr = inb(EWRK3_CR); /* Set up the Control Register */ cr |= eeprom_image[EEPROM_MISC0] & FAST_BUS;
cr |= eeprom_image[EEPROM_SETUP] & SETUP_APD; cr |= eeprom_image[EEPROM_MISC0] & ENA_16;
if (cr & SETUP_APD) outb(cr, EWRK3_CR);
cr |= eeprom_image[EEPROM_SETUP] & SETUP_PS;
cr |= eeprom_image[EEPROM_MISC0] & FAST_BUS;
cr |= eeprom_image[EEPROM_MISC0] & ENA_16;
outb(cr, EWRK3_CR);
/* /*
** Determine the base address and window length for the EWRK3 ** Determine the base address and window length for the EWRK3
** RAM from the memory base register. ** RAM from the memory base register.
*/ */
mem_start = inb(EWRK3_MBR); mem_start = inb(EWRK3_MBR);
shmem_length = 0; shmem_length = 0;
if (mem_start != 0) { if (mem_start != 0) {
if ((mem_start >= 0x0a) && (mem_start <= 0x0f)) { if ((mem_start >= 0x0a) && (mem_start <= 0x0f)) {
mem_start *= SHMEM_64K; mem_start *= SHMEM_64K;
shmem_length = SHMEM_64K; shmem_length = SHMEM_64K;
} else if ((mem_start >= 0x14) && (mem_start <= 0x1f)) { } else if ((mem_start >= 0x14) && (mem_start <= 0x1f)) {
mem_start *= SHMEM_32K; mem_start *= SHMEM_32K;
shmem_length = SHMEM_32K; shmem_length = SHMEM_32K;
} else if ((mem_start >= 0x40) && (mem_start <= 0xff)) { } else if ((mem_start >= 0x40) && (mem_start <= 0xff)) {
mem_start = mem_start * SHMEM_2K + 0x80000; mem_start = mem_start * SHMEM_2K + 0x80000;
shmem_length = SHMEM_2K; shmem_length = SHMEM_2K;
} else { } else {
status = -ENXIO; return -ENXIO;
} }
} }
/* /*
** See the top of this source code for comments about ** See the top of this source code for comments about
** uncommenting this line. ** uncommenting this line.
*/ */
/* FORCE_2K_MODE; */ /* FORCE_2K_MODE; */
if (hard_strapped) {
printk(" is hard strapped.\n");
} else if (mem_start) {
printk(" has a %dk RAM window", (int) (shmem_length >> 10));
printk(" at 0x%.5lx", mem_start);
} else {
printk(" is in I/O only mode");
}
if (!status) { lp = (struct ewrk3_private *) dev->priv;
if (hard_strapped) { lp->shmem_base = mem_start;
printk(" is hard strapped.\n"); lp->shmem_length = shmem_length;
} else if (mem_start) { lp->lemac = lemac;
printk(" has a %dk RAM window", (int) (shmem_length >> 10)); lp->hard_strapped = hard_strapped;
printk(" at 0x%.5lx", mem_start); lp->led_mask = CR_LED;
} else { spin_lock_init(&lp->hw_lock);
printk(" is in I/O only mode");
} lp->mPage = 64;
if (cmr & CMR_DRAM)
/* private area & initialise */ lp->mPage <<= 1; /* 2 DRAMS on module */
dev->priv = (void *) kmalloc(sizeof(struct ewrk3_private),
GFP_KERNEL); sprintf(lp->adapter_name, "%s (%s)", name, dev->name);
if (dev->priv == NULL) {
return -ENOMEM; lp->irq_mask = ICR_TNEM | ICR_TXDM | ICR_RNEM | ICR_RXDM;
}
lp = (struct ewrk3_private *) dev->priv; if (!hard_strapped) {
memset(dev->priv, 0, sizeof(struct ewrk3_private)); /*
lp->shmem_base = mem_start; ** Enable EWRK3 board interrupts for autoprobing
lp->shmem_length = shmem_length; */
lp->lemac = lemac; icr |= ICR_IE; /* Enable interrupts */
lp->hard_strapped = hard_strapped; outb(icr, EWRK3_ICR);
lp->led_mask = CR_LED;
spin_lock_init(&lp->hw_lock); /* The DMA channel may be passed in on this parameter. */
dev->dma = 0;
lp->mPage = 64;
if (cmr & CMR_DRAM) /* To auto-IRQ we enable the initialization-done and DMA err,
lp->mPage <<= 1; /* 2 DRAMS on module */ interrupts. For now we will always get a DMA error. */
if (dev->irq < 2) {
sprintf(lp->adapter_name, "%s (%s)", name, dev->name);
request_region(iobase, EWRK3_TOTAL_SIZE, lp->adapter_name);
lp->irq_mask = ICR_TNEM | ICR_TXDM | ICR_RNEM | ICR_RXDM;
if (!hard_strapped) {
/*
** Enable EWRK3 board interrupts for autoprobing
*/
icr |= ICR_IE; /* Enable interrupts */
outb(icr, EWRK3_ICR);
/* The DMA channel may be passed in on this parameter. */
dev->dma = 0;
/* To auto-IRQ we enable the initialization-done and DMA err,
interrupts. For now we will always get a DMA error. */
if (dev->irq < 2) {
#ifndef MODULE #ifndef MODULE
u_char irqnum; u_char irqnum;
unsigned long irq_mask; unsigned long irq_mask;
irq_mask = probe_irq_on(); irq_mask = probe_irq_on();
/* /*
** Trigger a TNE interrupt. ** Trigger a TNE interrupt.
*/ */
icr |= ICR_TNEM; icr |= ICR_TNEM;
outb(1, EWRK3_TDQ); /* Write to the TX done queue */ outb(1, EWRK3_TDQ); /* Write to the TX done queue */
outb(icr, EWRK3_ICR); /* Unmask the TXD interrupt */ outb(icr, EWRK3_ICR); /* Unmask the TXD interrupt */
irqnum = irq[((icr & IRQ_SEL) >> 4)]; irqnum = irq[((icr & IRQ_SEL) >> 4)];
mdelay(20); mdelay(20);
dev->irq = probe_irq_off(irq_mask); dev->irq = probe_irq_off(irq_mask);
if ((dev->irq) && (irqnum == dev->irq)) { if ((dev->irq) && (irqnum == dev->irq)) {
printk(" and uses IRQ%d.\n", dev->irq); printk(" and uses IRQ%d.\n", dev->irq);
} else {
if (!dev->irq) {
printk(" and failed to detect IRQ line.\n");
} else if ((irqnum == 1) && (lemac == LeMAC2)) {
printk(" and an illegal IRQ line detected.\n");
} else {
printk(", but incorrect IRQ line detected.\n");
}
status = -ENXIO;
}
DISABLE_IRQs; /* Mask all interrupts */
#endif /* MODULE */
} else {
printk(" and requires IRQ%d.\n", dev->irq);
}
}
if (status)
release_region(iobase, EWRK3_TOTAL_SIZE);
} else {
status = -ENXIO;
}
}
}
} else { } else {
status = -ENXIO; if (!dev->irq) {
printk(" and failed to detect IRQ line.\n");
} else if ((irqnum == 1) && (lemac == LeMAC2)) {
printk(" and an illegal IRQ line detected.\n");
} else {
printk(", but incorrect IRQ line detected.\n");
}
return -ENXIO;
} }
}
if (!status) { DISABLE_IRQs; /* Mask all interrupts */
if (ewrk3_debug > 1) {
printk(version); #endif /* MODULE */
} } else {
/* The EWRK3-specific entries in the device structure. */ printk(" and requires IRQ%d.\n", dev->irq);
dev->open = ewrk3_open;
dev->hard_start_xmit = ewrk3_queue_pkt;
dev->stop = ewrk3_close;
dev->get_stats = ewrk3_get_stats;
dev->set_multicast_list = set_multicast_list;
dev->do_ioctl = ewrk3_ioctl;
dev->tx_timeout = ewrk3_timeout;
dev->watchdog_timeo = QUEUE_PKT_TIMEOUT;
dev->mem_start = 0;
/* Fill in the generic field of the device structure. */
ether_setup(dev);
} }
} else {
status = -ENXIO;
} }
return status;
if (ewrk3_debug > 1) {
printk(version);
}
/* The EWRK3-specific entries in the device structure. */
dev->open = ewrk3_open;
dev->hard_start_xmit = ewrk3_queue_pkt;
dev->stop = ewrk3_close;
dev->get_stats = ewrk3_get_stats;
dev->set_multicast_list = set_multicast_list;
dev->do_ioctl = ewrk3_ioctl;
dev->tx_timeout = ewrk3_timeout;
dev->watchdog_timeo = QUEUE_PKT_TIMEOUT;
dev->mem_start = 0;
return 0;
} }
...@@ -1269,15 +1248,15 @@ static void SetMulticastFilter(struct net_device *dev) ...@@ -1269,15 +1248,15 @@ static void SetMulticastFilter(struct net_device *dev)
/* /*
** ISA bus I/O device probe ** ISA bus I/O device probe
*/ */
static void __init isa_probe(struct net_device *dev, u_long ioaddr) static int __init isa_probe(struct net_device *dev, u_long ioaddr)
{ {
int i = num_ewrk3s, maxSlots; int i = num_ewrks3s, maxSlots;
int ret = -ENODEV;
u_long iobase; u_long iobase;
if (!ioaddr && autoprobed)
return; /* Been here before ! */
if (ioaddr >= 0x400) if (ioaddr >= 0x400)
return; /* Not ISA */ goto out;
if (ioaddr == 0) { /* Autoprobing */ if (ioaddr == 0) { /* Autoprobing */
iobase = EWRK3_IO_BASE; /* Get the first slot address */ iobase = EWRK3_IO_BASE; /* Get the first slot address */
...@@ -1287,38 +1266,37 @@ static void __init isa_probe(struct net_device *dev, u_long ioaddr) ...@@ -1287,38 +1266,37 @@ static void __init isa_probe(struct net_device *dev, u_long ioaddr)
maxSlots = i + 1; maxSlots = i + 1;
} }
for (; (i < maxSlots) && (dev != NULL); iobase += EWRK3_IOP_INC, i++) { for (; (i < maxSlots) && (dev != NULL);
if (!check_region(iobase, EWRK3_TOTAL_SIZE)) { iobase += EWRK3_IOP_INC, i++)
{
if (request_region(iobase, EWRK3_TOTAL_SIZE, dev->name)) {
if (DevicePresent(iobase) == 0) { if (DevicePresent(iobase) == 0) {
if ((dev = alloc_device(dev, iobase)) != NULL) { int irq = dev->irq;
if (ewrk3_hw_init(dev, iobase) == 0) { ret = ewrk3_hw_init(dev, iobase);
num_ewrk3s++; if (!ret)
} break;
num_eth++; dev->irq = irq;
}
} }
} else if (autoprobed) { release_region(iobase, EWRK3_TOTAL_SIZE);
printk("%s: region already allocated at 0x%04lx.\n", dev->name, iobase);
} }
} }
out:
return; return ret;
} }
/* /*
** EISA bus I/O device probe. Probe from slot 1 since slot 0 is usually ** EISA bus I/O device probe. Probe from slot 1 since slot 0 is usually
** the motherboard. ** the motherboard.
*/ */
static void __init eisa_probe(struct net_device *dev, u_long ioaddr) static int __init eisa_probe(struct net_device *dev, u_long ioaddr)
{ {
int i, maxSlots; int i, maxSlots;
u_long iobase; u_long iobase;
char name[EWRK3_STRLEN]; int ret = -ENODEV;
if (!ioaddr && autoprobed)
return; /* Been here before ! */
if (ioaddr < 0x1000) if (ioaddr < 0x1000)
return; /* Not EISA */ goto out;
if (ioaddr == 0) { /* Autoprobing */ if (ioaddr == 0) { /* Autoprobing */
iobase = EISA_SLOT_INC; /* Get the first slot address */ iobase = EISA_SLOT_INC; /* Get the first slot address */
...@@ -1332,114 +1310,22 @@ static void __init eisa_probe(struct net_device *dev, u_long ioaddr) ...@@ -1332,114 +1310,22 @@ static void __init eisa_probe(struct net_device *dev, u_long ioaddr)
for (i = 1; (i < maxSlots) && (dev != NULL); i++, iobase += EISA_SLOT_INC) { for (i = 1; (i < maxSlots) && (dev != NULL); i++, iobase += EISA_SLOT_INC) {
if (EISA_signature(name, EISA_ID) == 0) { if (EISA_signature(name, EISA_ID) == 0) {
if (!check_region(iobase, EWRK3_TOTAL_SIZE)) { if (request_region(iobase, EWRK3_TOTAL_SIZE, dev->name) &&
if (DevicePresent(iobase) == 0) { DevicePresent(iobase) == 0) {
if ((dev = alloc_device(dev, iobase)) != NULL) { int irq = dev->irq;
if (ewrk3_hw_init(dev, iobase) == 0) { ret = ewrk3_hw_init(dev, iobase);
num_ewrk3s++; if (!ret)
} break;
num_eth++; dev->irq = irq;
}
}
} else if (autoprobed) {
printk("%s: region already allocated at 0x%04lx.\n", dev->name, iobase);
} }
release_region(iobase, EWRK3_TOTAL_SIZE);
} }
} }
return; out:
return ret;
} }
/*
** Search the entire 'eth' device list for a fixed probe. If a match isn't
** found then check for an autoprobe or unused device location. If they
** are not available then insert a new device structure at the end of
** the current list.
*/
static struct net_device * __init alloc_device(struct net_device *dev, u_long iobase)
{
struct net_device *adev = NULL;
int fixed = 0, new_dev = 0;
num_eth = ewrk3_dev_index(dev->name);
if (loading_module)
return dev;
while (1) {
if (((dev->base_addr == EWRK3_NDA) || (dev->base_addr == 0)) && !adev) {
adev = dev;
} else if ((dev->priv == NULL) && (dev->base_addr == iobase)) {
fixed = 1;
} else {
if (dev->next == NULL) {
new_dev = 1;
} else if (strncmp(dev->next->name, "eth", 3) != 0) {
new_dev = 1;
}
}
if ((dev->next == NULL) || new_dev || fixed)
break;
dev = dev->next;
num_eth++;
}
if (adev && !fixed) {
dev = adev;
num_eth = ewrk3_dev_index(dev->name);
new_dev = 0;
}
if (((dev->next == NULL) &&
((dev->base_addr != EWRK3_NDA) && (dev->base_addr != 0)) && !fixed) ||
new_dev) {
num_eth++; /* New device */
dev = insert_device(dev, iobase, ewrk3_probe);
}
return dev;
}
/*
** If at end of eth device list and can't use current entry, malloc
** one up. If memory could not be allocated, print an error message.
*/
static struct net_device * __init
insert_device(struct net_device *dev, u_long iobase, int (*init) (struct net_device *))
{
struct net_device *new;
new = (struct net_device *) kmalloc(sizeof(struct net_device) + 8, GFP_KERNEL);
if (new == NULL) {
printk("eth%d: Device not initialised, insufficient memory\n", num_eth);
return NULL;
} else {
new->next = dev->next;
dev->next = new;
dev = dev->next; /* point to the new device */
if (num_eth > 9999) {
sprintf(dev->name, "eth????"); /* New device name */
} else {
sprintf(dev->name, "eth%d", num_eth); /* New device name */
}
dev->base_addr = iobase; /* assign the io address */
dev->init = init; /* initialisation routine */
}
return dev;
}
static int __init
ewrk3_dev_index(char *s)
{
int i = 0, j = 0;
for (; *s; s++) {
if (isdigit(*s)) {
j = 1;
i = (i * 10) + (*s - '0');
} else if (j)
break;
}
return i;
}
/* /*
** Read the EWRK3 EEPROM using this routine ** Read the EWRK3 EEPROM using this routine
...@@ -2074,8 +1960,7 @@ static int ewrk3_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) ...@@ -2074,8 +1960,7 @@ static int ewrk3_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
#ifdef MODULE #ifdef MODULE
static struct net_device *ewrk3_devs[MAX_NUM_EWRK3S]; static struct net_device *ewrk3_devs[MAX_NUM_EWRK3S];
static int ndevs; static int ndevs;
static int io[MAX_NUM_EWRK3S+1] = { 0x300, 0, }; /* <--- EDIT THESE LINES FOR YOUR CONFIGURATION */ static int io[MAX_NUM_EWRK3S+1] = { 0x300, 0, };
static int irq[MAX_NUM_EWRK3S+1] = { 5, 0, }; /* or use the insmod io= irq= options */
/* '21' below should really be 'MAX_NUM_EWRK3S' */ /* '21' below should really be 'MAX_NUM_EWRK3S' */
MODULE_PARM(io, "0-21i"); MODULE_PARM(io, "0-21i");
...@@ -2083,50 +1968,39 @@ MODULE_PARM(irq, "0-21i"); ...@@ -2083,50 +1968,39 @@ MODULE_PARM(irq, "0-21i");
MODULE_PARM_DESC(io, "EtherWORKS 3 I/O base address(es)"); MODULE_PARM_DESC(io, "EtherWORKS 3 I/O base address(es)");
MODULE_PARM_DESC(irq, "EtherWORKS 3 IRQ number(s)"); MODULE_PARM_DESC(irq, "EtherWORKS 3 IRQ number(s)");
static void ewrk3_exit_module(void) static __exit void ewrk3_exit_module(void)
{ {
int i; int i;
for( i=0; i<ndevs; i++ ) { for( i=0; i<ndevs; i++ ) {
unregister_netdev(ewrk3_devs[i]); unregister_netdev(ewrk3_devs[i]);
if (ewrk3_devs[i]->priv) {
kfree(ewrk3_devs[i]->priv);
ewrk3_devs[i]->priv = NULL;
}
ewrk3_devs[i]->irq = 0;
release_region(ewrk3_devs[i]->base_addr, EWRK3_TOTAL_SIZE); release_region(ewrk3_devs[i]->base_addr, EWRK3_TOTAL_SIZE);
free_netdev(ewrk3_devs[i]); free_netdev(ewrk3_devs[i]);
ewrk3_devs[i] = NULL; ewrk3_devs[i] = NULL;
} }
} }
static int ewrk3_init_module(void) static __init int ewrk3_init_module(void)
{ {
int i=0; int i=0;
while( io[i] && irq[i] ) { while( io[i] && irq[i] ) {
ewrk3_devs[ndevs] = kmalloc(sizeof(struct net_device), GFP_KERNEL); struct net_device *dev
if (!ewrk3_devs[ndevs]) = alloc_etherdev(sizeof(struct ewrk3_private));
goto error;
memset(ewrk3_devs[ndevs], 0, sizeof(struct net_device)); if (!dev)
ewrk3_devs[ndevs]->base_addr = io[i]; break;
ewrk3_devs[ndevs]->irq = irq[i];
ewrk3_devs[ndevs]->init = ewrk3_probe;
if (register_netdev(ewrk3_devs[ndevs]) == 0)
ndevs++;
else
kfree(ewrk3_devs[ndevs]);
if (ewrk3_probe1(dev, io[i], irq[i]) != 0) {
free_netdev(dev);
break;
}
ewrk3_devs[ndevs++] = dev;
i++; i++;
} }
return ndevs ? 0 : -EIO; return ndevs ? 0 : -EIO;
error:
ewrk3_exit_module();
return -ENOMEM;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment