[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

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