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

Annotation of sys/arch/sparc/dev/qe.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: qe.c,v 1.30 2006/05/27 23:59:07 jason Exp $   */
        !             2:
        !             3: /*
        !             4:  * Copyright (c) 1998, 2000 Jason L. Wright.
        !             5:  * All rights reserved.
        !             6:  *
        !             7:  * Redistribution and use in source and binary forms, with or without
        !             8:  * modification, are permitted provided that the following conditions
        !             9:  * are met:
        !            10:  * 1. Redistributions of source code must retain the above copyright
        !            11:  *    notice, this list of conditions and the following disclaimer.
        !            12:  * 2. Redistributions in binary form must reproduce the above copyright
        !            13:  *    notice, this list of conditions and the following disclaimer in the
        !            14:  *    documentation and/or other materials provided with the distribution.
        !            15:  *
        !            16:  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
        !            17:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
        !            18:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
        !            19:  * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
        !            20:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
        !            21:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
        !            22:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
        !            23:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
        !            24:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
        !            25:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
        !            26:  */
        !            27:
        !            28: /*
        !            29:  * Driver for the SBus qec+qe QuadEthernet board.
        !            30:  *
        !            31:  * This driver was written using the AMD MACE Am79C940 documentation, some
        !            32:  * ideas gleaned from the S/Linux driver for this card, Solaris header files,
        !            33:  * and a loan of a card from Paul Southworth of the Internet Engineering
        !            34:  * Group (www.ieng.com).
        !            35:  */
        !            36:
        !            37: #include <sys/param.h>
        !            38: #include <sys/systm.h>
        !            39: #include <sys/kernel.h>
        !            40: #include <sys/errno.h>
        !            41: #include <sys/ioctl.h>
        !            42: #include <sys/mbuf.h>
        !            43: #include <sys/socket.h>
        !            44: #include <sys/syslog.h>
        !            45: #include <sys/device.h>
        !            46: #include <sys/malloc.h>
        !            47:
        !            48: #include <net/if.h>
        !            49: #include <net/if_dl.h>
        !            50: #include <net/if_types.h>
        !            51: #include <net/if_media.h>
        !            52: #include <net/netisr.h>
        !            53:
        !            54: #ifdef INET
        !            55: #include <netinet/in.h>
        !            56: #include <netinet/in_systm.h>
        !            57: #include <netinet/in_var.h>
        !            58: #include <netinet/ip.h>
        !            59: #include <netinet/if_ether.h>
        !            60: #endif
        !            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/autoconf.h>
        !            69: #include <machine/cpu.h>
        !            70:
        !            71: #include <sparc/dev/sbusvar.h>
        !            72: #include <sparc/dev/dmareg.h>
        !            73: #include <sparc/dev/dmavar.h>
        !            74:
        !            75: #include <sparc/dev/qecvar.h>
        !            76: #include <sparc/dev/qecreg.h>
        !            77: #include <sparc/dev/qereg.h>
        !            78: #include <sparc/dev/qevar.h>
        !            79:
        !            80: int    qematch(struct device *, void *, void *);
        !            81: void   qeattach(struct device *, struct device *, void *);
        !            82:
        !            83: void   qeinit(struct qesoftc *);
        !            84: void   qestart(struct ifnet *);
        !            85: void   qestop(struct qesoftc *);
        !            86: void   qewatchdog(struct ifnet *);
        !            87: int    qeioctl(struct ifnet *, u_long, caddr_t);
        !            88: void   qereset(struct qesoftc *);
        !            89:
        !            90: int            qeintr(void *);
        !            91: int            qe_eint(struct qesoftc *, u_int32_t);
        !            92: int            qe_rint(struct qesoftc *);
        !            93: int            qe_tint(struct qesoftc *);
        !            94: void           qe_read(struct qesoftc *, int, int);
        !            95: void           qe_mcreset(struct qesoftc *);
        !            96: void           qe_ifmedia_sts(struct ifnet *, struct ifmediareq *);
        !            97: int            qe_ifmedia_upd(struct ifnet *);
        !            98:
        !            99: struct cfdriver qe_cd = {
        !           100:        NULL, "qe", DV_IFNET
        !           101: };
        !           102:
        !           103: struct cfattach qe_ca = {
        !           104:        sizeof(struct qesoftc), qematch, qeattach
        !           105: };
        !           106:
        !           107: int
        !           108: qematch(parent, vcf, aux)
        !           109:        struct device *parent;
        !           110:        void *vcf, *aux;
        !           111: {
        !           112:        struct cfdata *cf = vcf;
        !           113:        struct confargs *ca = aux;
        !           114:        register struct romaux *ra = &ca->ca_ra;
        !           115:
        !           116:        if (strcmp(cf->cf_driver->cd_name, ra->ra_name))
        !           117:                return (0);
        !           118:        return (1);
        !           119: }
        !           120:
        !           121: void
        !           122: qeattach(parent, self, aux)
        !           123:        struct device *parent, *self;
        !           124:        void *aux;
        !           125: {
        !           126:        struct qec_softc *qec = (struct qec_softc *)parent;
        !           127:        struct qesoftc *sc = (struct qesoftc *)self;
        !           128:        struct ifnet *ifp = &sc->sc_arpcom.ac_if;
        !           129:        struct confargs *ca = aux;
        !           130:        struct bootpath *bp;
        !           131:        extern void myetheraddr(u_char *);
        !           132:        int pri;
        !           133:
        !           134:        if (qec->sc_pri == 0) {
        !           135:                printf(": no interrupt found on parent\n");
        !           136:                return;
        !           137:        }
        !           138:        pri = qec->sc_pri;
        !           139:
        !           140:        sc->sc_rev = getpropint(ca->ca_ra.ra_node, "mace-version", -1);
        !           141:
        !           142:        sc->sc_cr = mapiodev(&ca->ca_ra.ra_reg[0], 0, sizeof(struct qe_cregs));
        !           143:        sc->sc_mr = mapiodev(&ca->ca_ra.ra_reg[1], 0, sizeof(struct qe_mregs));
        !           144:        sc->sc_qec = qec;
        !           145:        sc->sc_qr = qec->sc_regs;
        !           146:        qestop(sc);
        !           147:
        !           148:        sc->sc_channel = getpropint(ca->ca_ra.ra_node, "channel#", -1);
        !           149:        sc->sc_burst = qec->sc_burst;
        !           150:
        !           151:        sc->sc_ih.ih_fun = qeintr;
        !           152:        sc->sc_ih.ih_arg = sc;
        !           153:        intr_establish(pri, &sc->sc_ih, IPL_NET, self->dv_xname);
        !           154:
        !           155:        myetheraddr(sc->sc_arpcom.ac_enaddr);
        !           156:
        !           157:        bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
        !           158:        ifp->if_softc = sc;
        !           159:        ifp->if_start = qestart;
        !           160:        ifp->if_ioctl = qeioctl;
        !           161:        ifp->if_watchdog = qewatchdog;
        !           162:        ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS |
        !           163:            IFF_MULTICAST;
        !           164:
        !           165:        ifmedia_init(&sc->sc_ifmedia, IFM_IMASK,
        !           166:            qe_ifmedia_upd, qe_ifmedia_sts);
        !           167:        ifmedia_add(&sc->sc_ifmedia,
        !           168:            IFM_MAKEWORD(IFM_ETHER, IFM_10_T, 0, 0), 0, NULL);
        !           169:        ifmedia_set(&sc->sc_ifmedia, IFM_ETHER | IFM_10_T);
        !           170:
        !           171:        IFQ_SET_MAXLEN(&ifp->if_snd, QE_TX_RING_SIZE);
        !           172:        IFQ_SET_READY(&ifp->if_snd);
        !           173:
        !           174:        /* Attach the interface. */
        !           175:        if_attach(ifp);
        !           176:        ether_ifattach(ifp);
        !           177:
        !           178:        printf(" pri %d: rev %x address %s\n", pri, sc->sc_rev,
        !           179:            ether_sprintf(sc->sc_arpcom.ac_enaddr));
        !           180:
        !           181:        bp = ca->ca_ra.ra_bp;
        !           182:        if (bp != NULL && strcmp(bp->name, "qe") == 0 &&
        !           183:            sc->sc_dev.dv_unit == bp->val[1])
        !           184:                bp->dev = &sc->sc_dev;
        !           185: }
        !           186:
        !           187: /*
        !           188:  * Start output on interface.
        !           189:  * We make two assumptions here:
        !           190:  *  1) that the current priority is set to splnet _before_ this code
        !           191:  *     is called *and* is returned to the appropriate priority after
        !           192:  *     return
        !           193:  *  2) that the IFF_OACTIVE flag is checked before this code is called
        !           194:  *     (i.e. that the output part of the interface is idle)
        !           195:  */
        !           196: void
        !           197: qestart(ifp)
        !           198:        struct ifnet *ifp;
        !           199: {
        !           200:        struct qesoftc *sc = (struct qesoftc *)ifp->if_softc;
        !           201:        struct mbuf *m;
        !           202:        int bix, len;
        !           203:
        !           204:        if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
        !           205:                return;
        !           206:
        !           207:        bix = sc->sc_last_td;
        !           208:
        !           209:        for (;;) {
        !           210:                IFQ_POLL(&ifp->if_snd, m);
        !           211:                if (m == NULL)
        !           212:                        break;
        !           213:
        !           214:                IFQ_DEQUEUE(&ifp->if_snd, m);
        !           215:
        !           216: #if NBPFILTER > 0
        !           217:                /*
        !           218:                 * If BPF is listening on this interface, let it see the
        !           219:                 * packet before we commit it to the wire.
        !           220:                 */
        !           221:                if (ifp->if_bpf)
        !           222:                        bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);
        !           223: #endif
        !           224:
        !           225:                /*
        !           226:                 * Copy the mbuf chain into the transmit buffer.
        !           227:                 */
        !           228:                len = qec_put(sc->sc_bufs->tx_buf[bix & QE_TX_RING_MASK], m);
        !           229:
        !           230:                /*
        !           231:                 * Initialize transmit registers and start transmission
        !           232:                 */
        !           233:                sc->sc_desc->qe_txd[bix].tx_flags =
        !           234:                        QE_TXD_OWN | QE_TXD_SOP | QE_TXD_EOP |
        !           235:                        (len & QE_TXD_LENGTH);
        !           236:                sc->sc_cr->ctrl = QE_CR_CTRL_TWAKEUP;
        !           237:
        !           238:                if (++bix == QE_TX_RING_MAXSIZE)
        !           239:                        bix = 0;
        !           240:
        !           241:                if (++sc->sc_no_td == QE_TX_RING_SIZE) {
        !           242:                        ifp->if_flags |= IFF_OACTIVE;
        !           243:                        break;
        !           244:                }
        !           245:        }
        !           246:
        !           247:        sc->sc_last_td = bix;
        !           248: }
        !           249:
        !           250: void
        !           251: qestop(sc)
        !           252:        struct qesoftc *sc;
        !           253: {
        !           254:        struct qe_cregs *cr = sc->sc_cr;
        !           255:        struct qe_mregs *mr = sc->sc_mr;
        !           256:        int n;
        !           257:
        !           258:        mr->biucc = QE_MR_BIUCC_SWRST;
        !           259:        for (n = 200; n > 0; n--) {
        !           260:                if ((mr->biucc & QE_MR_BIUCC_SWRST) == 0)
        !           261:                        break;
        !           262:                DELAY(20);
        !           263:        }
        !           264:
        !           265:        cr->ctrl = QE_CR_CTRL_RESET;
        !           266:        for (n = 200; n > 0; n--) {
        !           267:                if ((cr->ctrl & QE_CR_CTRL_RESET) == 0)
        !           268:                        break;
        !           269:                DELAY(20);
        !           270:        }
        !           271: }
        !           272:
        !           273: /*
        !           274:  * Reset interface.
        !           275:  */
        !           276: void
        !           277: qereset(sc)
        !           278:        struct qesoftc *sc;
        !           279: {
        !           280:        qestop(sc);
        !           281:        qeinit(sc);
        !           282: }
        !           283:
        !           284: void
        !           285: qewatchdog(ifp)
        !           286:        struct ifnet *ifp;
        !           287: {
        !           288:        struct qesoftc *sc = ifp->if_softc;
        !           289:        int s;
        !           290:
        !           291:        log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
        !           292:        ++sc->sc_arpcom.ac_if.if_oerrors;
        !           293:
        !           294:        s = splnet();
        !           295:        qereset(sc);
        !           296:        splx(s);
        !           297: }
        !           298:
        !           299: /*
        !           300:  * Interrupt dispatch.
        !           301:  */
        !           302: int
        !           303: qeintr(v)
        !           304:        void *v;
        !           305: {
        !           306:        struct qesoftc *sc = (struct qesoftc *)v;
        !           307:        u_int32_t qecstat, qestat;
        !           308:        int r = 0;
        !           309:
        !           310:        qecstat = sc->sc_qr->stat >> (4 * sc->sc_channel);
        !           311:        if ((qecstat & 0xf) == 0)
        !           312:                return (r);
        !           313:
        !           314:        qestat = sc->sc_cr->stat;
        !           315:
        !           316:        if (qestat & QE_CR_STAT_ALLERRORS) {
        !           317:                r |= qe_eint(sc, qestat);
        !           318:                if (r == -1)
        !           319:                        return (1);
        !           320:        }
        !           321:
        !           322:        if (qestat & QE_CR_STAT_TXIRQ)
        !           323:                r |= qe_tint(sc);
        !           324:
        !           325:        if (qestat & QE_CR_STAT_RXIRQ)
        !           326:                r |= qe_rint(sc);
        !           327:
        !           328:        return (1);
        !           329: }
        !           330:
        !           331: /*
        !           332:  * Transmit interrupt.
        !           333:  */
        !           334: int
        !           335: qe_tint(sc)
        !           336:        struct qesoftc *sc;
        !           337: {
        !           338:        struct ifnet *ifp = &sc->sc_arpcom.ac_if;
        !           339:        int bix;
        !           340:        struct qe_txd txd;
        !           341:
        !           342:        bix = sc->sc_first_td;
        !           343:
        !           344:        for (;;) {
        !           345:                if (sc->sc_no_td <= 0)
        !           346:                        break;
        !           347:
        !           348:                txd.tx_flags = sc->sc_desc->qe_txd[bix].tx_flags;
        !           349:                if (txd.tx_flags & QE_TXD_OWN)
        !           350:                        break;
        !           351:
        !           352:                ifp->if_opackets++;
        !           353:
        !           354:                if (++bix == QE_TX_RING_MAXSIZE)
        !           355:                        bix = 0;
        !           356:
        !           357:                --sc->sc_no_td;
        !           358:        }
        !           359:
        !           360:        if (sc->sc_no_td == 0)
        !           361:                ifp->if_timer = 0;
        !           362:
        !           363:        /*
        !           364:         * If we freed up at least one descriptor and tx is blocked,
        !           365:         * unblock it and start it up again.
        !           366:         */
        !           367:        if (sc->sc_first_td != bix) {
        !           368:                sc->sc_first_td = bix;
        !           369:                if (ifp->if_flags & IFF_OACTIVE) {
        !           370:                        ifp->if_flags &= ~IFF_OACTIVE;
        !           371:                        qestart(ifp);
        !           372:                }
        !           373:        }
        !           374:
        !           375:        return (1);
        !           376: }
        !           377:
        !           378: /*
        !           379:  * Receive interrupt.
        !           380:  */
        !           381: int
        !           382: qe_rint(sc)
        !           383:        struct qesoftc *sc;
        !           384: {
        !           385:        int bix, len;
        !           386:
        !           387:        bix = sc->sc_last_rd;
        !           388:
        !           389:        /*
        !           390:         * Process all buffers with valid data.
        !           391:         */
        !           392:        for (;;) {
        !           393:                if (sc->sc_desc->qe_rxd[bix].rx_flags & QE_RXD_OWN)
        !           394:                        break;
        !           395:
        !           396:                len = (sc->sc_desc->qe_rxd[bix].rx_flags & QE_RXD_LENGTH) - 4;
        !           397:                qe_read(sc, bix, len);
        !           398:                sc->sc_desc->qe_rxd[(bix + QE_RX_RING_SIZE) & QE_RX_RING_MAXMASK].rx_flags =
        !           399:                    QE_RXD_OWN | QE_RXD_LENGTH;
        !           400:
        !           401:                if (++bix == QE_RX_RING_MAXSIZE)
        !           402:                        bix = 0;
        !           403:        }
        !           404:
        !           405:        sc->sc_last_rd = bix;
        !           406:
        !           407:        return (1);
        !           408: }
        !           409:
        !           410: /*
        !           411:  * Error interrupt.
        !           412:  */
        !           413: int
        !           414: qe_eint(sc, why)
        !           415:        struct qesoftc *sc;
        !           416:        u_int32_t why;
        !           417: {
        !           418:        struct ifnet *ifp = &sc->sc_arpcom.ac_if;
        !           419:        int r = 0, rst = 0;
        !           420:
        !           421:        if (why & QE_CR_STAT_EDEFER) {
        !           422:                printf("%s: excessive tx defers.\n", sc->sc_dev.dv_xname);
        !           423:                r |= 1;
        !           424:                ifp->if_oerrors++;
        !           425:        }
        !           426:
        !           427:        if (why & QE_CR_STAT_CLOSS) {
        !           428:                ifp->if_oerrors++;
        !           429:                r |= 1;
        !           430:        }
        !           431:
        !           432:        if (why & QE_CR_STAT_ERETRIES) {
        !           433:                printf("%s: excessive tx retries\n", sc->sc_dev.dv_xname);
        !           434:                ifp->if_oerrors++;
        !           435:                r |= 1;
        !           436:                rst = 1;
        !           437:        }
        !           438:
        !           439:        if (why & QE_CR_STAT_LCOLL) {
        !           440:                printf("%s: late tx transmission\n", sc->sc_dev.dv_xname);
        !           441:                ifp->if_oerrors++;
        !           442:                r |= 1;
        !           443:                rst = 1;
        !           444:        }
        !           445:
        !           446:        if (why & QE_CR_STAT_FUFLOW) {
        !           447:                printf("%s: tx fifo underflow\n", sc->sc_dev.dv_xname);
        !           448:                ifp->if_oerrors++;
        !           449:                r |= 1;
        !           450:                rst = 1;
        !           451:        }
        !           452:
        !           453:        if (why & QE_CR_STAT_JERROR) {
        !           454:                printf("%s: jabber seen\n", sc->sc_dev.dv_xname);
        !           455:                r |= 1;
        !           456:        }
        !           457:
        !           458:        if (why & QE_CR_STAT_BERROR) {
        !           459:                printf("%s: babble seen\n", sc->sc_dev.dv_xname);
        !           460:                r |= 1;
        !           461:        }
        !           462:
        !           463:        if (why & QE_CR_STAT_TCCOFLOW) {
        !           464:                ifp->if_collisions += 256;
        !           465:                ifp->if_oerrors += 256;
        !           466:                r |= 1;
        !           467:        }
        !           468:
        !           469:        if (why & QE_CR_STAT_TXDERROR) {
        !           470:                printf("%s: tx descriptor is bad\n", sc->sc_dev.dv_xname);
        !           471:                rst = 1;
        !           472:                r |= 1;
        !           473:        }
        !           474:
        !           475:        if (why & QE_CR_STAT_TXLERR) {
        !           476:                printf("%s: tx late error\n", sc->sc_dev.dv_xname);
        !           477:                ifp->if_oerrors++;
        !           478:                rst = 1;
        !           479:                r |= 1;
        !           480:        }
        !           481:
        !           482:        if (why & QE_CR_STAT_TXPERR) {
        !           483:                printf("%s: tx dma parity error\n", sc->sc_dev.dv_xname);
        !           484:                ifp->if_oerrors++;
        !           485:                rst = 1;
        !           486:                r |= 1;
        !           487:        }
        !           488:
        !           489:        if (why & QE_CR_STAT_TXSERR) {
        !           490:                printf("%s: tx dma sbus error ack\n", sc->sc_dev.dv_xname);
        !           491:                ifp->if_oerrors++;
        !           492:                rst = 1;
        !           493:                r |= 1;
        !           494:        }
        !           495:
        !           496:        if (why & QE_CR_STAT_RCCOFLOW) {
        !           497:                ifp->if_collisions += 256;
        !           498:                ifp->if_ierrors += 256;
        !           499:                r |= 1;
        !           500:        }
        !           501:
        !           502:        if (why & QE_CR_STAT_RUOFLOW) {
        !           503:                ifp->if_ierrors += 256;
        !           504:                r |= 1;
        !           505:        }
        !           506:
        !           507:        if (why & QE_CR_STAT_MCOFLOW) {
        !           508:                ifp->if_ierrors += 256;
        !           509:                r |= 1;
        !           510:        }
        !           511:
        !           512:        if (why & QE_CR_STAT_RXFOFLOW) {
        !           513:                printf("%s: rx fifo overflow\n", sc->sc_dev.dv_xname);
        !           514:                ifp->if_ierrors++;
        !           515:                r |= 1;
        !           516:        }
        !           517:
        !           518:        if (why & QE_CR_STAT_RLCOLL) {
        !           519:                printf("%s: rx late collision\n", sc->sc_dev.dv_xname);
        !           520:                ifp->if_ierrors++;
        !           521:                ifp->if_collisions++;
        !           522:                r |= 1;
        !           523:        }
        !           524:
        !           525:        if (why & QE_CR_STAT_FCOFLOW) {
        !           526:                ifp->if_ierrors += 256;
        !           527:                r |= 1;
        !           528:        }
        !           529:
        !           530:        if (why & QE_CR_STAT_CECOFLOW) {
        !           531:                ifp->if_ierrors += 256;
        !           532:                r |= 1;
        !           533:        }
        !           534:
        !           535:        if (why & QE_CR_STAT_RXDROP) {
        !           536:                printf("%s: rx packet dropped\n", sc->sc_dev.dv_xname);
        !           537:                ifp->if_ierrors++;
        !           538:                r |= 1;
        !           539:        }
        !           540:
        !           541:        if (why & QE_CR_STAT_RXSMALL) {
        !           542:                printf("%s: rx buffer too small\n", sc->sc_dev.dv_xname);
        !           543:                ifp->if_ierrors++;
        !           544:                r |= 1;
        !           545:                rst = 1;
        !           546:        }
        !           547:
        !           548:        if (why & QE_CR_STAT_RXLERR) {
        !           549:                printf("%s: rx late error\n", sc->sc_dev.dv_xname);
        !           550:                ifp->if_ierrors++;
        !           551:                r |= 1;
        !           552:                rst = 1;
        !           553:        }
        !           554:
        !           555:        if (why & QE_CR_STAT_RXPERR) {
        !           556:                printf("%s: rx dma parity error\n", sc->sc_dev.dv_xname);
        !           557:                ifp->if_ierrors++;
        !           558:                r |= 1;
        !           559:                rst = 1;
        !           560:        }
        !           561:
        !           562:        if (why & QE_CR_STAT_RXSERR) {
        !           563:                printf("%s: rx dma sbus error ack\n", sc->sc_dev.dv_xname);
        !           564:                ifp->if_ierrors++;
        !           565:                r |= 1;
        !           566:                rst = 1;
        !           567:        }
        !           568:
        !           569:        if (r == 0)
        !           570:                printf("%s: unexpected interrupt error: %08x\n",
        !           571:                        sc->sc_dev.dv_xname, why);
        !           572:
        !           573:        if (rst) {
        !           574:                printf("%s: resetting...\n", sc->sc_dev.dv_xname);
        !           575:                qereset(sc);
        !           576:                return (-1);
        !           577:        }
        !           578:
        !           579:        return (r);
        !           580: }
        !           581:
        !           582: int
        !           583: qeioctl(ifp, cmd, data)
        !           584:        struct ifnet *ifp;
        !           585:        u_long cmd;
        !           586:        caddr_t data;
        !           587: {
        !           588:        struct qesoftc *sc = ifp->if_softc;
        !           589:        struct ifaddr *ifa = (struct ifaddr *)data;
        !           590:        struct ifreq *ifr = (struct ifreq *)data;
        !           591:        int s, error = 0;
        !           592:
        !           593:        s = splnet();
        !           594:
        !           595:        switch (cmd) {
        !           596:        case SIOCSIFADDR:
        !           597:                ifp->if_flags |= IFF_UP;
        !           598:                switch (ifa->ifa_addr->sa_family) {
        !           599: #ifdef INET
        !           600:                case AF_INET:
        !           601:                        qeinit(sc);
        !           602:                        arp_ifinit(&sc->sc_arpcom, ifa);
        !           603:                        break;
        !           604: #endif /* INET */
        !           605:                default:
        !           606:                        qeinit(sc);
        !           607:                        break;
        !           608:                }
        !           609:                break;
        !           610:
        !           611:        case SIOCSIFFLAGS:
        !           612:                if ((ifp->if_flags & IFF_UP) == 0 &&
        !           613:                    (ifp->if_flags & IFF_RUNNING) != 0) {
        !           614:                        /*
        !           615:                         * If interface is marked down and it is running, then
        !           616:                         * stop it.
        !           617:                         */
        !           618:                        qestop(sc);
        !           619:                        ifp->if_flags &= ~IFF_RUNNING;
        !           620:                } else if ((ifp->if_flags & IFF_UP) != 0 &&
        !           621:                    (ifp->if_flags & IFF_RUNNING) == 0) {
        !           622:                        /*
        !           623:                         * If interface is marked up and it is stopped, then
        !           624:                         * start it.
        !           625:                         */
        !           626:                        qeinit(sc);
        !           627:                } else {
        !           628:                        /*
        !           629:                         * Reset the interface to pick up changes in any other
        !           630:                         * flags that affect hardware registers.
        !           631:                         */
        !           632:                        qestop(sc);
        !           633:                        qeinit(sc);
        !           634:                }
        !           635:                break;
        !           636:
        !           637:        case SIOCADDMULTI:
        !           638:        case SIOCDELMULTI:
        !           639:                error = (cmd == SIOCADDMULTI) ?
        !           640:                    ether_addmulti(ifr, &sc->sc_arpcom):
        !           641:                    ether_delmulti(ifr, &sc->sc_arpcom);
        !           642:
        !           643:                if (error == ENETRESET) {
        !           644:                        /*
        !           645:                         * Multicast list has changed; set the hardware filter
        !           646:                         * accordingly.
        !           647:                         */
        !           648:                        if (ifp->if_flags & IFF_RUNNING)
        !           649:                                qeinit(sc);
        !           650:                        error = 0;
        !           651:                }
        !           652:                break;
        !           653:        case SIOCGIFMEDIA:
        !           654:        case SIOCSIFMEDIA:
        !           655:                error = ifmedia_ioctl(ifp, ifr, &sc->sc_ifmedia, cmd);
        !           656:                break;
        !           657:        default:
        !           658:                if ((error = ether_ioctl(ifp, &sc->sc_arpcom, cmd, data)) > 0) {
        !           659:                        splx(s);
        !           660:                        return (error);
        !           661:                }
        !           662:                error = ENOTTY;
        !           663:                break;
        !           664:        }
        !           665:        splx(s);
        !           666:        return (error);
        !           667: }
        !           668:
        !           669: void
        !           670: qeinit(sc)
        !           671:        struct qesoftc *sc;
        !           672: {
        !           673:        struct qe_mregs *mr = sc->sc_mr;
        !           674:        struct qe_cregs *cr = sc->sc_cr;
        !           675:        struct qec_softc *qec = sc->sc_qec;
        !           676:        struct ifnet *ifp = &sc->sc_arpcom.ac_if;
        !           677:        int s = splnet();
        !           678:        int i;
        !           679:
        !           680:        qestop(sc);
        !           681:
        !           682:        /*
        !           683:         * Allocate descriptor ring and buffers, if not already done
        !           684:         */
        !           685:        if (sc->sc_desc == NULL)
        !           686:                sc->sc_desc_dva = (struct qe_desc *) dvma_malloc(
        !           687:                        sizeof(struct qe_desc), &sc->sc_desc, M_NOWAIT);
        !           688:        bzero(sc->sc_desc, sizeof(struct qe_desc));
        !           689:
        !           690:        if (sc->sc_bufs == NULL)
        !           691:                sc->sc_bufs_dva = (struct qe_bufs *) dvma_malloc(
        !           692:                        sizeof(struct qe_bufs), &sc->sc_bufs, M_NOWAIT);
        !           693:        bzero(sc->sc_bufs, sizeof(struct qe_bufs));
        !           694:
        !           695:        for (i = 0; i < QE_TX_RING_MAXSIZE; i++)
        !           696:                sc->sc_desc->qe_txd[i].tx_addr =
        !           697:                        (u_int32_t)sc->sc_bufs_dva->tx_buf[i & QE_TX_RING_MASK];
        !           698:        for (i = 0; i < QE_RX_RING_MAXSIZE; i++) {
        !           699:                sc->sc_desc->qe_rxd[i].rx_addr =
        !           700:                        (u_int32_t)sc->sc_bufs_dva->rx_buf[i & QE_RX_RING_MASK];
        !           701:                if (i < QE_RX_RING_SIZE)
        !           702:                        sc->sc_desc->qe_rxd[i].rx_flags =
        !           703:                                QE_RXD_OWN | QE_RXD_LENGTH;
        !           704:        }
        !           705:
        !           706:        cr->rxds = (u_int32_t)sc->sc_desc_dva->qe_rxd;
        !           707:        cr->txds = (u_int32_t)sc->sc_desc_dva->qe_txd;
        !           708:
        !           709:        sc->sc_first_td = sc->sc_last_td = sc->sc_no_td = 0;
        !           710:        sc->sc_last_rd = 0;
        !           711:
        !           712:        cr->rimask = 0;
        !           713:        cr->timask = 0;
        !           714:        cr->qmask = 0;
        !           715:        cr->mmask = QE_CR_MMASK_RXCOLL | QE_CR_MMASK_CLOSS;
        !           716:        cr->ccnt = 0;
        !           717:        cr->pipg = 0;
        !           718:        cr->rxwbufptr = cr->rxrbufptr = sc->sc_channel * qec->sc_msize;
        !           719:        cr->txwbufptr = cr->txrbufptr = cr->rxrbufptr + qec->sc_rsize;
        !           720:
        !           721:        /*
        !           722:         * When switching from mace<->qec always guarantee an sbus
        !           723:         * turnaround (if last op was read, perform a dummy write, and
        !           724:         * vice versa).
        !           725:         */
        !           726:        i = cr->qmask;          /* dummy */
        !           727:
        !           728:        mr->biucc = QE_MR_BIUCC_BSWAP | QE_MR_BIUCC_64TS;
        !           729:        mr->fifofc = QE_MR_FIFOCC_TXF16 | QE_MR_FIFOCC_RXF32 |
        !           730:            QE_MR_FIFOCC_RFWU | QE_MR_FIFOCC_TFWU;
        !           731:        mr->xmtfc = QE_MR_XMTFC_APADXMT;
        !           732:        mr->rcvfc = 0;
        !           733:        mr->imr = QE_MR_IMR_CERRM | QE_MR_IMR_RCVINTM;
        !           734:        mr->phycc = QE_MR_PHYCC_ASEL;
        !           735:        mr->plscc = QE_MR_PLSCC_TP;
        !           736:
        !           737:        qe_ifmedia_upd(ifp);
        !           738:
        !           739:        mr->iac = QE_MR_IAC_ADDRCHG | QE_MR_IAC_PHYADDR;
        !           740:        for (i = 100; i > 0; i--) {
        !           741:                if ((mr->iac & QE_MR_IAC_ADDRCHG) == 0)
        !           742:                        break;
        !           743:                DELAY(2);
        !           744:        }
        !           745:        mr->padr = sc->sc_arpcom.ac_enaddr[0];
        !           746:        mr->padr = sc->sc_arpcom.ac_enaddr[1];
        !           747:        mr->padr = sc->sc_arpcom.ac_enaddr[2];
        !           748:        mr->padr = sc->sc_arpcom.ac_enaddr[3];
        !           749:        mr->padr = sc->sc_arpcom.ac_enaddr[4];
        !           750:        mr->padr = sc->sc_arpcom.ac_enaddr[5];
        !           751:        qe_mcreset(sc);
        !           752:        mr->iac = 0;
        !           753:
        !           754:        i = mr->mpc;    /* cleared on read */
        !           755:
        !           756:        ifp->if_flags |= IFF_RUNNING;
        !           757:        ifp->if_flags &= ~IFF_OACTIVE;
        !           758:
        !           759:        mr->maccc = QE_MR_MACCC_ENXMT | QE_MR_MACCC_ENRCV |
        !           760:            ((ifp->if_flags & IFF_PROMISC) ? QE_MR_MACCC_PROM : 0);
        !           761:        splx(s);
        !           762: }
        !           763:
        !           764: /*
        !           765:  * Pass a packet to the higher levels.
        !           766:  */
        !           767: void
        !           768: qe_read(sc, idx, len)
        !           769:        struct qesoftc *sc;
        !           770:        int idx, len;
        !           771: {
        !           772:        struct ifnet *ifp = &sc->sc_arpcom.ac_if;
        !           773:        struct mbuf *m;
        !           774:
        !           775:        if (len <= sizeof(struct ether_header) ||
        !           776:            len > ETHERMTU + sizeof(struct ether_header)) {
        !           777:
        !           778:                printf("%s: invalid packet size %d; dropping\n",
        !           779:                        ifp->if_xname, len);
        !           780:
        !           781:                ifp->if_ierrors++;
        !           782:                return;
        !           783:        }
        !           784:
        !           785:        /*
        !           786:         * Pull packet off interface.
        !           787:         */
        !           788:        m = qec_get(ifp, sc->sc_bufs->rx_buf[idx & QE_RX_RING_MASK], len);
        !           789:        if (m == NULL) {
        !           790:                ifp->if_ierrors++;
        !           791:                return;
        !           792:        }
        !           793:        ifp->if_ipackets++;
        !           794:
        !           795: #if NBPFILTER > 0
        !           796:        /*
        !           797:         * Check if there's a BPF listener on this interface.
        !           798:         * If so, hand off the raw packet to BPF.
        !           799:         */
        !           800:        if (ifp->if_bpf)
        !           801:                bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
        !           802: #endif
        !           803:        /* Pass the packet up. */
        !           804:        ether_input_mbuf(ifp, m);
        !           805: }
        !           806:
        !           807: /*
        !           808:  * Reset multicast filter.
        !           809:  */
        !           810: void
        !           811: qe_mcreset(sc)
        !           812:        struct qesoftc *sc;
        !           813: {
        !           814:        struct arpcom *ac = &sc->sc_arpcom;
        !           815:        struct ifnet *ifp = &sc->sc_arpcom.ac_if;
        !           816:        struct qe_mregs *mr = sc->sc_mr;
        !           817:        struct ether_multi *enm;
        !           818:        struct ether_multistep step;
        !           819:        u_int32_t crc;
        !           820:        u_int16_t hash[4];
        !           821:        u_int8_t octet, *ladrp = (u_int8_t *)&hash[0];
        !           822:        int i, j;
        !           823:
        !           824: allmulti:
        !           825:        if (ifp->if_flags & IFF_ALLMULTI) {
        !           826:                mr->iac = QE_MR_IAC_ADDRCHG | QE_MR_IAC_LOGADDR;
        !           827:                for (i = 100; i > 0; i--) {
        !           828:                        if ((mr->iac & QE_MR_IAC_ADDRCHG) == 0)
        !           829:                                break;
        !           830:                        DELAY(2);
        !           831:                }
        !           832:                for (i = 0; i < 8; i++)
        !           833:                        mr->ladrf = 0xff;
        !           834:                return;
        !           835:        }
        !           836:
        !           837:        hash[3] = hash[2] = hash[1] = hash[0] = 0;
        !           838:
        !           839:        ETHER_FIRST_MULTI(step, ac, enm);
        !           840:        while (enm != NULL) {
        !           841:                if (bcmp(enm->enm_addrlo, enm->enm_addrhi,
        !           842:                    ETHER_ADDR_LEN)) {
        !           843:                        /*
        !           844:                         * We must listen to a range of multicast
        !           845:                         * addresses. For now, just accept all
        !           846:                         * multicasts, rather than trying to set only
        !           847:                         * those filter bits needed to match the range.
        !           848:                         * (At this time, the only use of address
        !           849:                         * ranges is for IP multicast routing, for
        !           850:                         * which the range is big enough to require
        !           851:                         * all bits set.)
        !           852:                         */
        !           853:                        ifp->if_flags |= IFF_ALLMULTI;
        !           854:                        goto allmulti;
        !           855:                }
        !           856:
        !           857:                crc = 0xffffffff;
        !           858:
        !           859:                for (i = 0; i < ETHER_ADDR_LEN; i++) {
        !           860:                        octet = enm->enm_addrlo[i];
        !           861:
        !           862:                        for (j = 0; j < 8; j++) {
        !           863:                                if ((crc & 1) ^ (octet & 1)) {
        !           864:                                        crc >>= 1;
        !           865:                                        crc ^= MC_POLY_LE;
        !           866:                                }
        !           867:                                else
        !           868:                                        crc >>= 1;
        !           869:                                octet >>= 1;
        !           870:                        }
        !           871:                }
        !           872:
        !           873:                crc >>= 26;
        !           874:                hash[crc >> 4] |= 1 << (crc & 0xf);
        !           875:                ETHER_NEXT_MULTI(step, enm);
        !           876:        }
        !           877:
        !           878:        mr->iac = QE_MR_IAC_ADDRCHG | QE_MR_IAC_LOGADDR;
        !           879:        for (i = 100; i > 0; i--) {
        !           880:                if ((mr->iac & QE_MR_IAC_ADDRCHG) == 0)
        !           881:                        break;
        !           882:                DELAY(2);
        !           883:        }
        !           884:        for (i = 0; i < 8; i++)
        !           885:                mr->ladrf = ladrp[i];
        !           886: }
        !           887:
        !           888: void
        !           889: qe_ifmedia_sts(ifp, ifmr)
        !           890:        struct ifnet *ifp;
        !           891:        struct ifmediareq *ifmr;
        !           892: {
        !           893:        struct qesoftc *sc = (struct qesoftc *)ifp->if_softc;
        !           894:        u_int8_t phycc;
        !           895:
        !           896:        ifmr->ifm_active = IFM_ETHER | IFM_10_T;
        !           897:        phycc = sc->sc_mr->phycc;
        !           898:        if ((phycc & QE_MR_PHYCC_DLNKTST) == 0) {
        !           899:                ifmr->ifm_status |= IFM_AVALID;
        !           900:                if (phycc & QE_MR_PHYCC_LNKFL)
        !           901:                        ifmr->ifm_status &= ~IFM_ACTIVE;
        !           902:                else
        !           903:                        ifmr->ifm_status |= IFM_ACTIVE;
        !           904:        }
        !           905: }
        !           906:
        !           907: int
        !           908: qe_ifmedia_upd(ifp)
        !           909:        struct ifnet *ifp;
        !           910: {
        !           911:        struct qesoftc *sc = (struct qesoftc *)ifp->if_softc;
        !           912:        int media = sc->sc_ifmedia.ifm_media;
        !           913:
        !           914:        if (IFM_TYPE(media) != IFM_ETHER)
        !           915:                return (EINVAL);
        !           916:
        !           917:        if (IFM_SUBTYPE(media) != IFM_10_T)
        !           918:                return (EINVAL);
        !           919:
        !           920:        return (0);
        !           921: }

CVSweb