root/net/inet/3c509.c

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

DEFINITIONS

This source file includes following definitions.
  1. el3_probe
  2. read_eeprom
  3. el3_init
  4. el3_open
  5. el3_start_xmit
  6. el3_interrupt
  7. el3_get_stats
  8. update_stats
  9. printk_stats
  10. el3_rx
  11. el3_close

   1 /* el3.c: An 3c509 EtherLink3 ethernet driver for linux. */
   2 /*
   3     Written 1993 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     This driver should work with the 3Com EtherLinkIII series.
  11 
  12     The author may be reached as becker@super.org or
  13     C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715
  14 */
  15 
  16 static char *version = "el3.c: v0.02 8/13/93 becker@super.org\n";
  17 
  18 #include <linux/config.h>
  19 #include <linux/kernel.h>
  20 #include <linux/sched.h>
  21 #include <linux/string.h>
  22 #include <linux/interrupt.h>
  23 #include <linux/ptrace.h>
  24 #include <linux/errno.h>
  25 #include <linux/in.h>
  26 /*#include <asm/system.h>*/
  27 #include <asm/io.h>
  28 #ifndef port_read
  29 #include "iow.h"
  30 #endif
  31 
  32 #include "dev.h"
  33 #include "eth.h"
  34 #include "skbuff.h"
  35 #include "arp.h"
  36 
  37 /* From auto_irq.c, should be in a *.h file. */
  38 extern void autoirq_setup(int waittime);
  39 extern int autoirq_report(int waittime);
  40 extern struct device *irq2dev_map[16];
  41 
  42 /* These should be in <asm/io.h>. */
  43 #define port_read_l(port,buf,nr) \
  44 __asm__("cld;rep;insl": :"d" (port),"D" (buf),"c" (nr):"cx","di")
  45 #define port_write_l(port,buf,nr) \
  46 __asm__("cld;rep;outsl": :"d" (port),"S" (buf),"c" (nr):"cx","si")
  47 
  48 
  49 #ifdef EL3_DEBUG
  50 int el3_debug = EL3_DEBUG;
  51 #else
  52 int el3_debug = 1;
  53 #endif
  54 
  55 /* Offsets from base I/O address. */
  56 #define EL3_DATA 0x00
  57 #define EL3_CMD 0x0e
  58 #define EL3_STATUS 0x0e
  59 #define ID_PORT 0x100
  60 #define  EEPROM_READ 0x80
  61 
  62 /* Register window 1 offsets, used in normal operation. */
  63 #define TX_FREE 0x0C
  64 #define TX_STATUS 0x0B
  65 #define TX_FIFO 0x00
  66 #define RX_STATUS 0x08
  67 #define RX_FIFO 0x00
  68 
  69 struct el3_private {
  70     struct enet_statistics stats;
  71 };
  72 
  73 static int el3_init(struct device *dev);
  74 static int read_eeprom(int index);
  75 static int el3_open(struct device *dev);
  76 static int el3_start_xmit(struct sk_buff *skb, struct device *dev);
  77 static void el3_interrupt(int reg_ptr);
  78 static void update_stats(int addr, struct device *dev);
  79 static struct enet_statistics *el3_get_stats(struct device *dev);
  80 static int el3_rx(struct device *dev);
  81 static int el3_close(struct device *dev);
  82 
  83 
  84 
  85 int el3_probe(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
  86 {
  87     short lrs_state = 0xff, i;
  88     unsigned short iobase = 0;
  89 
  90     /* Send the ID sequence to the ID_PORT. */
  91     outb(0x00, ID_PORT);
  92     outb(0x00, ID_PORT);
  93     for(i = 0; i < 255; i++) {
  94         outb(lrs_state, ID_PORT);
  95         lrs_state <<= 1;
  96         lrs_state = lrs_state & 0x100 ? lrs_state ^ 0xcf : lrs_state;
  97     }
  98 
  99     /* The current Space.c initialization makes it difficult to have more
 100        than one adaptor initialized.  Send me email if you have a need for
 101        multiple adaptors. */
 102 
 103     /* Read in EEPROM data.
 104        Only the highest address board will stay on-line. */
 105 
 106     {
 107         short *phys_addr = (short *)dev->dev_addr;
 108         phys_addr[0] = htons(read_eeprom(0));
 109         if (phys_addr[0] != 0x6000)
 110             return 1;
 111         phys_addr[1] = htons(read_eeprom(1));
 112         phys_addr[2] = htons(read_eeprom(2));
 113     }
 114 
 115     iobase = read_eeprom(8);
 116     dev->irq = read_eeprom(9) >> 12;
 117 
 118     /* Activate the adaptor at the EEPROM location (if set), else 0x320. */
 119 
 120     if (iobase == 0x0000) {
 121         dev->base_addr = 0x320;
 122         outb(0xf2, ID_PORT);
 123     } else {
 124         dev->base_addr = 0x200 + ((iobase & 0x1f) << 4);
 125         outb(0xff, ID_PORT);
 126     }
 127 
 128     outw(0x0800, dev->base_addr + EL3_CMD);      /* Window 0. */
 129     printk("%s: 3c509 at %#3.3x  key %4.4x iobase %4.4x.\n",
 130            dev->name, dev->base_addr, inw(dev->base_addr), iobase);
 131 
 132     if (inw(dev->base_addr) == 0x6d50) {
 133         el3_init(dev);
 134         return 0;
 135     } else
 136         return -ENODEV;
 137 }
 138 
 139 static int
 140 read_eeprom(int index)
     /* [previous][next][first][last][top][bottom][index][help] */
 141 {
 142     int timer, bit, word = 0;
 143     
 144     /* Issue read command, and pause for at least 162 us. for it to complete.
 145        Assume extra-fast 16Mhz bus. */
 146     outb(EEPROM_READ + index, ID_PORT);
 147 
 148     for (timer = 0; timer < 162*4 + 400; timer++)
 149         SLOW_DOWN_IO;
 150 
 151     for (bit = 15; bit >= 0; bit--)
 152         word = (word << 1) + (inb(ID_PORT) & 0x01);
 153         
 154     if (el3_debug > 3)
 155         printk("  3c509 EEPROM word %d %#4.4x.\n", index, word);
 156 
 157     return word;
 158 }
 159 
 160 static int
 161 el3_init(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 162 {
 163     struct el3_private *lp;
 164     int ioaddr = dev->base_addr;
 165     int i;
 166 
 167     printk("%s: EL3 at %#3x, address", dev->name, ioaddr);
 168 
 169     /* Read in the station address. */
 170     for (i = 0; i < 6; i++)
 171         printk(" %2.2x", dev->dev_addr[i]);
 172     printk(", IRQ %d.\n", dev->irq);
 173 
 174     /* Make up a EL3-specific-data structure. */
 175     dev->priv = kmalloc(sizeof(struct el3_private), GFP_KERNEL);
 176     memset(dev->priv, 0, sizeof(struct el3_private));
 177     lp = (struct el3_private *)dev->priv;
 178 
 179     if (el3_debug > 1)
 180         printk(version);
 181 
 182     /* The EL3-specific entries in the device structure. */
 183     dev->open = &el3_open;
 184     dev->hard_start_xmit = &el3_start_xmit;
 185     dev->stop = &el3_close;
 186     dev->get_stats = &el3_get_stats;
 187 
 188     /* Fill in the generic field of the device structure. */
 189     for (i = 0; i < DEV_NUMBUFFS; i++)
 190         dev->buffs[i] = NULL;
 191 
 192     dev->hard_header    = eth_header;
 193     dev->add_arp        = eth_add_arp;
 194     dev->queue_xmit     = dev_queue_xmit;
 195     dev->rebuild_header = eth_rebuild_header;
 196     dev->type_trans     = eth_type_trans;
 197 
 198     dev->type           = ARPHRD_ETHER;
 199     dev->hard_header_len = ETH_HLEN;
 200     dev->mtu            = 1500; /* eth_mtu */
 201     dev->addr_len       = ETH_ALEN;
 202     for (i = 0; i < dev->addr_len; i++) {
 203         dev->broadcast[i]=0xff;
 204     }
 205 
 206     /* New-style flags. */
 207     dev->flags          = IFF_BROADCAST;
 208     dev->family         = AF_INET;
 209     dev->pa_addr        = 0;
 210     dev->pa_brdaddr     = 0;
 211     dev->pa_mask        = 0;
 212     dev->pa_alen        = sizeof(unsigned long);
 213 
 214     return 0;
 215 }
 216 
 217 
 218 static int
 219 el3_open(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 220 {
 221     int ioaddr = dev->base_addr;
 222     int i;
 223 
 224     if (request_irq(dev->irq, &el3_interrupt)) {
 225         return -EAGAIN;
 226     }
 227 
 228     if (el3_debug > 3)
 229         printk("%s: Opening, IRQ %d  status@%x %4.4x reg4 %4.4x.\n",
 230                dev->name, dev->irq, ioaddr + EL3_STATUS,
 231                inw(ioaddr + EL3_STATUS), inw(ioaddr + 4));
 232     outw(0x0800, ioaddr + EL3_CMD); /* Make certain we are in window 0. */
 233 
 234     /* This is probably unnecessary. */
 235     outw(0x0001, ioaddr + 4);
 236 
 237     outw((dev->irq << 12) | 0x0f00, ioaddr + 8);
 238 
 239     irq2dev_map[dev->irq] = dev;
 240 
 241     /* Set the station address in window 2 each time opened. */
 242     outw(0x0802, ioaddr + EL3_CMD);
 243 
 244     for (i = 0; i < 6; i++)
 245         outb(dev->dev_addr[i], ioaddr + i);
 246 
 247     outw(0x1000, ioaddr + EL3_CMD); /* Start the thinnet transceiver. */
 248 
 249     outw(0x8005, ioaddr + EL3_CMD); /* Accept b-case and phys addr only. */
 250     outw(0xA800, ioaddr + EL3_CMD); /* Turn on statistics. */
 251     outw(0x2000, ioaddr + EL3_CMD); /* Enable the receiver. */
 252     outw(0x4800, ioaddr + EL3_CMD); /* Enable transmitter. */
 253     outw(0x78ff, ioaddr + EL3_CMD); /* Allow all status bits to be seen. */
 254     outw(0x7098, ioaddr + EL3_CMD); /* Set interrupt mask. */
 255 
 256     /* Switch to register set 1 for normal use. */
 257     outw(0x0801, ioaddr + EL3_CMD);
 258 
 259     if (el3_debug > 3)
 260         printk("%s: Opened 3c509  IRQ %d  status %4.4x.\n",
 261                dev->name, dev->irq, inw(ioaddr + EL3_STATUS));
 262 
 263     dev->tbusy = 0;
 264     dev->interrupt = 0;
 265     dev->start = 1;
 266 
 267     return 0;                   /* Always succeed */
 268 }
 269 
 270 static int
 271 el3_start_xmit(struct sk_buff *skb, struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 272 {
 273     struct el3_private *lp = (struct el3_private *)dev->priv;
 274     int ioaddr = dev->base_addr;
 275 
 276     /* Transmitter timeout, serious problems. */
 277     if (dev->tbusy) {
 278         int tickssofar = jiffies - dev->trans_start;
 279         if (tickssofar < 10)
 280             return 1;
 281         printk("%s: transmit timed out, tx_status %4.4x status %4.4x.\n",
 282                dev->name, inb(ioaddr + TX_STATUS), inw(ioaddr + EL3_STATUS));
 283         dev->trans_start = jiffies;
 284         /* Issue TX_RESET and TX_START commands. */
 285         outw(0x5800, ioaddr + EL3_CMD); /* TX_RESET */
 286         outw(0x4800, ioaddr + EL3_CMD); /* TX_START */
 287         dev->tbusy = 0;
 288     }
 289 
 290     if (skb == NULL) {
 291         dev_tint(dev);
 292         return 0;
 293     }
 294 
 295     /* Fill in the ethernet header. */
 296     if (!skb->arp  &&  dev->rebuild_header(skb+1, dev)) {
 297         skb->dev = dev;
 298         arp_queue (skb);
 299         return 0;
 300     }
 301 
 302     if (skb->len <= 0)
 303         return 0;
 304 
 305     if (el3_debug > 4) {
 306         printk("%s: el3_start_xmit(lenght = %d) called, status %4.4x.\n",
 307                dev->name, skb->len, inw(ioaddr + EL3_STATUS));
 308     }
 309 
 310     if (inw(ioaddr + EL3_STATUS) & 0x0001) { /* IRQ line active, missed one. */
 311       printk("%s: Missed interrupt, status %4.4x.\n", dev->name,
 312              inw(ioaddr + EL3_STATUS));
 313       outw(0x7800, ioaddr + EL3_CMD); /* Fake interrupt trigger. */
 314       outw(0x6899, ioaddr + EL3_CMD); /* Ack IRQ */
 315       outw(0x78ff, ioaddr + EL3_CMD); /* Allow all status bits to be seen. */
 316     }
 317 
 318     /* Avoid timer-based retransmission conflicts. */
 319     dev->tbusy=1;
 320 
 321     /* Put out the doubleword header... */
 322     outw(skb->len, ioaddr + TX_FIFO);
 323     outw(0x00, ioaddr + TX_FIFO);
 324     /* ... and the packet rounded to a doubleword. */
 325     port_write(ioaddr + TX_FIFO, (void *)(skb+1),
 326                ((skb->len + 3) >> 1) & ~0x1);
 327     
 328     dev->trans_start = jiffies;
 329     if (skb->free)
 330         kfree_skb (skb, FREE_WRITE);
 331     
 332     if (inw(ioaddr + TX_FREE) > 1536) {
 333         dev->tbusy=0;
 334     } else
 335         /* Interrupt us when the FIFO has room for max-sized packet. */
 336         outw(0x9000 + 1536, ioaddr + EL3_CMD);
 337 
 338     if (el3_debug > 4)
 339         printk("        Finished queueing packet, FIFO room remaining %d.\n",
 340                inw(ioaddr + TX_FREE));
 341     /* Clear the Tx status stack. */
 342     {
 343         short tx_status;
 344         int i = 4;
 345 
 346         while (--i > 0  &&  (tx_status = inb(ioaddr + TX_STATUS)) > 0) {
 347             if (el3_debug > 5)
 348                 printk("        Tx status %4.4x.\n", tx_status);
 349             if (tx_status & 0x38) lp->stats.tx_aborted_errors++;
 350             if (tx_status & 0x30) outw(0x5800, ioaddr + EL3_CMD);
 351             if (tx_status & 0x3C) outw(0x4800, ioaddr + EL3_CMD);
 352             outb(0x00, ioaddr + TX_STATUS); /* Pop the status stack. */
 353         }
 354     }
 355     return 0;
 356 }
 357 
 358 /* The EL3 interrupt handler. */
 359 static void
 360 el3_interrupt(int reg_ptr)
     /* [previous][next][first][last][top][bottom][index][help] */
 361 {
 362     int irq = -(((struct pt_regs *)reg_ptr)->orig_eax+2);
 363     struct device *dev = irq2dev_map[irq];
 364     int ioaddr, status;
 365 
 366     if (dev == NULL) {
 367         printk ("el3_interrupt(): irq %d for unknown device.\n", irq);
 368         return;
 369     }
 370 
 371     if (dev->interrupt)
 372         printk("%s: Re-entering the interrupt handler.\n", dev->name);
 373     dev->interrupt = 1;
 374 
 375     ioaddr = dev->base_addr;
 376     status = inw(ioaddr + EL3_STATUS);
 377 
 378     if (el3_debug > 4)
 379         printk("%s: interrupt, status %4.4x.\n", dev->name, status);
 380     
 381     while ((status = inw(ioaddr + EL3_STATUS)) & 0x01) {
 382 
 383         if (status & 0x08) {
 384             if (el3_debug > 5)
 385                 printk("    TX room bit was handled.\n");
 386             /* There's room in the FIFO for a full-sized packet. */
 387             outw(0x6808, ioaddr + EL3_CMD); /* Ack IRQ */
 388             dev->tbusy = 0;
 389             mark_bh(INET_BH);
 390         }
 391         if (status & 0x80)              /* Statistics full. */
 392             update_stats(ioaddr, dev);
 393         
 394         if (status & 0x10)
 395             el3_rx(dev);
 396 
 397         /* Clear the interrupts we've handled. */
 398         outw(0x6899, ioaddr + EL3_CMD); /* Ack IRQ */
 399     }
 400 
 401     if (el3_debug > 4) {
 402         printk("%s: exiting interrupt, status %4.4x.\n", dev->name,
 403                inw(ioaddr + EL3_STATUS));
 404     }
 405     
 406     if (inw(ioaddr + EL3_STATUS) & 0x01) {
 407         int i = 100000;
 408         printk("%s: exiting interrupt with status %4.4x.\n", dev->name,
 409                inw(ioaddr + EL3_STATUS));
 410         while (i--)             /* Delay loop to see the message. */
 411             inw(ioaddr + EL3_STATUS);
 412         while ((inw(ioaddr + EL3_STATUS) & 0x0010)  && i++ < 20)
 413             outw(0x00, ioaddr + RX_STATUS);
 414     }
 415 
 416     dev->interrupt = 0;
 417     return;
 418 }
 419 
 420 
 421 static struct enet_statistics *
 422 el3_get_stats(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 423 {
 424     struct el3_private *lp = (struct el3_private *)dev->priv;
 425 
 426     sti();
 427     update_stats(dev->base_addr, dev);
 428     cli();
 429     return &lp->stats;
 430 }
 431 
 432 /* Update statistics.  We change to register window 6, so this
 433    must be run single-threaded. */
 434 static void update_stats(int ioaddr, struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 435 {
 436     struct el3_private *lp = (struct el3_private *)dev->priv;
 437 
 438     if (el3_debug > 5)
 439         printk("   Updating the statistics.\n");
 440     /* Turn off statistics updates while reading. */
 441     outw(0xB000, ioaddr + EL3_CMD);
 442     /* Switch to the stats window, and read everything. */
 443     outw(0x0806, ioaddr + EL3_CMD);
 444     lp->stats.tx_carrier_errors += inb(ioaddr + 0);
 445     lp->stats.tx_heartbeat_errors       += inb(ioaddr + 1);
 446     /* Multiple collisions. */     inb(ioaddr + 2);
 447     lp->stats.collisions                += inb(ioaddr + 3);
 448     lp->stats.tx_window_errors  += inb(ioaddr + 4);
 449     lp->stats.rx_fifo_errors    += inb(ioaddr + 5);
 450     lp->stats.tx_packets                += inb(ioaddr + 6);
 451     lp->stats.rx_packets                += inb(ioaddr + 7);
 452     /* Tx deferrals */             inb(ioaddr + 8);
 453     inw(ioaddr + 10);   /* Total Rx and Tx octets. */
 454     inw(ioaddr + 12);
 455 
 456     /* Back to window 1, and turn statistics back on. */
 457     outw(0x0801, ioaddr + EL3_CMD);
 458     outw(0xA800, ioaddr + EL3_CMD);
 459     return;
 460 }
 461 
 462 /* Print statistics on the kernel error output. */
 463 void printk_stats(struct enet_statistics *stats)
     /* [previous][next][first][last][top][bottom][index][help] */
 464 {
 465 
 466     printk("  Ethernet statistics:  Rx packets %6d  Tx packets %6d.\n",
 467            stats->rx_packets, stats->tx_packets);
 468     printk("   Carrier errors:   %6d.\n", stats->tx_carrier_errors);
 469     printk("   Heartbeat errors: %6d.\n", stats->tx_heartbeat_errors);
 470     printk("   Collisions:       %6d.\n", stats->collisions);
 471     printk("   Rx FIFO problems: %6d.\n", stats->rx_fifo_errors);
 472 
 473     return;
 474 }
 475 
 476 static int
 477 el3_rx(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 478 {
 479     struct el3_private *lp = (struct el3_private *)dev->priv;
 480     int ioaddr = dev->base_addr;
 481     short rx_status;
 482 
 483     if (el3_debug > 5)
 484         printk("       In rx_packet(), status %4.4x, rx_status %4.4x.\n",
 485                inw(ioaddr+EL3_STATUS), inw(ioaddr+RX_STATUS));
 486     while ((rx_status = inw(ioaddr + RX_STATUS)) > 0) {
 487         if (rx_status & 0x4000) { /* Error, update stats. */
 488             short error = rx_status & 0x3C00;
 489             lp->stats.rx_errors++;
 490             switch (error) {
 491             case 0x2000:        lp->stats.rx_over_errors++; break;
 492             case 0x2C00:        lp->stats.rx_length_errors++; break;
 493             case 0x3400:        lp->stats.rx_crc_errors++; break;
 494             case 0x2400:        lp->stats.rx_length_errors++; break;
 495             case 0x3000:        lp->stats.rx_frame_errors++; break;
 496             case 0x0800:        lp->stats.rx_frame_errors++; break;
 497             }
 498         }
 499         if ( (! (rx_status & 0x4000))
 500             || ! (rx_status & 0x2000)) { /* Dribble bits are OK. */
 501             short length = rx_status & 0x3ff;
 502             int sksize = sizeof(struct sk_buff) + length + 3;
 503             struct sk_buff *skb;
 504             skb = (struct sk_buff *) kmalloc(sksize, GFP_ATOMIC);
 505 
 506             if (el3_debug > 4)
 507                 printk("       Receiving packet size %d status %4.4x.\n",
 508                        length, rx_status);
 509             if (skb != NULL) {
 510                 skb->lock = 0;
 511                 skb->mem_len = sksize;
 512                 skb->mem_addr = skb;
 513                 /* 'skb+1' points to the start of sk_buff data area. */
 514                 port_read(ioaddr+RX_FIFO, (void *)(skb+1), ((length + 3) >> 2) << 1);
 515                 if (dev_rint((unsigned char *)skb, length, IN_SKBUFF,dev)== 0){
 516                     if (el3_debug > 6)
 517                         printk("     dev_rint() happy, status %4.4x.\n",
 518                         inb(ioaddr + EL3_STATUS));
 519                     outw(0x4000, ioaddr + EL3_CMD); /* Rx discard */
 520                     while (inw(ioaddr + EL3_STATUS) & 0x1000)
 521                       printk("  Waiting for 3c509 to discard packet, status %x.\n",
 522                              inw(ioaddr + EL3_STATUS) );
 523                     if (el3_debug > 6)
 524                         printk("     discarded packet, status %4.4x.\n",
 525                         inb(ioaddr + EL3_STATUS));
 526                     continue;
 527                 } else {
 528                     printk("%s: receive buffers full.\n", dev->name);
 529                     kfree_s(skb, sksize);
 530                 }           
 531             } else if (el3_debug)
 532                 printk("%s: Couldn't allocate a sk_buff of size %d.\n",
 533                        dev->name, sksize);
 534         }
 535         lp->stats.rx_dropped++;
 536         outw(0x4000, ioaddr + EL3_CMD); /* Rx discard */
 537         while (inw(ioaddr + EL3_STATUS) & 0x1000)
 538           printk("  Waiting for 3c509 to discard packet, status %x.\n",
 539                  inw(ioaddr + EL3_STATUS) );
 540     }
 541 
 542     if (el3_debug > 5)
 543         printk("       Exiting rx_packet(), status %4.4x, rx_status %4.4x.\n",
 544                inw(ioaddr+EL3_STATUS), inw(ioaddr+8));
 545 
 546     return 0;
 547 }
 548 
 549 static int
 550 el3_close(struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 551 {
 552     int ioaddr = dev->base_addr;
 553 
 554     if (el3_debug > 2)
 555         printk("%s: Shutting down ethercard.\n", dev->name);
 556 
 557     dev->tbusy = 1;
 558     dev->start = 0;
 559 
 560     /* Turn off statistics.  We update lp->stats below. */
 561     outw(0xB000, ioaddr + EL3_CMD);
 562 
 563     /* Disable the receiver and transmitter. */
 564     outw(0x1800, ioaddr + EL3_CMD);
 565     outw(0x5000, ioaddr + EL3_CMD);
 566 
 567     /* Turn off thinnet power. */
 568     outw(0xb800, ioaddr + EL3_CMD);
 569 
 570     if (el3_debug > 2) {
 571         struct el3_private *lp = (struct el3_private *)dev->priv;
 572         printk("%s: Status was %4.4x.\n", dev->name, inw(ioaddr + EL3_STATUS));
 573         printk_stats(&lp->stats);
 574     }
 575 
 576     /* Free the interrupt line. */
 577     free_irq(dev->irq);
 578     outw(0x1000, ioaddr + EL3_CMD);
 579     outw(0x0f00, ioaddr + 8);
 580 
 581     /* Switch back to register window 0. */
 582     outw(0x0800, ioaddr + EL3_CMD);
 583 
 584     irq2dev_map[dev->irq] = 0;
 585 
 586     update_stats(ioaddr, dev);
 587     return 0;
 588 }
 589 
 590 /*
 591  * Local variables:
 592  *  compile-command: "gcc -D__KERNEL__ -Wall -O6 -x c++ -c 3c509.c"
 593  * End:
 594  */

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