Annotation of Gnu-Mach/linux/src/drivers/net/8390.c, revision 1.1

1.1     ! root        1: /* 8390.c: A general NS8390 ethernet driver core 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.
        !             7: 
        !             8:        This software may be used and distributed according to the terms
        !             9:        of the GNU Public License, incorporated herein by reference.
        !            10: 
        !            11:        The author may be reached as [email protected], or C/O
        !            12:        Center of Excellence in Space Data and Information Sciences
        !            13:           Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
        !            14:   
        !            15:   This is the chip-specific code for many 8390-based ethernet adaptors.
        !            16:   This is not a complete driver, it must be combined with board-specific
        !            17:   code such as ne.c, wd.c, 3c503.c, etc.
        !            18: 
        !            19:   Seeing how at least eight drivers use this code, (not counting the
        !            20:   PCMCIA ones either) it is easy to break some card by what seems like
        !            21:   a simple innocent change. Please contact me or Donald if you think
        !            22:   you have found something that needs changing. -- PG
        !            23: 
        !            24: 
        !            25:   Changelog:
        !            26: 
        !            27:   Paul Gortmaker       : remove set_bit lock, other cleanups.
        !            28:   Paul Gortmaker       : add ei_get_8390_hdr() so we can pass skb's to 
        !            29:                          ei_block_input() for eth_io_copy_and_sum().
        !            30:   Paul Gortmaker       : exchange static int ei_pingpong for a #define,
        !            31:                          also add better Tx error handling.
        !            32:   Paul Gortmaker       : rewrite Rx overrun handling as per NS specs.
        !            33: 
        !            34: 
        !            35:   Sources:
        !            36:   The National Semiconductor LAN Databook, and the 3Com 3c503 databook.
        !            37: 
        !            38:   */
        !            39: 
        !            40: static const char *version =
        !            41:     "8390.c:v1.10 9/23/94 Donald Becker ([email protected])\n";
        !            42: 
        !            43: #include <linux/module.h>
        !            44: #include <linux/kernel.h>
        !            45: #include <linux/sched.h>
        !            46: #include <linux/fs.h>
        !            47: #include <linux/types.h>
        !            48: #include <linux/ptrace.h>
        !            49: #include <linux/string.h>
        !            50: #include <asm/system.h>
        !            51: #include <asm/segment.h>
        !            52: #include <asm/bitops.h>
        !            53: #include <asm/io.h>
        !            54: #include <linux/errno.h>
        !            55: #include <linux/fcntl.h>
        !            56: #include <linux/in.h>
        !            57: #include <linux/interrupt.h>
        !            58: 
        !            59: #include <linux/netdevice.h>
        !            60: #include <linux/etherdevice.h>
        !            61: 
        !            62: #include "8390.h"
        !            63: 
        !            64: /* These are the operational function interfaces to board-specific
        !            65:    routines.
        !            66:        void reset_8390(struct device *dev)
        !            67:                Resets the board associated with DEV, including a hardware reset of
        !            68:                the 8390.  This is only called when there is a transmit timeout, and
        !            69:                it is always followed by 8390_init().
        !            70:        void block_output(struct device *dev, int count, const unsigned char *buf,
        !            71:                                          int start_page)
        !            72:                Write the COUNT bytes of BUF to the packet buffer at START_PAGE.  The
        !            73:                "page" value uses the 8390's 256-byte pages.
        !            74:        void get_8390_hdr(struct device *dev, struct e8390_hdr *hdr, int ring_page)
        !            75:                Read the 4 byte, page aligned 8390 header. *If* there is a
        !            76:                subsequent read, it will be of the rest of the packet.
        !            77:        void block_input(struct device *dev, int count, struct sk_buff *skb, int ring_offset)
        !            78:                Read COUNT bytes from the packet buffer into the skb data area. Start 
        !            79:                reading from RING_OFFSET, the address as the 8390 sees it.  This will always
        !            80:                follow the read of the 8390 header. 
        !            81: */
        !            82: #define ei_reset_8390 (ei_local->reset_8390)
        !            83: #define ei_block_output (ei_local->block_output)
        !            84: #define ei_block_input (ei_local->block_input)
        !            85: #define ei_get_8390_hdr (ei_local->get_8390_hdr)
        !            86: 
        !            87: /* use 0 for production, 1 for verification, >2 for debug */
        !            88: #ifdef EI_DEBUG
        !            89: int ei_debug = EI_DEBUG;
        !            90: #else
        !            91: int ei_debug = 1;
        !            92: #endif
        !            93: 
        !            94: /* Index to functions. */
        !            95: static void ei_tx_intr(struct device *dev);
        !            96: static void ei_tx_err(struct device *dev);
        !            97: static void ei_receive(struct device *dev);
        !            98: static void ei_rx_overrun(struct device *dev);
        !            99: 
        !           100: /* Routines generic to NS8390-based boards. */
        !           101: static void NS8390_trigger_send(struct device *dev, unsigned int length,
        !           102:                                                                int start_page);
        !           103: static void set_multicast_list(struct device *dev);
        !           104: 
        !           105: 
        !           106: /* Open/initialize the board.  This routine goes all-out, setting everything
        !           107:    up anew at each open, even though many of these registers should only
        !           108:    need to be set once at boot.
        !           109:    */
        !           110: int ei_open(struct device *dev)
        !           111: {
        !           112:     struct ei_device *ei_local = (struct ei_device *) dev->priv;
        !           113: 
        !           114:     /* This can't happen unless somebody forgot to call ethdev_init(). */
        !           115:     if (ei_local == NULL) {
        !           116:        printk(KERN_EMERG "%s: ei_open passed a non-existent device!\n", dev->name);
        !           117:        return -ENXIO;
        !           118:     }
        !           119:     
        !           120:     irq2dev_map[dev->irq] = dev;
        !           121:     NS8390_init(dev, 1);
        !           122:     dev->start = 1;
        !           123:     ei_local->irqlock = 0;
        !           124:     return 0;
        !           125: }
        !           126: 
        !           127: /* Opposite of above. Only used when "ifconfig <devname> down" is done. */
        !           128: int ei_close(struct device *dev)
        !           129: {
        !           130:     NS8390_init(dev, 0);
        !           131:     dev->start = 0;
        !           132:     return 0;
        !           133: }
        !           134: 
        !           135: static int ei_start_xmit(struct sk_buff *skb, struct device *dev)
        !           136: {
        !           137:     int e8390_base = dev->base_addr;
        !           138:     struct ei_device *ei_local = (struct ei_device *) dev->priv;
        !           139:     int length, send_length, output_page;
        !           140: 
        !           141: /*
        !           142:  *  We normally shouldn't be called if dev->tbusy is set, but the
        !           143:  *  existing code does anyway. If it has been too long since the
        !           144:  *  last Tx, we assume the board has died and kick it.
        !           145:  */
        !           146:  
        !           147:     if (dev->tbusy) {  /* Do timeouts, just like the 8003 driver. */
        !           148:                int txsr = inb(e8390_base+EN0_TSR), isr;
        !           149:                int tickssofar = jiffies - dev->trans_start;
        !           150:                if (tickssofar < TX_TIMEOUT ||  (tickssofar < (TX_TIMEOUT+5) && ! (txsr & ENTSR_PTX))) {
        !           151:                        return 1;
        !           152:                }
        !           153:                isr = inb(e8390_base+EN0_ISR);
        !           154:                if (dev->start == 0) {
        !           155:                        printk("%s: xmit on stopped card\n", dev->name);
        !           156:                        return 1;
        !           157:                }
        !           158: 
        !           159:                /*
        !           160:                 * Note that if the Tx posted a TX_ERR interrupt, then the
        !           161:                 * error will have been handled from the interrupt handler.
        !           162:                 * and not here.
        !           163:                 */
        !           164: 
        !           165:                printk(KERN_DEBUG "%s: Tx timed out, %s TSR=%#2x, ISR=%#2x, t=%d.\n",
        !           166:                   dev->name, (txsr & ENTSR_ABT) ? "excess collisions." :
        !           167:                   (isr) ? "lost interrupt?" : "cable problem?", txsr, isr, tickssofar);
        !           168: 
        !           169:                if (!isr && !ei_local->stat.tx_packets) {
        !           170:                   /* The 8390 probably hasn't gotten on the cable yet. */
        !           171:                   ei_local->interface_num ^= 1;   /* Try a different xcvr.  */
        !           172:                }
        !           173: 
        !           174:                /* Try to restart the card.  Perhaps the user has fixed something. */
        !           175:                ei_reset_8390(dev);
        !           176:                NS8390_init(dev, 1);
        !           177:                dev->trans_start = jiffies;
        !           178:     }
        !           179:     
        !           180:     /* Sending a NULL skb means some higher layer thinks we've missed an
        !           181:        tx-done interrupt. Caution: dev_tint() handles the cli()/sti()
        !           182:        itself. */
        !           183:     if (skb == NULL) {
        !           184:                dev_tint(dev);
        !           185:                return 0;
        !           186:     }
        !           187:     
        !           188:     length = skb->len;
        !           189:     if (skb->len <= 0)
        !           190:                return 0;
        !           191: 
        !           192:     /* Mask interrupts from the ethercard. */
        !           193:     outb_p(0x00, e8390_base + EN0_IMR);
        !           194:     if (dev->interrupt) {
        !           195:        printk("%s: Tx request while isr active.\n",dev->name);
        !           196:        outb_p(ENISR_ALL, e8390_base + EN0_IMR);
        !           197:        return 1;
        !           198:     }
        !           199:     ei_local->irqlock = 1;
        !           200: 
        !           201:     send_length = ETH_ZLEN < length ? length : ETH_ZLEN;
        !           202: 
        !           203: #ifdef EI_PINGPONG
        !           204: 
        !           205:     /*
        !           206:      * We have two Tx slots available for use. Find the first free
        !           207:      * slot, and then perform some sanity checks. With two Tx bufs,
        !           208:      * you get very close to transmitting back-to-back packets. With
        !           209:      * only one Tx buf, the transmitter sits idle while you reload the
        !           210:      * card, leaving a substantial gap between each transmitted packet.
        !           211:      */
        !           212: 
        !           213:     if (ei_local->tx1 == 0) {
        !           214:        output_page = ei_local->tx_start_page;
        !           215:        ei_local->tx1 = send_length;
        !           216:        if (ei_debug  &&  ei_local->tx2 > 0)
        !           217:                printk("%s: idle transmitter tx2=%d, lasttx=%d, txing=%d.\n",
        !           218:                        dev->name, ei_local->tx2, ei_local->lasttx, ei_local->txing);
        !           219:     } else if (ei_local->tx2 == 0) {
        !           220:        output_page = ei_local->tx_start_page + TX_1X_PAGES;
        !           221:        ei_local->tx2 = send_length;
        !           222:        if (ei_debug  &&  ei_local->tx1 > 0)
        !           223:                printk("%s: idle transmitter, tx1=%d, lasttx=%d, txing=%d.\n",
        !           224:                        dev->name, ei_local->tx1, ei_local->lasttx, ei_local->txing);
        !           225:     } else {   /* We should never get here. */
        !           226:        if (ei_debug)
        !           227:                printk("%s: No Tx buffers free! irq=%d tx1=%d tx2=%d last=%d\n",
        !           228:                        dev->name, dev->interrupt, ei_local->tx1, ei_local->tx2, ei_local->lasttx);
        !           229:        ei_local->irqlock = 0;
        !           230:        dev->tbusy = 1;
        !           231:        outb_p(ENISR_ALL, e8390_base + EN0_IMR);
        !           232:        return 1;
        !           233:     }
        !           234: 
        !           235:     /*
        !           236:      * Okay, now upload the packet and trigger a send if the transmitter
        !           237:      * isn't already sending. If it is busy, the interrupt handler will
        !           238:      * trigger the send later, upon receiving a Tx done interrupt.
        !           239:      */
        !           240: 
        !           241:     ei_block_output(dev, length, skb->data, output_page);
        !           242:     if (! ei_local->txing) {
        !           243:        ei_local->txing = 1;
        !           244:        NS8390_trigger_send(dev, send_length, output_page);
        !           245:        dev->trans_start = jiffies;
        !           246:        if (output_page == ei_local->tx_start_page) {
        !           247:                ei_local->tx1 = -1;
        !           248:                ei_local->lasttx = -1;
        !           249:        } else {
        !           250:                ei_local->tx2 = -1;
        !           251:                ei_local->lasttx = -2;
        !           252:        }
        !           253:     } else
        !           254:        ei_local->txqueue++;
        !           255: 
        !           256:     dev->tbusy = (ei_local->tx1  &&  ei_local->tx2);
        !           257: 
        !           258: #else  /* EI_PINGPONG */
        !           259: 
        !           260:     /*
        !           261:      * Only one Tx buffer in use. You need two Tx bufs to come close to
        !           262:      * back-to-back transmits. Expect a 20 -> 25% performance hit on
        !           263:      * reasonable hardware if you only use one Tx buffer.
        !           264:      */
        !           265: 
        !           266:     ei_block_output(dev, length, skb->data, ei_local->tx_start_page);
        !           267:     ei_local->txing = 1;
        !           268:     NS8390_trigger_send(dev, send_length, ei_local->tx_start_page);
        !           269:     dev->trans_start = jiffies;
        !           270:     dev->tbusy = 1;
        !           271: 
        !           272: #endif /* EI_PINGPONG */
        !           273: 
        !           274:     /* Turn 8390 interrupts back on. */
        !           275:     ei_local->irqlock = 0;
        !           276:     outb_p(ENISR_ALL, e8390_base + EN0_IMR);
        !           277: 
        !           278:     dev_kfree_skb (skb, FREE_WRITE);
        !           279:     
        !           280:     return 0;
        !           281: }
        !           282: 
        !           283: /* The typical workload of the driver:
        !           284:    Handle the ether interface interrupts. */
        !           285: void ei_interrupt(int irq, void *dev_id, struct pt_regs * regs)
        !           286: {
        !           287:     struct device *dev = (struct device *)(irq2dev_map[irq]);
        !           288:     int e8390_base;
        !           289:     int interrupts, nr_serviced = 0;
        !           290:     struct ei_device *ei_local;
        !           291:     
        !           292:     if (dev == NULL) {
        !           293:                printk ("net_interrupt(): irq %d for unknown device.\n", irq);
        !           294:                return;
        !           295:     }
        !           296:     e8390_base = dev->base_addr;
        !           297:     ei_local = (struct ei_device *) dev->priv;
        !           298:     if (dev->interrupt || ei_local->irqlock) {
        !           299:                /* The "irqlock" check is only for testing. */
        !           300:                printk(ei_local->irqlock
        !           301:                           ? "%s: Interrupted while interrupts are masked! isr=%#2x imr=%#2x.\n"
        !           302:                           : "%s: Reentering the interrupt handler! isr=%#2x imr=%#2x.\n",
        !           303:                           dev->name, inb_p(e8390_base + EN0_ISR),
        !           304:                           inb_p(e8390_base + EN0_IMR));
        !           305:                return;
        !           306:     }
        !           307:     
        !           308:     dev->interrupt = 1;
        !           309:     
        !           310:     /* Change to page 0 and read the intr status reg. */
        !           311:     outb_p(E8390_NODMA+E8390_PAGE0, e8390_base + E8390_CMD);
        !           312:     if (ei_debug > 3)
        !           313:                printk("%s: interrupt(isr=%#2.2x).\n", dev->name,
        !           314:                           inb_p(e8390_base + EN0_ISR));
        !           315:     
        !           316:     /* !!Assumption!! -- we stay in page 0.     Don't break this. */
        !           317:     while ((interrupts = inb_p(e8390_base + EN0_ISR)) != 0
        !           318:                   && ++nr_serviced < MAX_SERVICE) {
        !           319:                if (dev->start == 0) {
        !           320:                        printk("%s: interrupt from stopped card\n", dev->name);
        !           321:                        interrupts = 0;
        !           322:                        break;
        !           323:                }
        !           324:                if (interrupts & ENISR_OVER) {
        !           325:                        ei_rx_overrun(dev);
        !           326:                } else if (interrupts & (ENISR_RX+ENISR_RX_ERR)) {
        !           327:                        /* Got a good (?) packet. */
        !           328:                        ei_receive(dev);
        !           329:                }
        !           330:                /* Push the next to-transmit packet through. */
        !           331:                if (interrupts & ENISR_TX) {
        !           332:                        ei_tx_intr(dev);
        !           333:                } else if (interrupts & ENISR_TX_ERR) {
        !           334:                        ei_tx_err(dev);
        !           335:                }
        !           336: 
        !           337:                if (interrupts & ENISR_COUNTERS) {
        !           338:                        ei_local->stat.rx_frame_errors += inb_p(e8390_base + EN0_COUNTER0);
        !           339:                        ei_local->stat.rx_crc_errors   += inb_p(e8390_base + EN0_COUNTER1);
        !           340:                        ei_local->stat.rx_missed_errors+= inb_p(e8390_base + EN0_COUNTER2);
        !           341:                        outb_p(ENISR_COUNTERS, e8390_base + EN0_ISR); /* Ack intr. */
        !           342:                }
        !           343:                
        !           344:                /* Ignore any RDC interrupts that make it back to here. */
        !           345:                if (interrupts & ENISR_RDC) {
        !           346:                        outb_p(ENISR_RDC, e8390_base + EN0_ISR);
        !           347:                }
        !           348: 
        !           349:                outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base + E8390_CMD);
        !           350:     }
        !           351:     
        !           352:     if (interrupts && ei_debug) {
        !           353:                outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base + E8390_CMD);
        !           354:                if (nr_serviced >= MAX_SERVICE) {
        !           355:                        printk("%s: Too much work at interrupt, status %#2.2x\n",
        !           356:                                   dev->name, interrupts);
        !           357:                        outb_p(ENISR_ALL, e8390_base + EN0_ISR); /* Ack. most intrs. */
        !           358:                } else {
        !           359:                        printk("%s: unknown interrupt %#2x\n", dev->name, interrupts);
        !           360:                        outb_p(0xff, e8390_base + EN0_ISR); /* Ack. all intrs. */
        !           361:                }
        !           362:     }
        !           363:     dev->interrupt = 0;
        !           364:     return;
        !           365: }
        !           366: 
        !           367: /*
        !           368:  * A transmitter error has happened. Most likely excess collisions (which
        !           369:  * is a fairly normal condition). If the error is one where the Tx will
        !           370:  * have been aborted, we try and send another one right away, instead of
        !           371:  * letting the failed packet sit and collect dust in the Tx buffer. This
        !           372:  * is a much better solution as it avoids kernel based Tx timeouts, and
        !           373:  * an unnecessary card reset.
        !           374:  */
        !           375: 
        !           376: static void ei_tx_err(struct device *dev)
        !           377: {
        !           378:     int e8390_base = dev->base_addr;
        !           379:     unsigned char txsr = inb_p(e8390_base+EN0_TSR);
        !           380:     unsigned char tx_was_aborted = txsr & (ENTSR_ABT+ENTSR_FU);
        !           381:     struct ei_device *ei_local = (struct ei_device *) dev->priv;
        !           382: 
        !           383: #ifdef VERBOSE_ERROR_DUMP
        !           384:     printk(KERN_DEBUG "%s: transmitter error (%#2x): ", dev->name, txsr);
        !           385:     if (txsr & ENTSR_ABT)
        !           386:                printk("excess-collisions ");
        !           387:     if (txsr & ENTSR_ND)
        !           388:                printk("non-deferral ");
        !           389:     if (txsr & ENTSR_CRS)
        !           390:                printk("lost-carrier ");
        !           391:     if (txsr & ENTSR_FU)
        !           392:                printk("FIFO-underrun ");
        !           393:     if (txsr & ENTSR_CDH)
        !           394:                printk("lost-heartbeat ");
        !           395:     printk("\n");
        !           396: #endif
        !           397: 
        !           398:     outb_p(ENISR_TX_ERR, e8390_base + EN0_ISR); /* Ack intr. */
        !           399: 
        !           400:     if (tx_was_aborted)
        !           401:                ei_tx_intr(dev);
        !           402: 
        !           403:     /*
        !           404:      * Note: NCR reads zero on 16 collisions so we add them
        !           405:      * in by hand. Somebody might care...
        !           406:      */
        !           407:     if (txsr & ENTSR_ABT)
        !           408:        ei_local->stat.collisions += 16;
        !           409:        
        !           410: }
        !           411: 
        !           412: /* We have finished a transmit: check for errors and then trigger the next
        !           413:    packet to be sent. */
        !           414: static void ei_tx_intr(struct device *dev)
        !           415: {
        !           416:     int e8390_base = dev->base_addr;
        !           417:     int status = inb(e8390_base + EN0_TSR);
        !           418:     struct ei_device *ei_local = (struct ei_device *) dev->priv;
        !           419:     
        !           420:     outb_p(ENISR_TX, e8390_base + EN0_ISR); /* Ack intr. */
        !           421: 
        !           422: #ifdef EI_PINGPONG
        !           423: 
        !           424:     /*
        !           425:      * There are two Tx buffers, see which one finished, and trigger
        !           426:      * the send of another one if it exists.
        !           427:      */
        !           428:     ei_local->txqueue--;
        !           429:     if (ei_local->tx1 < 0) {
        !           430:        if (ei_local->lasttx != 1 && ei_local->lasttx != -1)
        !           431:                printk("%s: bogus last_tx_buffer %d, tx1=%d.\n",
        !           432:                           ei_local->name, ei_local->lasttx, ei_local->tx1);
        !           433:        ei_local->tx1 = 0;
        !           434:        dev->tbusy = 0;
        !           435:        if (ei_local->tx2 > 0) {
        !           436:                ei_local->txing = 1;
        !           437:                NS8390_trigger_send(dev, ei_local->tx2, ei_local->tx_start_page + 6);
        !           438:                dev->trans_start = jiffies;
        !           439:                ei_local->tx2 = -1,
        !           440:                ei_local->lasttx = 2;
        !           441:        } else
        !           442:                ei_local->lasttx = 20, ei_local->txing = 0;
        !           443:     } else if (ei_local->tx2 < 0) {
        !           444:        if (ei_local->lasttx != 2  &&  ei_local->lasttx != -2)
        !           445:                printk("%s: bogus last_tx_buffer %d, tx2=%d.\n",
        !           446:                           ei_local->name, ei_local->lasttx, ei_local->tx2);
        !           447:        ei_local->tx2 = 0;
        !           448:        dev->tbusy = 0;
        !           449:        if (ei_local->tx1 > 0) {
        !           450:                ei_local->txing = 1;
        !           451:                NS8390_trigger_send(dev, ei_local->tx1, ei_local->tx_start_page);
        !           452:                dev->trans_start = jiffies;
        !           453:                ei_local->tx1 = -1;
        !           454:                ei_local->lasttx = 1;
        !           455:        } else
        !           456:                ei_local->lasttx = 10, ei_local->txing = 0;
        !           457:     } else
        !           458:        printk("%s: unexpected TX-done interrupt, lasttx=%d.\n",
        !           459:                   dev->name, ei_local->lasttx);
        !           460: 
        !           461: #else  /* EI_PINGPONG */
        !           462:     /*
        !           463:      *  Single Tx buffer: mark it free so another packet can be loaded.
        !           464:      */
        !           465:     ei_local->txing = 0;
        !           466:     dev->tbusy = 0;
        !           467: #endif
        !           468: 
        !           469:     /* Minimize Tx latency: update the statistics after we restart TXing. */
        !           470:     if (status & ENTSR_COL)
        !           471:        ei_local->stat.collisions++;
        !           472:     if (status & ENTSR_PTX)
        !           473:        ei_local->stat.tx_packets++;
        !           474:     else {
        !           475:        ei_local->stat.tx_errors++;
        !           476:        if (status & ENTSR_ABT) ei_local->stat.tx_aborted_errors++;
        !           477:        if (status & ENTSR_CRS) ei_local->stat.tx_carrier_errors++;
        !           478:        if (status & ENTSR_FU)  ei_local->stat.tx_fifo_errors++;
        !           479:        if (status & ENTSR_CDH) ei_local->stat.tx_heartbeat_errors++;
        !           480:        if (status & ENTSR_OWC) ei_local->stat.tx_window_errors++;
        !           481:     }
        !           482: 
        !           483:     mark_bh (NET_BH);
        !           484: }
        !           485: 
        !           486: /* We have a good packet(s), get it/them out of the buffers. */
        !           487: 
        !           488: static void ei_receive(struct device *dev)
        !           489: {
        !           490:     int e8390_base = dev->base_addr;
        !           491:     struct ei_device *ei_local = (struct ei_device *) dev->priv;
        !           492:     unsigned char rxing_page, this_frame, next_frame;
        !           493:     unsigned short current_offset;
        !           494:     int rx_pkt_count = 0;
        !           495:     struct e8390_pkt_hdr rx_frame;
        !           496:     int num_rx_pages = ei_local->stop_page-ei_local->rx_start_page;
        !           497:     
        !           498:     while (++rx_pkt_count < 10) {
        !           499:                int pkt_len;
        !           500:                
        !           501:                /* Get the rx page (incoming packet pointer). */
        !           502:                outb_p(E8390_NODMA+E8390_PAGE1, e8390_base + E8390_CMD);
        !           503:                rxing_page = inb_p(e8390_base + EN1_CURPAG);
        !           504:                outb_p(E8390_NODMA+E8390_PAGE0, e8390_base + E8390_CMD);
        !           505:                
        !           506:                /* Remove one frame from the ring.  Boundary is always a page behind. */
        !           507:                this_frame = inb_p(e8390_base + EN0_BOUNDARY) + 1;
        !           508:                if (this_frame >= ei_local->stop_page)
        !           509:                        this_frame = ei_local->rx_start_page;
        !           510:                
        !           511:                /* Someday we'll omit the previous, iff we never get this message.
        !           512:                   (There is at least one clone claimed to have a problem.)  */
        !           513:                if (ei_debug > 0  &&  this_frame != ei_local->current_page)
        !           514:                        printk("%s: mismatched read page pointers %2x vs %2x.\n",
        !           515:                                   dev->name, this_frame, ei_local->current_page);
        !           516:                
        !           517:                if (this_frame == rxing_page)   /* Read all the frames? */
        !           518:                        break;                          /* Done for now */
        !           519:                
        !           520:                current_offset = this_frame << 8;
        !           521:                ei_get_8390_hdr(dev, &rx_frame, this_frame);
        !           522:                
        !           523:                pkt_len = rx_frame.count - sizeof(struct e8390_pkt_hdr);
        !           524:                
        !           525:                next_frame = this_frame + 1 + ((pkt_len+4)>>8);
        !           526:                
        !           527:                /* Check for bogosity warned by 3c503 book: the status byte is never
        !           528:                   written.  This happened a lot during testing! This code should be
        !           529:                   cleaned up someday. */
        !           530:                if (rx_frame.next != next_frame
        !           531:                        && rx_frame.next != next_frame + 1
        !           532:                        && rx_frame.next != next_frame - num_rx_pages
        !           533:                        && rx_frame.next != next_frame + 1 - num_rx_pages) {
        !           534:                        ei_local->current_page = rxing_page;
        !           535:                        outb(ei_local->current_page-1, e8390_base+EN0_BOUNDARY);
        !           536:                        ei_local->stat.rx_errors++;
        !           537:                        continue;
        !           538:                }
        !           539: 
        !           540:                if (pkt_len < 60  ||  pkt_len > 1518) {
        !           541:                        if (ei_debug)
        !           542:                                printk("%s: bogus packet size: %d, status=%#2x nxpg=%#2x.\n",
        !           543:                                           dev->name, rx_frame.count, rx_frame.status,
        !           544:                                           rx_frame.next);
        !           545:                        ei_local->stat.rx_errors++;
        !           546:                } else if ((rx_frame.status & 0x0F) == ENRSR_RXOK) {
        !           547:                        struct sk_buff *skb;
        !           548:                        
        !           549:                        skb = dev_alloc_skb(pkt_len+2);
        !           550:                        if (skb == NULL) {
        !           551:                                if (ei_debug > 1)
        !           552:                                        printk("%s: Couldn't allocate a sk_buff of size %d.\n",
        !           553:                                                   dev->name, pkt_len);
        !           554:                                ei_local->stat.rx_dropped++;
        !           555:                                break;
        !           556:                        } else {
        !           557:                                skb_reserve(skb,2);     /* IP headers on 16 byte boundaries */
        !           558:                                skb->dev = dev;
        !           559:                                skb_put(skb, pkt_len);  /* Make room */
        !           560:                                ei_block_input(dev, pkt_len, skb, current_offset + sizeof(rx_frame));
        !           561:                                skb->protocol=eth_type_trans(skb,dev);
        !           562:                                netif_rx(skb);
        !           563:                                ei_local->stat.rx_packets++;
        !           564:                        }
        !           565:                } else {
        !           566:                        int errs = rx_frame.status;
        !           567:                        if (ei_debug)
        !           568:                                printk("%s: bogus packet: status=%#2x nxpg=%#2x size=%d\n",
        !           569:                                           dev->name, rx_frame.status, rx_frame.next,
        !           570:                                           rx_frame.count);
        !           571:                        if (errs & ENRSR_FO)
        !           572:                                ei_local->stat.rx_fifo_errors++;
        !           573:                }
        !           574:                next_frame = rx_frame.next;
        !           575:                
        !           576:                /* This _should_ never happen: it's here for avoiding bad clones. */
        !           577:                if (next_frame >= ei_local->stop_page) {
        !           578:                        printk("%s: next frame inconsistency, %#2x\n", dev->name,
        !           579:                                   next_frame);
        !           580:                        next_frame = ei_local->rx_start_page;
        !           581:                }
        !           582:                ei_local->current_page = next_frame;
        !           583:                outb_p(next_frame-1, e8390_base+EN0_BOUNDARY);
        !           584:     }
        !           585: 
        !           586:     /* We used to also ack ENISR_OVER here, but that would sometimes mask
        !           587:     a real overrun, leaving the 8390 in a stopped state with rec'vr off. */
        !           588:     outb_p(ENISR_RX+ENISR_RX_ERR, e8390_base+EN0_ISR);
        !           589:     return;
        !           590: }
        !           591: 
        !           592: /* 
        !           593:  * We have a receiver overrun: we have to kick the 8390 to get it started
        !           594:  * again. Problem is that you have to kick it exactly as NS prescribes in
        !           595:  * the updated datasheets, or "the NIC may act in an unpredictable manner."
        !           596:  * This includes causing "the NIC to defer indefinitely when it is stopped
        !           597:  * on a busy network."  Ugh.
        !           598:  */
        !           599: static void ei_rx_overrun(struct device *dev)
        !           600: {
        !           601:     int e8390_base = dev->base_addr;
        !           602:     unsigned long wait_start_time;
        !           603:     unsigned char was_txing, must_resend = 0;
        !           604:     struct ei_device *ei_local = (struct ei_device *) dev->priv;
        !           605:     
        !           606:     /*
        !           607:      * Record whether a Tx was in progress and then issue the
        !           608:      * stop command.
        !           609:      */
        !           610:     was_txing = inb_p(e8390_base+E8390_CMD) & E8390_TRANS;
        !           611:     outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD);
        !           612:     
        !           613:     if (ei_debug > 1)
        !           614:        printk("%s: Receiver overrun.\n", dev->name);
        !           615:     ei_local->stat.rx_over_errors++;
        !           616:     
        !           617:     /* 
        !           618:      * Wait a full Tx time (1.2ms) + some guard time, NS says 1.6ms total.
        !           619:      * Early datasheets said to poll the reset bit, but now they say that
        !           620:      * it "is not a reliable indicator and subsequently should be ignored."
        !           621:      * We wait at least 10ms.
        !           622:      */
        !           623:     wait_start_time = jiffies;
        !           624:     while (jiffies - wait_start_time <= 1*HZ/100)
        !           625:        barrier();
        !           626: 
        !           627:     /*
        !           628:      * Reset RBCR[01] back to zero as per magic incantation.
        !           629:      */
        !           630:     outb_p(0x00, e8390_base+EN0_RCNTLO);
        !           631:     outb_p(0x00, e8390_base+EN0_RCNTHI);
        !           632: 
        !           633:     /*
        !           634:      * See if any Tx was interrupted or not. According to NS, this
        !           635:      * step is vital, and skipping it will cause no end of havoc.
        !           636:      */
        !           637:     if (was_txing) { 
        !           638:        unsigned char tx_completed = inb_p(e8390_base+EN0_ISR) & (ENISR_TX+ENISR_TX_ERR);
        !           639:        if (!tx_completed) must_resend = 1;
        !           640:     }
        !           641: 
        !           642:     /*
        !           643:      * Have to enter loopback mode and then restart the NIC before
        !           644:      * you are allowed to slurp packets up off the ring.
        !           645:      */
        !           646:     outb_p(E8390_TXOFF, e8390_base + EN0_TXCR);
        !           647:     outb_p(E8390_NODMA + E8390_PAGE0 + E8390_START, e8390_base + E8390_CMD);
        !           648: 
        !           649:     /*
        !           650:      * Clear the Rx ring of all the debris, and ack the interrupt.
        !           651:      */
        !           652:     ei_receive(dev);
        !           653:     outb_p(ENISR_OVER, e8390_base+EN0_ISR);
        !           654: 
        !           655:     /*
        !           656:      * Leave loopback mode, and resend any packet that got stopped.
        !           657:      */
        !           658:     outb_p(E8390_TXCONFIG, e8390_base + EN0_TXCR); 
        !           659:     if (must_resend)
        !           660:        outb_p(E8390_NODMA + E8390_PAGE0 + E8390_START + E8390_TRANS, e8390_base + E8390_CMD);
        !           661:        
        !           662: }
        !           663: 
        !           664: static struct enet_statistics *get_stats(struct device *dev)
        !           665: {
        !           666:     short ioaddr = dev->base_addr;
        !           667:     struct ei_device *ei_local = (struct ei_device *) dev->priv;
        !           668:     
        !           669:     /* If the card is stopped, just return the present stats. */
        !           670:     if (dev->start == 0) return &ei_local->stat;
        !           671: 
        !           672:     /* Read the counter registers, assuming we are in page 0. */
        !           673:     ei_local->stat.rx_frame_errors += inb_p(ioaddr + EN0_COUNTER0);
        !           674:     ei_local->stat.rx_crc_errors   += inb_p(ioaddr + EN0_COUNTER1);
        !           675:     ei_local->stat.rx_missed_errors+= inb_p(ioaddr + EN0_COUNTER2);
        !           676:     
        !           677:     return &ei_local->stat;
        !           678: }
        !           679: 
        !           680: /*
        !           681:  *     Set or clear the multicast filter for this adaptor.
        !           682:  */
        !           683:  
        !           684: static void set_multicast_list(struct device *dev)
        !           685: {
        !           686:        short ioaddr = dev->base_addr;
        !           687:     
        !           688:        if(dev->flags&IFF_PROMISC)
        !           689:        {
        !           690:                outb_p(E8390_RXCONFIG | 0x18, ioaddr + EN0_RXCR);
        !           691:        }
        !           692:        else if((dev->flags&IFF_ALLMULTI)||dev->mc_list)
        !           693:        {
        !           694:                /* The multicast-accept list is initialized to accept-all, and we
        !           695:                   rely on higher-level filtering for now. */
        !           696:                outb_p(E8390_RXCONFIG | 0x08, ioaddr + EN0_RXCR);
        !           697:        } 
        !           698:        else
        !           699:                outb_p(E8390_RXCONFIG, ioaddr + EN0_RXCR);
        !           700: }
        !           701: 
        !           702: /* Initialize the rest of the 8390 device structure. */
        !           703: int ethdev_init(struct device *dev)
        !           704: {
        !           705:     if (ei_debug > 1)
        !           706:                printk(version);
        !           707:     
        !           708:     if (dev->priv == NULL) {
        !           709:                struct ei_device *ei_local;
        !           710:                
        !           711:                dev->priv = kmalloc(sizeof(struct ei_device), GFP_KERNEL);
        !           712:                if (dev->priv == NULL)
        !           713:                        return -ENOMEM;
        !           714:                memset(dev->priv, 0, sizeof(struct ei_device));
        !           715:                ei_local = (struct ei_device *)dev->priv;
        !           716:     }
        !           717:     
        !           718:     dev->hard_start_xmit = &ei_start_xmit;
        !           719:     dev->get_stats     = get_stats;
        !           720:     dev->set_multicast_list = &set_multicast_list;
        !           721: 
        !           722:     ether_setup(dev);
        !           723:         
        !           724:     return 0;
        !           725: }
        !           726: 
        !           727: 
        !           728: /* This page of functions should be 8390 generic */
        !           729: /* Follow National Semi's recommendations for initializing the "NIC". */
        !           730: void NS8390_init(struct device *dev, int startp)
        !           731: {
        !           732:     int e8390_base = dev->base_addr;
        !           733:     struct ei_device *ei_local = (struct ei_device *) dev->priv;
        !           734:     int i;
        !           735:     int endcfg = ei_local->word16 ? (0x48 | ENDCFG_WTS) : 0x48;
        !           736:     unsigned long flags;
        !           737:     
        !           738:     /* Follow National Semi's recommendations for initing the DP83902. */
        !           739:     outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base); /* 0x21 */
        !           740:     outb_p(endcfg, e8390_base + EN0_DCFG);     /* 0x48 or 0x49 */
        !           741:     /* Clear the remote byte count registers. */
        !           742:     outb_p(0x00,  e8390_base + EN0_RCNTLO);
        !           743:     outb_p(0x00,  e8390_base + EN0_RCNTHI);
        !           744:     /* Set to monitor and loopback mode -- this is vital!. */
        !           745:     outb_p(E8390_RXOFF, e8390_base + EN0_RXCR); /* 0x20 */
        !           746:     outb_p(E8390_TXOFF, e8390_base + EN0_TXCR); /* 0x02 */
        !           747:     /* Set the transmit page and receive ring. */
        !           748:     outb_p(ei_local->tx_start_page,     e8390_base + EN0_TPSR);
        !           749:     ei_local->tx1 = ei_local->tx2 = 0;
        !           750:     outb_p(ei_local->rx_start_page,     e8390_base + EN0_STARTPG);
        !           751:     outb_p(ei_local->stop_page-1, e8390_base + EN0_BOUNDARY); /* 3c503 says 0x3f,NS0x26*/
        !           752:     ei_local->current_page = ei_local->rx_start_page;          /* assert boundary+1 */
        !           753:     outb_p(ei_local->stop_page,          e8390_base + EN0_STOPPG);
        !           754:     /* Clear the pending interrupts and mask. */
        !           755:     outb_p(0xFF, e8390_base + EN0_ISR);
        !           756:     outb_p(0x00,  e8390_base + EN0_IMR);
        !           757:     
        !           758:     /* Copy the station address into the DS8390 registers,
        !           759:        and set the multicast hash bitmap to receive all multicasts. */
        !           760:     save_flags(flags);
        !           761:     cli();
        !           762:     outb_p(E8390_NODMA + E8390_PAGE1 + E8390_STOP, e8390_base); /* 0x61 */
        !           763:     for(i = 0; i < 6; i++) {
        !           764:                outb_p(dev->dev_addr[i], e8390_base + EN1_PHYS + i);
        !           765:     }
        !           766:     /* Initialize the multicast list to accept-all.  If we enable multicast
        !           767:        the higher levels can do the filtering. */
        !           768:     for(i = 0; i < 8; i++)
        !           769:                outb_p(0xff, e8390_base + EN1_MULT + i);
        !           770:     
        !           771:     outb_p(ei_local->rx_start_page,     e8390_base + EN1_CURPAG);
        !           772:     outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base);
        !           773:     restore_flags(flags);
        !           774:     dev->tbusy = 0;
        !           775:     dev->interrupt = 0;
        !           776:     ei_local->tx1 = ei_local->tx2 = 0;
        !           777:     ei_local->txing = 0;
        !           778:     if (startp) {
        !           779:                outb_p(0xff,  e8390_base + EN0_ISR);
        !           780:                outb_p(ENISR_ALL,  e8390_base + EN0_IMR);
        !           781:                outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base);
        !           782:                outb_p(E8390_TXCONFIG, e8390_base + EN0_TXCR); /* xmit on. */
        !           783:                /* 3c503 TechMan says rxconfig only after the NIC is started. */
        !           784:                outb_p(E8390_RXCONFIG,  e8390_base + EN0_RXCR); /* rx on,  */
        !           785:                dev->set_multicast_list(dev);           /* Get the multicast status right if this
        !           786:                                                           was a reset. */
        !           787:     }
        !           788:     return;
        !           789: }
        !           790: 
        !           791: /* Trigger a transmit start, assuming the length is valid. */
        !           792: static void NS8390_trigger_send(struct device *dev, unsigned int length,
        !           793:                                                                int start_page)
        !           794: {
        !           795:     int e8390_base = dev->base_addr;
        !           796:     
        !           797:     outb_p(E8390_NODMA+E8390_PAGE0, e8390_base);
        !           798:     
        !           799:     if (inb_p(e8390_base) & E8390_TRANS) {
        !           800:                printk("%s: trigger_send() called with the transmitter busy.\n",
        !           801:                           dev->name);
        !           802:                return;
        !           803:     }
        !           804:     outb_p(length & 0xff, e8390_base + EN0_TCNTLO);
        !           805:     outb_p(length >> 8, e8390_base + EN0_TCNTHI);
        !           806:     outb_p(start_page, e8390_base + EN0_TPSR);
        !           807:     outb_p(E8390_NODMA+E8390_TRANS+E8390_START, e8390_base);
        !           808:     return;
        !           809: }
        !           810: 
        !           811: #ifdef MODULE
        !           812: 
        !           813: int init_module(void)
        !           814: {
        !           815:      return 0;
        !           816: }
        !           817: 
        !           818: void
        !           819: cleanup_module(void)
        !           820: {
        !           821: }
        !           822: #endif /* MODULE */
        !           823: 
        !           824: /*
        !           825:  * Local variables:
        !           826:  *  compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c 8390.c"
        !           827:  *  version-control: t
        !           828:  *  kept-new-versions: 5
        !           829:  *  c-indent-level: 4
        !           830:  *  tab-width: 4
        !           831:  * End:
        !           832:  */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.