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

Annotation of sys/dev/sbus/be.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: be.c,v 1.19 2006/06/02 20:00:56 miod Exp $    */
                      2: /*     $NetBSD: be.c,v 1.26 2001/03/20 15:39:20 pk Exp $       */
                      3:
                      4: /*-
                      5:  * Copyright (c) 1999 The NetBSD Foundation, Inc.
                      6:  * All rights reserved.
                      7:  *
                      8:  * This code is derived from software contributed to The NetBSD Foundation
                      9:  * by Paul Kranenburg.
                     10:  *
                     11:  * Redistribution and use in source and binary forms, with or without
                     12:  * modification, are permitted provided that the following conditions
                     13:  * are met:
                     14:  * 1. Redistributions of source code must retain the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer.
                     16:  * 2. Redistributions in binary form must reproduce the above copyright
                     17:  *    notice, this list of conditions and the following disclaimer in the
                     18:  *    documentation and/or other materials provided with the distribution.
                     19:  * 3. All advertising materials mentioning features or use of this software
                     20:  *    must display the following acknowledgement:
                     21:  *        This product includes software developed by the NetBSD
                     22:  *        Foundation, Inc. and its contributors.
                     23:  * 4. Neither the name of The NetBSD Foundation nor the names of its
                     24:  *    contributors may be used to endorse or promote products derived
                     25:  *    from this software without specific prior written permission.
                     26:  *
                     27:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     28:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     29:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     30:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     31:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     32:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     33:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     34:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     35:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     36:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     37:  * POSSIBILITY OF SUCH DAMAGE.
                     38:  */
                     39:
                     40: /*
                     41:  * Copyright (c) 1998 Theo de Raadt and Jason L. Wright.
                     42:  * All rights reserved.
                     43:  *
                     44:  * Redistribution and use in source and binary forms, with or without
                     45:  * modification, are permitted provided that the following conditions
                     46:  * are met:
                     47:  * 1. Redistributions of source code must retain the above copyright
                     48:  *    notice, this list of conditions and the following disclaimer.
                     49:  * 2. Redistributions in binary form must reproduce the above copyright
                     50:  *    notice, this list of conditions and the following disclaimer in the
                     51:  *    documentation and/or other materials provided with the distribution.
                     52:  *
                     53:  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
                     54:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     55:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     56:  * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
                     57:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
                     58:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     59:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     60:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     61:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
                     62:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     63:  */
                     64:
                     65: #include "bpfilter.h"
                     66:
                     67: #include <sys/param.h>
                     68: #include <sys/systm.h>
                     69: #include <sys/timeout.h>
                     70: #include <sys/kernel.h>
                     71: #include <sys/errno.h>
                     72: #include <sys/ioctl.h>
                     73: #include <sys/mbuf.h>
                     74: #include <sys/socket.h>
                     75: #include <sys/syslog.h>
                     76: #include <sys/device.h>
                     77: #include <sys/malloc.h>
                     78:
                     79: #include <net/if.h>
                     80: #include <net/if_dl.h>
                     81: #include <net/if_types.h>
                     82: #include <net/netisr.h>
                     83: #include <net/if_media.h>
                     84:
                     85: #ifdef INET
                     86: #include <netinet/in.h>
                     87: #include <netinet/in_systm.h>
                     88: #include <netinet/in_var.h>
                     89: #include <netinet/ip.h>
                     90: #include <netinet/if_ether.h>
                     91: #endif
                     92:
                     93: #if NBPFILTER > 0
                     94: #include <net/bpf.h>
                     95: #endif
                     96:
                     97: #include <machine/bus.h>
                     98: #include <machine/intr.h>
                     99: #include <machine/autoconf.h>
                    100:
                    101: #include <dev/sbus/sbusvar.h>
                    102:
                    103: #include <dev/mii/mii.h>
                    104: #include <dev/mii/miivar.h>
                    105:
                    106: #include <dev/sbus/qecreg.h>
                    107: #include <dev/sbus/qecvar.h>
                    108: #include <dev/sbus/bereg.h>
                    109:
                    110: struct be_softc {
                    111:        struct  device  sc_dev;
                    112:        bus_space_tag_t sc_bustag;      /* bus & dma tags */
                    113:        bus_dma_tag_t   sc_dmatag;
                    114:        bus_dmamap_t    sc_dmamap;
                    115:        struct  arpcom sc_arpcom;
                    116:        /*struct        ifmedia sc_ifmedia;     -* interface media */
                    117:        struct mii_data sc_mii;         /* MII media control */
                    118: #define sc_media       sc_mii.mii_media/* shorthand */
                    119:        int             sc_phys[2];     /* MII instance -> phy */
                    120:
                    121:        struct timeout sc_tick_ch;
                    122:
                    123:        /*
                    124:         * Some `mii_softc' items we need to emulate MII operation
                    125:         * for our internal transceiver.
                    126:         */
                    127:        int             sc_mii_inst;    /* instance of internal phy */
                    128:        int             sc_mii_active;  /* currently active medium */
                    129:        int             sc_mii_ticks;   /* tick counter */
                    130:        int             sc_mii_flags;   /* phy status flags */
                    131: #define MIIF_HAVELINK  0x04000000
                    132:        int             sc_intphy_curspeed;     /* Established link speed */
                    133:
                    134:        struct  qec_softc *sc_qec;      /* QEC parent */
                    135:
                    136:        bus_space_handle_t      sc_qr;  /* QEC registers */
                    137:        bus_space_handle_t      sc_br;  /* BE registers */
                    138:        bus_space_handle_t      sc_cr;  /* channel registers */
                    139:        bus_space_handle_t      sc_tr;  /* transceiver registers */
                    140:
                    141:        u_int   sc_rev;
                    142:
                    143:        int     sc_channel;             /* channel number */
                    144:        int     sc_burst;
                    145:
                    146:        struct  qec_ring        sc_rb;  /* Packet Ring Buffer */
                    147: };
                    148:
                    149: int    bematch(struct device *, void *, void *);
                    150: void   beattach(struct device *, struct device *, void *);
                    151:
                    152: void   beinit(struct be_softc *);
                    153: void   bestart(struct ifnet *);
                    154: void   bestop(struct be_softc *);
                    155: void   bewatchdog(struct ifnet *);
                    156: int    beioctl(struct ifnet *, u_long, caddr_t);
                    157: void   bereset(struct be_softc *);
                    158:
                    159: int    beintr(void *);
                    160: int    berint(struct be_softc *);
                    161: int    betint(struct be_softc *);
                    162: int    beqint(struct be_softc *, u_int32_t);
                    163: int    beeint(struct be_softc *, u_int32_t);
                    164:
                    165: static void    be_read(struct be_softc *, int, int);
                    166: static int     be_put(struct be_softc *, int, struct mbuf *);
                    167: static struct mbuf *be_get(struct be_softc *, int, int);
                    168:
                    169: void   be_pal_gate(struct be_softc *, int);
                    170:
                    171: /* ifmedia callbacks */
                    172: void   be_ifmedia_sts(struct ifnet *, struct ifmediareq *);
                    173: int    be_ifmedia_upd(struct ifnet *);
                    174:
                    175: void   be_mcreset(struct be_softc *);
                    176:
                    177: /* MII methods & callbacks */
                    178: static int     be_mii_readreg(struct device *, int, int);
                    179: static void    be_mii_writereg(struct device *, int, int, int);
                    180: static void    be_mii_statchg(struct device *);
                    181:
                    182: /* MII helpers */
                    183: static void    be_mii_sync(struct be_softc *);
                    184: static void    be_mii_sendbits(struct be_softc *, int, u_int32_t, int);
                    185: static int     be_mii_reset(struct be_softc *, int);
                    186: static int     be_tcvr_read_bit(struct be_softc *, int);
                    187: static void    be_tcvr_write_bit(struct be_softc *, int, int);
                    188:
                    189: void   be_tick(void *);
                    190: void   be_intphy_auto(struct be_softc *);
                    191: void   be_intphy_status(struct be_softc *);
                    192: int    be_intphy_service(struct be_softc *, struct mii_data *, int);
                    193:
                    194:
                    195: struct cfattach be_ca = {
                    196:        sizeof(struct be_softc), bematch, beattach
                    197: };
                    198:
                    199: struct cfdriver be_cd = {
                    200:        NULL, "be", DV_IFNET
                    201: };
                    202:
                    203: int
                    204: bematch(struct device *parent, void *vcf, void *aux)
                    205: {
                    206:        struct cfdata *cf = vcf;
                    207:        struct sbus_attach_args *sa = aux;
                    208:
                    209:        return (strcmp(cf->cf_driver->cd_name, sa->sa_name) == 0);
                    210: }
                    211:
                    212: void
                    213: beattach(struct device *parent, struct device *self, void *aux)
                    214: {
                    215:        struct sbus_attach_args *sa = aux;
                    216:        struct qec_softc *qec = (struct qec_softc *)parent;
                    217:        struct be_softc *sc = (struct be_softc *)self;
                    218:        struct ifnet *ifp = &sc->sc_arpcom.ac_if;
                    219:        struct mii_data *mii = &sc->sc_mii;
                    220:        struct mii_softc *child;
                    221:        int node = sa->sa_node;
                    222:        bus_dma_tag_t dmatag = sa->sa_dmatag;
                    223:        bus_dma_segment_t seg;
                    224:        bus_size_t size;
                    225:        int instance;
                    226:        int rseg, error;
                    227:        u_int32_t v;
                    228:        extern void myetheraddr(u_char *);
                    229:
                    230:        /* Pass on the bus tags */
                    231:        sc->sc_bustag = sa->sa_bustag;
                    232:        sc->sc_dmatag = sa->sa_dmatag;
                    233:
                    234:        if (sa->sa_nreg < 3) {
                    235:                printf("%s: only %d register sets\n",
                    236:                    self->dv_xname, sa->sa_nreg);
                    237:                return;
                    238:        }
                    239:
                    240:        if (sbus_bus_map(sa->sa_bustag, sa->sa_reg[0].sbr_slot,
                    241:            (bus_addr_t)sa->sa_reg[0].sbr_offset,
                    242:            (bus_size_t)sa->sa_reg[0].sbr_size, 0, 0, &sc->sc_cr) != 0) {
                    243:                printf("beattach: cannot map registers\n");
                    244:                return;
                    245:        }
                    246:
                    247:        if (sbus_bus_map(sa->sa_bustag, sa->sa_reg[1].sbr_slot,
                    248:            (bus_addr_t)sa->sa_reg[1].sbr_offset,
                    249:            (bus_size_t)sa->sa_reg[1].sbr_size, 0, 0, &sc->sc_br) != 0) {
                    250:                printf("beattach: cannot map registers\n");
                    251:                return;
                    252:        }
                    253:
                    254:        if (sbus_bus_map(sa->sa_bustag, sa->sa_reg[2].sbr_slot,
                    255:            (bus_addr_t)sa->sa_reg[2].sbr_offset,
                    256:            (bus_size_t)sa->sa_reg[2].sbr_size, 0, 0, &sc->sc_tr) != 0) {
                    257:                printf("beattach: cannot map registers\n");
                    258:                return;
                    259:        }
                    260:
                    261:        sc->sc_qec = qec;
                    262:        sc->sc_qr = qec->sc_regs;
                    263:
                    264:        sc->sc_rev = getpropint(node, "board-version", -1);
                    265:        printf(" rev %x", sc->sc_rev);
                    266:
                    267:        bestop(sc);
                    268:
                    269:        sc->sc_channel = getpropint(node, "channel#", -1);
                    270:        if (sc->sc_channel == -1)
                    271:                sc->sc_channel = 0;
                    272:
                    273:        sc->sc_burst = getpropint(node, "burst-sizes", -1);
                    274:        if (sc->sc_burst == -1)
                    275:                sc->sc_burst = qec->sc_burst;
                    276:
                    277:        /* Clamp at parent's burst sizes */
                    278:        sc->sc_burst &= qec->sc_burst;
                    279:
                    280:        /* Establish interrupt handler */
                    281:        if (sa->sa_nintr == 0 || bus_intr_establish(sa->sa_bustag, sa->sa_pri,
                    282:            IPL_NET, 0, beintr, sc, self->dv_xname) == NULL) {
                    283:                printf(": no interrupt established\n");
                    284:                return;
                    285:        }
                    286:
                    287:        myetheraddr(sc->sc_arpcom.ac_enaddr);
                    288:        printf(" address %s\n", ether_sprintf(sc->sc_arpcom.ac_enaddr));
                    289:
                    290:        /*
                    291:         * Allocate descriptor ring and buffers.
                    292:         */
                    293:
                    294:        /* for now, allocate as many bufs as there are ring descriptors */
                    295:        sc->sc_rb.rb_ntbuf = QEC_XD_RING_MAXSIZE;
                    296:        sc->sc_rb.rb_nrbuf = QEC_XD_RING_MAXSIZE;
                    297:
                    298:        size =  QEC_XD_RING_MAXSIZE * sizeof(struct qec_xd) +
                    299:                QEC_XD_RING_MAXSIZE * sizeof(struct qec_xd) +
                    300:                sc->sc_rb.rb_ntbuf * BE_PKT_BUF_SZ +
                    301:                sc->sc_rb.rb_nrbuf * BE_PKT_BUF_SZ;
                    302:
                    303:        /* Get a DMA handle */
                    304:        if ((error = bus_dmamap_create(dmatag, size, 1, size, 0,
                    305:            BUS_DMA_NOWAIT, &sc->sc_dmamap)) != 0) {
                    306:                printf("%s: DMA map create error %d\n", self->dv_xname, error);
                    307:                return;
                    308:        }
                    309:
                    310:        /* Allocate DMA buffer */
                    311:        if ((error = bus_dmamem_alloc(sa->sa_dmatag, size, 0, 0,
                    312:            &seg, 1, &rseg, BUS_DMA_NOWAIT)) != 0) {
                    313:                printf("%s: DMA buffer alloc error %d\n",
                    314:                        self->dv_xname, error);
                    315:                return;
                    316:        }
                    317:
                    318:        /* Map DMA memory in CPU addressable space */
                    319:        if ((error = bus_dmamem_map(sa->sa_dmatag, &seg, rseg, size,
                    320:            &sc->sc_rb.rb_membase, BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) != 0) {
                    321:                printf("%s: DMA buffer map error %d\n",
                    322:                        self->dv_xname, error);
                    323:                bus_dmamem_free(sa->sa_dmatag, &seg, rseg);
                    324:                return;
                    325:        }
                    326:
                    327:        /* Load the buffer */
                    328:        if ((error = bus_dmamap_load(dmatag, sc->sc_dmamap,
                    329:            sc->sc_rb.rb_membase, size, NULL, BUS_DMA_NOWAIT)) != 0) {
                    330:                printf("%s: DMA buffer map load error %d\n",
                    331:                    self->dv_xname, error);
                    332:                bus_dmamem_unmap(dmatag, sc->sc_rb.rb_membase, size);
                    333:                bus_dmamem_free(dmatag, &seg, rseg);
                    334:                return;
                    335:        }
                    336:        sc->sc_rb.rb_dmabase = sc->sc_dmamap->dm_segs[0].ds_addr;
                    337:
                    338:        /*
                    339:         * Initialize our media structures and MII info.
                    340:         */
                    341:        mii->mii_ifp = ifp;
                    342:        mii->mii_readreg = be_mii_readreg;
                    343:        mii->mii_writereg = be_mii_writereg;
                    344:        mii->mii_statchg = be_mii_statchg;
                    345:
                    346:        ifmedia_init(&mii->mii_media, 0, be_ifmedia_upd, be_ifmedia_sts);
                    347:
                    348:        timeout_set(&sc->sc_tick_ch, be_tick, sc);
                    349:
                    350:        /*
                    351:         * Initialize transceiver and determine which PHY connection to use.
                    352:         */
                    353:        be_mii_sync(sc);
                    354:        v = bus_space_read_4(sc->sc_bustag, sc->sc_tr, BE_TRI_MGMTPAL);
                    355:
                    356:        instance = 0;
                    357:
                    358:        if ((v & MGMT_PAL_EXT_MDIO) != 0) {
                    359:
                    360:                mii_attach(&sc->sc_dev, mii, 0xffffffff, BE_PHY_EXTERNAL,
                    361:                    MII_OFFSET_ANY, 0);
                    362:
                    363:                child = LIST_FIRST(&mii->mii_phys);
                    364:                if (child == NULL) {
                    365:                        /* No PHY attached */
                    366:                        ifmedia_add(&sc->sc_media,
                    367:                            IFM_MAKEWORD(IFM_ETHER,IFM_NONE,0,instance),
                    368:                            0, NULL);
                    369:                        ifmedia_set(&sc->sc_media,
                    370:                            IFM_MAKEWORD(IFM_ETHER,IFM_NONE,0,instance));
                    371:                } else {
                    372:                        /*
                    373:                         * Note: we support just one PHY on the external
                    374:                         * MII connector.
                    375:                         */
                    376: #ifdef DIAGNOSTIC
                    377:                        if (LIST_NEXT(child, mii_list) != NULL) {
                    378:                                printf("%s: spurious MII device %s attached\n",
                    379:                                    sc->sc_dev.dv_xname,
                    380:                                    child->mii_dev.dv_xname);
                    381:                        }
                    382: #endif
                    383:                        if (child->mii_phy != BE_PHY_EXTERNAL ||
                    384:                            child->mii_inst > 0) {
                    385:                                printf("%s: cannot accommodate MII device %s"
                    386:                                    " at phy %d, instance %d\n",
                    387:                                    sc->sc_dev.dv_xname,
                    388:                                    child->mii_dev.dv_xname,
                    389:                                    child->mii_phy, child->mii_inst);
                    390:                        } else {
                    391:                                sc->sc_phys[instance] = child->mii_phy;
                    392:                        }
                    393:
                    394:                        /*
                    395:                         * XXX - we can really do the following ONLY if the
                    396:                         * phy indeed has the auto negotiation capability!!
                    397:                         */
                    398:                        ifmedia_set(&sc->sc_media,
                    399:                            IFM_MAKEWORD(IFM_ETHER,IFM_AUTO,0,instance));
                    400:
                    401:                        /* Mark our current media setting */
                    402:                        be_pal_gate(sc, BE_PHY_EXTERNAL);
                    403:                        instance++;
                    404:                }
                    405:
                    406:        }
                    407:
                    408:        if ((v & MGMT_PAL_INT_MDIO) != 0) {
                    409:                /*
                    410:                 * The be internal phy looks vaguely like MII hardware,
                    411:                 * but not enough to be able to use the MII device
                    412:                 * layer. Hence, we have to take care of media selection
                    413:                 * ourselves.
                    414:                 */
                    415:
                    416:                sc->sc_mii_inst = instance;
                    417:                sc->sc_phys[instance] = BE_PHY_INTERNAL;
                    418:
                    419:                /* Use `ifm_data' to store BMCR bits */
                    420:                ifmedia_add(&sc->sc_media,
                    421:                    IFM_MAKEWORD(IFM_ETHER,IFM_10_T,0,instance), 0, NULL);
                    422:                ifmedia_add(&sc->sc_media,
                    423:                    IFM_MAKEWORD(IFM_ETHER,IFM_100_TX,0,instance),
                    424:                    BMCR_S100, NULL);
                    425:                ifmedia_add(&sc->sc_media,
                    426:                    IFM_MAKEWORD(IFM_ETHER,IFM_AUTO,0,instance), 0, NULL);
                    427:
                    428:                printf("on-board transceiver at %s: 10baseT, 100baseTX, auto\n",
                    429:                    self->dv_xname);
                    430:
                    431:                be_mii_reset(sc, BE_PHY_INTERNAL);
                    432:                /* Only set default medium here if there's no external PHY */
                    433:                if (instance == 0) {
                    434:                        be_pal_gate(sc, BE_PHY_INTERNAL);
                    435:                        ifmedia_set(&sc->sc_media,
                    436:                            IFM_MAKEWORD(IFM_ETHER,IFM_AUTO,0,instance));
                    437:                } else
                    438:                        be_mii_writereg((void *)sc,
                    439:                            BE_PHY_INTERNAL, MII_BMCR, BMCR_ISO);
                    440:        }
                    441:
                    442:        bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
                    443:        ifp->if_softc = sc;
                    444:        ifp->if_start = bestart;
                    445:        ifp->if_ioctl = beioctl;
                    446:        ifp->if_watchdog = bewatchdog;
                    447:        ifp->if_flags =
                    448:            IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST;
                    449:        IFQ_SET_READY(&ifp->if_snd);
                    450:
                    451:        /* Attach the interface. */
                    452:        if_attach(ifp);
                    453:        ether_ifattach(ifp);
                    454: }
                    455:
                    456:
                    457: /*
                    458:  * Routine to copy from mbuf chain to transmit buffer in
                    459:  * network buffer memory.
                    460:  */
                    461: static __inline__ int
                    462: be_put(struct be_softc *sc, int idx, struct mbuf *m)
                    463: {
                    464:        struct mbuf *n;
                    465:        int len, tlen = 0, boff = 0;
                    466:        caddr_t bp;
                    467:
                    468:        bp = sc->sc_rb.rb_txbuf + (idx % sc->sc_rb.rb_ntbuf) * BE_PKT_BUF_SZ;
                    469:
                    470:        for (; m; m = n) {
                    471:                len = m->m_len;
                    472:                if (len == 0) {
                    473:                        MFREE(m, n);
                    474:                        continue;
                    475:                }
                    476:                bcopy(mtod(m, caddr_t), bp+boff, len);
                    477:                boff += len;
                    478:                tlen += len;
                    479:                MFREE(m, n);
                    480:        }
                    481:        return (tlen);
                    482: }
                    483:
                    484: /*
                    485:  * Pull data off an interface.
                    486:  * Len is the length of data, with local net header stripped.
                    487:  * We copy the data into mbufs.  When full cluster sized units are present,
                    488:  * we copy into clusters.
                    489:  */
                    490: static __inline__ struct mbuf *
                    491: be_get(struct be_softc *sc, int idx, int totlen)
                    492: {
                    493:        struct ifnet *ifp = &sc->sc_arpcom.ac_if;
                    494:        struct mbuf *m;
                    495:        struct mbuf *top, **mp;
                    496:        int len, pad, boff = 0;
                    497:        caddr_t bp;
                    498:
                    499:        bp = sc->sc_rb.rb_rxbuf + (idx % sc->sc_rb.rb_nrbuf) * BE_PKT_BUF_SZ;
                    500:
                    501:        MGETHDR(m, M_DONTWAIT, MT_DATA);
                    502:        if (m == NULL)
                    503:                return (NULL);
                    504:        m->m_pkthdr.rcvif = ifp;
                    505:        m->m_pkthdr.len = totlen;
                    506:
                    507:        pad = ALIGN(sizeof(struct ether_header)) - sizeof(struct ether_header);
                    508:        m->m_data += pad;
                    509:        len = MHLEN - pad;
                    510:        top = NULL;
                    511:        mp = &top;
                    512:
                    513:        while (totlen > 0) {
                    514:                if (top) {
                    515:                        MGET(m, M_DONTWAIT, MT_DATA);
                    516:                        if (m == NULL) {
                    517:                                m_freem(top);
                    518:                                return (NULL);
                    519:                        }
                    520:                        len = MLEN;
                    521:                }
                    522:                if (top && totlen >= MINCLSIZE) {
                    523:                        MCLGET(m, M_DONTWAIT);
                    524:                        if (m->m_flags & M_EXT)
                    525:                                len = MCLBYTES;
                    526:                }
                    527:                m->m_len = len = min(totlen, len);
                    528:                bcopy(bp + boff, mtod(m, caddr_t), len);
                    529:                boff += len;
                    530:                totlen -= len;
                    531:                *mp = m;
                    532:                mp = &m->m_next;
                    533:        }
                    534:
                    535:        return (top);
                    536: }
                    537:
                    538: /*
                    539:  * Pass a packet to the higher levels.
                    540:  */
                    541: static __inline__ void
                    542: be_read(struct be_softc *sc, int idx, int len)
                    543: {
                    544:        struct ifnet *ifp = &sc->sc_arpcom.ac_if;
                    545:        struct mbuf *m;
                    546:
                    547:        if (len <= sizeof(struct ether_header) ||
                    548:            len > ETHERMTU + sizeof(struct ether_header)) {
                    549:
                    550:                printf("%s: invalid packet size %d; dropping\n",
                    551:                    ifp->if_xname, len);
                    552:
                    553:                ifp->if_ierrors++;
                    554:                return;
                    555:        }
                    556:
                    557:        /*
                    558:         * Pull packet off interface.
                    559:         */
                    560:        m = be_get(sc, idx, len);
                    561:        if (m == NULL) {
                    562:                ifp->if_ierrors++;
                    563:                return;
                    564:        }
                    565:        ifp->if_ipackets++;
                    566:
                    567: #if NBPFILTER > 0
                    568:        /*
                    569:         * Check if there's a BPF listener on this interface.
                    570:         * If so, hand off the raw packet to BPF.
                    571:         */
                    572:        if (ifp->if_bpf)
                    573:                bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
                    574: #endif
                    575:        /* Pass the packet up. */
                    576:        ether_input_mbuf(ifp, m);
                    577: }
                    578:
                    579: /*
                    580:  * Start output on interface.
                    581:  * We make two assumptions here:
                    582:  *  1) that the current priority is set to splnet _before_ this code
                    583:  *     is called *and* is returned to the appropriate priority after
                    584:  *     return
                    585:  *  2) that the IFF_OACTIVE flag is checked before this code is called
                    586:  *     (i.e. that the output part of the interface is idle)
                    587:  */
                    588: void
                    589: bestart(struct ifnet *ifp)
                    590: {
                    591:        struct be_softc *sc = (struct be_softc *)ifp->if_softc;
                    592:        struct qec_xd *txd = sc->sc_rb.rb_txd;
                    593:        struct mbuf *m;
                    594:        unsigned int bix, len;
                    595:        unsigned int ntbuf = sc->sc_rb.rb_ntbuf;
                    596:
                    597:        if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
                    598:                return;
                    599:
                    600:        bix = sc->sc_rb.rb_tdhead;
                    601:
                    602:        for (;;) {
                    603:                IFQ_DEQUEUE(&ifp->if_snd, m);
                    604:                if (m == 0)
                    605:                        break;
                    606:
                    607: #if NBPFILTER > 0
                    608:                /*
                    609:                 * If BPF is listening on this interface, let it see the
                    610:                 * packet before we commit it to the wire.
                    611:                 */
                    612:                if (ifp->if_bpf)
                    613:                        bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);
                    614: #endif
                    615:
                    616:                /*
                    617:                 * Copy the mbuf chain into the transmit buffer.
                    618:                 */
                    619:                len = be_put(sc, bix, m);
                    620:
                    621:                /*
                    622:                 * Initialize transmit registers and start transmission
                    623:                 */
                    624:                txd[bix].xd_flags = QEC_XD_OWN | QEC_XD_SOP | QEC_XD_EOP |
                    625:                                    (len & QEC_XD_LENGTH);
                    626:                bus_space_write_4(sc->sc_bustag, sc->sc_cr, BE_CRI_CTRL,
                    627:                                  BE_CR_CTRL_TWAKEUP);
                    628:
                    629:                if (++bix == QEC_XD_RING_MAXSIZE)
                    630:                        bix = 0;
                    631:
                    632:                if (++sc->sc_rb.rb_td_nbusy == ntbuf) {
                    633:                        ifp->if_flags |= IFF_OACTIVE;
                    634:                        break;
                    635:                }
                    636:        }
                    637:
                    638:        sc->sc_rb.rb_tdhead = bix;
                    639: }
                    640:
                    641: void
                    642: bestop(struct be_softc *sc)
                    643: {
                    644:        int n;
                    645:        bus_space_tag_t t = sc->sc_bustag;
                    646:        bus_space_handle_t br = sc->sc_br;
                    647:
                    648:        timeout_del(&sc->sc_tick_ch);
                    649:
                    650:        /* Down the MII. */
                    651:        mii_down(&sc->sc_mii);
                    652:        (void)be_intphy_service(sc, &sc->sc_mii, MII_DOWN);
                    653:
                    654:        /* Stop the transmitter */
                    655:        bus_space_write_4(t, br, BE_BRI_TXCFG, 0);
                    656:        for (n = 32; n > 0; n--) {
                    657:                if (bus_space_read_4(t, br, BE_BRI_TXCFG) == 0)
                    658:                        break;
                    659:                DELAY(20);
                    660:        }
                    661:
                    662:        /* Stop the receiver */
                    663:        bus_space_write_4(t, br, BE_BRI_RXCFG, 0);
                    664:        for (n = 32; n > 0; n--) {
                    665:                if (bus_space_read_4(t, br, BE_BRI_RXCFG) == 0)
                    666:                        break;
                    667:                DELAY(20);
                    668:        }
                    669: }
                    670:
                    671: /*
                    672:  * Reset interface.
                    673:  */
                    674: void
                    675: bereset(struct be_softc *sc)
                    676: {
                    677:        int s;
                    678:
                    679:        s = splnet();
                    680:        bestop(sc);
                    681:        if ((sc->sc_arpcom.ac_if.if_flags & IFF_UP) != 0)
                    682:                beinit(sc);
                    683:        splx(s);
                    684: }
                    685:
                    686: void
                    687: bewatchdog(struct ifnet *ifp)
                    688: {
                    689:        struct be_softc *sc = ifp->if_softc;
                    690:
                    691:        log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
                    692:        ++sc->sc_arpcom.ac_if.if_oerrors;
                    693:        bereset(sc);
                    694: }
                    695:
                    696: int
                    697: beintr(void *v)
                    698: {
                    699:        struct be_softc *sc = (struct be_softc *)v;
                    700:        bus_space_tag_t t = sc->sc_bustag;
                    701:        u_int32_t whyq, whyb, whyc;
                    702:        int r = 0;
                    703:
                    704:        /* Read QEC status, channel status and BE status */
                    705:        whyq = bus_space_read_4(t, sc->sc_qr, QEC_QRI_STAT);
                    706:        whyc = bus_space_read_4(t, sc->sc_cr, BE_CRI_STAT);
                    707:        whyb = bus_space_read_4(t, sc->sc_br, BE_BRI_STAT);
                    708:
                    709:        if (whyq & QEC_STAT_BM)
                    710:                r |= beeint(sc, whyb);
                    711:
                    712:        if (whyq & QEC_STAT_ER)
                    713:                r |= beqint(sc, whyc);
                    714:
                    715:        if (whyq & QEC_STAT_TX && whyc & BE_CR_STAT_TXIRQ)
                    716:                r |= betint(sc);
                    717:
                    718:        if (whyq & QEC_STAT_RX && whyc & BE_CR_STAT_RXIRQ)
                    719:                r |= berint(sc);
                    720:
                    721:        return (r);
                    722: }
                    723:
                    724: /*
                    725:  * QEC Interrupt.
                    726:  */
                    727: int
                    728: beqint(struct be_softc *sc, u_int32_t why)
                    729: {
                    730:        int r = 0, rst = 0;
                    731:
                    732:        if (why & BE_CR_STAT_TXIRQ)
                    733:                r |= 1;
                    734:        if (why & BE_CR_STAT_RXIRQ)
                    735:                r |= 1;
                    736:
                    737:        if (why & BE_CR_STAT_BERROR) {
                    738:                r |= 1;
                    739:                rst = 1;
                    740:                printf("%s: bigmac error\n", sc->sc_dev.dv_xname);
                    741:        }
                    742:
                    743:        if (why & BE_CR_STAT_TXDERR) {
                    744:                r |= 1;
                    745:                rst = 1;
                    746:                printf("%s: bogus tx descriptor\n", sc->sc_dev.dv_xname);
                    747:        }
                    748:
                    749:        if (why & (BE_CR_STAT_TXLERR | BE_CR_STAT_TXPERR | BE_CR_STAT_TXSERR)) {
                    750:                r |= 1;
                    751:                rst = 1;
                    752:                printf("%s: tx dma error ( ", sc->sc_dev.dv_xname);
                    753:                if (why & BE_CR_STAT_TXLERR)
                    754:                        printf("Late ");
                    755:                if (why & BE_CR_STAT_TXPERR)
                    756:                        printf("Parity ");
                    757:                if (why & BE_CR_STAT_TXSERR)
                    758:                        printf("Generic ");
                    759:                printf(")\n");
                    760:        }
                    761:
                    762:        if (why & BE_CR_STAT_RXDROP) {
                    763:                r |= 1;
                    764:                rst = 1;
                    765:                printf("%s: out of rx descriptors\n", sc->sc_dev.dv_xname);
                    766:        }
                    767:
                    768:        if (why & BE_CR_STAT_RXSMALL) {
                    769:                r |= 1;
                    770:                rst = 1;
                    771:                printf("%s: rx descriptor too small\n", sc->sc_dev.dv_xname);
                    772:        }
                    773:
                    774:        if (why & (BE_CR_STAT_RXLERR | BE_CR_STAT_RXPERR | BE_CR_STAT_RXSERR)) {
                    775:                r |= 1;
                    776:                rst = 1;
                    777:                printf("%s: rx dma error ( ", sc->sc_dev.dv_xname);
                    778:                if (why & BE_CR_STAT_RXLERR)
                    779:                        printf("Late ");
                    780:                if (why & BE_CR_STAT_RXPERR)
                    781:                        printf("Parity ");
                    782:                if (why & BE_CR_STAT_RXSERR)
                    783:                        printf("Generic ");
                    784:                printf(")\n");
                    785:        }
                    786:
                    787:        if (!r) {
                    788:                rst = 1;
                    789:                printf("%s: unexpected error interrupt %08x\n",
                    790:                        sc->sc_dev.dv_xname, why);
                    791:        }
                    792:
                    793:        if (rst) {
                    794:                printf("%s: resetting\n", sc->sc_dev.dv_xname);
                    795:                bereset(sc);
                    796:        }
                    797:
                    798:        return (r);
                    799: }
                    800:
                    801: /*
                    802:  * Error interrupt.
                    803:  */
                    804: int
                    805: beeint(struct be_softc *sc, u_int32_t why)
                    806: {
                    807:        int r = 0, rst = 0;
                    808:
                    809:        if (why & BE_BR_STAT_RFIFOVF) {
                    810:                r |= 1;
                    811:                rst = 1;
                    812:                printf("%s: receive fifo overrun\n", sc->sc_dev.dv_xname);
                    813:        }
                    814:        if (why & BE_BR_STAT_TFIFO_UND) {
                    815:                r |= 1;
                    816:                rst = 1;
                    817:                printf("%s: transmit fifo underrun\n", sc->sc_dev.dv_xname);
                    818:        }
                    819:        if (why & BE_BR_STAT_MAXPKTERR) {
                    820:                r |= 1;
                    821:                rst = 1;
                    822:                printf("%s: max packet size error\n", sc->sc_dev.dv_xname);
                    823:        }
                    824:
                    825:        if (!r) {
                    826:                rst = 1;
                    827:                printf("%s: unexpected error interrupt %08x\n",
                    828:                        sc->sc_dev.dv_xname, why);
                    829:        }
                    830:
                    831:        if (rst) {
                    832:                printf("%s: resetting\n", sc->sc_dev.dv_xname);
                    833:                bereset(sc);
                    834:        }
                    835:
                    836:        return (r);
                    837: }
                    838:
                    839: /*
                    840:  * Transmit interrupt.
                    841:  */
                    842: int
                    843: betint(struct be_softc *sc)
                    844: {
                    845:        struct ifnet *ifp = &sc->sc_arpcom.ac_if;
                    846:        bus_space_tag_t t = sc->sc_bustag;
                    847:        bus_space_handle_t br = sc->sc_br;
                    848:        unsigned int bix, txflags;
                    849:
                    850:        /*
                    851:         * Unload collision counters
                    852:         */
                    853:        ifp->if_collisions +=
                    854:                bus_space_read_4(t, br, BE_BRI_NCCNT) +
                    855:                bus_space_read_4(t, br, BE_BRI_FCCNT) +
                    856:                bus_space_read_4(t, br, BE_BRI_EXCNT) +
                    857:                bus_space_read_4(t, br, BE_BRI_LTCNT);
                    858:
                    859:        /*
                    860:         * the clear the hardware counters
                    861:         */
                    862:        bus_space_write_4(t, br, BE_BRI_NCCNT, 0);
                    863:        bus_space_write_4(t, br, BE_BRI_FCCNT, 0);
                    864:        bus_space_write_4(t, br, BE_BRI_EXCNT, 0);
                    865:        bus_space_write_4(t, br, BE_BRI_LTCNT, 0);
                    866:
                    867:        bix = sc->sc_rb.rb_tdtail;
                    868:
                    869:        for (;;) {
                    870:                if (sc->sc_rb.rb_td_nbusy <= 0)
                    871:                        break;
                    872:
                    873:                txflags = sc->sc_rb.rb_txd[bix].xd_flags;
                    874:
                    875:                if (txflags & QEC_XD_OWN)
                    876:                        break;
                    877:
                    878:                ifp->if_flags &= ~IFF_OACTIVE;
                    879:                ifp->if_opackets++;
                    880:
                    881:                if (++bix == QEC_XD_RING_MAXSIZE)
                    882:                        bix = 0;
                    883:
                    884:                --sc->sc_rb.rb_td_nbusy;
                    885:        }
                    886:
                    887:        sc->sc_rb.rb_tdtail = bix;
                    888:
                    889:        bestart(ifp);
                    890:
                    891:        if (sc->sc_rb.rb_td_nbusy == 0)
                    892:                ifp->if_timer = 0;
                    893:
                    894:        return (1);
                    895: }
                    896:
                    897: /*
                    898:  * Receive interrupt.
                    899:  */
                    900: int
                    901: berint(struct be_softc *sc)
                    902: {
                    903:        struct qec_xd *xd = sc->sc_rb.rb_rxd;
                    904:        unsigned int bix, len;
                    905:        unsigned int nrbuf = sc->sc_rb.rb_nrbuf;
                    906:
                    907:        bix = sc->sc_rb.rb_rdtail;
                    908:
                    909:        /*
                    910:         * Process all buffers with valid data.
                    911:         */
                    912:        for (;;) {
                    913:                len = xd[bix].xd_flags;
                    914:                if (len & QEC_XD_OWN)
                    915:                        break;
                    916:
                    917:                len &= QEC_XD_LENGTH;
                    918:                be_read(sc, bix, len);
                    919:
                    920:                /* ... */
                    921:                xd[(bix+nrbuf) % QEC_XD_RING_MAXSIZE].xd_flags =
                    922:                        QEC_XD_OWN | (BE_PKT_BUF_SZ & QEC_XD_LENGTH);
                    923:
                    924:                if (++bix == QEC_XD_RING_MAXSIZE)
                    925:                        bix = 0;
                    926:        }
                    927:
                    928:        sc->sc_rb.rb_rdtail = bix;
                    929:
                    930:        return (1);
                    931: }
                    932:
                    933: int
                    934: beioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
                    935: {
                    936:        struct be_softc *sc = ifp->if_softc;
                    937:        struct ifaddr *ifa = (struct ifaddr *)data;
                    938:        struct ifreq *ifr = (struct ifreq *)data;
                    939:        int s, error = 0;
                    940:
                    941:        s = splnet();
                    942:
                    943:        if ((error = ether_ioctl(ifp, &sc->sc_arpcom, cmd, data)) > 0) {
                    944:                splx(s);
                    945:                return (error);
                    946:        }
                    947:
                    948:        switch (cmd) {
                    949:        case SIOCSIFADDR:
                    950:                ifp->if_flags |= IFF_UP;
                    951:                switch (ifa->ifa_addr->sa_family) {
                    952: #ifdef INET
                    953:                case AF_INET:
                    954:                        beinit(sc);
                    955:                        arp_ifinit(&sc->sc_arpcom, ifa);
                    956:                        break;
                    957: #endif /* INET */
                    958:                default:
                    959:                        beinit(sc);
                    960:                        break;
                    961:                }
                    962:                break;
                    963:
                    964:        case SIOCSIFFLAGS:
                    965:                if ((ifp->if_flags & IFF_UP) == 0 &&
                    966:                    (ifp->if_flags & IFF_RUNNING) != 0) {
                    967:                        /*
                    968:                         * If interface is marked down and it is running, then
                    969:                         * stop it.
                    970:                         */
                    971:                        bestop(sc);
                    972:                        ifp->if_flags &= ~IFF_RUNNING;
                    973:                } else if ((ifp->if_flags & IFF_UP) != 0 &&
                    974:                    (ifp->if_flags & IFF_RUNNING) == 0) {
                    975:                        /*
                    976:                         * If interface is marked up and it is stopped, then
                    977:                         * start it.
                    978:                         */
                    979:                        beinit(sc);
                    980:                } else {
                    981:                        /*
                    982:                         * Reset the interface to pick up changes in any other
                    983:                         * flags that affect hardware registers.
                    984:                         */
                    985:                        bestop(sc);
                    986:                        beinit(sc);
                    987:                }
                    988: #ifdef BEDEBUG
                    989:                if (ifp->if_flags & IFF_DEBUG)
                    990:                        sc->sc_debug = 1;
                    991:                else
                    992:                        sc->sc_debug = 0;
                    993: #endif
                    994:                break;
                    995:
                    996:        case SIOCADDMULTI:
                    997:        case SIOCDELMULTI:
                    998:                error = (cmd == SIOCADDMULTI) ?
                    999:                    ether_addmulti(ifr, &sc->sc_arpcom):
                   1000:                    ether_delmulti(ifr, &sc->sc_arpcom);
                   1001:
                   1002:                if (error == ENETRESET) {
                   1003:                        /*
                   1004:                         * Multicast list has changed; set the hardware filter
                   1005:                         * accordingly.
                   1006:                         */
                   1007:                        if (ifp->if_flags & IFF_RUNNING)
                   1008:                                be_mcreset(sc);
                   1009:                        error = 0;
                   1010:                }
                   1011:                break;
                   1012:        case SIOCGIFMEDIA:
                   1013:        case SIOCSIFMEDIA:
                   1014:                error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd);
                   1015:                break;
                   1016:        default:
                   1017:                error = EINVAL;
                   1018:                break;
                   1019:        }
                   1020:        splx(s);
                   1021:        return (error);
                   1022: }
                   1023:
                   1024:
                   1025: void
                   1026: beinit(struct be_softc *sc)
                   1027: {
                   1028:        struct ifnet *ifp = &sc->sc_arpcom.ac_if;
                   1029:        bus_space_tag_t t = sc->sc_bustag;
                   1030:        bus_space_handle_t br = sc->sc_br;
                   1031:        bus_space_handle_t cr = sc->sc_cr;
                   1032:        struct qec_softc *qec = sc->sc_qec;
                   1033:        u_int32_t v;
                   1034:        u_int32_t qecaddr;
                   1035:        u_int8_t *ea;
                   1036:        int s;
                   1037:
                   1038:        s = splnet();
                   1039:
                   1040:        qec_meminit(&sc->sc_rb, BE_PKT_BUF_SZ);
                   1041:
                   1042:        bestop(sc);
                   1043:
                   1044:        ea = sc->sc_arpcom.ac_enaddr;
                   1045:        bus_space_write_4(t, br, BE_BRI_MACADDR0, (ea[0] << 8) | ea[1]);
                   1046:        bus_space_write_4(t, br, BE_BRI_MACADDR1, (ea[2] << 8) | ea[3]);
                   1047:        bus_space_write_4(t, br, BE_BRI_MACADDR2, (ea[4] << 8) | ea[5]);
                   1048:
                   1049:        /* Clear hash table */
                   1050:        bus_space_write_4(t, br, BE_BRI_HASHTAB0, 0);
                   1051:        bus_space_write_4(t, br, BE_BRI_HASHTAB1, 0);
                   1052:        bus_space_write_4(t, br, BE_BRI_HASHTAB2, 0);
                   1053:        bus_space_write_4(t, br, BE_BRI_HASHTAB3, 0);
                   1054:
                   1055:        /* Re-initialize RX configuration */
                   1056:        v = BE_BR_RXCFG_FIFO;
                   1057:        bus_space_write_4(t, br, BE_BRI_RXCFG, v);
                   1058:
                   1059:        be_mcreset(sc);
                   1060:
                   1061:        bus_space_write_4(t, br, BE_BRI_RANDSEED, 0xbd);
                   1062:
                   1063:        bus_space_write_4(t, br, BE_BRI_XIFCFG,
                   1064:                          BE_BR_XCFG_ODENABLE | BE_BR_XCFG_RESV);
                   1065:
                   1066:        bus_space_write_4(t, br, BE_BRI_JSIZE, 4);
                   1067:
                   1068:        /*
                   1069:         * Turn off counter expiration interrupts as well as
                   1070:         * 'gotframe' and 'sentframe'
                   1071:         */
                   1072:        bus_space_write_4(t, br, BE_BRI_IMASK,
                   1073:                          BE_BR_IMASK_GOTFRAME  |
                   1074:                          BE_BR_IMASK_RCNTEXP   |
                   1075:                          BE_BR_IMASK_ACNTEXP   |
                   1076:                          BE_BR_IMASK_CCNTEXP   |
                   1077:                          BE_BR_IMASK_LCNTEXP   |
                   1078:                          BE_BR_IMASK_CVCNTEXP  |
                   1079:                          BE_BR_IMASK_SENTFRAME |
                   1080:                          BE_BR_IMASK_NCNTEXP   |
                   1081:                          BE_BR_IMASK_ECNTEXP   |
                   1082:                          BE_BR_IMASK_LCCNTEXP  |
                   1083:                          BE_BR_IMASK_FCNTEXP   |
                   1084:                          BE_BR_IMASK_DTIMEXP);
                   1085:
                   1086:        /* Channel registers: */
                   1087:        bus_space_write_4(t, cr, BE_CRI_RXDS, (u_int32_t)sc->sc_rb.rb_rxddma);
                   1088:        bus_space_write_4(t, cr, BE_CRI_TXDS, (u_int32_t)sc->sc_rb.rb_txddma);
                   1089:
                   1090:        qecaddr = sc->sc_channel * qec->sc_msize;
                   1091:        bus_space_write_4(t, cr, BE_CRI_RXWBUF, qecaddr);
                   1092:        bus_space_write_4(t, cr, BE_CRI_RXRBUF, qecaddr);
                   1093:        bus_space_write_4(t, cr, BE_CRI_TXWBUF, qecaddr + qec->sc_rsize);
                   1094:        bus_space_write_4(t, cr, BE_CRI_TXRBUF, qecaddr + qec->sc_rsize);
                   1095:
                   1096:        bus_space_write_4(t, cr, BE_CRI_RIMASK, 0);
                   1097:        bus_space_write_4(t, cr, BE_CRI_TIMASK, 0);
                   1098:        bus_space_write_4(t, cr, BE_CRI_QMASK, 0);
                   1099:        bus_space_write_4(t, cr, BE_CRI_BMASK, 0);
                   1100:        bus_space_write_4(t, cr, BE_CRI_CCNT, 0);
                   1101:
                   1102:        /* Enable transmitter */
                   1103:        bus_space_write_4(t, br, BE_BRI_TXCFG,
                   1104:                          BE_BR_TXCFG_FIFO | BE_BR_TXCFG_ENABLE);
                   1105:
                   1106:        /* Enable receiver */
                   1107:        v = bus_space_read_4(t, br, BE_BRI_RXCFG);
                   1108:        v |= BE_BR_RXCFG_FIFO | BE_BR_RXCFG_ENABLE;
                   1109:        bus_space_write_4(t, br, BE_BRI_RXCFG, v);
                   1110:
                   1111:        ifp->if_flags |= IFF_RUNNING;
                   1112:        ifp->if_flags &= ~IFF_OACTIVE;
                   1113:
                   1114:        be_ifmedia_upd(ifp);
                   1115:        timeout_add(&sc->sc_tick_ch, hz);
                   1116:        splx(s);
                   1117: }
                   1118:
                   1119: void
                   1120: be_mcreset(struct be_softc *sc)
                   1121: {
                   1122:        struct arpcom *ac = &sc->sc_arpcom;
                   1123:        struct ifnet *ifp = &sc->sc_arpcom.ac_if;
                   1124:        bus_space_tag_t t = sc->sc_bustag;
                   1125:        bus_space_handle_t br = sc->sc_br;
                   1126:        u_int32_t crc;
                   1127:        u_int16_t hash[4];
                   1128:        u_int8_t octet;
                   1129:        u_int32_t v;
                   1130:        int i, j;
                   1131:        struct ether_multi *enm;
                   1132:        struct ether_multistep step;
                   1133:
                   1134:        if (ifp->if_flags & IFF_PROMISC) {
                   1135:                v = bus_space_read_4(t, br, BE_BRI_RXCFG);
                   1136:                v |= BE_BR_RXCFG_PMISC;
                   1137:                bus_space_write_4(t, br, BE_BRI_RXCFG, v);
                   1138:                return;
                   1139:        }
                   1140:
                   1141:        if (ifp->if_flags & IFF_ALLMULTI) {
                   1142:                hash[3] = hash[2] = hash[1] = hash[0] = 0xffff;
                   1143:                goto chipit;
                   1144:        }
                   1145:
                   1146:        hash[3] = hash[2] = hash[1] = hash[0] = 0;
                   1147:
                   1148:        ETHER_FIRST_MULTI(step, ac, enm);
                   1149:        while (enm != NULL) {
                   1150:                if (bcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) {
                   1151:                        /*
                   1152:                         * We must listen to a range of multicast
                   1153:                         * addresses.  For now, just accept all
                   1154:                         * multicasts, rather than trying to set only
                   1155:                         * those filter bits needed to match the range.
                   1156:                         * (At this time, the only use of address
                   1157:                         * ranges is for IP multicast routing, for
                   1158:                         * which the range is big enough to require
                   1159:                         * all bits set.)
                   1160:                         */
                   1161:                        hash[3] = hash[2] = hash[1] = hash[0] = 0xffff;
                   1162:                        ifp->if_flags |= IFF_ALLMULTI;
                   1163:                        goto chipit;
                   1164:                }
                   1165:
                   1166:                crc = 0xffffffff;
                   1167:
                   1168:                for (i = 0; i < ETHER_ADDR_LEN; i++) {
                   1169:                        octet = enm->enm_addrlo[i];
                   1170:
                   1171:                        for (j = 0; j < 8; j++) {
                   1172:                                if ((crc & 1) ^ (octet & 1)) {
                   1173:                                        crc >>= 1;
                   1174:                                        crc ^= MC_POLY_LE;
                   1175:                                }
                   1176:                                else
                   1177:                                        crc >>= 1;
                   1178:                                octet >>= 1;
                   1179:                        }
                   1180:                }
                   1181:
                   1182:                crc >>= 26;
                   1183:                hash[crc >> 4] |= 1 << (crc & 0xf);
                   1184:                ETHER_NEXT_MULTI(step, enm);
                   1185:        }
                   1186:
                   1187:        ifp->if_flags &= ~IFF_ALLMULTI;
                   1188:
                   1189: chipit:
                   1190:        /* Enable the hash filter */
                   1191:        bus_space_write_4(t, br, BE_BRI_HASHTAB0, hash[0]);
                   1192:        bus_space_write_4(t, br, BE_BRI_HASHTAB1, hash[1]);
                   1193:        bus_space_write_4(t, br, BE_BRI_HASHTAB2, hash[2]);
                   1194:        bus_space_write_4(t, br, BE_BRI_HASHTAB3, hash[3]);
                   1195:
                   1196:        v = bus_space_read_4(t, br, BE_BRI_RXCFG);
                   1197:        v &= ~BE_BR_RXCFG_PMISC;
                   1198:        v |= BE_BR_RXCFG_HENABLE;
                   1199:        bus_space_write_4(t, br, BE_BRI_RXCFG, v);
                   1200: }
                   1201:
                   1202: /*
                   1203:  * Set the tcvr to an idle state
                   1204:  */
                   1205: void
                   1206: be_mii_sync(struct be_softc *sc)
                   1207: {
                   1208:        bus_space_tag_t t = sc->sc_bustag;
                   1209:        bus_space_handle_t tr = sc->sc_tr;
                   1210:        int n = 32;
                   1211:
                   1212:        while (n--) {
                   1213:                bus_space_write_4(t, tr, BE_TRI_MGMTPAL,
                   1214:                    MGMT_PAL_INT_MDIO | MGMT_PAL_EXT_MDIO | MGMT_PAL_OENAB);
                   1215:                (void)bus_space_read_4(t, tr, BE_TRI_MGMTPAL);
                   1216:                bus_space_write_4(t, tr, BE_TRI_MGMTPAL,
                   1217:                    MGMT_PAL_INT_MDIO | MGMT_PAL_EXT_MDIO |
                   1218:                    MGMT_PAL_OENAB | MGMT_PAL_DCLOCK);
                   1219:                (void)bus_space_read_4(t, tr, BE_TRI_MGMTPAL);
                   1220:        }
                   1221: }
                   1222:
                   1223: void
                   1224: be_pal_gate(struct be_softc *sc, int phy)
                   1225: {
                   1226:        bus_space_tag_t t = sc->sc_bustag;
                   1227:        bus_space_handle_t tr = sc->sc_tr;
                   1228:        u_int32_t v;
                   1229:
                   1230:        be_mii_sync(sc);
                   1231:
                   1232:        v = ~(TCVR_PAL_EXTLBACK | TCVR_PAL_MSENSE | TCVR_PAL_LTENABLE);
                   1233:        if (phy == BE_PHY_INTERNAL)
                   1234:                v &= ~TCVR_PAL_SERIAL;
                   1235:
                   1236:        bus_space_write_4(t, tr, BE_TRI_TCVRPAL, v);
                   1237:        (void)bus_space_read_4(t, tr, BE_TRI_TCVRPAL);
                   1238: }
                   1239:
                   1240: static int
                   1241: be_tcvr_read_bit(struct be_softc *sc, int phy)
                   1242: {
                   1243:        bus_space_tag_t t = sc->sc_bustag;
                   1244:        bus_space_handle_t tr = sc->sc_tr;
                   1245:        int ret;
                   1246:
                   1247:        if (phy == BE_PHY_INTERNAL) {
                   1248:                bus_space_write_4(t, tr, BE_TRI_MGMTPAL, MGMT_PAL_EXT_MDIO);
                   1249:                (void)bus_space_read_4(t, tr, BE_TRI_MGMTPAL);
                   1250:                bus_space_write_4(t, tr, BE_TRI_MGMTPAL,
                   1251:                    MGMT_PAL_EXT_MDIO | MGMT_PAL_DCLOCK);
                   1252:                (void)bus_space_read_4(t, tr, BE_TRI_MGMTPAL);
                   1253:                ret = (bus_space_read_4(t, tr, BE_TRI_MGMTPAL) &
                   1254:                        MGMT_PAL_INT_MDIO) >> MGMT_PAL_INT_MDIO_SHIFT;
                   1255:        } else {
                   1256:                bus_space_write_4(t, tr, BE_TRI_MGMTPAL, MGMT_PAL_INT_MDIO);
                   1257:                (void)bus_space_read_4(t, tr, BE_TRI_MGMTPAL);
                   1258:                ret = (bus_space_read_4(t, tr, BE_TRI_MGMTPAL) &
                   1259:                    MGMT_PAL_EXT_MDIO) >> MGMT_PAL_EXT_MDIO_SHIFT;
                   1260:                bus_space_write_4(t, tr, BE_TRI_MGMTPAL,
                   1261:                    MGMT_PAL_INT_MDIO | MGMT_PAL_DCLOCK);
                   1262:                (void)bus_space_read_4(t, tr, BE_TRI_MGMTPAL);
                   1263:        }
                   1264:
                   1265:        return (ret);
                   1266: }
                   1267:
                   1268: static void
                   1269: be_tcvr_write_bit(struct be_softc *sc, int phy, int bit)
                   1270: {
                   1271:        bus_space_tag_t t = sc->sc_bustag;
                   1272:        bus_space_handle_t tr = sc->sc_tr;
                   1273:        u_int32_t v;
                   1274:
                   1275:        if (phy == BE_PHY_INTERNAL) {
                   1276:                v = ((bit & 1) << MGMT_PAL_INT_MDIO_SHIFT) |
                   1277:                    MGMT_PAL_OENAB | MGMT_PAL_EXT_MDIO;
                   1278:        } else {
                   1279:                v = ((bit & 1) << MGMT_PAL_EXT_MDIO_SHIFT)
                   1280:                    | MGMT_PAL_OENAB | MGMT_PAL_INT_MDIO;
                   1281:        }
                   1282:        bus_space_write_4(t, tr, BE_TRI_MGMTPAL, v);
                   1283:        (void)bus_space_read_4(t, tr, BE_TRI_MGMTPAL);
                   1284:        bus_space_write_4(t, tr, BE_TRI_MGMTPAL, v | MGMT_PAL_DCLOCK);
                   1285:        (void)bus_space_read_4(t, tr, BE_TRI_MGMTPAL);
                   1286: }
                   1287:
                   1288: static void
                   1289: be_mii_sendbits(struct be_softc *sc, int phy, u_int32_t data, int nbits)
                   1290: {
                   1291:        int i;
                   1292:
                   1293:        for (i = 1 << (nbits - 1); i != 0; i >>= 1)
                   1294:                be_tcvr_write_bit(sc, phy, (data & i) != 0);
                   1295: }
                   1296:
                   1297: static int
                   1298: be_mii_readreg(struct device *self, int phy, int reg)
                   1299: {
                   1300:        struct be_softc *sc = (struct be_softc *)self;
                   1301:        int val = 0, i;
                   1302:
                   1303:        /*
                   1304:         * Read the PHY register by manually driving the MII control lines.
                   1305:         */
                   1306:        be_mii_sync(sc);
                   1307:        be_mii_sendbits(sc, phy, MII_COMMAND_START, 2);
                   1308:        be_mii_sendbits(sc, phy, MII_COMMAND_READ, 2);
                   1309:        be_mii_sendbits(sc, phy, phy, 5);
                   1310:        be_mii_sendbits(sc, phy, reg, 5);
                   1311:
                   1312:        (void) be_tcvr_read_bit(sc, phy);
                   1313:        (void) be_tcvr_read_bit(sc, phy);
                   1314:
                   1315:        for (i = 15; i >= 0; i--)
                   1316:                val |= (be_tcvr_read_bit(sc, phy) << i);
                   1317:
                   1318:        (void) be_tcvr_read_bit(sc, phy);
                   1319:        (void) be_tcvr_read_bit(sc, phy);
                   1320:        (void) be_tcvr_read_bit(sc, phy);
                   1321:
                   1322:        return (val);
                   1323: }
                   1324:
                   1325: void
                   1326: be_mii_writereg(struct device *self, int phy, int reg, int val)
                   1327: {
                   1328:        struct be_softc *sc = (struct be_softc *)self;
                   1329:        int i;
                   1330:
                   1331:        /*
                   1332:         * Write the PHY register by manually driving the MII control lines.
                   1333:         */
                   1334:        be_mii_sync(sc);
                   1335:        be_mii_sendbits(sc, phy, MII_COMMAND_START, 2);
                   1336:        be_mii_sendbits(sc, phy, MII_COMMAND_WRITE, 2);
                   1337:        be_mii_sendbits(sc, phy, phy, 5);
                   1338:        be_mii_sendbits(sc, phy, reg, 5);
                   1339:
                   1340:        be_tcvr_write_bit(sc, phy, 1);
                   1341:        be_tcvr_write_bit(sc, phy, 0);
                   1342:
                   1343:        for (i = 15; i >= 0; i--)
                   1344:                be_tcvr_write_bit(sc, phy, (val >> i) & 1);
                   1345: }
                   1346:
                   1347: int
                   1348: be_mii_reset(struct be_softc *sc, int phy)
                   1349: {
                   1350:        int n;
                   1351:
                   1352:        be_mii_writereg((struct device *)sc, phy, MII_BMCR,
                   1353:            BMCR_LOOP | BMCR_PDOWN | BMCR_ISO);
                   1354:        be_mii_writereg((struct device *)sc, phy, MII_BMCR, BMCR_RESET);
                   1355:
                   1356:        for (n = 16; n >= 0; n--) {
                   1357:                int bmcr = be_mii_readreg((struct device *)sc, phy, MII_BMCR);
                   1358:                if ((bmcr & BMCR_RESET) == 0)
                   1359:                        break;
                   1360:                DELAY(20);
                   1361:        }
                   1362:        if (n == 0) {
                   1363:                printf("%s: bmcr reset failed\n", sc->sc_dev.dv_xname);
                   1364:                return (EIO);
                   1365:        }
                   1366:
                   1367:        return (0);
                   1368: }
                   1369:
                   1370: void
                   1371: be_tick(void *arg)
                   1372: {
                   1373:        struct be_softc *sc = arg;
                   1374:        int s = splnet();
                   1375:
                   1376:        mii_tick(&sc->sc_mii);
                   1377:        (void)be_intphy_service(sc, &sc->sc_mii, MII_TICK);
                   1378:
                   1379:        timeout_add(&sc->sc_tick_ch, hz);
                   1380:        splx(s);
                   1381: }
                   1382:
                   1383: void
                   1384: be_mii_statchg(struct device *self)
                   1385: {
                   1386:        struct be_softc *sc = (struct be_softc *)self;
                   1387:        bus_space_tag_t t = sc->sc_bustag;
                   1388:        bus_space_handle_t br = sc->sc_br;
                   1389:        u_int instance;
                   1390:        u_int32_t v;
                   1391:
                   1392:        instance = IFM_INST(sc->sc_mii.mii_media.ifm_cur->ifm_media);
                   1393: #ifdef DIAGNOSTIC
                   1394:        if (instance > 1)
                   1395:                panic("be_mii_statchg: instance %d out of range", instance);
                   1396: #endif
                   1397:
                   1398:        /* Update duplex mode in TX configuration */
                   1399:        v = bus_space_read_4(t, br, BE_BRI_TXCFG);
                   1400:        if ((IFM_OPTIONS(sc->sc_mii.mii_media_active) & IFM_FDX) != 0)
                   1401:                v |= BE_BR_TXCFG_FULLDPLX;
                   1402:        else
                   1403:                v &= ~BE_BR_TXCFG_FULLDPLX;
                   1404:        bus_space_write_4(t, br, BE_BRI_TXCFG, v);
                   1405:
                   1406:        /* Change to appropriate gate in transceiver PAL */
                   1407:        be_pal_gate(sc, sc->sc_phys[instance]);
                   1408: }
                   1409:
                   1410: /*
                   1411:  * Get current media settings.
                   1412:  */
                   1413: void
                   1414: be_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
                   1415: {
                   1416:        struct be_softc *sc = ifp->if_softc;
                   1417:
                   1418:        mii_pollstat(&sc->sc_mii);
                   1419:        (void)be_intphy_service(sc, &sc->sc_mii, MII_POLLSTAT);
                   1420:
                   1421:        ifmr->ifm_status = sc->sc_mii.mii_media_status;
                   1422:        ifmr->ifm_active = sc->sc_mii.mii_media_active;
                   1423:        return;
                   1424: }
                   1425:
                   1426: /*
                   1427:  * Set media options.
                   1428:  */
                   1429: int
                   1430: be_ifmedia_upd(struct ifnet *ifp)
                   1431: {
                   1432:        struct be_softc *sc = ifp->if_softc;
                   1433:        int error;
                   1434:
                   1435:        if ((error = mii_mediachg(&sc->sc_mii)) != 0)
                   1436:                return (error);
                   1437:
                   1438:        return (be_intphy_service(sc, &sc->sc_mii, MII_MEDIACHG));
                   1439: }
                   1440:
                   1441: /*
                   1442:  * Service routine for our pseudo-MII internal transceiver.
                   1443:  */
                   1444: int
                   1445: be_intphy_service(struct be_softc *sc, struct mii_data *mii, int cmd)
                   1446: {
                   1447:        struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
                   1448:        int bmcr, bmsr;
                   1449:        int error;
                   1450:
                   1451:        switch (cmd) {
                   1452:        case MII_POLLSTAT:
                   1453:                /*
                   1454:                 * If we're not polling our PHY instance, just return.
                   1455:                 */
                   1456:                if (IFM_INST(ife->ifm_media) != sc->sc_mii_inst)
                   1457:                        return (0);
                   1458:
                   1459:                break;
                   1460:
                   1461:        case MII_MEDIACHG:
                   1462:
                   1463:                /*
                   1464:                 * If the media indicates a different PHY instance,
                   1465:                 * isolate ourselves.
                   1466:                 */
                   1467:                if (IFM_INST(ife->ifm_media) != sc->sc_mii_inst) {
                   1468:                        bmcr = be_mii_readreg((void *)sc,
                   1469:                            BE_PHY_INTERNAL, MII_BMCR);
                   1470:                        be_mii_writereg((void *)sc,
                   1471:                            BE_PHY_INTERNAL, MII_BMCR, bmcr | BMCR_ISO);
                   1472:                        sc->sc_mii_flags &= ~MIIF_HAVELINK;
                   1473:                        sc->sc_intphy_curspeed = 0;
                   1474:                        return (0);
                   1475:                }
                   1476:
                   1477:
                   1478:                if ((error = be_mii_reset(sc, BE_PHY_INTERNAL)) != 0)
                   1479:                        return (error);
                   1480:
                   1481:                bmcr = be_mii_readreg((void *)sc, BE_PHY_INTERNAL, MII_BMCR);
                   1482:
                   1483:                /*
                   1484:                 * Select the new mode and take out of isolation
                   1485:                 */
                   1486:                if (IFM_SUBTYPE(ife->ifm_media) == IFM_100_TX)
                   1487:                        bmcr |= BMCR_S100;
                   1488:                else if (IFM_SUBTYPE(ife->ifm_media) == IFM_10_T)
                   1489:                        bmcr &= ~BMCR_S100;
                   1490:                else if (IFM_SUBTYPE(ife->ifm_media) == IFM_AUTO) {
                   1491:                        if ((sc->sc_mii_flags & MIIF_HAVELINK) != 0) {
                   1492:                                bmcr &= ~BMCR_S100;
                   1493:                                bmcr |= sc->sc_intphy_curspeed;
                   1494:                        } else {
                   1495:                                /* Keep isolated until link is up */
                   1496:                                bmcr |= BMCR_ISO;
                   1497:                                sc->sc_mii_flags |= MIIF_DOINGAUTO;
                   1498:                        }
                   1499:                }
                   1500:
                   1501:                if ((IFM_OPTIONS(ife->ifm_media) & IFM_FDX) != 0)
                   1502:                        bmcr |= BMCR_FDX;
                   1503:                else
                   1504:                        bmcr &= ~BMCR_FDX;
                   1505:
                   1506:                be_mii_writereg((void *)sc, BE_PHY_INTERNAL, MII_BMCR, bmcr);
                   1507:                break;
                   1508:
                   1509:        case MII_TICK:
                   1510:                /*
                   1511:                 * If we're not currently selected, just return.
                   1512:                 */
                   1513:                if (IFM_INST(ife->ifm_media) != sc->sc_mii_inst)
                   1514:                        return (0);
                   1515:
                   1516:                /* Only used for automatic media selection */
                   1517:                if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO)
                   1518:                        return (0);
                   1519:
                   1520:                /* Is the interface even up? */
                   1521:                if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
                   1522:                        return (0);
                   1523:
                   1524:                /*
                   1525:                 * Check link status; if we don't have a link, try another
                   1526:                 * speed. We can't detect duplex mode, so half-duplex is
                   1527:                 * what we have to settle for.
                   1528:                 */
                   1529:
                   1530:                /* Read twice in case the register is latched */
                   1531:                bmsr = be_mii_readreg((void *)sc, BE_PHY_INTERNAL, MII_BMSR) |
                   1532:                    be_mii_readreg((void *)sc, BE_PHY_INTERNAL, MII_BMSR);
                   1533:
                   1534:                if ((bmsr & BMSR_LINK) != 0) {
                   1535:                        /* We have a carrier */
                   1536:                        bmcr = be_mii_readreg((void *)sc,
                   1537:                            BE_PHY_INTERNAL, MII_BMCR);
                   1538:
                   1539:                        if ((sc->sc_mii_flags & MIIF_DOINGAUTO) != 0) {
                   1540:                                bmcr = be_mii_readreg((void *)sc,
                   1541:                                    BE_PHY_INTERNAL, MII_BMCR);
                   1542:
                   1543:                                sc->sc_mii_flags |= MIIF_HAVELINK;
                   1544:                                sc->sc_intphy_curspeed = (bmcr & BMCR_S100);
                   1545:                                sc->sc_mii_flags &= ~MIIF_DOINGAUTO;
                   1546:
                   1547:                                bmcr &= ~BMCR_ISO;
                   1548:                                be_mii_writereg((void *)sc,
                   1549:                                    BE_PHY_INTERNAL, MII_BMCR, bmcr);
                   1550:
                   1551:                                printf("%s: link up at %s Mbps\n",
                   1552:                                    sc->sc_dev.dv_xname,
                   1553:                                    (bmcr & BMCR_S100) ? "100" : "10");
                   1554:                        }
                   1555:                        return (0);
                   1556:                }
                   1557:
                   1558:                if ((sc->sc_mii_flags & MIIF_DOINGAUTO) == 0) {
                   1559:                        sc->sc_mii_flags |= MIIF_DOINGAUTO;
                   1560:                        sc->sc_mii_flags &= ~MIIF_HAVELINK;
                   1561:                        sc->sc_intphy_curspeed = 0;
                   1562:                        printf("%s: link down\n", sc->sc_dev.dv_xname);
                   1563:                }
                   1564:
                   1565:                /* Only retry autonegotiation every 5 seconds. */
                   1566:                if (++sc->sc_mii_ticks < 5)
                   1567:                        return(0);
                   1568:
                   1569:                sc->sc_mii_ticks = 0;
                   1570:                bmcr = be_mii_readreg((void *)sc, BE_PHY_INTERNAL, MII_BMCR);
                   1571:                /* Just flip the fast speed bit */
                   1572:                bmcr ^= BMCR_S100;
                   1573:                be_mii_writereg((void *)sc, BE_PHY_INTERNAL, MII_BMCR, bmcr);
                   1574:
                   1575:                break;
                   1576:
                   1577:        case MII_DOWN:
                   1578:                /* Isolate this phy */
                   1579:                bmcr = be_mii_readreg((void *)sc, BE_PHY_INTERNAL, MII_BMCR);
                   1580:                be_mii_writereg((void *)sc,
                   1581:                    BE_PHY_INTERNAL, MII_BMCR, bmcr | BMCR_ISO);
                   1582:                return (0);
                   1583:        }
                   1584:
                   1585:        /* Update the media status. */
                   1586:        be_intphy_status(sc);
                   1587:
                   1588:        /* Callback if something changed. */
                   1589:        if (sc->sc_mii_active != mii->mii_media_active || cmd == MII_MEDIACHG) {
                   1590:                (*mii->mii_statchg)((struct device *)sc);
                   1591:                sc->sc_mii_active = mii->mii_media_active;
                   1592:        }
                   1593:        return (0);
                   1594: }
                   1595:
                   1596: /*
                   1597:  * Determine status of internal transceiver
                   1598:  */
                   1599: void
                   1600: be_intphy_status(struct be_softc *sc)
                   1601: {
                   1602:        struct mii_data *mii = &sc->sc_mii;
                   1603:        int media_active, media_status;
                   1604:        int bmcr, bmsr;
                   1605:
                   1606:        media_status = IFM_AVALID;
                   1607:        media_active = 0;
                   1608:
                   1609:        /*
                   1610:         * Internal transceiver; do the work here.
                   1611:         */
                   1612:        bmcr = be_mii_readreg((struct device *)sc, BE_PHY_INTERNAL, MII_BMCR);
                   1613:
                   1614:        switch (bmcr & (BMCR_S100 | BMCR_FDX)) {
                   1615:        case (BMCR_S100 | BMCR_FDX):
                   1616:                media_active = IFM_ETHER | IFM_100_TX | IFM_FDX;
                   1617:                break;
                   1618:        case BMCR_S100:
                   1619:                media_active = IFM_ETHER | IFM_100_TX | IFM_HDX;
                   1620:                break;
                   1621:        case BMCR_FDX:
                   1622:                media_active = IFM_ETHER | IFM_10_T | IFM_FDX;
                   1623:                break;
                   1624:        case 0:
                   1625:                media_active = IFM_ETHER | IFM_10_T | IFM_HDX;
                   1626:                break;
                   1627:        }
                   1628:
                   1629:        /* Read twice in case the register is latched */
                   1630:        bmsr = be_mii_readreg((struct device *)sc, BE_PHY_INTERNAL, MII_BMSR)|
                   1631:               be_mii_readreg((struct device *)sc, BE_PHY_INTERNAL, MII_BMSR);
                   1632:        if (bmsr & BMSR_LINK)
                   1633:                media_status |=  IFM_ACTIVE;
                   1634:
                   1635:        mii->mii_media_status = media_status;
                   1636:        mii->mii_media_active = media_active;
                   1637: }

CVSweb