Annotation of Gnu-Mach/i386/i386at/gpl/if_ns.c, revision 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.