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

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

1.1     ! nbrk        1: /*     $OpenBSD: be.c,v 1.40 2006/05/27 23:59:07 jason Exp $   */
        !             2:
        !             3: /*
        !             4:  * Copyright (c) 1998 Theo de Raadt and 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: #include <sys/param.h>
        !            29: #include <sys/systm.h>
        !            30: #include <sys/kernel.h>
        !            31: #include <sys/errno.h>
        !            32: #include <sys/ioctl.h>
        !            33: #include <sys/mbuf.h>
        !            34: #include <sys/socket.h>
        !            35: #include <sys/syslog.h>
        !            36: #include <sys/device.h>
        !            37: #include <sys/malloc.h>
        !            38: #include <sys/timeout.h>
        !            39:
        !            40: #include <net/if.h>
        !            41: #include <net/if_dl.h>
        !            42: #include <net/if_types.h>
        !            43: #include <net/netisr.h>
        !            44: #include <net/if_media.h>
        !            45:
        !            46: #ifdef INET
        !            47: #include <netinet/in.h>
        !            48: #include <netinet/in_systm.h>
        !            49: #include <netinet/in_var.h>
        !            50: #include <netinet/ip.h>
        !            51: #include <netinet/if_ether.h>
        !            52: #endif
        !            53:
        !            54: #include "bpfilter.h"
        !            55: #if NBPFILTER > 0
        !            56: #include <net/bpf.h>
        !            57: #include <net/bpfdesc.h>
        !            58: #endif
        !            59:
        !            60: #include <machine/autoconf.h>
        !            61: #include <machine/cpu.h>
        !            62:
        !            63: #include <sparc/dev/sbusvar.h>
        !            64: #include <sparc/dev/dmareg.h>
        !            65: #include <sparc/dev/dmavar.h>
        !            66:
        !            67: #include <sparc/dev/qecvar.h>
        !            68: #include <sparc/dev/qecreg.h>
        !            69: #include <sparc/dev/bereg.h>
        !            70: #include <sparc/dev/bevar.h>
        !            71:
        !            72: int    bematch(struct device *, void *, void *);
        !            73: void   beattach(struct device *, struct device *, void *);
        !            74:
        !            75: void   beinit(struct besoftc *);
        !            76: void   bestart(struct ifnet *);
        !            77: void   bestop(struct besoftc *);
        !            78: void   bewatchdog(struct ifnet *);
        !            79: int    beioctl(struct ifnet *, u_long, caddr_t);
        !            80: void   bereset(struct besoftc *);
        !            81:
        !            82: int    beintr(void *);
        !            83: int    berint(struct besoftc *);
        !            84: int    betint(struct besoftc *);
        !            85: int    beqint(struct besoftc *, u_int32_t);
        !            86: int    beeint(struct besoftc *, u_int32_t);
        !            87: void   be_read(struct besoftc *, int, int);
        !            88:
        !            89: void   be_tcvr_idle(struct besoftc *);
        !            90: void   be_tcvr_init(struct besoftc *);
        !            91: void   be_tcvr_write(struct besoftc *, u_int8_t, u_int16_t);
        !            92: void   be_tcvr_write_bit(struct besoftc *, int);
        !            93: int    be_tcvr_read_bit1(struct besoftc *);
        !            94: int    be_tcvr_read_bit2(struct besoftc *);
        !            95: int    be_tcvr_read(struct besoftc *, u_int8_t);
        !            96: void   be_ifmedia_sts(struct ifnet *, struct ifmediareq *);
        !            97: int    be_ifmedia_upd(struct ifnet *);
        !            98: void   be_mcreset(struct besoftc *);
        !            99: void   betick(void *);
        !           100: void   be_tx_harvest(struct besoftc *);
        !           101:
        !           102: struct cfdriver be_cd = {
        !           103:        NULL, "be", DV_IFNET
        !           104: };
        !           105:
        !           106: struct cfattach be_ca = {
        !           107:        sizeof(struct besoftc), bematch, beattach
        !           108: };
        !           109:
        !           110: int
        !           111: bematch(parent, vcf, aux)
        !           112:        struct device *parent;
        !           113:        void *vcf, *aux;
        !           114: {
        !           115:        struct cfdata *cf = vcf;
        !           116:        struct confargs *ca = aux;
        !           117:        register struct romaux *ra = &ca->ca_ra;
        !           118:
        !           119:        if (strcmp(cf->cf_driver->cd_name, ra->ra_name))
        !           120:                return (0);
        !           121:        return (1);
        !           122: }
        !           123:
        !           124: void
        !           125: beattach(parent, self, aux)
        !           126:        struct device *parent, *self;
        !           127:        void *aux;
        !           128: {
        !           129:        struct qec_softc *qec = (struct qec_softc *)parent;
        !           130:        struct besoftc *sc = (struct besoftc *)self;
        !           131:        struct ifnet *ifp = &sc->sc_arpcom.ac_if;
        !           132:        struct confargs *ca = aux;
        !           133:        struct bootpath *bp;
        !           134:        extern void myetheraddr(u_char *);
        !           135:        int pri, bmsr;
        !           136:
        !           137:        if (ca->ca_ra.ra_nintr != 1) {
        !           138:                printf(": expected 1 interrupt, got %d\n", ca->ca_ra.ra_nintr);
        !           139:                return;
        !           140:        }
        !           141:        pri = ca->ca_ra.ra_intr[0].int_pri;
        !           142:        sc->sc_rev = getpropint(ca->ca_ra.ra_node, "board-version", -1);
        !           143:
        !           144:        timeout_set(&sc->sc_tick, betick, sc);
        !           145:
        !           146:        sc->sc_cr = mapiodev(&ca->ca_ra.ra_reg[0], 0, sizeof(struct be_cregs));
        !           147:        sc->sc_br = mapiodev(&ca->ca_ra.ra_reg[1], 0, sizeof(struct be_bregs));
        !           148:        sc->sc_tr = mapiodev(&ca->ca_ra.ra_reg[2], 0, sizeof(struct be_tregs));
        !           149:        sc->sc_qec = qec;
        !           150:        sc->sc_qr = qec->sc_regs;
        !           151:        bestop(sc);
        !           152:
        !           153:        sc->sc_channel = getpropint(ca->ca_ra.ra_node, "channel#", -1);
        !           154:        if (sc->sc_channel == -1)
        !           155:                sc->sc_channel = 0;
        !           156:
        !           157:        sc->sc_burst = getpropint(ca->ca_ra.ra_node, "burst-sizes", -1);
        !           158:        if (sc->sc_burst == -1)
        !           159:                sc->sc_burst = qec->sc_burst;
        !           160:
        !           161:        /* Clamp at parent's burst sizes */
        !           162:        sc->sc_burst &= qec->sc_burst;
        !           163:
        !           164:        sc->sc_ih.ih_fun = beintr;
        !           165:        sc->sc_ih.ih_arg = sc;
        !           166:        intr_establish(pri, &sc->sc_ih, IPL_NET, sc->sc_dev.dv_xname);
        !           167:
        !           168:        myetheraddr(sc->sc_arpcom.ac_enaddr);
        !           169:
        !           170:        be_tcvr_init(sc);
        !           171:
        !           172:        ifmedia_init(&sc->sc_ifmedia, 0, be_ifmedia_upd, be_ifmedia_sts);
        !           173:        bmsr = be_tcvr_read(sc, PHY_BMSR);
        !           174:        if (bmsr == BE_TCVR_READ_INVALID)
        !           175:                return;
        !           176:
        !           177:        if (bmsr & PHY_BMSR_10BASET_HALF) {
        !           178:                ifmedia_add(&sc->sc_ifmedia, IFM_ETHER | IFM_10_T, 0, NULL);
        !           179:                ifmedia_add(&sc->sc_ifmedia,
        !           180:                    IFM_ETHER | IFM_10_T | IFM_HDX, 0, NULL);
        !           181:                sc->sc_ifmedia.ifm_media = IFM_ETHER | IFM_10_T | IFM_HDX;
        !           182:        }
        !           183:
        !           184:        if (bmsr & PHY_BMSR_10BASET_FULL) {
        !           185:                ifmedia_add(&sc->sc_ifmedia,
        !           186:                    IFM_ETHER | IFM_10_T | IFM_FDX, 0, NULL);
        !           187:                sc->sc_ifmedia.ifm_media = IFM_ETHER | IFM_10_T | IFM_FDX;
        !           188:        }
        !           189:
        !           190:        if (bmsr & PHY_BMSR_100BASETX_HALF) {
        !           191:                ifmedia_add(&sc->sc_ifmedia, IFM_ETHER | IFM_100_TX, 0, NULL);
        !           192:                ifmedia_add(&sc->sc_ifmedia,
        !           193:                    IFM_ETHER | IFM_100_TX | IFM_HDX, 0, NULL);
        !           194:                sc->sc_ifmedia.ifm_media = IFM_ETHER | IFM_100_TX | IFM_HDX;
        !           195:        }
        !           196:
        !           197:        if (bmsr & PHY_BMSR_100BASETX_FULL) {
        !           198:                ifmedia_add(&sc->sc_ifmedia,
        !           199:                    IFM_ETHER | IFM_100_TX | IFM_FDX, 0, NULL);
        !           200:                sc->sc_ifmedia.ifm_media = IFM_ETHER | IFM_100_TX | IFM_FDX;
        !           201:        }
        !           202:
        !           203:        if (bmsr & PHY_BMSR_100BASET4) {
        !           204:                ifmedia_add(&sc->sc_ifmedia,
        !           205:                    IFM_ETHER | IFM_100_T4, 0, NULL);
        !           206:                sc->sc_ifmedia.ifm_media = IFM_ETHER | IFM_100_T4;
        !           207:        }
        !           208:
        !           209:        if (bmsr & PHY_BMSR_ANC) {
        !           210:                ifmedia_add(&sc->sc_ifmedia,
        !           211:                    IFM_ETHER | IFM_AUTO, 0, NULL);
        !           212:                sc->sc_ifmedia.ifm_media = IFM_ETHER | IFM_AUTO;
        !           213:        }
        !           214:
        !           215:        ifmedia_set(&sc->sc_ifmedia, sc->sc_ifmedia.ifm_media);
        !           216:
        !           217:        bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
        !           218:        ifp->if_softc = sc;
        !           219:        ifp->if_start = bestart;
        !           220:        ifp->if_ioctl = beioctl;
        !           221:        ifp->if_watchdog = bewatchdog;
        !           222:        ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS |
        !           223:            IFF_MULTICAST;
        !           224:
        !           225:        IFQ_SET_MAXLEN(&ifp->if_snd, BE_TX_RING_SIZE);
        !           226:        IFQ_SET_READY(&ifp->if_snd);
        !           227:
        !           228:        /* Attach the interface. */
        !           229:        if_attach(ifp);
        !           230:        ether_ifattach(ifp);
        !           231:
        !           232:        printf(" pri %d: rev %x address %s\n", pri, sc->sc_rev,
        !           233:            ether_sprintf(sc->sc_arpcom.ac_enaddr));
        !           234:
        !           235:        bp = ca->ca_ra.ra_bp;
        !           236:        if (bp != NULL && strcmp(bp->name, "be") == 0 &&
        !           237:            sc->sc_dev.dv_unit == bp->val[1])
        !           238:                bp->dev = &sc->sc_dev;
        !           239: }
        !           240:
        !           241: /*
        !           242:  * Start output on interface.
        !           243:  * We make two assumptions here:
        !           244:  *  1) that the current priority is set to splnet _before_ this code
        !           245:  *     is called *and* is returned to the appropriate priority after
        !           246:  *     return
        !           247:  *  2) that the IFF_OACTIVE flag is checked before this code is called
        !           248:  *     (i.e. that the output part of the interface is idle)
        !           249:  */
        !           250: void
        !           251: bestart(ifp)
        !           252:        struct ifnet *ifp;
        !           253: {
        !           254:        struct besoftc *sc = (struct besoftc *)ifp->if_softc;
        !           255:        struct mbuf *m;
        !           256:        int bix, len, cnt;
        !           257:
        !           258:        if (sc->sc_no_td > 0) {
        !           259:                /* Try to free previous stuff */
        !           260:                be_tx_harvest(sc);
        !           261:        }
        !           262:
        !           263:        if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
        !           264:                return;
        !           265:
        !           266:        bix = sc->sc_last_td;
        !           267:        cnt = sc->sc_no_td;
        !           268:
        !           269:        for (;;) {
        !           270:                IFQ_POLL(&ifp->if_snd, m);
        !           271:                if (m == NULL)
        !           272:                        break;
        !           273:
        !           274:                IFQ_DEQUEUE(&ifp->if_snd, m);
        !           275:
        !           276: #if NBPFILTER > 0
        !           277:                /*
        !           278:                 * If BPF is listening on this interface, let it see the
        !           279:                 * packet before we commit it to the wire.
        !           280:                 */
        !           281:                if (ifp->if_bpf)
        !           282:                        bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);
        !           283: #endif
        !           284:
        !           285:                /*
        !           286:                 * Copy the mbuf chain into the transmit buffer.
        !           287:                 */
        !           288:                len = qec_put(sc->sc_bufs->tx_buf[bix & BE_TX_RING_MASK], m);
        !           289:
        !           290:                /*
        !           291:                 * Initialize transmit registers and start transmission
        !           292:                 */
        !           293:                sc->sc_desc->be_txd[bix].tx_flags =
        !           294:                        BE_TXD_OWN | BE_TXD_SOP | BE_TXD_EOP |
        !           295:                        (len & BE_TXD_LENGTH);
        !           296:                sc->sc_cr->ctrl = BE_CR_CTRL_TWAKEUP;
        !           297:
        !           298:                if (++bix == BE_TX_RING_MAXSIZE)
        !           299:                        bix = 0;
        !           300:
        !           301:                if (++cnt == BE_TX_RING_SIZE) {
        !           302:                        ifp->if_flags |= IFF_OACTIVE;
        !           303:                        break;
        !           304:                }
        !           305:        }
        !           306:
        !           307:        if (cnt > BE_TX_HIGH_WATER) {
        !           308:                /* turn on interrupt */
        !           309:                sc->sc_tx_intr = 1;
        !           310:                sc->sc_cr->timask = 0;
        !           311:        }
        !           312:
        !           313:        if (cnt != sc->sc_no_td) {
        !           314:                ifp->if_timer = 5;
        !           315:                sc->sc_last_td = bix;
        !           316:                sc->sc_no_td = cnt;
        !           317:        }
        !           318: }
        !           319:
        !           320: void
        !           321: bestop(sc)
        !           322:        struct besoftc *sc;
        !           323: {
        !           324:        int tries;
        !           325:
        !           326:        sc->sc_arpcom.ac_if.if_timer = 0;
        !           327:        if (timeout_pending(&sc->sc_tick))
        !           328:                timeout_del(&sc->sc_tick);
        !           329:
        !           330:        tries = 32;
        !           331:        sc->sc_br->tx_cfg = 0;
        !           332:        while (sc->sc_br->tx_cfg != 0 && --tries)
        !           333:                DELAY(20);
        !           334:
        !           335:        tries = 32;
        !           336:        sc->sc_br->rx_cfg = 0;
        !           337:        while (sc->sc_br->rx_cfg != 0 && --tries)
        !           338:                DELAY(20);
        !           339: }
        !           340:
        !           341: /*
        !           342:  * Reset interface.
        !           343:  */
        !           344: void
        !           345: bereset(sc)
        !           346:        struct besoftc *sc;
        !           347: {
        !           348:        int s;
        !           349:
        !           350:        s = splnet();
        !           351:        bestop(sc);
        !           352:        beinit(sc);
        !           353:        splx(s);
        !           354: }
        !           355:
        !           356: void
        !           357: bewatchdog(ifp)
        !           358:        struct ifnet *ifp;
        !           359: {
        !           360:        struct besoftc *sc = ifp->if_softc;
        !           361:
        !           362:        log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
        !           363:        ++sc->sc_arpcom.ac_if.if_oerrors;
        !           364:
        !           365:        bereset(sc);
        !           366: }
        !           367:
        !           368: int
        !           369: beintr(v)
        !           370:        void *v;
        !           371: {
        !           372:        struct besoftc *sc = (struct besoftc *)v;
        !           373:        u_int32_t whyq, whyb, whyc;
        !           374:        int r = 0;
        !           375:
        !           376:        whyq = sc->sc_qr->stat;         /* qec status */
        !           377:        whyc = sc->sc_cr->stat;         /* be channel status */
        !           378:        whyb = sc->sc_br->stat;         /* be status */
        !           379:
        !           380:        if (whyq & QEC_STAT_BM)
        !           381:                r |= beeint(sc, whyb);
        !           382:
        !           383:        if (whyq & QEC_STAT_ER)
        !           384:                r |= beqint(sc, whyc);
        !           385:
        !           386:        if (sc->sc_tx_intr && (whyq & QEC_STAT_TX) && (whyc & BE_CR_STAT_TXIRQ))
        !           387:                r |= betint(sc);
        !           388:
        !           389:        if (whyq & QEC_STAT_RX && whyc & BE_CR_STAT_RXIRQ)
        !           390:                r |= berint(sc);
        !           391:
        !           392:        return (r);
        !           393: }
        !           394:
        !           395: /*
        !           396:  * QEC Interrupt.
        !           397:  */
        !           398: int
        !           399: beqint(sc, why)
        !           400:        struct besoftc *sc;
        !           401:        u_int32_t why;
        !           402: {
        !           403:        int r = 0, rst = 0;
        !           404:
        !           405:        if (why & BE_CR_STAT_TXIRQ)
        !           406:                r |= 1;
        !           407:        if (why & BE_CR_STAT_RXIRQ)
        !           408:                r |= 1;
        !           409:
        !           410:        if (why & BE_CR_STAT_ERRORS) {
        !           411:                r |= 1;
        !           412:                rst = 1;
        !           413:        }
        !           414:
        !           415:        if (rst || r == 0) {
        !           416:                printf("%s:%s qstat=%b\n", sc->sc_dev.dv_xname,
        !           417:                    (r) ? "" : " unexpected",
        !           418:                    why, BE_CR_STAT_BITS);
        !           419:                printf("%s: resetting\n", sc->sc_dev.dv_xname);
        !           420:                bereset(sc);
        !           421:        }
        !           422:
        !           423:        return r;
        !           424: }
        !           425:
        !           426: /*
        !           427:  * Error interrupt.
        !           428:  */
        !           429: int
        !           430: beeint(sc, why)
        !           431:        struct besoftc *sc;
        !           432:        u_int32_t why;
        !           433: {
        !           434:        int r = 0;
        !           435:
        !           436:        if (why & (BE_BR_STAT_RFIFOVF | BE_BR_STAT_TFIFO_UND |
        !           437:                   BE_BR_STAT_MAXPKTERR)) {
        !           438:                r |= 1;
        !           439:        }
        !           440:
        !           441:        printf("%s:%s stat=%b\n", sc->sc_dev.dv_xname,
        !           442:            (r) ? "" : " unexpected", why, BE_BR_STAT_BITS);
        !           443:
        !           444:        printf("%s: resetting\n", sc->sc_dev.dv_xname);
        !           445:        bereset(sc);
        !           446:
        !           447:        return r;
        !           448: }
        !           449:
        !           450: void
        !           451: be_tx_harvest(sc)
        !           452:        struct besoftc *sc;
        !           453: {
        !           454:        struct ifnet *ifp = &sc->sc_arpcom.ac_if;
        !           455:        int bix, cnt;
        !           456:        struct be_txd txd;
        !           457:
        !           458:        bix = sc->sc_first_td;
        !           459:        cnt = sc->sc_no_td;
        !           460:
        !           461:        for (;;) {
        !           462:                if (cnt <= 0)
        !           463:                        break;
        !           464:
        !           465:                txd.tx_flags = sc->sc_desc->be_txd[bix].tx_flags;
        !           466:
        !           467:                if (txd.tx_flags & BE_TXD_OWN)
        !           468:                        break;
        !           469:
        !           470:                ifp->if_opackets++;
        !           471:
        !           472:                if (++bix == BE_TX_RING_MAXSIZE)
        !           473:                        bix = 0;
        !           474:
        !           475:                --cnt;
        !           476:        }
        !           477:
        !           478:        if (cnt <= 0)
        !           479:                ifp->if_timer = 0;
        !           480:
        !           481:        if (sc->sc_no_td != cnt) {
        !           482:                sc->sc_first_td = bix;
        !           483:                sc->sc_no_td = cnt;
        !           484:                ifp->if_flags &= ~IFF_OACTIVE;
        !           485:        }
        !           486:
        !           487:        if (sc->sc_no_td < BE_TX_LOW_WATER) {
        !           488:                /* turn off interrupt */
        !           489:                sc->sc_tx_intr = 0;
        !           490:                sc->sc_cr->timask = 0xffffffff;
        !           491:        }
        !           492: }
        !           493:
        !           494: /*
        !           495:  * Transmit interrupt.
        !           496:  */
        !           497: int
        !           498: betint(sc)
        !           499:        struct besoftc *sc;
        !           500: {
        !           501:        struct ifnet *ifp = &sc->sc_arpcom.ac_if;
        !           502:
        !           503:        bestart(ifp);
        !           504:        return (1);
        !           505: }
        !           506:
        !           507: /*
        !           508:  * Receive interrupt.
        !           509:  */
        !           510: int
        !           511: berint(sc)
        !           512:        struct besoftc *sc;
        !           513: {
        !           514:        int bix, len;
        !           515:
        !           516:        bix = sc->sc_last_rd;
        !           517:
        !           518:        /*
        !           519:         * Process all buffers with valid data.
        !           520:         */
        !           521:        for (;;) {
        !           522:                if (sc->sc_desc->be_rxd[bix].rx_flags & BE_RXD_OWN)
        !           523:                        break;
        !           524:
        !           525:                len = sc->sc_desc->be_rxd[bix].rx_flags & BE_RXD_LENGTH;
        !           526:                be_read(sc, bix, len);
        !           527:
        !           528:                sc->sc_desc->be_rxd[(bix + BE_RX_RING_SIZE) & BE_RX_RING_MAXMASK].rx_flags =
        !           529:                    BE_RXD_OWN | (BE_PKT_BUF_SZ & BE_RXD_LENGTH);
        !           530:
        !           531:                if (++bix == BE_RX_RING_MAXSIZE)
        !           532:                        bix = 0;
        !           533:        }
        !           534:
        !           535:        sc->sc_last_rd = bix;
        !           536:
        !           537:        return 1;
        !           538: }
        !           539:
        !           540: void
        !           541: betick(vsc)
        !           542:        void *vsc;
        !           543: {
        !           544:        struct besoftc *sc = vsc;
        !           545:        struct ifnet *ifp = &sc->sc_arpcom.ac_if;
        !           546:        struct be_bregs *br = sc->sc_br;
        !           547:        int s;
        !           548:
        !           549:        s = splnet();
        !           550:        /*
        !           551:         * Get collision counters
        !           552:         */
        !           553:        ifp->if_collisions += br->nc_ctr + br->fc_ctr + br->ex_ctr + br->lt_ctr;
        !           554:        br->nc_ctr = 0;
        !           555:        br->fc_ctr = 0;
        !           556:        br->ex_ctr = 0;
        !           557:        br->lt_ctr = 0;
        !           558:        bestart(ifp);
        !           559:        splx(s);
        !           560:        timeout_add(&sc->sc_tick, hz);
        !           561: }
        !           562:
        !           563: int
        !           564: beioctl(ifp, cmd, data)
        !           565:        struct ifnet *ifp;
        !           566:        u_long cmd;
        !           567:        caddr_t data;
        !           568: {
        !           569:        struct besoftc *sc = ifp->if_softc;
        !           570:        struct ifaddr *ifa = (struct ifaddr *)data;
        !           571:        struct ifreq *ifr = (struct ifreq *)data;
        !           572:        int s, error = 0;
        !           573:
        !           574:        s = splnet();
        !           575:
        !           576:        switch (cmd) {
        !           577:        case SIOCSIFADDR:
        !           578:                ifp->if_flags |= IFF_UP;
        !           579:                switch (ifa->ifa_addr->sa_family) {
        !           580: #ifdef INET
        !           581:                case AF_INET:
        !           582:                        beinit(sc);
        !           583:                        arp_ifinit(&sc->sc_arpcom, ifa);
        !           584:                        break;
        !           585: #endif /* INET */
        !           586:                default:
        !           587:                        beinit(sc);
        !           588:                        break;
        !           589:                }
        !           590:                break;
        !           591:
        !           592:        case SIOCSIFFLAGS:
        !           593:                if ((ifp->if_flags & IFF_UP) == 0 &&
        !           594:                    (ifp->if_flags & IFF_RUNNING) != 0) {
        !           595:                        /*
        !           596:                         * If interface is marked down and it is running, then
        !           597:                         * stop it.
        !           598:                         */
        !           599:                        bestop(sc);
        !           600:                        ifp->if_flags &= ~IFF_RUNNING;
        !           601:                } else if ((ifp->if_flags & IFF_UP) != 0 &&
        !           602:                    (ifp->if_flags & IFF_RUNNING) == 0) {
        !           603:                        /*
        !           604:                         * If interface is marked up and it is stopped, then
        !           605:                         * start it.
        !           606:                         */
        !           607:                        beinit(sc);
        !           608:                } else {
        !           609:                        /*
        !           610:                         * Reset the interface to pick up changes in any other
        !           611:                         * flags that affect hardware registers.
        !           612:                         */
        !           613:                        bestop(sc);
        !           614:                        beinit(sc);
        !           615:                }
        !           616:                break;
        !           617:
        !           618:        case SIOCADDMULTI:
        !           619:        case SIOCDELMULTI:
        !           620:                error = (cmd == SIOCADDMULTI) ?
        !           621:                    ether_addmulti(ifr, &sc->sc_arpcom):
        !           622:                    ether_delmulti(ifr, &sc->sc_arpcom);
        !           623:
        !           624:                if (error == ENETRESET) {
        !           625:                        /*
        !           626:                         * Multicast list has changed; set the hardware filter
        !           627:                         * accordingly.
        !           628:                         */
        !           629:                        if (ifp->if_flags & IFF_RUNNING)
        !           630:                                be_mcreset(sc);
        !           631:                        error = 0;
        !           632:                }
        !           633:                break;
        !           634:        case SIOCGIFMEDIA:
        !           635:        case SIOCSIFMEDIA:
        !           636:                error = ifmedia_ioctl(ifp, ifr, &sc->sc_ifmedia, cmd);
        !           637:                break;
        !           638:        default:
        !           639:                if ((error = ether_ioctl(ifp, &sc->sc_arpcom, cmd, data)) > 0) {
        !           640:                        splx(s);
        !           641:                        return error;
        !           642:                }
        !           643:                error = ENOTTY;
        !           644:                break;
        !           645:        }
        !           646:        splx(s);
        !           647:        return error;
        !           648: }
        !           649:
        !           650: void
        !           651: beinit(sc)
        !           652:        struct besoftc *sc;
        !           653: {
        !           654:        struct be_bregs *br = sc->sc_br;
        !           655:        struct be_cregs *cr = sc->sc_cr;
        !           656:        struct qec_softc *qec = sc->sc_qec;
        !           657:        struct ifnet *ifp = &sc->sc_arpcom.ac_if;
        !           658:        int s = splnet();
        !           659:        int i;
        !           660:
        !           661:        /*
        !           662:         * Allocate descriptor ring and buffers, if not already done
        !           663:         */
        !           664:        if (sc->sc_desc == NULL)
        !           665:                sc->sc_desc_dva = (struct be_desc *) dvma_malloc(
        !           666:                        sizeof(struct be_desc), &sc->sc_desc, M_NOWAIT);
        !           667:        if (sc->sc_bufs == NULL)
        !           668:                sc->sc_bufs_dva = (struct be_bufs *) dvma_malloc(
        !           669:                        sizeof(struct be_bufs), &sc->sc_bufs, M_NOWAIT);
        !           670:
        !           671:        for (i = 0; i < BE_TX_RING_MAXSIZE; i++) {
        !           672:                sc->sc_desc->be_txd[i].tx_addr =
        !           673:                        (u_int32_t)sc->sc_bufs_dva->tx_buf[i & BE_TX_RING_MASK];
        !           674:                sc->sc_desc->be_txd[i].tx_flags = 0;
        !           675:        }
        !           676:        for (i = 0; i < BE_RX_RING_MAXSIZE; i++) {
        !           677:                sc->sc_desc->be_rxd[i].rx_addr =
        !           678:                    (u_int32_t)sc->sc_bufs_dva->rx_buf[i & BE_RX_RING_MASK];
        !           679:                if (i < BE_RX_RING_SIZE)
        !           680:                        sc->sc_desc->be_rxd[i].rx_flags =
        !           681:                            BE_RXD_OWN | (BE_PKT_BUF_SZ & BE_RXD_LENGTH);
        !           682:                else
        !           683:                        sc->sc_desc->be_rxd[i].rx_flags = 0;
        !           684:        }
        !           685:
        !           686:        sc->sc_first_td = sc->sc_last_td = sc->sc_no_td = 0;
        !           687:        sc->sc_last_rd = 0;
        !           688:
        !           689:        be_tcvr_init(sc);
        !           690:
        !           691:        be_ifmedia_upd(ifp);
        !           692:
        !           693:        bestop(sc);
        !           694:
        !           695:        br->mac_addr2 = (sc->sc_arpcom.ac_enaddr[4] << 8) |
        !           696:            sc->sc_arpcom.ac_enaddr[5];
        !           697:        br->mac_addr1 = (sc->sc_arpcom.ac_enaddr[2] << 8) |
        !           698:            sc->sc_arpcom.ac_enaddr[3];
        !           699:        br->mac_addr0 = (sc->sc_arpcom.ac_enaddr[0] << 8) |
        !           700:            sc->sc_arpcom.ac_enaddr[1];
        !           701:
        !           702:        br->rx_cfg = BE_BR_RXCFG_HENABLE | BE_BR_RXCFG_FIFO;
        !           703:
        !           704:        be_mcreset(sc);
        !           705:
        !           706:        DELAY(20);
        !           707:
        !           708:        br->tx_cfg = BE_BR_TXCFG_FIFO;
        !           709:        br->rand_seed = 0xbd;
        !           710:
        !           711:        br->xif_cfg = BE_BR_XCFG_ODENABLE | BE_BR_XCFG_RESV;
        !           712:
        !           713:        cr->rxds = (u_int32_t)sc->sc_desc_dva->be_rxd;
        !           714:        cr->txds = (u_int32_t)sc->sc_desc_dva->be_txd;
        !           715:
        !           716:        cr->rxwbufptr = cr->rxrbufptr = sc->sc_channel * qec->sc_msize;
        !           717:        cr->txwbufptr = cr->txrbufptr = cr->rxrbufptr + qec->sc_rsize;
        !           718:
        !           719:        /*
        !           720:         * Turn off counter expiration interrupts as well as
        !           721:         * 'gotframe' and 'sentframe'
        !           722:         */
        !           723:        br->imask = BE_BR_IMASK_GOTFRAME        |
        !           724:                    BE_BR_IMASK_RCNTEXP         |
        !           725:                    BE_BR_IMASK_ACNTEXP         |
        !           726:                    BE_BR_IMASK_CCNTEXP         |
        !           727:                    BE_BR_IMASK_LCNTEXP         |
        !           728:                    BE_BR_IMASK_CVCNTEXP        |
        !           729:                    BE_BR_IMASK_SENTFRAME       |
        !           730:                    BE_BR_IMASK_NCNTEXP         |
        !           731:                    BE_BR_IMASK_ECNTEXP         |
        !           732:                    BE_BR_IMASK_LCCNTEXP        |
        !           733:                    BE_BR_IMASK_FCNTEXP         |
        !           734:                    BE_BR_IMASK_DTIMEXP;
        !           735:
        !           736:        cr->rimask = 0;
        !           737:
        !           738:        /* disable tx interrupts initially */
        !           739:        cr->timask = 0xffffffff;
        !           740:        sc->sc_tx_intr = 0;
        !           741:
        !           742:        cr->qmask = 0;
        !           743:        cr->bmask = 0;
        !           744:
        !           745:        br->jsize = 4;
        !           746:
        !           747:        cr->ccnt = 0;
        !           748:
        !           749:        br->tx_cfg |= BE_BR_TXCFG_ENABLE;
        !           750:        br->rx_cfg |= BE_BR_RXCFG_ENABLE;
        !           751:
        !           752:        ifp->if_flags |= IFF_RUNNING;
        !           753:        ifp->if_flags &= ~IFF_OACTIVE;
        !           754:        splx(s);
        !           755:
        !           756:        timeout_add(&sc->sc_tick, hz);
        !           757:        bestart(ifp);
        !           758: }
        !           759:
        !           760: /*
        !           761:  * Set the tcvr to an idle state
        !           762:  */
        !           763: void
        !           764: be_tcvr_idle(sc)
        !           765:        struct besoftc *sc;
        !           766: {
        !           767:        struct be_tregs *tr = sc->sc_tr;
        !           768:        volatile u_int32_t x;
        !           769:        int i = 20;
        !           770:
        !           771:        while (i--) {
        !           772:                tr->mgmt_pal = MGMT_PAL_INT_MDIO | MGMT_PAL_EXT_MDIO |
        !           773:                               MGMT_PAL_OENAB;
        !           774:                x = tr->mgmt_pal;
        !           775:                tr->mgmt_pal = MGMT_PAL_INT_MDIO | MGMT_PAL_EXT_MDIO |
        !           776:                               MGMT_PAL_OENAB | MGMT_PAL_DCLOCK;
        !           777:                x = tr->mgmt_pal;
        !           778:        }
        !           779: }
        !           780:
        !           781: /*
        !           782:  * Initialize the transceiver and figure out whether we're using the
        !           783:  * external or internal one.
        !           784:  */
        !           785: void
        !           786: be_tcvr_init(sc)
        !           787:        struct besoftc *sc;
        !           788: {
        !           789:        volatile u_int32_t x;
        !           790:        struct be_tregs *tr = sc->sc_tr;
        !           791:
        !           792:        be_tcvr_idle(sc);
        !           793:
        !           794:        if (sc->sc_rev != 1) {
        !           795:                printf("%s: rev %d PAL not supported.\n",
        !           796:                        sc->sc_dev.dv_xname,
        !           797:                        sc->sc_rev);
        !           798:                return;
        !           799:        }
        !           800:
        !           801:        tr->mgmt_pal = MGMT_PAL_INT_MDIO | MGMT_PAL_EXT_MDIO | MGMT_PAL_DCLOCK;
        !           802:        x = tr->mgmt_pal;
        !           803:
        !           804:        tr->mgmt_pal = MGMT_PAL_INT_MDIO | MGMT_PAL_EXT_MDIO;
        !           805:        x = tr->mgmt_pal;
        !           806:        DELAY(200);
        !           807:
        !           808:        if (tr->mgmt_pal & MGMT_PAL_EXT_MDIO) {
        !           809:                sc->sc_tcvr_type = BE_TCVR_EXTERNAL;
        !           810:                tr->tcvr_pal = ~(TCVR_PAL_EXTLBACK | TCVR_PAL_MSENSE |
        !           811:                                 TCVR_PAL_LTENABLE);
        !           812:                x = tr->tcvr_pal;
        !           813:        }
        !           814:        else if (tr->mgmt_pal & MGMT_PAL_INT_MDIO) {
        !           815:                sc->sc_tcvr_type = BE_TCVR_INTERNAL;
        !           816:                tr->tcvr_pal = ~(TCVR_PAL_EXTLBACK | TCVR_PAL_MSENSE |
        !           817:                                 TCVR_PAL_LTENABLE | TCVR_PAL_SERIAL);
        !           818:                x = tr->tcvr_pal;
        !           819:        }
        !           820:        else {
        !           821:                printf("%s: no internal or external transceiver found.\n",
        !           822:                        sc->sc_dev.dv_xname);
        !           823:        }
        !           824: }
        !           825:
        !           826: int
        !           827: be_tcvr_read(sc, reg)
        !           828:        struct besoftc *sc;
        !           829:        u_int8_t reg;
        !           830: {
        !           831:        int phy, i;
        !           832:        u_int32_t ret = 0;
        !           833:
        !           834:        if (sc->sc_tcvr_type == BE_TCVR_INTERNAL)
        !           835:                phy = BE_PHY_INTERNAL;
        !           836:        else if (sc->sc_tcvr_type == BE_TCVR_EXTERNAL)
        !           837:                phy = BE_PHY_EXTERNAL;
        !           838:        else {
        !           839:                printf("%s: invalid tcvr type\n", sc->sc_dev.dv_xname);
        !           840:                return BE_TCVR_READ_INVALID;
        !           841:        }
        !           842:
        !           843:        be_tcvr_idle(sc);
        !           844:
        !           845:        be_tcvr_write_bit(sc, 0);
        !           846:        be_tcvr_write_bit(sc, 1);
        !           847:        be_tcvr_write_bit(sc, 1);
        !           848:        be_tcvr_write_bit(sc, 0);
        !           849:
        !           850:        for (i = 4; i >= 0; i--)
        !           851:                be_tcvr_write_bit(sc, (phy >> i) & 1);
        !           852:
        !           853:        for (i = 4; i >= 0; i--)
        !           854:                be_tcvr_write_bit(sc, (reg >> i) & 1);
        !           855:
        !           856:        if (sc->sc_tcvr_type == BE_TCVR_EXTERNAL) {
        !           857:                (void) be_tcvr_read_bit2(sc);
        !           858:                (void) be_tcvr_read_bit2(sc);
        !           859:
        !           860:                for (i = 15; i >= 0; i--) {
        !           861:                        int b;
        !           862:
        !           863:                        b = be_tcvr_read_bit2(sc);
        !           864:                        ret |= (b & 1) << i;
        !           865:                }
        !           866:
        !           867:                (void) be_tcvr_read_bit2(sc);
        !           868:                (void) be_tcvr_read_bit2(sc);
        !           869:                (void) be_tcvr_read_bit2(sc);
        !           870:        }
        !           871:        else {
        !           872:                (void) be_tcvr_read_bit1(sc);
        !           873:                (void) be_tcvr_read_bit1(sc);
        !           874:
        !           875:                for (i = 15; i >= 0; i--) {
        !           876:                        int b;
        !           877:
        !           878:                        b = be_tcvr_read_bit1(sc);
        !           879:                        ret |= (b & 1) << i;
        !           880:                }
        !           881:
        !           882:                (void) be_tcvr_read_bit1(sc);
        !           883:                (void) be_tcvr_read_bit1(sc);
        !           884:                (void) be_tcvr_read_bit1(sc);
        !           885:        }
        !           886:        return ret;
        !           887: }
        !           888:
        !           889: int
        !           890: be_tcvr_read_bit1(sc)
        !           891:        struct besoftc *sc;
        !           892: {
        !           893:        volatile u_int32_t x;
        !           894:        struct be_tregs *tr = sc->sc_tr;
        !           895:        int ret = 0;
        !           896:
        !           897:        if (sc->sc_tcvr_type == BE_TCVR_INTERNAL) {
        !           898:                tr->mgmt_pal = MGMT_PAL_EXT_MDIO;
        !           899:                x = tr->mgmt_pal;
        !           900:                tr->mgmt_pal = MGMT_PAL_EXT_MDIO | MGMT_PAL_DCLOCK;
        !           901:                x = tr->mgmt_pal;
        !           902:                DELAY(20);
        !           903:                ret = (tr->mgmt_pal & MGMT_PAL_INT_MDIO) >> 3;
        !           904:        } else if (sc->sc_tcvr_type == BE_TCVR_EXTERNAL) {
        !           905:                tr->mgmt_pal = MGMT_PAL_INT_MDIO;
        !           906:                x = tr->mgmt_pal;
        !           907:                tr->mgmt_pal = MGMT_PAL_INT_MDIO | MGMT_PAL_DCLOCK;
        !           908:                x = tr->mgmt_pal;
        !           909:                DELAY(20);
        !           910:                ret = (tr->mgmt_pal & MGMT_PAL_EXT_MDIO) >> 2;
        !           911:        } else {
        !           912:                printf("%s: invalid tcvr type\n", sc->sc_dev.dv_xname);
        !           913:        }
        !           914:        return (ret & 1);
        !           915: }
        !           916:
        !           917: int
        !           918: be_tcvr_read_bit2(sc)
        !           919:        struct besoftc *sc;
        !           920: {
        !           921:        volatile u_int32_t x;
        !           922:        struct be_tregs *tr = sc->sc_tr;
        !           923:        int ret = 0;
        !           924:
        !           925:        if (sc->sc_tcvr_type == BE_TCVR_INTERNAL) {
        !           926:                tr->mgmt_pal = MGMT_PAL_EXT_MDIO;
        !           927:                x = tr->mgmt_pal;
        !           928:                DELAY(20);
        !           929:                ret = (tr->mgmt_pal & MGMT_PAL_INT_MDIO) >> 3;
        !           930:                tr->mgmt_pal = MGMT_PAL_EXT_MDIO | MGMT_PAL_DCLOCK;
        !           931:                x = tr->mgmt_pal;
        !           932:        } else if (sc->sc_tcvr_type == BE_TCVR_EXTERNAL) {
        !           933:                tr->mgmt_pal = MGMT_PAL_INT_MDIO;
        !           934:                x = tr->mgmt_pal;
        !           935:                DELAY(20);
        !           936:                ret = (tr->mgmt_pal & MGMT_PAL_EXT_MDIO) >> 2;
        !           937:                tr->mgmt_pal = MGMT_PAL_INT_MDIO | MGMT_PAL_DCLOCK;
        !           938:                x = tr->mgmt_pal;
        !           939:        } else {
        !           940:                printf("%s: invalid tcvr type\n", sc->sc_dev.dv_xname);
        !           941:        }
        !           942:        return ret;
        !           943: }
        !           944:
        !           945: void
        !           946: be_tcvr_write(sc, reg, val)
        !           947:        struct besoftc *sc;
        !           948:        u_int8_t reg;
        !           949:        u_int16_t val;
        !           950: {
        !           951:        int phy, i;
        !           952:
        !           953:        if (sc->sc_tcvr_type == BE_TCVR_INTERNAL)
        !           954:                phy = BE_PHY_INTERNAL;
        !           955:        else if (sc->sc_tcvr_type == BE_TCVR_EXTERNAL)
        !           956:                phy = BE_PHY_EXTERNAL;
        !           957:        else {
        !           958:                printf("%s: invalid tcvr type\n", sc->sc_dev.dv_xname);
        !           959:                return;
        !           960:        }
        !           961:
        !           962:        be_tcvr_idle(sc);
        !           963:
        !           964:        be_tcvr_write_bit(sc, 0);
        !           965:        be_tcvr_write_bit(sc, 1);
        !           966:        be_tcvr_write_bit(sc, 0);
        !           967:        be_tcvr_write_bit(sc, 1);
        !           968:
        !           969:        for (i = 4; i >= 0; i--)
        !           970:                be_tcvr_write_bit(sc, (phy >> i) & 1);
        !           971:
        !           972:        for (i = 4; i >= 0; i--)
        !           973:                be_tcvr_write_bit(sc, (reg >> i) & 1);
        !           974:
        !           975:        be_tcvr_write_bit(sc, 1);
        !           976:        be_tcvr_write_bit(sc, 0);
        !           977:
        !           978:        for (i = 15; i >= 0; i--)
        !           979:                be_tcvr_write_bit(sc, (val >> i) & 1);
        !           980: }
        !           981:
        !           982: void
        !           983: be_tcvr_write_bit(sc, bit)
        !           984:        struct besoftc *sc;
        !           985:        int bit;
        !           986: {
        !           987:        volatile u_int32_t x;
        !           988:
        !           989:        if (sc->sc_tcvr_type == BE_TCVR_INTERNAL) {
        !           990:                bit = ((bit & 1) << 3) | MGMT_PAL_OENAB | MGMT_PAL_EXT_MDIO;
        !           991:                sc->sc_tr->mgmt_pal = bit;
        !           992:                x = sc->sc_tr->mgmt_pal;
        !           993:                sc->sc_tr->mgmt_pal = bit | MGMT_PAL_DCLOCK;
        !           994:                x = sc->sc_tr->mgmt_pal;
        !           995:        } else {
        !           996:                bit = ((bit & 1) << 2) | MGMT_PAL_OENAB | MGMT_PAL_INT_MDIO;
        !           997:                sc->sc_tr->mgmt_pal = bit;
        !           998:                x = sc->sc_tr->mgmt_pal;
        !           999:                sc->sc_tr->mgmt_pal = bit | MGMT_PAL_DCLOCK;
        !          1000:                x = sc->sc_tr->mgmt_pal;
        !          1001:        }
        !          1002: }
        !          1003:
        !          1004: /*
        !          1005:  * Pass a packet to the higher levels.
        !          1006:  */
        !          1007: void
        !          1008: be_read(sc, idx, len)
        !          1009:        struct besoftc *sc;
        !          1010:        int idx, len;
        !          1011: {
        !          1012:        struct ifnet *ifp = &sc->sc_arpcom.ac_if;
        !          1013:        struct mbuf *m;
        !          1014:
        !          1015:        if (len <= sizeof(struct ether_header) ||
        !          1016:            len > ETHERMTU + sizeof(struct ether_header)) {
        !          1017:
        !          1018:                printf("%s: invalid packet size %d; dropping\n",
        !          1019:                        ifp->if_xname, len);
        !          1020:
        !          1021:                ifp->if_ierrors++;
        !          1022:                return;
        !          1023:        }
        !          1024:
        !          1025:        /*
        !          1026:         * Pull packet off interface.
        !          1027:         */
        !          1028:        m = qec_get(ifp, sc->sc_bufs->rx_buf[idx & BE_RX_RING_MASK], len);
        !          1029:        if (m == NULL) {
        !          1030:                ifp->if_ierrors++;
        !          1031:                return;
        !          1032:        }
        !          1033:        ifp->if_ipackets++;
        !          1034:
        !          1035:
        !          1036: #if NBPFILTER > 0
        !          1037:        /*
        !          1038:         * Check if there's a BPF listener on this interface.
        !          1039:         * If so, hand off the raw packet to BPF.
        !          1040:         */
        !          1041:        if (ifp->if_bpf)
        !          1042:                bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
        !          1043: #endif
        !          1044:        /* Pass the packet up. */
        !          1045:        ether_input_mbuf(ifp, m);
        !          1046: }
        !          1047:
        !          1048: /*
        !          1049:  * Get current media settings.
        !          1050:  */
        !          1051: void
        !          1052: be_ifmedia_sts(ifp, ifmr)
        !          1053:        struct ifnet *ifp;
        !          1054:        struct ifmediareq *ifmr;
        !          1055: {
        !          1056:        struct besoftc *sc = ifp->if_softc;
        !          1057:        int bmcr, bmsr;
        !          1058:
        !          1059:        bmcr = be_tcvr_read(sc, PHY_BMCR);
        !          1060:
        !          1061:        switch (bmcr & (PHY_BMCR_SPEED | PHY_BMCR_DUPLEX)) {
        !          1062:        case (PHY_BMCR_SPEED | PHY_BMCR_DUPLEX):
        !          1063:                ifmr->ifm_active = IFM_ETHER | IFM_100_TX | IFM_FDX;
        !          1064:                break;
        !          1065:        case PHY_BMCR_SPEED:
        !          1066:                ifmr->ifm_active = IFM_ETHER | IFM_100_TX | IFM_HDX;
        !          1067:                break;
        !          1068:        case PHY_BMCR_DUPLEX:
        !          1069:                ifmr->ifm_active = IFM_ETHER | IFM_10_T | IFM_FDX;
        !          1070:                break;
        !          1071:        case 0:
        !          1072:                ifmr->ifm_active = IFM_ETHER | IFM_10_T | IFM_HDX;
        !          1073:                break;
        !          1074:        }
        !          1075:
        !          1076:        bmsr = be_tcvr_read(sc, PHY_BMSR);
        !          1077:        if (bmsr & PHY_BMSR_LINKSTATUS)
        !          1078:                ifmr->ifm_status |=  IFM_AVALID | IFM_ACTIVE;
        !          1079:        else {
        !          1080:                ifmr->ifm_status |=  IFM_AVALID;
        !          1081:                ifmr->ifm_status &= ~IFM_ACTIVE;
        !          1082:        }
        !          1083: }
        !          1084:
        !          1085: /*
        !          1086:  * Set media options.
        !          1087:  */
        !          1088: int
        !          1089: be_ifmedia_upd(ifp)
        !          1090:        struct ifnet *ifp;
        !          1091: {
        !          1092:        struct besoftc *sc = ifp->if_softc;
        !          1093:        struct ifmedia *ifm = &sc->sc_ifmedia;
        !          1094:        int bmcr, tries;
        !          1095:
        !          1096:        if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER)
        !          1097:                return (EINVAL);
        !          1098:
        !          1099:        be_tcvr_write(sc, PHY_BMCR,
        !          1100:                PHY_BMCR_LOOPBACK | PHY_BMCR_PDOWN | PHY_BMCR_ISOLATE);
        !          1101:        be_tcvr_write(sc, PHY_BMCR, PHY_BMCR_RESET);
        !          1102:
        !          1103:        for (tries = 16; tries >= 0; tries--) {
        !          1104:                bmcr = be_tcvr_read(sc, PHY_BMCR);
        !          1105:                if ((bmcr & PHY_BMCR_RESET) == 0)
        !          1106:                        break;
        !          1107:                DELAY(20);
        !          1108:        }
        !          1109:        if (tries == 0) {
        !          1110:                printf("%s: bmcr reset failed\n", sc->sc_dev.dv_xname);
        !          1111:                return (EIO);
        !          1112:        }
        !          1113:
        !          1114:        bmcr = be_tcvr_read(sc, PHY_BMCR);
        !          1115:
        !          1116:        if (IFM_SUBTYPE(ifm->ifm_media) == IFM_100_T4) {
        !          1117:                bmcr |= PHY_BMCR_SPEED;
        !          1118:                bmcr &= ~PHY_BMCR_DUPLEX;
        !          1119:        }
        !          1120:
        !          1121:        if (IFM_SUBTYPE(ifm->ifm_media) == IFM_100_TX) {
        !          1122:                bmcr |= PHY_BMCR_SPEED;
        !          1123:        }
        !          1124:
        !          1125:        if (IFM_SUBTYPE(ifm->ifm_media) == IFM_10_T) {
        !          1126:                bmcr &= ~PHY_BMCR_SPEED;
        !          1127:        }
        !          1128:
        !          1129:        if ((ifm->ifm_media & IFM_GMASK) == IFM_FDX) {
        !          1130:                bmcr |= PHY_BMCR_DUPLEX;
        !          1131:                sc->sc_br->tx_cfg |= BE_BR_TXCFG_FULLDPLX;
        !          1132:        }
        !          1133:        else {
        !          1134:                bmcr &= ~PHY_BMCR_DUPLEX;
        !          1135:                sc->sc_br->tx_cfg &= ~BE_BR_TXCFG_FULLDPLX;
        !          1136:        }
        !          1137:
        !          1138:        be_tcvr_write(sc, PHY_BMCR, bmcr & (~PHY_BMCR_ISOLATE));
        !          1139:
        !          1140:        for (tries = 32; tries >= 0; tries--) {
        !          1141:                bmcr = be_tcvr_read(sc, PHY_BMCR);
        !          1142:                if ((bmcr & PHY_BMCR_ISOLATE) == 0)
        !          1143:                        break;
        !          1144:                DELAY(20);
        !          1145:        }
        !          1146:        if (tries == 0) {
        !          1147:                printf("%s: bmcr unisolate failed\n", sc->sc_dev.dv_xname);
        !          1148:                return (EIO);
        !          1149:        }
        !          1150:
        !          1151:        return (0);
        !          1152: }
        !          1153:
        !          1154: void
        !          1155: be_mcreset(sc)
        !          1156:        struct besoftc *sc;
        !          1157: {
        !          1158:        struct arpcom *ac = &sc->sc_arpcom;
        !          1159:        struct ifnet *ifp = &sc->sc_arpcom.ac_if;
        !          1160:        struct be_bregs *br = sc->sc_br;
        !          1161:        u_int32_t crc;
        !          1162:        u_int16_t hash[4];
        !          1163:        u_int8_t octet;
        !          1164:        int i, j;
        !          1165:        struct ether_multi *enm;
        !          1166:        struct ether_multistep step;
        !          1167:
        !          1168:        if (ifp->if_flags & IFF_PROMISC) {
        !          1169:                br->rx_cfg |= BE_BR_RXCFG_PMISC;
        !          1170:                return;
        !          1171:        }
        !          1172:        else
        !          1173:                br->rx_cfg &= ~BE_BR_RXCFG_PMISC;
        !          1174:
        !          1175:        if (ifp->if_flags & IFF_ALLMULTI) {
        !          1176:                br->htable3 = 0xffff;
        !          1177:                br->htable2 = 0xffff;
        !          1178:                br->htable1 = 0xffff;
        !          1179:                br->htable0 = 0xffff;
        !          1180:                return;
        !          1181:        }
        !          1182:
        !          1183:        hash[3] = hash[2] = hash[1] = hash[0] = 0;
        !          1184:
        !          1185:        ETHER_FIRST_MULTI(step, ac, enm);
        !          1186:        while (enm != NULL) {
        !          1187:                if (bcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) {
        !          1188:                        /*
        !          1189:                         * We must listen to a range of multicast
        !          1190:                         * addresses.  For now, just accept all
        !          1191:                         * multicasts, rather than trying to set only
        !          1192:                         * those filter bits needed to match the range.
        !          1193:                         * (At this time, the only use of address
        !          1194:                         * ranges is for IP multicast routing, for
        !          1195:                         * which the range is big enough to require
        !          1196:                         * all bits set.)
        !          1197:                         */
        !          1198:                        br->htable3 = 0xffff;
        !          1199:                        br->htable2 = 0xffff;
        !          1200:                        br->htable1 = 0xffff;
        !          1201:                        br->htable0 = 0xffff;
        !          1202:                        ifp->if_flags |= IFF_ALLMULTI;
        !          1203:                        return;
        !          1204:                }
        !          1205:
        !          1206:                crc = 0xffffffff;
        !          1207:
        !          1208:                for (i = 0; i < ETHER_ADDR_LEN; i++) {
        !          1209:                        octet = enm->enm_addrlo[i];
        !          1210:
        !          1211:                        for (j = 0; j < 8; j++) {
        !          1212:                                if ((crc & 1) ^ (octet & 1)) {
        !          1213:                                        crc >>= 1;
        !          1214:                                        crc ^= MC_POLY_LE;
        !          1215:                                }
        !          1216:                                else
        !          1217:                                        crc >>= 1;
        !          1218:                                octet >>= 1;
        !          1219:                        }
        !          1220:                }
        !          1221:
        !          1222:                crc >>= 26;
        !          1223:                hash[crc >> 4] |= 1 << (crc & 0xf);
        !          1224:                ETHER_NEXT_MULTI(step, enm);
        !          1225:        }
        !          1226:
        !          1227:        br->htable3 = hash[3];
        !          1228:        br->htable2 = hash[2];
        !          1229:        br->htable1 = hash[1];
        !          1230:        br->htable0 = hash[0];
        !          1231:        ifp->if_flags &= ~IFF_ALLMULTI;
        !          1232: }

CVSweb