Annotation of Gnu-Mach/i386/i386at/gpl/if_ns.c, revision 1.1.1.1

1.1       root        1: /* 
                      2:  * Copyright (c) 1994 Shantanu Goel
                      3:  * All Rights Reserved.
                      4:  * 
                      5:  * Permission to use, copy, modify and distribute this software and its
                      6:  * documentation is hereby granted, provided that both the copyright
                      7:  * notice and this permission notice appear in all copies of the
                      8:  * software, derivative works or modified versions, and any portions
                      9:  * thereof, and that both notices appear in supporting documentation.
                     10:  * 
                     11:  * THE AUTHOR ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
                     12:  * CONDITION.  THE AUTHOR DISCLAIMS ANY LIABILITY OF ANY KIND FOR
                     13:  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
                     14:  */
                     15: 
                     16: /*
                     17:  * Written 1992,1993 by Donald Becker.
                     18:  * 
                     19:  * Copyright 1993 United States Government as represented by the
                     20:  * Director, National Security Agency.  This software may be used and
                     21:  * distributed according to the terms of the GNU Public License,
                     22:  * incorporated herein by reference.
                     23:  *
                     24:  * The Author may be reached as [email protected] or
                     25:  * C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715
                     26:  */
                     27: 
                     28: #include <ul.h>
                     29: #include <wd.h>
                     30: #include <hpp.h>
                     31: #if NUL > 0 || NWD > 0 || NHPP > 0
                     32: /*
                     33:  * Generic NS8390 routines.
                     34:  * Derived from the Linux driver by Donald Becker.
                     35:  *
                     36:  * Shantanu Goel ([email protected])
                     37:  */
                     38: #include <sys/types.h>
                     39: #include <device/device_types.h>
                     40: #include <device/errno.h>
                     41: #include <device/io_req.h>
                     42: #include <device/if_hdr.h>
                     43: #include <device/if_ether.h>
                     44: #include <device/net_status.h>
                     45: #include <device/net_io.h>
                     46: #include <chips/busses.h>
                     47: #include <i386/machspl.h>
                     48: #include <i386/pio.h>
                     49: #include <i386at/gpl/if_nsreg.h>
                     50: 
                     51: #define IO_DELAY       __asm__ __volatile__ ("outb %al,$0x80")
                     52: #define outb_p(p, v)   { outb(p, v); IO_DELAY; }
                     53: #define inb_p(p)       ({ unsigned char _v; _v = inb(p); IO_DELAY; _v; })
                     54: 
                     55: #define NSDEBUG
                     56: #ifdef NSDEBUG
                     57: int    nsdebug = 0;
                     58: #define DEBUGF(stmt)   { if (nsdebug) stmt; }
                     59: #else
                     60: #define DEBUGF(stmt)
                     61: #endif
                     62: 
                     63: void   nsxint(struct nssoftc *);
                     64: void   nsrint(struct nssoftc *);
                     65: void   nsxmit(struct nssoftc *, unsigned, int);
                     66: void   nsrxoverrun(struct nssoftc *);
                     67: 
                     68: /*
                     69:  * Initialize the NIC.
                     70:  * Must be called at splimp().
                     71:  */
                     72: void
                     73: nsinit(sc)
                     74:        struct nssoftc *sc;
                     75: {
                     76:        int port = sc->sc_port, i, rxconfig;
                     77:        int endcfg = sc->sc_word16 ? (0x48 | ENDCFG_WTS) : 0x48;
                     78:        struct ifnet *ifp = &sc->sc_if;
                     79: 
                     80:        /*
                     81:         * Reset the board.
                     82:         */
                     83:        (*sc->sc_reset)(sc);
                     84: 
                     85:        sc->sc_oactive = 0;
                     86:        sc->sc_txing = 0;
                     87:        sc->sc_timer = 0;
                     88:        sc->sc_tx1 = sc->sc_tx2 = 0;
                     89:        sc->sc_curpg = sc->sc_rxstrtpg;
                     90: 
                     91:        /*
                     92:         * Follow National Semiconductor's recommendations for
                     93:         * initializing the DP83902.
                     94:         */
                     95:        outb_p(port, E8390_NODMA+E8390_PAGE0+E8390_STOP);       /* 0x21 */
                     96:        outb_p(port + EN0_DCFG, endcfg);        /* 0x48 or 0x49 */
                     97: 
                     98:        /*
                     99:         * Clear remote byte count registers.
                    100:         */
                    101:        outb_p(port + EN0_RCNTLO, 0);
                    102:        outb_p(port + EN0_RCNTHI, 0);
                    103: 
                    104:        /*
                    105:         * Set to monitor and loopback mode -- this is vital!
                    106:         */
                    107:        outb_p(port + EN0_RXCR, E8390_RXOFF);   /* 0x20 */
                    108:        outb_p(port + EN0_TXCR, E8390_TXOFF);   /* 0x02 */
                    109: 
                    110:        /*
                    111:         * Set transmit page and receive ring.
                    112:         */
                    113:        outb_p(port + EN0_TPSR, sc->sc_txstrtpg);
                    114:        outb_p(port + EN0_STARTPG, sc->sc_rxstrtpg);
                    115:        outb_p(port + EN0_BOUNDARY, sc->sc_stoppg - 1);
                    116:        outb_p(port + EN0_STOPPG, sc->sc_stoppg);
                    117: 
                    118:        /*
                    119:         * Clear pending interrupts and mask.
                    120:         */
                    121:        outb_p(port + EN0_ISR, 0xff);
                    122: 
                    123:        /*
                    124:          * Enable the following interrupts: receive/transmit complete,
                    125:          * receive/transmit error, and Receiver OverWrite.
                    126:          *
                    127:          * Counter overflow and Remote DMA complete are *not* enabled.
                    128:          */
                    129:        outb_p(port + EN0_IMR, ENISR_RX | ENISR_TX | ENISR_RX_ERR |
                    130:               ENISR_TX_ERR | ENISR_OVER );
                    131: 
                    132:        /*
                    133:         * Copy station address into 8390 registers.
                    134:         */
                    135:        outb_p(port, E8390_NODMA + E8390_PAGE1 + E8390_STOP);   /* 0x61 */
                    136:        for (i = 0; i < ETHER_ADDR_LEN; i++)
                    137:                outb_p(port + EN1_PHYS + i, sc->sc_addr[i]);
                    138: 
                    139:        /*
                    140:         * Set up to accept all multicast packets.
                    141:         */
                    142:        for (i = 0; i < 8; i++)
                    143:                outb_p(port + EN1_MULT + i, 0xff);
                    144: 
                    145:        /*
                    146:         * Initialize CURRent pointer
                    147:         */
                    148:        outb_p(port + EN1_CURPAG, sc->sc_rxstrtpg);
                    149: 
                    150:        /*
                    151:         * Program command register for page 0.
                    152:         */
                    153:        outb_p(port, E8390_NODMA + E8390_PAGE0 + E8390_STOP);
                    154: 
                    155: #if 0
                    156:        outb_p(port + EN0_ISR, 0xff);
                    157:        outb_p(port + EN0_IMR, ENISR_ALL);
                    158: #endif
                    159: 
                    160:        outb_p(port + E8390_CMD, E8390_NODMA + E8390_PAGE0 + E8390_START);
                    161:        outb_p(port + EN0_TXCR, E8390_TXCONFIG);        /* xmit on */
                    162: 
                    163:        /* 3c503 TechMan says rxconfig only after the NIC is started. */
                    164:        rxconfig = E8390_RXCONFIG;
                    165:        if (ifp->if_flags & IFF_ALLMULTI)
                    166:                rxconfig |= 0x08;
                    167:        if (ifp->if_flags & IFF_PROMISC)
                    168:                rxconfig |= 0x10;
                    169:        outb_p(port + EN0_RXCR, rxconfig);      /* rx on */
                    170: 
                    171:        /*
                    172:         * Mark interface as up and start output.
                    173:         */
                    174:        ifp->if_flags |= IFF_RUNNING;
                    175:        nsstart(sc);
                    176: }
                    177: 
                    178: /*
                    179:  * Start output on interface.
                    180:  * Must be called at splimp().
                    181:  */
                    182: void
                    183: nsstart(sc)
                    184:        struct nssoftc *sc;
                    185: {
                    186:        io_req_t ior;
                    187:        struct ifnet *ifp = &sc->sc_if;
                    188: 
                    189:        /*
                    190:         * Drop packets if interface is down.
                    191:         */
                    192:        if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) {
                    193:                while (1) {
                    194:                        IF_DEQUEUE(&ifp->if_snd, ior);
                    195:                        if (ior == 0)
                    196:                                return;
                    197:                        iodone(ior);
                    198:                }
                    199:        }
                    200:        /*
                    201:         * If transmitter is busy, bail out.
                    202:         */
                    203:        if (sc->sc_oactive)
                    204:                return;
                    205: 
                    206:        /*
                    207:         * Dequeue a packet.
                    208:         */
                    209:        IF_DEQUEUE(&ifp->if_snd, ior);
                    210:        if (ior == 0)
                    211:                return;
                    212: 
                    213:        /* Mask interrupts from the ethercard. */
                    214:        outb( sc->sc_port + EN0_IMR, 0x00);
                    215: 
                    216:        if (sc->sc_pingpong) {
                    217:                int count, output_page;
                    218: 
                    219:                if (sc->sc_tx1 == 0) {
                    220:                        output_page = sc->sc_txstrtpg;
                    221:                        sc->sc_tx1 = count = (*sc->sc_output)(sc,
                    222:                                                              ior->io_count,
                    223:                                                              ior->io_data,
                    224:                                                              sc->sc_txstrtpg);
                    225:                } else if (sc->sc_tx2 == 0) {
                    226:                        output_page = sc->sc_txstrtpg + 6;
                    227:                        sc->sc_tx2 = count = (*sc->sc_output)(sc,
                    228:                                                              ior->io_count,
                    229:                                                              ior->io_data,
                    230:                                                              output_page);
                    231:                } else {
                    232:                        sc->sc_oactive = 1;
                    233:                        IF_PREPEND(&ifp->if_snd, ior);
                    234:                        return;
                    235:                }
                    236: 
                    237:                DEBUGF({
                    238:                        struct ether_header *eh;
                    239: 
                    240:                        eh =  (struct ether_header *)ior->io_data;
                    241:                        printf("send: %s%d: %x:%x:%x:%x:%x:%x, "
                    242:                               "olen %d, len %d\n",
                    243:                               sc->sc_name, sc->sc_unit,
                    244:                               eh->ether_dhost[0], eh->ether_dhost[1],
                    245:                               eh->ether_dhost[2], eh->ether_dhost[3],
                    246:                               eh->ether_dhost[4], eh->ether_dhost[5],
                    247:                               ior->io_count, count);
                    248:                });
                    249: 
                    250:                if (!sc->sc_txing) {
                    251:                        nsxmit(sc, count, output_page);
                    252:                        if (output_page == sc->sc_txstrtpg)
                    253:                                sc->sc_tx1 = -1, sc->sc_lasttx = -1;
                    254:                        else
                    255:                                sc->sc_tx2 = -1, sc->sc_lasttx = -2;
                    256:                }
                    257:                sc->sc_oactive = (sc->sc_tx1 && sc->sc_tx2);
                    258:        } else {
                    259:                int count;
                    260: 
                    261:                count = (*sc->sc_output)(sc, ior->io_count,
                    262:                                         ior->io_data, sc->sc_txstrtpg);
                    263: 
                    264:                DEBUGF({
                    265:                        struct ether_header *eh;
                    266: 
                    267:                        eh =  (struct ether_header *)ior->io_data;
                    268:                        printf("send: %s%d: %x:%x:%x:%x:%x:%x, "
                    269:                               "olen %d, len %d\n",
                    270:                               sc->sc_name, sc->sc_unit,
                    271:                               eh->ether_dhost[0], eh->ether_dhost[1],
                    272:                               eh->ether_dhost[2], eh->ether_dhost[3],
                    273:                               eh->ether_dhost[4], eh->ether_dhost[5],
                    274:                               ior->io_count, count);
                    275:                });
                    276: 
                    277:                nsxmit(sc, count, sc->sc_txstrtpg);
                    278:                sc->sc_oactive = 1;
                    279:        }
                    280: 
                    281:        /* reenable 8390 interrupts. */ 
                    282:        outb_p(sc->sc_port + EN0_IMR, ENISR_ALL);
                    283:        
                    284:        iodone(ior);
                    285: }
                    286: 
                    287: /*
                    288:  * Interrupt routine.
                    289:  * Called by board level driver.
                    290:  */
                    291: void
                    292: nsintr(sc)
                    293:        struct nssoftc *sc;
                    294: {
                    295:        int port = sc->sc_port;
                    296:        int interrupts, boguscount = 0;
                    297:        struct ifnet *ifp = &sc->sc_if;
                    298: 
                    299:        if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) {
                    300:                DEBUGF(printf("nsintr: %s%d: interface down\n",
                    301:                              sc->sc_name, sc->sc_unit));
                    302:                return;
                    303:        }
                    304: 
                    305:        /*
                    306:         * Change to page 0 and read intr status reg.
                    307:         */
                    308:        outb_p(port + E8390_CMD, E8390_NODMA+E8390_PAGE0);
                    309: 
                    310:        while ((interrupts = inb_p(port + EN0_ISR)) != 0 && ++boguscount < 9) {
                    311:                if (interrupts & ENISR_RDC) {
                    312:                        /*
                    313:                         * Ack meaningless DMA complete.
                    314:                         */
                    315:                        outb_p(port + EN0_ISR, ENISR_RDC);
                    316:                }
                    317:                
                    318:                if (interrupts & ENISR_OVER) 
                    319:                        nsrxoverrun(sc);
                    320:                else if (interrupts & (ENISR_RX+ENISR_RX_ERR)) {
                    321:                        nsrint(sc);
                    322:                }
                    323:                
                    324:                if (interrupts & ENISR_TX) {
                    325:                        nsxint(sc);
                    326:                }
                    327:                else if (interrupts & ENISR_COUNTERS) {
                    328:                        /*
                    329:                         * XXX - We really should be storing statistics 
                    330:                         * about the interface.  For now we just drop them.
                    331:                         */
                    332: 
                    333:                        /* reading resets the counters! */
                    334:                        (void) inb_p(port + EN0_COUNTER0);      /* frame */
                    335:                        (void) inb_p(port + EN0_COUNTER1);      /* crc */
                    336:                        (void) inb_p(port + EN0_COUNTER2);      /* miss */
                    337: 
                    338:                        DEBUGF(printf("%s%d: acked counter interrupt.\n",
                    339:                                      sc->sc_name, sc->sc_unit));
                    340: 
                    341:                        outb_p(port + EN0_ISR, ENISR_COUNTERS); /* ack intr */
                    342:                }
                    343:                
                    344:                if (interrupts & ENISR_TX_ERR) {
                    345:                        DEBUGF(printf("acking transmit error\n"));
                    346:                        outb_p(port + EN0_ISR, ENISR_TX_ERR);   /* ack intr */
                    347:                }
                    348: 
                    349:                outb_p(port + E8390_CMD, E8390_NODMA+E8390_PAGE0+E8390_START);
                    350:        }
                    351: 
                    352:        DEBUGF({
                    353:                if (interrupts) {
                    354:                        printf("%s%d: unknown interrupt 0x%x",
                    355:                               sc->sc_name, sc->sc_unit, interrupts);
                    356:                        outb_p(port + E8390_CMD,
                    357:                               E8390_NODMA+E8390_PAGE0+E8390_START);
                    358:                        outb_p(port + EN0_ISR, 0xff);   /* ack all intrs */
                    359:                }
                    360:        })
                    361: }
                    362: 
                    363: /*
                    364:  * Process a transmit interrupt.
                    365:  */
                    366: void
                    367: nsxint(sc)
                    368:        struct nssoftc *sc;
                    369: {
                    370:        int port = sc->sc_port, status;
                    371:        struct ifnet *ifp = &sc->sc_if;
                    372: 
                    373:        status = inb(port + EN0_TSR);
                    374:        outb_p(port + EN0_ISR, ENISR_TX);       /* ack intr */
                    375: 
                    376:        sc->sc_txing = 0;
                    377:        sc->sc_timer = 0;
                    378:        sc->sc_oactive = 0;
                    379: 
                    380:        if (sc->sc_pingpong) {
                    381:                if (sc->sc_tx1 < 0) {
                    382:                        if (sc->sc_lasttx != 1 && sc->sc_lasttx != -1)
                    383:                                printf("%s%d: bogus last_tx_buffer %d,"
                    384:                                       "tx1 = %d\n",
                    385:                                       sc->sc_name, sc->sc_unit,
                    386:                                       sc->sc_lasttx, sc->sc_tx1);
                    387:                        sc->sc_tx1 = 0;
                    388:                        if (sc->sc_tx2 > 0) {
                    389:                                nsxmit(sc, sc->sc_tx2, sc->sc_txstrtpg + 6);
                    390:                                sc->sc_tx2 = -1;
                    391:                                sc->sc_lasttx = 2;
                    392:                        } else
                    393:                                sc->sc_lasttx = 20;
                    394:                } else if (sc->sc_tx2 < 0) {
                    395:                        if (sc->sc_lasttx != 2 && sc->sc_lasttx != -2)
                    396:                                printf("%s%d: bogus last_tx_buffer %d,"
                    397:                                       "tx2 = %d\n",
                    398:                                       sc->sc_name, sc->sc_unit,
                    399:                                       sc->sc_lasttx, sc->sc_tx2);
                    400:                        sc->sc_tx2 = 0;
                    401:                        if (sc->sc_tx1 > 0) {
                    402:                                nsxmit(sc, sc->sc_tx1, sc->sc_txstrtpg);
                    403:                                sc->sc_tx1 = -1;
                    404:                                sc->sc_lasttx = 1;
                    405:                        } else
                    406:                                sc->sc_lasttx = 10;
                    407:                } else
                    408:                        printf("%s%d: unexpected TX-done interrupt, "
                    409:                               "lasttx = %d\n",
                    410:                               sc->sc_name, sc->sc_unit, sc->sc_lasttx);
                    411:        }
                    412:        /*
                    413:         * Update stats.
                    414:         */
                    415:        if (status & ENTSR_COL) {
                    416:                if (status & ENTSR_ABT)
                    417:                        ifp->if_collisions += 16;
                    418:                else
                    419:                        ifp->if_collisions += inb(port + EN0_NCR);
                    420:        }
                    421:        if (status & ENTSR_PTX) {
                    422:                DEBUGF(printf("sent: %s%d\n", sc->sc_name, sc->sc_unit));
                    423:                ifp->if_opackets++;
                    424:        } else
                    425:                ifp->if_oerrors++;
                    426: 
                    427:        /*
                    428:         * Start output on interface.
                    429:         */
                    430:        nsstart(sc);
                    431: }
                    432: 
                    433: /*
                    434:  * Process a receive interrupt.
                    435:  */
                    436: void
                    437: nsrint(sc)
                    438:        struct nssoftc *sc;
                    439: {
                    440:        int port = sc->sc_port;
                    441:        int rxing_page, this_frame, next_frame, current_offset;
                    442:        int rx_pkt_count = 0;
                    443:        int num_rx_pages = sc->sc_stoppg - sc->sc_rxstrtpg;
                    444:        struct nspkthdr rx_frame;
                    445:        struct ifnet *ifp = &sc->sc_if;
                    446: 
                    447:        while (++rx_pkt_count < 10) {
                    448:                int pkt_len;
                    449: 
                    450:                /*
                    451:                 * Get the rx page (incoming packet pointer).
                    452:                 */
                    453:                outb_p(port + E8390_CMD, E8390_NODMA+E8390_PAGE1);
                    454:                rxing_page = inb_p(port + EN1_CURPAG);
                    455:                outb_p(port + E8390_CMD, E8390_NODMA+E8390_PAGE0);
                    456: 
                    457:                /*
                    458:                 * Remove one frame from the ring.
                    459:                 * Boundary is always a page behind.
                    460:                 */
                    461:                this_frame = inb_p(port + EN0_BOUNDARY) + 1;
                    462:                if (this_frame >= sc->sc_stoppg)
                    463:                        this_frame = sc->sc_rxstrtpg;
                    464: 
                    465:                DEBUGF({
                    466:                        if (this_frame != sc->sc_curpg)
                    467:                                printf("%s%d: mismatched read page pointers "
                    468:                                       "%x vs %x\n",
                    469:                                       sc->sc_name, sc->sc_unit,
                    470:                                       this_frame, sc->sc_curpg);
                    471:                });
                    472: 
                    473:                if (this_frame == rxing_page) {
                    474:                        DEBUGF(printf("this_frame = rxing_page!\n"));
                    475:                        break;
                    476:                }
                    477: 
                    478:                current_offset = this_frame << 8;
                    479:                (*sc->sc_input)(sc, sizeof(rx_frame), (char *)&rx_frame,
                    480:                                current_offset);
                    481: 
                    482:                pkt_len = rx_frame.count - sizeof(rx_frame);
                    483: 
                    484:                next_frame = this_frame + 1 + ((pkt_len + 4) >> 8);
                    485: 
                    486:                if (rx_frame.next != next_frame
                    487:                    && rx_frame.next != next_frame + 1
                    488:                    && rx_frame.next != next_frame - num_rx_pages
                    489:                    && rx_frame.next != next_frame + 1 - num_rx_pages) {
                    490:                        sc->sc_curpg = rxing_page;
                    491:                        outb(port + EN0_BOUNDARY, sc->sc_curpg - 1);
                    492:                        ifp->if_ierrors++;
                    493:                        DEBUGF(printf("INPUT ERROR?\n"));
                    494:                        continue;
                    495:                }
                    496:                if (pkt_len < 60 || pkt_len > 1518) {
                    497:                        ifp->if_ierrors++;
                    498:                        DEBUGF(printf("%s%d: bad packet length %d\n",
                    499:                                      sc->sc_name, sc->sc_unit, pkt_len));
                    500:                } else if ((rx_frame.status & 0x0f) == ENRSR_RXOK) {
                    501:                        ipc_kmsg_t kmsg;
                    502: 
                    503:                        kmsg = net_kmsg_get();
                    504:                        if (kmsg == 0) {
                    505:                                DEBUGF(printf("%s%d: dropped packet\n",
                    506:                                              sc->sc_name, sc->sc_unit));
                    507:                                ifp->if_rcvdrops++;
                    508:                        } else {
                    509:                                int len, off;
                    510:                                struct ether_header *eh;
                    511:                                struct packet_header *pkt;
                    512: 
                    513:                                ifp->if_ipackets++;
                    514:                                off = current_offset + sizeof(rx_frame);
                    515:                                eh = ((struct ether_header *)
                    516:                                      (&net_kmsg(kmsg)->header[0]));
                    517:                                (*sc->sc_input)(sc,
                    518:                                                sizeof(struct ether_header),
                    519:                                                (char *)eh, off);
                    520:                                off += sizeof(struct ether_header);
                    521:                                len = pkt_len - sizeof(struct ether_header);
                    522: 
                    523:                                DEBUGF(printf("rcv: %s%d: %x:%x:%x:%x:%x:%x, "
                    524:                                              "len %d, type 0x%x\n",
                    525:                                              sc->sc_name, sc->sc_unit,
                    526:                                              eh->ether_shost[0],
                    527:                                              eh->ether_shost[1],
                    528:                                              eh->ether_shost[2],
                    529:                                              eh->ether_shost[3],
                    530:                                              eh->ether_shost[4],
                    531:                                              eh->ether_shost[5],
                    532:                                              len, eh->ether_type));
                    533: 
                    534:                                pkt = ((struct packet_header *)
                    535:                                       (&net_kmsg(kmsg)->packet[0]));
                    536:                                (*sc->sc_input)(sc, len, (char *)(pkt+1), off);
                    537:                                pkt->type = eh->ether_type;
                    538:                                pkt->length = len+sizeof(struct packet_header);
                    539:                                net_packet(ifp, kmsg, pkt->length,
                    540:                                           ethernet_priority(kmsg));
                    541:                        }
                    542:                } else {
                    543:                        DEBUGF(printf("%s%d: bogus packet: "
                    544:                                      "status=0x%x nxpg=0x%x size=%d\n",
                    545:                                      sc->sc_name, sc->sc_unit,
                    546:                                      rx_frame.status, rx_frame.next,
                    547:                                      rx_frame.count));
                    548:                        ifp->if_ierrors++;
                    549:                }
                    550:                next_frame = rx_frame.next;
                    551:                if (next_frame >= sc->sc_stoppg) {
                    552:                        DEBUGF(printf("%s%d: next frame inconsistency, 0x%x\n",
                    553:                                      sc->sc_name, sc->sc_unit, next_frame));
                    554:                        next_frame = sc->sc_rxstrtpg;
                    555:                }
                    556:                sc->sc_curpg = next_frame;
                    557:                outb(port + EN0_BOUNDARY, next_frame - 1);
                    558:        }
                    559: 
                    560:        /*
                    561:         * Bug alert!  Reset ENISR_OVER to avoid spurious overruns!
                    562:         */
                    563:        outb_p(port + EN0_ISR, ENISR_RX+ENISR_RX_ERR+ENISR_OVER);
                    564: }
                    565: 
                    566: /*
                    567:  * Handle a receive overrun condition.
                    568:  *
                    569:  * XXX - this needs to be gone over in light of the NS documentation.
                    570:  */
                    571: void
                    572: nsrxoverrun(sc)
                    573:        struct nssoftc *sc;
                    574: {
                    575:        int port = sc->sc_port, i;
                    576:        extern unsigned delaycount;
                    577: 
                    578:        printf("%s%d: receive overrun\n", sc->sc_name, sc->sc_unit);
                    579: 
                    580:        /*
                    581:         * We should already be stopped and in page0, but just to be sure...
                    582:         */
                    583:        outb_p(port + E8390_CMD, E8390_NODMA+E8390_PAGE0+E8390_STOP);
                    584: 
                    585:        /*
                    586:         * Clear remote byte counter registers.
                    587:         */
                    588:        outb_p(port + EN0_RCNTLO, 0);
                    589:        outb_p(port + EN0_RCNTHI, 0);
                    590: 
                    591:        /*
                    592:         * Wait for reset to complete.
                    593:         */
                    594:        for (i = delaycount*2; i && !(inb_p(port+EN0_ISR) & ENISR_RESET); i--)
                    595:                ;
                    596:        if (i == 0) {
                    597:                printf("%s%d: reset did not complete at overrun\n",
                    598:                       sc->sc_name, sc->sc_unit);
                    599:                nsinit(sc);
                    600:                return;
                    601:        }
                    602:        /*
                    603:         * Disable transmitter.
                    604:         */
                    605:        outb_p(port + EN0_TXCR, E8390_TXOFF);
                    606: 
                    607:        /*
                    608:         * Remove packets.
                    609:         */
                    610:        nsrint(sc);
                    611: 
                    612:        outb_p(port + EN0_ISR, 0xff);
                    613:        outb_p(port + E8390_CMD, E8390_NODMA+E8390_PAGE0+E8390_START);
                    614:        outb_p(port + EN0_TXCR, E8390_TXCONFIG);
                    615: }
                    616: 
                    617: /*
                    618:  * Trigger a transmit start.
                    619:  */
                    620: void
                    621: nsxmit(sc, length, start_page)
                    622:        struct nssoftc *sc;
                    623:        unsigned length;
                    624:        int start_page;
                    625: {
                    626:        int port = sc->sc_port;
                    627: 
                    628:        sc->sc_txing = 1;
                    629:        outb_p(port, E8390_NODMA+E8390_PAGE0);
                    630:        if (inb_p(port) & E8390_TRANS) {
                    631:                printf("%s%d: nsxmit() called with the transmitter busy\n",
                    632:                       sc->sc_name, sc->sc_unit);
                    633:                return;
                    634:        }
                    635:        outb_p(port + EN0_TCNTLO, length & 0xff);
                    636:        outb_p(port + EN0_TCNTHI, (length >> 8) & 0xff);
                    637:        outb_p(port + EN0_TPSR, start_page);
                    638:        outb_p(port, E8390_NODMA+E8390_TRANS+E8390_START);
                    639:        sc->sc_timer = 4;
                    640: }
                    641: 
                    642: #endif /* NUL > 0 || NWD > 0 */

unix.superglobalmegacorp.com

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