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

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

1.1       nbrk        1: /*     $OpenBSD: if_wb.c,v 1.38 2007/05/26 00:36:03 krw Exp $  */
                      2:
                      3: /*
                      4:  * Copyright (c) 1997, 1998
                      5:  *     Bill Paul <wpaul@ctr.columbia.edu>.  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. All advertising materials mentioning features or use of this software
                     16:  *    must display the following acknowledgement:
                     17:  *     This product includes software developed by Bill Paul.
                     18:  * 4. Neither the name of the author nor the names of any co-contributors
                     19:  *    may be used to endorse or promote products derived from this software
                     20:  *    without specific prior written permission.
                     21:  *
                     22:  * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
                     23:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     24:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     25:  * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
                     26:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     27:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     28:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     29:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     30:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     31:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
                     32:  * THE POSSIBILITY OF SUCH DAMAGE.
                     33:  *
                     34:  * $FreeBSD: src/sys/pci/if_wb.c,v 1.26 1999/09/25 17:29:02 wpaul Exp $
                     35:  */
                     36:
                     37: /*
                     38:  * Winbond fast ethernet PCI NIC driver
                     39:  *
                     40:  * Supports various cheap network adapters based on the Winbond W89C840F
                     41:  * fast ethernet controller chip. This includes adapters manufactured by
                     42:  * Winbond itself and some made by Linksys.
                     43:  *
                     44:  * Written by Bill Paul <wpaul@ctr.columbia.edu>
                     45:  * Electrical Engineering Department
                     46:  * Columbia University, New York City
                     47:  */
                     48:
                     49: /*
                     50:  * The Winbond W89C840F chip is a bus master; in some ways it resembles
                     51:  * a DEC 'tulip' chip, only not as complicated. Unfortunately, it has
                     52:  * one major difference which is that while the registers do many of
                     53:  * the same things as a tulip adapter, the offsets are different: where
                     54:  * tulip registers are typically spaced 8 bytes apart, the Winbond
                     55:  * registers are spaced 4 bytes apart. The receiver filter is also
                     56:  * programmed differently.
                     57:  *
                     58:  * Like the tulip, the Winbond chip uses small descriptors containing
                     59:  * a status word, a control word and 32-bit areas that can either be used
                     60:  * to point to two external data blocks, or to point to a single block
                     61:  * and another descriptor in a linked list. Descriptors can be grouped
                     62:  * together in blocks to form fixed length rings or can be chained
                     63:  * together in linked lists. A single packet may be spread out over
                     64:  * several descriptors if necessary.
                     65:  *
                     66:  * For the receive ring, this driver uses a linked list of descriptors,
                     67:  * each pointing to a single mbuf cluster buffer, which us large enough
                     68:  * to hold an entire packet. The link list is looped back to created a
                     69:  * closed ring.
                     70:  *
                     71:  * For transmission, the driver creates a linked list of 'super descriptors'
                     72:  * which each contain several individual descriptors linked together.
                     73:  * Each 'super descriptor' contains WB_MAXFRAGS descriptors, which we
                     74:  * abuse as fragment pointers. This allows us to use a buffer management
                     75:  * scheme very similar to that used in the ThunderLAN and Etherlink XL
                     76:  * drivers.
                     77:  *
                     78:  * Autonegotiation is performed using the external PHY via the MII bus.
                     79:  * The sample boards I have all use a Davicom PHY.
                     80:  *
                     81:  * Note: the author of the Linux driver for the Winbond chip alludes
                     82:  * to some sort of flaw in the chip's design that seems to mandate some
                     83:  * drastic workaround which significantly impairs transmit performance.
                     84:  * I have no idea what he's on about: transmit performance with all
                     85:  * three of my test boards seems fine.
                     86:  */
                     87:
                     88: #include "bpfilter.h"
                     89:
                     90: #include <sys/param.h>
                     91: #include <sys/systm.h>
                     92: #include <sys/sockio.h>
                     93: #include <sys/mbuf.h>
                     94: #include <sys/malloc.h>
                     95: #include <sys/kernel.h>
                     96: #include <sys/socket.h>
                     97: #include <sys/device.h>
                     98: #include <sys/queue.h>
                     99: #include <sys/timeout.h>
                    100:
                    101: #include <net/if.h>
                    102: #include <net/if_dl.h>
                    103: #include <net/if_types.h>
                    104:
                    105: #ifdef INET
                    106: #include <netinet/in.h>
                    107: #include <netinet/in_systm.h>
                    108: #include <netinet/in_var.h>
                    109: #include <netinet/ip.h>
                    110: #include <netinet/if_ether.h>
                    111: #endif
                    112:
                    113: #include <net/if_media.h>
                    114:
                    115: #if NBPFILTER > 0
                    116: #include <net/bpf.h>
                    117: #endif
                    118:
                    119: #include <uvm/uvm_extern.h>            /* for vtophys */
                    120: #define        VTOPHYS(v)      vtophys((vaddr_t)(v))
                    121:
                    122: #include <dev/mii/mii.h>
                    123: #include <dev/mii/miivar.h>
                    124: #include <dev/pci/pcireg.h>
                    125: #include <dev/pci/pcivar.h>
                    126: #include <dev/pci/pcidevs.h>
                    127:
                    128: #define WB_USEIOSPACE
                    129:
                    130: /* #define WB_BACKGROUND_AUTONEG */
                    131:
                    132: #include <dev/pci/if_wbreg.h>
                    133:
                    134: int wb_probe(struct device *, void *, void *);
                    135: void wb_attach(struct device *, struct device *, void *);
                    136:
                    137: void wb_bfree(caddr_t, u_int, void *);
                    138: int wb_newbuf(struct wb_softc *, struct wb_chain_onefrag *,
                    139:     struct mbuf *);
                    140: int wb_encap(struct wb_softc *, struct wb_chain *,
                    141:     struct mbuf *);
                    142:
                    143: void wb_rxeof(struct wb_softc *);
                    144: void wb_rxeoc(struct wb_softc *);
                    145: void wb_txeof(struct wb_softc *);
                    146: void wb_txeoc(struct wb_softc *);
                    147: int wb_intr(void *);
                    148: void wb_tick(void *);
                    149: void wb_start(struct ifnet *);
                    150: int wb_ioctl(struct ifnet *, u_long, caddr_t);
                    151: void wb_init(void *);
                    152: void wb_stop(struct wb_softc *);
                    153: void wb_watchdog(struct ifnet *);
                    154: void wb_shutdown(void *);
                    155: int wb_ifmedia_upd(struct ifnet *);
                    156: void wb_ifmedia_sts(struct ifnet *, struct ifmediareq *);
                    157:
                    158: void wb_eeprom_putbyte(struct wb_softc *, int);
                    159: void wb_eeprom_getword(struct wb_softc *, int, u_int16_t *);
                    160: void wb_read_eeprom(struct wb_softc *, caddr_t, int, int, int);
                    161: void wb_mii_sync(struct wb_softc *);
                    162: void wb_mii_send(struct wb_softc *, u_int32_t, int);
                    163: int wb_mii_readreg(struct wb_softc *, struct wb_mii_frame *);
                    164: int wb_mii_writereg(struct wb_softc *, struct wb_mii_frame *);
                    165:
                    166: void wb_setcfg(struct wb_softc *, u_int32_t);
                    167: u_int8_t wb_calchash(caddr_t);
                    168: void wb_setmulti(struct wb_softc *);
                    169: void wb_reset(struct wb_softc *);
                    170: void wb_fixmedia(struct wb_softc *);
                    171: int wb_list_rx_init(struct wb_softc *);
                    172: int wb_list_tx_init(struct wb_softc *);
                    173:
                    174: int wb_miibus_readreg(struct device *, int, int);
                    175: void wb_miibus_writereg(struct device *, int, int, int);
                    176: void wb_miibus_statchg(struct device *);
                    177:
                    178: #define WB_SETBIT(sc, reg, x)                          \
                    179:        CSR_WRITE_4(sc, reg,                            \
                    180:                CSR_READ_4(sc, reg) | x)
                    181:
                    182: #define WB_CLRBIT(sc, reg, x)                          \
                    183:        CSR_WRITE_4(sc, reg,                            \
                    184:                CSR_READ_4(sc, reg) & ~x)
                    185:
                    186: #define SIO_SET(x)                                     \
                    187:        CSR_WRITE_4(sc, WB_SIO,                         \
                    188:                CSR_READ_4(sc, WB_SIO) | x)
                    189:
                    190: #define SIO_CLR(x)                                     \
                    191:        CSR_WRITE_4(sc, WB_SIO,                         \
                    192:                CSR_READ_4(sc, WB_SIO) & ~x)
                    193:
                    194: /*
                    195:  * Send a read command and address to the EEPROM, check for ACK.
                    196:  */
                    197: void wb_eeprom_putbyte(sc, addr)
                    198:        struct wb_softc         *sc;
                    199:        int                     addr;
                    200: {
                    201:        int                     d, i;
                    202:
                    203:        d = addr | WB_EECMD_READ;
                    204:
                    205:        /*
                    206:         * Feed in each bit and strobe the clock.
                    207:         */
                    208:        for (i = 0x400; i; i >>= 1) {
                    209:                if (d & i) {
                    210:                        SIO_SET(WB_SIO_EE_DATAIN);
                    211:                } else {
                    212:                        SIO_CLR(WB_SIO_EE_DATAIN);
                    213:                }
                    214:                DELAY(100);
                    215:                SIO_SET(WB_SIO_EE_CLK);
                    216:                DELAY(150);
                    217:                SIO_CLR(WB_SIO_EE_CLK);
                    218:                DELAY(100);
                    219:        }
                    220:
                    221:        return;
                    222: }
                    223:
                    224: /*
                    225:  * Read a word of data stored in the EEPROM at address 'addr.'
                    226:  */
                    227: void wb_eeprom_getword(sc, addr, dest)
                    228:        struct wb_softc         *sc;
                    229:        int                     addr;
                    230:        u_int16_t               *dest;
                    231: {
                    232:        int                     i;
                    233:        u_int16_t               word = 0;
                    234:
                    235:        /* Enter EEPROM access mode. */
                    236:        CSR_WRITE_4(sc, WB_SIO, WB_SIO_EESEL|WB_SIO_EE_CS);
                    237:
                    238:        /*
                    239:         * Send address of word we want to read.
                    240:         */
                    241:        wb_eeprom_putbyte(sc, addr);
                    242:
                    243:        CSR_WRITE_4(sc, WB_SIO, WB_SIO_EESEL|WB_SIO_EE_CS);
                    244:
                    245:        /*
                    246:         * Start reading bits from EEPROM.
                    247:         */
                    248:        for (i = 0x8000; i; i >>= 1) {
                    249:                SIO_SET(WB_SIO_EE_CLK);
                    250:                DELAY(100);
                    251:                if (CSR_READ_4(sc, WB_SIO) & WB_SIO_EE_DATAOUT)
                    252:                        word |= i;
                    253:                SIO_CLR(WB_SIO_EE_CLK);
                    254:                DELAY(100);
                    255:        }
                    256:
                    257:        /* Turn off EEPROM access mode. */
                    258:        CSR_WRITE_4(sc, WB_SIO, 0);
                    259:
                    260:        *dest = word;
                    261:
                    262:        return;
                    263: }
                    264:
                    265: /*
                    266:  * Read a sequence of words from the EEPROM.
                    267:  */
                    268: void wb_read_eeprom(sc, dest, off, cnt, swap)
                    269:        struct wb_softc         *sc;
                    270:        caddr_t                 dest;
                    271:        int                     off;
                    272:        int                     cnt;
                    273:        int                     swap;
                    274: {
                    275:        int                     i;
                    276:        u_int16_t               word = 0, *ptr;
                    277:
                    278:        for (i = 0; i < cnt; i++) {
                    279:                wb_eeprom_getword(sc, off + i, &word);
                    280:                ptr = (u_int16_t *)(dest + (i * 2));
                    281:                if (swap)
                    282:                        *ptr = ntohs(word);
                    283:                else
                    284:                        *ptr = word;
                    285:        }
                    286:
                    287:        return;
                    288: }
                    289:
                    290: /*
                    291:  * Sync the PHYs by setting data bit and strobing the clock 32 times.
                    292:  */
                    293: void wb_mii_sync(sc)
                    294:        struct wb_softc         *sc;
                    295: {
                    296:        int                     i;
                    297:
                    298:        SIO_SET(WB_SIO_MII_DIR|WB_SIO_MII_DATAIN);
                    299:
                    300:        for (i = 0; i < 32; i++) {
                    301:                SIO_SET(WB_SIO_MII_CLK);
                    302:                DELAY(1);
                    303:                SIO_CLR(WB_SIO_MII_CLK);
                    304:                DELAY(1);
                    305:        }
                    306:
                    307:        return;
                    308: }
                    309:
                    310: /*
                    311:  * Clock a series of bits through the MII.
                    312:  */
                    313: void wb_mii_send(sc, bits, cnt)
                    314:        struct wb_softc         *sc;
                    315:        u_int32_t               bits;
                    316:        int                     cnt;
                    317: {
                    318:        int                     i;
                    319:
                    320:        SIO_CLR(WB_SIO_MII_CLK);
                    321:
                    322:        for (i = (0x1 << (cnt - 1)); i; i >>= 1) {
                    323:                 if (bits & i) {
                    324:                        SIO_SET(WB_SIO_MII_DATAIN);
                    325:                 } else {
                    326:                        SIO_CLR(WB_SIO_MII_DATAIN);
                    327:                 }
                    328:                DELAY(1);
                    329:                SIO_CLR(WB_SIO_MII_CLK);
                    330:                DELAY(1);
                    331:                SIO_SET(WB_SIO_MII_CLK);
                    332:        }
                    333: }
                    334:
                    335: /*
                    336:  * Read an PHY register through the MII.
                    337:  */
                    338: int wb_mii_readreg(sc, frame)
                    339:        struct wb_softc         *sc;
                    340:        struct wb_mii_frame     *frame;
                    341:
                    342: {
                    343:        int                     i, ack, s;
                    344:
                    345:        s = splnet();
                    346:
                    347:        /*
                    348:         * Set up frame for RX.
                    349:         */
                    350:        frame->mii_stdelim = WB_MII_STARTDELIM;
                    351:        frame->mii_opcode = WB_MII_READOP;
                    352:        frame->mii_turnaround = 0;
                    353:        frame->mii_data = 0;
                    354:
                    355:        CSR_WRITE_4(sc, WB_SIO, 0);
                    356:
                    357:        /*
                    358:         * Turn on data xmit.
                    359:         */
                    360:        SIO_SET(WB_SIO_MII_DIR);
                    361:
                    362:        wb_mii_sync(sc);
                    363:
                    364:        /*
                    365:         * Send command/address info.
                    366:         */
                    367:        wb_mii_send(sc, frame->mii_stdelim, 2);
                    368:        wb_mii_send(sc, frame->mii_opcode, 2);
                    369:        wb_mii_send(sc, frame->mii_phyaddr, 5);
                    370:        wb_mii_send(sc, frame->mii_regaddr, 5);
                    371:
                    372:        /* Idle bit */
                    373:        SIO_CLR((WB_SIO_MII_CLK|WB_SIO_MII_DATAIN));
                    374:        DELAY(1);
                    375:        SIO_SET(WB_SIO_MII_CLK);
                    376:        DELAY(1);
                    377:
                    378:        /* Turn off xmit. */
                    379:        SIO_CLR(WB_SIO_MII_DIR);
                    380:        /* Check for ack */
                    381:        SIO_CLR(WB_SIO_MII_CLK);
                    382:        DELAY(1);
                    383:        ack = CSR_READ_4(sc, WB_SIO) & WB_SIO_MII_DATAOUT;
                    384:        SIO_SET(WB_SIO_MII_CLK);
                    385:        DELAY(1);
                    386:        SIO_CLR(WB_SIO_MII_CLK);
                    387:        DELAY(1);
                    388:        SIO_SET(WB_SIO_MII_CLK);
                    389:        DELAY(1);
                    390:
                    391:        /*
                    392:         * Now try reading data bits. If the ack failed, we still
                    393:         * need to clock through 16 cycles to keep the PHY(s) in sync.
                    394:         */
                    395:        if (ack) {
                    396:                for(i = 0; i < 16; i++) {
                    397:                        SIO_CLR(WB_SIO_MII_CLK);
                    398:                        DELAY(1);
                    399:                        SIO_SET(WB_SIO_MII_CLK);
                    400:                        DELAY(1);
                    401:                }
                    402:                goto fail;
                    403:        }
                    404:
                    405:        for (i = 0x8000; i; i >>= 1) {
                    406:                SIO_CLR(WB_SIO_MII_CLK);
                    407:                DELAY(1);
                    408:                if (!ack) {
                    409:                        if (CSR_READ_4(sc, WB_SIO) & WB_SIO_MII_DATAOUT)
                    410:                                frame->mii_data |= i;
                    411:                        DELAY(1);
                    412:                }
                    413:                SIO_SET(WB_SIO_MII_CLK);
                    414:                DELAY(1);
                    415:        }
                    416:
                    417: fail:
                    418:
                    419:        SIO_CLR(WB_SIO_MII_CLK);
                    420:        DELAY(1);
                    421:        SIO_SET(WB_SIO_MII_CLK);
                    422:        DELAY(1);
                    423:
                    424:        splx(s);
                    425:
                    426:        if (ack)
                    427:                return(1);
                    428:        return(0);
                    429: }
                    430:
                    431: /*
                    432:  * Write to a PHY register through the MII.
                    433:  */
                    434: int wb_mii_writereg(sc, frame)
                    435:        struct wb_softc         *sc;
                    436:        struct wb_mii_frame     *frame;
                    437:
                    438: {
                    439:        int                     s;
                    440:
                    441:        s = splnet();
                    442:        /*
                    443:         * Set up frame for TX.
                    444:         */
                    445:
                    446:        frame->mii_stdelim = WB_MII_STARTDELIM;
                    447:        frame->mii_opcode = WB_MII_WRITEOP;
                    448:        frame->mii_turnaround = WB_MII_TURNAROUND;
                    449:
                    450:        /*
                    451:         * Turn on data output.
                    452:         */
                    453:        SIO_SET(WB_SIO_MII_DIR);
                    454:
                    455:        wb_mii_sync(sc);
                    456:
                    457:        wb_mii_send(sc, frame->mii_stdelim, 2);
                    458:        wb_mii_send(sc, frame->mii_opcode, 2);
                    459:        wb_mii_send(sc, frame->mii_phyaddr, 5);
                    460:        wb_mii_send(sc, frame->mii_regaddr, 5);
                    461:        wb_mii_send(sc, frame->mii_turnaround, 2);
                    462:        wb_mii_send(sc, frame->mii_data, 16);
                    463:
                    464:        /* Idle bit. */
                    465:        SIO_SET(WB_SIO_MII_CLK);
                    466:        DELAY(1);
                    467:        SIO_CLR(WB_SIO_MII_CLK);
                    468:        DELAY(1);
                    469:
                    470:        /*
                    471:         * Turn off xmit.
                    472:         */
                    473:        SIO_CLR(WB_SIO_MII_DIR);
                    474:
                    475:        splx(s);
                    476:
                    477:        return(0);
                    478: }
                    479:
                    480: int
                    481: wb_miibus_readreg(dev, phy, reg)
                    482:        struct device *dev;
                    483:        int phy, reg;
                    484: {
                    485:        struct wb_softc *sc = (struct wb_softc *)dev;
                    486:        struct wb_mii_frame frame;
                    487:
                    488:        bzero((char *)&frame, sizeof(frame));
                    489:
                    490:        frame.mii_phyaddr = phy;
                    491:        frame.mii_regaddr = reg;
                    492:        wb_mii_readreg(sc, &frame);
                    493:
                    494:        return(frame.mii_data);
                    495: }
                    496:
                    497: void
                    498: wb_miibus_writereg(dev, phy, reg, data)
                    499:        struct device *dev;
                    500:        int phy, reg, data;
                    501: {
                    502:        struct wb_softc *sc = (struct wb_softc *)dev;
                    503:        struct wb_mii_frame frame;
                    504:
                    505:        bzero((char *)&frame, sizeof(frame));
                    506:
                    507:        frame.mii_phyaddr = phy;
                    508:        frame.mii_regaddr = reg;
                    509:        frame.mii_data = data;
                    510:
                    511:        wb_mii_writereg(sc, &frame);
                    512:
                    513:        return;
                    514: }
                    515:
                    516: void
                    517: wb_miibus_statchg(dev)
                    518:        struct device *dev;
                    519: {
                    520:        struct wb_softc *sc = (struct wb_softc *)dev;
                    521:
                    522:        wb_setcfg(sc, sc->sc_mii.mii_media_active);
                    523: }
                    524:
                    525: /*
                    526:  * Program the 64-bit multicast hash filter.
                    527:  */
                    528: void wb_setmulti(sc)
                    529:        struct wb_softc         *sc;
                    530: {
                    531:        struct ifnet            *ifp;
                    532:        int                     h = 0;
                    533:        u_int32_t               hashes[2] = { 0, 0 };
                    534:        struct arpcom           *ac = &sc->arpcom;
                    535:        struct ether_multi      *enm;
                    536:        struct ether_multistep  step;
                    537:        u_int32_t               rxfilt;
                    538:        int                     mcnt = 0;
                    539:
                    540:        ifp = &sc->arpcom.ac_if;
                    541:
                    542:        rxfilt = CSR_READ_4(sc, WB_NETCFG);
                    543:
                    544: allmulti:
                    545:        if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) {
                    546:                rxfilt |= WB_NETCFG_RX_MULTI;
                    547:                CSR_WRITE_4(sc, WB_NETCFG, rxfilt);
                    548:                CSR_WRITE_4(sc, WB_MAR0, 0xFFFFFFFF);
                    549:                CSR_WRITE_4(sc, WB_MAR1, 0xFFFFFFFF);
                    550:                return;
                    551:        }
                    552:
                    553:        /* first, zot all the existing hash bits */
                    554:        CSR_WRITE_4(sc, WB_MAR0, 0);
                    555:        CSR_WRITE_4(sc, WB_MAR1, 0);
                    556:
                    557:        /* now program new ones */
                    558:        ETHER_FIRST_MULTI(step, ac, enm);
                    559:        while (enm != NULL) {
                    560:                if (bcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) {
                    561:                        ifp->if_flags |= IFF_ALLMULTI;
                    562:                        goto allmulti;
                    563:                }
                    564:                h = ~(ether_crc32_be(enm->enm_addrlo, ETHER_ADDR_LEN) >> 26);
                    565:                if (h < 32)
                    566:                        hashes[0] |= (1 << h);
                    567:                else
                    568:                        hashes[1] |= (1 << (h - 32));
                    569:                mcnt++;
                    570:                ETHER_NEXT_MULTI(step, enm);
                    571:        }
                    572:
                    573:        if (mcnt)
                    574:                rxfilt |= WB_NETCFG_RX_MULTI;
                    575:        else
                    576:                rxfilt &= ~WB_NETCFG_RX_MULTI;
                    577:
                    578:        CSR_WRITE_4(sc, WB_MAR0, hashes[0]);
                    579:        CSR_WRITE_4(sc, WB_MAR1, hashes[1]);
                    580:        CSR_WRITE_4(sc, WB_NETCFG, rxfilt);
                    581:
                    582:        return;
                    583: }
                    584:
                    585: /*
                    586:  * The Winbond manual states that in order to fiddle with the
                    587:  * 'full-duplex' and '100Mbps' bits in the netconfig register, we
                    588:  * first have to put the transmit and/or receive logic in the idle state.
                    589:  */
                    590: void
                    591: wb_setcfg(sc, media)
                    592:        struct wb_softc *sc;
                    593:        u_int32_t media;
                    594: {
                    595:        int                     i, restart = 0;
                    596:
                    597:        if (CSR_READ_4(sc, WB_NETCFG) & (WB_NETCFG_TX_ON|WB_NETCFG_RX_ON)) {
                    598:                restart = 1;
                    599:                WB_CLRBIT(sc, WB_NETCFG, (WB_NETCFG_TX_ON|WB_NETCFG_RX_ON));
                    600:
                    601:                for (i = 0; i < WB_TIMEOUT; i++) {
                    602:                        DELAY(10);
                    603:                        if ((CSR_READ_4(sc, WB_ISR) & WB_ISR_TX_IDLE) &&
                    604:                                (CSR_READ_4(sc, WB_ISR) & WB_ISR_RX_IDLE))
                    605:                                break;
                    606:                }
                    607:
                    608:                if (i == WB_TIMEOUT)
                    609:                        printf("%s: failed to force tx and "
                    610:                                "rx to idle state\n", sc->sc_dev.dv_xname);
                    611:        }
                    612:
                    613:        if (IFM_SUBTYPE(media) == IFM_10_T)
                    614:                WB_CLRBIT(sc, WB_NETCFG, WB_NETCFG_100MBPS);
                    615:        else
                    616:                WB_SETBIT(sc, WB_NETCFG, WB_NETCFG_100MBPS);
                    617:
                    618:        if ((media & IFM_GMASK) == IFM_FDX)
                    619:                WB_SETBIT(sc, WB_NETCFG, WB_NETCFG_FULLDUPLEX);
                    620:        else
                    621:                WB_CLRBIT(sc, WB_NETCFG, WB_NETCFG_FULLDUPLEX);
                    622:
                    623:        if (restart)
                    624:                WB_SETBIT(sc, WB_NETCFG, WB_NETCFG_TX_ON|WB_NETCFG_RX_ON);
                    625:
                    626:        return;
                    627: }
                    628:
                    629: void
                    630: wb_reset(sc)
                    631:        struct wb_softc *sc;
                    632: {
                    633:        int i;
                    634:        struct mii_data *mii = &sc->sc_mii;
                    635:
                    636:        CSR_WRITE_4(sc, WB_NETCFG, 0);
                    637:        CSR_WRITE_4(sc, WB_BUSCTL, 0);
                    638:        CSR_WRITE_4(sc, WB_TXADDR, 0);
                    639:        CSR_WRITE_4(sc, WB_RXADDR, 0);
                    640:
                    641:        WB_SETBIT(sc, WB_BUSCTL, WB_BUSCTL_RESET);
                    642:        WB_SETBIT(sc, WB_BUSCTL, WB_BUSCTL_RESET);
                    643:
                    644:        for (i = 0; i < WB_TIMEOUT; i++) {
                    645:                DELAY(10);
                    646:                if (!(CSR_READ_4(sc, WB_BUSCTL) & WB_BUSCTL_RESET))
                    647:                        break;
                    648:        }
                    649:        if (i == WB_TIMEOUT)
                    650:                printf("%s: reset never completed!\n", sc->sc_dev.dv_xname);
                    651:
                    652:        /* Wait a little while for the chip to get its brains in order. */
                    653:        DELAY(1000);
                    654:
                    655:        if (mii->mii_instance) {
                    656:                struct mii_softc *miisc;
                    657:                LIST_FOREACH(miisc, &mii->mii_phys, mii_list)
                    658:                        mii_phy_reset(miisc);
                    659:        }
                    660: }
                    661:
                    662: void
                    663: wb_fixmedia(sc)
                    664:        struct wb_softc *sc;
                    665: {
                    666:        struct mii_data *mii = &sc->sc_mii;
                    667:        u_int32_t media;
                    668:
                    669:        if (LIST_FIRST(&mii->mii_phys) == NULL)
                    670:                return;
                    671:
                    672:        mii_pollstat(mii);
                    673:        if (IFM_SUBTYPE(mii->mii_media_active) == IFM_10_T) {
                    674:                media = mii->mii_media_active & ~IFM_10_T;
                    675:                media |= IFM_100_TX;
                    676:        } if (IFM_SUBTYPE(mii->mii_media_active) == IFM_100_TX) {
                    677:                media = mii->mii_media_active & ~IFM_100_TX;
                    678:                media |= IFM_10_T;
                    679:        } else
                    680:                return;
                    681:
                    682:        ifmedia_set(&mii->mii_media, media);
                    683: }
                    684:
                    685: const struct pci_matchid wb_devices[] = {
                    686:        { PCI_VENDOR_WINBOND, PCI_PRODUCT_WINBOND_W89C840F },
                    687:        { PCI_VENDOR_COMPEX, PCI_PRODUCT_COMPEX_RL100ATX },
                    688: };
                    689:
                    690: /*
                    691:  * Probe for a Winbond chip. Check the PCI vendor and device
                    692:  * IDs against our list and return a device name if we find a match.
                    693:  */
                    694: int
                    695: wb_probe(parent, match, aux)
                    696:        struct device *parent;
                    697:        void *match, *aux;
                    698: {
                    699:        return (pci_matchbyid((struct pci_attach_args *)aux, wb_devices,
                    700:            sizeof(wb_devices)/sizeof(wb_devices[0])));
                    701: }
                    702:
                    703: /*
                    704:  * Attach the interface. Allocate softc structures, do ifmedia
                    705:  * setup and ethernet/BPF attach.
                    706:  */
                    707: void
                    708: wb_attach(parent, self, aux)
                    709:        struct device *parent, *self;
                    710:        void *aux;
                    711: {
                    712:        struct wb_softc *sc = (struct wb_softc *)self;
                    713:        struct pci_attach_args *pa = aux;
                    714:        pci_chipset_tag_t pc = pa->pa_pc;
                    715:        pci_intr_handle_t ih;
                    716:        const char *intrstr = NULL;
                    717:        struct ifnet *ifp = &sc->arpcom.ac_if;
                    718:        bus_size_t size;
                    719:        int rseg;
                    720:        pcireg_t command;
                    721:        bus_dma_segment_t seg;
                    722:        bus_dmamap_t dmamap;
                    723:        caddr_t kva;
                    724:
                    725:        /*
                    726:         * Handle power management nonsense.
                    727:         */
                    728:
                    729:        command = pci_conf_read(pc, pa->pa_tag, WB_PCI_CAPID) & 0x000000FF;
                    730:        if (command == 0x01) {
                    731:
                    732:                command = pci_conf_read(pc, pa->pa_tag, WB_PCI_PWRMGMTCTRL);
                    733:                if (command & WB_PSTATE_MASK) {
                    734:                        u_int32_t               io, mem, irq;
                    735:
                    736:                        /* Save important PCI config data. */
                    737:                        io = pci_conf_read(pc, pa->pa_tag, WB_PCI_LOIO);
                    738:                        mem = pci_conf_read(pc, pa->pa_tag, WB_PCI_LOMEM);
                    739:                        irq = pci_conf_read(pc, pa->pa_tag, WB_PCI_INTLINE);
                    740:
                    741:                        /* Reset the power state. */
                    742:                        printf("%s: chip is in D%d power mode "
                    743:                            "-- setting to D0\n", sc->sc_dev.dv_xname,
                    744:                            command & WB_PSTATE_MASK);
                    745:                        command &= 0xFFFFFFFC;
                    746:                        pci_conf_write(pc, pa->pa_tag, WB_PCI_PWRMGMTCTRL,
                    747:                            command);
                    748:
                    749:                        /* Restore PCI config data. */
                    750:                        pci_conf_write(pc, pa->pa_tag, WB_PCI_LOIO, io);
                    751:                        pci_conf_write(pc, pa->pa_tag, WB_PCI_LOMEM, mem);
                    752:                        pci_conf_write(pc, pa->pa_tag, WB_PCI_INTLINE, irq);
                    753:                }
                    754:        }
                    755:
                    756:        /*
                    757:         * Map control/status registers.
                    758:         */
                    759:
                    760: #ifdef WB_USEIOSPACE
                    761:        if (pci_mapreg_map(pa, WB_PCI_LOIO, PCI_MAPREG_TYPE_IO, 0,
                    762:            &sc->wb_btag, &sc->wb_bhandle, NULL, &size, 0)) {
                    763:                printf(": can't map i/o space\n");
                    764:                return;
                    765:        }
                    766: #else
                    767:        if (pci_mapreg_map(pa, WB_PCI_LOMEM, PCI_MAPREG_TYPE_MEM, 0,
                    768:            &sc->wb_btag, &sc->wb_bhandle, NULL, &size, 0)){
                    769:                printf(": can't map mem space\n");
                    770:                return;
                    771:        }
                    772: #endif
                    773:
                    774:        /* Allocate interrupt */
                    775:        if (pci_intr_map(pa, &ih)) {
                    776:                printf(": couldn't map interrupt\n");
                    777:                goto fail_1;
                    778:        }
                    779:        intrstr = pci_intr_string(pc, ih);
                    780:        sc->sc_ih = pci_intr_establish(pc, ih, IPL_NET, wb_intr, sc,
                    781:            self->dv_xname);
                    782:        if (sc->sc_ih == NULL) {
                    783:                printf(": couldn't establish interrupt");
                    784:                if (intrstr != NULL)
                    785:                        printf(" at %s", intrstr);
                    786:                printf("\n");
                    787:                goto fail_1;
                    788:        }
                    789:        printf(": %s", intrstr);
                    790:
                    791:        sc->wb_cachesize = pci_conf_read(pc, pa->pa_tag, WB_PCI_CACHELEN)&0xff;
                    792:
                    793:        /* Reset the adapter. */
                    794:        wb_reset(sc);
                    795:
                    796:        /*
                    797:         * Get station address from the EEPROM.
                    798:         */
                    799:        wb_read_eeprom(sc, (caddr_t)&sc->arpcom.ac_enaddr, 0, 3, 0);
                    800:        printf(", address %s\n", ether_sprintf(sc->arpcom.ac_enaddr));
                    801:
                    802:        if (bus_dmamem_alloc(pa->pa_dmat, sizeof(struct wb_list_data),
                    803:            PAGE_SIZE, 0, &seg, 1, &rseg, BUS_DMA_NOWAIT)) {
                    804:                printf(": can't alloc list data\n");
                    805:                goto fail_2;
                    806:        }
                    807:        if (bus_dmamem_map(pa->pa_dmat, &seg, rseg,
                    808:            sizeof(struct wb_list_data), &kva, BUS_DMA_NOWAIT)) {
                    809:                printf(": can't map list data, size %d\n",
                    810:                    sizeof(struct wb_list_data));
                    811:                goto fail_3;
                    812:        }
                    813:        if (bus_dmamap_create(pa->pa_dmat, sizeof(struct wb_list_data), 1,
                    814:            sizeof(struct wb_list_data), 0, BUS_DMA_NOWAIT, &dmamap)) {
                    815:                printf(": can't create dma map\n");
                    816:                goto fail_4;
                    817:        }
                    818:        if (bus_dmamap_load(pa->pa_dmat, dmamap, kva,
                    819:            sizeof(struct wb_list_data), NULL, BUS_DMA_NOWAIT)) {
                    820:                printf(": can't load dma map\n");
                    821:                goto fail_5;
                    822:        }
                    823:        sc->wb_ldata = (struct wb_list_data *)kva;
                    824:        bzero(sc->wb_ldata, sizeof(struct wb_list_data));
                    825:
                    826:        ifp->if_softc = sc;
                    827:        ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
                    828:        ifp->if_ioctl = wb_ioctl;
                    829:        ifp->if_start = wb_start;
                    830:        ifp->if_watchdog = wb_watchdog;
                    831:        ifp->if_baudrate = 10000000;
                    832:        IFQ_SET_MAXLEN(&ifp->if_snd, WB_TX_LIST_CNT - 1);
                    833:        IFQ_SET_READY(&ifp->if_snd);
                    834:
                    835:        bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
                    836:
                    837:        /*
                    838:         * Do ifmedia setup.
                    839:         */
                    840:        wb_stop(sc);
                    841:
                    842:        ifmedia_init(&sc->sc_mii.mii_media, 0, wb_ifmedia_upd, wb_ifmedia_sts);
                    843:        sc->sc_mii.mii_ifp = ifp;
                    844:        sc->sc_mii.mii_readreg = wb_miibus_readreg;
                    845:        sc->sc_mii.mii_writereg = wb_miibus_writereg;
                    846:        sc->sc_mii.mii_statchg = wb_miibus_statchg;
                    847:        mii_attach(self, &sc->sc_mii, 0xffffffff, MII_PHY_ANY, MII_OFFSET_ANY,
                    848:            0);
                    849:        if (LIST_FIRST(&sc->sc_mii.mii_phys) == NULL) {
                    850:                ifmedia_add(&sc->sc_mii.mii_media, IFM_ETHER|IFM_NONE,0,NULL);
                    851:                ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_NONE);
                    852:        } else
                    853:                ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_AUTO);
                    854:
                    855:        /*
                    856:         * Call MI attach routines.
                    857:         */
                    858:        if_attach(ifp);
                    859:        ether_ifattach(ifp);
                    860:
                    861:        shutdownhook_establish(wb_shutdown, sc);
                    862:        return;
                    863:
                    864: fail_5:
                    865:        bus_dmamap_destroy(pa->pa_dmat, dmamap);
                    866:
                    867: fail_4:
                    868:        bus_dmamem_unmap(pa->pa_dmat, kva,
                    869:            sizeof(struct wb_list_data));
                    870:
                    871: fail_3:
                    872:        bus_dmamem_free(pa->pa_dmat, &seg, rseg);
                    873:
                    874: fail_2:
                    875:        pci_intr_disestablish(pc, sc->sc_ih);
                    876:
                    877: fail_1:
                    878:        bus_space_unmap(sc->wb_btag, sc->wb_bhandle, size);
                    879: }
                    880:
                    881: /*
                    882:  * Initialize the transmit descriptors.
                    883:  */
                    884: int wb_list_tx_init(sc)
                    885:        struct wb_softc         *sc;
                    886: {
                    887:        struct wb_chain_data    *cd;
                    888:        struct wb_list_data     *ld;
                    889:        int                     i;
                    890:
                    891:        cd = &sc->wb_cdata;
                    892:        ld = sc->wb_ldata;
                    893:
                    894:        for (i = 0; i < WB_TX_LIST_CNT; i++) {
                    895:                cd->wb_tx_chain[i].wb_ptr = &ld->wb_tx_list[i];
                    896:                if (i == (WB_TX_LIST_CNT - 1)) {
                    897:                        cd->wb_tx_chain[i].wb_nextdesc =
                    898:                                &cd->wb_tx_chain[0];
                    899:                } else {
                    900:                        cd->wb_tx_chain[i].wb_nextdesc =
                    901:                                &cd->wb_tx_chain[i + 1];
                    902:                }
                    903:        }
                    904:
                    905:        cd->wb_tx_free = &cd->wb_tx_chain[0];
                    906:        cd->wb_tx_tail = cd->wb_tx_head = NULL;
                    907:
                    908:        return(0);
                    909: }
                    910:
                    911:
                    912: /*
                    913:  * Initialize the RX descriptors and allocate mbufs for them. Note that
                    914:  * we arrange the descriptors in a closed ring, so that the last descriptor
                    915:  * points back to the first.
                    916:  */
                    917: int wb_list_rx_init(sc)
                    918:        struct wb_softc         *sc;
                    919: {
                    920:        struct wb_chain_data    *cd;
                    921:        struct wb_list_data     *ld;
                    922:        int                     i;
                    923:
                    924:        cd = &sc->wb_cdata;
                    925:        ld = sc->wb_ldata;
                    926:
                    927:        for (i = 0; i < WB_RX_LIST_CNT; i++) {
                    928:                cd->wb_rx_chain[i].wb_ptr =
                    929:                        (struct wb_desc *)&ld->wb_rx_list[i];
                    930:                cd->wb_rx_chain[i].wb_buf = (void *)&ld->wb_rxbufs[i];
                    931:                if (wb_newbuf(sc, &cd->wb_rx_chain[i], NULL) == ENOBUFS)
                    932:                        return(ENOBUFS);
                    933:                if (i == (WB_RX_LIST_CNT - 1)) {
                    934:                        cd->wb_rx_chain[i].wb_nextdesc = &cd->wb_rx_chain[0];
                    935:                        ld->wb_rx_list[i].wb_next =
                    936:                                        VTOPHYS(&ld->wb_rx_list[0]);
                    937:                } else {
                    938:                        cd->wb_rx_chain[i].wb_nextdesc =
                    939:                                        &cd->wb_rx_chain[i + 1];
                    940:                        ld->wb_rx_list[i].wb_next =
                    941:                                        VTOPHYS(&ld->wb_rx_list[i + 1]);
                    942:                }
                    943:        }
                    944:
                    945:        cd->wb_rx_head = &cd->wb_rx_chain[0];
                    946:
                    947:        return(0);
                    948: }
                    949:
                    950: void
                    951: wb_bfree(buf, size, arg)
                    952:        caddr_t                 buf;
                    953:        u_int                   size;
                    954:        void *arg;
                    955: {
                    956: }
                    957:
                    958: /*
                    959:  * Initialize an RX descriptor and attach an MBUF cluster.
                    960:  */
                    961: int
                    962: wb_newbuf(sc, c, m)
                    963:        struct wb_softc *sc;
                    964:        struct wb_chain_onefrag *c;
                    965:        struct mbuf *m;
                    966: {
                    967:        struct mbuf             *m_new = NULL;
                    968:
                    969:        if (m == NULL) {
                    970:                MGETHDR(m_new, M_DONTWAIT, MT_DATA);
                    971:                if (m_new == NULL)
                    972:                        return(ENOBUFS);
                    973:                m_new->m_data = m_new->m_ext.ext_buf = c->wb_buf;
                    974:                m_new->m_flags |= M_EXT;
                    975:                m_new->m_ext.ext_size = m_new->m_pkthdr.len =
                    976:                    m_new->m_len = WB_BUFBYTES;
                    977:                m_new->m_ext.ext_free = wb_bfree;
                    978:                m_new->m_ext.ext_arg = NULL;
                    979:                MCLINITREFERENCE(m_new);
                    980:        } else {
                    981:                m_new = m;
                    982:                m_new->m_len = m_new->m_pkthdr.len = WB_BUFBYTES;
                    983:                m_new->m_data = m_new->m_ext.ext_buf;
                    984:        }
                    985:
                    986:        m_adj(m_new, sizeof(u_int64_t));
                    987:
                    988:        c->wb_mbuf = m_new;
                    989:        c->wb_ptr->wb_data = VTOPHYS(mtod(m_new, caddr_t));
                    990:        c->wb_ptr->wb_ctl = WB_RXCTL_RLINK | ETHER_MAX_DIX_LEN;
                    991:        c->wb_ptr->wb_status = WB_RXSTAT;
                    992:
                    993:        return(0);
                    994: }
                    995:
                    996: /*
                    997:  * A frame has been uploaded: pass the resulting mbuf chain up to
                    998:  * the higher level protocols.
                    999:  */
                   1000: void wb_rxeof(sc)
                   1001:        struct wb_softc         *sc;
                   1002: {
                   1003:         struct mbuf            *m = NULL;
                   1004:         struct ifnet           *ifp;
                   1005:        struct wb_chain_onefrag *cur_rx;
                   1006:        int                     total_len = 0;
                   1007:        u_int32_t               rxstat;
                   1008:
                   1009:        ifp = &sc->arpcom.ac_if;
                   1010:
                   1011:        while(!((rxstat = sc->wb_cdata.wb_rx_head->wb_ptr->wb_status) &
                   1012:                                                        WB_RXSTAT_OWN)) {
                   1013:                struct mbuf *m0 = NULL;
                   1014:
                   1015:                cur_rx = sc->wb_cdata.wb_rx_head;
                   1016:                sc->wb_cdata.wb_rx_head = cur_rx->wb_nextdesc;
                   1017:
                   1018:                m = cur_rx->wb_mbuf;
                   1019:
                   1020:                if ((rxstat & WB_RXSTAT_MIIERR) ||
                   1021:                    (WB_RXBYTES(cur_rx->wb_ptr->wb_status) < WB_MIN_FRAMELEN) ||
                   1022:                    (WB_RXBYTES(cur_rx->wb_ptr->wb_status) > ETHER_MAX_DIX_LEN) ||
                   1023:                    !(rxstat & WB_RXSTAT_LASTFRAG) ||
                   1024:                    !(rxstat & WB_RXSTAT_RXCMP)) {
                   1025:                        ifp->if_ierrors++;
                   1026:                        wb_newbuf(sc, cur_rx, m);
                   1027:                        printf("%s: receiver babbling: possible chip "
                   1028:                                "bug, forcing reset\n", sc->sc_dev.dv_xname);
                   1029:                        wb_fixmedia(sc);
                   1030:                        wb_reset(sc);
                   1031:                        wb_init(sc);
                   1032:                        return;
                   1033:                }
                   1034:
                   1035:                if (rxstat & WB_RXSTAT_RXERR) {
                   1036:                        ifp->if_ierrors++;
                   1037:                        wb_newbuf(sc, cur_rx, m);
                   1038:                        break;
                   1039:                }
                   1040:
                   1041:                /* No errors; receive the packet. */
                   1042:                total_len = WB_RXBYTES(cur_rx->wb_ptr->wb_status);
                   1043:
                   1044:                /*
                   1045:                 * XXX The Winbond chip includes the CRC with every
                   1046:                 * received frame, and there's no way to turn this
                   1047:                 * behavior off (at least, I can't find anything in
                   1048:                 * the manual that explains how to do it) so we have
                   1049:                 * to trim off the CRC manually.
                   1050:                 */
                   1051:                total_len -= ETHER_CRC_LEN;
                   1052:
                   1053:                m0 = m_devget(mtod(m, char *) - ETHER_ALIGN,
                   1054:                    total_len + ETHER_ALIGN, 0, ifp, NULL);
                   1055:                wb_newbuf(sc, cur_rx, m);
                   1056:                if (m0 == NULL) {
                   1057:                        ifp->if_ierrors++;
                   1058:                        break;
                   1059:                }
                   1060:                m_adj(m0, ETHER_ALIGN);
                   1061:                m = m0;
                   1062:
                   1063:                ifp->if_ipackets++;
                   1064:
                   1065: #if NBPFILTER > 0
                   1066:                /*
                   1067:                 * Handle BPF listeners. Let the BPF user see the packet.
                   1068:                 */
                   1069:                if (ifp->if_bpf)
                   1070:                        bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
                   1071: #endif
                   1072:                /* pass it on. */
                   1073:                ether_input_mbuf(ifp, m);
                   1074:        }
                   1075:
                   1076:        return;
                   1077: }
                   1078:
                   1079: void wb_rxeoc(sc)
                   1080:        struct wb_softc         *sc;
                   1081: {
                   1082:        wb_rxeof(sc);
                   1083:
                   1084:        WB_CLRBIT(sc, WB_NETCFG, WB_NETCFG_RX_ON);
                   1085:        CSR_WRITE_4(sc, WB_RXADDR, VTOPHYS(&sc->wb_ldata->wb_rx_list[0]));
                   1086:        WB_SETBIT(sc, WB_NETCFG, WB_NETCFG_RX_ON);
                   1087:        if (CSR_READ_4(sc, WB_ISR) & WB_RXSTATE_SUSPEND)
                   1088:                CSR_WRITE_4(sc, WB_RXSTART, 0xFFFFFFFF);
                   1089:
                   1090:        return;
                   1091: }
                   1092:
                   1093: /*
                   1094:  * A frame was downloaded to the chip. It's safe for us to clean up
                   1095:  * the list buffers.
                   1096:  */
                   1097: void wb_txeof(sc)
                   1098:        struct wb_softc         *sc;
                   1099: {
                   1100:        struct wb_chain         *cur_tx;
                   1101:        struct ifnet            *ifp;
                   1102:
                   1103:        ifp = &sc->arpcom.ac_if;
                   1104:
                   1105:        /* Clear the timeout timer. */
                   1106:        ifp->if_timer = 0;
                   1107:
                   1108:        if (sc->wb_cdata.wb_tx_head == NULL)
                   1109:                return;
                   1110:
                   1111:        /*
                   1112:         * Go through our tx list and free mbufs for those
                   1113:         * frames that have been transmitted.
                   1114:         */
                   1115:        while(sc->wb_cdata.wb_tx_head->wb_mbuf != NULL) {
                   1116:                u_int32_t               txstat;
                   1117:
                   1118:                cur_tx = sc->wb_cdata.wb_tx_head;
                   1119:                txstat = WB_TXSTATUS(cur_tx);
                   1120:
                   1121:                if ((txstat & WB_TXSTAT_OWN) || txstat == WB_UNSENT)
                   1122:                        break;
                   1123:
                   1124:                if (txstat & WB_TXSTAT_TXERR) {
                   1125:                        ifp->if_oerrors++;
                   1126:                        if (txstat & WB_TXSTAT_ABORT)
                   1127:                                ifp->if_collisions++;
                   1128:                        if (txstat & WB_TXSTAT_LATECOLL)
                   1129:                                ifp->if_collisions++;
                   1130:                }
                   1131:
                   1132:                ifp->if_collisions += (txstat & WB_TXSTAT_COLLCNT) >> 3;
                   1133:
                   1134:                ifp->if_opackets++;
                   1135:                m_freem(cur_tx->wb_mbuf);
                   1136:                cur_tx->wb_mbuf = NULL;
                   1137:
                   1138:                if (sc->wb_cdata.wb_tx_head == sc->wb_cdata.wb_tx_tail) {
                   1139:                        sc->wb_cdata.wb_tx_head = NULL;
                   1140:                        sc->wb_cdata.wb_tx_tail = NULL;
                   1141:                        break;
                   1142:                }
                   1143:
                   1144:                sc->wb_cdata.wb_tx_head = cur_tx->wb_nextdesc;
                   1145:        }
                   1146:
                   1147:        return;
                   1148: }
                   1149:
                   1150: /*
                   1151:  * TX 'end of channel' interrupt handler.
                   1152:  */
                   1153: void wb_txeoc(sc)
                   1154:        struct wb_softc         *sc;
                   1155: {
                   1156:        struct ifnet            *ifp;
                   1157:
                   1158:        ifp = &sc->arpcom.ac_if;
                   1159:
                   1160:        ifp->if_timer = 0;
                   1161:
                   1162:        if (sc->wb_cdata.wb_tx_head == NULL) {
                   1163:                ifp->if_flags &= ~IFF_OACTIVE;
                   1164:                sc->wb_cdata.wb_tx_tail = NULL;
                   1165:        } else {
                   1166:                if (WB_TXOWN(sc->wb_cdata.wb_tx_head) == WB_UNSENT) {
                   1167:                        WB_TXOWN(sc->wb_cdata.wb_tx_head) = WB_TXSTAT_OWN;
                   1168:                        ifp->if_timer = 5;
                   1169:                        CSR_WRITE_4(sc, WB_TXSTART, 0xFFFFFFFF);
                   1170:                }
                   1171:        }
                   1172:
                   1173:        return;
                   1174: }
                   1175:
                   1176: int wb_intr(arg)
                   1177:        void                    *arg;
                   1178: {
                   1179:        struct wb_softc         *sc;
                   1180:        struct ifnet            *ifp;
                   1181:        u_int32_t               status;
                   1182:        int                     r = 0;
                   1183:
                   1184:        sc = arg;
                   1185:        ifp = &sc->arpcom.ac_if;
                   1186:
                   1187:        if (!(ifp->if_flags & IFF_UP))
                   1188:                return (r);
                   1189:
                   1190:        /* Disable interrupts. */
                   1191:        CSR_WRITE_4(sc, WB_IMR, 0x00000000);
                   1192:
                   1193:        for (;;) {
                   1194:
                   1195:                status = CSR_READ_4(sc, WB_ISR);
                   1196:                if (status)
                   1197:                        CSR_WRITE_4(sc, WB_ISR, status);
                   1198:
                   1199:                if ((status & WB_INTRS) == 0)
                   1200:                        break;
                   1201:
                   1202:                r = 1;
                   1203:
                   1204:                if ((status & WB_ISR_RX_NOBUF) || (status & WB_ISR_RX_ERR)) {
                   1205:                        ifp->if_ierrors++;
                   1206:                        wb_reset(sc);
                   1207:                        if (status & WB_ISR_RX_ERR)
                   1208:                                wb_fixmedia(sc);
                   1209:                        wb_init(sc);
                   1210:                        continue;
                   1211:                }
                   1212:
                   1213:                if (status & WB_ISR_RX_OK)
                   1214:                        wb_rxeof(sc);
                   1215:
                   1216:                if (status & WB_ISR_RX_IDLE)
                   1217:                        wb_rxeoc(sc);
                   1218:
                   1219:                if (status & WB_ISR_TX_OK)
                   1220:                        wb_txeof(sc);
                   1221:
                   1222:                if (status & WB_ISR_TX_NOBUF)
                   1223:                        wb_txeoc(sc);
                   1224:
                   1225:                if (status & WB_ISR_TX_IDLE) {
                   1226:                        wb_txeof(sc);
                   1227:                        if (sc->wb_cdata.wb_tx_head != NULL) {
                   1228:                                WB_SETBIT(sc, WB_NETCFG, WB_NETCFG_TX_ON);
                   1229:                                CSR_WRITE_4(sc, WB_TXSTART, 0xFFFFFFFF);
                   1230:                        }
                   1231:                }
                   1232:
                   1233:                if (status & WB_ISR_TX_UNDERRUN) {
                   1234:                        ifp->if_oerrors++;
                   1235:                        wb_txeof(sc);
                   1236:                        WB_CLRBIT(sc, WB_NETCFG, WB_NETCFG_TX_ON);
                   1237:                        /* Jack up TX threshold */
                   1238:                        sc->wb_txthresh += WB_TXTHRESH_CHUNK;
                   1239:                        WB_CLRBIT(sc, WB_NETCFG, WB_NETCFG_TX_THRESH);
                   1240:                        WB_SETBIT(sc, WB_NETCFG, WB_TXTHRESH(sc->wb_txthresh));
                   1241:                        WB_SETBIT(sc, WB_NETCFG, WB_NETCFG_TX_ON);
                   1242:                }
                   1243:
                   1244:                if (status & WB_ISR_BUS_ERR) {
                   1245:                        wb_reset(sc);
                   1246:                        wb_init(sc);
                   1247:                }
                   1248:
                   1249:        }
                   1250:
                   1251:        /* Re-enable interrupts. */
                   1252:        CSR_WRITE_4(sc, WB_IMR, WB_INTRS);
                   1253:
                   1254:        if (!IFQ_IS_EMPTY(&ifp->if_snd)) {
                   1255:                wb_start(ifp);
                   1256:        }
                   1257:
                   1258:        return (r);
                   1259: }
                   1260:
                   1261: void
                   1262: wb_tick(xsc)
                   1263:        void *xsc;
                   1264: {
                   1265:        struct wb_softc *sc = xsc;
                   1266:        int s;
                   1267:
                   1268:        s = splnet();
                   1269:        mii_tick(&sc->sc_mii);
                   1270:        splx(s);
                   1271:        timeout_add(&sc->wb_tick_tmo, hz);
                   1272: }
                   1273:
                   1274: /*
                   1275:  * Encapsulate an mbuf chain in a descriptor by coupling the mbuf data
                   1276:  * pointers to the fragment pointers.
                   1277:  */
                   1278: int wb_encap(sc, c, m_head)
                   1279:        struct wb_softc         *sc;
                   1280:        struct wb_chain         *c;
                   1281:        struct mbuf             *m_head;
                   1282: {
                   1283:        int                     frag = 0;
                   1284:        struct wb_desc          *f = NULL;
                   1285:        int                     total_len;
                   1286:        struct mbuf             *m;
                   1287:
                   1288:        /*
                   1289:         * Start packing the mbufs in this chain into
                   1290:         * the fragment pointers. Stop when we run out
                   1291:         * of fragments or hit the end of the mbuf chain.
                   1292:         */
                   1293:        m = m_head;
                   1294:        total_len = 0;
                   1295:
                   1296:        for (m = m_head, frag = 0; m != NULL; m = m->m_next) {
                   1297:                if (m->m_len != 0) {
                   1298:                        if (frag == WB_MAXFRAGS)
                   1299:                                break;
                   1300:                        total_len += m->m_len;
                   1301:                        f = &c->wb_ptr->wb_frag[frag];
                   1302:                        f->wb_ctl = WB_TXCTL_TLINK | m->m_len;
                   1303:                        if (frag == 0) {
                   1304:                                f->wb_ctl |= WB_TXCTL_FIRSTFRAG;
                   1305:                                f->wb_status = 0;
                   1306:                        } else
                   1307:                                f->wb_status = WB_TXSTAT_OWN;
                   1308:                        f->wb_next = VTOPHYS(&c->wb_ptr->wb_frag[frag + 1]);
                   1309:                        f->wb_data = VTOPHYS(mtod(m, vaddr_t));
                   1310:                        frag++;
                   1311:                }
                   1312:        }
                   1313:
                   1314:        /*
                   1315:         * Handle special case: we used up all 16 fragments,
                   1316:         * but we have more mbufs left in the chain. Copy the
                   1317:         * data into an mbuf cluster. Note that we don't
                   1318:         * bother clearing the values in the other fragment
                   1319:         * pointers/counters; it wouldn't gain us anything,
                   1320:         * and would waste cycles.
                   1321:         */
                   1322:        if (m != NULL) {
                   1323:                struct mbuf             *m_new = NULL;
                   1324:
                   1325:                MGETHDR(m_new, M_DONTWAIT, MT_DATA);
                   1326:                if (m_new == NULL)
                   1327:                        return(1);
                   1328:                if (m_head->m_pkthdr.len > MHLEN) {
                   1329:                        MCLGET(m_new, M_DONTWAIT);
                   1330:                        if (!(m_new->m_flags & M_EXT)) {
                   1331:                                m_freem(m_new);
                   1332:                                return(1);
                   1333:                        }
                   1334:                }
                   1335:                m_copydata(m_head, 0, m_head->m_pkthdr.len,
                   1336:                                        mtod(m_new, caddr_t));
                   1337:                m_new->m_pkthdr.len = m_new->m_len = m_head->m_pkthdr.len;
                   1338:                m_freem(m_head);
                   1339:                m_head = m_new;
                   1340:                f = &c->wb_ptr->wb_frag[0];
                   1341:                f->wb_status = 0;
                   1342:                f->wb_data = VTOPHYS(mtod(m_new, caddr_t));
                   1343:                f->wb_ctl = total_len = m_new->m_len;
                   1344:                f->wb_ctl |= WB_TXCTL_TLINK|WB_TXCTL_FIRSTFRAG;
                   1345:                frag = 1;
                   1346:        }
                   1347:
                   1348:        if (total_len < WB_MIN_FRAMELEN) {
                   1349:                f = &c->wb_ptr->wb_frag[frag];
                   1350:                f->wb_ctl = WB_MIN_FRAMELEN - total_len;
                   1351:                f->wb_data = VTOPHYS(&sc->wb_cdata.wb_pad);
                   1352:                f->wb_ctl |= WB_TXCTL_TLINK;
                   1353:                f->wb_status = WB_TXSTAT_OWN;
                   1354:                frag++;
                   1355:        }
                   1356:
                   1357:        c->wb_mbuf = m_head;
                   1358:        c->wb_lastdesc = frag - 1;
                   1359:        WB_TXCTL(c) |= WB_TXCTL_LASTFRAG;
                   1360:        WB_TXNEXT(c) = VTOPHYS(&c->wb_nextdesc->wb_ptr->wb_frag[0]);
                   1361:
                   1362:        return(0);
                   1363: }
                   1364:
                   1365: /*
                   1366:  * Main transmit routine. To avoid having to do mbuf copies, we put pointers
                   1367:  * to the mbuf data regions directly in the transmit lists. We also save a
                   1368:  * copy of the pointers since the transmit list fragment pointers are
                   1369:  * physical addresses.
                   1370:  */
                   1371:
                   1372: void wb_start(ifp)
                   1373:        struct ifnet            *ifp;
                   1374: {
                   1375:        struct wb_softc         *sc;
                   1376:        struct mbuf             *m_head = NULL;
                   1377:        struct wb_chain         *cur_tx = NULL, *start_tx;
                   1378:
                   1379:        sc = ifp->if_softc;
                   1380:
                   1381:        /*
                   1382:         * Check for an available queue slot. If there are none,
                   1383:         * punt.
                   1384:         */
                   1385:        if (sc->wb_cdata.wb_tx_free->wb_mbuf != NULL) {
                   1386:                ifp->if_flags |= IFF_OACTIVE;
                   1387:                return;
                   1388:        }
                   1389:
                   1390:        start_tx = sc->wb_cdata.wb_tx_free;
                   1391:
                   1392:        while(sc->wb_cdata.wb_tx_free->wb_mbuf == NULL) {
                   1393:                IFQ_DEQUEUE(&ifp->if_snd, m_head);
                   1394:                if (m_head == NULL)
                   1395:                        break;
                   1396:
                   1397:                /* Pick a descriptor off the free list. */
                   1398:                cur_tx = sc->wb_cdata.wb_tx_free;
                   1399:                sc->wb_cdata.wb_tx_free = cur_tx->wb_nextdesc;
                   1400:
                   1401:                /* Pack the data into the descriptor. */
                   1402:                wb_encap(sc, cur_tx, m_head);
                   1403:
                   1404:                if (cur_tx != start_tx)
                   1405:                        WB_TXOWN(cur_tx) = WB_TXSTAT_OWN;
                   1406:
                   1407: #if NBPFILTER > 0
                   1408:                /*
                   1409:                 * If there's a BPF listener, bounce a copy of this frame
                   1410:                 * to him.
                   1411:                 */
                   1412:                if (ifp->if_bpf)
                   1413:                        bpf_mtap(ifp->if_bpf, cur_tx->wb_mbuf,
                   1414:                            BPF_DIRECTION_OUT);
                   1415: #endif
                   1416:        }
                   1417:
                   1418:        /*
                   1419:         * If there are no packets queued, bail.
                   1420:         */
                   1421:        if (cur_tx == NULL)
                   1422:                return;
                   1423:
                   1424:        /*
                   1425:         * Place the request for the upload interrupt
                   1426:         * in the last descriptor in the chain. This way, if
                   1427:         * we're chaining several packets at once, we'll only
                   1428:         * get an interrupt once for the whole chain rather than
                   1429:         * once for each packet.
                   1430:         */
                   1431:        WB_TXCTL(cur_tx) |= WB_TXCTL_FINT;
                   1432:        cur_tx->wb_ptr->wb_frag[0].wb_ctl |= WB_TXCTL_FINT;
                   1433:        sc->wb_cdata.wb_tx_tail = cur_tx;
                   1434:
                   1435:        if (sc->wb_cdata.wb_tx_head == NULL) {
                   1436:                sc->wb_cdata.wb_tx_head = start_tx;
                   1437:                WB_TXOWN(start_tx) = WB_TXSTAT_OWN;
                   1438:                CSR_WRITE_4(sc, WB_TXSTART, 0xFFFFFFFF);
                   1439:        } else {
                   1440:                /*
                   1441:                 * We need to distinguish between the case where
                   1442:                 * the own bit is clear because the chip cleared it
                   1443:                 * and where the own bit is clear because we haven't
                   1444:                 * set it yet. The magic value WB_UNSET is just some
                   1445:                 * ramdomly chosen number which doesn't have the own
                   1446:                 * bit set. When we actually transmit the frame, the
                   1447:                 * status word will have _only_ the own bit set, so
                   1448:                 * the txeoc handler will be able to tell if it needs
                   1449:                 * to initiate another transmission to flush out pending
                   1450:                 * frames.
                   1451:                 */
                   1452:                WB_TXOWN(start_tx) = WB_UNSENT;
                   1453:        }
                   1454:
                   1455:        /*
                   1456:         * Set a timeout in case the chip goes out to lunch.
                   1457:         */
                   1458:        ifp->if_timer = 5;
                   1459:
                   1460:        return;
                   1461: }
                   1462:
                   1463: void wb_init(xsc)
                   1464:        void                    *xsc;
                   1465: {
                   1466:        struct wb_softc *sc = xsc;
                   1467:        struct ifnet *ifp = &sc->arpcom.ac_if;
                   1468:        int s, i;
                   1469:
                   1470:        s = splnet();
                   1471:
                   1472:        /*
                   1473:         * Cancel pending I/O and free all RX/TX buffers.
                   1474:         */
                   1475:        wb_stop(sc);
                   1476:        wb_reset(sc);
                   1477:
                   1478:        sc->wb_txthresh = WB_TXTHRESH_INIT;
                   1479:
                   1480:        /*
                   1481:         * Set cache alignment and burst length.
                   1482:         */
                   1483: #ifdef foo
                   1484:        CSR_WRITE_4(sc, WB_BUSCTL, WB_BUSCTL_CONFIG);
                   1485:        WB_CLRBIT(sc, WB_NETCFG, WB_NETCFG_TX_THRESH);
                   1486:        WB_SETBIT(sc, WB_NETCFG, WB_TXTHRESH(sc->wb_txthresh));
                   1487: #endif
                   1488:
                   1489:        CSR_WRITE_4(sc, WB_BUSCTL, WB_BUSCTL_MUSTBEONE|WB_BUSCTL_ARBITRATION);
                   1490:        WB_SETBIT(sc, WB_BUSCTL, WB_BURSTLEN_16LONG);
                   1491:        switch(sc->wb_cachesize) {
                   1492:        case 32:
                   1493:                WB_SETBIT(sc, WB_BUSCTL, WB_CACHEALIGN_32LONG);
                   1494:                break;
                   1495:        case 16:
                   1496:                WB_SETBIT(sc, WB_BUSCTL, WB_CACHEALIGN_16LONG);
                   1497:                break;
                   1498:        case 8:
                   1499:                WB_SETBIT(sc, WB_BUSCTL, WB_CACHEALIGN_8LONG);
                   1500:                break;
                   1501:        case 0:
                   1502:        default:
                   1503:                WB_SETBIT(sc, WB_BUSCTL, WB_CACHEALIGN_NONE);
                   1504:                break;
                   1505:        }
                   1506:
                   1507:        /* This doesn't tend to work too well at 100Mbps. */
                   1508:        WB_CLRBIT(sc, WB_NETCFG, WB_NETCFG_TX_EARLY_ON);
                   1509:
                   1510:        /* Init our MAC address */
                   1511:        for (i = 0; i < ETHER_ADDR_LEN; i++) {
                   1512:                CSR_WRITE_1(sc, WB_NODE0 + i, sc->arpcom.ac_enaddr[i]);
                   1513:        }
                   1514:
                   1515:        /* Init circular RX list. */
                   1516:        if (wb_list_rx_init(sc) == ENOBUFS) {
                   1517:                printf("%s: initialization failed: no "
                   1518:                        "memory for rx buffers\n", sc->sc_dev.dv_xname);
                   1519:                wb_stop(sc);
                   1520:                splx(s);
                   1521:                return;
                   1522:        }
                   1523:
                   1524:        /* Init TX descriptors. */
                   1525:        wb_list_tx_init(sc);
                   1526:
                   1527:        /* If we want promiscuous mode, set the allframes bit. */
                   1528:        if (ifp->if_flags & IFF_PROMISC) {
                   1529:                WB_SETBIT(sc, WB_NETCFG, WB_NETCFG_RX_ALLPHYS);
                   1530:        } else {
                   1531:                WB_CLRBIT(sc, WB_NETCFG, WB_NETCFG_RX_ALLPHYS);
                   1532:        }
                   1533:
                   1534:        /*
                   1535:         * Set capture broadcast bit to capture broadcast frames.
                   1536:         */
                   1537:        if (ifp->if_flags & IFF_BROADCAST) {
                   1538:                WB_SETBIT(sc, WB_NETCFG, WB_NETCFG_RX_BROAD);
                   1539:        } else {
                   1540:                WB_CLRBIT(sc, WB_NETCFG, WB_NETCFG_RX_BROAD);
                   1541:        }
                   1542:
                   1543:        /*
                   1544:         * Program the multicast filter, if necessary.
                   1545:         */
                   1546:        wb_setmulti(sc);
                   1547:
                   1548:        /*
                   1549:         * Load the address of the RX list.
                   1550:         */
                   1551:        WB_CLRBIT(sc, WB_NETCFG, WB_NETCFG_RX_ON);
                   1552:        CSR_WRITE_4(sc, WB_RXADDR, VTOPHYS(&sc->wb_ldata->wb_rx_list[0]));
                   1553:
                   1554:        /*
                   1555:         * Enable interrupts.
                   1556:         */
                   1557:        CSR_WRITE_4(sc, WB_IMR, WB_INTRS);
                   1558:        CSR_WRITE_4(sc, WB_ISR, 0xFFFFFFFF);
                   1559:
                   1560:        /* Enable receiver and transmitter. */
                   1561:        WB_SETBIT(sc, WB_NETCFG, WB_NETCFG_RX_ON);
                   1562:        CSR_WRITE_4(sc, WB_RXSTART, 0xFFFFFFFF);
                   1563:
                   1564:        WB_CLRBIT(sc, WB_NETCFG, WB_NETCFG_TX_ON);
                   1565:        CSR_WRITE_4(sc, WB_TXADDR, VTOPHYS(&sc->wb_ldata->wb_tx_list[0]));
                   1566:        WB_SETBIT(sc, WB_NETCFG, WB_NETCFG_TX_ON);
                   1567:
                   1568:        ifp->if_flags |= IFF_RUNNING;
                   1569:        ifp->if_flags &= ~IFF_OACTIVE;
                   1570:
                   1571:        splx(s);
                   1572:
                   1573:        timeout_set(&sc->wb_tick_tmo, wb_tick, sc);
                   1574:        timeout_add(&sc->wb_tick_tmo, hz);
                   1575:
                   1576:        return;
                   1577: }
                   1578:
                   1579: /*
                   1580:  * Set media options.
                   1581:  */
                   1582: int
                   1583: wb_ifmedia_upd(ifp)
                   1584:        struct ifnet *ifp;
                   1585: {
                   1586:        struct wb_softc *sc = ifp->if_softc;
                   1587:
                   1588:        if (ifp->if_flags & IFF_UP)
                   1589:                wb_init(sc);
                   1590:
                   1591:        return(0);
                   1592: }
                   1593:
                   1594: /*
                   1595:  * Report current media status.
                   1596:  */
                   1597: void
                   1598: wb_ifmedia_sts(ifp, ifmr)
                   1599:        struct ifnet            *ifp;
                   1600:        struct ifmediareq       *ifmr;
                   1601: {
                   1602:        struct wb_softc *sc = ifp->if_softc;
                   1603:        struct mii_data *mii = &sc->sc_mii;
                   1604:
                   1605:        mii_pollstat(mii);
                   1606:        ifmr->ifm_active = mii->mii_media_active;
                   1607:        ifmr->ifm_status = mii->mii_media_status;
                   1608: }
                   1609:
                   1610: int wb_ioctl(ifp, command, data)
                   1611:        struct ifnet            *ifp;
                   1612:        u_long                  command;
                   1613:        caddr_t                 data;
                   1614: {
                   1615:        struct wb_softc         *sc = ifp->if_softc;
                   1616:        struct ifreq            *ifr = (struct ifreq *) data;
                   1617:        struct ifaddr           *ifa = (struct ifaddr *)data;
                   1618:        int                     s, error = 0;
                   1619:
                   1620:        s = splnet();
                   1621:
                   1622:        if ((error = ether_ioctl(ifp, &sc->arpcom, command, data)) > 0) {
                   1623:                splx(s);
                   1624:                return (error);
                   1625:        }
                   1626:
                   1627:        switch(command) {
                   1628:        case SIOCSIFADDR:
                   1629:                ifp->if_flags |= IFF_UP;
                   1630:                switch (ifa->ifa_addr->sa_family) {
                   1631: #ifdef INET
                   1632:                case AF_INET:
                   1633:                        wb_init(sc);
                   1634:                        arp_ifinit(&sc->arpcom, ifa);
                   1635:                        break;
                   1636: #endif /* INET */
                   1637:                default:
                   1638:                        wb_init(sc);
                   1639:                }
                   1640:                break;
                   1641:        case SIOCSIFFLAGS:
                   1642:                if (ifp->if_flags & IFF_UP) {
                   1643:                        wb_init(sc);
                   1644:                } else {
                   1645:                        if (ifp->if_flags & IFF_RUNNING)
                   1646:                                wb_stop(sc);
                   1647:                }
                   1648:                error = 0;
                   1649:                break;
                   1650:        case SIOCADDMULTI:
                   1651:        case SIOCDELMULTI:
                   1652:                error = (command == SIOCADDMULTI) ?
                   1653:                    ether_addmulti(ifr, &sc->arpcom) :
                   1654:                    ether_delmulti(ifr, &sc->arpcom);
                   1655:
                   1656:                if (error == ENETRESET) {
                   1657:                        /*
                   1658:                         * Multicast list has changed; set the hardware
                   1659:                         * filter accordingly.
                   1660:                         */
                   1661:                        if (ifp->if_flags & IFF_RUNNING)
                   1662:                                wb_setmulti(sc);
                   1663:                        error = 0;
                   1664:                }
                   1665:                break;
                   1666:        case SIOCGIFMEDIA:
                   1667:        case SIOCSIFMEDIA:
                   1668:                error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii.mii_media, command);
                   1669:                break;
                   1670:        default:
                   1671:                error = ENOTTY;
                   1672:                break;
                   1673:        }
                   1674:
                   1675:        splx(s);
                   1676:
                   1677:        return(error);
                   1678: }
                   1679:
                   1680: void wb_watchdog(ifp)
                   1681:        struct ifnet            *ifp;
                   1682: {
                   1683:        struct wb_softc         *sc;
                   1684:
                   1685:        sc = ifp->if_softc;
                   1686:
                   1687:        ifp->if_oerrors++;
                   1688:        printf("%s: watchdog timeout\n", sc->sc_dev.dv_xname);
                   1689:
                   1690: #ifdef foo
                   1691:        if (!(wb_phy_readreg(sc, PHY_BMSR) & PHY_BMSR_LINKSTAT))
                   1692:                printf("%s: no carrier - transceiver cable problem?\n",
                   1693:                    sc->sc_dev.dv_xname);
                   1694: #endif
                   1695:        wb_stop(sc);
                   1696:        wb_reset(sc);
                   1697:        wb_init(sc);
                   1698:
                   1699:        if (!IFQ_IS_EMPTY(&ifp->if_snd))
                   1700:                wb_start(ifp);
                   1701:
                   1702:        return;
                   1703: }
                   1704:
                   1705: /*
                   1706:  * Stop the adapter and free any mbufs allocated to the
                   1707:  * RX and TX lists.
                   1708:  */
                   1709: void wb_stop(sc)
                   1710:        struct wb_softc         *sc;
                   1711: {
                   1712:        int                     i;
                   1713:        struct ifnet            *ifp;
                   1714:
                   1715:        ifp = &sc->arpcom.ac_if;
                   1716:        ifp->if_timer = 0;
                   1717:
                   1718:        timeout_del(&sc->wb_tick_tmo);
                   1719:
                   1720:        ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
                   1721:
                   1722:        WB_CLRBIT(sc, WB_NETCFG, (WB_NETCFG_RX_ON|WB_NETCFG_TX_ON));
                   1723:        CSR_WRITE_4(sc, WB_IMR, 0x00000000);
                   1724:        CSR_WRITE_4(sc, WB_TXADDR, 0x00000000);
                   1725:        CSR_WRITE_4(sc, WB_RXADDR, 0x00000000);
                   1726:
                   1727:        /*
                   1728:         * Free data in the RX lists.
                   1729:         */
                   1730:        for (i = 0; i < WB_RX_LIST_CNT; i++) {
                   1731:                if (sc->wb_cdata.wb_rx_chain[i].wb_mbuf != NULL) {
                   1732:                        m_freem(sc->wb_cdata.wb_rx_chain[i].wb_mbuf);
                   1733:                        sc->wb_cdata.wb_rx_chain[i].wb_mbuf = NULL;
                   1734:                }
                   1735:        }
                   1736:        bzero((char *)&sc->wb_ldata->wb_rx_list,
                   1737:                sizeof(sc->wb_ldata->wb_rx_list));
                   1738:
                   1739:        /*
                   1740:         * Free the TX list buffers.
                   1741:         */
                   1742:        for (i = 0; i < WB_TX_LIST_CNT; i++) {
                   1743:                if (sc->wb_cdata.wb_tx_chain[i].wb_mbuf != NULL) {
                   1744:                        m_freem(sc->wb_cdata.wb_tx_chain[i].wb_mbuf);
                   1745:                        sc->wb_cdata.wb_tx_chain[i].wb_mbuf = NULL;
                   1746:                }
                   1747:        }
                   1748:
                   1749:        bzero((char *)&sc->wb_ldata->wb_tx_list,
                   1750:                sizeof(sc->wb_ldata->wb_tx_list));
                   1751: }
                   1752:
                   1753: /*
                   1754:  * Stop all chip I/O so that the kernel's probe routines don't
                   1755:  * get confused by errant DMAs when rebooting.
                   1756:  */
                   1757: void wb_shutdown(arg)
                   1758:        void                    *arg;
                   1759: {
                   1760:        struct wb_softc         *sc = (struct wb_softc *)arg;
                   1761:
                   1762:        wb_stop(sc);
                   1763:
                   1764:        return;
                   1765: }
                   1766:
                   1767: struct cfattach wb_ca = {
                   1768:        sizeof(struct wb_softc), wb_probe, wb_attach
                   1769: };
                   1770:
                   1771: struct cfdriver wb_cd = {
                   1772:        0, "wb", DV_IFNET
                   1773: };

CVSweb