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

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

1.1       nbrk        1: /*     $OpenBSD: if_mc.c,v 1.15 2007/01/12 16:31:21 martin Exp $       */
                      2: /*     $NetBSD: if_mc.c,v 1.24 2004/10/30 18:08:34 thorpej Exp $       */
                      3:
                      4: /*-
                      5:  * Copyright (c) 1997 David Huang <khym@azeotrope.org>
                      6:  * All rights reserved.
                      7:  *
                      8:  * Portions of this code are based on code by Denton Gentry <denny1@home.com>,
                      9:  * Charles M. Hannum, Yanagisawa Takeshi <yanagisw@aa.ap.titech.ac.jp>, and
                     10:  * Jason R. Thorpe.
                     11:  *
                     12:  * Redistribution and use in source and binary forms, with or without
                     13:  * modification, are permitted provided that the following conditions
                     14:  * are met:
                     15:  * 1. Redistributions of source code must retain the above copyright
                     16:  *    notice, this list of conditions and the following disclaimer.
                     17:  * 2. The name of the author may not be used to endorse or promote products
                     18:  *    derived from this software without specific prior written permission
                     19:  *
                     20:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     21:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     22:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     23:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     24:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
                     25:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     26:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     27:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     28:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
                     29:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     30:  *
                     31:  */
                     32:
                     33: /*
                     34:  * Driver for the AMD Am79C940 (MACE) ethernet chip, used for onboard
                     35:  * ethernet on the Centris/Quadra 660av and Quadra 840av.
                     36:  */
                     37:
                     38: #include <sys/param.h>
                     39: #include <sys/systm.h>
                     40: #include <sys/mbuf.h>
                     41: #include <sys/buf.h>
                     42: #include <sys/protosw.h>
                     43: #include <sys/socket.h>
                     44: #include <sys/syslog.h>
                     45: #include <sys/ioctl.h>
                     46: #include <sys/errno.h>
                     47: #include <sys/device.h>
                     48:
                     49: #include <net/if.h>
                     50: #include <net/if_dl.h>
                     51:
                     52: #ifdef INET
                     53: #include <netinet/in.h>
                     54: #include <netinet/if_ether.h>
                     55: #include <netinet/in_systm.h>
                     56: #include <netinet/in_var.h>
                     57: #include <netinet/ip.h>
                     58: #endif
                     59:
                     60: #include <uvm/uvm_extern.h>
                     61:
                     62: #include "bpfilter.h"
                     63: #if NBPFILTER > 0
                     64: #include <net/bpf.h>
                     65: #include <net/bpfdesc.h>
                     66: #endif
                     67:
                     68: #include <machine/bus.h>
                     69: #include <mac68k/dev/if_mcreg.h>
                     70: #include <mac68k/dev/if_mcvar.h>
                     71:
                     72: struct cfdriver mc_cd = {
                     73:        NULL, "mc", DV_IFNET
                     74: };
                     75:
                     76: void   mcwatchdog(struct ifnet *);
                     77: int    mcinit(struct mc_softc *sc);
                     78: int    mcstop(struct mc_softc *sc);
                     79: int    mcioctl(struct ifnet *ifp, u_long cmd, caddr_t data);
                     80: void   mcstart(struct ifnet *ifp);
                     81: void   mcreset(struct mc_softc *sc);
                     82:
                     83: u_int  maceput(struct mc_softc *sc, struct mbuf *m0);
                     84: void   mc_tint(struct mc_softc *sc);
                     85: void   mace_read(struct mc_softc *, caddr_t, int);
                     86: struct mbuf *mace_get(struct mc_softc *, caddr_t, int);
                     87: static void mace_calcladrf(struct arpcom *ac, u_int8_t *af);
                     88: static inline u_int16_t ether_cmp(void *, void *);
                     89:
                     90:
                     91: /*
                     92:  * Compare two Ether/802 addresses for equality, inlined and
                     93:  * unrolled for speed.  Use this like bcmp().
                     94:  *
                     95:  * XXX: Add <machine/inlines.h> for stuff like this?
                     96:  * XXX: or maybe add it to libkern.h instead?
                     97:  *
                     98:  * "I'd love to have an inline assembler version of this."
                     99:  * XXX: Who wanted that? mycroft?  I wrote one, but this
                    100:  * version in C is as good as hand-coded assembly. -gwr
                    101:  *
                    102:  * Please do NOT tweak this without looking at the actual
                    103:  * assembly code generated before and after your tweaks!
                    104:  */
                    105: static inline u_int16_t
                    106: ether_cmp(one, two)
                    107:        void *one, *two;
                    108: {
                    109:        register u_int16_t *a = (u_short *) one;
                    110:        register u_int16_t *b = (u_short *) two;
                    111:        register u_int16_t diff;
                    112:
                    113: #ifdef m68k
                    114:        /*
                    115:         * The post-increment-pointer form produces the best
                    116:         * machine code for m68k.  This was carefully tuned
                    117:         * so it compiles to just 8 short (2-byte) op-codes!
                    118:         */
                    119:        diff  = *a++ - *b++;
                    120:        diff |= *a++ - *b++;
                    121:        diff |= *a++ - *b++;
                    122: #else
                    123:        /*
                    124:         * Most modern CPUs do better with a single expresion.
                    125:         * Note that short-cut evaluation is NOT helpful here,
                    126:         * because it just makes the code longer, not faster!
                    127:         */
                    128:        diff = (a[0] - b[0]) | (a[1] - b[1]) | (a[2] - b[2]);
                    129: #endif
                    130:
                    131:        return (diff);
                    132: }
                    133:
                    134: #define ETHER_CMP      ether_cmp
                    135:
                    136: /*
                    137:  * Interface exists: make available by filling in network interface
                    138:  * record.  System will initialize the interface when it is ready
                    139:  * to accept packets.
                    140:  */
                    141: int
                    142: mcsetup(sc, lladdr)
                    143:        struct mc_softc *sc;
                    144:        u_int8_t *lladdr;
                    145: {
                    146:        struct ifnet *ifp = &sc->sc_if;
                    147:
                    148:        /* reset the chip and disable all interrupts */
                    149:        NIC_PUT(sc, MACE_BIUCC, SWRST);
                    150:        DELAY(100);
                    151:        NIC_PUT(sc, MACE_IMR, ~0);
                    152:
                    153:        bcopy(lladdr, sc->sc_enaddr, ETHER_ADDR_LEN);
                    154:        bcopy(sc->sc_enaddr, sc->sc_ethercom.ac_enaddr, ETHER_ADDR_LEN);
                    155:        printf(": address %s\n", ether_sprintf(lladdr));
                    156:
                    157:        bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
                    158:        ifp->if_softc = sc;
                    159:        ifp->if_ioctl = mcioctl;
                    160:        ifp->if_start = mcstart;
                    161:        ifp->if_flags =
                    162:            IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST;
                    163:        ifp->if_watchdog = mcwatchdog;
                    164:        IFQ_SET_READY(&ifp->if_snd);
                    165:
                    166:        if_attach(ifp);
                    167:        ether_ifattach(ifp);
                    168:
                    169:        return (0);
                    170: }
                    171:
                    172: int
                    173: mcioctl(ifp, cmd, data)
                    174:        struct ifnet *ifp;
                    175:        u_long cmd;
                    176:        caddr_t data;
                    177: {
                    178:        struct mc_softc *sc = ifp->if_softc;
                    179:        struct ifaddr *ifa;
                    180:        struct ifreq *ifr;
                    181:
                    182:        int     s = splnet(), err = 0;
                    183:
                    184:        switch (cmd) {
                    185:
                    186:        case SIOCSIFADDR:
                    187:                ifa = (struct ifaddr *)data;
                    188:                ifp->if_flags |= IFF_UP;
                    189:                switch (ifa->ifa_addr->sa_family) {
                    190: #ifdef INET
                    191:                case AF_INET:
                    192:                        mcinit(sc);
                    193:                        arp_ifinit(&sc->sc_ethercom, ifa);
                    194:                        break;
                    195: #endif
                    196:                default:
                    197:                        mcinit(sc);
                    198:                        break;
                    199:                }
                    200:                break;
                    201:
                    202:        case SIOCSIFFLAGS:
                    203:                if ((ifp->if_flags & IFF_UP) == 0 &&
                    204:                    (ifp->if_flags & IFF_RUNNING) != 0) {
                    205:                        /*
                    206:                         * If interface is marked down and it is running,
                    207:                         * then stop it.
                    208:                         */
                    209:                        mcstop(sc);
                    210:                        ifp->if_flags &= ~IFF_RUNNING;
                    211:                } else if ((ifp->if_flags & IFF_UP) != 0 &&
                    212:                    (ifp->if_flags & IFF_RUNNING) == 0) {
                    213:                        /*
                    214:                         * If interface is marked up and it is stopped,
                    215:                         * then start it.
                    216:                         */
                    217:                        (void)mcinit(sc);
                    218:                } else {
                    219:                        /*
                    220:                         * reset the interface to pick up any other changes
                    221:                         * in flags
                    222:                         */
                    223:                        mcreset(sc);
                    224:                        mcstart(ifp);
                    225:                }
                    226:                break;
                    227:
                    228:        case SIOCADDMULTI:
                    229:        case SIOCDELMULTI:
                    230:                ifr = (struct ifreq *) data;
                    231:                err = (cmd == SIOCADDMULTI) ?
                    232:                    ether_addmulti(ifr, &sc->sc_ethercom) :
                    233:                    ether_delmulti(ifr, &sc->sc_ethercom);
                    234:
                    235:                if (err == ENETRESET) {
                    236:                        /*
                    237:                         * Multicast list has changed; set the hardware
                    238:                         * filter accordingly. But remember UP flag!
                    239:                         */
                    240:                        if (ifp->if_flags & IFF_RUNNING)
                    241:                                mcreset(sc);
                    242:                        err = 0;
                    243:                }
                    244:                break;
                    245:        default:
                    246:                err = EINVAL;
                    247:        }
                    248:        splx(s);
                    249:        return (err);
                    250: }
                    251:
                    252: /*
                    253:  * Encapsulate a packet of type family for the local net.
                    254:  */
                    255: void
                    256: mcstart(ifp)
                    257:        struct ifnet *ifp;
                    258: {
                    259:        struct mc_softc *sc = ifp->if_softc;
                    260:        struct mbuf     *m;
                    261:
                    262:        if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
                    263:                return;
                    264:
                    265:        while (1) {
                    266:                if (ifp->if_flags & IFF_OACTIVE)
                    267:                        return;
                    268:
                    269:                IFQ_DEQUEUE(&ifp->if_snd, m);
                    270:                if (m == NULL)
                    271:                        return;
                    272:
                    273: #if NBPFILTER > 0
                    274:                /*
                    275:                 * If bpf is listening on this interface, let it
                    276:                 * see the packet before we commit it to the wire.
                    277:                 */
                    278:                if (ifp->if_bpf)
                    279:                        bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);
                    280: #endif
                    281:
                    282:                /*
                    283:                 * Copy the mbuf chain into the transmit buffer.
                    284:                 */
                    285:                ifp->if_flags |= IFF_OACTIVE;
                    286:                maceput(sc, m);
                    287:
                    288:                ifp->if_opackets++;             /* # of pkts */
                    289:        }
                    290: }
                    291:
                    292: /*
                    293:  * reset and restart the MACE.  Called in case of fatal
                    294:  * hardware/software errors.
                    295:  */
                    296: void
                    297: mcreset(sc)
                    298:        struct mc_softc *sc;
                    299: {
                    300:        mcstop(sc);
                    301:        mcinit(sc);
                    302: }
                    303:
                    304: int
                    305: mcinit(sc)
                    306:        struct mc_softc *sc;
                    307: {
                    308:        int s;
                    309:        u_int8_t maccc, ladrf[8];
                    310:
                    311:        if (sc->sc_if.if_flags & IFF_RUNNING)
                    312:                /* already running */
                    313:                return (0);
                    314:
                    315:        s = splnet();
                    316:
                    317:        NIC_PUT(sc, MACE_BIUCC, sc->sc_biucc);
                    318:        NIC_PUT(sc, MACE_FIFOCC, sc->sc_fifocc);
                    319:        NIC_PUT(sc, MACE_IMR, ~0); /* disable all interrupts */
                    320:        NIC_PUT(sc, MACE_PLSCC, sc->sc_plscc);
                    321:
                    322:        NIC_PUT(sc, MACE_UTR, RTRD); /* disable reserved test registers */
                    323:
                    324:        /* set MAC address */
                    325:        NIC_PUT(sc, MACE_IAC, ADDRCHG);
                    326:        while (NIC_GET(sc, MACE_IAC) & ADDRCHG)
                    327:                ;
                    328:        NIC_PUT(sc, MACE_IAC, PHYADDR);
                    329:        bus_space_write_multi_1(sc->sc_regt, sc->sc_regh, MACE_REG(MACE_PADR),
                    330:            sc->sc_enaddr, ETHER_ADDR_LEN);
                    331:
                    332:        /* set logical address filter */
                    333:        mace_calcladrf(&sc->sc_ethercom, ladrf);
                    334:
                    335:        NIC_PUT(sc, MACE_IAC, ADDRCHG);
                    336:        while (NIC_GET(sc, MACE_IAC) & ADDRCHG)
                    337:                ;
                    338:        NIC_PUT(sc, MACE_IAC, LOGADDR);
                    339:        bus_space_write_multi_1(sc->sc_regt, sc->sc_regh, MACE_REG(MACE_LADRF),
                    340:            ladrf, 8);
                    341:
                    342:        NIC_PUT(sc, MACE_XMTFC, APADXMT);
                    343:        /*
                    344:         * No need to autostrip padding on receive... Ethernet frames
                    345:         * don't have a length field, unlike 802.3 frames, so the MACE
                    346:         * can't figure out the length of the packet anyways.
                    347:         */
                    348:        NIC_PUT(sc, MACE_RCVFC, 0);
                    349:
                    350:        maccc = ENXMT | ENRCV;
                    351:        if (sc->sc_if.if_flags & IFF_PROMISC)
                    352:                maccc |= PROM;
                    353:
                    354:        NIC_PUT(sc, MACE_MACCC, maccc);
                    355:
                    356:        if (sc->sc_bus_init)
                    357:                (*sc->sc_bus_init)(sc);
                    358:
                    359:        /*
                    360:         * Enable all interrupts except receive, since we use the DMA
                    361:         * completion interrupt for that.
                    362:         */
                    363:        NIC_PUT(sc, MACE_IMR, RCVINTM);
                    364:
                    365:        /* flag interface as "running" */
                    366:        sc->sc_if.if_flags |= IFF_RUNNING;
                    367:        sc->sc_if.if_flags &= ~IFF_OACTIVE;
                    368:
                    369:        splx(s);
                    370:        return (0);
                    371: }
                    372:
                    373: /*
                    374:  * close down an interface and free its buffers
                    375:  * Called on final close of device, or if mcinit() fails
                    376:  * part way through.
                    377:  */
                    378: int
                    379: mcstop(sc)
                    380:        struct mc_softc *sc;
                    381: {
                    382:        int     s = splnet();
                    383:
                    384:        NIC_PUT(sc, MACE_BIUCC, SWRST);
                    385:        DELAY(100);
                    386:
                    387:        sc->sc_if.if_timer = 0;
                    388:        sc->sc_if.if_flags &= ~IFF_RUNNING;
                    389:
                    390:        splx(s);
                    391:        return (0);
                    392: }
                    393:
                    394: /*
                    395:  * Called if any Tx packets remain unsent after 5 seconds,
                    396:  * In all cases we just reset the chip, and any retransmission
                    397:  * will be handled by higher level protocol timeouts.
                    398:  */
                    399: void
                    400: mcwatchdog(ifp)
                    401:        struct ifnet *ifp;
                    402: {
                    403:        struct mc_softc *sc = ifp->if_softc;
                    404:
                    405:        printf("mcwatchdog: resetting chip\n");
                    406:        mcreset(sc);
                    407: }
                    408:
                    409: /*
                    410:  * stuff packet into MACE (at splnet)
                    411:  */
                    412: u_int
                    413: maceput(sc, m)
                    414:        struct mc_softc *sc;
                    415:        struct mbuf *m;
                    416: {
                    417:        struct mbuf *n;
                    418:        u_int len, totlen = 0;
                    419:        u_char *buff;
                    420:
                    421:        buff = sc->sc_txbuf;
                    422:
                    423:        for (; m; m = n) {
                    424:                u_char *data = mtod(m, u_char *);
                    425:                len = m->m_len;
                    426:                totlen += len;
                    427:                bcopy(data, buff, len);
                    428:                buff += len;
                    429:                MFREE(m, n);
                    430:        }
                    431:
                    432:        if (totlen > PAGE_SIZE)
                    433:                panic("%s: maceput: packet overflow", sc->sc_dev.dv_xname);
                    434:
                    435: #if 0
                    436:        if (totlen < ETHERMIN + sizeof(struct ether_header)) {
                    437:                int pad = ETHERMIN + sizeof(struct ether_header) - totlen;
                    438:                bzero(sc->sc_txbuf + totlen, pad);
                    439:                totlen = ETHERMIN + sizeof(struct ether_header);
                    440:        }
                    441: #endif
                    442:
                    443:        (*sc->sc_putpacket)(sc, totlen);
                    444:
                    445:        sc->sc_if.if_timer = 5; /* 5 seconds to watch for failing to transmit */
                    446:        return (totlen);
                    447: }
                    448:
                    449: void
                    450: mcintr(arg)
                    451:        void *arg;
                    452: {
                    453: struct mc_softc *sc = arg;
                    454:        u_int8_t ir;
                    455:
                    456:        ir = NIC_GET(sc, MACE_IR) & ~NIC_GET(sc, MACE_IMR);
                    457:        if (ir & JAB) {
                    458: #ifdef MCDEBUG
                    459:                printf("%s: jabber error\n", sc->sc_dev.dv_xname);
                    460: #endif
                    461:                sc->sc_if.if_oerrors++;
                    462:        }
                    463:
                    464:        if (ir & BABL) {
                    465: #ifdef MCDEBUG
                    466:                printf("%s: babble\n", sc->sc_dev.dv_xname);
                    467: #endif
                    468:                sc->sc_if.if_oerrors++;
                    469:        }
                    470:
                    471:        if (ir & CERR) {
                    472: #ifdef MCDEBUG
                    473:                printf("%s: collision error\n", sc->sc_dev.dv_xname);
                    474: #endif
                    475:                sc->sc_if.if_collisions++;
                    476:        }
                    477:
                    478:        /*
                    479:         * Pretend we have carrier; if we don't this will be cleared
                    480:         * shortly.
                    481:         */
                    482:        sc->sc_havecarrier = 1;
                    483:
                    484:        if (ir & XMTINT)
                    485:                mc_tint(sc);
                    486:
                    487:        if (ir & RCVINT)
                    488:                mc_rint(sc);
                    489: }
                    490:
                    491: void
                    492: mc_tint(sc)
                    493:        struct mc_softc *sc;
                    494: {
                    495:        u_int8_t xmtrc, xmtfs;
                    496:
                    497:        xmtrc = NIC_GET(sc, MACE_XMTRC);
                    498:        xmtfs = NIC_GET(sc, MACE_XMTFS);
                    499:
                    500:        if ((xmtfs & XMTSV) == 0)
                    501:                return;
                    502:
                    503:        if (xmtfs & UFLO) {
                    504:                printf("%s: underflow\n", sc->sc_dev.dv_xname);
                    505:                mcreset(sc);
                    506:                return;
                    507:        }
                    508:
                    509:        if (xmtfs & LCOL) {
                    510:                printf("%s: late collision\n", sc->sc_dev.dv_xname);
                    511:                sc->sc_if.if_oerrors++;
                    512:                sc->sc_if.if_collisions++;
                    513:        }
                    514:
                    515:        if (xmtfs & MORE)
                    516:                /* Real number is unknown. */
                    517:                sc->sc_if.if_collisions += 2;
                    518:        else if (xmtfs & ONE)
                    519:                sc->sc_if.if_collisions++;
                    520:        else if (xmtfs & RTRY) {
                    521:                printf("%s: excessive collisions\n", sc->sc_dev.dv_xname);
                    522:                sc->sc_if.if_collisions += 16;
                    523:                sc->sc_if.if_oerrors++;
                    524:        }
                    525:
                    526:        if (xmtfs & LCAR) {
                    527:                sc->sc_havecarrier = 0;
                    528:                printf("%s: lost carrier\n", sc->sc_dev.dv_xname);
                    529:                sc->sc_if.if_oerrors++;
                    530:        }
                    531:
                    532:        sc->sc_if.if_flags &= ~IFF_OACTIVE;
                    533:        sc->sc_if.if_timer = 0;
                    534:        mcstart(&sc->sc_if);
                    535: }
                    536:
                    537: void
                    538: mc_rint(sc)
                    539:        struct mc_softc *sc;
                    540: {
                    541: #define        rxf     sc->sc_rxframe
                    542:        u_int len;
                    543:
                    544:        len = (rxf.rx_rcvcnt | ((rxf.rx_rcvsts & 0xf) << 8)) - 4;
                    545:
                    546: #ifdef MCDEBUG
                    547:        if (rxf.rx_rcvsts & 0xf0)
                    548:                printf("%s: rcvcnt %02x rcvsts %02x rntpc 0x%02x rcvcc 0x%02x\n",
                    549:                    sc->sc_dev.dv_xname, rxf.rx_rcvcnt, rxf.rx_rcvsts,
                    550:                    rxf.rx_rntpc, rxf.rx_rcvcc);
                    551: #endif
                    552:
                    553:        if (rxf.rx_rcvsts & OFLO) {
                    554: #ifdef MCDEBUG
                    555:                printf("%s: receive FIFO overflow\n", sc->sc_dev.dv_xname);
                    556: #endif
                    557:                sc->sc_if.if_ierrors++;
                    558:                return;
                    559:        }
                    560:
                    561:        if (rxf.rx_rcvsts & CLSN)
                    562:                sc->sc_if.if_collisions++;
                    563:
                    564:        if (rxf.rx_rcvsts & FRAM) {
                    565: #ifdef MCDEBUG
                    566:                printf("%s: framing error\n", sc->sc_dev.dv_xname);
                    567: #endif
                    568:                sc->sc_if.if_ierrors++;
                    569:                return;
                    570:        }
                    571:
                    572:        if (rxf.rx_rcvsts & FCS) {
                    573: #ifdef MCDEBUG
                    574:                printf("%s: frame control checksum error\n", sc->sc_dev.dv_xname);
                    575: #endif
                    576:                sc->sc_if.if_ierrors++;
                    577:                return;
                    578:        }
                    579:
                    580:        mace_read(sc, rxf.rx_frame, len);
                    581: #undef rxf
                    582: }
                    583:
                    584: void
                    585: mace_read(sc, pkt, len)
                    586:        struct mc_softc *sc;
                    587:        caddr_t pkt;
                    588:        int len;
                    589: {
                    590:        struct ifnet *ifp = &sc->sc_if;
                    591:        struct mbuf *m;
                    592:
                    593:        if (len <= sizeof(struct ether_header) ||
                    594:            len > ETHERMTU + sizeof(struct ether_header)) {
                    595: #ifdef MCDEBUG
                    596:                printf("%s: invalid packet size %d; dropping\n",
                    597:                    sc->sc_dev.dv_xname, len);
                    598: #endif
                    599:                ifp->if_ierrors++;
                    600:                return;
                    601:        }
                    602:
                    603:        m = mace_get(sc, pkt, len);
                    604:        if (m == NULL) {
                    605:                ifp->if_ierrors++;
                    606:                return;
                    607:        }
                    608:
                    609:        ifp->if_ipackets++;
                    610:
                    611: #if NBPFILTER > 0
                    612:        /* Pass the packet to any BPF listeners. */
                    613:        if (ifp->if_bpf)
                    614:                bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
                    615: #endif
                    616:
                    617:        /* Pass the packet up. */
                    618:        ether_input_mbuf(ifp, m);
                    619: }
                    620:
                    621: /*
                    622:  * Pull data off an interface.
                    623:  * Len is length of data, with local net header stripped.
                    624:  * We copy the data into mbufs.  When full cluster sized units are present
                    625:  * we copy into clusters.
                    626:  */
                    627: struct mbuf *
                    628: mace_get(sc, pkt, totlen)
                    629:        struct mc_softc *sc;
                    630:        caddr_t pkt;
                    631:        int totlen;
                    632: {
                    633:        register struct mbuf *m;
                    634:        struct mbuf *top, **mp;
                    635:        int len;
                    636:
                    637:        MGETHDR(m, M_DONTWAIT, MT_DATA);
                    638:        if (m == NULL)
                    639:                return (NULL);
                    640:
                    641:        m->m_pkthdr.rcvif = &sc->sc_if;
                    642:        m->m_pkthdr.len = totlen;
                    643:        len = MHLEN;
                    644:        top = 0;
                    645:        mp = &top;
                    646:
                    647:        while (totlen > 0) {
                    648:                if (top) {
                    649:                        MGET(m, M_DONTWAIT, MT_DATA);
                    650:                        if (m == NULL) {
                    651:                                m_freem(top);
                    652:                                return (NULL);
                    653:                        }
                    654:                        len = MLEN;
                    655:                }
                    656:                if (totlen >= MINCLSIZE) {
                    657:                        MCLGET(m, M_DONTWAIT);
                    658:                        if ((m->m_flags & M_EXT) == 0) {
                    659:                                m_free(m);
                    660:                                m_freem(top);
                    661:                                return (NULL);
                    662:                        }
                    663:                        len = MCLBYTES;
                    664:                }
                    665:                m->m_len = len = min(totlen, len);
                    666:                bcopy(pkt, mtod(m, caddr_t), len);
                    667:                pkt += len;
                    668:                totlen -= len;
                    669:                *mp = m;
                    670:                mp = &m->m_next;
                    671:        }
                    672:
                    673:        return (top);
                    674: }
                    675:
                    676: /*
                    677:  * Go through the list of multicast addresses and calculate the logical
                    678:  * address filter.
                    679:  */
                    680: void
                    681: mace_calcladrf(ac, af)
                    682:        struct arpcom *ac;
                    683:        u_int8_t *af;
                    684: {
                    685:        struct ifnet *ifp = &ac->ac_if;
                    686:        struct ether_multi *enm;
                    687:        register u_int32_t crc;
                    688:        struct ether_multistep step;
                    689:
                    690:        /*
                    691:         * Set up multicast address filter by passing all multicast addresses
                    692:         * through a crc generator, and then using the high order 6 bits as an
                    693:         * index into the 64 bit logical address filter.  The high order bit
                    694:         * selects the word, while the rest of the bits select the bit within
                    695:         * the word.
                    696:         */
                    697:
                    698:        *((u_int32_t *)af) = *((u_int32_t *)af + 1) = 0;
                    699:        ETHER_FIRST_MULTI(step, ac, enm);
                    700:        while (enm != NULL) {
                    701:                if (ETHER_CMP(enm->enm_addrlo, enm->enm_addrhi)) {
                    702:                        /*
                    703:                         * We must listen to a range of multicast addresses.
                    704:                         * For now, just accept all multicasts, rather than
                    705:                         * trying to set only those filter bits needed to match
                    706:                         * the range.  (At this time, the only use of address
                    707:                         * ranges is for IP multicast routing, for which the
                    708:                         * range is big enough to require all bits set.)
                    709:                         */
                    710:                        goto allmulti;
                    711:                }
                    712:
                    713:                crc = ether_crc32_le(enm->enm_addrlo, sizeof(enm->enm_addrlo));
                    714:
                    715:                /* Just want the 6 most significant bits. */
                    716:                crc >>= 26;
                    717:
                    718:                /* Set the corresponding bit in the filter. */
                    719:                af[crc >> 3] |= 1 << (crc & 7);
                    720:
                    721:                ETHER_NEXT_MULTI(step, enm);
                    722:        }
                    723:        ifp->if_flags &= ~IFF_ALLMULTI;
                    724:        return;
                    725:
                    726: allmulti:
                    727:        ifp->if_flags |= IFF_ALLMULTI;
                    728:        *((u_int32_t *)af) = *((u_int32_t *)af + 1) = 0xffffffff;
                    729: }
                    730:
                    731: static u_char bbr4[] = {0,8,4,12,2,10,6,14,1,9,5,13,3,11,7,15};
                    732: #define bbr(v)  ((bbr4[(v)&0xf] << 4) | bbr4[((v)>>4) & 0xf])
                    733:
                    734: u_char
                    735: mc_get_enaddr(t, h, o, dst)
                    736:        bus_space_tag_t t;
                    737:        bus_space_handle_t h;
                    738:        bus_size_t o;
                    739:        u_char *dst;
                    740: {
                    741:        int     i;
                    742:        u_char  b, csum;
                    743:
                    744:        /*
                    745:         * The XOR of the 8 bytes of the ROM must be 0xff for it to be
                    746:         * valid
                    747:        */
                    748:        for (i = 0, csum = 0; i < 8; i++) {
                    749:                b = bus_space_read_1(t, h, o+16*i);
                    750:                if (i < ETHER_ADDR_LEN)
                    751:                        dst[i] = bbr(b);
                    752:                csum ^= b;
                    753:        }
                    754:
                    755:        return csum;
                    756: }

CVSweb