[BACK]Return to if_sn.c CVS log [TXT][DIR] Up to [local] / sys / arch / mac68k / dev

Annotation of sys/arch/mac68k/dev/if_sn.c, Revision 1.1.1.1

1.1       nbrk        1: /*    $OpenBSD: if_sn.c,v 1.46 2007/01/12 16:31:21 martin Exp $        */
                      2: /*    $NetBSD: if_sn.c,v 1.13 1997/04/25 03:40:10 briggs Exp $        */
                      3:
                      4: /*
                      5:  * National Semiconductor  DP8393X SONIC Driver
                      6:  * Copyright (c) 1991   Algorithmics Ltd (http://www.algor.co.uk)
                      7:  * You may use, copy, and modify this program so long as you retain the
                      8:  * copyright line.
                      9:  *
                     10:  * This driver has been substantially modified since Algorithmics donated
                     11:  * it.
                     12:  *
                     13:  *   Denton Gentry <denny1@home.com>
                     14:  * and also
                     15:  *   Yanagisawa Takeshi <yanagisw@aa.ap.titech.ac.jp>
                     16:  * did the work to get this running on the Macintosh.
                     17:  */
                     18:
                     19: #include <sys/param.h>
                     20: #include <sys/systm.h>
                     21: #include <sys/mbuf.h>
                     22: #include <sys/buf.h>
                     23: #include <sys/protosw.h>
                     24: #include <sys/socket.h>
                     25: #include <sys/syslog.h>
                     26: #include <sys/ioctl.h>
                     27: #include <sys/errno.h>
                     28: #include <sys/device.h>
                     29:
                     30: #include <net/if.h>
                     31: #include <net/if_dl.h>
                     32: #include <net/netisr.h>
                     33:
                     34: #ifdef INET
                     35: #include <netinet/in.h>
                     36: #include <netinet/in_systm.h>
                     37: #include <netinet/in_var.h>
                     38: #include <netinet/ip.h>
                     39: #include <netinet/if_ether.h>
                     40: #endif
                     41:
                     42: #include <uvm/uvm_extern.h>
                     43:
                     44: #include "bpfilter.h"
                     45: #if NBPFILTER > 0
                     46: #include <net/bpf.h>
                     47: #include <net/bpfdesc.h>
                     48: #endif
                     49:
                     50: #include <machine/bus.h>
                     51: #include <machine/cpu.h>
                     52: /* #include <machine/viareg.h> */
                     53: #include <mac68k/dev/if_snreg.h>
                     54: #include <mac68k/dev/if_snvar.h>
                     55:
                     56: static void    snwatchdog(struct ifnet *);
                     57: static int     sninit(struct sn_softc *);
                     58: static int     snstop(struct sn_softc *);
                     59: static int     snioctl(struct ifnet *, u_long, caddr_t);
                     60: static void    snstart(struct ifnet *);
                     61: static void    snreset(struct sn_softc *);
                     62:
                     63: static void    caminitialise(struct sn_softc *);
                     64: static void    camentry(struct sn_softc *, int, u_char *);
                     65: static void    camprogram(struct sn_softc *);
                     66: static void    initialise_tda(struct sn_softc *);
                     67: static void    initialise_rda(struct sn_softc *);
                     68: static void    initialise_rra(struct sn_softc *);
                     69: #ifdef SNDEBUG
                     70: static void    camdump(struct sn_softc *);
                     71: #endif
                     72:
                     73: static void    sonictxint(struct sn_softc *);
                     74: static void    sonicrxint(struct sn_softc *);
                     75:
                     76: static __inline__ int  sonicput(struct sn_softc *, struct mbuf *,
                     77:                            int);
                     78: static __inline__ int  sonic_read(struct sn_softc *, caddr_t, int);
                     79: static __inline__ struct mbuf *sonic_get(struct sn_softc *, caddr_t, int);
                     80:
                     81: struct cfdriver sn_cd = {
                     82:        NULL, "sn", DV_IFNET
                     83: };
                     84:
                     85: /*
                     86:  * SONIC buffers need to be aligned 16 or 32 bit aligned.
                     87:  * These macros calculate and verify alignment.
                     88:  */
                     89: #define        ROUNDUP(p, N)   (((int) p + N - 1) & ~(N - 1))
                     90:
                     91: #define SOALIGN(m, array)      (m ? (ROUNDUP(array, 4)) : (ROUNDUP(array, 2)))
                     92:
                     93: #define LOWER(x) ((unsigned)(x) & 0xffff)
                     94: #define UPPER(x) ((unsigned)(x) >> 16)
                     95:
                     96: /*
                     97:  * Interface exists: make available by filling in network interface
                     98:  * record.  System will initialize the interface when it is ready
                     99:  * to accept packets.
                    100:  */
                    101: int
                    102: snsetup(struct sn_softc *sc, u_int8_t *lladdr)
                    103: {
                    104:        struct ifnet *ifp = &sc->sc_if;
                    105:        struct pglist pglist;
                    106:        vm_page_t pg;
                    107:        paddr_t phys;
                    108:        vaddr_t p, pp;
                    109:        int     i, offset, error;
                    110:
                    111:        /*
                    112:         * XXX if_sn.c is intended to be MI. Should it allocate memory
                    113:         * for its descriptor areas, or expect the MD attach code
                    114:         * to do that?
                    115:         */
                    116:        TAILQ_INIT(&pglist);
                    117:        error = uvm_pglistalloc(SN_NPAGES * PAGE_SIZE, 0, -PAGE_SIZE,
                    118:            PAGE_SIZE, 0, &pglist, 1, 0);
                    119:        if (error != 0) {
                    120:                printf(": could not allocate descriptor memory\n");
                    121:                return (error);
                    122:        }
                    123:
                    124:        /*
                    125:         * Map the pages uncached.
                    126:         */
                    127:        sc->space = uvm_km_valloc(kernel_map, SN_NPAGES * PAGE_SIZE);
                    128:        if (sc->space == NULL) {
                    129:                printf(": could not map descriptor memory\n");
                    130:                uvm_pglistfree(&pglist);
                    131:                return (ENOMEM);
                    132:        }
                    133:
                    134:        phys = VM_PAGE_TO_PHYS(TAILQ_FIRST(&pglist));
                    135:        p = pp = sc->space;
                    136:        TAILQ_FOREACH(pg, &pglist, pageq) {
                    137:                pmap_enter_cache(pmap_kernel(), p, VM_PAGE_TO_PHYS(pg),
                    138:                    UVM_PROT_RW, UVM_PROT_RW | PMAP_WIRED, PG_CI);
                    139:                p += PAGE_SIZE;
                    140:        }
                    141:        pmap_update(pmap_kernel());
                    142:        p = pp;
                    143:
                    144:        /*
                    145:         * Put the pup in reset mode (sninit() will fix it later),
                    146:         * stop the timer, disable all interrupts and clear any interrupts.
                    147:         */
                    148:        NIC_PUT(sc, SNR_CR, CR_STP);
                    149:        wbflush();
                    150:        NIC_PUT(sc, SNR_CR, CR_RST);
                    151:        wbflush();
                    152:        NIC_PUT(sc, SNR_IMR, 0);
                    153:        wbflush();
                    154:        NIC_PUT(sc, SNR_ISR, ISR_ALL);
                    155:        wbflush();
                    156:
                    157:        for (i = 0; i < NRRA; i++) {
                    158:                sc->p_rra[i] = (void *)p;
                    159:                sc->v_rra[i] = (p - sc->space) + phys;
                    160:                p += RXRSRC_SIZE(sc);
                    161:        }
                    162:        sc->v_rea = (p - sc->space) + phys;
                    163:
                    164:        p = SOALIGN(sc, p);
                    165:
                    166:        sc->p_cda = (void *)(p);
                    167:        sc->v_cda = (p - sc->space) + phys;
                    168:        p += CDA_SIZE(sc);
                    169:
                    170:        p = SOALIGN(sc, p);
                    171:
                    172:        for (i = 0; i < NTDA; i++) {
                    173:                struct mtd *mtdp = &sc->mtda[i];
                    174:                mtdp->mtd_txp = (void *)p;
                    175:                mtdp->mtd_vtxp = (p - sc->space) + phys;
                    176:                p += TXP_SIZE(sc);
                    177:        }
                    178:
                    179:        p = SOALIGN(sc, p);
                    180:
                    181: #ifdef DIAGNOSTIC
                    182:        if ((p - pp) > PAGE_SIZE) {
                    183:                printf (": sizeof RRA (%ld) + CDA (%ld) +"
                    184:                    "TDA (%ld) > PAGE_SIZE (%d). Punt!\n",
                    185:                    (ulong)sc->p_cda - (ulong)sc->p_rra[0],
                    186:                    (ulong)sc->mtda[0].mtd_txp - (ulong)sc->p_cda,
                    187:                    (ulong)p - (ulong)sc->mtda[0].mtd_txp,
                    188:                    PAGE_SIZE);
                    189:                return (EINVAL);
                    190:        }
                    191: #endif
                    192:
                    193:        p = pp + PAGE_SIZE;
                    194:        pp = p;
                    195:
                    196:        sc->sc_nrda = PAGE_SIZE / RXPKT_SIZE(sc);
                    197:        sc->p_rda = (caddr_t)p;
                    198:        sc->v_rda = (p - sc->space) + phys;
                    199:
                    200:        p = pp + PAGE_SIZE;
                    201:
                    202:        for (i = 0; i < NRBA; i++) {
                    203:                sc->rbuf[i] = (caddr_t)p;
                    204:                sc->rbuf_phys[i] = (p - sc->space) + phys;
                    205:                p += PAGE_SIZE;
                    206:        }
                    207:
                    208:        pp = p;
                    209:        offset = 0;
                    210:        for (i = 0; i < NTDA; i++) {
                    211:                struct mtd *mtdp = &sc->mtda[i];
                    212:
                    213:                mtdp->mtd_buf = (caddr_t)p;
                    214:                mtdp->mtd_vbuf = (p - sc->space) + phys;
                    215:                offset += TXBSIZE;
                    216:                if (offset < PAGE_SIZE - TXBSIZE) {
                    217:                        p += TXBSIZE;
                    218:                } else {
                    219:                        p = pp + PAGE_SIZE;
                    220:                        pp = p;
                    221:                        offset = 0;
                    222:                }
                    223:        }
                    224:
                    225: #ifdef SNDEBUG
                    226:        camdump(sc);
                    227: #endif
                    228:        printf("address %s\n", ether_sprintf(lladdr));
                    229:
                    230: #ifdef SNDEBUG
                    231:        printf("%s: buffers: rra=%p cda=%p rda=%p tda=%p\n",
                    232:            sc->sc_dev.dv_xname, sc->p_rra[0], sc->p_cda,
                    233:            sc->p_rda, sc->mtda[0].mtd_txp);
                    234: #endif
                    235:
                    236:        bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
                    237:        bcopy(lladdr, sc->sc_enaddr, ETHER_ADDR_LEN);
                    238:
                    239:        ifp->if_softc = sc;
                    240:        ifp->if_ioctl = snioctl;
                    241:        ifp->if_start = snstart;
                    242:        ifp->if_flags =
                    243:            IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST;
                    244:        ifp->if_watchdog = snwatchdog;
                    245:        if_attach(ifp);
                    246:        ether_ifattach(ifp);
                    247:
                    248:        return (0);
                    249: }
                    250:
                    251: static int
                    252: snioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
                    253: {
                    254:        struct ifaddr *ifa;
                    255:        struct ifreq *ifr;
                    256:        struct sn_softc *sc = ifp->if_softc;
                    257:        int     s = splnet(), err = 0;
                    258:
                    259:        switch (cmd) {
                    260:
                    261:        case SIOCSIFADDR:
                    262:                ifa = (struct ifaddr *)data;
                    263:                ifp->if_flags |= IFF_UP;
                    264:                switch (ifa->ifa_addr->sa_family) {
                    265: #ifdef INET
                    266:                case AF_INET:
                    267:                        (void)sninit(sc);
                    268:                        arp_ifinit(&sc->sc_arpcom, ifa);
                    269:                        break;
                    270: #endif
                    271:                default:
                    272:                        (void)sninit(sc);
                    273:                        break;
                    274:                }
                    275:                break;
                    276:
                    277:        case SIOCSIFFLAGS:
                    278:                if ((ifp->if_flags & IFF_UP) == 0 &&
                    279:                    (ifp->if_flags & IFF_RUNNING) != 0) {
                    280:                        /*
                    281:                         * If interface is marked down and it is running,
                    282:                         * then stop it.
                    283:                         */
                    284:                        snstop(sc);
                    285:                        ifp->if_flags &= ~IFF_RUNNING;
                    286:                } else if ((ifp->if_flags & IFF_UP) != 0 &&
                    287:                            (ifp->if_flags & IFF_RUNNING) == 0) {
                    288:                        /*
                    289:                         * If interface is marked up and it is stopped,
                    290:                         * then start it.
                    291:                         */
                    292:                        (void)sninit(sc);
                    293:                } else {
                    294:                        /*
                    295:                         * reset the interface to pick up any other changes
                    296:                         * in flags
                    297:                         */
                    298:                        snreset(sc);
                    299:                        snstart(ifp);
                    300:                }
                    301:                break;
                    302:
                    303:        case SIOCADDMULTI:
                    304:        case SIOCDELMULTI:
                    305:                ifr = (struct ifreq *) data;
                    306:                if (cmd == SIOCADDMULTI)
                    307:                        err = ether_addmulti(ifr, &sc->sc_arpcom);
                    308:                else
                    309:                        err = ether_delmulti(ifr, &sc->sc_arpcom);
                    310:
                    311:                if (err == ENETRESET) {
                    312:                        /*
                    313:                         * Multicast list has changed; set the hardware
                    314:                         * filter accordingly. But remember UP flag!
                    315:                         */
                    316:                        if (ifp->if_flags & IFF_RUNNING)
                    317:                                snreset(sc);
                    318:                        err = 0;
                    319:                }
                    320:                break;
                    321:        default:
                    322:                err = EINVAL;
                    323:        }
                    324:        splx(s);
                    325:        return (err);
                    326: }
                    327:
                    328: /*
                    329:  * Encapsulate a packet of type family for the local net.
                    330:  */
                    331: static void
                    332: snstart(struct ifnet *ifp)
                    333: {
                    334:        struct sn_softc *sc = ifp->if_softc;
                    335:        struct mbuf     *m;
                    336:        int             mtd_next;
                    337:
                    338:        if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
                    339:                return;
                    340:
                    341: outloop:
                    342:        /* Check for room in the xmit buffer. */
                    343:        if ((mtd_next = (sc->mtd_free + 1)) == NTDA)
                    344:                mtd_next = 0;
                    345:
                    346:        if (mtd_next == sc->mtd_hw) {
                    347:                ifp->if_flags |= IFF_OACTIVE;
                    348:                return;
                    349:        }
                    350:
                    351:        IF_DEQUEUE(&ifp->if_snd, m);
                    352:        if (m == NULL)
                    353:                return;
                    354:
                    355:        /* We need the header for m_pkthdr.len. */
                    356:        if ((m->m_flags & M_PKTHDR) == 0)
                    357:                panic("%s: snstart: no header mbuf", sc->sc_dev.dv_xname);
                    358:
                    359: #if NBPFILTER > 0
                    360:        /*
                    361:         * If bpf is listening on this interface, let it
                    362:         * see the packet before we commit it to the wire.
                    363:         */
                    364:        if (ifp->if_bpf)
                    365:                bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);
                    366: #endif
                    367:
                    368:        /*
                    369:         * If there is nothing in the o/p queue, and there is room in
                    370:         * the Tx ring, then send the packet directly.  Otherwise append
                    371:         * it to the o/p queue.
                    372:         */
                    373:        if ((sonicput(sc, m, mtd_next)) > 0) {
                    374:        } else {
                    375:                IF_PREPEND(&ifp->if_snd, m);
                    376:                return;
                    377:        }
                    378:
                    379:        sc->mtd_prev = sc->mtd_free;
                    380:        sc->mtd_free = mtd_next;
                    381:
                    382:        ifp->if_opackets++;             /* # of pkts */
                    383:
                    384:        /* Jump back for possibly more punishment. */
                    385:        goto outloop;
                    386: }
                    387:
                    388: /*
                    389:  * reset and restart the SONIC.  Called in case of fatal
                    390:  * hardware/software errors.
                    391:  */
                    392: static void
                    393: snreset(struct sn_softc *sc)
                    394: {
                    395:        snstop(sc);
                    396:        sninit(sc);
                    397: }
                    398:
                    399: static int
                    400: sninit(struct sn_softc *sc)
                    401: {
                    402:        u_long  s_rcr;
                    403:        int     s;
                    404:
                    405:        if (sc->sc_if.if_flags & IFF_RUNNING)
                    406:                /* already running */
                    407:                return (0);
                    408:
                    409:        s = splnet();
                    410:
                    411:        NIC_PUT(sc, SNR_CR, CR_RST);    /* DCR only accessible in reset mode! */
                    412:
                    413:        /* config it */
                    414:        NIC_PUT(sc, SNR_DCR, (sc->snr_dcr |
                    415:                (sc->bitmode ? DCR_DW32 : DCR_DW16)));
                    416:        NIC_PUT(sc, SNR_DCR2, sc->snr_dcr2);
                    417:
                    418:        s_rcr = RCR_BRD | RCR_LBNONE;
                    419:        if (sc->sc_if.if_flags & IFF_PROMISC)
                    420:                s_rcr |= RCR_PRO;
                    421:        if (sc->sc_if.if_flags & IFF_ALLMULTI)
                    422:                s_rcr |= RCR_AMC;
                    423:        NIC_PUT(sc, SNR_RCR, s_rcr);
                    424:
                    425:        NIC_PUT(sc, SNR_IMR, (IMR_PRXEN | IMR_PTXEN | IMR_TXEREN | IMR_LCDEN));
                    426:
                    427:        /* clear pending interrupts */
                    428:        NIC_PUT(sc, SNR_ISR, ISR_ALL);
                    429:
                    430:        /* clear tally counters */
                    431:        NIC_PUT(sc, SNR_CRCT, -1);
                    432:        NIC_PUT(sc, SNR_FAET, -1);
                    433:        NIC_PUT(sc, SNR_MPT, -1);
                    434:
                    435:        initialise_tda(sc);
                    436:        initialise_rda(sc);
                    437:        initialise_rra(sc);
                    438:
                    439:        /* enable the chip */
                    440:        NIC_PUT(sc, SNR_CR, 0);
                    441:        wbflush();
                    442:
                    443:        /* program the CAM */
                    444:        camprogram(sc);
                    445:
                    446:        /* get it to read resource descriptors */
                    447:        NIC_PUT(sc, SNR_CR, CR_RRRA);
                    448:        wbflush();
                    449:        while ((NIC_GET(sc, SNR_CR)) & CR_RRRA)
                    450:                continue;
                    451:
                    452:        /* enable rx */
                    453:        NIC_PUT(sc, SNR_CR, CR_RXEN);
                    454:        wbflush();
                    455:
                    456:        /* flag interface as "running" */
                    457:        sc->sc_if.if_flags |= IFF_RUNNING;
                    458:        sc->sc_if.if_flags &= ~IFF_OACTIVE;
                    459:
                    460:        splx(s);
                    461:        return (0);
                    462: }
                    463:
                    464: /*
                    465:  * close down an interface and free its buffers
                    466:  * Called on final close of device, or if sninit() fails
                    467:  * part way through.
                    468:  */
                    469: static int
                    470: snstop(struct sn_softc *sc)
                    471: {
                    472:        struct mtd *mtd;
                    473:        int     s = splnet();
                    474:
                    475:        /* stick chip in reset */
                    476:        NIC_PUT(sc, SNR_CR, CR_RST);
                    477:        wbflush();
                    478:
                    479:        /* free all receive buffers (currently static so nothing to do) */
                    480:
                    481:        /* free all pending transmit mbufs */
                    482:        while (sc->mtd_hw != sc->mtd_free) {
                    483:                mtd = &sc->mtda[sc->mtd_hw];
                    484:                if (mtd->mtd_mbuf)
                    485:                        m_freem(mtd->mtd_mbuf);
                    486:                if (++sc->mtd_hw == NTDA) sc->mtd_hw = 0;
                    487:        }
                    488:
                    489:        sc->sc_if.if_timer = 0;
                    490:        sc->sc_if.if_flags &= ~IFF_RUNNING;
                    491:
                    492:        splx(s);
                    493:        return (0);
                    494: }
                    495:
                    496: /*
                    497:  * Called if any Tx packets remain unsent after 5 seconds,
                    498:  * In all cases we just reset the chip, and any retransmission
                    499:  * will be handled by higher level protocol timeouts.
                    500:  */
                    501: static void
                    502: snwatchdog(struct ifnet *ifp)
                    503: {
                    504:        struct sn_softc *sc = ifp->if_softc;
                    505:        struct mtd *mtd;
                    506:
                    507:        if (sc->mtd_hw != sc->mtd_free) {
                    508:                /* something still pending for transmit */
                    509:                mtd = &sc->mtda[sc->mtd_hw];
                    510:                if (SRO(sc->bitmode, mtd->mtd_txp, TXP_STATUS) == 0)
                    511:                        log(LOG_ERR, "%s: Tx - timeout\n",
                    512:                            sc->sc_dev.dv_xname);
                    513:                else
                    514:                        log(LOG_ERR, "%s: Tx - lost interrupt\n",
                    515:                            sc->sc_dev.dv_xname);
                    516:                snreset(sc);
                    517:        }
                    518: }
                    519:
                    520: /*
                    521:  * stuff packet into sonic (at splnet)
                    522:  */
                    523: static __inline__ int
                    524: sonicput(struct sn_softc *sc, struct mbuf *m0, int mtd_next)
                    525: {
                    526:        struct mtd *mtdp;
                    527:        struct mbuf *m;
                    528:        u_char  *buff;
                    529:        void    *txp;
                    530:        u_int   len = 0;
                    531:        u_int   totlen = 0;
                    532:
                    533:        /* grab the replacement mtd */
                    534:        mtdp = &sc->mtda[sc->mtd_free];
                    535:
                    536:        buff = mtdp->mtd_buf;
                    537:
                    538:        /* this packet goes to mtdnext fill in the TDA */
                    539:        mtdp->mtd_mbuf = m0;
                    540:        txp = mtdp->mtd_txp;
                    541:
                    542:        /* Write to the config word. Every (NTDA/2)+1 packets we set an intr */
                    543:        if (sc->mtd_pint == 0) {
                    544:                sc->mtd_pint = NTDA/2;
                    545:                SWO(sc->bitmode, txp, TXP_CONFIG, TCR_PINT);
                    546:        } else {
                    547:                sc->mtd_pint--;
                    548:                SWO(sc->bitmode, txp, TXP_CONFIG, 0);
                    549:        }
                    550:
                    551:        for (m = m0; m; m = m->m_next) {
                    552:                u_char *data = mtod(m, u_char *);
                    553:                len = m->m_len;
                    554:                totlen += len;
                    555:                bcopy(data, buff, len);
                    556:                buff += len;
                    557:        }
                    558:        if (totlen >= TXBSIZE) {
                    559:                panic("%s: sonicput: packet overflow", sc->sc_dev.dv_xname);
                    560:        }
                    561:
                    562:        SWO(sc->bitmode, txp, TXP_FRAGOFF + (0 * TXP_FRAGSIZE) + TXP_FPTRLO,
                    563:            LOWER(mtdp->mtd_vbuf));
                    564:        SWO(sc->bitmode, txp, TXP_FRAGOFF + (0 * TXP_FRAGSIZE) + TXP_FPTRHI,
                    565:            UPPER(mtdp->mtd_vbuf));
                    566:
                    567:        if (totlen < ETHERMIN + ETHER_HDR_LEN) {
                    568:                int pad = ETHERMIN + ETHER_HDR_LEN - totlen;
                    569:                bzero(mtdp->mtd_buf + totlen, pad);
                    570:                totlen = ETHERMIN + ETHER_HDR_LEN;
                    571:        }
                    572:
                    573:        SWO(sc->bitmode, txp, TXP_FRAGOFF + (0 * TXP_FRAGSIZE) + TXP_FSIZE,
                    574:            totlen);
                    575:        SWO(sc->bitmode, txp, TXP_FRAGCNT, 1);
                    576:        SWO(sc->bitmode, txp, TXP_PKTSIZE, totlen);
                    577:
                    578:        /* link onto the next mtd that will be used */
                    579:        SWO(sc->bitmode, txp, TXP_FRAGOFF + (1 * TXP_FRAGSIZE) + TXP_FPTRLO,
                    580:            LOWER(sc->mtda[mtd_next].mtd_vtxp) | EOL);
                    581:
                    582:        /*
                    583:         * The previous txp.tlink currently contains a pointer to
                    584:         * our txp | EOL. Want to clear the EOL, so write our
                    585:         * pointer to the previous txp.
                    586:         */
                    587:        SWO(sc->bitmode, sc->mtda[sc->mtd_prev].mtd_txp, sc->mtd_tlinko,
                    588:            LOWER(mtdp->mtd_vtxp));
                    589:
                    590:        /* make sure chip is running */
                    591:        wbflush();
                    592:        NIC_PUT(sc, SNR_CR, CR_TXP);
                    593:        wbflush();
                    594:        sc->sc_if.if_timer = 5; /* 5 seconds to watch for failing to transmit */
                    595:
                    596:        return (totlen);
                    597: }
                    598:
                    599: /*
                    600:  * These are called from sonicioctl() when /etc/ifconfig is run to set
                    601:  * the address or switch the i/f on.
                    602:  */
                    603: /*
                    604:  * CAM support
                    605:  */
                    606: static void
                    607: caminitialise(struct sn_softc *sc)
                    608: {
                    609:        void    *p_cda = sc->p_cda;
                    610:        int     i;
                    611:        int     bitmode = sc->bitmode;
                    612:        int     camoffset;
                    613:
                    614:        for (i = 0; i < MAXCAM; i++) {
                    615:                camoffset = i * CDA_CAMDESC;
                    616:                SWO(bitmode, p_cda, (camoffset + CDA_CAMEP), i);
                    617:                SWO(bitmode, p_cda, (camoffset + CDA_CAMAP2), 0);
                    618:                SWO(bitmode, p_cda, (camoffset + CDA_CAMAP1), 0);
                    619:                SWO(bitmode, p_cda, (camoffset + CDA_CAMAP0), 0);
                    620:        }
                    621:        SWO(bitmode, p_cda, CDA_ENABLE, 0);
                    622: }
                    623:
                    624: static void
                    625: camentry(struct sn_softc *sc, int entry, u_char *ea)
                    626: {
                    627:        void    *p_cda = sc->p_cda;
                    628:        int     bitmode = sc->bitmode;
                    629:        int     camoffset = entry * CDA_CAMDESC;
                    630:
                    631:        SWO(bitmode, p_cda, camoffset + CDA_CAMEP, entry);
                    632:        SWO(bitmode, p_cda, camoffset + CDA_CAMAP2, (ea[5] << 8) | ea[4]);
                    633:        SWO(bitmode, p_cda, camoffset + CDA_CAMAP1, (ea[3] << 8) | ea[2]);
                    634:        SWO(bitmode, p_cda, camoffset + CDA_CAMAP0, (ea[1] << 8) | ea[0]);
                    635:        SWO(bitmode, p_cda, CDA_ENABLE,
                    636:            (SRO(bitmode, p_cda, CDA_ENABLE) | (1 << entry)));
                    637: }
                    638:
                    639: static void
                    640: camprogram(struct sn_softc *sc)
                    641: {
                    642:        struct ether_multistep step;
                    643:        struct ether_multi *enm;
                    644:        struct ifnet *ifp;
                    645:        int     timeout;
                    646:        int     mcount = 0;
                    647:
                    648:        caminitialise(sc);
                    649:
                    650:        ifp = &sc->sc_if;
                    651:
                    652:        /* Always load our own address first. */
                    653:        camentry (sc, mcount, sc->sc_enaddr);
                    654:        mcount++;
                    655:
                    656:        /* Assume we won't need allmulti bit. */
                    657:        ifp->if_flags &= ~IFF_ALLMULTI;
                    658:
                    659:        /* Loop through multicast addresses */
                    660:        ETHER_FIRST_MULTI(step, &sc->sc_arpcom, enm);
                    661:        while (enm != NULL) {
                    662:                if (mcount == MAXCAM) {
                    663:                         ifp->if_flags |= IFF_ALLMULTI;
                    664:                         break;
                    665:                }
                    666:
                    667:                if (bcmp(enm->enm_addrlo, enm->enm_addrhi,
                    668:                    sizeof(enm->enm_addrlo)) != 0) {
                    669:                        /*
                    670:                         * SONIC's CAM is programmed with specific
                    671:                         * addresses. It has no way to specify a range.
                    672:                         * (Well, thats not exactly true. If the
                    673:                         * range is small one could program each addr
                    674:                         * within the range as a separate CAM entry)
                    675:                         */
                    676:                        ifp->if_flags |= IFF_ALLMULTI;
                    677:                        break;
                    678:                }
                    679:
                    680:                /* program the CAM with the specified entry */
                    681:                camentry(sc, mcount, enm->enm_addrlo);
                    682:                mcount++;
                    683:
                    684:                ETHER_NEXT_MULTI(step, enm);
                    685:        }
                    686:
                    687:        NIC_PUT(sc, SNR_CDP, LOWER(sc->v_cda));
                    688:        NIC_PUT(sc, SNR_CDC, MAXCAM);
                    689:        NIC_PUT(sc, SNR_CR, CR_LCAM);
                    690:        wbflush();
                    691:
                    692:        timeout = 10000;
                    693:        while ((NIC_GET(sc, SNR_CR) & CR_LCAM) && timeout--)
                    694:                continue;
                    695:        if (timeout == 0) {
                    696:                /* XXX */
                    697:                panic("%s: CAM initialisation failed", sc->sc_dev.dv_xname);
                    698:        }
                    699:        timeout = 10000;
                    700:        while (((NIC_GET(sc, SNR_ISR) & ISR_LCD) == 0) && timeout--)
                    701:                continue;
                    702:
                    703:        if (NIC_GET(sc, SNR_ISR) & ISR_LCD)
                    704:                NIC_PUT(sc, SNR_ISR, ISR_LCD);
                    705:        else
                    706:                printf("%s: CAM initialisation without interrupt\n",
                    707:                    sc->sc_dev.dv_xname);
                    708: }
                    709:
                    710: #ifdef SNDEBUG
                    711: static void
                    712: camdump(struct sn_softc *sc)
                    713: {
                    714:        int     i;
                    715:
                    716:        printf("CAM entries:\n");
                    717:        NIC_PUT(sc, SNR_CR, CR_RST);
                    718:        wbflush();
                    719:
                    720:        for (i = 0; i < 16; i++) {
                    721:                ushort  ap2, ap1, ap0;
                    722:                NIC_PUT(sc, SNR_CEP, i);
                    723:                wbflush();
                    724:                ap2 = NIC_GET(sc, SNR_CAP2);
                    725:                ap1 = NIC_GET(sc, SNR_CAP1);
                    726:                ap0 = NIC_GET(sc, SNR_CAP0);
                    727:                printf("%d: ap2=0x%x ap1=0x%x ap0=0x%x\n", i, ap2, ap1, ap0);
                    728:        }
                    729:        printf("CAM enable 0x%x\n", NIC_GET(sc, SNR_CEP));
                    730:
                    731:        NIC_PUT(sc, SNR_CR, 0);
                    732:        wbflush();
                    733: }
                    734: #endif
                    735:
                    736: static void
                    737: initialise_tda(struct sn_softc *sc)
                    738: {
                    739:        struct mtd *mtd;
                    740:        int     i;
                    741:
                    742:        for (i = 0; i < NTDA; i++) {
                    743:                mtd = &sc->mtda[i];
                    744:                mtd->mtd_mbuf = 0;
                    745:        }
                    746:
                    747:        sc->mtd_hw = 0;
                    748:        sc->mtd_prev = NTDA - 1;
                    749:        sc->mtd_free = 0;
                    750:        sc->mtd_tlinko = TXP_FRAGOFF + 1*TXP_FRAGSIZE + TXP_FPTRLO;
                    751:        sc->mtd_pint = NTDA/2;
                    752:
                    753:        NIC_PUT(sc, SNR_UTDA, UPPER(sc->mtda[0].mtd_vtxp));
                    754:        NIC_PUT(sc, SNR_CTDA, LOWER(sc->mtda[0].mtd_vtxp));
                    755: }
                    756:
                    757: static void
                    758: initialise_rda(struct sn_softc *sc)
                    759: {
                    760:        int             bitmode = sc->bitmode;
                    761:        int             i;
                    762:        caddr_t         p_rda = 0;
                    763:        u_int32_t       v_rda = 0;
                    764:
                    765:        /* link the RDA's together into a circular list */
                    766:        for (i = 0; i < (sc->sc_nrda - 1); i++) {
                    767:                p_rda = sc->p_rda + (i * RXPKT_SIZE(sc));
                    768:                v_rda = sc->v_rda + ((i+1) * RXPKT_SIZE(sc));
                    769:                SWO(bitmode, p_rda, RXPKT_RLINK, LOWER(v_rda));
                    770:                SWO(bitmode, p_rda, RXPKT_INUSE, 1);
                    771:        }
                    772:        p_rda = sc->p_rda + ((sc->sc_nrda - 1) * RXPKT_SIZE(sc));
                    773:        SWO(bitmode, p_rda, RXPKT_RLINK, LOWER(sc->v_rda) | EOL);
                    774:        SWO(bitmode, p_rda, RXPKT_INUSE, 1);
                    775:
                    776:        /* mark end of receive descriptor list */
                    777:        sc->sc_rdamark = sc->sc_nrda - 1;
                    778:
                    779:        sc->sc_rxmark = 0;
                    780:
                    781:        NIC_PUT(sc, SNR_URDA, UPPER(sc->v_rda));
                    782:        NIC_PUT(sc, SNR_CRDA, LOWER(sc->v_rda));
                    783:        wbflush();
                    784: }
                    785:
                    786: static void
                    787: initialise_rra(struct sn_softc *sc)
                    788: {
                    789:        int     i;
                    790:        u_int   v;
                    791:        int     bitmode = sc->bitmode;
                    792:
                    793:        if (bitmode)
                    794:                NIC_PUT(sc, SNR_EOBC, RBASIZE(sc) / 2 - 2);
                    795:        else
                    796:                NIC_PUT(sc, SNR_EOBC, RBASIZE(sc) / 2 - 1);
                    797:
                    798:        NIC_PUT(sc, SNR_URRA, UPPER(sc->v_rra[0]));
                    799:        NIC_PUT(sc, SNR_RSA, LOWER(sc->v_rra[0]));
                    800:        /* rea must point just past the end of the rra space */
                    801:        NIC_PUT(sc, SNR_REA, LOWER(sc->v_rea));
                    802:        NIC_PUT(sc, SNR_RRP, LOWER(sc->v_rra[0]));
                    803:        NIC_PUT(sc, SNR_RSC, 0);
                    804:
                    805:        /* fill up SOME of the rra with buffers */
                    806:        for (i = 0; i < NRBA; i++) {
                    807:                v = sc->rbuf_phys[i];
                    808:                SWO(bitmode, sc->p_rra[i], RXRSRC_PTRHI, UPPER(v));
                    809:                SWO(bitmode, sc->p_rra[i], RXRSRC_PTRLO, LOWER(v));
                    810:                SWO(bitmode, sc->p_rra[i], RXRSRC_WCHI, UPPER(PAGE_SIZE/2));
                    811:                SWO(bitmode, sc->p_rra[i], RXRSRC_WCLO, LOWER(PAGE_SIZE/2));
                    812:        }
                    813:        sc->sc_rramark = NRBA;
                    814:        NIC_PUT(sc, SNR_RWP, LOWER(sc->v_rra[sc->sc_rramark]));
                    815:        wbflush();
                    816: }
                    817:
                    818: int
                    819: snintr(void *arg)
                    820: {
                    821:        struct sn_softc *sc = (struct sn_softc *)arg;
                    822:        int isr;
                    823:        int rv = 0;
                    824:
                    825:        while ((isr = (NIC_GET(sc, SNR_ISR) & ISR_ALL)) != 0) {
                    826:                rv = 1;
                    827:                /* scrub the interrupts that we are going to service */
                    828:                NIC_PUT(sc, SNR_ISR, isr);
                    829:                wbflush();
                    830:
                    831:                if (isr & (ISR_BR | ISR_LCD | ISR_TC))
                    832:                        printf("%s: unexpected interrupt status 0x%x\n",
                    833:                            sc->sc_dev.dv_xname, isr);
                    834:
                    835:                if (isr & (ISR_TXDN | ISR_TXER | ISR_PINT))
                    836:                        sonictxint(sc);
                    837:
                    838:                if (isr & ISR_PKTRX)
                    839:                        sonicrxint(sc);
                    840:
                    841:                if (isr & (ISR_HBL | ISR_RDE | ISR_RBE | ISR_RBAE | ISR_RFO)) {
                    842:                        if (isr & ISR_HBL)
                    843:                                /*
                    844:                                 * The repeater is not providing a heartbeat.
                    845:                                 * In itself this isn't harmful, lots of the
                    846:                                 * cheap repeater hubs don't supply a heartbeat.
                    847:                                 * So ignore the lack of heartbeat. Its only
                    848:                                 * if we can't detect a carrier that we have a
                    849:                                 * problem.
                    850:                                 */
                    851:                                ;
                    852:                        if (isr & ISR_RDE)
                    853:                                printf("%s: receive descriptors exhausted\n",
                    854:                                    sc->sc_dev.dv_xname);
                    855:                        if (isr & ISR_RBE)
                    856:                                printf("%s: receive buffers exhausted\n",
                    857:                                    sc->sc_dev.dv_xname);
                    858:                        if (isr & ISR_RBAE)
                    859:                                printf("%s: receive buffer area exhausted\n",
                    860:                                    sc->sc_dev.dv_xname);
                    861:                        if (isr & ISR_RFO)
                    862:                                printf("%s: receive FIFO overrun\n",
                    863:                                    sc->sc_dev.dv_xname);
                    864:                }
                    865:                if (isr & (ISR_CRC | ISR_FAE | ISR_MP)) {
                    866: #ifdef notdef
                    867:                        if (isr & ISR_CRC)
                    868:                                sc->sc_crctally++;
                    869:                        if (isr & ISR_FAE)
                    870:                                sc->sc_faetally++;
                    871:                        if (isr & ISR_MP)
                    872:                                sc->sc_mptally++;
                    873: #endif
                    874:                }
                    875:                snstart(&sc->sc_if);
                    876:        }
                    877:
                    878:        return (rv);
                    879: }
                    880:
                    881: /*
                    882:  * Transmit interrupt routine
                    883:  */
                    884: static void
                    885: sonictxint(struct sn_softc *sc)
                    886: {
                    887:        struct mtd      *mtd;
                    888:        void            *txp;
                    889:        unsigned short  txp_status;
                    890:        int             mtd_hw;
                    891:        struct ifnet    *ifp = &sc->sc_if;
                    892:
                    893:        mtd_hw = sc->mtd_hw;
                    894:
                    895:        if (mtd_hw == sc->mtd_free)
                    896:                return;
                    897:
                    898:        while (mtd_hw != sc->mtd_free) {
                    899:                mtd = &sc->mtda[mtd_hw];
                    900:
                    901:                txp = mtd->mtd_txp;
                    902:
                    903:                if (SRO(sc->bitmode, txp, TXP_STATUS) == 0) {
                    904:                        break; /* it hasn't really gone yet */
                    905:                }
                    906:
                    907: #ifdef SNDEBUG
                    908:                {
                    909:                        struct ether_header *eh;
                    910:
                    911:                        eh = (struct ether_header *) mtd->mtd_buf;
                    912:                        printf("%s: xmit status=0x%x len=%d type=0x%x from %s",
                    913:                            sc->sc_dev.dv_xname,
                    914:                            SRO(sc->bitmode, txp, TXP_STATUS),
                    915:                            SRO(sc->bitmode, txp, TXP_PKTSIZE),
                    916:                            htons(eh->ether_type),
                    917:                            ether_sprintf(eh->ether_shost));
                    918:                        printf(" (to %s)\n", ether_sprintf(eh->ether_dhost));
                    919:                }
                    920: #endif /* SNDEBUG */
                    921:
                    922:                ifp->if_flags &= ~IFF_OACTIVE;
                    923:
                    924:                if (mtd->mtd_mbuf != 0) {
                    925:                        m_freem(mtd->mtd_mbuf);
                    926:                        mtd->mtd_mbuf = 0;
                    927:                }
                    928:                if (++mtd_hw == NTDA) mtd_hw = 0;
                    929:
                    930:                txp_status = SRO(sc->bitmode, txp, TXP_STATUS);
                    931:
                    932:                ifp->if_collisions += (txp_status & TCR_EXC) ? 16 :
                    933:                        ((txp_status & TCR_NC) >> 12);
                    934:
                    935:                if ((txp_status & TCR_PTX) == 0) {
                    936:                        ifp->if_oerrors++;
                    937:
                    938:                        /* XXX - DG This looks bogus */
                    939:                        if (mtd_hw != sc->mtd_free) {
                    940:                                mtd = &sc->mtda[mtd_hw];
                    941:                                NIC_PUT(sc, SNR_CTDA, LOWER(mtd->mtd_vtxp));
                    942:                                NIC_PUT(sc, SNR_CR, CR_TXP);
                    943:                                wbflush();
                    944:                                break;
                    945:                        }
                    946:                }
                    947:        }
                    948:
                    949:        sc->mtd_hw = mtd_hw;
                    950:        return;
                    951: }
                    952:
                    953: /*
                    954:  * Receive interrupt routine
                    955:  */
                    956: static void
                    957: sonicrxint(struct sn_softc *sc)
                    958: {
                    959:        caddr_t rda;
                    960:        int     orra;
                    961:        int     len;
                    962:        int     rramark;
                    963:        int     rdamark;
                    964:        int     bitmode = sc->bitmode;
                    965:        u_int16_t rxpkt_ptr;
                    966:
                    967:        rda = sc->p_rda + (sc->sc_rxmark * RXPKT_SIZE(sc));
                    968:
                    969:        while (SRO(bitmode, rda, RXPKT_INUSE) == 0) {
                    970:                u_int status = SRO(bitmode, rda, RXPKT_STATUS);
                    971:
                    972:                orra = RBASEQ(SRO(bitmode, rda, RXPKT_SEQNO)) & RRAMASK;
                    973:                rxpkt_ptr = SRO(bitmode, rda, RXPKT_PTRLO);
                    974:                len = SRO(bitmode, rda, RXPKT_BYTEC) - FCSSIZE;
                    975:                if (status & RCR_PRX) {
                    976:                        caddr_t pkt = sc->rbuf[orra & RBAMASK] +
                    977:                            m68k_page_offset(rxpkt_ptr);
                    978:                        if (sonic_read(sc, pkt, len))
                    979:                                sc->sc_if.if_ipackets++;
                    980:                        else
                    981:                                sc->sc_if.if_ierrors++;
                    982:                } else
                    983:                        sc->sc_if.if_ierrors++;
                    984:
                    985:                /*
                    986:                 * give receive buffer area back to chip.
                    987:                 *
                    988:                 * If this was the last packet in the RRA, give the RRA to
                    989:                 * the chip again.
                    990:                 * If sonic read didnt copy it out then we would have to
                    991:                 * wait !!
                    992:                 * (dont bother add it back in again straight away)
                    993:                 *
                    994:                 * Really, we're doing p_rra[rramark] = p_rra[orra] but
                    995:                 * we have to use the macros because SONIC might be in
                    996:                 * 16 or 32 bit mode.
                    997:                 */
                    998:                if (status & RCR_LPKT) {
                    999:                        void *tmp1, *tmp2;
                   1000:
                   1001:                        rramark = sc->sc_rramark;
                   1002:                        tmp1 = sc->p_rra[rramark];
                   1003:                        tmp2 = sc->p_rra[orra];
                   1004:                        SWO(bitmode, tmp1, RXRSRC_PTRLO,
                   1005:                                SRO(bitmode, tmp2, RXRSRC_PTRLO));
                   1006:                        SWO(bitmode, tmp1, RXRSRC_PTRHI,
                   1007:                                SRO(bitmode, tmp2, RXRSRC_PTRHI));
                   1008:                        SWO(bitmode, tmp1, RXRSRC_WCLO,
                   1009:                                SRO(bitmode, tmp2, RXRSRC_WCLO));
                   1010:                        SWO(bitmode, tmp1, RXRSRC_WCHI,
                   1011:                                SRO(bitmode, tmp2, RXRSRC_WCHI));
                   1012:
                   1013:                        /* zap old rra for fun */
                   1014:                        SWO(bitmode, tmp2, RXRSRC_WCHI, 0);
                   1015:                        SWO(bitmode, tmp2, RXRSRC_WCLO, 0);
                   1016:
                   1017:                        sc->sc_rramark = (++rramark) & RRAMASK;
                   1018:                        NIC_PUT(sc, SNR_RWP, LOWER(sc->v_rra[rramark]));
                   1019:                        wbflush();
                   1020:                }
                   1021:
                   1022:                /*
                   1023:                 * give receive descriptor back to chip simple
                   1024:                 * list is circular
                   1025:                 */
                   1026:                rdamark = sc->sc_rdamark;
                   1027:                SWO(bitmode, rda, RXPKT_INUSE, 1);
                   1028:                SWO(bitmode, rda, RXPKT_RLINK,
                   1029:                        SRO(bitmode, rda, RXPKT_RLINK) | EOL);
                   1030:                SWO(bitmode, (sc->p_rda + (rdamark * RXPKT_SIZE(sc))), RXPKT_RLINK,
                   1031:                        SRO(bitmode, (sc->p_rda + (rdamark * RXPKT_SIZE(sc))),
                   1032:                        RXPKT_RLINK) & ~EOL);
                   1033:                sc->sc_rdamark = sc->sc_rxmark;
                   1034:
                   1035:                if (++sc->sc_rxmark >= sc->sc_nrda)
                   1036:                        sc->sc_rxmark = 0;
                   1037:                rda = sc->p_rda + (sc->sc_rxmark * RXPKT_SIZE(sc));
                   1038:        }
                   1039: }
                   1040:
                   1041: /*
                   1042:  * sonic_read -- pull packet off interface and forward to
                   1043:  * appropriate protocol handler
                   1044:  */
                   1045: static __inline__ int
                   1046: sonic_read(struct sn_softc *sc, caddr_t pkt, int len)
                   1047: {
                   1048:        struct ifnet *ifp = &sc->sc_if;
                   1049: #ifdef SNDEBUG
                   1050:        struct ether_header *et;
                   1051: #endif
                   1052:        struct mbuf *m;
                   1053:
                   1054: #ifdef SNDEBUG
                   1055:        /*
                   1056:         * Get pointer to ethernet header (in input buffer).
                   1057:         */
                   1058:        et = (struct ether_header *)pkt;
                   1059:
                   1060:        printf("%s: rcvd %p len=%d type=0x%x from %s",
                   1061:            sc->sc_dev.dv_xname, et, len, htons(et->ether_type),
                   1062:            ether_sprintf(et->ether_shost));
                   1063:        printf(" (to %s)\n", ether_sprintf(et->ether_dhost));
                   1064: #endif /* SNDEBUG */
                   1065:
                   1066:        if (len < (ETHER_MIN_LEN - ETHER_CRC_LEN) ||
                   1067:            len > (ETHER_MAX_LEN - ETHER_CRC_LEN)) {
                   1068:                printf("%s: invalid packet length %d bytes\n",
                   1069:                    sc->sc_dev.dv_xname, len);
                   1070:                return (0);
                   1071:        }
                   1072:
                   1073:        m = sonic_get(sc, pkt, len);
                   1074:        if (m == NULL)
                   1075:                return (0);
                   1076: #if NBPFILTER > 0
                   1077:        /* Pass this up to any BPF listeners. */
                   1078:        if (ifp->if_bpf)
                   1079:                bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
                   1080: #endif
                   1081:        ether_input_mbuf(ifp, m);
                   1082:        return (1);
                   1083: }
                   1084:
                   1085: /*
                   1086:  * munge the received packet into an mbuf chain
                   1087:  */
                   1088: static __inline__ struct mbuf *
                   1089: sonic_get(struct sn_softc *sc, caddr_t pkt, int datalen)
                   1090: {
                   1091:        struct  mbuf *m, *top, **mp;
                   1092:        int     len;
                   1093:
                   1094:        MGETHDR(m, M_DONTWAIT, MT_DATA);
                   1095:        if (m == NULL)
                   1096:                return (NULL);
                   1097:
                   1098:        m->m_pkthdr.rcvif = &sc->sc_if;
                   1099:        m->m_pkthdr.len = datalen;
                   1100:        len = MHLEN;
                   1101:        top = 0;
                   1102:        mp = &top;
                   1103:
                   1104:        while (datalen > 0) {
                   1105:                if (top) {
                   1106:                        MGET(m, M_DONTWAIT, MT_DATA);
                   1107:                        if (m == NULL) {
                   1108:                                m_freem(top);
                   1109:                                return (NULL);
                   1110:                        }
                   1111:                        len = MLEN;
                   1112:                }
                   1113:                if (datalen >= MINCLSIZE) {
                   1114:                        MCLGET(m, M_DONTWAIT);
                   1115:                        if ((m->m_flags & M_EXT) == 0) {
                   1116:                                if (top)
                   1117:                                        m_freem(top);
                   1118:                                return (NULL);
                   1119:                        }
                   1120:                        len = MCLBYTES;
                   1121:                }
                   1122:                m->m_len = len = min(datalen, len);
                   1123:
                   1124:                bcopy(pkt, mtod(m, caddr_t), (unsigned) len);
                   1125:                pkt += len;
                   1126:                datalen -= len;
                   1127:                *mp = m;
                   1128:                mp = &m->m_next;
                   1129:        }
                   1130:
                   1131:        return (top);
                   1132: }
                   1133:
                   1134: static u_char bbr4[] = {0,8,4,12,2,10,6,14,1,9,5,13,3,11,7,15};
                   1135: #define bbr(v) ((bbr4[(v)&0xf] << 4) | bbr4[((v)>>4) & 0xf])
                   1136:
                   1137: void
                   1138: sn_get_enaddr(bus_space_tag_t t, bus_space_handle_t h, bus_addr_t o,
                   1139:     u_char *dst)
                   1140: {
                   1141:        int     i, do_bbr;
                   1142:        u_char  b;
                   1143:
                   1144:        /*
                   1145:         * For reasons known only to Apple, MAC addresses in the ethernet
                   1146:         * PROM are stored in Token Ring (IEEE 802.5) format, that is
                   1147:         * with all of the bits in each byte reversed (canonical bit format).
                   1148:         * When the address is read out it must be reversed to ethernet format
                   1149:         * before use.
                   1150:         *
                   1151:         * Apple has been assigned OUI's 08:00:07 and 00:a0:40. All onboard
                   1152:         * ethernet addresses on 68K machines should be in one of these
                   1153:         * two ranges.
                   1154:         *
                   1155:         * Here is where it gets complicated.
                   1156:         *
                   1157:         * The PMac 7200, 7500, 8500, and 9500 accidentally had the PROM
                   1158:         * written in standard ethernet format. The MacOS accounted for this
                   1159:         * in these systems, and did not reverse the bytes. Some other
                   1160:         * networking utilities were not so forgiving, and got confused.
                   1161:         * "Some" of Apple's Nubus ethernet cards also had their bits
                   1162:         * burned in ethernet format.
                   1163:         *
                   1164:         * Apple petitioned the IEEE and was granted the 00:05:02 (bit reversal
                   1165:         * of 00:a0:40) as well. As of OpenTransport 1.1.1, Apple removed
                   1166:         * their workaround and now reverses the bits regardless of
                   1167:         * what kind of machine it is. So PMac systems and the affected
                   1168:         * Nubus cards now use 00:05:02, instead of the 00:a0:40 for which they
                   1169:         * were intended.
                   1170:         *
                   1171:         * See Apple Techinfo article TECHINFO-0020552, "OpenTransport 1.1.1
                   1172:         * and MacOS System 7.5.3 FAQ (10/96)" for more details.
                   1173:         */
                   1174:        do_bbr = 0;
                   1175:        b = bus_space_read_1(t, h, o);
                   1176:        if (b == 0x10)
                   1177:                do_bbr = 1;
                   1178:        dst[0] = (do_bbr) ? bbr(b) : b;
                   1179:
                   1180:        for (i = 1 ; i < ETHER_ADDR_LEN ; i++) {
                   1181:                b = bus_space_read_1(t, h, o+i);
                   1182:                dst[i] = (do_bbr) ? bbr(b) : b;
                   1183:        }
                   1184: }

CVSweb