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

Annotation of sys/dev/ic/xl.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: xl.c,v 1.78 2007/05/19 16:51:57 kettenis Exp $        */
        !             2:
        !             3: /*
        !             4:  * Copyright (c) 1997, 1998, 1999
        !             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: if_xl.c,v 1.77 2000/08/28 20:40:03 wpaul Exp $
        !            35:  */
        !            36:
        !            37: /*
        !            38:  * 3Com 3c90x Etherlink XL PCI NIC driver
        !            39:  *
        !            40:  * Supports the 3Com "boomerang", "cyclone", and "hurricane" PCI
        !            41:  * bus-master chips (3c90x cards and embedded controllers) including
        !            42:  * the following:
        !            43:  *
        !            44:  * 3Com 3c900-TPO      10Mbps/RJ-45
        !            45:  * 3Com 3c900-COMBO    10Mbps/RJ-45,AUI,BNC
        !            46:  * 3Com 3c905-TX       10/100Mbps/RJ-45
        !            47:  * 3Com 3c905-T4       10/100Mbps/RJ-45
        !            48:  * 3Com 3c900B-TPO     10Mbps/RJ-45
        !            49:  * 3Com 3c900B-COMBO   10Mbps/RJ-45,AUI,BNC
        !            50:  * 3Com 3c900B-TPC     10Mbps/RJ-45,BNC
        !            51:  * 3Com 3c900B-FL      10Mbps/Fiber-optic
        !            52:  * 3Com 3c905B-COMBO   10/100Mbps/RJ-45,AUI,BNC
        !            53:  * 3Com 3c905B-TX      10/100Mbps/RJ-45
        !            54:  * 3Com 3c905B-FL/FX   10/100Mbps/Fiber-optic
        !            55:  * 3Com 3c905C-TX      10/100Mbps/RJ-45 (Tornado ASIC)
        !            56:  * 3Com 3c980-TX       10/100Mbps server adapter (Hurricane ASIC)
        !            57:  * 3Com 3c980C-TX      10/100Mbps server adapter (Tornado ASIC)
        !            58:  * 3Com 3cSOHO100-TX   10/100Mbps/RJ-45 (Hurricane ASIC)
        !            59:  * 3Com 3c450-TX       10/100Mbps/RJ-45 (Tornado ASIC)
        !            60:  * 3Com 3c555          10/100Mbps/RJ-45 (MiniPCI, Laptop Hurricane)
        !            61:  * 3Com 3c556          10/100Mbps/RJ-45 (MiniPCI, Hurricane ASIC)
        !            62:  * 3Com 3c556B         10/100Mbps/RJ-45 (MiniPCI, Hurricane ASIC)
        !            63:  * 3Com 3c575TX                10/100Mbps/RJ-45 (Cardbus, Hurricane ASIC)
        !            64:  * 3Com 3c575B         10/100Mbps/RJ-45 (Cardbus, Hurricane ASIC)
        !            65:  * 3Com 3c575C         10/100Mbps/RJ-45 (Cardbus, Hurricane ASIC)
        !            66:  * 3Com 3cxfem656      10/100Mbps/RJ-45 (Cardbus, Hurricane ASIC)
        !            67:  * 3Com 3cxfem656b     10/100Mbps/RJ-45 (Cardbus, Hurricane ASIC)
        !            68:  * 3Com 3cxfem656c     10/100Mbps/RJ-45 (Cardbus, Tornado ASIC)
        !            69:  * Dell Optiplex GX1 on-board 3c918 10/100Mbps/RJ-45
        !            70:  * Dell on-board 3c920 10/100Mbps/RJ-45
        !            71:  * Dell Precision on-board 3c905B 10/100Mbps/RJ-45
        !            72:  * Dell Latitude laptop docking station embedded 3c905-TX
        !            73:  *
        !            74:  * Written by Bill Paul <wpaul@ctr.columbia.edu>
        !            75:  * Electrical Engineering Department
        !            76:  * Columbia University, New York City
        !            77:  */
        !            78:
        !            79: /*
        !            80:  * The 3c90x series chips use a bus-master DMA interface for transfering
        !            81:  * packets to and from the controller chip. Some of the "vortex" cards
        !            82:  * (3c59x) also supported a bus master mode, however for those chips
        !            83:  * you could only DMA packets to/from a contiguous memory buffer. For
        !            84:  * transmission this would mean copying the contents of the queued mbuf
        !            85:  * chain into an mbuf cluster and then DMAing the cluster. This extra
        !            86:  * copy would sort of defeat the purpose of the bus master support for
        !            87:  * any packet that doesn't fit into a single mbuf.
        !            88:  *
        !            89:  * By contrast, the 3c90x cards support a fragment-based bus master
        !            90:  * mode where mbuf chains can be encapsulated using TX descriptors.
        !            91:  * This is similar to other PCI chips such as the Texas Instruments
        !            92:  * ThunderLAN and the Intel 82557/82558.
        !            93:  *
        !            94:  * The "vortex" driver (if_vx.c) happens to work for the "boomerang"
        !            95:  * bus master chips because they maintain the old PIO interface for
        !            96:  * backwards compatibility, but starting with the 3c905B and the
        !            97:  * "cyclone" chips, the compatibility interface has been dropped.
        !            98:  * Since using bus master DMA is a big win, we use this driver to
        !            99:  * support the PCI "boomerang" chips even though they work with the
        !           100:  * "vortex" driver in order to obtain better performance.
        !           101:  */
        !           102:
        !           103: #include "bpfilter.h"
        !           104:
        !           105: #include <sys/param.h>
        !           106: #include <sys/systm.h>
        !           107: #include <sys/mbuf.h>
        !           108: #include <sys/protosw.h>
        !           109: #include <sys/socket.h>
        !           110: #include <sys/ioctl.h>
        !           111: #include <sys/errno.h>
        !           112: #include <sys/malloc.h>
        !           113: #include <sys/kernel.h>
        !           114: #include <sys/proc.h>   /* only for declaration of wakeup() used by vm.h */
        !           115: #include <sys/device.h>
        !           116:
        !           117: #include <net/if.h>
        !           118: #include <net/if_dl.h>
        !           119: #include <net/if_types.h>
        !           120: #include <net/if_media.h>
        !           121:
        !           122: #ifdef INET
        !           123: #include <netinet/in.h>
        !           124: #include <netinet/in_systm.h>
        !           125: #include <netinet/in_var.h>
        !           126: #include <netinet/ip.h>
        !           127: #include <netinet/if_ether.h>
        !           128: #endif
        !           129:
        !           130: #include <dev/mii/mii.h>
        !           131: #include <dev/mii/miivar.h>
        !           132:
        !           133: #include <machine/bus.h>
        !           134:
        !           135: #if NBPFILTER > 0
        !           136: #include <net/bpf.h>
        !           137: #endif
        !           138:
        !           139: #include <dev/ic/xlreg.h>
        !           140:
        !           141: /*
        !           142:  * TX Checksumming is disabled by default for two reasons:
        !           143:  * - TX Checksumming will occasionally produce corrupt packets
        !           144:  * - TX Checksumming seems to reduce performance
        !           145:  *
        !           146:  * Only 905B/C cards were reported to have this problem, it is possible
        !           147:  * that later chips _may_ be immune.
        !           148:  */
        !           149: #define        XL905B_TXCSUM_BROKEN    1
        !           150:
        !           151: int xl_newbuf(struct xl_softc *, struct xl_chain_onefrag *);
        !           152: void xl_stats_update(void *);
        !           153: int xl_encap(struct xl_softc *, struct xl_chain *,
        !           154:     struct mbuf * );
        !           155: void xl_rxeof(struct xl_softc *);
        !           156: int xl_rx_resync(struct xl_softc *);
        !           157: void xl_txeof(struct xl_softc *);
        !           158: void xl_txeof_90xB(struct xl_softc *);
        !           159: void xl_txeoc(struct xl_softc *);
        !           160: int xl_intr(void *);
        !           161: void xl_start(struct ifnet *);
        !           162: void xl_start_90xB(struct ifnet *);
        !           163: int xl_ioctl(struct ifnet *, u_long, caddr_t);
        !           164: void xl_init(void *);
        !           165: void xl_stop(struct xl_softc *);
        !           166: void xl_freetxrx(struct xl_softc *);
        !           167: void xl_watchdog(struct ifnet *);
        !           168: void xl_shutdown(void *);
        !           169: int xl_ifmedia_upd(struct ifnet *);
        !           170: void xl_ifmedia_sts(struct ifnet *, struct ifmediareq *);
        !           171:
        !           172: int xl_eeprom_wait(struct xl_softc *);
        !           173: int xl_read_eeprom(struct xl_softc *, caddr_t, int, int, int);
        !           174: void xl_mii_sync(struct xl_softc *);
        !           175: void xl_mii_send(struct xl_softc *, u_int32_t, int);
        !           176: int xl_mii_readreg(struct xl_softc *, struct xl_mii_frame *);
        !           177: int xl_mii_writereg(struct xl_softc *, struct xl_mii_frame *);
        !           178:
        !           179: void xl_setcfg(struct xl_softc *);
        !           180: void xl_setmode(struct xl_softc *, int);
        !           181: void xl_setmulti(struct xl_softc *);
        !           182: void xl_setmulti_hash(struct xl_softc *);
        !           183: void xl_setpromisc(struct xl_softc *);
        !           184: void xl_reset(struct xl_softc *);
        !           185: int xl_list_rx_init(struct xl_softc *);
        !           186: int xl_list_tx_init(struct xl_softc *);
        !           187: int xl_list_tx_init_90xB(struct xl_softc *);
        !           188: void xl_wait(struct xl_softc *);
        !           189: void xl_mediacheck(struct xl_softc *);
        !           190: void xl_choose_xcvr(struct xl_softc *, int);
        !           191: #ifdef notdef
        !           192: void xl_testpacket(struct xl_softc *);
        !           193: #endif
        !           194:
        !           195: int xl_miibus_readreg(struct device *, int, int);
        !           196: void xl_miibus_writereg(struct device *, int, int, int);
        !           197: void xl_miibus_statchg(struct device *);
        !           198:
        !           199: void xl_power(int, void *);
        !           200:
        !           201: void
        !           202: xl_power(int why, void *arg)
        !           203: {
        !           204:        struct xl_softc *sc = arg;
        !           205:        struct ifnet *ifp;
        !           206:        int s;
        !           207:
        !           208:        s = splnet();
        !           209:        if (why != PWR_RESUME)
        !           210:                xl_stop(sc);
        !           211:        else {
        !           212:                ifp = &sc->sc_arpcom.ac_if;
        !           213:                if (ifp->if_flags & IFF_UP) {
        !           214:                        xl_reset(sc);
        !           215:                        xl_init(sc);
        !           216:                }
        !           217:        }
        !           218:        splx(s);
        !           219: }
        !           220:
        !           221: /*
        !           222:  * Murphy's law says that it's possible the chip can wedge and
        !           223:  * the 'command in progress' bit may never clear. Hence, we wait
        !           224:  * only a finite amount of time to avoid getting caught in an
        !           225:  * infinite loop. Normally this delay routine would be a macro,
        !           226:  * but it isn't called during normal operation so we can afford
        !           227:  * to make it a function.
        !           228:  */
        !           229: void
        !           230: xl_wait(struct xl_softc *sc)
        !           231: {
        !           232:        int     i;
        !           233:
        !           234:        for (i = 0; i < XL_TIMEOUT; i++) {
        !           235:                if (!(CSR_READ_2(sc, XL_STATUS) & XL_STAT_CMDBUSY))
        !           236:                        break;
        !           237:        }
        !           238:
        !           239:        if (i == XL_TIMEOUT)
        !           240:                printf("%s: command never completed!\n", sc->sc_dev.dv_xname);
        !           241: }
        !           242:
        !           243: /*
        !           244:  * MII access routines are provided for adapters with external
        !           245:  * PHYs (3c905-TX, 3c905-T4, 3c905B-T4) and those with built-in
        !           246:  * autoneg logic that's faked up to look like a PHY (3c905B-TX).
        !           247:  * Note: if you don't perform the MDIO operations just right,
        !           248:  * it's possible to end up with code that works correctly with
        !           249:  * some chips/CPUs/processor speeds/bus speeds/etc but not
        !           250:  * with others.
        !           251:  */
        !           252: #define MII_SET(x)                                     \
        !           253:        CSR_WRITE_2(sc, XL_W4_PHY_MGMT,                 \
        !           254:                CSR_READ_2(sc, XL_W4_PHY_MGMT) | (x))
        !           255:
        !           256: #define MII_CLR(x)                                     \
        !           257:        CSR_WRITE_2(sc, XL_W4_PHY_MGMT,                 \
        !           258:                CSR_READ_2(sc, XL_W4_PHY_MGMT) & ~(x))
        !           259:
        !           260: /*
        !           261:  * Sync the PHYs by setting data bit and strobing the clock 32 times.
        !           262:  */
        !           263: void
        !           264: xl_mii_sync(struct xl_softc *sc)
        !           265: {
        !           266:        int     i;
        !           267:
        !           268:        XL_SEL_WIN(4);
        !           269:        MII_SET(XL_MII_DIR|XL_MII_DATA);
        !           270:
        !           271:        for (i = 0; i < 32; i++) {
        !           272:                MII_SET(XL_MII_CLK);
        !           273:                MII_SET(XL_MII_DATA);
        !           274:                MII_SET(XL_MII_DATA);
        !           275:                MII_CLR(XL_MII_CLK);
        !           276:                MII_SET(XL_MII_DATA);
        !           277:                MII_SET(XL_MII_DATA);
        !           278:        }
        !           279: }
        !           280:
        !           281: /*
        !           282:  * Clock a series of bits through the MII.
        !           283:  */
        !           284: void
        !           285: xl_mii_send(struct xl_softc *sc, u_int32_t bits, int cnt)
        !           286: {
        !           287:        int     i;
        !           288:
        !           289:        XL_SEL_WIN(4);
        !           290:        MII_CLR(XL_MII_CLK);
        !           291:
        !           292:        for (i = (0x1 << (cnt - 1)); i; i >>= 1) {
        !           293:                 if (bits & i) {
        !           294:                        MII_SET(XL_MII_DATA);
        !           295:                 } else {
        !           296:                        MII_CLR(XL_MII_DATA);
        !           297:                 }
        !           298:                MII_CLR(XL_MII_CLK);
        !           299:                MII_SET(XL_MII_CLK);
        !           300:        }
        !           301: }
        !           302:
        !           303: /*
        !           304:  * Read an PHY register through the MII.
        !           305:  */
        !           306: int
        !           307: xl_mii_readreg(struct xl_softc *sc, struct xl_mii_frame *frame)
        !           308: {
        !           309:        int     i, ack, s;
        !           310:
        !           311:        s = splnet();
        !           312:
        !           313:        /*
        !           314:         * Set up frame for RX.
        !           315:         */
        !           316:        frame->mii_stdelim = XL_MII_STARTDELIM;
        !           317:        frame->mii_opcode = XL_MII_READOP;
        !           318:        frame->mii_turnaround = 0;
        !           319:        frame->mii_data = 0;
        !           320:
        !           321:        /*
        !           322:         * Select register window 4.
        !           323:         */
        !           324:
        !           325:        XL_SEL_WIN(4);
        !           326:
        !           327:        CSR_WRITE_2(sc, XL_W4_PHY_MGMT, 0);
        !           328:        /*
        !           329:         * Turn on data xmit.
        !           330:         */
        !           331:        MII_SET(XL_MII_DIR);
        !           332:
        !           333:        xl_mii_sync(sc);
        !           334:
        !           335:        /*
        !           336:         * Send command/address info.
        !           337:         */
        !           338:        xl_mii_send(sc, frame->mii_stdelim, 2);
        !           339:        xl_mii_send(sc, frame->mii_opcode, 2);
        !           340:        xl_mii_send(sc, frame->mii_phyaddr, 5);
        !           341:        xl_mii_send(sc, frame->mii_regaddr, 5);
        !           342:
        !           343:        /* Idle bit */
        !           344:        MII_CLR((XL_MII_CLK|XL_MII_DATA));
        !           345:        MII_SET(XL_MII_CLK);
        !           346:
        !           347:        /* Turn off xmit. */
        !           348:        MII_CLR(XL_MII_DIR);
        !           349:
        !           350:        /* Check for ack */
        !           351:        MII_CLR(XL_MII_CLK);
        !           352:        ack = CSR_READ_2(sc, XL_W4_PHY_MGMT) & XL_MII_DATA;
        !           353:        MII_SET(XL_MII_CLK);
        !           354:
        !           355:        /*
        !           356:         * Now try reading data bits. If the ack failed, we still
        !           357:         * need to clock through 16 cycles to keep the PHY(s) in sync.
        !           358:         */
        !           359:        if (ack) {
        !           360:                for(i = 0; i < 16; i++) {
        !           361:                        MII_CLR(XL_MII_CLK);
        !           362:                        MII_SET(XL_MII_CLK);
        !           363:                }
        !           364:                goto fail;
        !           365:        }
        !           366:
        !           367:        for (i = 0x8000; i; i >>= 1) {
        !           368:                MII_CLR(XL_MII_CLK);
        !           369:                if (!ack) {
        !           370:                        if (CSR_READ_2(sc, XL_W4_PHY_MGMT) & XL_MII_DATA)
        !           371:                                frame->mii_data |= i;
        !           372:                }
        !           373:                MII_SET(XL_MII_CLK);
        !           374:        }
        !           375:
        !           376: fail:
        !           377:
        !           378:        MII_CLR(XL_MII_CLK);
        !           379:        MII_SET(XL_MII_CLK);
        !           380:
        !           381:        splx(s);
        !           382:
        !           383:        if (ack)
        !           384:                return (1);
        !           385:        return (0);
        !           386: }
        !           387:
        !           388: /*
        !           389:  * Write to a PHY register through the MII.
        !           390:  */
        !           391: int
        !           392: xl_mii_writereg(struct xl_softc *sc, struct xl_mii_frame *frame)
        !           393: {
        !           394:        int     s;
        !           395:
        !           396:        s = splnet();
        !           397:
        !           398:        /*
        !           399:         * Set up frame for TX.
        !           400:         */
        !           401:
        !           402:        frame->mii_stdelim = XL_MII_STARTDELIM;
        !           403:        frame->mii_opcode = XL_MII_WRITEOP;
        !           404:        frame->mii_turnaround = XL_MII_TURNAROUND;
        !           405:
        !           406:        /*
        !           407:         * Select the window 4.
        !           408:         */
        !           409:        XL_SEL_WIN(4);
        !           410:
        !           411:        /*
        !           412:         * Turn on data output.
        !           413:         */
        !           414:        MII_SET(XL_MII_DIR);
        !           415:
        !           416:        xl_mii_sync(sc);
        !           417:
        !           418:        xl_mii_send(sc, frame->mii_stdelim, 2);
        !           419:        xl_mii_send(sc, frame->mii_opcode, 2);
        !           420:        xl_mii_send(sc, frame->mii_phyaddr, 5);
        !           421:        xl_mii_send(sc, frame->mii_regaddr, 5);
        !           422:        xl_mii_send(sc, frame->mii_turnaround, 2);
        !           423:        xl_mii_send(sc, frame->mii_data, 16);
        !           424:
        !           425:        /* Idle bit. */
        !           426:        MII_SET(XL_MII_CLK);
        !           427:        MII_CLR(XL_MII_CLK);
        !           428:
        !           429:        /*
        !           430:         * Turn off xmit.
        !           431:         */
        !           432:        MII_CLR(XL_MII_DIR);
        !           433:
        !           434:        splx(s);
        !           435:
        !           436:        return (0);
        !           437: }
        !           438:
        !           439: int
        !           440: xl_miibus_readreg(struct device *self, int phy, int reg)
        !           441: {
        !           442:        struct xl_softc *sc = (struct xl_softc *)self;
        !           443:        struct xl_mii_frame     frame;
        !           444:
        !           445:        if (!(sc->xl_flags & XL_FLAG_PHYOK) && phy != 24)
        !           446:                return (0);
        !           447:
        !           448:        bzero((char *)&frame, sizeof(frame));
        !           449:
        !           450:        frame.mii_phyaddr = phy;
        !           451:        frame.mii_regaddr = reg;
        !           452:        xl_mii_readreg(sc, &frame);
        !           453:
        !           454:        return (frame.mii_data);
        !           455: }
        !           456:
        !           457: void
        !           458: xl_miibus_writereg(struct device *self, int phy, int reg, int data)
        !           459: {
        !           460:        struct xl_softc *sc = (struct xl_softc *)self;
        !           461:        struct xl_mii_frame     frame;
        !           462:
        !           463:        if (!(sc->xl_flags & XL_FLAG_PHYOK) && phy != 24)
        !           464:                return;
        !           465:
        !           466:        bzero((char *)&frame, sizeof(frame));
        !           467:
        !           468:        frame.mii_phyaddr = phy;
        !           469:        frame.mii_regaddr = reg;
        !           470:        frame.mii_data = data;
        !           471:
        !           472:        xl_mii_writereg(sc, &frame);
        !           473: }
        !           474:
        !           475: void
        !           476: xl_miibus_statchg(struct device *self)
        !           477: {
        !           478:        struct xl_softc *sc = (struct xl_softc *)self;
        !           479:
        !           480:        xl_setcfg(sc);
        !           481:
        !           482:        /* Set ASIC's duplex mode to match the PHY. */
        !           483:        XL_SEL_WIN(3);
        !           484:        if ((sc->sc_mii.mii_media_active & IFM_GMASK) == IFM_FDX)
        !           485:                CSR_WRITE_1(sc, XL_W3_MAC_CTRL, XL_MACCTRL_DUPLEX);
        !           486:        else
        !           487:                CSR_WRITE_1(sc, XL_W3_MAC_CTRL,
        !           488:                    (CSR_READ_1(sc, XL_W3_MAC_CTRL) & ~XL_MACCTRL_DUPLEX));
        !           489: }
        !           490:
        !           491: /*
        !           492:  * The EEPROM is slow: give it time to come ready after issuing
        !           493:  * it a command.
        !           494:  */
        !           495: int
        !           496: xl_eeprom_wait(struct xl_softc *sc)
        !           497: {
        !           498:        int     i;
        !           499:
        !           500:        for (i = 0; i < 100; i++) {
        !           501:                if (CSR_READ_2(sc, XL_W0_EE_CMD) & XL_EE_BUSY)
        !           502:                        DELAY(162);
        !           503:                else
        !           504:                        break;
        !           505:        }
        !           506:
        !           507:        if (i == 100) {
        !           508:                printf("%s: eeprom failed to come ready\n", sc->sc_dev.dv_xname);
        !           509:                return (1);
        !           510:        }
        !           511:
        !           512:        return (0);
        !           513: }
        !           514:
        !           515: /*
        !           516:  * Read a sequence of words from the EEPROM. Note that ethernet address
        !           517:  * data is stored in the EEPROM in network byte order.
        !           518:  */
        !           519: int
        !           520: xl_read_eeprom(struct xl_softc *sc, caddr_t dest, int off, int cnt, int swap)
        !           521: {
        !           522:        int             err = 0, i;
        !           523:        u_int16_t       word = 0, *ptr;
        !           524: #define EEPROM_5BIT_OFFSET(A) ((((A) << 2) & 0x7F00) | ((A) & 0x003F))
        !           525: #define EEPROM_8BIT_OFFSET(A) ((A) & 0x003F)
        !           526:        /* WARNING! DANGER!
        !           527:         * It's easy to accidentally overwrite the rom content!
        !           528:         * Note: the 3c575 uses 8bit EEPROM offsets.
        !           529:         */
        !           530:        XL_SEL_WIN(0);
        !           531:
        !           532:        if (xl_eeprom_wait(sc))
        !           533:                return (1);
        !           534:
        !           535:        if (sc->xl_flags & XL_FLAG_EEPROM_OFFSET_30)
        !           536:                off += 0x30;
        !           537:
        !           538:        for (i = 0; i < cnt; i++) {
        !           539:                if (sc->xl_flags & XL_FLAG_8BITROM)
        !           540:                        CSR_WRITE_2(sc, XL_W0_EE_CMD,
        !           541:                            XL_EE_8BIT_READ | EEPROM_8BIT_OFFSET(off + i));
        !           542:                else
        !           543:                        CSR_WRITE_2(sc, XL_W0_EE_CMD,
        !           544:                            XL_EE_READ | EEPROM_5BIT_OFFSET(off + i));
        !           545:                err = xl_eeprom_wait(sc);
        !           546:                if (err)
        !           547:                        break;
        !           548:                word = CSR_READ_2(sc, XL_W0_EE_DATA);
        !           549:                ptr = (u_int16_t *)(dest + (i * 2));
        !           550:                if (swap)
        !           551:                        *ptr = ntohs(word);
        !           552:                else
        !           553:                        *ptr = word;
        !           554:        }
        !           555:
        !           556:        return (err ? 1 : 0);
        !           557: }
        !           558:
        !           559: /*
        !           560:  * NICs older than the 3c905B have only one multicast option, which
        !           561:  * is to enable reception of all multicast frames.
        !           562:  */
        !           563: void
        !           564: xl_setmulti(struct xl_softc *sc)
        !           565: {
        !           566:        struct ifnet    *ifp;
        !           567:        struct arpcom   *ac = &sc->sc_arpcom;
        !           568:        u_int8_t        rxfilt;
        !           569:
        !           570:        ifp = &sc->sc_arpcom.ac_if;
        !           571:
        !           572:        XL_SEL_WIN(5);
        !           573:        rxfilt = CSR_READ_1(sc, XL_W5_RX_FILTER);
        !           574:
        !           575:        if (ifp->if_flags & IFF_ALLMULTI) {
        !           576:                rxfilt |= XL_RXFILTER_ALLMULTI;
        !           577:                CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_SET_FILT|rxfilt);
        !           578:                return;
        !           579:        }
        !           580:
        !           581:        if (ac->ac_multicnt > 0)
        !           582:                rxfilt |= XL_RXFILTER_ALLMULTI;
        !           583:        else
        !           584:                rxfilt &= ~XL_RXFILTER_ALLMULTI;
        !           585:
        !           586:        CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_SET_FILT|rxfilt);
        !           587: }
        !           588:
        !           589: /*
        !           590:  * 3c905B adapters have a hash filter that we can program.
        !           591:  */
        !           592: void
        !           593: xl_setmulti_hash(struct xl_softc *sc)
        !           594: {
        !           595:        struct ifnet    *ifp;
        !           596:        int             h = 0, i;
        !           597:        struct arpcom   *ac = &sc->sc_arpcom;
        !           598:        struct ether_multi *enm;
        !           599:        struct ether_multistep step;
        !           600:        u_int8_t        rxfilt;
        !           601:        int             mcnt = 0;
        !           602:
        !           603:        ifp = &sc->sc_arpcom.ac_if;
        !           604:
        !           605:        XL_SEL_WIN(5);
        !           606:        rxfilt = CSR_READ_1(sc, XL_W5_RX_FILTER);
        !           607:
        !           608:        if (ifp->if_flags & IFF_ALLMULTI) {
        !           609: allmulti:
        !           610:                rxfilt |= XL_RXFILTER_ALLMULTI;
        !           611:                CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_SET_FILT|rxfilt);
        !           612:                return;
        !           613:        } else
        !           614:                rxfilt &= ~XL_RXFILTER_ALLMULTI;
        !           615:
        !           616:
        !           617:        /* first, zot all the existing hash bits */
        !           618:        for (i = 0; i < XL_HASHFILT_SIZE; i++)
        !           619:                CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_SET_HASH|i);
        !           620:
        !           621:        /* now program new ones */
        !           622:        ETHER_FIRST_MULTI(step, ac, enm);
        !           623:        while (enm != NULL) {
        !           624:                if (bcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) {
        !           625:                        ifp->if_flags |= IFF_ALLMULTI;
        !           626:                        goto allmulti;
        !           627:                }
        !           628:                h = ether_crc32_be(enm->enm_addrlo, ETHER_ADDR_LEN) &
        !           629:                    0x000000FF;
        !           630:                CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_SET_HASH|XL_HASH_SET|h);
        !           631:                mcnt++;
        !           632:                ETHER_NEXT_MULTI(step, enm);
        !           633:        }
        !           634:
        !           635:        if (mcnt)
        !           636:                rxfilt |= XL_RXFILTER_MULTIHASH;
        !           637:        else
        !           638:                rxfilt &= ~XL_RXFILTER_MULTIHASH;
        !           639:
        !           640:        CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_SET_FILT|rxfilt);
        !           641: }
        !           642:
        !           643: void
        !           644: xl_setpromisc(struct xl_softc *sc)
        !           645: {
        !           646:        struct ifnet *ifp;
        !           647:        u_int8_t rxfilt;
        !           648:
        !           649:        ifp = &sc->sc_arpcom.ac_if;
        !           650:
        !           651:        XL_SEL_WIN(5);
        !           652:        rxfilt = CSR_READ_1(sc, XL_W5_RX_FILTER);
        !           653:
        !           654:        if (ifp->if_flags & IFF_PROMISC)
        !           655:                rxfilt |= XL_RXFILTER_ALLFRAMES;
        !           656:        else
        !           657:                rxfilt &= ~XL_RXFILTER_ALLFRAMES;
        !           658:
        !           659:        CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_SET_FILT|rxfilt);
        !           660: }
        !           661:
        !           662:
        !           663: #ifdef notdef
        !           664: void
        !           665: xl_testpacket(struct xl_softc *sc)
        !           666: {
        !           667:        struct mbuf     *m;
        !           668:        struct ifnet    *ifp;
        !           669:        int             error;
        !           670:
        !           671:        ifp = &sc->sc_arpcom.ac_if;
        !           672:
        !           673:        MGETHDR(m, M_DONTWAIT, MT_DATA);
        !           674:
        !           675:        if (m == NULL)
        !           676:                return;
        !           677:
        !           678:        bcopy(&sc->sc_arpcom.ac_enaddr,
        !           679:                mtod(m, struct ether_header *)->ether_dhost, ETHER_ADDR_LEN);
        !           680:        bcopy(&sc->sc_arpcom.ac_enaddr,
        !           681:                mtod(m, struct ether_header *)->ether_shost, ETHER_ADDR_LEN);
        !           682:        mtod(m, struct ether_header *)->ether_type = htons(3);
        !           683:        mtod(m, unsigned char *)[14] = 0;
        !           684:        mtod(m, unsigned char *)[15] = 0;
        !           685:        mtod(m, unsigned char *)[16] = 0xE3;
        !           686:        m->m_len = m->m_pkthdr.len = sizeof(struct ether_header) + 3;
        !           687:        IFQ_ENQUEUE(&ifp->if_snd, m, NULL, error);
        !           688:        xl_start(ifp);
        !           689: }
        !           690: #endif
        !           691:
        !           692: void
        !           693: xl_setcfg(struct xl_softc *sc)
        !           694: {
        !           695:        u_int32_t icfg;
        !           696:
        !           697:        XL_SEL_WIN(3);
        !           698:        icfg = CSR_READ_4(sc, XL_W3_INTERNAL_CFG);
        !           699:        icfg &= ~XL_ICFG_CONNECTOR_MASK;
        !           700:        if (sc->xl_media & XL_MEDIAOPT_MII ||
        !           701:                sc->xl_media & XL_MEDIAOPT_BT4)
        !           702:                icfg |= (XL_XCVR_MII << XL_ICFG_CONNECTOR_BITS);
        !           703:        if (sc->xl_media & XL_MEDIAOPT_BTX)
        !           704:                icfg |= (XL_XCVR_AUTO << XL_ICFG_CONNECTOR_BITS);
        !           705:
        !           706:        CSR_WRITE_4(sc, XL_W3_INTERNAL_CFG, icfg);
        !           707:        CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_COAX_STOP);
        !           708: }
        !           709:
        !           710: void
        !           711: xl_setmode(struct xl_softc *sc, int media)
        !           712: {
        !           713:        struct ifnet *ifp = &sc->sc_arpcom.ac_if;
        !           714:        u_int32_t icfg;
        !           715:        u_int16_t mediastat;
        !           716:
        !           717:        XL_SEL_WIN(4);
        !           718:        mediastat = CSR_READ_2(sc, XL_W4_MEDIA_STATUS);
        !           719:        XL_SEL_WIN(3);
        !           720:        icfg = CSR_READ_4(sc, XL_W3_INTERNAL_CFG);
        !           721:
        !           722:        if (sc->xl_media & XL_MEDIAOPT_BT) {
        !           723:                if (IFM_SUBTYPE(media) == IFM_10_T) {
        !           724:                        ifp->if_baudrate = IF_Mbps(10);
        !           725:                        sc->xl_xcvr = XL_XCVR_10BT;
        !           726:                        icfg &= ~XL_ICFG_CONNECTOR_MASK;
        !           727:                        icfg |= (XL_XCVR_10BT << XL_ICFG_CONNECTOR_BITS);
        !           728:                        mediastat |= XL_MEDIASTAT_LINKBEAT|
        !           729:                                        XL_MEDIASTAT_JABGUARD;
        !           730:                        mediastat &= ~XL_MEDIASTAT_SQEENB;
        !           731:                }
        !           732:        }
        !           733:
        !           734:        if (sc->xl_media & XL_MEDIAOPT_BFX) {
        !           735:                if (IFM_SUBTYPE(media) == IFM_100_FX) {
        !           736:                        ifp->if_baudrate = IF_Mbps(100);
        !           737:                        sc->xl_xcvr = XL_XCVR_100BFX;
        !           738:                        icfg &= ~XL_ICFG_CONNECTOR_MASK;
        !           739:                        icfg |= (XL_XCVR_100BFX << XL_ICFG_CONNECTOR_BITS);
        !           740:                        mediastat |= XL_MEDIASTAT_LINKBEAT;
        !           741:                        mediastat &= ~XL_MEDIASTAT_SQEENB;
        !           742:                }
        !           743:        }
        !           744:
        !           745:        if (sc->xl_media & (XL_MEDIAOPT_AUI|XL_MEDIAOPT_10FL)) {
        !           746:                if (IFM_SUBTYPE(media) == IFM_10_5) {
        !           747:                        ifp->if_baudrate = IF_Mbps(10);
        !           748:                        sc->xl_xcvr = XL_XCVR_AUI;
        !           749:                        icfg &= ~XL_ICFG_CONNECTOR_MASK;
        !           750:                        icfg |= (XL_XCVR_AUI << XL_ICFG_CONNECTOR_BITS);
        !           751:                        mediastat &= ~(XL_MEDIASTAT_LINKBEAT|
        !           752:                                        XL_MEDIASTAT_JABGUARD);
        !           753:                        mediastat |= ~XL_MEDIASTAT_SQEENB;
        !           754:                }
        !           755:                if (IFM_SUBTYPE(media) == IFM_10_FL) {
        !           756:                        ifp->if_baudrate = IF_Mbps(10);
        !           757:                        sc->xl_xcvr = XL_XCVR_AUI;
        !           758:                        icfg &= ~XL_ICFG_CONNECTOR_MASK;
        !           759:                        icfg |= (XL_XCVR_AUI << XL_ICFG_CONNECTOR_BITS);
        !           760:                        mediastat &= ~(XL_MEDIASTAT_LINKBEAT|
        !           761:                                        XL_MEDIASTAT_JABGUARD);
        !           762:                        mediastat |= ~XL_MEDIASTAT_SQEENB;
        !           763:                }
        !           764:        }
        !           765:
        !           766:        if (sc->xl_media & XL_MEDIAOPT_BNC) {
        !           767:                if (IFM_SUBTYPE(media) == IFM_10_2) {
        !           768:                        ifp->if_baudrate = IF_Mbps(10);
        !           769:                        sc->xl_xcvr = XL_XCVR_COAX;
        !           770:                        icfg &= ~XL_ICFG_CONNECTOR_MASK;
        !           771:                        icfg |= (XL_XCVR_COAX << XL_ICFG_CONNECTOR_BITS);
        !           772:                        mediastat &= ~(XL_MEDIASTAT_LINKBEAT|
        !           773:                                        XL_MEDIASTAT_JABGUARD|
        !           774:                                        XL_MEDIASTAT_SQEENB);
        !           775:                }
        !           776:        }
        !           777:
        !           778:        if ((media & IFM_GMASK) == IFM_FDX ||
        !           779:                        IFM_SUBTYPE(media) == IFM_100_FX) {
        !           780:                XL_SEL_WIN(3);
        !           781:                CSR_WRITE_1(sc, XL_W3_MAC_CTRL, XL_MACCTRL_DUPLEX);
        !           782:        } else {
        !           783:                XL_SEL_WIN(3);
        !           784:                CSR_WRITE_1(sc, XL_W3_MAC_CTRL,
        !           785:                        (CSR_READ_1(sc, XL_W3_MAC_CTRL) & ~XL_MACCTRL_DUPLEX));
        !           786:        }
        !           787:
        !           788:        if (IFM_SUBTYPE(media) == IFM_10_2)
        !           789:                CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_COAX_START);
        !           790:        else
        !           791:                CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_COAX_STOP);
        !           792:        CSR_WRITE_4(sc, XL_W3_INTERNAL_CFG, icfg);
        !           793:        XL_SEL_WIN(4);
        !           794:        CSR_WRITE_2(sc, XL_W4_MEDIA_STATUS, mediastat);
        !           795:        DELAY(800);
        !           796:        XL_SEL_WIN(7);
        !           797: }
        !           798:
        !           799: void
        !           800: xl_reset(struct xl_softc *sc)
        !           801: {
        !           802:        int     i;
        !           803:
        !           804:        XL_SEL_WIN(0);
        !           805:        CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RESET |
        !           806:                    ((sc->xl_flags & XL_FLAG_WEIRDRESET) ?
        !           807:                     XL_RESETOPT_DISADVFD:0));
        !           808:
        !           809:        /*
        !           810:         * Pause briefly after issuing the reset command before trying
        !           811:         * to access any other registers. With my 3c575C cardbus card,
        !           812:         * failing to do this results in the system locking up while
        !           813:         * trying to poll the command busy bit in the status register.
        !           814:         */
        !           815:        DELAY(100000);
        !           816:
        !           817:        for (i = 0; i < XL_TIMEOUT; i++) {
        !           818:                DELAY(10);
        !           819:                if (!(CSR_READ_2(sc, XL_STATUS) & XL_STAT_CMDBUSY))
        !           820:                        break;
        !           821:        }
        !           822:
        !           823:        if (i == XL_TIMEOUT)
        !           824:                printf("%s: reset didn't complete\n", sc->sc_dev.dv_xname);
        !           825:
        !           826:        /* Note: the RX reset takes an absurd amount of time
        !           827:         * on newer versions of the Tornado chips such as those
        !           828:         * on the 3c905CX and newer 3c908C cards. We wait an
        !           829:         * extra amount of time so that xl_wait() doesn't complain
        !           830:         * and annoy the users.
        !           831:         */
        !           832:        CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_RESET);
        !           833:        DELAY(100000);
        !           834:        xl_wait(sc);
        !           835:        CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_TX_RESET);
        !           836:        xl_wait(sc);
        !           837:
        !           838:        if (sc->xl_flags & XL_FLAG_INVERT_LED_PWR ||
        !           839:            sc->xl_flags & XL_FLAG_INVERT_MII_PWR) {
        !           840:                XL_SEL_WIN(2);
        !           841:                CSR_WRITE_2(sc, XL_W2_RESET_OPTIONS, CSR_READ_2(sc,
        !           842:                    XL_W2_RESET_OPTIONS)
        !           843:                    | ((sc->xl_flags & XL_FLAG_INVERT_LED_PWR)?XL_RESETOPT_INVERT_LED:0)
        !           844:                    | ((sc->xl_flags & XL_FLAG_INVERT_MII_PWR)?XL_RESETOPT_INVERT_MII:0)
        !           845:                    );
        !           846:        }
        !           847:
        !           848:        /* Wait a little while for the chip to get its brains in order. */
        !           849:        DELAY(100000);
        !           850: }
        !           851:
        !           852: /*
        !           853:  * This routine is a kludge to work around possible hardware faults
        !           854:  * or manufacturing defects that can cause the media options register
        !           855:  * (or reset options register, as it's called for the first generation
        !           856:  * 3c90x adapters) to return an incorrect result. I have encountered
        !           857:  * one Dell Latitude laptop docking station with an integrated 3c905-TX
        !           858:  * which doesn't have any of the 'mediaopt' bits set. This screws up
        !           859:  * the attach routine pretty badly because it doesn't know what media
        !           860:  * to look for. If we find ourselves in this predicament, this routine
        !           861:  * will try to guess the media options values and warn the user of a
        !           862:  * possible manufacturing defect with his adapter/system/whatever.
        !           863:  */
        !           864: void
        !           865: xl_mediacheck(struct xl_softc *sc)
        !           866: {
        !           867:        /*
        !           868:         * If some of the media options bits are set, assume they are
        !           869:         * correct. If not, try to figure it out down below.
        !           870:         * XXX I should check for 10baseFL, but I don't have an adapter
        !           871:         * to test with.
        !           872:         */
        !           873:        if (sc->xl_media & (XL_MEDIAOPT_MASK & ~XL_MEDIAOPT_VCO)) {
        !           874:                /*
        !           875:                 * Check the XCVR value. If it's not in the normal range
        !           876:                 * of values, we need to fake it up here.
        !           877:                 */
        !           878:                if (sc->xl_xcvr <= XL_XCVR_AUTO)
        !           879:                        return;
        !           880:                else {
        !           881:                        printf("%s: bogus xcvr value "
        !           882:                        "in EEPROM (%x)\n", sc->sc_dev.dv_xname, sc->xl_xcvr);
        !           883:                        printf("%s: choosing new default based "
        !           884:                                "on card type\n", sc->sc_dev.dv_xname);
        !           885:                }
        !           886:        } else {
        !           887:                if (sc->xl_type == XL_TYPE_905B &&
        !           888:                    sc->xl_media & XL_MEDIAOPT_10FL)
        !           889:                        return;
        !           890:                printf("%s: WARNING: no media options bits set in "
        !           891:                        "the media options register!!\n", sc->sc_dev.dv_xname);
        !           892:                printf("%s: this could be a manufacturing defect in "
        !           893:                        "your adapter or system\n", sc->sc_dev.dv_xname);
        !           894:                printf("%s: attempting to guess media type; you "
        !           895:                        "should probably consult your vendor\n", sc->sc_dev.dv_xname);
        !           896:        }
        !           897:
        !           898:        xl_choose_xcvr(sc, 1);
        !           899: }
        !           900:
        !           901: void
        !           902: xl_choose_xcvr(struct xl_softc *sc, int verbose)
        !           903: {
        !           904:        u_int16_t devid;
        !           905:
        !           906:        /*
        !           907:         * Read the device ID from the EEPROM.
        !           908:         * This is what's loaded into the PCI device ID register, so it has
        !           909:         * to be correct otherwise we wouldn't have gotten this far.
        !           910:         */
        !           911:        xl_read_eeprom(sc, (caddr_t)&devid, XL_EE_PRODID, 1, 0);
        !           912:
        !           913:        switch(devid) {
        !           914:        case TC_DEVICEID_BOOMERANG_10BT:        /* 3c900-TPO */
        !           915:        case TC_DEVICEID_KRAKATOA_10BT:         /* 3c900B-TPO */
        !           916:                sc->xl_media = XL_MEDIAOPT_BT;
        !           917:                sc->xl_xcvr = XL_XCVR_10BT;
        !           918:                if (verbose)
        !           919:                        printf("%s: guessing 10BaseT transceiver\n",
        !           920:                            sc->sc_dev.dv_xname);
        !           921:                break;
        !           922:        case TC_DEVICEID_BOOMERANG_10BT_COMBO:  /* 3c900-COMBO */
        !           923:        case TC_DEVICEID_KRAKATOA_10BT_COMBO:   /* 3c900B-COMBO */
        !           924:                sc->xl_media = XL_MEDIAOPT_BT|XL_MEDIAOPT_BNC|XL_MEDIAOPT_AUI;
        !           925:                sc->xl_xcvr = XL_XCVR_10BT;
        !           926:                if (verbose)
        !           927:                        printf("%s: guessing COMBO (AUI/BNC/TP)\n",
        !           928:                            sc->sc_dev.dv_xname);
        !           929:                break;
        !           930:        case TC_DEVICEID_KRAKATOA_10BT_TPC:     /* 3c900B-TPC */
        !           931:                sc->xl_media = XL_MEDIAOPT_BT|XL_MEDIAOPT_BNC;
        !           932:                sc->xl_xcvr = XL_XCVR_10BT;
        !           933:                if (verbose)
        !           934:                        printf("%s: guessing TPC (BNC/TP)\n", sc->sc_dev.dv_xname);
        !           935:                break;
        !           936:        case TC_DEVICEID_CYCLONE_10FL:          /* 3c900B-FL */
        !           937:                sc->xl_media = XL_MEDIAOPT_10FL;
        !           938:                sc->xl_xcvr = XL_XCVR_AUI;
        !           939:                if (verbose)
        !           940:                        printf("%s: guessing 10baseFL\n", sc->sc_dev.dv_xname);
        !           941:                break;
        !           942:        case TC_DEVICEID_BOOMERANG_10_100BT:    /* 3c905-TX */
        !           943:        case TC_DEVICEID_HURRICANE_555:         /* 3c555 */
        !           944:        case TC_DEVICEID_HURRICANE_556:         /* 3c556 */
        !           945:        case TC_DEVICEID_HURRICANE_556B:        /* 3c556B */
        !           946:        case TC_DEVICEID_HURRICANE_575A:        /* 3c575TX */
        !           947:        case TC_DEVICEID_HURRICANE_575B:        /* 3c575B */
        !           948:        case TC_DEVICEID_HURRICANE_575C:        /* 3c575C */
        !           949:        case TC_DEVICEID_HURRICANE_656:         /* 3c656 */
        !           950:        case TC_DEVICEID_HURRICANE_656B:        /* 3c656B */
        !           951:        case TC_DEVICEID_TORNADO_656C:          /* 3c656C */
        !           952:        case TC_DEVICEID_TORNADO_10_100BT_920B: /* 3c920B-EMB */
        !           953:                sc->xl_media = XL_MEDIAOPT_MII;
        !           954:                sc->xl_xcvr = XL_XCVR_MII;
        !           955:                if (verbose)
        !           956:                        printf("%s: guessing MII\n", sc->sc_dev.dv_xname);
        !           957:                break;
        !           958:        case TC_DEVICEID_BOOMERANG_100BT4:      /* 3c905-T4 */
        !           959:        case TC_DEVICEID_CYCLONE_10_100BT4:     /* 3c905B-T4 */
        !           960:                sc->xl_media = XL_MEDIAOPT_BT4;
        !           961:                sc->xl_xcvr = XL_XCVR_MII;
        !           962:                if (verbose)
        !           963:                        printf("%s: guessing 100BaseT4/MII\n", sc->sc_dev.dv_xname);
        !           964:                break;
        !           965:        case TC_DEVICEID_HURRICANE_10_100BT:    /* 3c905B-TX */
        !           966:        case TC_DEVICEID_HURRICANE_10_100BT_SERV:/* 3c980-TX */
        !           967:        case TC_DEVICEID_TORNADO_10_100BT_SERV: /* 3c980C-TX */
        !           968:        case TC_DEVICEID_HURRICANE_SOHO100TX:   /* 3cSOHO100-TX */
        !           969:        case TC_DEVICEID_TORNADO_10_100BT:      /* 3c905C-TX */
        !           970:        case TC_DEVICEID_TORNADO_HOMECONNECT:   /* 3c450-TX */
        !           971:                sc->xl_media = XL_MEDIAOPT_BTX;
        !           972:                sc->xl_xcvr = XL_XCVR_AUTO;
        !           973:                if (verbose)
        !           974:                        printf("%s: guessing 10/100 internal\n",
        !           975:                            sc->sc_dev.dv_xname);
        !           976:                break;
        !           977:        case TC_DEVICEID_CYCLONE_10_100_COMBO:  /* 3c905B-COMBO */
        !           978:                sc->xl_media = XL_MEDIAOPT_BTX|XL_MEDIAOPT_BNC|XL_MEDIAOPT_AUI;
        !           979:                sc->xl_xcvr = XL_XCVR_AUTO;
        !           980:                if (verbose)
        !           981:                        printf("%s: guessing 10/100 plus BNC/AUI\n",
        !           982:                            sc->sc_dev.dv_xname);
        !           983:                break;
        !           984:        default:
        !           985:                printf("%s: unknown device ID: %x -- "
        !           986:                        "defaulting to 10baseT\n", sc->sc_dev.dv_xname, devid);
        !           987:                sc->xl_media = XL_MEDIAOPT_BT;
        !           988:                break;
        !           989:        }
        !           990: }
        !           991:
        !           992: /*
        !           993:  * Initialize the transmit descriptors.
        !           994:  */
        !           995: int
        !           996: xl_list_tx_init(struct xl_softc *sc)
        !           997: {
        !           998:        struct xl_chain_data    *cd;
        !           999:        struct xl_list_data     *ld;
        !          1000:        int                     i;
        !          1001:
        !          1002:        cd = &sc->xl_cdata;
        !          1003:        ld = sc->xl_ldata;
        !          1004:        for (i = 0; i < XL_TX_LIST_CNT; i++) {
        !          1005:                cd->xl_tx_chain[i].xl_ptr = &ld->xl_tx_list[i];
        !          1006:                if (i == (XL_TX_LIST_CNT - 1))
        !          1007:                        cd->xl_tx_chain[i].xl_next = NULL;
        !          1008:                else
        !          1009:                        cd->xl_tx_chain[i].xl_next = &cd->xl_tx_chain[i + 1];
        !          1010:        }
        !          1011:
        !          1012:        cd->xl_tx_free = &cd->xl_tx_chain[0];
        !          1013:        cd->xl_tx_tail = cd->xl_tx_head = NULL;
        !          1014:
        !          1015:        return (0);
        !          1016: }
        !          1017:
        !          1018: /*
        !          1019:  * Initialize the transmit descriptors.
        !          1020:  */
        !          1021: int
        !          1022: xl_list_tx_init_90xB(struct xl_softc *sc)
        !          1023: {
        !          1024:        struct xl_chain_data    *cd;
        !          1025:        struct xl_list_data     *ld;
        !          1026:        int                     i, next, prev;
        !          1027:
        !          1028:        cd = &sc->xl_cdata;
        !          1029:        ld = sc->xl_ldata;
        !          1030:        for (i = 0; i < XL_TX_LIST_CNT; i++) {
        !          1031:                if (i == (XL_TX_LIST_CNT - 1))
        !          1032:                        next = 0;
        !          1033:                else
        !          1034:                        next = i + 1;
        !          1035:                if (i == 0)
        !          1036:                        prev = XL_TX_LIST_CNT - 1;
        !          1037:                else
        !          1038:                        prev = i - 1;
        !          1039:                cd->xl_tx_chain[i].xl_ptr = &ld->xl_tx_list[i];
        !          1040:                cd->xl_tx_chain[i].xl_phys =
        !          1041:                    sc->sc_listmap->dm_segs[0].ds_addr +
        !          1042:                    offsetof(struct xl_list_data, xl_tx_list[i]);
        !          1043:                cd->xl_tx_chain[i].xl_next = &cd->xl_tx_chain[next];
        !          1044:                cd->xl_tx_chain[i].xl_prev = &cd->xl_tx_chain[prev];
        !          1045:        }
        !          1046:
        !          1047:        bzero((char *)ld->xl_tx_list, sizeof(struct xl_list) * XL_TX_LIST_CNT);
        !          1048:        ld->xl_tx_list[0].xl_status = htole32(XL_TXSTAT_EMPTY);
        !          1049:
        !          1050:        cd->xl_tx_prod = 1;
        !          1051:        cd->xl_tx_cons = 1;
        !          1052:        cd->xl_tx_cnt = 0;
        !          1053:
        !          1054:        return (0);
        !          1055: }
        !          1056:
        !          1057: /*
        !          1058:  * Initialize the RX descriptors and allocate mbufs for them. Note that
        !          1059:  * we arrange the descriptors in a closed ring, so that the last descriptor
        !          1060:  * points back to the first.
        !          1061:  */
        !          1062: int
        !          1063: xl_list_rx_init(struct xl_softc *sc)
        !          1064: {
        !          1065:        struct xl_chain_data    *cd;
        !          1066:        struct xl_list_data     *ld;
        !          1067:        int                     i, n;
        !          1068:        bus_addr_t              next;
        !          1069:
        !          1070:        cd = &sc->xl_cdata;
        !          1071:        ld = sc->xl_ldata;
        !          1072:
        !          1073:        for (i = 0; i < XL_RX_LIST_CNT; i++) {
        !          1074:                cd->xl_rx_chain[i].xl_ptr =
        !          1075:                        (struct xl_list_onefrag *)&ld->xl_rx_list[i];
        !          1076:                if (xl_newbuf(sc, &cd->xl_rx_chain[i]) == ENOBUFS)
        !          1077:                        return(ENOBUFS);
        !          1078:                if (i == (XL_RX_LIST_CNT - 1))
        !          1079:                        n = 0;
        !          1080:                else
        !          1081:                        n = i + 1;
        !          1082:                cd->xl_rx_chain[i].xl_next = &cd->xl_rx_chain[n];
        !          1083:                next = sc->sc_listmap->dm_segs[0].ds_addr +
        !          1084:                       offsetof(struct xl_list_data, xl_rx_list[n]);
        !          1085:                ld->xl_rx_list[i].xl_next = htole32(next);
        !          1086:        }
        !          1087:
        !          1088:        cd->xl_rx_head = &cd->xl_rx_chain[0];
        !          1089:
        !          1090:        return (0);
        !          1091: }
        !          1092:
        !          1093: /*
        !          1094:  * Initialize an RX descriptor and attach an MBUF cluster.
        !          1095:  */
        !          1096: int
        !          1097: xl_newbuf(struct xl_softc *sc, struct xl_chain_onefrag *c)
        !          1098: {
        !          1099:        struct mbuf     *m_new = NULL;
        !          1100:        bus_dmamap_t    map;
        !          1101:
        !          1102:        MGETHDR(m_new, M_DONTWAIT, MT_DATA);
        !          1103:        if (m_new == NULL)
        !          1104:                return (ENOBUFS);
        !          1105:
        !          1106:        MCLGET(m_new, M_DONTWAIT);
        !          1107:        if (!(m_new->m_flags & M_EXT)) {
        !          1108:                m_freem(m_new);
        !          1109:                return (ENOBUFS);
        !          1110:        }
        !          1111:
        !          1112:        m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
        !          1113:        if (bus_dmamap_load(sc->sc_dmat, sc->sc_rx_sparemap,
        !          1114:            mtod(m_new, caddr_t), MCLBYTES, NULL, BUS_DMA_NOWAIT) != 0) {
        !          1115:                m_freem(m_new);
        !          1116:                return (ENOBUFS);
        !          1117:        }
        !          1118:
        !          1119:        /* sync the old map, and unload it (if necessary) */
        !          1120:        if (c->map->dm_nsegs != 0) {
        !          1121:                bus_dmamap_sync(sc->sc_dmat, c->map,
        !          1122:                    0, c->map->dm_mapsize, BUS_DMASYNC_POSTREAD);
        !          1123:                bus_dmamap_unload(sc->sc_dmat, c->map);
        !          1124:        }
        !          1125:
        !          1126:        map = c->map;
        !          1127:        c->map = sc->sc_rx_sparemap;
        !          1128:        sc->sc_rx_sparemap = map;
        !          1129:
        !          1130:        /* Force longword alignment for packet payload. */
        !          1131:        m_adj(m_new, ETHER_ALIGN);
        !          1132:
        !          1133:        bus_dmamap_sync(sc->sc_dmat, c->map, 0, c->map->dm_mapsize,
        !          1134:            BUS_DMASYNC_PREREAD);
        !          1135:
        !          1136:        c->xl_mbuf = m_new;
        !          1137:        c->xl_ptr->xl_frag.xl_addr =
        !          1138:            htole32(c->map->dm_segs[0].ds_addr + ETHER_ALIGN);
        !          1139:        c->xl_ptr->xl_frag.xl_len =
        !          1140:            htole32(c->map->dm_segs[0].ds_len | XL_LAST_FRAG);
        !          1141:        c->xl_ptr->xl_status = htole32(0);
        !          1142:
        !          1143:        bus_dmamap_sync(sc->sc_dmat, sc->sc_listmap,
        !          1144:            ((caddr_t)c->xl_ptr - sc->sc_listkva), sizeof(struct xl_list),
        !          1145:            BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
        !          1146:
        !          1147:        return (0);
        !          1148: }
        !          1149:
        !          1150: int
        !          1151: xl_rx_resync(struct xl_softc *sc)
        !          1152: {
        !          1153:        struct xl_chain_onefrag *pos;
        !          1154:        int i;
        !          1155:
        !          1156:        pos = sc->xl_cdata.xl_rx_head;
        !          1157:
        !          1158:        for (i = 0; i < XL_RX_LIST_CNT; i++) {
        !          1159:                bus_dmamap_sync(sc->sc_dmat, sc->sc_listmap,
        !          1160:                    ((caddr_t)pos->xl_ptr - sc->sc_listkva),
        !          1161:                    sizeof(struct xl_list),
        !          1162:                    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
        !          1163:
        !          1164:                if (pos->xl_ptr->xl_status)
        !          1165:                        break;
        !          1166:                pos = pos->xl_next;
        !          1167:        }
        !          1168:
        !          1169:        if (i == XL_RX_LIST_CNT)
        !          1170:                return (0);
        !          1171:
        !          1172:        sc->xl_cdata.xl_rx_head = pos;
        !          1173:
        !          1174:        return (EAGAIN);
        !          1175: }
        !          1176:
        !          1177: /*
        !          1178:  * A frame has been uploaded: pass the resulting mbuf chain up to
        !          1179:  * the higher level protocols.
        !          1180:  */
        !          1181: void
        !          1182: xl_rxeof(struct xl_softc *sc)
        !          1183: {
        !          1184:         struct mbuf            *m;
        !          1185:         struct ifnet           *ifp;
        !          1186:        struct xl_chain_onefrag *cur_rx;
        !          1187:        int                     total_len = 0, sumflags = 0;
        !          1188:        u_int32_t               rxstat;
        !          1189:
        !          1190:        ifp = &sc->sc_arpcom.ac_if;
        !          1191:
        !          1192: again:
        !          1193:
        !          1194:        while ((rxstat = letoh32(sc->xl_cdata.xl_rx_head->xl_ptr->xl_status))
        !          1195:            != 0) {
        !          1196:                cur_rx = sc->xl_cdata.xl_rx_head;
        !          1197:                sc->xl_cdata.xl_rx_head = cur_rx->xl_next;
        !          1198:                total_len = rxstat & XL_RXSTAT_LENMASK;
        !          1199:
        !          1200:                bus_dmamap_sync(sc->sc_dmat, sc->sc_listmap,
        !          1201:                    ((caddr_t)cur_rx->xl_ptr - sc->sc_listkva),
        !          1202:                    sizeof(struct xl_list),
        !          1203:                    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
        !          1204:
        !          1205:                /*
        !          1206:                 * Since we have told the chip to allow large frames,
        !          1207:                 * we need to trap giant frame errors in software. We allow
        !          1208:                 * a little more than the normal frame size to account for
        !          1209:                 * frames with VLAN tags.
        !          1210:                 */
        !          1211:                if (total_len > XL_MAX_FRAMELEN)
        !          1212:                        rxstat |= (XL_RXSTAT_UP_ERROR|XL_RXSTAT_OVERSIZE);
        !          1213:
        !          1214:                /*
        !          1215:                 * If an error occurs, update stats, clear the
        !          1216:                 * status word and leave the mbuf cluster in place:
        !          1217:                 * it should simply get re-used next time this descriptor
        !          1218:                 * comes up in the ring.
        !          1219:                 */
        !          1220:                if (rxstat & XL_RXSTAT_UP_ERROR) {
        !          1221:                        ifp->if_ierrors++;
        !          1222:                        cur_rx->xl_ptr->xl_status = htole32(0);
        !          1223:                        continue;
        !          1224:                }
        !          1225:
        !          1226:                /*
        !          1227:                 * If the error bit was not set, the upload complete
        !          1228:                 * bit should be set which means we have a valid packet.
        !          1229:                 * If not, something truly strange has happened.
        !          1230:                 */
        !          1231:                if (!(rxstat & XL_RXSTAT_UP_CMPLT)) {
        !          1232:                        printf("%s: bad receive status -- "
        !          1233:                            "packet dropped\n", sc->sc_dev.dv_xname);
        !          1234:                        ifp->if_ierrors++;
        !          1235:                        cur_rx->xl_ptr->xl_status = htole32(0);
        !          1236:                        continue;
        !          1237:                }
        !          1238:
        !          1239:                /* No errors; receive the packet. */
        !          1240:                m = cur_rx->xl_mbuf;
        !          1241:
        !          1242:                /*
        !          1243:                 * Try to conjure up a new mbuf cluster. If that
        !          1244:                 * fails, it means we have an out of memory condition and
        !          1245:                 * should leave the buffer in place and continue. This will
        !          1246:                 * result in a lost packet, but there's little else we
        !          1247:                 * can do in this situation.
        !          1248:                 */
        !          1249:                if (xl_newbuf(sc, cur_rx) == ENOBUFS) {
        !          1250:                        ifp->if_ierrors++;
        !          1251:                        cur_rx->xl_ptr->xl_status = htole32(0);
        !          1252:                        continue;
        !          1253:                }
        !          1254:
        !          1255:                ifp->if_ipackets++;
        !          1256:                m->m_pkthdr.rcvif = ifp;
        !          1257:                m->m_pkthdr.len = m->m_len = total_len;
        !          1258: #if NBPFILTER > 0
        !          1259:                /*
        !          1260:                 * Handle BPF listeners. Let the BPF user see the packet.
        !          1261:                 */
        !          1262:                if (ifp->if_bpf) {
        !          1263:                        bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
        !          1264:                }
        !          1265: #endif
        !          1266:
        !          1267:                if (sc->xl_type == XL_TYPE_905B) {
        !          1268:                        if (!(rxstat & XL_RXSTAT_IPCKERR) &&
        !          1269:                            (rxstat & XL_RXSTAT_IPCKOK))
        !          1270:                                sumflags |= M_IPV4_CSUM_IN_OK;
        !          1271:
        !          1272:                        if (!(rxstat & XL_RXSTAT_TCPCKERR) &&
        !          1273:                            (rxstat & XL_RXSTAT_TCPCKOK))
        !          1274:                                sumflags |= M_TCP_CSUM_IN_OK;
        !          1275:
        !          1276:                        if (!(rxstat & XL_RXSTAT_UDPCKERR) &&
        !          1277:                            (rxstat & XL_RXSTAT_UDPCKOK))
        !          1278:                                sumflags |= M_UDP_CSUM_IN_OK;
        !          1279:
        !          1280:                        m->m_pkthdr.csum_flags = sumflags;
        !          1281:                }
        !          1282:
        !          1283:                ether_input_mbuf(ifp, m);
        !          1284:        }
        !          1285:
        !          1286:        /*
        !          1287:         * Handle the 'end of channel' condition. When the upload
        !          1288:         * engine hits the end of the RX ring, it will stall. This
        !          1289:         * is our cue to flush the RX ring, reload the uplist pointer
        !          1290:         * register and unstall the engine.
        !          1291:         * XXX This is actually a little goofy. With the ThunderLAN
        !          1292:         * chip, you get an interrupt when the receiver hits the end
        !          1293:         * of the receive ring, which tells you exactly when you
        !          1294:         * you need to reload the ring pointer. Here we have to
        !          1295:         * fake it. I'm mad at myself for not being clever enough
        !          1296:         * to avoid the use of a goto here.
        !          1297:         */
        !          1298:        if (CSR_READ_4(sc, XL_UPLIST_PTR) == 0 ||
        !          1299:                CSR_READ_4(sc, XL_UPLIST_STATUS) & XL_PKTSTAT_UP_STALLED) {
        !          1300:                CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_UP_STALL);
        !          1301:                xl_wait(sc);
        !          1302:                CSR_WRITE_4(sc, XL_UPLIST_PTR,
        !          1303:                    sc->sc_listmap->dm_segs[0].ds_addr +
        !          1304:                    offsetof(struct xl_list_data, xl_rx_list[0]));
        !          1305:                sc->xl_cdata.xl_rx_head = &sc->xl_cdata.xl_rx_chain[0];
        !          1306:                CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_UP_UNSTALL);
        !          1307:                goto again;
        !          1308:        }
        !          1309: }
        !          1310:
        !          1311: /*
        !          1312:  * A frame was downloaded to the chip. It's safe for us to clean up
        !          1313:  * the list buffers.
        !          1314:  */
        !          1315: void
        !          1316: xl_txeof(struct xl_softc *sc)
        !          1317: {
        !          1318:        struct xl_chain         *cur_tx;
        !          1319:        struct ifnet            *ifp;
        !          1320:
        !          1321:        ifp = &sc->sc_arpcom.ac_if;
        !          1322:
        !          1323:        /* Clear the timeout timer. */
        !          1324:        ifp->if_timer = 0;
        !          1325:
        !          1326:        /*
        !          1327:         * Go through our tx list and free mbufs for those
        !          1328:         * frames that have been uploaded. Note: the 3c905B
        !          1329:         * sets a special bit in the status word to let us
        !          1330:         * know that a frame has been downloaded, but the
        !          1331:         * original 3c900/3c905 adapters don't do that.
        !          1332:         * Consequently, we have to use a different test if
        !          1333:         * xl_type != XL_TYPE_905B.
        !          1334:         */
        !          1335:        while (sc->xl_cdata.xl_tx_head != NULL) {
        !          1336:                cur_tx = sc->xl_cdata.xl_tx_head;
        !          1337:
        !          1338:                bus_dmamap_sync(sc->sc_dmat, sc->sc_listmap,
        !          1339:                    ((caddr_t)cur_tx->xl_ptr - sc->sc_listkva),
        !          1340:                    sizeof(struct xl_list),
        !          1341:                    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
        !          1342:
        !          1343:                if (CSR_READ_4(sc, XL_DOWNLIST_PTR))
        !          1344:                        break;
        !          1345:
        !          1346:                sc->xl_cdata.xl_tx_head = cur_tx->xl_next;
        !          1347:                ifp->if_opackets++;
        !          1348:                if (cur_tx->map->dm_nsegs != 0) {
        !          1349:                        bus_dmamap_t map = cur_tx->map;
        !          1350:
        !          1351:                        bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize,
        !          1352:                            BUS_DMASYNC_POSTWRITE);
        !          1353:                        bus_dmamap_unload(sc->sc_dmat, map);
        !          1354:                }
        !          1355:                if (cur_tx->xl_mbuf != NULL) {
        !          1356:                        m_freem(cur_tx->xl_mbuf);
        !          1357:                        cur_tx->xl_mbuf = NULL;
        !          1358:                }
        !          1359:                cur_tx->xl_next = sc->xl_cdata.xl_tx_free;
        !          1360:                sc->xl_cdata.xl_tx_free = cur_tx;
        !          1361:        }
        !          1362:
        !          1363:        if (sc->xl_cdata.xl_tx_head == NULL) {
        !          1364:                ifp->if_flags &= ~IFF_OACTIVE;
        !          1365:                sc->xl_cdata.xl_tx_tail = NULL;
        !          1366:        } else {
        !          1367:                if (CSR_READ_4(sc, XL_DMACTL) & XL_DMACTL_DOWN_STALLED ||
        !          1368:                        !CSR_READ_4(sc, XL_DOWNLIST_PTR)) {
        !          1369:                        CSR_WRITE_4(sc, XL_DOWNLIST_PTR,
        !          1370:                            sc->sc_listmap->dm_segs[0].ds_addr +
        !          1371:                            ((caddr_t)sc->xl_cdata.xl_tx_head->xl_ptr -
        !          1372:                            sc->sc_listkva));
        !          1373:                        CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_DOWN_UNSTALL);
        !          1374:                }
        !          1375:        }
        !          1376: }
        !          1377:
        !          1378: void
        !          1379: xl_txeof_90xB(struct xl_softc *sc)
        !          1380: {
        !          1381:        struct xl_chain *cur_tx = NULL;
        !          1382:        struct ifnet *ifp;
        !          1383:        int idx;
        !          1384:
        !          1385:        ifp = &sc->sc_arpcom.ac_if;
        !          1386:
        !          1387:        idx = sc->xl_cdata.xl_tx_cons;
        !          1388:        while (idx != sc->xl_cdata.xl_tx_prod) {
        !          1389:
        !          1390:                cur_tx = &sc->xl_cdata.xl_tx_chain[idx];
        !          1391:
        !          1392:                if ((cur_tx->xl_ptr->xl_status &
        !          1393:                    htole32(XL_TXSTAT_DL_COMPLETE)) == 0)
        !          1394:                        break;
        !          1395:
        !          1396:                if (cur_tx->xl_mbuf != NULL) {
        !          1397:                        m_freem(cur_tx->xl_mbuf);
        !          1398:                        cur_tx->xl_mbuf = NULL;
        !          1399:                }
        !          1400:
        !          1401:                if (cur_tx->map->dm_nsegs != 0) {
        !          1402:                        bus_dmamap_sync(sc->sc_dmat, cur_tx->map,
        !          1403:                            0, cur_tx->map->dm_mapsize, BUS_DMASYNC_POSTWRITE);
        !          1404:                        bus_dmamap_unload(sc->sc_dmat, cur_tx->map);
        !          1405:                }
        !          1406:
        !          1407:                ifp->if_opackets++;
        !          1408:
        !          1409:                sc->xl_cdata.xl_tx_cnt--;
        !          1410:                XL_INC(idx, XL_TX_LIST_CNT);
        !          1411:                ifp->if_timer = 0;
        !          1412:        }
        !          1413:
        !          1414:        sc->xl_cdata.xl_tx_cons = idx;
        !          1415:
        !          1416:        if (cur_tx != NULL)
        !          1417:                ifp->if_flags &= ~IFF_OACTIVE;
        !          1418: }
        !          1419:
        !          1420: /*
        !          1421:  * TX 'end of channel' interrupt handler. Actually, we should
        !          1422:  * only get a 'TX complete' interrupt if there's a transmit error,
        !          1423:  * so this is really TX error handler.
        !          1424:  */
        !          1425: void
        !          1426: xl_txeoc(struct xl_softc *sc)
        !          1427: {
        !          1428:        u_int8_t        txstat;
        !          1429:
        !          1430:        while ((txstat = CSR_READ_1(sc, XL_TX_STATUS))) {
        !          1431:                if (txstat & XL_TXSTATUS_UNDERRUN ||
        !          1432:                        txstat & XL_TXSTATUS_JABBER ||
        !          1433:                        txstat & XL_TXSTATUS_RECLAIM) {
        !          1434:                        if (txstat != 0x90) {
        !          1435:                                printf("%s: transmission error: %x\n",
        !          1436:                                    sc->sc_dev.dv_xname, txstat);
        !          1437:                        }
        !          1438:                        CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_TX_RESET);
        !          1439:                        xl_wait(sc);
        !          1440:                        if (sc->xl_type == XL_TYPE_905B) {
        !          1441:                                if (sc->xl_cdata.xl_tx_cnt) {
        !          1442:                                        int i;
        !          1443:                                        struct xl_chain *c;
        !          1444:
        !          1445:                                        i = sc->xl_cdata.xl_tx_cons;
        !          1446:                                        c = &sc->xl_cdata.xl_tx_chain[i];
        !          1447:                                        CSR_WRITE_4(sc, XL_DOWNLIST_PTR,
        !          1448:                                            c->xl_phys);
        !          1449:                                        CSR_WRITE_1(sc, XL_DOWN_POLL, 64);
        !          1450:                                }
        !          1451:                        } else {
        !          1452:                                if (sc->xl_cdata.xl_tx_head != NULL)
        !          1453:                                        CSR_WRITE_4(sc, XL_DOWNLIST_PTR,
        !          1454:                                            sc->sc_listmap->dm_segs[0].ds_addr +
        !          1455:                                            ((caddr_t)sc->xl_cdata.xl_tx_head->xl_ptr -
        !          1456:                                            sc->sc_listkva));
        !          1457:                        }
        !          1458:                        /*
        !          1459:                         * Remember to set this for the
        !          1460:                         * first generation 3c90X chips.
        !          1461:                         */
        !          1462:                        CSR_WRITE_1(sc, XL_TX_FREETHRESH, XL_PACKET_SIZE >> 8);
        !          1463:                        if (txstat & XL_TXSTATUS_UNDERRUN &&
        !          1464:                            sc->xl_tx_thresh < XL_PACKET_SIZE) {
        !          1465:                                sc->xl_tx_thresh += XL_MIN_FRAMELEN;
        !          1466: #ifdef notdef
        !          1467:                                printf("%s: tx underrun, increasing tx start"
        !          1468:                                    " threshold to %d\n", sc->sc_dev.dv_xname,
        !          1469:                                    sc->xl_tx_thresh);
        !          1470: #endif
        !          1471:                        }
        !          1472:                        CSR_WRITE_2(sc, XL_COMMAND,
        !          1473:                            XL_CMD_TX_SET_START|sc->xl_tx_thresh);
        !          1474:                        if (sc->xl_type == XL_TYPE_905B) {
        !          1475:                                CSR_WRITE_2(sc, XL_COMMAND,
        !          1476:                                XL_CMD_SET_TX_RECLAIM|(XL_PACKET_SIZE >> 4));
        !          1477:                        }
        !          1478:                        CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_TX_ENABLE);
        !          1479:                        CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_DOWN_UNSTALL);
        !          1480:                } else {
        !          1481:                        CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_TX_ENABLE);
        !          1482:                        CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_DOWN_UNSTALL);
        !          1483:                }
        !          1484:                /*
        !          1485:                 * Write an arbitrary byte to the TX_STATUS register
        !          1486:                 * to clear this interrupt/error and advance to the next.
        !          1487:                 */
        !          1488:                CSR_WRITE_1(sc, XL_TX_STATUS, 0x01);
        !          1489:        }
        !          1490: }
        !          1491:
        !          1492: int
        !          1493: xl_intr(void *arg)
        !          1494: {
        !          1495:        struct xl_softc         *sc;
        !          1496:        struct ifnet            *ifp;
        !          1497:        u_int16_t               status;
        !          1498:        int                     claimed = 0;
        !          1499:
        !          1500:        sc = arg;
        !          1501:        ifp = &sc->sc_arpcom.ac_if;
        !          1502:
        !          1503:        while ((status = CSR_READ_2(sc, XL_STATUS)) & XL_INTRS && status != 0xFFFF) {
        !          1504:
        !          1505:                claimed = 1;
        !          1506:
        !          1507:                CSR_WRITE_2(sc, XL_COMMAND,
        !          1508:                    XL_CMD_INTR_ACK|(status & XL_INTRS));
        !          1509:
        !          1510:                if (sc->intr_ack)
        !          1511:                        (*sc->intr_ack)(sc);
        !          1512:
        !          1513:                if (status & XL_STAT_UP_COMPLETE) {
        !          1514:                        int curpkts;
        !          1515:
        !          1516:                        curpkts = ifp->if_ipackets;
        !          1517:                        xl_rxeof(sc);
        !          1518:                        if (curpkts == ifp->if_ipackets) {
        !          1519:                                while (xl_rx_resync(sc))
        !          1520:                                        xl_rxeof(sc);
        !          1521:                        }
        !          1522:                }
        !          1523:
        !          1524:                if (status & XL_STAT_DOWN_COMPLETE) {
        !          1525:                        if (sc->xl_type == XL_TYPE_905B)
        !          1526:                                xl_txeof_90xB(sc);
        !          1527:                        else
        !          1528:                                xl_txeof(sc);
        !          1529:                }
        !          1530:
        !          1531:                if (status & XL_STAT_TX_COMPLETE) {
        !          1532:                        ifp->if_oerrors++;
        !          1533:                        xl_txeoc(sc);
        !          1534:                }
        !          1535:
        !          1536:                if (status & XL_STAT_ADFAIL) {
        !          1537:                        xl_reset(sc);
        !          1538:                        xl_init(sc);
        !          1539:                }
        !          1540:
        !          1541:                if (status & XL_STAT_STATSOFLOW) {
        !          1542:                        sc->xl_stats_no_timeout = 1;
        !          1543:                        xl_stats_update(sc);
        !          1544:                        sc->xl_stats_no_timeout = 0;
        !          1545:                }
        !          1546:        }
        !          1547:
        !          1548:        if (!IFQ_IS_EMPTY(&ifp->if_snd))
        !          1549:                (*ifp->if_start)(ifp);
        !          1550:
        !          1551:        return (claimed);
        !          1552: }
        !          1553:
        !          1554: void
        !          1555: xl_stats_update(void *xsc)
        !          1556: {
        !          1557:        struct xl_softc         *sc;
        !          1558:        struct ifnet            *ifp;
        !          1559:        struct xl_stats         xl_stats;
        !          1560:        u_int8_t                *p;
        !          1561:        int                     i;
        !          1562:        struct mii_data         *mii = NULL;
        !          1563:
        !          1564:        bzero((char *)&xl_stats, sizeof(struct xl_stats));
        !          1565:
        !          1566:        sc = xsc;
        !          1567:        ifp = &sc->sc_arpcom.ac_if;
        !          1568:        if (sc->xl_hasmii)
        !          1569:                mii = &sc->sc_mii;
        !          1570:
        !          1571:        p = (u_int8_t *)&xl_stats;
        !          1572:
        !          1573:        /* Read all the stats registers. */
        !          1574:        XL_SEL_WIN(6);
        !          1575:
        !          1576:        for (i = 0; i < 16; i++)
        !          1577:                *p++ = CSR_READ_1(sc, XL_W6_CARRIER_LOST + i);
        !          1578:
        !          1579:        ifp->if_ierrors += xl_stats.xl_rx_overrun;
        !          1580:
        !          1581:        ifp->if_collisions += xl_stats.xl_tx_multi_collision +
        !          1582:                                xl_stats.xl_tx_single_collision +
        !          1583:                                xl_stats.xl_tx_late_collision;
        !          1584:
        !          1585:        /*
        !          1586:         * Boomerang and cyclone chips have an extra stats counter
        !          1587:         * in window 4 (BadSSD). We have to read this too in order
        !          1588:         * to clear out all the stats registers and avoid a statsoflow
        !          1589:         * interrupt.
        !          1590:         */
        !          1591:        XL_SEL_WIN(4);
        !          1592:        CSR_READ_1(sc, XL_W4_BADSSD);
        !          1593:
        !          1594:        if (mii != NULL && (!sc->xl_stats_no_timeout))
        !          1595:                mii_tick(mii);
        !          1596:
        !          1597:        XL_SEL_WIN(7);
        !          1598:
        !          1599:        if (!sc->xl_stats_no_timeout)
        !          1600:                timeout_add(&sc->xl_stsup_tmo, hz);
        !          1601: }
        !          1602:
        !          1603: /*
        !          1604:  * Encapsulate an mbuf chain in a descriptor by coupling the mbuf data
        !          1605:  * pointers to the fragment pointers.
        !          1606:  */
        !          1607: int
        !          1608: xl_encap(struct xl_softc *sc, struct xl_chain *c, struct mbuf *m_head)
        !          1609: {
        !          1610:        int             error, frag, total_len;
        !          1611:        u_int32_t       status;
        !          1612:        bus_dmamap_t    map;
        !          1613:
        !          1614:        map = sc->sc_tx_sparemap;
        !          1615:
        !          1616: reload:
        !          1617:        error = bus_dmamap_load_mbuf(sc->sc_dmat, map,
        !          1618:            m_head, BUS_DMA_NOWAIT);
        !          1619:
        !          1620:        if (error && error != EFBIG) {
        !          1621:                m_freem(m_head);
        !          1622:                return (1);
        !          1623:        }
        !          1624:
        !          1625:        /*
        !          1626:         * Start packing the mbufs in this chain into
        !          1627:         * the fragment pointers. Stop when we run out
        !          1628:         * of fragments or hit the end of the mbuf chain.
        !          1629:         */
        !          1630:        for (frag = 0, total_len = 0; frag < map->dm_nsegs; frag++) {
        !          1631:                if (frag == XL_MAXFRAGS)
        !          1632:                        break;
        !          1633:                total_len += map->dm_segs[frag].ds_len;
        !          1634:                c->xl_ptr->xl_frag[frag].xl_addr =
        !          1635:                    htole32(map->dm_segs[frag].ds_addr);
        !          1636:                c->xl_ptr->xl_frag[frag].xl_len =
        !          1637:                    htole32(map->dm_segs[frag].ds_len);
        !          1638:        }
        !          1639:
        !          1640:        /*
        !          1641:         * Handle special case: we used up all 63 fragments,
        !          1642:         * but we have more mbufs left in the chain. Copy the
        !          1643:         * data into an mbuf cluster. Note that we don't
        !          1644:         * bother clearing the values in the other fragment
        !          1645:         * pointers/counters; it wouldn't gain us anything,
        !          1646:         * and would waste cycles.
        !          1647:         */
        !          1648:        if (error) {
        !          1649:                struct mbuf     *m_new = NULL;
        !          1650:
        !          1651:                MGETHDR(m_new, M_DONTWAIT, MT_DATA);
        !          1652:                if (m_new == NULL) {
        !          1653:                        m_freem(m_head);
        !          1654:                        return (1);
        !          1655:                }
        !          1656:                if (m_head->m_pkthdr.len > MHLEN) {
        !          1657:                        MCLGET(m_new, M_DONTWAIT);
        !          1658:                        if (!(m_new->m_flags & M_EXT)) {
        !          1659:                                m_freem(m_new);
        !          1660:                                m_freem(m_head);
        !          1661:                                return (1);
        !          1662:                        }
        !          1663:                }
        !          1664:                m_copydata(m_head, 0, m_head->m_pkthdr.len,
        !          1665:                    mtod(m_new, caddr_t));
        !          1666:                m_new->m_pkthdr.len = m_new->m_len = m_head->m_pkthdr.len;
        !          1667:                m_freem(m_head);
        !          1668:                m_head = m_new;
        !          1669:                goto reload;
        !          1670:        }
        !          1671:
        !          1672:        bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize,
        !          1673:            BUS_DMASYNC_PREWRITE);
        !          1674:
        !          1675:        if (c->map->dm_nsegs != 0) {
        !          1676:                bus_dmamap_sync(sc->sc_dmat, c->map,
        !          1677:                    0, c->map->dm_mapsize, BUS_DMASYNC_POSTWRITE);
        !          1678:                bus_dmamap_unload(sc->sc_dmat, c->map);
        !          1679:        }
        !          1680:
        !          1681:        c->xl_mbuf = m_head;
        !          1682:        sc->sc_tx_sparemap = c->map;
        !          1683:        c->map = map;
        !          1684:        c->xl_ptr->xl_frag[frag - 1].xl_len |= htole32(XL_LAST_FRAG);
        !          1685:        c->xl_ptr->xl_status = htole32(total_len);
        !          1686:        c->xl_ptr->xl_next = 0;
        !          1687:
        !          1688:        if (sc->xl_type == XL_TYPE_905B) {
        !          1689:                status = XL_TXSTAT_RND_DEFEAT;
        !          1690:
        !          1691: #ifndef XL905B_TXCSUM_BROKEN
        !          1692:                if (m_head->m_pkthdr.csum_flags) {
        !          1693:                        if (m_head->m_pkthdr.csum_flags & M_IPV4_CSUM_OUT)
        !          1694:                                status |= XL_TXSTAT_IPCKSUM;
        !          1695:                        if (m_head->m_pkthdr.csum_flags & M_TCPV4_CSUM_OUT)
        !          1696:                                status |= XL_TXSTAT_TCPCKSUM;
        !          1697:                        if (m_head->m_pkthdr.csum_flags & M_UDPV4_CSUM_OUT)
        !          1698:                                status |= XL_TXSTAT_UDPCKSUM;
        !          1699:                }
        !          1700: #endif
        !          1701:                c->xl_ptr->xl_status = htole32(status);
        !          1702:        }
        !          1703:
        !          1704:        bus_dmamap_sync(sc->sc_dmat, sc->sc_listmap,
        !          1705:            offsetof(struct xl_list_data, xl_tx_list[0]),
        !          1706:            sizeof(struct xl_list) * XL_TX_LIST_CNT,
        !          1707:            BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
        !          1708:
        !          1709:        return (0);
        !          1710: }
        !          1711:
        !          1712: /*
        !          1713:  * Main transmit routine. To avoid having to do mbuf copies, we put pointers
        !          1714:  * to the mbuf data regions directly in the transmit lists. We also save a
        !          1715:  * copy of the pointers since the transmit list fragment pointers are
        !          1716:  * physical addresses.
        !          1717:  */
        !          1718: void
        !          1719: xl_start(struct ifnet *ifp)
        !          1720: {
        !          1721:        struct xl_softc         *sc;
        !          1722:        struct mbuf             *m_head = NULL;
        !          1723:        struct xl_chain         *prev = NULL, *cur_tx = NULL, *start_tx;
        !          1724:        struct xl_chain         *prev_tx;
        !          1725:        int                     error;
        !          1726:
        !          1727:        sc = ifp->if_softc;
        !          1728:
        !          1729:        /*
        !          1730:         * Check for an available queue slot. If there are none,
        !          1731:         * punt.
        !          1732:         */
        !          1733:        if (sc->xl_cdata.xl_tx_free == NULL) {
        !          1734:                xl_txeoc(sc);
        !          1735:                xl_txeof(sc);
        !          1736:                if (sc->xl_cdata.xl_tx_free == NULL) {
        !          1737:                        ifp->if_flags |= IFF_OACTIVE;
        !          1738:                        return;
        !          1739:                }
        !          1740:        }
        !          1741:
        !          1742:        start_tx = sc->xl_cdata.xl_tx_free;
        !          1743:
        !          1744:        while (sc->xl_cdata.xl_tx_free != NULL) {
        !          1745:                IFQ_DEQUEUE(&ifp->if_snd, m_head);
        !          1746:                if (m_head == NULL)
        !          1747:                        break;
        !          1748:
        !          1749:                /* Pick a descriptor off the free list. */
        !          1750:                prev_tx = cur_tx;
        !          1751:                cur_tx = sc->xl_cdata.xl_tx_free;
        !          1752:
        !          1753:                /* Pack the data into the descriptor. */
        !          1754:                error = xl_encap(sc, cur_tx, m_head);
        !          1755:                if (error) {
        !          1756:                        cur_tx = prev_tx;
        !          1757:                        continue;
        !          1758:                }
        !          1759:
        !          1760:                sc->xl_cdata.xl_tx_free = cur_tx->xl_next;
        !          1761:                cur_tx->xl_next = NULL;
        !          1762:
        !          1763:                /* Chain it together. */
        !          1764:                if (prev != NULL) {
        !          1765:                        prev->xl_next = cur_tx;
        !          1766:                        prev->xl_ptr->xl_next =
        !          1767:                            sc->sc_listmap->dm_segs[0].ds_addr +
        !          1768:                            ((caddr_t)cur_tx->xl_ptr - sc->sc_listkva);
        !          1769:
        !          1770:                }
        !          1771:                prev = cur_tx;
        !          1772:
        !          1773: #if NBPFILTER > 0
        !          1774:                /*
        !          1775:                 * If there's a BPF listener, bounce a copy of this frame
        !          1776:                 * to him.
        !          1777:                 */
        !          1778:                if (ifp->if_bpf)
        !          1779:                        bpf_mtap(ifp->if_bpf, cur_tx->xl_mbuf,
        !          1780:                            BPF_DIRECTION_OUT);
        !          1781: #endif
        !          1782:        }
        !          1783:
        !          1784:        /*
        !          1785:         * If there are no packets queued, bail.
        !          1786:         */
        !          1787:        if (cur_tx == NULL)
        !          1788:                return;
        !          1789:
        !          1790:        /*
        !          1791:         * Place the request for the upload interrupt
        !          1792:         * in the last descriptor in the chain. This way, if
        !          1793:         * we're chaining several packets at once, we'll only
        !          1794:         * get an interrupt once for the whole chain rather than
        !          1795:         * once for each packet.
        !          1796:         */
        !          1797:        cur_tx->xl_ptr->xl_status |= htole32(XL_TXSTAT_DL_INTR);
        !          1798:
        !          1799:        /*
        !          1800:         * Queue the packets. If the TX channel is clear, update
        !          1801:         * the downlist pointer register.
        !          1802:         */
        !          1803:        CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_DOWN_STALL);
        !          1804:        xl_wait(sc);
        !          1805:
        !          1806:        if (sc->xl_cdata.xl_tx_head != NULL) {
        !          1807:                sc->xl_cdata.xl_tx_tail->xl_next = start_tx;
        !          1808:                sc->xl_cdata.xl_tx_tail->xl_ptr->xl_next =
        !          1809:                    sc->sc_listmap->dm_segs[0].ds_addr +
        !          1810:                    ((caddr_t)start_tx->xl_ptr - sc->sc_listkva);
        !          1811:                sc->xl_cdata.xl_tx_tail->xl_ptr->xl_status &=
        !          1812:                    htole32(~XL_TXSTAT_DL_INTR);
        !          1813:                sc->xl_cdata.xl_tx_tail = cur_tx;
        !          1814:        } else {
        !          1815:                sc->xl_cdata.xl_tx_head = start_tx;
        !          1816:                sc->xl_cdata.xl_tx_tail = cur_tx;
        !          1817:        }
        !          1818:        if (!CSR_READ_4(sc, XL_DOWNLIST_PTR))
        !          1819:                CSR_WRITE_4(sc, XL_DOWNLIST_PTR,
        !          1820:                    sc->sc_listmap->dm_segs[0].ds_addr +
        !          1821:                    ((caddr_t)start_tx->xl_ptr - sc->sc_listkva));
        !          1822:
        !          1823:        CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_DOWN_UNSTALL);
        !          1824:
        !          1825:        XL_SEL_WIN(7);
        !          1826:
        !          1827:        /*
        !          1828:         * Set a timeout in case the chip goes out to lunch.
        !          1829:         */
        !          1830:        ifp->if_timer = 5;
        !          1831:
        !          1832:        /*
        !          1833:         * XXX Under certain conditions, usually on slower machines
        !          1834:         * where interrupts may be dropped, it's possible for the
        !          1835:         * adapter to chew up all the buffers in the receive ring
        !          1836:         * and stall, without us being able to do anything about it.
        !          1837:         * To guard against this, we need to make a pass over the
        !          1838:         * RX queue to make sure there aren't any packets pending.
        !          1839:         * Doing it here means we can flush the receive ring at the
        !          1840:         * same time the chip is DMAing the transmit descriptors we
        !          1841:         * just gave it.
        !          1842:         *
        !          1843:         * 3Com goes to some lengths to emphasize the Parallel Tasking (tm)
        !          1844:         * nature of their chips in all their marketing literature;
        !          1845:         * we may as well take advantage of it. :)
        !          1846:         */
        !          1847:        xl_rxeof(sc);
        !          1848: }
        !          1849:
        !          1850: void
        !          1851: xl_start_90xB(struct ifnet *ifp)
        !          1852: {
        !          1853:        struct xl_softc *sc;
        !          1854:        struct mbuf     *m_head = NULL;
        !          1855:        struct xl_chain *prev = NULL, *cur_tx = NULL, *start_tx;
        !          1856:        struct xl_chain *prev_tx;
        !          1857:        int             error, idx;
        !          1858:
        !          1859:        sc = ifp->if_softc;
        !          1860:
        !          1861:        if (ifp->if_flags & IFF_OACTIVE)
        !          1862:                return;
        !          1863:
        !          1864:        idx = sc->xl_cdata.xl_tx_prod;
        !          1865:        start_tx = &sc->xl_cdata.xl_tx_chain[idx];
        !          1866:
        !          1867:        while (sc->xl_cdata.xl_tx_chain[idx].xl_mbuf == NULL) {
        !          1868:
        !          1869:                if ((XL_TX_LIST_CNT - sc->xl_cdata.xl_tx_cnt) < 3) {
        !          1870:                        ifp->if_flags |= IFF_OACTIVE;
        !          1871:                        break;
        !          1872:                }
        !          1873:
        !          1874:                IFQ_DEQUEUE(&ifp->if_snd, m_head);
        !          1875:                if (m_head == NULL)
        !          1876:                        break;
        !          1877:
        !          1878:                prev_tx = cur_tx;
        !          1879:                cur_tx = &sc->xl_cdata.xl_tx_chain[idx];
        !          1880:
        !          1881:                /* Pack the data into the descriptor. */
        !          1882:                error = xl_encap(sc, cur_tx, m_head);
        !          1883:                if (error) {
        !          1884:                        cur_tx = prev_tx;
        !          1885:                        continue;
        !          1886:                }
        !          1887:
        !          1888:                /* Chain it together. */
        !          1889:                if (prev != NULL)
        !          1890:                        prev->xl_ptr->xl_next = htole32(cur_tx->xl_phys);
        !          1891:                prev = cur_tx;
        !          1892:
        !          1893: #if NBPFILTER > 0
        !          1894:                /*
        !          1895:                 * If there's a BPF listener, bounce a copy of this frame
        !          1896:                 * to him.
        !          1897:                 */
        !          1898:                if (ifp->if_bpf)
        !          1899:                        bpf_mtap(ifp->if_bpf, cur_tx->xl_mbuf,
        !          1900:                            BPF_DIRECTION_OUT);
        !          1901: #endif
        !          1902:
        !          1903:                XL_INC(idx, XL_TX_LIST_CNT);
        !          1904:                sc->xl_cdata.xl_tx_cnt++;
        !          1905:        }
        !          1906:
        !          1907:        /*
        !          1908:         * If there are no packets queued, bail.
        !          1909:         */
        !          1910:        if (cur_tx == NULL)
        !          1911:                return;
        !          1912:
        !          1913:        /*
        !          1914:         * Place the request for the upload interrupt
        !          1915:         * in the last descriptor in the chain. This way, if
        !          1916:         * we're chaining several packets at once, we'll only
        !          1917:         * get an interrupt once for the whole chain rather than
        !          1918:         * once for each packet.
        !          1919:         */
        !          1920:        cur_tx->xl_ptr->xl_status |= htole32(XL_TXSTAT_DL_INTR);
        !          1921:
        !          1922:        /* Start transmission */
        !          1923:        sc->xl_cdata.xl_tx_prod = idx;
        !          1924:        start_tx->xl_prev->xl_ptr->xl_next = htole32(start_tx->xl_phys);
        !          1925:
        !          1926:        /*
        !          1927:         * Set a timeout in case the chip goes out to lunch.
        !          1928:         */
        !          1929:        ifp->if_timer = 5;
        !          1930: }
        !          1931:
        !          1932: void
        !          1933: xl_init(void *xsc)
        !          1934: {
        !          1935:        struct xl_softc         *sc = xsc;
        !          1936:        struct ifnet            *ifp = &sc->sc_arpcom.ac_if;
        !          1937:        int                     s, i;
        !          1938:        u_int16_t               rxfilt = 0;
        !          1939:        struct mii_data         *mii = NULL;
        !          1940:
        !          1941:        s = splnet();
        !          1942:
        !          1943:        /*
        !          1944:         * Cancel pending I/O and free all RX/TX buffers.
        !          1945:         */
        !          1946:        xl_stop(sc);
        !          1947:
        !          1948:        if (sc->xl_hasmii)
        !          1949:                mii = &sc->sc_mii;
        !          1950:
        !          1951:        if (mii == NULL) {
        !          1952:                CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_RESET);
        !          1953:                xl_wait(sc);
        !          1954:        }
        !          1955:        CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_TX_RESET);
        !          1956:        xl_wait(sc);
        !          1957:        DELAY(10000);
        !          1958:
        !          1959:        /* Init our MAC address */
        !          1960:        XL_SEL_WIN(2);
        !          1961:        for (i = 0; i < ETHER_ADDR_LEN; i++) {
        !          1962:                CSR_WRITE_1(sc, XL_W2_STATION_ADDR_LO + i,
        !          1963:                                sc->sc_arpcom.ac_enaddr[i]);
        !          1964:        }
        !          1965:
        !          1966:        /* Clear the station mask. */
        !          1967:        for (i = 0; i < 3; i++)
        !          1968:                CSR_WRITE_2(sc, XL_W2_STATION_MASK_LO + (i * 2), 0);
        !          1969: #ifdef notdef
        !          1970:        /* Reset TX and RX. */
        !          1971:        CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_RESET);
        !          1972:        xl_wait(sc);
        !          1973:        CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_TX_RESET);
        !          1974:        xl_wait(sc);
        !          1975: #endif
        !          1976:        /* Init circular RX list. */
        !          1977:        if (xl_list_rx_init(sc) == ENOBUFS) {
        !          1978:                printf("%s: initialization failed: no "
        !          1979:                        "memory for rx buffers\n", sc->sc_dev.dv_xname);
        !          1980:                xl_stop(sc);
        !          1981:                splx(s);
        !          1982:                return;
        !          1983:        }
        !          1984:
        !          1985:        /* Init TX descriptors. */
        !          1986:        if (sc->xl_type == XL_TYPE_905B)
        !          1987:                xl_list_tx_init_90xB(sc);
        !          1988:        else
        !          1989:                xl_list_tx_init(sc);
        !          1990:
        !          1991:        /*
        !          1992:         * Set the TX freethresh value.
        !          1993:         * Note that this has no effect on 3c905B "cyclone"
        !          1994:         * cards but is required for 3c900/3c905 "boomerang"
        !          1995:         * cards in order to enable the download engine.
        !          1996:         */
        !          1997:        CSR_WRITE_1(sc, XL_TX_FREETHRESH, XL_PACKET_SIZE >> 8);
        !          1998:
        !          1999:        /* Set the TX start threshold for best performance. */
        !          2000:        sc->xl_tx_thresh = XL_MIN_FRAMELEN;
        !          2001:        CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_TX_SET_START|sc->xl_tx_thresh);
        !          2002:
        !          2003:        /*
        !          2004:         * If this is a 3c905B, also set the tx reclaim threshold.
        !          2005:         * This helps cut down on the number of tx reclaim errors
        !          2006:         * that could happen on a busy network. The chip multiplies
        !          2007:         * the register value by 16 to obtain the actual threshold
        !          2008:         * in bytes, so we divide by 16 when setting the value here.
        !          2009:         * The existing threshold value can be examined by reading
        !          2010:         * the register at offset 9 in window 5.
        !          2011:         */
        !          2012:        if (sc->xl_type == XL_TYPE_905B) {
        !          2013:                CSR_WRITE_2(sc, XL_COMMAND,
        !          2014:                    XL_CMD_SET_TX_RECLAIM|(XL_PACKET_SIZE >> 4));
        !          2015:        }
        !          2016:
        !          2017:        /* Set RX filter bits. */
        !          2018:        XL_SEL_WIN(5);
        !          2019:        rxfilt = CSR_READ_1(sc, XL_W5_RX_FILTER);
        !          2020:
        !          2021:        /* Set the individual bit to receive frames for this host only. */
        !          2022:        rxfilt |= XL_RXFILTER_INDIVIDUAL;
        !          2023:
        !          2024:        CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_SET_FILT|rxfilt);
        !          2025:
        !          2026:        /* Set promiscuous mode. */
        !          2027:        xl_setpromisc(sc);
        !          2028:
        !          2029:        rxfilt = CSR_READ_1(sc, XL_W5_RX_FILTER);
        !          2030:
        !          2031:        /*
        !          2032:         * Set capture broadcast bit to capture broadcast frames.
        !          2033:         */
        !          2034:        if (ifp->if_flags & IFF_BROADCAST)
        !          2035:                rxfilt |= XL_RXFILTER_BROADCAST;
        !          2036:        else
        !          2037:                rxfilt &= ~XL_RXFILTER_BROADCAST;
        !          2038:
        !          2039:        CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_SET_FILT|rxfilt);
        !          2040:
        !          2041:        /*
        !          2042:         * Program the multicast filter, if necessary.
        !          2043:         */
        !          2044:        if (sc->xl_type == XL_TYPE_905B)
        !          2045:                xl_setmulti_hash(sc);
        !          2046:        else
        !          2047:                xl_setmulti(sc);
        !          2048:
        !          2049:        /*
        !          2050:         * Load the address of the RX list. We have to
        !          2051:         * stall the upload engine before we can manipulate
        !          2052:         * the uplist pointer register, then unstall it when
        !          2053:         * we're finished. We also have to wait for the
        !          2054:         * stall command to complete before proceeding.
        !          2055:         * Note that we have to do this after any RX resets
        !          2056:         * have completed since the uplist register is cleared
        !          2057:         * by a reset.
        !          2058:         */
        !          2059:        CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_UP_STALL);
        !          2060:        xl_wait(sc);
        !          2061:        CSR_WRITE_4(sc, XL_UPLIST_PTR, sc->sc_listmap->dm_segs[0].ds_addr +
        !          2062:            offsetof(struct xl_list_data, xl_rx_list[0]));
        !          2063:        CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_UP_UNSTALL);
        !          2064:        xl_wait(sc);
        !          2065:
        !          2066:        if (sc->xl_type == XL_TYPE_905B) {
        !          2067:                /* Set polling interval */
        !          2068:                CSR_WRITE_1(sc, XL_DOWN_POLL, 64);
        !          2069:                /* Load the address of the TX list */
        !          2070:                CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_DOWN_STALL);
        !          2071:                xl_wait(sc);
        !          2072:                CSR_WRITE_4(sc, XL_DOWNLIST_PTR,
        !          2073:                    sc->sc_listmap->dm_segs[0].ds_addr +
        !          2074:                    offsetof(struct xl_list_data, xl_tx_list[0]));
        !          2075:                CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_DOWN_UNSTALL);
        !          2076:                xl_wait(sc);
        !          2077:        }
        !          2078:
        !          2079:        /*
        !          2080:         * If the coax transceiver is on, make sure to enable
        !          2081:         * the DC-DC converter.
        !          2082:         */
        !          2083:        XL_SEL_WIN(3);
        !          2084:        if (sc->xl_xcvr == XL_XCVR_COAX)
        !          2085:                CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_COAX_START);
        !          2086:        else
        !          2087:                CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_COAX_STOP);
        !          2088:
        !          2089:        /*
        !          2090:         * increase packet size to allow reception of 802.1q or ISL packets.
        !          2091:         * For the 3c90x chip, set the 'allow large packets' bit in the MAC
        !          2092:         * control register. For 3c90xB/C chips, use the RX packet size
        !          2093:         * register.
        !          2094:         */
        !          2095:
        !          2096:        if (sc->xl_type == XL_TYPE_905B)
        !          2097:                CSR_WRITE_2(sc, XL_W3_MAXPKTSIZE, XL_PACKET_SIZE);
        !          2098:        else {
        !          2099:                u_int8_t macctl;
        !          2100:                macctl = CSR_READ_1(sc, XL_W3_MAC_CTRL);
        !          2101:                macctl |= XL_MACCTRL_ALLOW_LARGE_PACK;
        !          2102:                CSR_WRITE_1(sc, XL_W3_MAC_CTRL, macctl);
        !          2103:        }
        !          2104:
        !          2105:        /* Clear out the stats counters. */
        !          2106:        CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_STATS_DISABLE);
        !          2107:        sc->xl_stats_no_timeout = 1;
        !          2108:        xl_stats_update(sc);
        !          2109:        sc->xl_stats_no_timeout = 0;
        !          2110:        XL_SEL_WIN(4);
        !          2111:        CSR_WRITE_2(sc, XL_W4_NET_DIAG, XL_NETDIAG_UPPER_BYTES_ENABLE);
        !          2112:        CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_STATS_ENABLE);
        !          2113:
        !          2114:        /*
        !          2115:         * Enable interrupts.
        !          2116:         */
        !          2117:        CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_INTR_ACK|0xFF);
        !          2118:        CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_STAT_ENB|XL_INTRS);
        !          2119:        CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_INTR_ENB|XL_INTRS);
        !          2120:
        !          2121:        if (sc->intr_ack)
        !          2122:                (*sc->intr_ack)(sc);
        !          2123:
        !          2124:        /* Set the RX early threshold */
        !          2125:        CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_SET_THRESH|(XL_PACKET_SIZE >>2));
        !          2126:        CSR_WRITE_2(sc, XL_DMACTL, XL_DMACTL_UP_RX_EARLY);
        !          2127:
        !          2128:        /* Enable receiver and transmitter. */
        !          2129:        CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_TX_ENABLE);
        !          2130:        xl_wait(sc);
        !          2131:        CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_ENABLE);
        !          2132:        xl_wait(sc);
        !          2133:
        !          2134:        /* Restore state of BMCR */
        !          2135:        if (mii != NULL)
        !          2136:                mii_mediachg(mii);
        !          2137:
        !          2138:        /* Select window 7 for normal operations. */
        !          2139:        XL_SEL_WIN(7);
        !          2140:
        !          2141:        ifp->if_flags |= IFF_RUNNING;
        !          2142:        ifp->if_flags &= ~IFF_OACTIVE;
        !          2143:
        !          2144:        splx(s);
        !          2145:
        !          2146:        timeout_add(&sc->xl_stsup_tmo, hz);
        !          2147: }
        !          2148:
        !          2149: /*
        !          2150:  * Set media options.
        !          2151:  */
        !          2152: int
        !          2153: xl_ifmedia_upd(struct ifnet *ifp)
        !          2154: {
        !          2155:        struct xl_softc         *sc;
        !          2156:        struct ifmedia          *ifm = NULL;
        !          2157:        struct mii_data         *mii = NULL;
        !          2158:
        !          2159:        sc = ifp->if_softc;
        !          2160:
        !          2161:        if (sc->xl_hasmii)
        !          2162:                mii = &sc->sc_mii;
        !          2163:        if (mii == NULL)
        !          2164:                ifm = &sc->ifmedia;
        !          2165:        else
        !          2166:                ifm = &mii->mii_media;
        !          2167:
        !          2168:        switch(IFM_SUBTYPE(ifm->ifm_media)) {
        !          2169:        case IFM_100_FX:
        !          2170:        case IFM_10_FL:
        !          2171:        case IFM_10_2:
        !          2172:        case IFM_10_5:
        !          2173:                xl_setmode(sc, ifm->ifm_media);
        !          2174:                return (0);
        !          2175:                break;
        !          2176:        default:
        !          2177:                break;
        !          2178:        }
        !          2179:
        !          2180:        if (sc->xl_media & XL_MEDIAOPT_MII || sc->xl_media & XL_MEDIAOPT_BTX
        !          2181:                || sc->xl_media & XL_MEDIAOPT_BT4) {
        !          2182:                xl_init(sc);
        !          2183:        } else {
        !          2184:                xl_setmode(sc, ifm->ifm_media);
        !          2185:        }
        !          2186:
        !          2187:        return (0);
        !          2188: }
        !          2189:
        !          2190: /*
        !          2191:  * Report current media status.
        !          2192:  */
        !          2193: void
        !          2194: xl_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
        !          2195: {
        !          2196:        struct xl_softc         *sc;
        !          2197:        u_int32_t               icfg;
        !          2198:        u_int16_t               status = 0;
        !          2199:        struct mii_data         *mii = NULL;
        !          2200:
        !          2201:        sc = ifp->if_softc;
        !          2202:        if (sc->xl_hasmii != 0)
        !          2203:                mii = &sc->sc_mii;
        !          2204:
        !          2205:        XL_SEL_WIN(4);
        !          2206:        status = CSR_READ_2(sc, XL_W4_MEDIA_STATUS);
        !          2207:
        !          2208:        XL_SEL_WIN(3);
        !          2209:        icfg = CSR_READ_4(sc, XL_W3_INTERNAL_CFG) & XL_ICFG_CONNECTOR_MASK;
        !          2210:        icfg >>= XL_ICFG_CONNECTOR_BITS;
        !          2211:
        !          2212:        ifmr->ifm_active = IFM_ETHER;
        !          2213:        ifmr->ifm_status = IFM_AVALID;
        !          2214:
        !          2215:        if ((status & XL_MEDIASTAT_CARRIER) == 0)
        !          2216:                ifmr->ifm_status |= IFM_ACTIVE;
        !          2217:
        !          2218:        switch(icfg) {
        !          2219:        case XL_XCVR_10BT:
        !          2220:                ifmr->ifm_active = IFM_ETHER|IFM_10_T;
        !          2221:                if (CSR_READ_1(sc, XL_W3_MAC_CTRL) & XL_MACCTRL_DUPLEX)
        !          2222:                        ifmr->ifm_active |= IFM_FDX;
        !          2223:                else
        !          2224:                        ifmr->ifm_active |= IFM_HDX;
        !          2225:                break;
        !          2226:        case XL_XCVR_AUI:
        !          2227:                if (sc->xl_type == XL_TYPE_905B &&
        !          2228:                    sc->xl_media == XL_MEDIAOPT_10FL) {
        !          2229:                        ifmr->ifm_active = IFM_ETHER|IFM_10_FL;
        !          2230:                        if (CSR_READ_1(sc, XL_W3_MAC_CTRL) & XL_MACCTRL_DUPLEX)
        !          2231:                                ifmr->ifm_active |= IFM_FDX;
        !          2232:                        else
        !          2233:                                ifmr->ifm_active |= IFM_FDX;
        !          2234:                } else
        !          2235:                        ifmr->ifm_active = IFM_ETHER|IFM_10_5;
        !          2236:                break;
        !          2237:        case XL_XCVR_COAX:
        !          2238:                ifmr->ifm_active = IFM_ETHER|IFM_10_2;
        !          2239:                break;
        !          2240:        /*
        !          2241:         * XXX MII and BTX/AUTO should be separate cases.
        !          2242:         */
        !          2243:
        !          2244:        case XL_XCVR_100BTX:
        !          2245:        case XL_XCVR_AUTO:
        !          2246:        case XL_XCVR_MII:
        !          2247:                if (mii != NULL) {
        !          2248:                        mii_pollstat(mii);
        !          2249:                        ifmr->ifm_active = mii->mii_media_active;
        !          2250:                        ifmr->ifm_status = mii->mii_media_status;
        !          2251:                }
        !          2252:                break;
        !          2253:        case XL_XCVR_100BFX:
        !          2254:                ifmr->ifm_active = IFM_ETHER|IFM_100_FX;
        !          2255:                break;
        !          2256:        default:
        !          2257:                printf("%s: unknown XCVR type: %d\n", sc->sc_dev.dv_xname, icfg);
        !          2258:                break;
        !          2259:        }
        !          2260: }
        !          2261:
        !          2262: int
        !          2263: xl_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
        !          2264: {
        !          2265:        struct xl_softc *sc = ifp->if_softc;
        !          2266:        struct ifreq *ifr = (struct ifreq *)data;
        !          2267:        struct ifaddr *ifa = (struct ifaddr *)data;
        !          2268:        int s, error = 0;
        !          2269:        struct mii_data *mii = NULL;
        !          2270:
        !          2271:        s = splnet();
        !          2272:
        !          2273:        if ((error = ether_ioctl(ifp, &sc->sc_arpcom, command, data)) > 0) {
        !          2274:                splx(s);
        !          2275:                return error;
        !          2276:        }
        !          2277:
        !          2278:        switch(command) {
        !          2279:        case SIOCSIFADDR:
        !          2280:                ifp->if_flags |= IFF_UP;
        !          2281:                if (!(ifp->if_flags & IFF_RUNNING))
        !          2282:                        xl_init(sc);
        !          2283: #ifdef INET
        !          2284:                if (ifa->ifa_addr->sa_family == AF_INET)
        !          2285:                        arp_ifinit(&sc->sc_arpcom, ifa);
        !          2286: #endif /* INET */
        !          2287:                break;
        !          2288:
        !          2289:        case SIOCSIFMTU:
        !          2290:                if (ifr->ifr_mtu > ETHERMTU || ifr->ifr_mtu < ETHERMIN)
        !          2291:                        error = EINVAL;
        !          2292:                else if (ifp->if_mtu != ifr->ifr_mtu)
        !          2293:                        ifp->if_mtu = ifr->ifr_mtu;
        !          2294:                break;
        !          2295:
        !          2296:        case SIOCSIFFLAGS:
        !          2297:                XL_SEL_WIN(5);
        !          2298:                if (ifp->if_flags & IFF_UP) {
        !          2299:                        if (ifp->if_flags & IFF_RUNNING &&
        !          2300:                            (ifp->if_flags ^ sc->xl_if_flags) &
        !          2301:                             IFF_PROMISC) {
        !          2302:                                xl_setpromisc(sc);
        !          2303:                                XL_SEL_WIN(7);
        !          2304:                        } else {
        !          2305:                                if (!(ifp->if_flags & IFF_RUNNING))
        !          2306:                                        xl_init(sc);
        !          2307:                        }
        !          2308:                } else {
        !          2309:                        if (ifp->if_flags & IFF_RUNNING)
        !          2310:                                xl_stop(sc);
        !          2311:                }
        !          2312:                sc->xl_if_flags = ifp->if_flags;
        !          2313:                break;
        !          2314:        case SIOCADDMULTI:
        !          2315:        case SIOCDELMULTI:
        !          2316:                error = (command == SIOCADDMULTI) ?
        !          2317:                    ether_addmulti(ifr, &sc->sc_arpcom) :
        !          2318:                    ether_delmulti(ifr, &sc->sc_arpcom);
        !          2319:
        !          2320:                if (error == ENETRESET) {
        !          2321:                        /*
        !          2322:                         * Multicast list has changed; set the hardware
        !          2323:                         * filter accordingly.
        !          2324:                         */
        !          2325:                        if (ifp->if_flags & IFF_RUNNING) {
        !          2326:                                if (sc->xl_type == XL_TYPE_905B)
        !          2327:                                        xl_setmulti_hash(sc);
        !          2328:                                else
        !          2329:                                        xl_setmulti(sc);
        !          2330:                        }
        !          2331:                        error = 0;
        !          2332:                }
        !          2333:                break;
        !          2334:        case SIOCGIFMEDIA:
        !          2335:        case SIOCSIFMEDIA:
        !          2336:                if (sc->xl_hasmii != 0)
        !          2337:                        mii = &sc->sc_mii;
        !          2338:                if (mii == NULL)
        !          2339:                        error = ifmedia_ioctl(ifp, ifr,
        !          2340:                            &sc->ifmedia, command);
        !          2341:                else
        !          2342:                        error = ifmedia_ioctl(ifp, ifr,
        !          2343:                            &mii->mii_media, command);
        !          2344:                break;
        !          2345:        default:
        !          2346:                error = EINVAL;
        !          2347:                break;
        !          2348:        }
        !          2349:
        !          2350:        splx(s);
        !          2351:
        !          2352:        return (error);
        !          2353: }
        !          2354:
        !          2355: void
        !          2356: xl_watchdog(struct ifnet *ifp)
        !          2357: {
        !          2358:        struct xl_softc         *sc;
        !          2359:        u_int16_t               status = 0;
        !          2360:
        !          2361:        sc = ifp->if_softc;
        !          2362:
        !          2363:        ifp->if_oerrors++;
        !          2364:        XL_SEL_WIN(4);
        !          2365:        status = CSR_READ_2(sc, XL_W4_MEDIA_STATUS);
        !          2366:        printf("%s: watchdog timeout\n", sc->sc_dev.dv_xname);
        !          2367:
        !          2368:        if (status & XL_MEDIASTAT_CARRIER)
        !          2369:                printf("%s: no carrier - transceiver cable problem?\n",
        !          2370:                                                                sc->sc_dev.dv_xname);
        !          2371:        xl_txeoc(sc);
        !          2372:        xl_txeof(sc);
        !          2373:        xl_rxeof(sc);
        !          2374:        xl_reset(sc);
        !          2375:        xl_init(sc);
        !          2376:
        !          2377:        if (!IFQ_IS_EMPTY(&ifp->if_snd))
        !          2378:                (*ifp->if_start)(ifp);
        !          2379: }
        !          2380:
        !          2381: void
        !          2382: xl_freetxrx(struct xl_softc *sc)
        !          2383: {
        !          2384:        bus_dmamap_t    map;
        !          2385:        int             i;
        !          2386:
        !          2387:        /*
        !          2388:         * Free data in the RX lists.
        !          2389:         */
        !          2390:        for (i = 0; i < XL_RX_LIST_CNT; i++) {
        !          2391:                if (sc->xl_cdata.xl_rx_chain[i].map->dm_nsegs != 0) {
        !          2392:                        map = sc->xl_cdata.xl_rx_chain[i].map;
        !          2393:
        !          2394:                        bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize,
        !          2395:                            BUS_DMASYNC_POSTREAD);
        !          2396:                        bus_dmamap_unload(sc->sc_dmat, map);
        !          2397:                }
        !          2398:                if (sc->xl_cdata.xl_rx_chain[i].xl_mbuf != NULL) {
        !          2399:                        m_freem(sc->xl_cdata.xl_rx_chain[i].xl_mbuf);
        !          2400:                        sc->xl_cdata.xl_rx_chain[i].xl_mbuf = NULL;
        !          2401:                }
        !          2402:        }
        !          2403:        bzero((char *)&sc->xl_ldata->xl_rx_list,
        !          2404:                sizeof(sc->xl_ldata->xl_rx_list));
        !          2405:        /*
        !          2406:         * Free the TX list buffers.
        !          2407:         */
        !          2408:        for (i = 0; i < XL_TX_LIST_CNT; i++) {
        !          2409:                if (sc->xl_cdata.xl_tx_chain[i].map->dm_nsegs != 0) {
        !          2410:                        map = sc->xl_cdata.xl_tx_chain[i].map;
        !          2411:
        !          2412:                        bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize,
        !          2413:                            BUS_DMASYNC_POSTWRITE);
        !          2414:                        bus_dmamap_unload(sc->sc_dmat, map);
        !          2415:                }
        !          2416:                if (sc->xl_cdata.xl_tx_chain[i].xl_mbuf != NULL) {
        !          2417:                        m_freem(sc->xl_cdata.xl_tx_chain[i].xl_mbuf);
        !          2418:                        sc->xl_cdata.xl_tx_chain[i].xl_mbuf = NULL;
        !          2419:                }
        !          2420:        }
        !          2421:        bzero((char *)&sc->xl_ldata->xl_tx_list,
        !          2422:                sizeof(sc->xl_ldata->xl_tx_list));
        !          2423: }
        !          2424:
        !          2425: /*
        !          2426:  * Stop the adapter and free any mbufs allocated to the
        !          2427:  * RX and TX lists.
        !          2428:  */
        !          2429: void
        !          2430: xl_stop(struct xl_softc *sc)
        !          2431: {
        !          2432:        struct ifnet *ifp;
        !          2433:
        !          2434:        ifp = &sc->sc_arpcom.ac_if;
        !          2435:        ifp->if_timer = 0;
        !          2436:
        !          2437:        CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_DISABLE);
        !          2438:        CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_STATS_DISABLE);
        !          2439:        CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_INTR_ENB);
        !          2440:        CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_DISCARD);
        !          2441:        xl_wait(sc);
        !          2442:        CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_TX_DISABLE);
        !          2443:        CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_COAX_STOP);
        !          2444:        DELAY(800);
        !          2445:
        !          2446: #ifdef foo
        !          2447:        CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_RX_RESET);
        !          2448:        xl_wait(sc);
        !          2449:        CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_TX_RESET);
        !          2450:        xl_wait(sc);
        !          2451: #endif
        !          2452:
        !          2453:        CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_INTR_ACK|XL_STAT_INTLATCH);
        !          2454:        CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_STAT_ENB|0);
        !          2455:        CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_INTR_ENB|0);
        !          2456:
        !          2457:        if (sc->intr_ack)
        !          2458:                (*sc->intr_ack)(sc);
        !          2459:
        !          2460:        /* Stop the stats updater. */
        !          2461:        timeout_del(&sc->xl_stsup_tmo);
        !          2462:
        !          2463:        ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
        !          2464:
        !          2465:        xl_freetxrx(sc);
        !          2466: }
        !          2467:
        !          2468: void
        !          2469: xl_attach(struct xl_softc *sc)
        !          2470: {
        !          2471:        u_int8_t enaddr[ETHER_ADDR_LEN];
        !          2472:        u_int16_t               xcvr[2];
        !          2473:        struct ifnet *ifp = &sc->sc_arpcom.ac_if;
        !          2474:        int i, media = IFM_ETHER|IFM_100_TX|IFM_FDX;
        !          2475:        struct ifmedia *ifm;
        !          2476:
        !          2477:        i = splnet();
        !          2478:        xl_reset(sc);
        !          2479:        splx(i);
        !          2480:
        !          2481:        /*
        !          2482:         * Get station address from the EEPROM.
        !          2483:         */
        !          2484:        if (xl_read_eeprom(sc, (caddr_t)&enaddr, XL_EE_OEM_ADR0, 3, 1)) {
        !          2485:                printf("\n%s: failed to read station address\n",
        !          2486:                    sc->sc_dev.dv_xname);
        !          2487:                return;
        !          2488:        }
        !          2489:        bcopy(enaddr, (char *)&sc->sc_arpcom.ac_enaddr, ETHER_ADDR_LEN);
        !          2490:
        !          2491:        if (bus_dmamem_alloc(sc->sc_dmat, sizeof(struct xl_list_data),
        !          2492:            PAGE_SIZE, 0, sc->sc_listseg, 1, &sc->sc_listnseg,
        !          2493:            BUS_DMA_NOWAIT) != 0) {
        !          2494:                printf(": can't alloc list mem\n");
        !          2495:                return;
        !          2496:        }
        !          2497:        if (bus_dmamem_map(sc->sc_dmat, sc->sc_listseg, sc->sc_listnseg,
        !          2498:            sizeof(struct xl_list_data), &sc->sc_listkva,
        !          2499:            BUS_DMA_NOWAIT) != 0) {
        !          2500:                printf(": can't map list mem\n");
        !          2501:                return;
        !          2502:        }
        !          2503:        if (bus_dmamap_create(sc->sc_dmat, sizeof(struct xl_list_data), 1,
        !          2504:            sizeof(struct xl_list_data), 0, BUS_DMA_NOWAIT,
        !          2505:            &sc->sc_listmap) != 0) {
        !          2506:                printf(": can't alloc list map\n");
        !          2507:                return;
        !          2508:        }
        !          2509:        if (bus_dmamap_load(sc->sc_dmat, sc->sc_listmap, sc->sc_listkva,
        !          2510:            sizeof(struct xl_list_data), NULL, BUS_DMA_NOWAIT) != 0) {
        !          2511:                printf(": can't load list map\n");
        !          2512:                return;
        !          2513:        }
        !          2514:        sc->xl_ldata = (struct xl_list_data *)sc->sc_listkva;
        !          2515:        bzero(sc->xl_ldata, sizeof(struct xl_list_data));
        !          2516:
        !          2517:        for (i = 0; i < XL_RX_LIST_CNT; i++) {
        !          2518:                if (bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES,
        !          2519:                    0, BUS_DMA_NOWAIT,
        !          2520:                    &sc->xl_cdata.xl_rx_chain[i].map) != 0) {
        !          2521:                        printf(": can't create rx map\n");
        !          2522:                        return;
        !          2523:                }
        !          2524:        }
        !          2525:        if (bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES, 0,
        !          2526:            BUS_DMA_NOWAIT, &sc->sc_rx_sparemap) != 0) {
        !          2527:                printf(": can't create rx spare map\n");
        !          2528:                return;
        !          2529:        }
        !          2530:
        !          2531:        for (i = 0; i < XL_TX_LIST_CNT; i++) {
        !          2532:                if (bus_dmamap_create(sc->sc_dmat, MCLBYTES,
        !          2533:                    XL_TX_LIST_CNT - 3, MCLBYTES, 0, BUS_DMA_NOWAIT,
        !          2534:                    &sc->xl_cdata.xl_tx_chain[i].map) != 0) {
        !          2535:                        printf(": can't create tx map\n");
        !          2536:                        return;
        !          2537:                }
        !          2538:        }
        !          2539:        if (bus_dmamap_create(sc->sc_dmat, MCLBYTES, XL_TX_LIST_CNT - 3,
        !          2540:            MCLBYTES, 0, BUS_DMA_NOWAIT, &sc->sc_tx_sparemap) != 0) {
        !          2541:                printf(": can't create tx spare map\n");
        !          2542:                return;
        !          2543:        }
        !          2544:
        !          2545:        printf(", address %s\n", ether_sprintf(sc->sc_arpcom.ac_enaddr));
        !          2546:
        !          2547:        if (sc->xl_flags & (XL_FLAG_INVERT_LED_PWR|XL_FLAG_INVERT_MII_PWR)) {
        !          2548:                u_int16_t n;
        !          2549:
        !          2550:                XL_SEL_WIN(2);
        !          2551:                n = CSR_READ_2(sc, 12);
        !          2552:
        !          2553:                if (sc->xl_flags & XL_FLAG_INVERT_LED_PWR)
        !          2554:                        n |= 0x0010;
        !          2555:
        !          2556:                if (sc->xl_flags & XL_FLAG_INVERT_MII_PWR)
        !          2557:                        n |= 0x4000;
        !          2558:
        !          2559:                CSR_WRITE_2(sc, 12, n);
        !          2560:        }
        !          2561:
        !          2562:        /*
        !          2563:         * Figure out the card type. 3c905B adapters have the
        !          2564:         * 'supportsNoTxLength' bit set in the capabilities
        !          2565:         * word in the EEPROM.
        !          2566:         * Note: my 3c575C cardbus card lies. It returns a value
        !          2567:         * of 0x1578 for its capabilities word, which is somewhat
        !          2568:         * nonsensical. Another way to distinguish a 3c90x chip
        !          2569:         * from a 3c90xB/C chip is to check for the 'supportsLargePackets'
        !          2570:         * bit. This will only be set for 3c90x boomerage chips.
        !          2571:         */
        !          2572:        xl_read_eeprom(sc, (caddr_t)&sc->xl_caps, XL_EE_CAPS, 1, 0);
        !          2573:        if (sc->xl_caps & XL_CAPS_NO_TXLENGTH ||
        !          2574:            !(sc->xl_caps & XL_CAPS_LARGE_PKTS))
        !          2575:                sc->xl_type = XL_TYPE_905B;
        !          2576:        else
        !          2577:                sc->xl_type = XL_TYPE_90X;
        !          2578:
        !          2579:        timeout_set(&sc->xl_stsup_tmo, xl_stats_update, sc);
        !          2580:
        !          2581:        ifp->if_softc = sc;
        !          2582:        ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
        !          2583:        ifp->if_ioctl = xl_ioctl;
        !          2584:        if (sc->xl_type == XL_TYPE_905B)
        !          2585:                ifp->if_start = xl_start_90xB;
        !          2586:        else
        !          2587:                ifp->if_start = xl_start;
        !          2588:        ifp->if_watchdog = xl_watchdog;
        !          2589:        ifp->if_baudrate = 10000000;
        !          2590:        IFQ_SET_MAXLEN(&ifp->if_snd, XL_TX_LIST_CNT - 1);
        !          2591:        IFQ_SET_READY(&ifp->if_snd);
        !          2592:        bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
        !          2593:
        !          2594:        ifp->if_capabilities = IFCAP_VLAN_MTU;
        !          2595:
        !          2596: #ifndef XL905B_TXCSUM_BROKEN
        !          2597:        ifp->if_capabilities |= IFCAP_CSUM_IPv4|IFCAP_CSUM_TCPv4|
        !          2598:                                IFCAP_CSUM_UDPv4;
        !          2599: #endif
        !          2600:
        !          2601:        XL_SEL_WIN(3);
        !          2602:        sc->xl_media = CSR_READ_2(sc, XL_W3_MEDIA_OPT);
        !          2603:
        !          2604:        xl_read_eeprom(sc, (char *)&xcvr, XL_EE_ICFG_0, 2, 0);
        !          2605:        sc->xl_xcvr = xcvr[0] | xcvr[1] << 16;
        !          2606:        sc->xl_xcvr &= XL_ICFG_CONNECTOR_MASK;
        !          2607:        sc->xl_xcvr >>= XL_ICFG_CONNECTOR_BITS;
        !          2608:
        !          2609:        xl_mediacheck(sc);
        !          2610:
        !          2611:        if (sc->xl_media & XL_MEDIAOPT_MII || sc->xl_media & XL_MEDIAOPT_BTX
        !          2612:            || sc->xl_media & XL_MEDIAOPT_BT4) {
        !          2613:                ifmedia_init(&sc->sc_mii.mii_media, 0,
        !          2614:                    xl_ifmedia_upd, xl_ifmedia_sts);
        !          2615:                sc->xl_hasmii = 1;
        !          2616:                sc->sc_mii.mii_ifp = ifp;
        !          2617:                sc->sc_mii.mii_readreg = xl_miibus_readreg;
        !          2618:                sc->sc_mii.mii_writereg = xl_miibus_writereg;
        !          2619:                sc->sc_mii.mii_statchg = xl_miibus_statchg;
        !          2620:                xl_setcfg(sc);
        !          2621:                mii_attach((struct device *)sc, &sc->sc_mii, 0xffffffff,
        !          2622:                    MII_PHY_ANY, MII_OFFSET_ANY, 0);
        !          2623:
        !          2624:                if (LIST_FIRST(&sc->sc_mii.mii_phys) == NULL) {
        !          2625:                        ifmedia_add(&sc->sc_mii.mii_media, IFM_ETHER|IFM_NONE,
        !          2626:                            0, NULL);
        !          2627:                        ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_NONE);
        !          2628:                }
        !          2629:                else {
        !          2630:                        ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_AUTO);
        !          2631:                }
        !          2632:                ifm = &sc->sc_mii.mii_media;
        !          2633:        }
        !          2634:        else {
        !          2635:                ifmedia_init(&sc->ifmedia, 0, xl_ifmedia_upd, xl_ifmedia_sts);
        !          2636:                sc->xl_hasmii = 0;
        !          2637:                ifm = &sc->ifmedia;
        !          2638:        }
        !          2639:
        !          2640:        /*
        !          2641:         * Sanity check. If the user has selected "auto" and this isn't
        !          2642:         * a 10/100 card of some kind, we need to force the transceiver
        !          2643:         * type to something sane.
        !          2644:         */
        !          2645:        if (sc->xl_xcvr == XL_XCVR_AUTO) {
        !          2646:                xl_choose_xcvr(sc, 0);
        !          2647:                i = splnet();
        !          2648:                xl_reset(sc);
        !          2649:                splx(i);
        !          2650:        }
        !          2651:
        !          2652:        if (sc->xl_media & XL_MEDIAOPT_BT) {
        !          2653:                ifmedia_add(ifm, IFM_ETHER|IFM_10_T, 0, NULL);
        !          2654:                ifmedia_add(ifm, IFM_ETHER|IFM_10_T|IFM_HDX, 0, NULL);
        !          2655:                if (sc->xl_caps & XL_CAPS_FULL_DUPLEX)
        !          2656:                        ifmedia_add(ifm, IFM_ETHER|IFM_10_T|IFM_FDX, 0, NULL);
        !          2657:        }
        !          2658:
        !          2659:        if (sc->xl_media & (XL_MEDIAOPT_AUI|XL_MEDIAOPT_10FL)) {
        !          2660:                /*
        !          2661:                 * Check for a 10baseFL board in disguise.
        !          2662:                 */
        !          2663:                if (sc->xl_type == XL_TYPE_905B &&
        !          2664:                    sc->xl_media == XL_MEDIAOPT_10FL) {
        !          2665:                        ifmedia_add(ifm, IFM_ETHER|IFM_10_FL, 0, NULL);
        !          2666:                        ifmedia_add(ifm, IFM_ETHER|IFM_10_FL|IFM_HDX,
        !          2667:                            0, NULL);
        !          2668:                        if (sc->xl_caps & XL_CAPS_FULL_DUPLEX)
        !          2669:                                ifmedia_add(ifm,
        !          2670:                                    IFM_ETHER|IFM_10_FL|IFM_FDX, 0, NULL);
        !          2671:                } else {
        !          2672:                        ifmedia_add(ifm, IFM_ETHER|IFM_10_5, 0, NULL);
        !          2673:                }
        !          2674:        }
        !          2675:
        !          2676:        if (sc->xl_media & XL_MEDIAOPT_BNC) {
        !          2677:                ifmedia_add(ifm, IFM_ETHER|IFM_10_2, 0, NULL);
        !          2678:        }
        !          2679:
        !          2680:        if (sc->xl_media & XL_MEDIAOPT_BFX) {
        !          2681:                ifp->if_baudrate = 100000000;
        !          2682:                ifmedia_add(ifm, IFM_ETHER|IFM_100_FX, 0, NULL);
        !          2683:        }
        !          2684:
        !          2685:        /* Choose a default media. */
        !          2686:        switch(sc->xl_xcvr) {
        !          2687:        case XL_XCVR_10BT:
        !          2688:                media = IFM_ETHER|IFM_10_T;
        !          2689:                xl_setmode(sc, media);
        !          2690:                break;
        !          2691:        case XL_XCVR_AUI:
        !          2692:                if (sc->xl_type == XL_TYPE_905B &&
        !          2693:                    sc->xl_media == XL_MEDIAOPT_10FL) {
        !          2694:                        media = IFM_ETHER|IFM_10_FL;
        !          2695:                        xl_setmode(sc, media);
        !          2696:                } else {
        !          2697:                        media = IFM_ETHER|IFM_10_5;
        !          2698:                        xl_setmode(sc, media);
        !          2699:                }
        !          2700:                break;
        !          2701:        case XL_XCVR_COAX:
        !          2702:                media = IFM_ETHER|IFM_10_2;
        !          2703:                xl_setmode(sc, media);
        !          2704:                break;
        !          2705:        case XL_XCVR_AUTO:
        !          2706:        case XL_XCVR_100BTX:
        !          2707:        case XL_XCVR_MII:
        !          2708:                /* Chosen by miibus */
        !          2709:                break;
        !          2710:        case XL_XCVR_100BFX:
        !          2711:                media = IFM_ETHER|IFM_100_FX;
        !          2712:                xl_setmode(sc, media);
        !          2713:                break;
        !          2714:        default:
        !          2715:                printf("%s: unknown XCVR type: %d\n", sc->sc_dev.dv_xname,
        !          2716:                                                        sc->xl_xcvr);
        !          2717:                /*
        !          2718:                 * This will probably be wrong, but it prevents
        !          2719:                 * the ifmedia code from panicking.
        !          2720:                 */
        !          2721:                media = IFM_ETHER | IFM_10_T;
        !          2722:                break;
        !          2723:        }
        !          2724:
        !          2725:        if (sc->xl_hasmii == 0)
        !          2726:                ifmedia_set(&sc->ifmedia, media);
        !          2727:
        !          2728:        if (sc->xl_flags & XL_FLAG_NO_XCVR_PWR) {
        !          2729:                XL_SEL_WIN(0);
        !          2730:                CSR_WRITE_2(sc, XL_W0_MFG_ID, XL_NO_XCVR_PWR_MAGICBITS);
        !          2731:        }
        !          2732:
        !          2733:        /*
        !          2734:         * Call MI attach routines.
        !          2735:         */
        !          2736:        if_attach(ifp);
        !          2737:        ether_ifattach(ifp);
        !          2738:
        !          2739:        sc->sc_sdhook = shutdownhook_establish(xl_shutdown, sc);
        !          2740:        sc->sc_pwrhook = powerhook_establish(xl_power, sc);
        !          2741: }
        !          2742:
        !          2743: void
        !          2744: xl_shutdown(void *v)
        !          2745: {
        !          2746:        struct xl_softc *sc = (struct xl_softc *)v;
        !          2747:
        !          2748:        xl_reset(sc);
        !          2749:        xl_stop(sc);
        !          2750: }
        !          2751:
        !          2752: struct cfdriver xl_cd = {
        !          2753:        0, "xl", DV_IFNET
        !          2754: };

CVSweb