cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

wd.c (18068B)


      1/* wd.c: A WD80x3 ethernet driver for linux. */
      2/*
      3	Written 1993-94 by Donald Becker.
      4
      5	Copyright 1993 United States Government as represented by the
      6	Director, National Security Agency.
      7
      8	This software may be used and distributed according to the terms
      9	of the GNU General Public License, incorporated herein by reference.
     10
     11	The author may be reached as becker@scyld.com, or C/O
     12	Scyld Computing Corporation
     13	410 Severn Ave., Suite 210
     14	Annapolis MD 21403
     15
     16	This is a driver for WD8003 and WD8013 "compatible" ethercards.
     17
     18	Thanks to Russ Nelson (nelson@crnwyr.com) for loaning me a WD8013.
     19
     20	Changelog:
     21
     22	Paul Gortmaker	: multiple card support for module users, support
     23			  for non-standard memory sizes.
     24
     25
     26*/
     27
     28static const char version[] =
     29	"wd.c:v1.10 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
     30
     31#include <linux/module.h>
     32#include <linux/kernel.h>
     33#include <linux/errno.h>
     34#include <linux/string.h>
     35#include <linux/init.h>
     36#include <linux/interrupt.h>
     37#include <linux/delay.h>
     38#include <linux/netdevice.h>
     39#include <linux/etherdevice.h>
     40
     41#include <asm/io.h>
     42
     43#include "8390.h"
     44
     45#define DRV_NAME "wd"
     46
     47/* A zero-terminated list of I/O addresses to be probed. */
     48static unsigned int wd_portlist[] __initdata =
     49{0x300, 0x280, 0x380, 0x240, 0};
     50
     51static int wd_probe1(struct net_device *dev, int ioaddr);
     52
     53static int wd_open(struct net_device *dev);
     54static void wd_reset_8390(struct net_device *dev);
     55static void wd_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
     56						int ring_page);
     57static void wd_block_input(struct net_device *dev, int count,
     58						  struct sk_buff *skb, int ring_offset);
     59static void wd_block_output(struct net_device *dev, int count,
     60							const unsigned char *buf, int start_page);
     61static int wd_close(struct net_device *dev);
     62
     63static u32 wd_msg_enable;
     64
     65#define WD_START_PG		0x00	/* First page of TX buffer */
     66#define WD03_STOP_PG	0x20	/* Last page +1 of RX ring */
     67#define WD13_STOP_PG	0x40	/* Last page +1 of RX ring */
     68
     69#define WD_CMDREG		0		/* Offset to ASIC command register. */
     70#define	 WD_RESET		0x80	/* Board reset, in WD_CMDREG. */
     71#define	 WD_MEMENB		0x40	/* Enable the shared memory. */
     72#define WD_CMDREG5		5		/* Offset to 16-bit-only ASIC register 5. */
     73#define	 ISA16			0x80	/* Enable 16 bit access from the ISA bus. */
     74#define	 NIC16			0x40	/* Enable 16 bit access from the 8390. */
     75#define WD_NIC_OFFSET	16		/* Offset to the 8390 from the base_addr. */
     76#define WD_IO_EXTENT	32
     77
     78
     79/*	Probe for the WD8003 and WD8013.  These cards have the station
     80	address PROM at I/O ports <base>+8 to <base>+13, with a checksum
     81	following. A Soundblaster can have the same checksum as an WDethercard,
     82	so we have an extra exclusionary check for it.
     83
     84	The wd_probe1() routine initializes the card and fills the
     85	station address field. */
     86
     87static int __init do_wd_probe(struct net_device *dev)
     88{
     89	int i;
     90	struct resource *r;
     91	int base_addr = dev->base_addr;
     92	int irq = dev->irq;
     93	int mem_start = dev->mem_start;
     94	int mem_end = dev->mem_end;
     95
     96	if (base_addr > 0x1ff) {	/* Check a user specified location. */
     97		r = request_region(base_addr, WD_IO_EXTENT, "wd-probe");
     98		if ( r == NULL)
     99			return -EBUSY;
    100		i = wd_probe1(dev, base_addr);
    101		if (i != 0)
    102			release_region(base_addr, WD_IO_EXTENT);
    103		else
    104			r->name = dev->name;
    105		return i;
    106	}
    107	else if (base_addr != 0)	/* Don't probe at all. */
    108		return -ENXIO;
    109
    110	for (i = 0; wd_portlist[i]; i++) {
    111		int ioaddr = wd_portlist[i];
    112		r = request_region(ioaddr, WD_IO_EXTENT, "wd-probe");
    113		if (r == NULL)
    114			continue;
    115		if (wd_probe1(dev, ioaddr) == 0) {
    116			r->name = dev->name;
    117			return 0;
    118		}
    119		release_region(ioaddr, WD_IO_EXTENT);
    120		dev->irq = irq;
    121		dev->mem_start = mem_start;
    122		dev->mem_end = mem_end;
    123	}
    124
    125	return -ENODEV;
    126}
    127
    128#ifndef MODULE
    129struct net_device * __init wd_probe(int unit)
    130{
    131	struct net_device *dev = alloc_ei_netdev();
    132	int err;
    133
    134	if (!dev)
    135		return ERR_PTR(-ENOMEM);
    136
    137	sprintf(dev->name, "eth%d", unit);
    138	netdev_boot_setup_check(dev);
    139
    140	err = do_wd_probe(dev);
    141	if (err)
    142		goto out;
    143	return dev;
    144out:
    145	free_netdev(dev);
    146	return ERR_PTR(err);
    147}
    148#endif
    149
    150static const struct net_device_ops wd_netdev_ops = {
    151	.ndo_open		= wd_open,
    152	.ndo_stop		= wd_close,
    153	.ndo_start_xmit		= ei_start_xmit,
    154	.ndo_tx_timeout		= ei_tx_timeout,
    155	.ndo_get_stats		= ei_get_stats,
    156	.ndo_set_rx_mode	= ei_set_multicast_list,
    157	.ndo_validate_addr	= eth_validate_addr,
    158	.ndo_set_mac_address 	= eth_mac_addr,
    159#ifdef CONFIG_NET_POLL_CONTROLLER
    160	.ndo_poll_controller 	= ei_poll,
    161#endif
    162};
    163
    164static int __init wd_probe1(struct net_device *dev, int ioaddr)
    165{
    166	int i;
    167	int err;
    168	int checksum = 0;
    169	int ancient = 0;			/* An old card without config registers. */
    170	int word16 = 0;				/* 0 = 8 bit, 1 = 16 bit */
    171	u8 addr[ETH_ALEN];
    172	const char *model_name;
    173	static unsigned version_printed;
    174	struct ei_device *ei_local = netdev_priv(dev);
    175
    176	for (i = 0; i < 8; i++)
    177		checksum += inb(ioaddr + 8 + i);
    178	if (inb(ioaddr + 8) == 0xff 	/* Extra check to avoid soundcard. */
    179		|| inb(ioaddr + 9) == 0xff
    180		|| (checksum & 0xff) != 0xFF)
    181		return -ENODEV;
    182
    183	/* Check for semi-valid mem_start/end values if supplied. */
    184	if ((dev->mem_start % 0x2000) || (dev->mem_end % 0x2000)) {
    185		netdev_warn(dev,
    186			    "wd.c: user supplied mem_start or mem_end not on 8kB boundary - ignored.\n");
    187		dev->mem_start = 0;
    188		dev->mem_end = 0;
    189	}
    190
    191	if ((wd_msg_enable & NETIF_MSG_DRV) && (version_printed++ == 0))
    192		netdev_info(dev, version);
    193
    194	for (i = 0; i < 6; i++)
    195		addr[i] = inb(ioaddr + 8 + i);
    196	eth_hw_addr_set(dev, addr);
    197
    198	netdev_info(dev, "WD80x3 at %#3x, %pM", ioaddr, dev->dev_addr);
    199
    200	/* The following PureData probe code was contributed by
    201	   Mike Jagdis <jaggy@purplet.demon.co.uk>. Puredata does software
    202	   configuration differently from others so we have to check for them.
    203	   This detects an 8 bit, 16 bit or dumb (Toshiba, jumpered) card.
    204	   */
    205	if (inb(ioaddr+0) == 'P' && inb(ioaddr+1) == 'D') {
    206		unsigned char reg5 = inb(ioaddr+5);
    207
    208		switch (inb(ioaddr+2)) {
    209		case 0x03: word16 = 0; model_name = "PDI8023-8";	break;
    210		case 0x05: word16 = 0; model_name = "PDUC8023";	break;
    211		case 0x0a: word16 = 1; model_name = "PDI8023-16"; break;
    212			/* Either 0x01 (dumb) or they've released a new version. */
    213		default:	 word16 = 0; model_name = "PDI8023";	break;
    214		}
    215		dev->mem_start = ((reg5 & 0x1c) + 0xc0) << 12;
    216		dev->irq = (reg5 & 0xe0) == 0xe0 ? 10 : (reg5 >> 5) + 1;
    217	} else {								/* End of PureData probe */
    218		/* This method of checking for a 16-bit board is borrowed from the
    219		   we.c driver.  A simpler method is just to look in ASIC reg. 0x03.
    220		   I'm comparing the two method in alpha test to make certain they
    221		   return the same result. */
    222		/* Check for the old 8 bit board - it has register 0/8 aliasing.
    223		   Do NOT check i>=6 here -- it hangs the old 8003 boards! */
    224		for (i = 0; i < 6; i++)
    225			if (inb(ioaddr+i) != inb(ioaddr+8+i))
    226				break;
    227		if (i >= 6) {
    228			ancient = 1;
    229			model_name = "WD8003-old";
    230			word16 = 0;
    231		} else {
    232			int tmp = inb(ioaddr+1); /* fiddle with 16bit bit */
    233			outb( tmp ^ 0x01, ioaddr+1 ); /* attempt to clear 16bit bit */
    234			if (((inb( ioaddr+1) & 0x01) == 0x01) /* A 16 bit card */
    235				&& (tmp & 0x01) == 0x01	) {				/* In a 16 slot. */
    236				int asic_reg5 = inb(ioaddr+WD_CMDREG5);
    237				/* Magic to set ASIC to word-wide mode. */
    238				outb( NIC16 | (asic_reg5&0x1f), ioaddr+WD_CMDREG5);
    239				outb(tmp, ioaddr+1);
    240				model_name = "WD8013";
    241				word16 = 1;		/* We have a 16bit board here! */
    242			} else {
    243				model_name = "WD8003";
    244				word16 = 0;
    245			}
    246			outb(tmp, ioaddr+1);			/* Restore original reg1 value. */
    247		}
    248#ifndef final_version
    249		if ( !ancient && (inb(ioaddr+1) & 0x01) != (word16 & 0x01))
    250			pr_cont("\nWD80?3: Bus width conflict, %d (probe) != %d (reg report).",
    251				word16 ? 16 : 8,
    252				(inb(ioaddr+1) & 0x01) ? 16 : 8);
    253#endif
    254	}
    255
    256#if defined(WD_SHMEM) && WD_SHMEM > 0x80000
    257	/* Allow a compile-time override.	 */
    258	dev->mem_start = WD_SHMEM;
    259#else
    260	if (dev->mem_start == 0) {
    261		/* Sanity and old 8003 check */
    262		int reg0 = inb(ioaddr);
    263		if (reg0 == 0xff || reg0 == 0) {
    264			/* Future plan: this could check a few likely locations first. */
    265			dev->mem_start = 0xd0000;
    266			pr_cont(" assigning address %#lx", dev->mem_start);
    267		} else {
    268			int high_addr_bits = inb(ioaddr+WD_CMDREG5) & 0x1f;
    269			/* Some boards don't have the register 5 -- it returns 0xff. */
    270			if (high_addr_bits == 0x1f || word16 == 0)
    271				high_addr_bits = 0x01;
    272			dev->mem_start = ((reg0&0x3f) << 13) + (high_addr_bits << 19);
    273		}
    274	}
    275#endif
    276
    277	/* The 8390 isn't at the base address -- the ASIC regs are there! */
    278	dev->base_addr = ioaddr+WD_NIC_OFFSET;
    279
    280	if (dev->irq < 2) {
    281		static const int irqmap[] = {9, 3, 5, 7, 10, 11, 15, 4};
    282		int reg1 = inb(ioaddr+1);
    283		int reg4 = inb(ioaddr+4);
    284		if (ancient || reg1 == 0xff) {	/* Ack!! No way to read the IRQ! */
    285			short nic_addr = ioaddr+WD_NIC_OFFSET;
    286			unsigned long irq_mask;
    287
    288			/* We have an old-style ethercard that doesn't report its IRQ
    289			   line.  Do autoirq to find the IRQ line. Note that this IS NOT
    290			   a reliable way to trigger an interrupt. */
    291			outb_p(E8390_NODMA + E8390_STOP, nic_addr);
    292			outb(0x00, nic_addr+EN0_IMR);	/* Disable all intrs. */
    293
    294			irq_mask = probe_irq_on();
    295			outb_p(0xff, nic_addr + EN0_IMR);	/* Enable all interrupts. */
    296			outb_p(0x00, nic_addr + EN0_RCNTLO);
    297			outb_p(0x00, nic_addr + EN0_RCNTHI);
    298			outb(E8390_RREAD+E8390_START, nic_addr); /* Trigger it... */
    299			mdelay(20);
    300			dev->irq = probe_irq_off(irq_mask);
    301
    302			outb_p(0x00, nic_addr+EN0_IMR);	/* Mask all intrs. again. */
    303
    304			if (wd_msg_enable & NETIF_MSG_PROBE)
    305				pr_cont(" autoirq is %d", dev->irq);
    306			if (dev->irq < 2)
    307				dev->irq = word16 ? 10 : 5;
    308		} else
    309			dev->irq = irqmap[((reg4 >> 5) & 0x03) + (reg1 & 0x04)];
    310	} else if (dev->irq == 2)		/* Fixup bogosity: IRQ2 is really IRQ9 */
    311		dev->irq = 9;
    312
    313	/* Snarf the interrupt now.  There's no point in waiting since we cannot
    314	   share and the board will usually be enabled. */
    315	i = request_irq(dev->irq, ei_interrupt, 0, DRV_NAME, dev);
    316	if (i) {
    317		pr_cont(" unable to get IRQ %d.\n", dev->irq);
    318		return i;
    319	}
    320
    321	/* OK, were are certain this is going to work.  Setup the device. */
    322	ei_status.name = model_name;
    323	ei_status.word16 = word16;
    324	ei_status.tx_start_page = WD_START_PG;
    325	ei_status.rx_start_page = WD_START_PG + TX_PAGES;
    326
    327	/* Don't map in the shared memory until the board is actually opened. */
    328
    329	/* Some cards (eg WD8003EBT) can be jumpered for more (32k!) memory. */
    330	if (dev->mem_end != 0) {
    331		ei_status.stop_page = (dev->mem_end - dev->mem_start)/256;
    332		ei_status.priv = dev->mem_end - dev->mem_start;
    333	} else {
    334		ei_status.stop_page = word16 ? WD13_STOP_PG : WD03_STOP_PG;
    335		dev->mem_end = dev->mem_start + (ei_status.stop_page - WD_START_PG)*256;
    336		ei_status.priv = (ei_status.stop_page - WD_START_PG)*256;
    337	}
    338
    339	ei_status.mem = ioremap(dev->mem_start, ei_status.priv);
    340	if (!ei_status.mem) {
    341		free_irq(dev->irq, dev);
    342		return -ENOMEM;
    343	}
    344
    345	pr_cont(" %s, IRQ %d, shared memory at %#lx-%#lx.\n",
    346		model_name, dev->irq, dev->mem_start, dev->mem_end-1);
    347
    348	ei_status.reset_8390 = wd_reset_8390;
    349	ei_status.block_input = wd_block_input;
    350	ei_status.block_output = wd_block_output;
    351	ei_status.get_8390_hdr = wd_get_8390_hdr;
    352
    353	dev->netdev_ops = &wd_netdev_ops;
    354	NS8390_init(dev, 0);
    355	ei_local->msg_enable = wd_msg_enable;
    356
    357#if 1
    358	/* Enable interrupt generation on softconfig cards -- M.U */
    359	/* .. but possibly potentially unsafe - Donald */
    360	if (inb(ioaddr+14) & 0x20)
    361		outb(inb(ioaddr+4)|0x80, ioaddr+4);
    362#endif
    363
    364	err = register_netdev(dev);
    365	if (err) {
    366		free_irq(dev->irq, dev);
    367		iounmap(ei_status.mem);
    368	}
    369	return err;
    370}
    371
    372static int
    373wd_open(struct net_device *dev)
    374{
    375  int ioaddr = dev->base_addr - WD_NIC_OFFSET; /* WD_CMDREG */
    376
    377  /* Map in the shared memory. Always set register 0 last to remain
    378	 compatible with very old boards. */
    379  ei_status.reg0 = ((dev->mem_start>>13) & 0x3f) | WD_MEMENB;
    380  ei_status.reg5 = ((dev->mem_start>>19) & 0x1f) | NIC16;
    381
    382  if (ei_status.word16)
    383	  outb(ei_status.reg5, ioaddr+WD_CMDREG5);
    384  outb(ei_status.reg0, ioaddr); /* WD_CMDREG */
    385
    386  return ei_open(dev);
    387}
    388
    389static void
    390wd_reset_8390(struct net_device *dev)
    391{
    392	int wd_cmd_port = dev->base_addr - WD_NIC_OFFSET; /* WD_CMDREG */
    393	struct ei_device *ei_local = netdev_priv(dev);
    394
    395	outb(WD_RESET, wd_cmd_port);
    396	netif_dbg(ei_local, hw, dev, "resetting the WD80x3 t=%lu...\n",
    397		  jiffies);
    398	ei_status.txing = 0;
    399
    400	/* Set up the ASIC registers, just in case something changed them. */
    401	outb((((dev->mem_start>>13) & 0x3f)|WD_MEMENB), wd_cmd_port);
    402	if (ei_status.word16)
    403		outb(NIC16 | ((dev->mem_start>>19) & 0x1f), wd_cmd_port+WD_CMDREG5);
    404
    405	netif_dbg(ei_local, hw, dev, "reset done\n");
    406}
    407
    408/* Grab the 8390 specific header. Similar to the block_input routine, but
    409   we don't need to be concerned with ring wrap as the header will be at
    410   the start of a page, so we optimize accordingly. */
    411
    412static void
    413wd_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
    414{
    415
    416	int wd_cmdreg = dev->base_addr - WD_NIC_OFFSET; /* WD_CMDREG */
    417	void __iomem *hdr_start = ei_status.mem + ((ring_page - WD_START_PG)<<8);
    418
    419	/* We'll always get a 4 byte header read followed by a packet read, so
    420	   we enable 16 bit mode before the header, and disable after the body. */
    421	if (ei_status.word16)
    422		outb(ISA16 | ei_status.reg5, wd_cmdreg+WD_CMDREG5);
    423
    424#ifdef __BIG_ENDIAN
    425	/* Officially this is what we are doing, but the readl() is faster */
    426	/* unfortunately it isn't endian aware of the struct               */
    427	memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
    428	hdr->count = le16_to_cpu(hdr->count);
    429#else
    430	((unsigned int*)hdr)[0] = readl(hdr_start);
    431#endif
    432}
    433
    434/* Block input and output are easy on shared memory ethercards, and trivial
    435   on the Western digital card where there is no choice of how to do it.
    436   The only complications are that the ring buffer wraps, and need to map
    437   switch between 8- and 16-bit modes. */
    438
    439static void
    440wd_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
    441{
    442	int wd_cmdreg = dev->base_addr - WD_NIC_OFFSET; /* WD_CMDREG */
    443	unsigned long offset = ring_offset - (WD_START_PG<<8);
    444	void __iomem *xfer_start = ei_status.mem + offset;
    445
    446	if (offset + count > ei_status.priv) {
    447		/* We must wrap the input move. */
    448		int semi_count = ei_status.priv - offset;
    449		memcpy_fromio(skb->data, xfer_start, semi_count);
    450		count -= semi_count;
    451		memcpy_fromio(skb->data + semi_count, ei_status.mem + TX_PAGES * 256, count);
    452	} else {
    453		/* Packet is in one chunk -- we can copy + cksum. */
    454		memcpy_fromio(skb->data, xfer_start, count);
    455	}
    456
    457	/* Turn off 16 bit access so that reboot works.	 ISA brain-damage */
    458	if (ei_status.word16)
    459		outb(ei_status.reg5, wd_cmdreg+WD_CMDREG5);
    460}
    461
    462static void
    463wd_block_output(struct net_device *dev, int count, const unsigned char *buf,
    464				int start_page)
    465{
    466	int wd_cmdreg = dev->base_addr - WD_NIC_OFFSET; /* WD_CMDREG */
    467	void __iomem *shmem = ei_status.mem + ((start_page - WD_START_PG)<<8);
    468
    469
    470	if (ei_status.word16) {
    471		/* Turn on and off 16 bit access so that reboot works. */
    472		outb(ISA16 | ei_status.reg5, wd_cmdreg+WD_CMDREG5);
    473		memcpy_toio(shmem, buf, count);
    474		outb(ei_status.reg5, wd_cmdreg+WD_CMDREG5);
    475	} else
    476		memcpy_toio(shmem, buf, count);
    477}
    478
    479
    480static int
    481wd_close(struct net_device *dev)
    482{
    483	int wd_cmdreg = dev->base_addr - WD_NIC_OFFSET; /* WD_CMDREG */
    484	struct ei_device *ei_local = netdev_priv(dev);
    485
    486	netif_dbg(ei_local, ifdown, dev, "Shutting down ethercard.\n");
    487	ei_close(dev);
    488
    489	/* Change from 16-bit to 8-bit shared memory so reboot works. */
    490	if (ei_status.word16)
    491		outb(ei_status.reg5, wd_cmdreg + WD_CMDREG5 );
    492
    493	/* And disable the shared memory. */
    494	outb(ei_status.reg0 & ~WD_MEMENB, wd_cmdreg);
    495
    496	return 0;
    497}
    498
    499
    500#ifdef MODULE
    501#define MAX_WD_CARDS	4	/* Max number of wd cards per module */
    502static struct net_device *dev_wd[MAX_WD_CARDS];
    503static int io[MAX_WD_CARDS];
    504static int irq[MAX_WD_CARDS];
    505static int mem[MAX_WD_CARDS];
    506static int mem_end[MAX_WD_CARDS];	/* for non std. mem size */
    507
    508module_param_hw_array(io, int, ioport, NULL, 0);
    509module_param_hw_array(irq, int, irq, NULL, 0);
    510module_param_hw_array(mem, int, iomem, NULL, 0);
    511module_param_hw_array(mem_end, int, iomem, NULL, 0);
    512module_param_named(msg_enable, wd_msg_enable, uint, 0444);
    513MODULE_PARM_DESC(io, "I/O base address(es)");
    514MODULE_PARM_DESC(irq, "IRQ number(s) (ignored for PureData boards)");
    515MODULE_PARM_DESC(mem, "memory base address(es)(ignored for PureData boards)");
    516MODULE_PARM_DESC(mem_end, "memory end address(es)");
    517MODULE_PARM_DESC(msg_enable, "Debug message level (see linux/netdevice.h for bitmap)");
    518MODULE_DESCRIPTION("ISA Western Digital wd8003/wd8013 ; SMC Elite, Elite16 ethernet driver");
    519MODULE_LICENSE("GPL");
    520
    521/* This is set up so that only a single autoprobe takes place per call.
    522ISA device autoprobes on a running machine are not recommended. */
    523
    524static int __init wd_init_module(void)
    525{
    526	struct net_device *dev;
    527	int this_dev, found = 0;
    528
    529	for (this_dev = 0; this_dev < MAX_WD_CARDS; this_dev++) {
    530		if (io[this_dev] == 0)  {
    531			if (this_dev != 0) break; /* only autoprobe 1st one */
    532			printk(KERN_NOTICE "wd.c: Presently autoprobing (not recommended) for a single card.\n");
    533		}
    534		dev = alloc_ei_netdev();
    535		if (!dev)
    536			break;
    537		dev->irq = irq[this_dev];
    538		dev->base_addr = io[this_dev];
    539		dev->mem_start = mem[this_dev];
    540		dev->mem_end = mem_end[this_dev];
    541		if (do_wd_probe(dev) == 0) {
    542			dev_wd[found++] = dev;
    543			continue;
    544		}
    545		free_netdev(dev);
    546		printk(KERN_WARNING "wd.c: No wd80x3 card found (i/o = 0x%x).\n", io[this_dev]);
    547		break;
    548	}
    549	if (found)
    550		return 0;
    551	return -ENXIO;
    552}
    553module_init(wd_init_module);
    554
    555static void cleanup_card(struct net_device *dev)
    556{
    557	free_irq(dev->irq, dev);
    558	release_region(dev->base_addr - WD_NIC_OFFSET, WD_IO_EXTENT);
    559	iounmap(ei_status.mem);
    560}
    561
    562static void __exit wd_cleanup_module(void)
    563{
    564	int this_dev;
    565
    566	for (this_dev = 0; this_dev < MAX_WD_CARDS; this_dev++) {
    567		struct net_device *dev = dev_wd[this_dev];
    568		if (dev) {
    569			unregister_netdev(dev);
    570			cleanup_card(dev);
    571			free_netdev(dev);
    572		}
    573	}
    574}
    575module_exit(wd_cleanup_module);
    576#endif /* MODULE */