root/drivers/net/3c503.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. el2_probe
  2. el2_pio_probe
  3. el2_probe1
  4. el2_open
  5. el2_close
  6. el2_reset_8390
  7. el2_init_card
  8. el2_block_output
  9. el2_get_8390_hdr
  10. el2_block_input
  11. init_module
  12. cleanup_module

   1 /* 3c503.c: A shared-memory NS8390 ethernet driver for linux. */
   2 /*
   3     Written 1992-94 by Donald Becker.
   4 
   5     Copyright 1993 United States Government as represented by the
   6     Director, National Security Agency.  This software may be used and
   7     distributed according to the terms of the GNU Public License,
   8     incorporated herein by reference.
   9 
  10     The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
  11     Center of Excellence in Space Data and Information Sciences
  12        Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
  13 
  14     This driver should work with the 3c503 and 3c503/16.  It should be used
  15     in shared memory mode for best performance, although it may also work
  16     in programmed-I/O mode.
  17 
  18     Sources:
  19     EtherLink II Technical Reference Guide,
  20     3Com Corporation, 5400 Bayfront Plaza, Santa Clara CA 95052-8145
  21     
  22     The Crynwr 3c503 packet driver.
  23 */
  24 
  25 static const char *version =
  26     "3c503.c:v1.10 9/23/93  Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
  27 
  28 
  29 #ifdef MODULE
  30 #include <linux/module.h>
  31 #include <linux/version.h>
  32 #endif
  33 
  34 #include <linux/kernel.h>
  35 #include <linux/sched.h>
  36 #include <linux/errno.h>
  37 #include <linux/string.h>
  38 #include <linux/delay.h>
  39 #include <asm/io.h>
  40 #include <asm/system.h>
  41 
  42 #include <linux/netdevice.h>
  43 #include <linux/etherdevice.h>
  44 
  45 #include "8390.h"
  46 #include "3c503.h"
  47 
  48 
  49 int el2_probe(struct device *dev);
  50 int el2_pio_probe(struct device *dev);
  51 int el2_probe1(struct device *dev, int ioaddr);
  52 
  53 /* A zero-terminated list of I/O addresses to be probed in PIO mode. */
  54 static unsigned int netcard_portlist[] =
  55         { 0x300,0x310,0x330,0x350,0x250,0x280,0x2a0,0x2e0,0};
  56 
  57 #define EL2_IO_EXTENT   16
  58 
  59 #ifdef HAVE_DEVLIST
  60 /* The 3c503 uses two entries, one for the safe memory-mapped probe and
  61    the other for the typical I/O probe. */
  62 struct netdev_entry el2_drv =
  63 {"3c503", el2_probe, EL1_IO_EXTENT, 0};
  64 struct netdev_entry el2pio_drv =
  65 {"3c503pio", el2_pioprobe1, EL1_IO_EXTENT, netcard_portlist};
  66 #endif
  67 
  68 static int el2_open(struct device *dev);
  69 static int el2_close(struct device *dev);
  70 static void el2_reset_8390(struct device *dev);
  71 static void el2_init_card(struct device *dev);
  72 static void el2_block_output(struct device *dev, int count,
  73                              const unsigned char *buf, const start_page);
  74 static void el2_block_input(struct device *dev, int count, struct sk_buff *skb,
  75                            int ring_offset);
  76 static void el2_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr,
  77                          int ring_page);
  78 
  79 
  80 /* This routine probes for a memory-mapped 3c503 board by looking for
  81    the "location register" at the end of the jumpered boot PROM space.
  82    This works even if a PROM isn't there.
  83 
  84    If the ethercard isn't found there is an optional probe for
  85    ethercard jumpered to programmed-I/O mode.
  86    */
  87 int
  88 el2_probe(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
  89 {
  90     int *addr, addrs[] = { 0xddffe, 0xd9ffe, 0xcdffe, 0xc9ffe, 0};
  91     int base_addr = dev->base_addr;
  92 
  93     if (base_addr > 0x1ff)      /* Check a single specified location. */
  94         return el2_probe1(dev, base_addr);
  95     else if (base_addr != 0)            /* Don't probe at all. */
  96         return ENXIO;
  97 
  98     for (addr = addrs; *addr; addr++) {
  99         int i;
 100         unsigned int base_bits = readb(*addr);
 101         /* Find first set bit. */
 102         for(i = 7; i >= 0; i--, base_bits >>= 1)
 103             if (base_bits & 0x1)
 104                 break;
 105         if (base_bits != 1)
 106             continue;
 107         if (check_region(netcard_portlist[i], EL2_IO_EXTENT))
 108             continue;
 109         if (el2_probe1(dev, netcard_portlist[i]) == 0)
 110             return 0;
 111     }
 112 #if ! defined(no_probe_nonshared_memory) && ! defined (HAVE_DEVLIST)
 113     return el2_pio_probe(dev);
 114 #else
 115     return ENODEV;
 116 #endif
 117 }
 118 
 119 #ifndef HAVE_DEVLIST
 120 /*  Try all of the locations that aren't obviously empty.  This touches
 121     a lot of locations, and is much riskier than the code above. */
 122 int
 123 el2_pio_probe(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 124 {
 125     int i;
 126     int base_addr = dev ? dev->base_addr : 0;
 127 
 128     if (base_addr > 0x1ff)      /* Check a single specified location. */
 129         return el2_probe1(dev, base_addr);
 130     else if (base_addr != 0)    /* Don't probe at all. */
 131         return ENXIO;
 132 
 133     for (i = 0; netcard_portlist[i]; i++) {
 134         int ioaddr = netcard_portlist[i];
 135         if (check_region(ioaddr, EL2_IO_EXTENT))
 136             continue;
 137         if (el2_probe1(dev, ioaddr) == 0)
 138             return 0;
 139     }
 140 
 141     return ENODEV;
 142 }
 143 #endif
 144 
 145 /* Probe for the Etherlink II card at I/O port base IOADDR,
 146    returning non-zero on success.  If found, set the station
 147    address and memory parameters in DEVICE. */
 148 int
 149 el2_probe1(struct device *dev, int ioaddr)
     /* [previous][next][first][last][top][bottom][index][help] */
 150 {
 151     int i, iobase_reg, membase_reg, saved_406;
 152     static unsigned version_printed = 0;
 153     unsigned long vendor_id;
 154 
 155     /* Reset and/or avoid any lurking NE2000 */
 156     if (inb(ioaddr + 0x408) == 0xff) {
 157         udelay(1000);
 158         return ENODEV;
 159     }
 160 
 161     /* We verify that it's a 3C503 board by checking the first three octets
 162        of its ethernet address. */
 163     iobase_reg = inb(ioaddr+0x403);
 164     membase_reg = inb(ioaddr+0x404);
 165     /* ASIC location registers should be 0 or have only a single bit set. */
 166     if (   (iobase_reg  & (iobase_reg - 1))
 167         || (membase_reg & (membase_reg - 1))) {
 168         return ENODEV;
 169     }
 170     saved_406 = inb_p(ioaddr + 0x406);
 171     outb_p(ECNTRL_RESET|ECNTRL_THIN, ioaddr + 0x406); /* Reset it... */
 172     outb_p(ECNTRL_THIN, ioaddr + 0x406);
 173     /* Map the station addr PROM into the lower I/O ports. We now check
 174        for both the old and new 3Com prefix */
 175     outb(ECNTRL_SAPROM|ECNTRL_THIN, ioaddr + 0x406);
 176     vendor_id = inb(ioaddr)*0x10000 + inb(ioaddr + 1)*0x100 + inb(ioaddr + 2);
 177     if ((vendor_id != OLD_3COM_ID) && (vendor_id != NEW_3COM_ID)) {
 178         /* Restore the register we frobbed. */
 179         outb(saved_406, ioaddr + 0x406);
 180         return ENODEV;
 181     }
 182 
 183     request_region(ioaddr, EL2_IO_EXTENT,"3c503");
 184 
 185     if (dev == NULL)
 186         dev = init_etherdev(0, sizeof(struct ei_device));
 187 
 188     if (ei_debug  &&  version_printed++ == 0)
 189         printk(version);
 190 
 191     dev->base_addr = ioaddr;
 192     ethdev_init(dev);
 193 
 194     printk("%s: 3c503 at %#3x,", dev->name, ioaddr);
 195 
 196     /* Retrieve and print the ethernet address. */
 197     for (i = 0; i < 6; i++)
 198         printk(" %2.2x", dev->dev_addr[i] = inb(ioaddr + i));
 199 
 200     /* Map the 8390 back into the window. */
 201     outb(ECNTRL_THIN, ioaddr + 0x406);
 202 
 203     /* Probe for, turn on and clear the board's shared memory. */
 204     if (ei_debug > 2) printk(" memory jumpers %2.2x ", membase_reg);
 205     outb(EGACFR_NORM, ioaddr + 0x405);  /* Enable RAM */
 206 
 207     /* This should be probed for (or set via an ioctl()) at run-time.
 208        Right now we use a sleazy hack to pass in the interface number
 209        at boot-time via the low bits of the mem_end field.  That value is
 210        unused, and the low bits would be discarded even if it was used. */
 211 #if defined(EI8390_THICK) || defined(EL2_AUI)
 212     ei_status.interface_num = 1;
 213 #else
 214     ei_status.interface_num = dev->mem_end & 0xf;
 215 #endif
 216 
 217     if ((membase_reg & 0xf0) == 0) {
 218         dev->mem_start = 0;
 219     } else {
 220         dev->mem_start = ((membase_reg & 0xc0) ? 0xD8000 : 0xC8000) +
 221             ((membase_reg & 0xA0) ? 0x4000 : 0);
 222 
 223 #define EL2_MEMSIZE (EL2SM_STOP_PG - EL2SM_START_PG)*256
 224 #ifdef EL2MEMTEST
 225         /* This has never found an error, but someone might care. */
 226         {                       /* Check the card's memory. */
 227             unsigned long mem_base = dev->mem_start;
 228             unsigned int test_val = 0xbbadf00d;
 229             writel(0xba5eba5e, mem_base);
 230             for (i = sizeof(test_val); i < EL2_MEMSIZE; i+=sizeof(test_val)) {
 231                 writel(test_val, mem_base + i);
 232                 if (readl(mem_base) != 0xba5eba5e
 233                     || readl(mem_base + i) != test_val) {
 234                     printk(" memory failure or memory address conflict.\n");
 235                     dev->mem_start = 0;
 236                     break;
 237                 }
 238                 test_val += 0x55555555;
 239                 writel(0, mem_base + i);
 240             }
 241         }
 242 #endif  /* EL2MEMTEST */
 243         /* Divide the on-board memory into a single maximum-sized transmit
 244            (double-sized for ping-pong transmit) buffer at the base, and
 245            use the rest as a receive ring. */
 246         dev->mem_end = dev->rmem_end = dev->mem_start + EL2_MEMSIZE;
 247         dev->rmem_start = TX_PAGES*256 + dev->mem_start;
 248     }
 249 
 250     /* Finish setting the board's parameters. */
 251     ei_status.name = "3C503";
 252     ei_status.tx_start_page = EL2SM_START_PG;
 253     ei_status.rx_start_page = EL2SM_START_PG + TX_PAGES;
 254     ei_status.stop_page = EL2SM_STOP_PG;
 255     ei_status.reset_8390 = &el2_reset_8390;
 256     ei_status.get_8390_hdr = &el2_get_8390_hdr;
 257     ei_status.block_input = &el2_block_input;
 258     ei_status.block_output = &el2_block_output;
 259 
 260     if (dev->irq == 2)
 261         dev->irq = 9;
 262     else if (dev->irq > 5 && dev->irq != 9) {
 263         printk("\n3c503: configured interrupt %d invalid, using autoIRQ.\n",
 264                dev->irq);
 265         dev->irq = 0;
 266     }
 267 
 268     ei_status.saved_irq = dev->irq;
 269 
 270     dev->start = 0;
 271     dev->open = &el2_open;
 272     dev->stop = &el2_close;
 273 
 274     if (dev->mem_start)
 275         printk("\n%s: %s with shared memory at %#6lx-%#6lx.\n",
 276                dev->name, ei_status.name, dev->mem_start, dev->mem_end-1);
 277     else
 278         printk("\n%s: %s using programmed I/O (REJUMPER for SHARED MEMORY).\n",
 279                dev->name, ei_status.name);
 280 
 281     if (ei_debug > 1)
 282         printk(version);
 283 
 284     return 0;
 285 }
 286 
 287 static int
 288 el2_open(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 289 {
 290 
 291     if (dev->irq < 2) {
 292         int irqlist[] = {5, 9, 3, 4, 0};
 293         int *irqp = irqlist;
 294 
 295         outb(EGACFR_NORM, E33G_GACFR);  /* Enable RAM and interrupts. */
 296         do {
 297             if (request_irq (*irqp, NULL, 0, "bogus") != -EBUSY) {
 298                 /* Twinkle the interrupt, and check if it's seen. */
 299                 autoirq_setup(0);
 300                 outb_p(0x04 << ((*irqp == 9) ? 2 : *irqp), E33G_IDCFR);
 301                 outb_p(0x00, E33G_IDCFR);
 302                 if (*irqp == autoirq_report(0)   /* It's a good IRQ line! */
 303                     && request_irq (dev->irq = *irqp, &ei_interrupt, 0, "3c503") == 0)
 304                     break;
 305             }
 306         } while (*++irqp);
 307         if (*irqp == 0) {
 308             outb(EGACFR_IRQOFF, E33G_GACFR);    /* disable interrupts. */
 309             return -EAGAIN;
 310         }
 311     } else {
 312         if (request_irq(dev->irq, &ei_interrupt, 0, "3c503")) {
 313             return -EAGAIN;
 314         }
 315     }
 316     el2_init_card(dev);
 317     return ei_open(dev);
 318 }
 319 
 320 static int
 321 el2_close(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 322 {
 323     free_irq(dev->irq);
 324     dev->irq = ei_status.saved_irq;
 325     irq2dev_map[dev->irq] = NULL;
 326     outb(EGACFR_IRQOFF, E33G_GACFR);    /* disable interrupts. */
 327 
 328     NS8390_init(dev, 0);
 329     dev->start = 0;
 330 
 331     return 0;
 332 }
 333 
 334 /* This is called whenever we have a unrecoverable failure:
 335        transmit timeout
 336        Bad ring buffer packet header
 337  */
 338 static void
 339 el2_reset_8390(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 340 {
 341     if (ei_debug > 1) {
 342         printk("%s: Resetting the 3c503 board...", dev->name);
 343         printk("%#lx=%#02x %#lx=%#02x %#lx=%#02x...", E33G_IDCFR, inb(E33G_IDCFR),
 344                E33G_CNTRL, inb(E33G_CNTRL), E33G_GACFR, inb(E33G_GACFR));
 345     }
 346     outb_p(ECNTRL_RESET|ECNTRL_THIN, E33G_CNTRL);
 347     ei_status.txing = 0;
 348     outb_p(ei_status.interface_num==0 ? ECNTRL_THIN : ECNTRL_AUI, E33G_CNTRL);
 349     el2_init_card(dev);
 350     if (ei_debug > 1) printk("done\n");
 351 }
 352 
 353 /* Initialize the 3c503 GA registers after a reset. */
 354 static void
 355 el2_init_card(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 356 {
 357     /* Unmap the station PROM and select the DIX or BNC connector. */
 358     outb_p(ei_status.interface_num==0 ? ECNTRL_THIN : ECNTRL_AUI, E33G_CNTRL);
 359 
 360     /* Set ASIC copy of rx's first and last+1 buffer pages */
 361     /* These must be the same as in the 8390. */
 362     outb(ei_status.rx_start_page, E33G_STARTPG);
 363     outb(ei_status.stop_page,  E33G_STOPPG);
 364 
 365     /* Point the vector pointer registers somewhere ?harmless?. */
 366     outb(0xff, E33G_VP2);       /* Point at the ROM restart location 0xffff0 */
 367     outb(0xff, E33G_VP1);
 368     outb(0x00, E33G_VP0);
 369     /* Turn off all interrupts until we're opened. */
 370     outb_p(0x00,  dev->base_addr + EN0_IMR);
 371     /* Enable IRQs iff started. */
 372     outb(EGACFR_NORM, E33G_GACFR);
 373 
 374     /* Set the interrupt line. */
 375     outb_p((0x04 << (dev->irq == 9 ? 2 : dev->irq)), E33G_IDCFR);
 376     outb_p(8, E33G_DRQCNT);             /* Set burst size to 8 */
 377     outb_p(0x20, E33G_DMAAH);   /* Put a valid addr in the GA DMA */
 378     outb_p(0x00, E33G_DMAAL);
 379     return;                     /* We always succeed */
 380 }
 381 
 382 /* Either use the shared memory (if enabled on the board) or put the packet
 383    out through the ASIC FIFO.  The latter is probably much slower. */
 384 static void
 385 el2_block_output(struct device *dev, int count,
     /* [previous][next][first][last][top][bottom][index][help] */
 386                  const unsigned char *buf, const start_page)
 387 {
 388     int i;                              /* Buffer index */
 389     int boguscount = 0;         /* timeout counter */
 390 
 391     /* This should really be set with during an open(). */
 392     outb(EGACFR_NORM, E33G_GACFR);      /* Enable RAM and interrupts. */
 393 
 394     if (dev->mem_start) {       /* Shared memory transfer */
 395         unsigned long dest_addr = dev->mem_start +
 396             ((start_page - ei_status.tx_start_page) << 8);
 397         memcpy_toio(dest_addr, buf, count);
 398         return;
 399     }
 400     /* No shared memory, put the packet out the slow way. */
 401     /* Set up then start the internal memory transfer to Tx Start Page */
 402     outb(0x00, E33G_DMAAL);
 403     outb_p(start_page, E33G_DMAAH);
 404     outb_p((ei_status.interface_num ? ECNTRL_AUI : ECNTRL_THIN ) | ECNTRL_OUTPUT
 405            | ECNTRL_START, E33G_CNTRL);
 406 
 407     /* This is the byte copy loop: it should probably be tuned for
 408        speed once everything is working.  I think it is possible
 409        to output 8 bytes between each check of the status bit. */
 410     for(i = 0; i < count; i++) {
 411         if (i % 8 == 0)
 412             while ((inb(E33G_STATUS) & ESTAT_DPRDY) == 0)
 413                 if (++boguscount > (i<<3) + 32) {
 414                     printk("%s: FIFO blocked in el2_block_output (at %d of %d, bc=%d).\n",
 415                            dev->name, i, count, boguscount);
 416                     return;
 417                 }
 418         outb(buf[i], E33G_FIFOH);
 419     }
 420     outb_p(ei_status.interface_num==0 ? ECNTRL_THIN : ECNTRL_AUI, E33G_CNTRL);
 421     return;
 422 }
 423 
 424 /* Read the 4 byte, page aligned 8390 specific header. */
 425 static void
 426 el2_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
     /* [previous][next][first][last][top][bottom][index][help] */
 427 {
 428     unsigned int i;
 429     unsigned long hdr_start = dev->mem_start + ((ring_page - EL2SM_START_PG)<<8);
 430 
 431     if (dev->mem_start) {       /* Use the shared memory. */
 432         memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
 433         return;
 434     }
 435 
 436     /* No shared memory, use programmed I/O. Ugh. */
 437     outb(0, E33G_DMAAL);
 438     outb_p(ring_page & 0xff, E33G_DMAAH);
 439     outb_p((ei_status.interface_num == 0 ? ECNTRL_THIN : ECNTRL_AUI) | ECNTRL_INPUT
 440            | ECNTRL_START, E33G_CNTRL);
 441 
 442     /* Header is less than 8 bytes, so we can ignore the FIFO. */
 443     for(i = 0; i < sizeof(struct e8390_pkt_hdr); i++)
 444         ((char *)(hdr))[i] = inb_p(E33G_FIFOH);
 445 
 446     outb_p(ei_status.interface_num == 0 ? ECNTRL_THIN : ECNTRL_AUI, E33G_CNTRL);
 447 }
 448 
 449 /* Returns the new ring pointer. */
 450 static void
 451 el2_block_input(struct device *dev, int count, struct sk_buff *skb, int ring_offset)
     /* [previous][next][first][last][top][bottom][index][help] */
 452 {
 453     int boguscount = 0;
 454     int end_of_ring = dev->rmem_end;
 455     unsigned int i;
 456 
 457     /* Maybe enable shared memory just be to be safe... nahh.*/
 458     if (dev->mem_start) {       /* Use the shared memory. */
 459         ring_offset -= (EL2SM_START_PG<<8);
 460         if (dev->mem_start + ring_offset + count > end_of_ring) {
 461             /* We must wrap the input move. */
 462             int semi_count = end_of_ring - (dev->mem_start + ring_offset);
 463             memcpy_fromio(skb->data, dev->mem_start + ring_offset, semi_count);
 464             count -= semi_count;
 465             memcpy_fromio(skb->data + semi_count, dev->rmem_start, count);
 466         } else {
 467                 /* Packet is in one chunk -- we can copy + cksum. */
 468                 eth_io_copy_and_sum(skb, dev->mem_start + ring_offset, count, 0);
 469         }
 470         return;
 471     }
 472     /* No shared memory, use programmed I/O. */
 473     outb(ring_offset & 0xff, E33G_DMAAL);
 474     outb_p((ring_offset >> 8) & 0xff, E33G_DMAAH);
 475     outb_p((ei_status.interface_num == 0 ? ECNTRL_THIN : ECNTRL_AUI) | ECNTRL_INPUT
 476            | ECNTRL_START, E33G_CNTRL);
 477 
 478     /* This is the byte copy loop: it should probably be tuned for
 479        speed once everything is working. */
 480     for(i = 0; i < count; i++) {
 481         if (i % 8 == 0)
 482             while ((inb(E33G_STATUS) & ESTAT_DPRDY) == 0)
 483                 if (++boguscount > (i<<3) + 32) {
 484                     printk("%s: FIFO blocked in el2_block_input() (at %d of %d, bc=%d).\n",
 485                            dev->name, i, count, boguscount);
 486                     boguscount = 0;
 487                     break;
 488                 }
 489         (skb->data)[i] = inb_p(E33G_FIFOH);
 490     }
 491     outb_p(ei_status.interface_num == 0 ? ECNTRL_THIN : ECNTRL_AUI, E33G_CNTRL);
 492 }
 493 #ifdef MODULE
 494 char kernel_version[] = UTS_RELEASE;
 495 static struct device el2_drv =
 496 {"3c503", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, el2_probe };
 497        
 498 static struct device el2pio_drv =
 499 {"3c503pio", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, el2_pio_probe };
 500 
 501 int io = 0x300;
 502 int irq = 0;
 503 
 504 static int no_pio = 1;
 505 int init_module(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 506 {
 507         int rc1, rc2;
 508         el2_drv.base_addr = io;
 509         el2_drv.irq       = irq;
 510         el2pio_drv.base_addr = io;
 511         el2pio_drv.irq       = irq;
 512 
 513         if (io == 0)
 514             printk("3c503: You should not use auto-probing with insmod!\n");
 515 
 516         rc2 = 0;
 517         no_pio = 1;
 518         rc1 = register_netdev(&el2_drv);
 519         if (rc1 != 0) {
 520             rc2 = register_netdev(&el2pio_drv);
 521             no_pio = 0;
 522         }
 523 
 524         if (rc1 != 0 && rc2 != 0)
 525                 return -EIO;
 526         return 0;
 527 }
 528 
 529 void
 530 cleanup_module(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 531 {
 532         if (MOD_IN_USE)
 533                 printk("3c503: device busy, remove delayed\n");
 534         else {
 535             int ioaddr;
 536 
 537             if (no_pio) {
 538                 ioaddr = el2_drv.base_addr;
 539                 unregister_netdev(&el2_drv);
 540             } else {
 541                 ioaddr = el2pio_drv.base_addr;
 542                 unregister_netdev(&el2pio_drv);
 543             }
 544 
 545             /* If we don't do this, we can't re-insmod it later. */
 546             release_region(ioaddr, EL2_IO_EXTENT);
 547 
 548         }
 549 }
 550 #endif /* MODULE */
 551 
 552 /*
 553  * Local variables:
 554  *  version-control: t
 555  *  kept-new-versions: 5
 556  *  c-indent-level: 4
 557  * End:
 558  */

/* [previous][next][first][last][top][bottom][index][help] */