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

Annotation of sys/dev/pci/if_bce.c, Revision 1.1.1.1

1.1       nbrk        1: /* $OpenBSD: if_bce.c,v 1.20 2007/05/21 10:30:10 reyk Exp $ */
                      2: /* $NetBSD: if_bce.c,v 1.3 2003/09/29 01:53:02 mrg Exp $        */
                      3:
                      4: /*
                      5:  * Copyright (c) 2003 Clifford Wright. All rights reserved.
                      6:  *
                      7:  * Redistribution and use in source and binary forms, with or without
                      8:  * modification, are permitted provided that the following conditions
                      9:  * are met:
                     10:  * 1. Redistributions of source code must retain the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer.
                     12:  * 2. Redistributions in binary form must reproduce the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer in the
                     14:  *    documentation and/or other materials provided with the distribution.
                     15:  * 3. The name of the author may not be used to endorse or promote products
                     16:  *    derived from this software without specific prior written permission.
                     17:  *
                     18:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     19:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     20:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     21:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     22:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
                     23:  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
                     24:  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
                     25:  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
                     26:  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     27:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     28:  * SUCH DAMAGE.
                     29:  */
                     30:
                     31: /*
                     32:  * Broadcom BCM440x 10/100 ethernet (broadcom.com)
                     33:  * SiliconBackplane is technology from Sonics, Inc.(sonicsinc.com)
                     34:  *
                     35:  * Cliff Wright cliff@snipe444.org
                     36:  */
                     37:
                     38: #include "bpfilter.h"
                     39:
                     40: #include <sys/param.h>
                     41: #include <sys/systm.h>
                     42: #include <sys/timeout.h>
                     43: #include <sys/sockio.h>
                     44: #include <sys/mbuf.h>
                     45: #include <sys/malloc.h>
                     46: #include <sys/kernel.h>
                     47: #include <sys/device.h>
                     48: #include <sys/socket.h>
                     49:
                     50: #include <net/if.h>
                     51: #include <net/if_dl.h>
                     52: #include <net/if_media.h>
                     53:
                     54: #ifdef INET
                     55: #include <netinet/in.h>
                     56: #include <netinet/in_systm.h>
                     57: #include <netinet/in_var.h>
                     58: #include <netinet/ip.h>
                     59: #include <netinet/if_ether.h>
                     60: #endif
                     61: #if NBPFILTER > 0
                     62: #include <net/bpf.h>
                     63: #endif
                     64:
                     65: #include <dev/pci/pcireg.h>
                     66: #include <dev/pci/pcivar.h>
                     67: #include <dev/pci/pcidevs.h>
                     68:
                     69: #include <dev/mii/mii.h>
                     70: #include <dev/mii/miivar.h>
                     71: #include <dev/mii/miidevs.h>
                     72: #include <dev/mii/brgphyreg.h>
                     73:
                     74: #include <dev/pci/if_bcereg.h>
                     75:
                     76: #include <uvm/uvm_extern.h>
                     77:
                     78: /* transmit buffer max frags allowed */
                     79: #define BCE_NTXFRAGS   16
                     80:
                     81: /* ring descriptor */
                     82: struct bce_dma_slot {
                     83:        u_int32_t ctrl;
                     84:        u_int32_t addr;
                     85: };
                     86: #define CTRL_BC_MASK   0x1fff  /* buffer byte count */
                     87: #define CTRL_EOT       0x10000000      /* end of descriptor table */
                     88: #define CTRL_IOC       0x20000000      /* interrupt on completion */
                     89: #define CTRL_EOF       0x40000000      /* end of frame */
                     90: #define CTRL_SOF       0x80000000      /* start of frame */
                     91:
                     92: /* Packet status is returned in a pre-packet header */
                     93: struct rx_pph {
                     94:        u_int16_t len;
                     95:        u_int16_t flags;
                     96:        u_int16_t pad[12];
                     97: };
                     98:
                     99: #define        BCE_PREPKT_HEADER_SIZE          30
                    100:
                    101: /* packet status flags bits */
                    102: #define RXF_NO                         0x8     /* odd number of nibbles */
                    103: #define RXF_RXER                       0x4     /* receive symbol error */
                    104: #define RXF_CRC                                0x2     /* crc error */
                    105: #define RXF_OV                         0x1     /* fifo overflow */
                    106:
                    107: /* number of descriptors used in a ring */
                    108: #define BCE_NRXDESC            128
                    109: #define BCE_NTXDESC            128
                    110:
                    111: /*
                    112:  * Mbuf pointers. We need these to keep track of the virtual addresses
                    113:  * of our mbuf chains since we can only convert from physical to virtual,
                    114:  * not the other way around.
                    115:  */
                    116: struct bce_chain_data {
                    117:        struct mbuf    *bce_tx_chain[BCE_NTXDESC];
                    118:        struct mbuf    *bce_rx_chain[BCE_NRXDESC];
                    119:        bus_dmamap_t    bce_tx_map[BCE_NTXDESC];
                    120:        bus_dmamap_t    bce_rx_map[BCE_NRXDESC];
                    121: };
                    122:
                    123: #define BCE_TIMEOUT            100     /* # 10us for mii read/write */
                    124:
                    125: struct bce_softc {
                    126:        struct device           bce_dev;
                    127:        bus_space_tag_t         bce_btag;
                    128:        bus_space_handle_t      bce_bhandle;
                    129:        bus_dma_tag_t           bce_dmatag;
                    130:        struct arpcom           bce_ac;         /* interface info */
                    131:        void                    *bce_intrhand;
                    132:        struct pci_attach_args  bce_pa;
                    133:        struct mii_data         bce_mii;
                    134:        u_int32_t               bce_phy;        /* eeprom indicated phy */
                    135:        struct bce_dma_slot     *bce_rx_ring;   /* receive ring */
                    136:        struct bce_dma_slot     *bce_tx_ring;   /* transmit ring */
                    137:        struct bce_chain_data   bce_cdata;      /* mbufs */
                    138:        bus_dmamap_t            bce_ring_map;
                    139:        u_int32_t               bce_intmask;    /* current intr mask */
                    140:        u_int32_t               bce_rxin;       /* last rx descriptor seen */
                    141:        u_int32_t               bce_txin;       /* last tx descriptor seen */
                    142:        int                     bce_txsfree;    /* no. tx slots available */
                    143:        int                     bce_txsnext;    /* next available tx slot */
                    144:        struct timeout          bce_timeout;
                    145: };
                    146:
                    147: /* for ring descriptors */
                    148: #define BCE_RXBUF_LEN  (MCLBYTES - 4)
                    149: #define BCE_INIT_RXDESC(sc, x)                                         \
                    150: do {                                                                   \
                    151:        struct bce_dma_slot *__bced = &sc->bce_rx_ring[x];              \
                    152:                                                                        \
                    153:        *mtod(sc->bce_cdata.bce_rx_chain[x], u_int32_t *) = 0;          \
                    154:        __bced->addr =                                                  \
                    155:            htole32(sc->bce_cdata.bce_rx_map[x]->dm_segs[0].ds_addr     \
                    156:            + 0x40000000);                                              \
                    157:        if (x != (BCE_NRXDESC - 1))                                     \
                    158:                __bced->ctrl = htole32(BCE_RXBUF_LEN);                  \
                    159:        else                                                            \
                    160:                __bced->ctrl = htole32(BCE_RXBUF_LEN | CTRL_EOT);       \
                    161:        bus_dmamap_sync(sc->bce_dmatag, sc->bce_ring_map,               \
                    162:            sizeof(struct bce_dma_slot) * x,                            \
                    163:            sizeof(struct bce_dma_slot),                                \
                    164:            BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);                  \
                    165: } while (/* CONSTCOND */ 0)
                    166:
                    167: int    bce_probe(struct device *, void *, void *);
                    168: void   bce_attach(struct device *, struct device *, void *);
                    169: int    bce_ioctl(struct ifnet *, u_long, caddr_t);
                    170: void   bce_start(struct ifnet *);
                    171: void   bce_watchdog(struct ifnet *);
                    172: int    bce_intr(void *);
                    173: void   bce_rxintr(struct bce_softc *);
                    174: void   bce_txintr(struct bce_softc *);
                    175: int    bce_init(struct ifnet *);
                    176: void   bce_add_mac(struct bce_softc *, u_int8_t *, unsigned long);
                    177: int    bce_add_rxbuf(struct bce_softc *, int);
                    178: void   bce_rxdrain(struct bce_softc *);
                    179: void   bce_stop(struct ifnet *, int);
                    180: void   bce_reset(struct bce_softc *);
                    181: void   bce_set_filter(struct ifnet *);
                    182: int    bce_mii_read(struct device *, int, int);
                    183: void   bce_mii_write(struct device *, int, int, int);
                    184: void   bce_statchg(struct device *);
                    185: int    bce_mediachange(struct ifnet *);
                    186: void   bce_mediastatus(struct ifnet *, struct ifmediareq *);
                    187: void   bce_tick(void *);
                    188:
                    189: #ifdef BCE_DEBUG
                    190: #define DPRINTF(x)     do {            \
                    191:        if (bcedebug)                   \
                    192:                printf x;               \
                    193: } while (/* CONSTCOND */ 0)
                    194: #define DPRINTFN(n,x)  do {            \
                    195:        if (bcedebug >= (n))            \
                    196:                printf x;               \
                    197: } while (/* CONSTCOND */ 0)
                    198: int             bcedebug = 0;
                    199: #else
                    200: #define DPRINTF(x)
                    201: #define DPRINTFN(n,x)
                    202: #endif
                    203:
                    204: struct cfattach bce_ca = {
                    205:        sizeof(struct bce_softc), bce_probe, bce_attach
                    206: };
                    207: struct cfdriver bce_cd = {
                    208:        0, "bce", DV_IFNET
                    209: };
                    210:
                    211: const struct pci_matchid bce_devices[] = {
                    212:        { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM4401 },
                    213:        { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM4401B0 },
                    214:        { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM4401B1 }
                    215: };
                    216:
                    217: int
                    218: bce_probe(struct device *parent, void *match, void *aux)
                    219: {
                    220:        return (pci_matchbyid((struct pci_attach_args *)aux, bce_devices,
                    221:            sizeof(bce_devices)/sizeof(bce_devices[0])));
                    222: }
                    223:
                    224: void
                    225: bce_attach(struct device *parent, struct device *self, void *aux)
                    226: {
                    227:        struct bce_softc *sc = (struct bce_softc *) self;
                    228:        struct pci_attach_args *pa = aux;
                    229:        pci_chipset_tag_t pc = pa->pa_pc;
                    230:        pci_intr_handle_t ih;
                    231:        const char     *intrstr = NULL;
                    232:        caddr_t         kva;
                    233:        bus_dma_segment_t seg;
                    234:        int             rseg;
                    235:        struct ifnet   *ifp;
                    236:        pcireg_t        memtype;
                    237:        bus_addr_t      memaddr;
                    238:        bus_size_t      memsize;
                    239:        int             pmreg;
                    240:        pcireg_t        pmode;
                    241:        int             error;
                    242:        int             i;
                    243:
                    244:        sc->bce_pa = *pa;
                    245:        sc->bce_dmatag = pa->pa_dmat;
                    246:
                    247:        /*
                    248:         * Map control/status registers.
                    249:         */
                    250:        memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, BCE_PCI_BAR0);
                    251:        switch (memtype) {
                    252:        case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT:
                    253:        case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_64BIT:
                    254:                if (pci_mapreg_map(pa, BCE_PCI_BAR0, memtype, 0, &sc->bce_btag,
                    255:                    &sc->bce_bhandle, &memaddr, &memsize, 0) == 0)
                    256:                        break;
                    257:        default:
                    258:                printf("%s: unable to find mem space\n",
                    259:                    sc->bce_dev.dv_xname);
                    260:                return;
                    261:        }
                    262:
                    263:        /* Get it out of power save mode if needed. */
                    264:        if (pci_get_capability(pc, pa->pa_tag, PCI_CAP_PWRMGMT, &pmreg, 0)) {
                    265:                pmode = pci_conf_read(pc, pa->pa_tag, pmreg + 4) & 0x3;
                    266:                if (pmode == 3) {
                    267:                        /*
                    268:                         * The card has lost all configuration data in
                    269:                         * this state, so punt.
                    270:                         */
                    271:                        printf("%s: unable to wake up from power state D3\n",
                    272:                               sc->bce_dev.dv_xname);
                    273:                        return;
                    274:                }
                    275:                if (pmode != 0) {
                    276:                        printf("%s: waking up from power state D%d\n",
                    277:                               sc->bce_dev.dv_xname, pmode);
                    278:                        pci_conf_write(pc, pa->pa_tag, pmreg + 4, 0);
                    279:                }
                    280:        }
                    281:        if (pci_intr_map(pa, &ih)) {
                    282:                printf("%s: couldn't map interrupt\n",
                    283:                    sc->bce_dev.dv_xname);
                    284:                return;
                    285:        }
                    286:        intrstr = pci_intr_string(pc, ih);
                    287:
                    288:        sc->bce_intrhand = pci_intr_establish(pc, ih, IPL_NET, bce_intr, sc,
                    289:            self->dv_xname);
                    290:
                    291:        if (sc->bce_intrhand == NULL) {
                    292:                printf("%s: couldn't establish interrupt",
                    293:                    sc->bce_dev.dv_xname);
                    294:                if (intrstr != NULL)
                    295:                        printf(" at %s", intrstr);
                    296:                printf("\n");
                    297:                return;
                    298:        }
                    299:
                    300:        /* reset the chip */
                    301:        bce_reset(sc);
                    302:
                    303:        /*
                    304:         * Allocate DMA-safe memory for ring descriptors.
                    305:         * The receive, and transmit rings can not share the same
                    306:         * 4k space, however both are allocated at once here.
                    307:         */
                    308:        /*
                    309:         * XXX PAGE_SIZE is wasteful; we only need 1KB + 1KB, but
                    310:         * due to the limition above. ??
                    311:         */
                    312:        if ((error = bus_dmamem_alloc(sc->bce_dmatag,
                    313:            2 * PAGE_SIZE, PAGE_SIZE, 2 * PAGE_SIZE,
                    314:                                      &seg, 1, &rseg, BUS_DMA_NOWAIT))) {
                    315:                printf("%s: unable to alloc space for ring descriptors, "
                    316:                       "error = %d\n", sc->bce_dev.dv_xname, error);
                    317:                return;
                    318:        }
                    319:        /* map ring space to kernel */
                    320:        if ((error = bus_dmamem_map(sc->bce_dmatag, &seg, rseg,
                    321:            2 * PAGE_SIZE, &kva, BUS_DMA_NOWAIT))) {
                    322:                printf("%s: unable to map DMA buffers, error = %d\n",
                    323:                    sc->bce_dev.dv_xname, error);
                    324:                bus_dmamem_free(sc->bce_dmatag, &seg, rseg);
                    325:                return;
                    326:        }
                    327:        /* create a dma map for the ring */
                    328:        if ((error = bus_dmamap_create(sc->bce_dmatag,
                    329:            2 * PAGE_SIZE, 1, 2 * PAGE_SIZE, 0, BUS_DMA_NOWAIT,
                    330:                                       &sc->bce_ring_map))) {
                    331:                printf("%s: unable to create ring DMA map, error = %d\n",
                    332:                    sc->bce_dev.dv_xname, error);
                    333:                bus_dmamem_unmap(sc->bce_dmatag, kva, 2 * PAGE_SIZE);
                    334:                bus_dmamem_free(sc->bce_dmatag, &seg, rseg);
                    335:                return;
                    336:        }
                    337:        /* connect the ring space to the dma map */
                    338:        if (bus_dmamap_load(sc->bce_dmatag, sc->bce_ring_map, kva,
                    339:            2 * PAGE_SIZE, NULL, BUS_DMA_NOWAIT)) {
                    340:                bus_dmamap_destroy(sc->bce_dmatag, sc->bce_ring_map);
                    341:                bus_dmamem_unmap(sc->bce_dmatag, kva, 2 * PAGE_SIZE);
                    342:                bus_dmamem_free(sc->bce_dmatag, &seg, rseg);
                    343:                return;
                    344:        }
                    345:        /* save the ring space in softc */
                    346:        sc->bce_rx_ring = (struct bce_dma_slot *) kva;
                    347:        sc->bce_tx_ring = (struct bce_dma_slot *) (kva + PAGE_SIZE);
                    348:
                    349:        /* Create the transmit buffer DMA maps. */
                    350:        for (i = 0; i < BCE_NTXDESC; i++) {
                    351:                if ((error = bus_dmamap_create(sc->bce_dmatag, MCLBYTES,
                    352:                    BCE_NTXFRAGS, MCLBYTES, 0, 0, &sc->bce_cdata.bce_tx_map[i])) != 0) {
                    353:                        printf("%s: unable to create tx DMA map, error = %d\n",
                    354:                            sc->bce_dev.dv_xname, error);
                    355:                }
                    356:                sc->bce_cdata.bce_tx_chain[i] = NULL;
                    357:        }
                    358:
                    359:        /* Create the receive buffer DMA maps. */
                    360:        for (i = 0; i < BCE_NRXDESC; i++) {
                    361:                if ((error = bus_dmamap_create(sc->bce_dmatag, MCLBYTES, 1,
                    362:                    MCLBYTES, 0, 0, &sc->bce_cdata.bce_rx_map[i])) != 0) {
                    363:                        printf("%s: unable to create rx DMA map, error = %d\n",
                    364:                            sc->bce_dev.dv_xname, error);
                    365:                }
                    366:                sc->bce_cdata.bce_rx_chain[i] = NULL;
                    367:        }
                    368:
                    369:        /* Set up ifnet structure */
                    370:        ifp = &sc->bce_ac.ac_if;
                    371:        strlcpy(ifp->if_xname, sc->bce_dev.dv_xname, IF_NAMESIZE);
                    372:        ifp->if_softc = sc;
                    373:        ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
                    374:        ifp->if_ioctl = bce_ioctl;
                    375:        ifp->if_start = bce_start;
                    376:        ifp->if_watchdog = bce_watchdog;
                    377:        ifp->if_init = bce_init;
                    378:        IFQ_SET_READY(&ifp->if_snd);
                    379:
                    380:        ifp->if_capabilities = IFCAP_VLAN_MTU;
                    381:
                    382:        /* MAC address */
                    383:        sc->bce_ac.ac_enaddr[0] =
                    384:            bus_space_read_1(sc->bce_btag, sc->bce_bhandle, BCE_ENET0);
                    385:        sc->bce_ac.ac_enaddr[1] =
                    386:            bus_space_read_1(sc->bce_btag, sc->bce_bhandle, BCE_ENET1);
                    387:        sc->bce_ac.ac_enaddr[2] =
                    388:            bus_space_read_1(sc->bce_btag, sc->bce_bhandle, BCE_ENET2);
                    389:        sc->bce_ac.ac_enaddr[3] =
                    390:            bus_space_read_1(sc->bce_btag, sc->bce_bhandle, BCE_ENET3);
                    391:        sc->bce_ac.ac_enaddr[4] =
                    392:            bus_space_read_1(sc->bce_btag, sc->bce_bhandle, BCE_ENET4);
                    393:        sc->bce_ac.ac_enaddr[5] =
                    394:            bus_space_read_1(sc->bce_btag, sc->bce_bhandle, BCE_ENET5);
                    395:        printf(": %s, address %s\n", intrstr,
                    396:            ether_sprintf(sc->bce_ac.ac_enaddr));
                    397:
                    398:        /* Initialize our media structures and probe the MII. */
                    399:
                    400:        sc->bce_mii.mii_ifp = ifp;
                    401:        sc->bce_mii.mii_readreg = bce_mii_read;
                    402:        sc->bce_mii.mii_writereg = bce_mii_write;
                    403:        sc->bce_mii.mii_statchg = bce_statchg;
                    404:        ifmedia_init(&sc->bce_mii.mii_media, 0, bce_mediachange,
                    405:            bce_mediastatus);
                    406:        mii_attach(&sc->bce_dev, &sc->bce_mii, 0xffffffff, MII_PHY_ANY,
                    407:            MII_OFFSET_ANY, 0);
                    408:        if (LIST_FIRST(&sc->bce_mii.mii_phys) == NULL) {
                    409:                ifmedia_add(&sc->bce_mii.mii_media, IFM_ETHER | IFM_NONE, 0, NULL);
                    410:                ifmedia_set(&sc->bce_mii.mii_media, IFM_ETHER | IFM_NONE);
                    411:        } else
                    412:                ifmedia_set(&sc->bce_mii.mii_media, IFM_ETHER | IFM_AUTO);
                    413:        /* get the phy */
                    414:        sc->bce_phy = bus_space_read_1(sc->bce_btag, sc->bce_bhandle,
                    415:            BCE_PHY) & 0x1f;
                    416:        /*
                    417:         * Enable activity led.
                    418:         * XXX This should be in a phy driver, but not currently.
                    419:         */
                    420:        bce_mii_write((struct device *) sc, 1, 26,       /* MAGIC */
                    421:            bce_mii_read((struct device *) sc, 1, 26) & 0x7fff);         /* MAGIC */
                    422:        /* enable traffic meter led mode */
                    423:        bce_mii_write((struct device *) sc, 1, 27,       /* MAGIC */
                    424:            bce_mii_read((struct device *) sc, 1, 27) | (1 << 6));       /* MAGIC */
                    425:
                    426:
                    427:        /* Attach the interface */
                    428:        if_attach(ifp);
                    429:        ether_ifattach(ifp);
                    430:        timeout_set(&sc->bce_timeout, bce_tick, sc);
                    431: }
                    432:
                    433: /* handle media, and ethernet requests */
                    434: int
                    435: bce_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
                    436: {
                    437:        struct bce_softc *sc = ifp->if_softc;
                    438:        struct ifreq   *ifr = (struct ifreq *) data;
                    439:        struct ifaddr *ifa = (struct ifaddr *)data;
                    440:        int             s, error = 0;
                    441:
                    442:        s = splnet();
                    443:
                    444:        if ((error = ether_ioctl(ifp, &sc->bce_ac, cmd, data)) > 0) {
                    445:                splx(s);
                    446:                return (error);
                    447:        }
                    448:
                    449:        switch (cmd) {
                    450:        case SIOCSIFADDR:
                    451:                ifp->if_flags |= IFF_UP;
                    452:
                    453:                switch (ifa->ifa_addr->sa_family) {
                    454: #ifdef INET
                    455:                case AF_INET:
                    456:                        bce_init(ifp);
                    457:                        arp_ifinit(&sc->bce_ac, ifa);
                    458:                        break;
                    459: #endif /* INET */
                    460:                default:
                    461:                        bce_init(ifp);
                    462:                        break;
                    463:                }
                    464:                break;
                    465:        case SIOCSIFMTU:
                    466:                if (ifr->ifr_mtu < ETHERMIN || ifr->ifr_mtu > ETHERMTU)
                    467:                        error = EINVAL;
                    468:                else if (ifp->if_mtu != ifr->ifr_mtu)
                    469:                        ifp->if_mtu = ifr->ifr_mtu;
                    470:                break;
                    471:        case SIOCSIFFLAGS:
                    472:                if(ifp->if_flags & IFF_UP)
                    473:                        if(ifp->if_flags & IFF_RUNNING)
                    474:                                bce_set_filter(ifp);
                    475:                        else
                    476:                                bce_init(ifp);
                    477:                else if(ifp->if_flags & IFF_RUNNING)
                    478:                        bce_stop(ifp, 0);
                    479:
                    480:                break;
                    481:        case SIOCADDMULTI:
                    482:        case SIOCDELMULTI:
                    483:                error = (cmd == SIOCADDMULTI) ?
                    484:                    ether_addmulti(ifr, &sc->bce_ac) :
                    485:                    ether_delmulti(ifr, &sc->bce_ac);
                    486:
                    487:                if (error == ENETRESET) {
                    488:                        /*
                    489:                         * Multicast list has changed; set the hardware
                    490:                         * filter accordingly.
                    491:                         */
                    492:                        if (ifp->if_flags & IFF_RUNNING)
                    493:                                bce_set_filter(ifp);
                    494:                        error = 0;
                    495:                }
                    496:                break;
                    497:        case SIOCSIFMEDIA:
                    498:        case SIOCGIFMEDIA:
                    499:                error = ifmedia_ioctl(ifp, ifr, &sc->bce_mii.mii_media, cmd);
                    500:                break;
                    501:        default:
                    502:                error = ENOTTY;
                    503:                break;
                    504:        }
                    505:
                    506:        if (error == 0) {
                    507:                /* Try to get more packets going. */
                    508:                bce_start(ifp);
                    509:        }
                    510:
                    511:        splx(s);
                    512:        return error;
                    513: }
                    514:
                    515: /* Start packet transmission on the interface. */
                    516: void
                    517: bce_start(struct ifnet *ifp)
                    518: {
                    519:        struct bce_softc *sc = ifp->if_softc;
                    520:        struct mbuf    *m0;
                    521:        bus_dmamap_t    dmamap;
                    522:        int             txstart;
                    523:        int             txsfree;
                    524:        int             newpkts = 0;
                    525:        int             error;
                    526:
                    527:        /*
                    528:          * do not start another if currently transmitting, and more
                    529:          * descriptors(tx slots) are needed for next packet.
                    530:          */
                    531:        if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
                    532:                return;
                    533:
                    534:        /* determine number of descriptors available */
                    535:        if (sc->bce_txsnext >= sc->bce_txin)
                    536:                txsfree = BCE_NTXDESC - 1 + sc->bce_txin - sc->bce_txsnext;
                    537:        else
                    538:                txsfree = sc->bce_txin - sc->bce_txsnext - 1;
                    539:
                    540:        /*
                    541:          * Loop through the send queue, setting up transmit descriptors
                    542:          * until we drain the queue, or use up all available transmit
                    543:          * descriptors.
                    544:          */
                    545:        while (txsfree > 0) {
                    546:                int             seg;
                    547:
                    548:                /* Grab a packet off the queue. */
                    549:                IFQ_POLL(&ifp->if_snd, m0);
                    550:                if (m0 == NULL)
                    551:                        break;
                    552:
                    553:                /* get the transmit slot dma map */
                    554:                dmamap = sc->bce_cdata.bce_tx_map[sc->bce_txsnext];
                    555:
                    556:                /*
                    557:                 * Load the DMA map.  If this fails, the packet either
                    558:                 * didn't fit in the alloted number of segments, or we
                    559:                 * were short on resources. If the packet will not fit,
                    560:                 * it will be dropped. If short on resources, it will
                    561:                 * be tried again later.
                    562:                 */
                    563:                error = bus_dmamap_load_mbuf(sc->bce_dmatag, dmamap, m0,
                    564:                    BUS_DMA_WRITE | BUS_DMA_NOWAIT);
                    565:                if (error == EFBIG) {
                    566:                        printf("%s: Tx packet consumes too many DMA segments, "
                    567:                            "dropping...\n", sc->bce_dev.dv_xname);
                    568:                        IFQ_DEQUEUE(&ifp->if_snd, m0);
                    569:                        m_freem(m0);
                    570:                        ifp->if_oerrors++;
                    571:                        continue;
                    572:                } else if (error) {
                    573:                        /* short on resources, come back later */
                    574:                        printf("%s: unable to load Tx buffer, error = %d\n",
                    575:                            sc->bce_dev.dv_xname, error);
                    576:                        break;
                    577:                }
                    578:                /* If not enough descriptors available, try again later */
                    579:                if (dmamap->dm_nsegs > txsfree) {
                    580:                        ifp->if_flags |= IFF_OACTIVE;
                    581:                        bus_dmamap_unload(sc->bce_dmatag, dmamap);
                    582:                        break;
                    583:                }
                    584:                /* WE ARE NOW COMMITTED TO TRANSMITTING THE PACKET. */
                    585:
                    586:                /* So take it off the queue */
                    587:                IFQ_DEQUEUE(&ifp->if_snd, m0);
                    588:
                    589:                /* save the pointer so it can be freed later */
                    590:                sc->bce_cdata.bce_tx_chain[sc->bce_txsnext] = m0;
                    591:
                    592:                /* Sync the data DMA map. */
                    593:                bus_dmamap_sync(sc->bce_dmatag, dmamap, 0, dmamap->dm_mapsize,
                    594:                                BUS_DMASYNC_PREWRITE);
                    595:
                    596:                /* Initialize the transmit descriptor(s). */
                    597:                txstart = sc->bce_txsnext;
                    598:                for (seg = 0; seg < dmamap->dm_nsegs; seg++) {
                    599:                        u_int32_t ctrl;
                    600:
                    601:                        ctrl = dmamap->dm_segs[seg].ds_len & CTRL_BC_MASK;
                    602:                        if (seg == 0)
                    603:                                ctrl |= CTRL_SOF;
                    604:                        if (seg == dmamap->dm_nsegs - 1)
                    605:                                ctrl |= CTRL_EOF;
                    606:                        if (sc->bce_txsnext == BCE_NTXDESC - 1)
                    607:                                ctrl |= CTRL_EOT;
                    608:                        ctrl |= CTRL_IOC;
                    609:                        sc->bce_tx_ring[sc->bce_txsnext].ctrl = htole32(ctrl);
                    610:                        sc->bce_tx_ring[sc->bce_txsnext].addr =
                    611:                            htole32(dmamap->dm_segs[seg].ds_addr + 0x40000000); /* MAGIC */
                    612:                        if (sc->bce_txsnext + 1 > BCE_NTXDESC - 1)
                    613:                                sc->bce_txsnext = 0;
                    614:                        else
                    615:                                sc->bce_txsnext++;
                    616:                        txsfree--;
                    617:                }
                    618:                /* sync descriptors being used */
                    619:                bus_dmamap_sync(sc->bce_dmatag, sc->bce_ring_map,
                    620:                          sizeof(struct bce_dma_slot) * txstart + PAGE_SIZE,
                    621:                             sizeof(struct bce_dma_slot) * dmamap->dm_nsegs,
                    622:                                BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
                    623:
                    624:                /* Give the packet to the chip. */
                    625:                bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_DMA_DPTR,
                    626:                             sc->bce_txsnext * sizeof(struct bce_dma_slot));
                    627:
                    628:                newpkts++;
                    629:
                    630: #if NBPFILTER > 0
                    631:                /* Pass the packet to any BPF listeners. */
                    632:                if (ifp->if_bpf)
                    633:                        bpf_mtap(ifp->if_bpf, m0, BPF_DIRECTION_OUT);
                    634: #endif                         /* NBPFILTER > 0 */
                    635:        }
                    636:        if (txsfree == 0) {
                    637:                /* No more slots left; notify upper layer. */
                    638:                ifp->if_flags |= IFF_OACTIVE;
                    639:        }
                    640:        if (newpkts) {
                    641:                /* Set a watchdog timer in case the chip flakes out. */
                    642:                ifp->if_timer = 5;
                    643:        }
                    644: }
                    645:
                    646: /* Watchdog timer handler. */
                    647: void
                    648: bce_watchdog(struct ifnet *ifp)
                    649: {
                    650:        struct bce_softc *sc = ifp->if_softc;
                    651:
                    652:        printf("%s: device timeout\n", sc->bce_dev.dv_xname);
                    653:        ifp->if_oerrors++;
                    654:
                    655:        (void) bce_init(ifp);
                    656:
                    657:        /* Try to get more packets going. */
                    658:        bce_start(ifp);
                    659: }
                    660:
                    661: int
                    662: bce_intr(void *xsc)
                    663: {
                    664:        struct bce_softc *sc;
                    665:        struct ifnet   *ifp;
                    666:        u_int32_t intstatus;
                    667:        int             wantinit;
                    668:        int             handled = 0;
                    669:
                    670:        sc = xsc;
                    671:        ifp = &sc->bce_ac.ac_if;
                    672:
                    673:
                    674:        for (wantinit = 0; wantinit == 0;) {
                    675:                intstatus = bus_space_read_4(sc->bce_btag, sc->bce_bhandle,
                    676:                    BCE_INT_STS);
                    677:
                    678:                /* ignore if not ours, or unsolicited interrupts */
                    679:                intstatus &= sc->bce_intmask;
                    680:                if (intstatus == 0)
                    681:                        break;
                    682:
                    683:                handled = 1;
                    684:
                    685:                /* Ack interrupt */
                    686:                bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_INT_STS,
                    687:                    intstatus);
                    688:
                    689:                /* Receive interrupts. */
                    690:                if (intstatus & I_RI)
                    691:                        bce_rxintr(sc);
                    692:                /* Transmit interrupts. */
                    693:                if (intstatus & I_XI)
                    694:                        bce_txintr(sc);
                    695:                /* Error interrupts */
                    696:                if (intstatus & ~(I_RI | I_XI)) {
                    697:                        if (intstatus & I_XU)
                    698:                                printf("%s: transmit fifo underflow\n",
                    699:                                    sc->bce_dev.dv_xname);
                    700:                        if (intstatus & I_RO) {
                    701:                                printf("%s: receive fifo overflow\n",
                    702:                                    sc->bce_dev.dv_xname);
                    703:                                ifp->if_ierrors++;
                    704:                        }
                    705:                        if (intstatus & I_RU)
                    706:                                printf("%s: receive descriptor underflow\n",
                    707:                                       sc->bce_dev.dv_xname);
                    708:                        if (intstatus & I_DE)
                    709:                                printf("%s: descriptor protocol error\n",
                    710:                                       sc->bce_dev.dv_xname);
                    711:                        if (intstatus & I_PD)
                    712:                                printf("%s: data error\n",
                    713:                                    sc->bce_dev.dv_xname);
                    714:                        if (intstatus & I_PC)
                    715:                                printf("%s: descriptor error\n",
                    716:                                    sc->bce_dev.dv_xname);
                    717:                        if (intstatus & I_TO)
                    718:                                printf("%s: general purpose timeout\n",
                    719:                                    sc->bce_dev.dv_xname);
                    720:                        wantinit = 1;
                    721:                }
                    722:        }
                    723:
                    724:        if (handled) {
                    725:                if (wantinit)
                    726:                        bce_init(ifp);
                    727:                /* Try to get more packets going. */
                    728:                bce_start(ifp);
                    729:        }
                    730:        return (handled);
                    731: }
                    732:
                    733: /* Receive interrupt handler */
                    734: void
                    735: bce_rxintr(struct bce_softc *sc)
                    736: {
                    737:        struct ifnet   *ifp = &sc->bce_ac.ac_if;
                    738:        struct rx_pph  *pph;
                    739:        struct mbuf    *m;
                    740:        int             curr;
                    741:        int             len;
                    742:        int             i;
                    743:
                    744:        /* get pointer to active receive slot */
                    745:        curr = bus_space_read_4(sc->bce_btag, sc->bce_bhandle, BCE_DMA_RXSTATUS)
                    746:            & RS_CD_MASK;
                    747:        curr = curr / sizeof(struct bce_dma_slot);
                    748:        if (curr >= BCE_NRXDESC)
                    749:                curr = BCE_NRXDESC - 1;
                    750:
                    751:        /* process packets up to but not current packet being worked on */
                    752:        for (i = sc->bce_rxin; i != curr;
                    753:            i + 1 > BCE_NRXDESC - 1 ? i = 0 : i++) {
                    754:                /* complete any post dma memory ops on packet */
                    755:                bus_dmamap_sync(sc->bce_dmatag, sc->bce_cdata.bce_rx_map[i], 0,
                    756:                    sc->bce_cdata.bce_rx_map[i]->dm_mapsize,
                    757:                    BUS_DMASYNC_POSTREAD);
                    758:
                    759:                /*
                    760:                 * If the packet had an error, simply recycle the buffer,
                    761:                 * resetting the len, and flags.
                    762:                 */
                    763:                pph = mtod(sc->bce_cdata.bce_rx_chain[i], struct rx_pph *);
                    764:                if (pph->flags & (RXF_NO | RXF_RXER | RXF_CRC | RXF_OV)) {
                    765:                        ifp->if_ierrors++;
                    766:                        pph->len = 0;
                    767:                        pph->flags = 0;
                    768:                        continue;
                    769:                }
                    770:                /* receive the packet */
                    771:                len = pph->len;
                    772:                if (len == 0)
                    773:                        continue;       /* no packet if empty */
                    774:                pph->len = 0;
                    775:                pph->flags = 0;
                    776:                /* bump past pre header to packet */
                    777:                sc->bce_cdata.bce_rx_chain[i]->m_data +=
                    778:                        BCE_PREPKT_HEADER_SIZE;
                    779:
                    780:                /*
                    781:                 * The chip includes the CRC with every packet.  Trim
                    782:                 * it off here.
                    783:                 */
                    784:                len -= ETHER_CRC_LEN;
                    785:
                    786:                /*
                    787:                 * If the packet is small enough to fit in a
                    788:                 * single header mbuf, allocate one and copy
                    789:                 * the data into it.  This greatly reduces
                    790:                 * memory consumption when receiving lots
                    791:                 * of small packets.
                    792:                 *
                    793:                 * Otherwise, add a new buffer to the receive
                    794:                 * chain.  If this fails, drop the packet and
                    795:                 * recycle the old buffer.
                    796:                 */
                    797:                if (len <= (MHLEN - 2)) {
                    798:                        MGETHDR(m, M_DONTWAIT, MT_DATA);
                    799:                        if (m == NULL)
                    800:                                goto dropit;
                    801:                        m->m_data += 2;
                    802:                        memcpy(mtod(m, caddr_t),
                    803:                         mtod(sc->bce_cdata.bce_rx_chain[i], caddr_t), len);
                    804:                        sc->bce_cdata.bce_rx_chain[i]->m_data -=
                    805:                                BCE_PREPKT_HEADER_SIZE;
                    806:                } else {
                    807:                        m = sc->bce_cdata.bce_rx_chain[i];
                    808:                        if (bce_add_rxbuf(sc, i) != 0) {
                    809:                dropit:
                    810:                                ifp->if_ierrors++;
                    811:                                /* continue to use old buffer */
                    812:                                sc->bce_cdata.bce_rx_chain[i]->m_data -=
                    813:                                        BCE_PREPKT_HEADER_SIZE;
                    814:                                bus_dmamap_sync(sc->bce_dmatag,
                    815:                                    sc->bce_cdata.bce_rx_map[i], 0,
                    816:                                    sc->bce_cdata.bce_rx_map[i]->dm_mapsize,
                    817:                                    BUS_DMASYNC_PREREAD);
                    818:                                continue;
                    819:                        }
                    820:                }
                    821:
                    822:                m->m_pkthdr.rcvif = ifp;
                    823:                m->m_pkthdr.len = m->m_len = len;
                    824:                ifp->if_ipackets++;
                    825:
                    826: #if NBPFILTER > 0
                    827:                /*
                    828:                 * Pass this up to any BPF listeners, but only
                    829:                 * pass it up the stack if it's for us.
                    830:                 */
                    831:                if (ifp->if_bpf)
                    832:                        bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
                    833: #endif                         /* NBPFILTER > 0 */
                    834:
                    835:                /* Pass it on. */
                    836:                ether_input_mbuf(ifp, m);
                    837:
                    838:                /* re-check current in case it changed */
                    839:                curr = (bus_space_read_4(sc->bce_btag, sc->bce_bhandle,
                    840:                    BCE_DMA_RXSTATUS) & RS_CD_MASK) /
                    841:                    sizeof(struct bce_dma_slot);
                    842:                if (curr >= BCE_NRXDESC)
                    843:                        curr = BCE_NRXDESC - 1;
                    844:        }
                    845:        sc->bce_rxin = curr;
                    846: }
                    847:
                    848: /* Transmit interrupt handler */
                    849: void
                    850: bce_txintr(struct bce_softc *sc)
                    851: {
                    852:        struct ifnet   *ifp = &sc->bce_ac.ac_if;
                    853:        int             curr;
                    854:        int             i;
                    855:
                    856:        ifp->if_flags &= ~IFF_OACTIVE;
                    857:
                    858:        /*
                    859:          * Go through the Tx list and free mbufs for those
                    860:          * frames which have been transmitted.
                    861:          */
                    862:        curr = bus_space_read_4(sc->bce_btag, sc->bce_bhandle, BCE_DMA_TXSTATUS) &
                    863:                RS_CD_MASK;
                    864:        curr = curr / sizeof(struct bce_dma_slot);
                    865:        if (curr >= BCE_NTXDESC)
                    866:                curr = BCE_NTXDESC - 1;
                    867:        for (i = sc->bce_txin; i != curr;
                    868:            i + 1 > BCE_NTXDESC - 1 ? i = 0 : i++) {
                    869:                /* do any post dma memory ops on transmit data */
                    870:                if (sc->bce_cdata.bce_tx_chain[i] == NULL)
                    871:                        continue;
                    872:                bus_dmamap_sync(sc->bce_dmatag, sc->bce_cdata.bce_tx_map[i], 0,
                    873:                    sc->bce_cdata.bce_tx_map[i]->dm_mapsize,
                    874:                    BUS_DMASYNC_POSTWRITE);
                    875:                bus_dmamap_unload(sc->bce_dmatag, sc->bce_cdata.bce_tx_map[i]);
                    876:                m_freem(sc->bce_cdata.bce_tx_chain[i]);
                    877:                sc->bce_cdata.bce_tx_chain[i] = NULL;
                    878:                ifp->if_opackets++;
                    879:        }
                    880:        sc->bce_txin = curr;
                    881:
                    882:        /*
                    883:         * If there are no more pending transmissions, cancel the watchdog
                    884:         * timer
                    885:         */
                    886:        if (sc->bce_txsnext == sc->bce_txin)
                    887:                ifp->if_timer = 0;
                    888: }
                    889:
                    890: /* initialize the interface */
                    891: int
                    892: bce_init(struct ifnet *ifp)
                    893: {
                    894:        struct bce_softc *sc = ifp->if_softc;
                    895:        u_int32_t reg_win;
                    896:        int             error;
                    897:        int             i;
                    898:
                    899:        /* Cancel any pending I/O. */
                    900:        bce_stop(ifp, 0);
                    901:
                    902:        /* enable pci inerrupts, bursts, and prefetch */
                    903:
                    904:        /* remap the pci registers to the Sonics config registers */
                    905:
                    906:        /* save the current map, so it can be restored */
                    907:        reg_win = pci_conf_read(sc->bce_pa.pa_pc, sc->bce_pa.pa_tag,
                    908:            BCE_REG_WIN);
                    909:
                    910:        /* set register window to Sonics registers */
                    911:        pci_conf_write(sc->bce_pa.pa_pc, sc->bce_pa.pa_tag, BCE_REG_WIN,
                    912:            BCE_SONICS_WIN);
                    913:
                    914:        /* enable SB to PCI interrupt */
                    915:        bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_SBINTVEC,
                    916:            bus_space_read_4(sc->bce_btag, sc->bce_bhandle, BCE_SBINTVEC) |
                    917:            SBIV_ENET0);
                    918:
                    919:        /* enable prefetch and bursts for sonics-to-pci translation 2 */
                    920:        bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_SPCI_TR2,
                    921:            bus_space_read_4(sc->bce_btag, sc->bce_bhandle, BCE_SPCI_TR2) |
                    922:            SBTOPCI_PREF | SBTOPCI_BURST);
                    923:
                    924:        /* restore to ethernet register space */
                    925:        pci_conf_write(sc->bce_pa.pa_pc, sc->bce_pa.pa_tag, BCE_REG_WIN,
                    926:            reg_win);
                    927:
                    928:        /* Reset the chip to a known state. */
                    929:        bce_reset(sc);
                    930:
                    931:        /* Initialize transmit descriptors */
                    932:        memset(sc->bce_tx_ring, 0, BCE_NTXDESC * sizeof(struct bce_dma_slot));
                    933:        sc->bce_txsnext = 0;
                    934:        sc->bce_txin = 0;
                    935:
                    936:        /* enable crc32 generation and set proper LED modes */
                    937:        bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_MACCTL,
                    938:            bus_space_read_4(sc->bce_btag, sc->bce_bhandle, BCE_MACCTL) |
                    939:            BCE_EMC_CRC32_ENAB | BCE_EMC_LED);
                    940:
                    941:        /* reset or clear powerdown control bit  */
                    942:        bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_MACCTL,
                    943:            bus_space_read_4(sc->bce_btag, sc->bce_bhandle, BCE_MACCTL) &
                    944:            ~BCE_EMC_PDOWN);
                    945:
                    946:        /* setup DMA interrupt control */
                    947:        bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_DMAI_CTL, 1 << 24);        /* MAGIC */
                    948:
                    949:        /* setup packet filter */
                    950:        bce_set_filter(ifp);
                    951:
                    952:        /* set max frame length, account for possible VLAN tag */
                    953:        bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_RX_MAX,
                    954:            ETHER_MAX_LEN + ETHER_VLAN_ENCAP_LEN);
                    955:        bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_TX_MAX,
                    956:            ETHER_MAX_LEN + ETHER_VLAN_ENCAP_LEN);
                    957:
                    958:        /* set tx watermark */
                    959:        bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_TX_WATER, 56);
                    960:
                    961:        /* enable transmit */
                    962:        bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_DMA_TXCTL, XC_XE);
                    963:        bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_DMA_TXADDR,
                    964:            sc->bce_ring_map->dm_segs[0].ds_addr + PAGE_SIZE + 0x40000000);     /* MAGIC */
                    965:
                    966:        /*
                    967:          * Give the receive ring to the chip, and
                    968:          * start the receive DMA engine.
                    969:          */
                    970:        sc->bce_rxin = 0;
                    971:
                    972:        /* clear the rx descriptor ring */
                    973:        memset(sc->bce_rx_ring, 0, BCE_NRXDESC * sizeof(struct bce_dma_slot));
                    974:        /* enable receive */
                    975:        bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_DMA_RXCTL,
                    976:            BCE_PREPKT_HEADER_SIZE << 1 | XC_XE);
                    977:        bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_DMA_RXADDR,
                    978:            sc->bce_ring_map->dm_segs[0].ds_addr + 0x40000000);         /* MAGIC */
                    979:
                    980:        /* Initalize receive descriptors */
                    981:        for (i = 0; i < BCE_NRXDESC; i++) {
                    982:                if (sc->bce_cdata.bce_rx_chain[i] == NULL) {
                    983:                        if ((error = bce_add_rxbuf(sc, i)) != 0) {
                    984:                                printf("%s: unable to allocate or map rx(%d) "
                    985:                                    "mbuf, error = %d\n", sc->bce_dev.dv_xname,
                    986:                                    i, error);
                    987:                                bce_rxdrain(sc);
                    988:                                return (error);
                    989:                        }
                    990:                } else
                    991:                        BCE_INIT_RXDESC(sc, i);
                    992:        }
                    993:
                    994:        /* Enable interrupts */
                    995:        sc->bce_intmask =
                    996:            I_XI | I_RI | I_XU | I_RO | I_RU | I_DE | I_PD | I_PC | I_TO;
                    997:        bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_INT_MASK,
                    998:            sc->bce_intmask);
                    999:
                   1000:        /* start the receive dma */
                   1001:        bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_DMA_RXDPTR,
                   1002:            BCE_NRXDESC * sizeof(struct bce_dma_slot));
                   1003:
                   1004:        /* set media */
                   1005:        mii_mediachg(&sc->bce_mii);
                   1006:
                   1007:        /* turn on the ethernet mac */
                   1008:        bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_ENET_CTL,
                   1009:            bus_space_read_4(sc->bce_btag, sc->bce_bhandle,
                   1010:            BCE_ENET_CTL) | EC_EE);
                   1011:
                   1012:        /* start timer */
                   1013:        timeout_add(&sc->bce_timeout, hz);
                   1014:
                   1015:        /* mark as running, and no outputs active */
                   1016:        ifp->if_flags |= IFF_RUNNING;
                   1017:        ifp->if_flags &= ~IFF_OACTIVE;
                   1018:
                   1019:        return 0;
                   1020: }
                   1021:
                   1022: /* add a mac address to packet filter */
                   1023: void
                   1024: bce_add_mac(struct bce_softc *sc, u_int8_t *mac, unsigned long idx)
                   1025: {
                   1026:        int             i;
                   1027:        u_int32_t rval;
                   1028:
                   1029:        bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_FILT_LOW,
                   1030:            mac[2] << 24 | mac[3] << 16 | mac[4] << 8 | mac[5]);
                   1031:        bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_FILT_HI,
                   1032:            mac[0] << 8 | mac[1] | 0x10000);    /* MAGIC */
                   1033:        bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_FILT_CTL,
                   1034:            idx << 16 | 8);     /* MAGIC */
                   1035:        /* wait for write to complete */
                   1036:        for (i = 0; i < 100; i++) {
                   1037:                rval = bus_space_read_4(sc->bce_btag, sc->bce_bhandle,
                   1038:                    BCE_FILT_CTL);
                   1039:                if (!(rval & 0x80000000))       /* MAGIC */
                   1040:                        break;
                   1041:                delay(10);
                   1042:        }
                   1043:        if (i == 100) {
                   1044:                printf("%s: timed out writing pkt filter ctl\n",
                   1045:                   sc->bce_dev.dv_xname);
                   1046:        }
                   1047: }
                   1048:
                   1049: /* Add a receive buffer to the indiciated descriptor. */
                   1050: int
                   1051: bce_add_rxbuf(struct bce_softc *sc, int idx)
                   1052: {
                   1053:        struct mbuf    *m;
                   1054:        int             error;
                   1055:
                   1056:        MGETHDR(m, M_DONTWAIT, MT_DATA);
                   1057:        if (m == NULL)
                   1058:                return (ENOBUFS);
                   1059:
                   1060:        MCLGET(m, M_DONTWAIT);
                   1061:        if ((m->m_flags & M_EXT) == 0) {
                   1062:                m_freem(m);
                   1063:                return (ENOBUFS);
                   1064:        }
                   1065:        if (sc->bce_cdata.bce_rx_chain[idx] != NULL)
                   1066:                bus_dmamap_unload(sc->bce_dmatag,
                   1067:                    sc->bce_cdata.bce_rx_map[idx]);
                   1068:
                   1069:        sc->bce_cdata.bce_rx_chain[idx] = m;
                   1070:
                   1071:        error = bus_dmamap_load(sc->bce_dmatag, sc->bce_cdata.bce_rx_map[idx],
                   1072:            m->m_ext.ext_buf, m->m_ext.ext_size, NULL,
                   1073:            BUS_DMA_READ | BUS_DMA_NOWAIT);
                   1074:        if (error)
                   1075:                return (error);
                   1076:
                   1077:        bus_dmamap_sync(sc->bce_dmatag, sc->bce_cdata.bce_rx_map[idx], 0,
                   1078:            sc->bce_cdata.bce_rx_map[idx]->dm_mapsize, BUS_DMASYNC_PREREAD);
                   1079:
                   1080:        BCE_INIT_RXDESC(sc, idx);
                   1081:
                   1082:        return (0);
                   1083:
                   1084: }
                   1085:
                   1086: /* Drain the receive queue. */
                   1087: void
                   1088: bce_rxdrain(struct bce_softc *sc)
                   1089: {
                   1090:        int             i;
                   1091:
                   1092:        for (i = 0; i < BCE_NRXDESC; i++) {
                   1093:                if (sc->bce_cdata.bce_rx_chain[i] != NULL) {
                   1094:                        bus_dmamap_unload(sc->bce_dmatag,
                   1095:                            sc->bce_cdata.bce_rx_map[i]);
                   1096:                        m_freem(sc->bce_cdata.bce_rx_chain[i]);
                   1097:                        sc->bce_cdata.bce_rx_chain[i] = NULL;
                   1098:                }
                   1099:        }
                   1100: }
                   1101:
                   1102: /* Stop transmission on the interface */
                   1103: void
                   1104: bce_stop(struct ifnet *ifp, int disable)
                   1105: {
                   1106:        struct bce_softc *sc = ifp->if_softc;
                   1107:        int             i;
                   1108:        u_int32_t val;
                   1109:
                   1110:        /* Stop the 1 second timer */
                   1111:        timeout_del(&sc->bce_timeout);
                   1112:
                   1113:        /* Mark the interface down and cancel the watchdog timer. */
                   1114:        ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
                   1115:        ifp->if_timer = 0;
                   1116:
                   1117:        /* Down the MII. */
                   1118:        mii_down(&sc->bce_mii);
                   1119:
                   1120:        /* Disable interrupts. */
                   1121:        bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_INT_MASK, 0);
                   1122:        sc->bce_intmask = 0;
                   1123:        delay(10);
                   1124:
                   1125:        /* Disable emac */
                   1126:        bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_ENET_CTL, EC_ED);
                   1127:        for (i = 0; i < 200; i++) {
                   1128:                val = bus_space_read_4(sc->bce_btag, sc->bce_bhandle,
                   1129:                    BCE_ENET_CTL);
                   1130:                if (!(val & EC_ED))
                   1131:                        break;
                   1132:                delay(10);
                   1133:        }
                   1134:
                   1135:        /* Stop the DMA */
                   1136:        bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_DMA_RXCTL, 0);
                   1137:        bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_DMA_TXCTL, 0);
                   1138:        delay(10);
                   1139:
                   1140:        /* Release any queued transmit buffers. */
                   1141:        for (i = 0; i < BCE_NTXDESC; i++) {
                   1142:                if (sc->bce_cdata.bce_tx_chain[i] != NULL) {
                   1143:                        bus_dmamap_unload(sc->bce_dmatag,
                   1144:                            sc->bce_cdata.bce_tx_map[i]);
                   1145:                        m_freem(sc->bce_cdata.bce_tx_chain[i]);
                   1146:                        sc->bce_cdata.bce_tx_chain[i] = NULL;
                   1147:                }
                   1148:        }
                   1149:
                   1150:        /* drain receive queue */
                   1151:        if (disable)
                   1152:                bce_rxdrain(sc);
                   1153: }
                   1154:
                   1155: /* reset the chip */
                   1156: void
                   1157: bce_reset(struct bce_softc *sc)
                   1158: {
                   1159:        u_int32_t val;
                   1160:        u_int32_t sbval;
                   1161:        int             i;
                   1162:
                   1163:        /* if SB core is up */
                   1164:        sbval = bus_space_read_4(sc->bce_btag, sc->bce_bhandle,
                   1165:            BCE_SBTMSTATELOW);
                   1166:        if ((sbval & (SBTML_RESET | SBTML_REJ | SBTML_CLK)) == SBTML_CLK) {
                   1167:                bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_DMAI_CTL,
                   1168:                    0);
                   1169:
                   1170:                /* disable emac */
                   1171:                bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_ENET_CTL,
                   1172:                    EC_ED);
                   1173:                for (i = 0; i < 200; i++) {
                   1174:                        val = bus_space_read_4(sc->bce_btag, sc->bce_bhandle,
                   1175:                            BCE_ENET_CTL);
                   1176:                        if (!(val & EC_ED))
                   1177:                                break;
                   1178:                        delay(10);
                   1179:                }
                   1180:                if (i == 200)
                   1181:                        printf("%s: timed out disabling ethernet mac\n",
                   1182:                               sc->bce_dev.dv_xname);
                   1183:
                   1184:                /* reset the dma engines */
                   1185:                bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_DMA_TXCTL, 0);
                   1186:                val = bus_space_read_4(sc->bce_btag, sc->bce_bhandle, BCE_DMA_RXSTATUS);
                   1187:                /* if error on receive, wait to go idle */
                   1188:                if (val & RS_ERROR) {
                   1189:                        for (i = 0; i < 100; i++) {
                   1190:                                val = bus_space_read_4(sc->bce_btag,
                   1191:                                    sc->bce_bhandle, BCE_DMA_RXSTATUS);
                   1192:                                if (val & RS_DMA_IDLE)
                   1193:                                        break;
                   1194:                                delay(10);
                   1195:                        }
                   1196:                        if (i == 100)
                   1197:                                printf("%s: receive dma did not go idle after"
                   1198:                                    " error\n", sc->bce_dev.dv_xname);
                   1199:                }
                   1200:                bus_space_write_4(sc->bce_btag, sc->bce_bhandle,
                   1201:                   BCE_DMA_RXSTATUS, 0);
                   1202:
                   1203:                /* reset ethernet mac */
                   1204:                bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_ENET_CTL,
                   1205:                    EC_ES);
                   1206:                for (i = 0; i < 200; i++) {
                   1207:                        val = bus_space_read_4(sc->bce_btag, sc->bce_bhandle,
                   1208:                            BCE_ENET_CTL);
                   1209:                        if (!(val & EC_ES))
                   1210:                                break;
                   1211:                        delay(10);
                   1212:                }
                   1213:                if (i == 200)
                   1214:                        printf("%s: timed out resetting ethernet mac\n",
                   1215:                               sc->bce_dev.dv_xname);
                   1216:        } else {
                   1217:                u_int32_t reg_win;
                   1218:
                   1219:                /* remap the pci registers to the Sonics config registers */
                   1220:
                   1221:                /* save the current map, so it can be restored */
                   1222:                reg_win = pci_conf_read(sc->bce_pa.pa_pc, sc->bce_pa.pa_tag,
                   1223:                    BCE_REG_WIN);
                   1224:                /* set register window to Sonics registers */
                   1225:                pci_conf_write(sc->bce_pa.pa_pc, sc->bce_pa.pa_tag,
                   1226:                    BCE_REG_WIN, BCE_SONICS_WIN);
                   1227:
                   1228:                /* enable SB to PCI interrupt */
                   1229:                bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_SBINTVEC,
                   1230:                    bus_space_read_4(sc->bce_btag, sc->bce_bhandle,
                   1231:                        BCE_SBINTVEC) |
                   1232:                    SBIV_ENET0);
                   1233:
                   1234:                /* enable prefetch and bursts for sonics-to-pci translation 2 */
                   1235:                bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_SPCI_TR2,
                   1236:                    bus_space_read_4(sc->bce_btag, sc->bce_bhandle,
                   1237:                        BCE_SPCI_TR2) |
                   1238:                    SBTOPCI_PREF | SBTOPCI_BURST);
                   1239:
                   1240:                /* restore to ethernet register space */
                   1241:                pci_conf_write(sc->bce_pa.pa_pc, sc->bce_pa.pa_tag, BCE_REG_WIN,
                   1242:                               reg_win);
                   1243:        }
                   1244:
                   1245:        /* disable SB core if not in reset */
                   1246:        if (!(sbval & SBTML_RESET)) {
                   1247:
                   1248:                /* set the reject bit */
                   1249:                bus_space_write_4(sc->bce_btag, sc->bce_bhandle,
                   1250:                    BCE_SBTMSTATELOW, SBTML_REJ | SBTML_CLK);
                   1251:                for (i = 0; i < 200; i++) {
                   1252:                        val = bus_space_read_4(sc->bce_btag, sc->bce_bhandle,
                   1253:                            BCE_SBTMSTATELOW);
                   1254:                        if (val & SBTML_REJ)
                   1255:                                break;
                   1256:                        delay(1);
                   1257:                }
                   1258:                if (i == 200)
                   1259:                        printf("%s: while resetting core, reject did not set\n",
                   1260:                            sc->bce_dev.dv_xname);
                   1261:                /* wait until busy is clear */
                   1262:                for (i = 0; i < 200; i++) {
                   1263:                        val = bus_space_read_4(sc->bce_btag, sc->bce_bhandle,
                   1264:                            BCE_SBTMSTATEHI);
                   1265:                        if (!(val & 0x4))
                   1266:                                break;
                   1267:                        delay(1);
                   1268:                }
                   1269:                if (i == 200)
                   1270:                        printf("%s: while resetting core, busy did not clear\n",
                   1271:                            sc->bce_dev.dv_xname);
                   1272:                /* set reset and reject while enabling the clocks */
                   1273:                bus_space_write_4(sc->bce_btag, sc->bce_bhandle,
                   1274:                    BCE_SBTMSTATELOW,
                   1275:                    SBTML_FGC | SBTML_CLK | SBTML_REJ | SBTML_RESET);
                   1276:                val = bus_space_read_4(sc->bce_btag, sc->bce_bhandle,
                   1277:                    BCE_SBTMSTATELOW);
                   1278:                delay(10);
                   1279:                bus_space_write_4(sc->bce_btag, sc->bce_bhandle,
                   1280:                    BCE_SBTMSTATELOW, SBTML_REJ | SBTML_RESET);
                   1281:                delay(1);
                   1282:        }
                   1283:        /* enable clock */
                   1284:        bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_SBTMSTATELOW,
                   1285:            SBTML_FGC | SBTML_CLK | SBTML_RESET);
                   1286:        val = bus_space_read_4(sc->bce_btag, sc->bce_bhandle, BCE_SBTMSTATELOW);
                   1287:        delay(1);
                   1288:
                   1289:        /* clear any error bits that may be on */
                   1290:        val = bus_space_read_4(sc->bce_btag, sc->bce_bhandle, BCE_SBTMSTATEHI);
                   1291:        if (val & 1)
                   1292:                bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_SBTMSTATEHI,
                   1293:                    0);
                   1294:        val = bus_space_read_4(sc->bce_btag, sc->bce_bhandle, BCE_SBIMSTATE);
                   1295:        if (val & SBIM_ERRORBITS)
                   1296:                bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_SBIMSTATE,
                   1297:                    val & ~SBIM_ERRORBITS);
                   1298:
                   1299:        /* clear reset and allow it to propagate throughout the core */
                   1300:        bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_SBTMSTATELOW,
                   1301:            SBTML_FGC | SBTML_CLK);
                   1302:        val = bus_space_read_4(sc->bce_btag, sc->bce_bhandle, BCE_SBTMSTATELOW);
                   1303:        delay(1);
                   1304:
                   1305:        /* leave clock enabled */
                   1306:        bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_SBTMSTATELOW,
                   1307:            SBTML_CLK);
                   1308:        val = bus_space_read_4(sc->bce_btag, sc->bce_bhandle, BCE_SBTMSTATELOW);
                   1309:        delay(1);
                   1310:
                   1311:        /* initialize MDC preamble, frequency */
                   1312:        bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_MI_CTL, 0x8d);     /* MAGIC */
                   1313:
                   1314:        /* enable phy, differs for internal, and external */
                   1315:        val = bus_space_read_4(sc->bce_btag, sc->bce_bhandle, BCE_DEVCTL);
                   1316:        if (!(val & BCE_DC_IP)) {
                   1317:                /* select external phy */
                   1318:                bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_ENET_CTL, EC_EP);
                   1319:        } else if (val & BCE_DC_ER) {   /* internal, clear reset bit if on */
                   1320:                bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_DEVCTL,
                   1321:                    val & ~BCE_DC_ER);
                   1322:                delay(100);
                   1323:        }
                   1324: }
                   1325:
                   1326: /* Set up the receive filter. */
                   1327: void
                   1328: bce_set_filter(struct ifnet *ifp)
                   1329: {
                   1330:        struct bce_softc *sc = ifp->if_softc;
                   1331:
                   1332:        if (ifp->if_flags & IFF_PROMISC) {
                   1333:                ifp->if_flags |= IFF_ALLMULTI;
                   1334:                bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_RX_CTL,
                   1335:                    bus_space_read_4(sc->bce_btag, sc->bce_bhandle, BCE_RX_CTL)
                   1336:                    | ERC_PE);
                   1337:        } else {
                   1338:                ifp->if_flags &= ~IFF_ALLMULTI;
                   1339:
                   1340:                /* turn off promiscuous */
                   1341:                bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_RX_CTL,
                   1342:                    bus_space_read_4(sc->bce_btag, sc->bce_bhandle,
                   1343:                    BCE_RX_CTL) & ~ERC_PE);
                   1344:
                   1345:                /* enable/disable broadcast */
                   1346:                if (ifp->if_flags & IFF_BROADCAST)
                   1347:                        bus_space_write_4(sc->bce_btag, sc->bce_bhandle,
                   1348:                            BCE_RX_CTL, bus_space_read_4(sc->bce_btag,
                   1349:                            sc->bce_bhandle, BCE_RX_CTL) & ~ERC_DB);
                   1350:                else
                   1351:                        bus_space_write_4(sc->bce_btag, sc->bce_bhandle,
                   1352:                            BCE_RX_CTL, bus_space_read_4(sc->bce_btag,
                   1353:                            sc->bce_bhandle, BCE_RX_CTL) | ERC_DB);
                   1354:
                   1355:                /* disable the filter */
                   1356:                bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_FILT_CTL,
                   1357:                    0);
                   1358:
                   1359:                /* add our own address */
                   1360:                bce_add_mac(sc, sc->bce_ac.ac_enaddr, 0);
                   1361:
                   1362:                /* for now accept all multicast */
                   1363:                bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_RX_CTL,
                   1364:                bus_space_read_4(sc->bce_btag, sc->bce_bhandle, BCE_RX_CTL) |
                   1365:                    ERC_AM);
                   1366:                ifp->if_flags |= IFF_ALLMULTI;
                   1367:
                   1368:                /* enable the filter */
                   1369:                bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_FILT_CTL,
                   1370:                    bus_space_read_4(sc->bce_btag, sc->bce_bhandle,
                   1371:                    BCE_FILT_CTL) | 1);
                   1372:        }
                   1373: }
                   1374:
                   1375: /* Read a PHY register on the MII. */
                   1376: int
                   1377: bce_mii_read(struct device *self, int phy, int reg)
                   1378: {
                   1379:        struct bce_softc *sc = (struct bce_softc *) self;
                   1380:        int             i;
                   1381:        u_int32_t val;
                   1382:
                   1383:        /* clear mii_int */
                   1384:        bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_MI_STS, BCE_MIINTR);
                   1385:
                   1386:        /* Read the PHY register */
                   1387:        bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_MI_COMM,
                   1388:            (MII_COMMAND_READ << 28) | (MII_COMMAND_START << 30) |      /* MAGIC */
                   1389:            (MII_COMMAND_ACK << 16) | BCE_MIPHY(phy) | BCE_MIREG(reg)); /* MAGIC */
                   1390:
                   1391:        for (i = 0; i < BCE_TIMEOUT; i++) {
                   1392:                val = bus_space_read_4(sc->bce_btag, sc->bce_bhandle, BCE_MI_STS);
                   1393:                if (val & BCE_MIINTR)
                   1394:                        break;
                   1395:                delay(10);
                   1396:        }
                   1397:        val = bus_space_read_4(sc->bce_btag, sc->bce_bhandle, BCE_MI_COMM);
                   1398:        if (i == BCE_TIMEOUT) {
                   1399:                printf("%s: PHY read timed out reading phy %d, reg %d, val = "
                   1400:                    "0x%08x\n", sc->bce_dev.dv_xname, phy, reg, val);
                   1401:                return (0);
                   1402:        }
                   1403:        return (val & BCE_MICOMM_DATA);
                   1404: }
                   1405:
                   1406: /* Write a PHY register on the MII */
                   1407: void
                   1408: bce_mii_write(struct device *self, int phy, int reg, int val)
                   1409: {
                   1410:        struct bce_softc *sc = (struct bce_softc *) self;
                   1411:        int             i;
                   1412:        u_int32_t rval;
                   1413:
                   1414:        /* clear mii_int */
                   1415:        bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_MI_STS,
                   1416:            BCE_MIINTR);
                   1417:
                   1418:        /* Write the PHY register */
                   1419:        bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_MI_COMM,
                   1420:            (MII_COMMAND_WRITE << 28) | (MII_COMMAND_START << 30) |     /* MAGIC */
                   1421:            (MII_COMMAND_ACK << 16) | (val & BCE_MICOMM_DATA) | /* MAGIC */
                   1422:            BCE_MIPHY(phy) | BCE_MIREG(reg));
                   1423:
                   1424:        /* wait for write to complete */
                   1425:        for (i = 0; i < BCE_TIMEOUT; i++) {
                   1426:                rval = bus_space_read_4(sc->bce_btag, sc->bce_bhandle,
                   1427:                    BCE_MI_STS);
                   1428:                if (rval & BCE_MIINTR)
                   1429:                        break;
                   1430:                delay(10);
                   1431:        }
                   1432:        rval = bus_space_read_4(sc->bce_btag, sc->bce_bhandle, BCE_MI_COMM);
                   1433:        if (i == BCE_TIMEOUT) {
                   1434:                printf("%s: PHY timed out writing phy %d, reg %d, val "
                   1435:                    "= 0x%08x\n", sc->bce_dev.dv_xname, phy, reg, val);
                   1436:        }
                   1437: }
                   1438:
                   1439: /* sync hardware duplex mode to software state */
                   1440: void
                   1441: bce_statchg(struct device *self)
                   1442: {
                   1443:        struct bce_softc *sc = (struct bce_softc *) self;
                   1444:        u_int32_t reg;
                   1445:
                   1446:        /* if needed, change register to match duplex mode */
                   1447:        reg = bus_space_read_4(sc->bce_btag, sc->bce_bhandle, BCE_TX_CTL);
                   1448:        if (sc->bce_mii.mii_media_active & IFM_FDX && !(reg & EXC_FD))
                   1449:                bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_TX_CTL,
                   1450:                    reg | EXC_FD);
                   1451:        else if (!(sc->bce_mii.mii_media_active & IFM_FDX) && reg & EXC_FD)
                   1452:                bus_space_write_4(sc->bce_btag, sc->bce_bhandle, BCE_TX_CTL,
                   1453:                    reg & ~EXC_FD);
                   1454:
                   1455:        /*
                   1456:          * Enable activity led.
                   1457:          * XXX This should be in a phy driver, but not currently.
                   1458:          */
                   1459:        bce_mii_write((struct device *) sc, 1, 26,      /* MAGIC */
                   1460:            bce_mii_read((struct device *) sc, 1, 26) & 0x7fff);        /* MAGIC */
                   1461:        /* enable traffic meter led mode */
                   1462:        bce_mii_write((struct device *) sc, 1, 26,      /* MAGIC */
                   1463:            bce_mii_read((struct device *) sc, 1, 27) | (1 << 6));      /* MAGIC */
                   1464: }
                   1465:
                   1466: /* Set hardware to newly-selected media */
                   1467: int
                   1468: bce_mediachange(struct ifnet *ifp)
                   1469: {
                   1470:        struct bce_softc *sc = ifp->if_softc;
                   1471:
                   1472:        if (ifp->if_flags & IFF_UP)
                   1473:                mii_mediachg(&sc->bce_mii);
                   1474:        return (0);
                   1475: }
                   1476:
                   1477: /* Get the current interface media status */
                   1478: void
                   1479: bce_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr)
                   1480: {
                   1481:        struct bce_softc *sc = ifp->if_softc;
                   1482:
                   1483:        mii_pollstat(&sc->bce_mii);
                   1484:        ifmr->ifm_active = sc->bce_mii.mii_media_active;
                   1485:        ifmr->ifm_status = sc->bce_mii.mii_media_status;
                   1486: }
                   1487:
                   1488: /* One second timer, checks link status */
                   1489: void
                   1490: bce_tick(void *v)
                   1491: {
                   1492:        struct bce_softc *sc = v;
                   1493:
                   1494:        /* Tick the MII. */
                   1495:        mii_tick(&sc->bce_mii);
                   1496:
                   1497:        timeout_add(&sc->bce_timeout, hz);
                   1498: }

CVSweb