linux/drivers/net/ethernet/8390/wd.c
<<
>>
Prefs
   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        .ndo_change_mtu         = eth_change_mtu,
 160#ifdef CONFIG_NET_POLL_CONTROLLER
 161        .ndo_poll_controller    = ei_poll,
 162#endif
 163};
 164
 165static int __init wd_probe1(struct net_device *dev, int ioaddr)
 166{
 167        int i;
 168        int err;
 169        int checksum = 0;
 170        int ancient = 0;                        /* An old card without config registers. */
 171        int word16 = 0;                         /* 0 = 8 bit, 1 = 16 bit */
 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                dev->dev_addr[i] = inb(ioaddr + 8 + i);
 196
 197        netdev_info(dev, "WD80x3 at %#3x, %pM", ioaddr, dev->dev_addr);
 198
 199        /* The following PureData probe code was contributed by
 200           Mike Jagdis <jaggy@purplet.demon.co.uk>. Puredata does software
 201           configuration differently from others so we have to check for them.
 202           This detects an 8 bit, 16 bit or dumb (Toshiba, jumpered) card.
 203           */
 204        if (inb(ioaddr+0) == 'P' && inb(ioaddr+1) == 'D') {
 205                unsigned char reg5 = inb(ioaddr+5);
 206
 207                switch (inb(ioaddr+2)) {
 208                case 0x03: word16 = 0; model_name = "PDI8023-8";        break;
 209                case 0x05: word16 = 0; model_name = "PDUC8023"; break;
 210                case 0x0a: word16 = 1; model_name = "PDI8023-16"; break;
 211                        /* Either 0x01 (dumb) or they've released a new version. */
 212                default:         word16 = 0; model_name = "PDI8023";    break;
 213                }
 214                dev->mem_start = ((reg5 & 0x1c) + 0xc0) << 12;
 215                dev->irq = (reg5 & 0xe0) == 0xe0 ? 10 : (reg5 >> 5) + 1;
 216        } else {                                                                /* End of PureData probe */
 217                /* This method of checking for a 16-bit board is borrowed from the
 218                   we.c driver.  A simpler method is just to look in ASIC reg. 0x03.
 219                   I'm comparing the two method in alpha test to make certain they
 220                   return the same result. */
 221                /* Check for the old 8 bit board - it has register 0/8 aliasing.
 222                   Do NOT check i>=6 here -- it hangs the old 8003 boards! */
 223                for (i = 0; i < 6; i++)
 224                        if (inb(ioaddr+i) != inb(ioaddr+8+i))
 225                                break;
 226                if (i >= 6) {
 227                        ancient = 1;
 228                        model_name = "WD8003-old";
 229                        word16 = 0;
 230                } else {
 231                        int tmp = inb(ioaddr+1); /* fiddle with 16bit bit */
 232                        outb( tmp ^ 0x01, ioaddr+1 ); /* attempt to clear 16bit bit */
 233                        if (((inb( ioaddr+1) & 0x01) == 0x01) /* A 16 bit card */
 234                                && (tmp & 0x01) == 0x01 ) {                             /* In a 16 slot. */
 235                                int asic_reg5 = inb(ioaddr+WD_CMDREG5);
 236                                /* Magic to set ASIC to word-wide mode. */
 237                                outb( NIC16 | (asic_reg5&0x1f), ioaddr+WD_CMDREG5);
 238                                outb(tmp, ioaddr+1);
 239                                model_name = "WD8013";
 240                                word16 = 1;             /* We have a 16bit board here! */
 241                        } else {
 242                                model_name = "WD8003";
 243                                word16 = 0;
 244                        }
 245                        outb(tmp, ioaddr+1);                    /* Restore original reg1 value. */
 246                }
 247#ifndef final_version
 248                if ( !ancient && (inb(ioaddr+1) & 0x01) != (word16 & 0x01))
 249                        pr_cont("\nWD80?3: Bus width conflict, %d (probe) != %d (reg report).",
 250                                word16 ? 16 : 8,
 251                                (inb(ioaddr+1) & 0x01) ? 16 : 8);
 252#endif
 253        }
 254
 255#if defined(WD_SHMEM) && WD_SHMEM > 0x80000
 256        /* Allow a compile-time override.        */
 257        dev->mem_start = WD_SHMEM;
 258#else
 259        if (dev->mem_start == 0) {
 260                /* Sanity and old 8003 check */
 261                int reg0 = inb(ioaddr);
 262                if (reg0 == 0xff || reg0 == 0) {
 263                        /* Future plan: this could check a few likely locations first. */
 264                        dev->mem_start = 0xd0000;
 265                        pr_cont(" assigning address %#lx", dev->mem_start);
 266                } else {
 267                        int high_addr_bits = inb(ioaddr+WD_CMDREG5) & 0x1f;
 268                        /* Some boards don't have the register 5 -- it returns 0xff. */
 269                        if (high_addr_bits == 0x1f || word16 == 0)
 270                                high_addr_bits = 0x01;
 271                        dev->mem_start = ((reg0&0x3f) << 13) + (high_addr_bits << 19);
 272                }
 273        }
 274#endif
 275
 276        /* The 8390 isn't at the base address -- the ASIC regs are there! */
 277        dev->base_addr = ioaddr+WD_NIC_OFFSET;
 278
 279        if (dev->irq < 2) {
 280                static const int irqmap[] = {9, 3, 5, 7, 10, 11, 15, 4};
 281                int reg1 = inb(ioaddr+1);
 282                int reg4 = inb(ioaddr+4);
 283                if (ancient || reg1 == 0xff) {  /* Ack!! No way to read the IRQ! */
 284                        short nic_addr = ioaddr+WD_NIC_OFFSET;
 285                        unsigned long irq_mask;
 286
 287                        /* We have an old-style ethercard that doesn't report its IRQ
 288                           line.  Do autoirq to find the IRQ line. Note that this IS NOT
 289                           a reliable way to trigger an interrupt. */
 290                        outb_p(E8390_NODMA + E8390_STOP, nic_addr);
 291                        outb(0x00, nic_addr+EN0_IMR);   /* Disable all intrs. */
 292
 293                        irq_mask = probe_irq_on();
 294                        outb_p(0xff, nic_addr + EN0_IMR);       /* Enable all interrupts. */
 295                        outb_p(0x00, nic_addr + EN0_RCNTLO);
 296                        outb_p(0x00, nic_addr + EN0_RCNTHI);
 297                        outb(E8390_RREAD+E8390_START, nic_addr); /* Trigger it... */
 298                        mdelay(20);
 299                        dev->irq = probe_irq_off(irq_mask);
 300
 301                        outb_p(0x00, nic_addr+EN0_IMR); /* Mask all intrs. again. */
 302
 303                        if (netif_msg_drv(ei_local))
 304                                pr_cont(" autoirq is %d", dev->irq);
 305                        if (dev->irq < 2)
 306                                dev->irq = word16 ? 10 : 5;
 307                } else
 308                        dev->irq = irqmap[((reg4 >> 5) & 0x03) + (reg1 & 0x04)];
 309        } else if (dev->irq == 2)               /* Fixup bogosity: IRQ2 is really IRQ9 */
 310                dev->irq = 9;
 311
 312        /* Snarf the interrupt now.  There's no point in waiting since we cannot
 313           share and the board will usually be enabled. */
 314        i = request_irq(dev->irq, ei_interrupt, 0, DRV_NAME, dev);
 315        if (i) {
 316                pr_cont(" unable to get IRQ %d.\n", dev->irq);
 317                return i;
 318        }
 319
 320        /* OK, were are certain this is going to work.  Setup the device. */
 321        ei_status.name = model_name;
 322        ei_status.word16 = word16;
 323        ei_status.tx_start_page = WD_START_PG;
 324        ei_status.rx_start_page = WD_START_PG + TX_PAGES;
 325
 326        /* Don't map in the shared memory until the board is actually opened. */
 327
 328        /* Some cards (eg WD8003EBT) can be jumpered for more (32k!) memory. */
 329        if (dev->mem_end != 0) {
 330                ei_status.stop_page = (dev->mem_end - dev->mem_start)/256;
 331                ei_status.priv = dev->mem_end - dev->mem_start;
 332        } else {
 333                ei_status.stop_page = word16 ? WD13_STOP_PG : WD03_STOP_PG;
 334                dev->mem_end = dev->mem_start + (ei_status.stop_page - WD_START_PG)*256;
 335                ei_status.priv = (ei_status.stop_page - WD_START_PG)*256;
 336        }
 337
 338        ei_status.mem = ioremap(dev->mem_start, ei_status.priv);
 339        if (!ei_status.mem) {
 340                free_irq(dev->irq, dev);
 341                return -ENOMEM;
 342        }
 343
 344        pr_cont(" %s, IRQ %d, shared memory at %#lx-%#lx.\n",
 345                model_name, dev->irq, dev->mem_start, dev->mem_end-1);
 346
 347        ei_status.reset_8390 = wd_reset_8390;
 348        ei_status.block_input = wd_block_input;
 349        ei_status.block_output = wd_block_output;
 350        ei_status.get_8390_hdr = wd_get_8390_hdr;
 351
 352        dev->netdev_ops = &wd_netdev_ops;
 353        NS8390_init(dev, 0);
 354        ei_local->msg_enable = wd_msg_enable;
 355
 356#if 1
 357        /* Enable interrupt generation on softconfig cards -- M.U */
 358        /* .. but possibly potentially unsafe - Donald */
 359        if (inb(ioaddr+14) & 0x20)
 360                outb(inb(ioaddr+4)|0x80, ioaddr+4);
 361#endif
 362
 363        err = register_netdev(dev);
 364        if (err) {
 365                free_irq(dev->irq, dev);
 366                iounmap(ei_status.mem);
 367        }
 368        return err;
 369}
 370
 371static int
 372wd_open(struct net_device *dev)
 373{
 374  int ioaddr = dev->base_addr - WD_NIC_OFFSET; /* WD_CMDREG */
 375
 376  /* Map in the shared memory. Always set register 0 last to remain
 377         compatible with very old boards. */
 378  ei_status.reg0 = ((dev->mem_start>>13) & 0x3f) | WD_MEMENB;
 379  ei_status.reg5 = ((dev->mem_start>>19) & 0x1f) | NIC16;
 380
 381  if (ei_status.word16)
 382          outb(ei_status.reg5, ioaddr+WD_CMDREG5);
 383  outb(ei_status.reg0, ioaddr); /* WD_CMDREG */
 384
 385  return ei_open(dev);
 386}
 387
 388static void
 389wd_reset_8390(struct net_device *dev)
 390{
 391        int wd_cmd_port = dev->base_addr - WD_NIC_OFFSET; /* WD_CMDREG */
 392        struct ei_device *ei_local = netdev_priv(dev);
 393
 394        outb(WD_RESET, wd_cmd_port);
 395        netif_dbg(ei_local, hw, dev, "resetting the WD80x3 t=%lu...\n",
 396                  jiffies);
 397        ei_status.txing = 0;
 398
 399        /* Set up the ASIC registers, just in case something changed them. */
 400        outb((((dev->mem_start>>13) & 0x3f)|WD_MEMENB), wd_cmd_port);
 401        if (ei_status.word16)
 402                outb(NIC16 | ((dev->mem_start>>19) & 0x1f), wd_cmd_port+WD_CMDREG5);
 403
 404        netif_dbg(ei_local, hw, dev, "reset done\n");
 405}
 406
 407/* Grab the 8390 specific header. Similar to the block_input routine, but
 408   we don't need to be concerned with ring wrap as the header will be at
 409   the start of a page, so we optimize accordingly. */
 410
 411static void
 412wd_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
 413{
 414
 415        int wd_cmdreg = dev->base_addr - WD_NIC_OFFSET; /* WD_CMDREG */
 416        void __iomem *hdr_start = ei_status.mem + ((ring_page - WD_START_PG)<<8);
 417
 418        /* We'll always get a 4 byte header read followed by a packet read, so
 419           we enable 16 bit mode before the header, and disable after the body. */
 420        if (ei_status.word16)
 421                outb(ISA16 | ei_status.reg5, wd_cmdreg+WD_CMDREG5);
 422
 423#ifdef __BIG_ENDIAN
 424        /* Officially this is what we are doing, but the readl() is faster */
 425        /* unfortunately it isn't endian aware of the struct               */
 426        memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
 427        hdr->count = le16_to_cpu(hdr->count);
 428#else
 429        ((unsigned int*)hdr)[0] = readl(hdr_start);
 430#endif
 431}
 432
 433/* Block input and output are easy on shared memory ethercards, and trivial
 434   on the Western digital card where there is no choice of how to do it.
 435   The only complications are that the ring buffer wraps, and need to map
 436   switch between 8- and 16-bit modes. */
 437
 438static void
 439wd_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
 440{
 441        int wd_cmdreg = dev->base_addr - WD_NIC_OFFSET; /* WD_CMDREG */
 442        unsigned long offset = ring_offset - (WD_START_PG<<8);
 443        void __iomem *xfer_start = ei_status.mem + offset;
 444
 445        if (offset + count > ei_status.priv) {
 446                /* We must wrap the input move. */
 447                int semi_count = ei_status.priv - offset;
 448                memcpy_fromio(skb->data, xfer_start, semi_count);
 449                count -= semi_count;
 450                memcpy_fromio(skb->data + semi_count, ei_status.mem + TX_PAGES * 256, count);
 451        } else {
 452                /* Packet is in one chunk -- we can copy + cksum. */
 453                memcpy_fromio(skb->data, xfer_start, count);
 454        }
 455
 456        /* Turn off 16 bit access so that reboot works.  ISA brain-damage */
 457        if (ei_status.word16)
 458                outb(ei_status.reg5, wd_cmdreg+WD_CMDREG5);
 459}
 460
 461static void
 462wd_block_output(struct net_device *dev, int count, const unsigned char *buf,
 463                                int start_page)
 464{
 465        int wd_cmdreg = dev->base_addr - WD_NIC_OFFSET; /* WD_CMDREG */
 466        void __iomem *shmem = ei_status.mem + ((start_page - WD_START_PG)<<8);
 467
 468
 469        if (ei_status.word16) {
 470                /* Turn on and off 16 bit access so that reboot works. */
 471                outb(ISA16 | ei_status.reg5, wd_cmdreg+WD_CMDREG5);
 472                memcpy_toio(shmem, buf, count);
 473                outb(ei_status.reg5, wd_cmdreg+WD_CMDREG5);
 474        } else
 475                memcpy_toio(shmem, buf, count);
 476}
 477
 478
 479static int
 480wd_close(struct net_device *dev)
 481{
 482        int wd_cmdreg = dev->base_addr - WD_NIC_OFFSET; /* WD_CMDREG */
 483        struct ei_device *ei_local = netdev_priv(dev);
 484
 485        netif_dbg(ei_local, ifdown, dev, "Shutting down ethercard.\n");
 486        ei_close(dev);
 487
 488        /* Change from 16-bit to 8-bit shared memory so reboot works. */
 489        if (ei_status.word16)
 490                outb(ei_status.reg5, wd_cmdreg + WD_CMDREG5 );
 491
 492        /* And disable the shared memory. */
 493        outb(ei_status.reg0 & ~WD_MEMENB, wd_cmdreg);
 494
 495        return 0;
 496}
 497
 498
 499#ifdef MODULE
 500#define MAX_WD_CARDS    4       /* Max number of wd cards per module */
 501static struct net_device *dev_wd[MAX_WD_CARDS];
 502static int io[MAX_WD_CARDS];
 503static int irq[MAX_WD_CARDS];
 504static int mem[MAX_WD_CARDS];
 505static int mem_end[MAX_WD_CARDS];       /* for non std. mem size */
 506
 507module_param_array(io, int, NULL, 0);
 508module_param_array(irq, int, NULL, 0);
 509module_param_array(mem, int, NULL, 0);
 510module_param_array(mem_end, int, NULL, 0);
 511module_param_named(msg_enable, wd_msg_enable, uint, (S_IRUSR|S_IRGRP|S_IROTH));
 512MODULE_PARM_DESC(io, "I/O base address(es)");
 513MODULE_PARM_DESC(irq, "IRQ number(s) (ignored for PureData boards)");
 514MODULE_PARM_DESC(mem, "memory base address(es)(ignored for PureData boards)");
 515MODULE_PARM_DESC(mem_end, "memory end address(es)");
 516MODULE_PARM_DESC(msg_enable, "Debug message level (see linux/netdevice.h for bitmap)");
 517MODULE_DESCRIPTION("ISA Western Digital wd8003/wd8013 ; SMC Elite, Elite16 ethernet driver");
 518MODULE_LICENSE("GPL");
 519
 520/* This is set up so that only a single autoprobe takes place per call.
 521ISA device autoprobes on a running machine are not recommended. */
 522
 523int __init init_module(void)
 524{
 525        struct net_device *dev;
 526        int this_dev, found = 0;
 527
 528        for (this_dev = 0; this_dev < MAX_WD_CARDS; this_dev++) {
 529                if (io[this_dev] == 0)  {
 530                        if (this_dev != 0) break; /* only autoprobe 1st one */
 531                        printk(KERN_NOTICE "wd.c: Presently autoprobing (not recommended) for a single card.\n");
 532                }
 533                dev = alloc_ei_netdev();
 534                if (!dev)
 535                        break;
 536                dev->irq = irq[this_dev];
 537                dev->base_addr = io[this_dev];
 538                dev->mem_start = mem[this_dev];
 539                dev->mem_end = mem_end[this_dev];
 540                if (do_wd_probe(dev) == 0) {
 541                        dev_wd[found++] = dev;
 542                        continue;
 543                }
 544                free_netdev(dev);
 545                printk(KERN_WARNING "wd.c: No wd80x3 card found (i/o = 0x%x).\n", io[this_dev]);
 546                break;
 547        }
 548        if (found)
 549                return 0;
 550        return -ENXIO;
 551}
 552
 553static void cleanup_card(struct net_device *dev)
 554{
 555        free_irq(dev->irq, dev);
 556        release_region(dev->base_addr - WD_NIC_OFFSET, WD_IO_EXTENT);
 557        iounmap(ei_status.mem);
 558}
 559
 560void __exit
 561cleanup_module(void)
 562{
 563        int this_dev;
 564
 565        for (this_dev = 0; this_dev < MAX_WD_CARDS; this_dev++) {
 566                struct net_device *dev = dev_wd[this_dev];
 567                if (dev) {
 568                        unregister_netdev(dev);
 569                        cleanup_card(dev);
 570                        free_netdev(dev);
 571                }
 572        }
 573}
 574#endif /* MODULE */
 575