linux/drivers/net/ethernet/cirrus/mac89x0.c
<<
>>
Prefs
   1/* mac89x0.c: A Crystal Semiconductor CS89[02]0 driver for linux. */
   2/*
   3        Written 1996 by Russell Nelson, with reference to skeleton.c
   4        written 1993-1994 by Donald Becker.
   5
   6        This software may be used and distributed according to the terms
   7        of the GNU General Public License, incorporated herein by reference.
   8
   9        The author may be reached at nelson@crynwr.com, Crynwr
  10        Software, 11 Grant St., Potsdam, NY 13676
  11
  12  Changelog:
  13
  14  Mike Cruse        : mcruse@cti-ltd.com
  15                    : Changes for Linux 2.0 compatibility.
  16                    : Added dev_id parameter in net_interrupt(),
  17                    : request_irq() and free_irq(). Just NULL for now.
  18
  19  Mike Cruse        : Added MOD_INC_USE_COUNT and MOD_DEC_USE_COUNT macros
  20                    : in net_open() and net_close() so kerneld would know
  21                    : that the module is in use and wouldn't eject the
  22                    : driver prematurely.
  23
  24  Mike Cruse        : Rewrote init_module() and cleanup_module using 8390.c
  25                    : as an example. Disabled autoprobing in init_module(),
  26                    : not a good thing to do to other devices while Linux
  27                    : is running from all accounts.
  28
  29  Alan Cox          : Removed 1.2 support, added 2.1 extra counters.
  30
  31  David Huggins-Daines <dhd@debian.org>
  32
  33  Split this off into mac89x0.c, and gutted it of all parts which are
  34  not relevant to the existing CS8900 cards on the Macintosh
  35  (i.e. basically the Daynaport CS and LC cards).  To be precise:
  36
  37    * Removed all the media-detection stuff, because these cards are
  38    TP-only.
  39
  40    * Lobotomized the ISA interrupt bogosity, because these cards use
  41    a hardwired NuBus interrupt and a magic ISAIRQ value in the card.
  42
  43    * Basically eliminated everything not relevant to getting the
  44    cards minimally functioning on the Macintosh.
  45
  46  I might add that these cards are badly designed even from the Mac
  47  standpoint, in that Dayna, in their infinite wisdom, used NuBus slot
  48  I/O space and NuBus interrupts for these cards, but neglected to
  49  provide anything even remotely resembling a NuBus ROM.  Therefore we
  50  have to probe for them in a brain-damaged ISA-like fashion.
  51
  52  Arnaldo Carvalho de Melo <acme@conectiva.com.br> - 11/01/2001
  53  check kmalloc and release the allocated memory on failure in
  54  mac89x0_probe and in init_module
  55  use local_irq_{save,restore}(flags) in net_get_stat, not just
  56  local_irq_{dis,en}able()
  57*/
  58
  59static char *version =
  60"cs89x0.c:v1.02 11/26/96 Russell Nelson <nelson@crynwr.com>\n";
  61
  62/* ======================= configure the driver here ======================= */
  63
  64/* use 0 for production, 1 for verification, >2 for debug */
  65#ifndef NET_DEBUG
  66#define NET_DEBUG 0
  67#endif
  68
  69/* ======================= end of configuration ======================= */
  70
  71
  72/* Always include 'config.h' first in case the user wants to turn on
  73   or override something. */
  74#include <linux/module.h>
  75
  76/*
  77  Sources:
  78
  79        Crynwr packet driver epktisa.
  80
  81        Crystal Semiconductor data sheets.
  82
  83*/
  84
  85#include <linux/kernel.h>
  86#include <linux/types.h>
  87#include <linux/fcntl.h>
  88#include <linux/interrupt.h>
  89#include <linux/ioport.h>
  90#include <linux/in.h>
  91#include <linux/string.h>
  92#include <linux/nubus.h>
  93#include <linux/errno.h>
  94#include <linux/init.h>
  95#include <linux/netdevice.h>
  96#include <linux/etherdevice.h>
  97#include <linux/skbuff.h>
  98#include <linux/delay.h>
  99#include <linux/bitops.h>
 100#include <linux/gfp.h>
 101
 102#include <asm/io.h>
 103#include <asm/hwtest.h>
 104#include <asm/macints.h>
 105
 106#include "cs89x0.h"
 107
 108static unsigned int net_debug = NET_DEBUG;
 109
 110/* Information that need to be kept for each board. */
 111struct net_local {
 112        int chip_type;          /* one of: CS8900, CS8920, CS8920M */
 113        char chip_revision;     /* revision letter of the chip ('A'...) */
 114        int send_cmd;           /* the propercommand used to send a packet. */
 115        int rx_mode;
 116        int curr_rx_cfg;
 117        int send_underrun;      /* keep track of how many underruns in a row we get */
 118        struct sk_buff *skb;
 119};
 120
 121/* Index to functions, as function prototypes. */
 122
 123#if 0
 124extern void reset_chip(struct net_device *dev);
 125#endif
 126static int net_open(struct net_device *dev);
 127static int net_send_packet(struct sk_buff *skb, struct net_device *dev);
 128static irqreturn_t net_interrupt(int irq, void *dev_id);
 129static void set_multicast_list(struct net_device *dev);
 130static void net_rx(struct net_device *dev);
 131static int net_close(struct net_device *dev);
 132static struct net_device_stats *net_get_stats(struct net_device *dev);
 133static int set_mac_address(struct net_device *dev, void *addr);
 134
 135
 136/* Example routines you must write ;->. */
 137#define tx_done(dev) 1
 138
 139/* For reading/writing registers ISA-style */
 140static inline int
 141readreg_io(struct net_device *dev, int portno)
 142{
 143        nubus_writew(swab16(portno), dev->base_addr + ADD_PORT);
 144        return swab16(nubus_readw(dev->base_addr + DATA_PORT));
 145}
 146
 147static inline void
 148writereg_io(struct net_device *dev, int portno, int value)
 149{
 150        nubus_writew(swab16(portno), dev->base_addr + ADD_PORT);
 151        nubus_writew(swab16(value), dev->base_addr + DATA_PORT);
 152}
 153
 154/* These are for reading/writing registers in shared memory */
 155static inline int
 156readreg(struct net_device *dev, int portno)
 157{
 158        return swab16(nubus_readw(dev->mem_start + portno));
 159}
 160
 161static inline void
 162writereg(struct net_device *dev, int portno, int value)
 163{
 164        nubus_writew(swab16(value), dev->mem_start + portno);
 165}
 166
 167static const struct net_device_ops mac89x0_netdev_ops = {
 168        .ndo_open               = net_open,
 169        .ndo_stop               = net_close,
 170        .ndo_start_xmit         = net_send_packet,
 171        .ndo_get_stats          = net_get_stats,
 172        .ndo_set_rx_mode        = set_multicast_list,
 173        .ndo_set_mac_address    = set_mac_address,
 174        .ndo_validate_addr      = eth_validate_addr,
 175};
 176
 177/* Probe for the CS8900 card in slot E.  We won't bother looking
 178   anywhere else until we have a really good reason to do so. */
 179struct net_device * __init mac89x0_probe(int unit)
 180{
 181        struct net_device *dev;
 182        static int once_is_enough;
 183        struct net_local *lp;
 184        static unsigned version_printed;
 185        int i, slot;
 186        unsigned rev_type = 0;
 187        unsigned long ioaddr;
 188        unsigned short sig;
 189        int err = -ENODEV;
 190
 191        if (!MACH_IS_MAC)
 192                return ERR_PTR(-ENODEV);
 193
 194        dev = alloc_etherdev(sizeof(struct net_local));
 195        if (!dev)
 196                return ERR_PTR(-ENOMEM);
 197
 198        if (unit >= 0) {
 199                sprintf(dev->name, "eth%d", unit);
 200                netdev_boot_setup_check(dev);
 201        }
 202
 203        if (once_is_enough)
 204                goto out;
 205        once_is_enough = 1;
 206
 207        /* We might have to parameterize this later */
 208        slot = 0xE;
 209        /* Get out now if there's a real NuBus card in slot E */
 210        if (nubus_find_slot(slot, NULL) != NULL)
 211                goto out;
 212
 213        /* The pseudo-ISA bits always live at offset 0x300 (gee,
 214           wonder why...) */
 215        ioaddr = (unsigned long)
 216                nubus_slot_addr(slot) | (((slot&0xf) << 20) + DEFAULTIOBASE);
 217        {
 218                int card_present;
 219
 220                card_present = (hwreg_present((void *)ioaddr + 4) &&
 221                                hwreg_present((void *)ioaddr + DATA_PORT));
 222                if (!card_present)
 223                        goto out;
 224        }
 225
 226        nubus_writew(0, ioaddr + ADD_PORT);
 227        sig = nubus_readw(ioaddr + DATA_PORT);
 228        if (sig != swab16(CHIP_EISA_ID_SIG))
 229                goto out;
 230
 231        /* Initialize the net_device structure. */
 232        lp = netdev_priv(dev);
 233
 234        /* Fill in the 'dev' fields. */
 235        dev->base_addr = ioaddr;
 236        dev->mem_start = (unsigned long)
 237                nubus_slot_addr(slot) | (((slot&0xf) << 20) + MMIOBASE);
 238        dev->mem_end = dev->mem_start + 0x1000;
 239
 240        /* Turn on shared memory */
 241        writereg_io(dev, PP_BusCTL, MEMORY_ON);
 242
 243        /* get the chip type */
 244        rev_type = readreg(dev, PRODUCT_ID_ADD);
 245        lp->chip_type = rev_type &~ REVISON_BITS;
 246        lp->chip_revision = ((rev_type & REVISON_BITS) >> 8) + 'A';
 247
 248        /* Check the chip type and revision in order to set the correct send command
 249        CS8920 revision C and CS8900 revision F can use the faster send. */
 250        lp->send_cmd = TX_AFTER_381;
 251        if (lp->chip_type == CS8900 && lp->chip_revision >= 'F')
 252                lp->send_cmd = TX_NOW;
 253        if (lp->chip_type != CS8900 && lp->chip_revision >= 'C')
 254                lp->send_cmd = TX_NOW;
 255
 256        if (net_debug && version_printed++ == 0)
 257                printk(version);
 258
 259        printk(KERN_INFO "%s: cs89%c0%s rev %c found at %#8lx",
 260               dev->name,
 261               lp->chip_type==CS8900?'0':'2',
 262               lp->chip_type==CS8920M?"M":"",
 263               lp->chip_revision,
 264               dev->base_addr);
 265
 266        /* Try to read the MAC address */
 267        if ((readreg(dev, PP_SelfST) & (EEPROM_PRESENT | EEPROM_OK)) == 0) {
 268                printk("\nmac89x0: No EEPROM, giving up now.\n");
 269                goto out1;
 270        } else {
 271                for (i = 0; i < ETH_ALEN; i += 2) {
 272                        /* Big-endian (why??!) */
 273                        unsigned short s = readreg(dev, PP_IA + i);
 274                        dev->dev_addr[i] = s >> 8;
 275                        dev->dev_addr[i+1] = s & 0xff;
 276                }
 277        }
 278
 279        dev->irq = SLOT2IRQ(slot);
 280
 281        /* print the IRQ and ethernet address. */
 282
 283        printk(" IRQ %d ADDR %pM\n", dev->irq, dev->dev_addr);
 284
 285        dev->netdev_ops         = &mac89x0_netdev_ops;
 286
 287        err = register_netdev(dev);
 288        if (err)
 289                goto out1;
 290        return NULL;
 291out1:
 292        nubus_writew(0, dev->base_addr + ADD_PORT);
 293out:
 294        free_netdev(dev);
 295        return ERR_PTR(err);
 296}
 297
 298#if 0
 299/* This is useful for something, but I don't know what yet. */
 300void __init reset_chip(struct net_device *dev)
 301{
 302        int reset_start_time;
 303
 304        writereg(dev, PP_SelfCTL, readreg(dev, PP_SelfCTL) | POWER_ON_RESET);
 305
 306        /* wait 30 ms */
 307        msleep_interruptible(30);
 308
 309        /* Wait until the chip is reset */
 310        reset_start_time = jiffies;
 311        while( (readreg(dev, PP_SelfST) & INIT_DONE) == 0 && jiffies - reset_start_time < 2)
 312                ;
 313}
 314#endif
 315
 316/* Open/initialize the board.  This is called (in the current kernel)
 317   sometime after booting when the 'ifconfig' program is run.
 318
 319   This routine should set everything up anew at each open, even
 320   registers that "should" only need to be set once at boot, so that
 321   there is non-reboot way to recover if something goes wrong.
 322   */
 323static int
 324net_open(struct net_device *dev)
 325{
 326        struct net_local *lp = netdev_priv(dev);
 327        int i;
 328
 329        /* Disable the interrupt for now */
 330        writereg(dev, PP_BusCTL, readreg(dev, PP_BusCTL) & ~ENABLE_IRQ);
 331
 332        /* Grab the interrupt */
 333        if (request_irq(dev->irq, net_interrupt, 0, "cs89x0", dev))
 334                return -EAGAIN;
 335
 336        /* Set up the IRQ - Apparently magic */
 337        if (lp->chip_type == CS8900)
 338                writereg(dev, PP_CS8900_ISAINT, 0);
 339        else
 340                writereg(dev, PP_CS8920_ISAINT, 0);
 341
 342        /* set the Ethernet address */
 343        for (i=0; i < ETH_ALEN/2; i++)
 344                writereg(dev, PP_IA+i*2, dev->dev_addr[i*2] | (dev->dev_addr[i*2+1] << 8));
 345
 346        /* Turn on both receive and transmit operations */
 347        writereg(dev, PP_LineCTL, readreg(dev, PP_LineCTL) | SERIAL_RX_ON | SERIAL_TX_ON);
 348
 349        /* Receive only error free packets addressed to this card */
 350        lp->rx_mode = 0;
 351        writereg(dev, PP_RxCTL, DEF_RX_ACCEPT);
 352
 353        lp->curr_rx_cfg = RX_OK_ENBL | RX_CRC_ERROR_ENBL;
 354
 355        writereg(dev, PP_RxCFG, lp->curr_rx_cfg);
 356
 357        writereg(dev, PP_TxCFG, TX_LOST_CRS_ENBL | TX_SQE_ERROR_ENBL | TX_OK_ENBL |
 358               TX_LATE_COL_ENBL | TX_JBR_ENBL | TX_ANY_COL_ENBL | TX_16_COL_ENBL);
 359
 360        writereg(dev, PP_BufCFG, READY_FOR_TX_ENBL | RX_MISS_COUNT_OVRFLOW_ENBL |
 361                 TX_COL_COUNT_OVRFLOW_ENBL | TX_UNDERRUN_ENBL);
 362
 363        /* now that we've got our act together, enable everything */
 364        writereg(dev, PP_BusCTL, readreg(dev, PP_BusCTL) | ENABLE_IRQ);
 365        netif_start_queue(dev);
 366        return 0;
 367}
 368
 369static int
 370net_send_packet(struct sk_buff *skb, struct net_device *dev)
 371{
 372        struct net_local *lp = netdev_priv(dev);
 373        unsigned long flags;
 374
 375        if (net_debug > 3)
 376                printk("%s: sent %d byte packet of type %x\n",
 377                       dev->name, skb->len,
 378                       (skb->data[ETH_ALEN+ETH_ALEN] << 8)
 379                       | skb->data[ETH_ALEN+ETH_ALEN+1]);
 380
 381        /* keep the upload from being interrupted, since we
 382           ask the chip to start transmitting before the
 383           whole packet has been completely uploaded. */
 384        local_irq_save(flags);
 385        netif_stop_queue(dev);
 386
 387        /* initiate a transmit sequence */
 388        writereg(dev, PP_TxCMD, lp->send_cmd);
 389        writereg(dev, PP_TxLength, skb->len);
 390
 391        /* Test to see if the chip has allocated memory for the packet */
 392        if ((readreg(dev, PP_BusST) & READY_FOR_TX_NOW) == 0) {
 393                /* Gasp!  It hasn't.  But that shouldn't happen since
 394                   we're waiting for TxOk, so return 1 and requeue this packet. */
 395                local_irq_restore(flags);
 396                return NETDEV_TX_BUSY;
 397        }
 398
 399        /* Write the contents of the packet */
 400        skb_copy_from_linear_data(skb, (void *)(dev->mem_start + PP_TxFrame),
 401                                  skb->len+1);
 402
 403        local_irq_restore(flags);
 404        dev_kfree_skb (skb);
 405
 406        return NETDEV_TX_OK;
 407}
 408
 409/* The typical workload of the driver:
 410   Handle the network interface interrupts. */
 411static irqreturn_t net_interrupt(int irq, void *dev_id)
 412{
 413        struct net_device *dev = dev_id;
 414        struct net_local *lp;
 415        int ioaddr, status;
 416
 417        if (dev == NULL) {
 418                printk ("net_interrupt(): irq %d for unknown device.\n", irq);
 419                return IRQ_NONE;
 420        }
 421
 422        ioaddr = dev->base_addr;
 423        lp = netdev_priv(dev);
 424
 425        /* we MUST read all the events out of the ISQ, otherwise we'll never
 426           get interrupted again.  As a consequence, we can't have any limit
 427           on the number of times we loop in the interrupt handler.  The
 428           hardware guarantees that eventually we'll run out of events.  Of
 429           course, if you're on a slow machine, and packets are arriving
 430           faster than you can read them off, you're screwed.  Hasta la
 431           vista, baby!  */
 432        while ((status = swab16(nubus_readw(dev->base_addr + ISQ_PORT)))) {
 433                if (net_debug > 4)printk("%s: event=%04x\n", dev->name, status);
 434                switch(status & ISQ_EVENT_MASK) {
 435                case ISQ_RECEIVER_EVENT:
 436                        /* Got a packet(s). */
 437                        net_rx(dev);
 438                        break;
 439                case ISQ_TRANSMITTER_EVENT:
 440                        dev->stats.tx_packets++;
 441                        netif_wake_queue(dev);
 442                        if ((status & TX_OK) == 0)
 443                                dev->stats.tx_errors++;
 444                        if (status & TX_LOST_CRS)
 445                                dev->stats.tx_carrier_errors++;
 446                        if (status & TX_SQE_ERROR)
 447                                dev->stats.tx_heartbeat_errors++;
 448                        if (status & TX_LATE_COL)
 449                                dev->stats.tx_window_errors++;
 450                        if (status & TX_16_COL)
 451                                dev->stats.tx_aborted_errors++;
 452                        break;
 453                case ISQ_BUFFER_EVENT:
 454                        if (status & READY_FOR_TX) {
 455                                /* we tried to transmit a packet earlier,
 456                                   but inexplicably ran out of buffers.
 457                                   That shouldn't happen since we only ever
 458                                   load one packet.  Shrug.  Do the right
 459                                   thing anyway. */
 460                                netif_wake_queue(dev);
 461                        }
 462                        if (status & TX_UNDERRUN) {
 463                                if (net_debug > 0) printk("%s: transmit underrun\n", dev->name);
 464                                lp->send_underrun++;
 465                                if (lp->send_underrun == 3) lp->send_cmd = TX_AFTER_381;
 466                                else if (lp->send_underrun == 6) lp->send_cmd = TX_AFTER_ALL;
 467                        }
 468                        break;
 469                case ISQ_RX_MISS_EVENT:
 470                        dev->stats.rx_missed_errors += (status >> 6);
 471                        break;
 472                case ISQ_TX_COL_EVENT:
 473                        dev->stats.collisions += (status >> 6);
 474                        break;
 475                }
 476        }
 477        return IRQ_HANDLED;
 478}
 479
 480/* We have a good packet(s), get it/them out of the buffers. */
 481static void
 482net_rx(struct net_device *dev)
 483{
 484        struct sk_buff *skb;
 485        int status, length;
 486
 487        status = readreg(dev, PP_RxStatus);
 488        if ((status & RX_OK) == 0) {
 489                dev->stats.rx_errors++;
 490                if (status & RX_RUNT)
 491                                dev->stats.rx_length_errors++;
 492                if (status & RX_EXTRA_DATA)
 493                                dev->stats.rx_length_errors++;
 494                if ((status & RX_CRC_ERROR) &&
 495                    !(status & (RX_EXTRA_DATA|RX_RUNT)))
 496                        /* per str 172 */
 497                        dev->stats.rx_crc_errors++;
 498                if (status & RX_DRIBBLE)
 499                                dev->stats.rx_frame_errors++;
 500                return;
 501        }
 502
 503        length = readreg(dev, PP_RxLength);
 504        /* Malloc up new buffer. */
 505        skb = alloc_skb(length, GFP_ATOMIC);
 506        if (skb == NULL) {
 507                printk("%s: Memory squeeze, dropping packet.\n", dev->name);
 508                dev->stats.rx_dropped++;
 509                return;
 510        }
 511        skb_put(skb, length);
 512
 513        skb_copy_to_linear_data(skb, (void *)(dev->mem_start + PP_RxFrame),
 514                                length);
 515
 516        if (net_debug > 3)printk("%s: received %d byte packet of type %x\n",
 517                                 dev->name, length,
 518                                 (skb->data[ETH_ALEN+ETH_ALEN] << 8)
 519                                 | skb->data[ETH_ALEN+ETH_ALEN+1]);
 520
 521        skb->protocol=eth_type_trans(skb,dev);
 522        netif_rx(skb);
 523        dev->stats.rx_packets++;
 524        dev->stats.rx_bytes += length;
 525}
 526
 527/* The inverse routine to net_open(). */
 528static int
 529net_close(struct net_device *dev)
 530{
 531
 532        writereg(dev, PP_RxCFG, 0);
 533        writereg(dev, PP_TxCFG, 0);
 534        writereg(dev, PP_BufCFG, 0);
 535        writereg(dev, PP_BusCTL, 0);
 536
 537        netif_stop_queue(dev);
 538
 539        free_irq(dev->irq, dev);
 540
 541        /* Update the statistics here. */
 542
 543        return 0;
 544
 545}
 546
 547/* Get the current statistics.  This may be called with the card open or
 548   closed. */
 549static struct net_device_stats *
 550net_get_stats(struct net_device *dev)
 551{
 552        unsigned long flags;
 553
 554        local_irq_save(flags);
 555        /* Update the statistics from the device registers. */
 556        dev->stats.rx_missed_errors += (readreg(dev, PP_RxMiss) >> 6);
 557        dev->stats.collisions += (readreg(dev, PP_TxCol) >> 6);
 558        local_irq_restore(flags);
 559
 560        return &dev->stats;
 561}
 562
 563static void set_multicast_list(struct net_device *dev)
 564{
 565        struct net_local *lp = netdev_priv(dev);
 566
 567        if(dev->flags&IFF_PROMISC)
 568        {
 569                lp->rx_mode = RX_ALL_ACCEPT;
 570        } else if ((dev->flags & IFF_ALLMULTI) || !netdev_mc_empty(dev)) {
 571                /* The multicast-accept list is initialized to accept-all, and we
 572                   rely on higher-level filtering for now. */
 573                lp->rx_mode = RX_MULTCAST_ACCEPT;
 574        }
 575        else
 576                lp->rx_mode = 0;
 577
 578        writereg(dev, PP_RxCTL, DEF_RX_ACCEPT | lp->rx_mode);
 579
 580        /* in promiscuous mode, we accept errored packets, so we have to enable interrupts on them also */
 581        writereg(dev, PP_RxCFG, lp->curr_rx_cfg |
 582             (lp->rx_mode == RX_ALL_ACCEPT? (RX_CRC_ERROR_ENBL|RX_RUNT_ENBL|RX_EXTRA_DATA_ENBL) : 0));
 583}
 584
 585
 586static int set_mac_address(struct net_device *dev, void *addr)
 587{
 588        struct sockaddr *saddr = addr;
 589        int i;
 590
 591        if (!is_valid_ether_addr(saddr->sa_data))
 592                return -EADDRNOTAVAIL;
 593
 594        memcpy(dev->dev_addr, saddr->sa_data, ETH_ALEN);
 595        printk("%s: Setting MAC address to %pM\n", dev->name, dev->dev_addr);
 596
 597        /* set the Ethernet address */
 598        for (i=0; i < ETH_ALEN/2; i++)
 599                writereg(dev, PP_IA+i*2, dev->dev_addr[i*2] | (dev->dev_addr[i*2+1] << 8));
 600
 601        return 0;
 602}
 603
 604#ifdef MODULE
 605
 606static struct net_device *dev_cs89x0;
 607static int debug;
 608
 609module_param(debug, int, 0);
 610MODULE_PARM_DESC(debug, "CS89[02]0 debug level (0-5)");
 611MODULE_LICENSE("GPL");
 612
 613int __init
 614init_module(void)
 615{
 616        net_debug = debug;
 617        dev_cs89x0 = mac89x0_probe(-1);
 618        if (IS_ERR(dev_cs89x0)) {
 619                printk(KERN_WARNING "mac89x0.c: No card found\n");
 620                return PTR_ERR(dev_cs89x0);
 621        }
 622        return 0;
 623}
 624
 625void
 626cleanup_module(void)
 627{
 628        unregister_netdev(dev_cs89x0);
 629        nubus_writew(0, dev_cs89x0->base_addr + ADD_PORT);
 630        free_netdev(dev_cs89x0);
 631}
 632#endif /* MODULE */
 633