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

Annotation of sys/dev/pci/if_lge.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: if_lge.c,v 1.45 2006/10/25 02:37:50 brad Exp $        */
        !             2: /*
        !             3:  * Copyright (c) 2001 Wind River Systems
        !             4:  * Copyright (c) 1997, 1998, 1999, 2000, 2001
        !             5:  *     Bill Paul <william.paul@windriver.com>.  All rights reserved.
        !             6:  *
        !             7:  * Redistribution and use in source and binary forms, with or without
        !             8:  * modification, are permitted provided that the following conditions
        !             9:  * are met:
        !            10:  * 1. Redistributions of source code must retain the above copyright
        !            11:  *    notice, this list of conditions and the following disclaimer.
        !            12:  * 2. Redistributions in binary form must reproduce the above copyright
        !            13:  *    notice, this list of conditions and the following disclaimer in the
        !            14:  *    documentation and/or other materials provided with the distribution.
        !            15:  * 3. All advertising materials mentioning features or use of this software
        !            16:  *    must display the following acknowledgement:
        !            17:  *     This product includes software developed by Bill Paul.
        !            18:  * 4. Neither the name of the author nor the names of any co-contributors
        !            19:  *    may be used to endorse or promote products derived from this software
        !            20:  *    without specific prior written permission.
        !            21:  *
        !            22:  * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
        !            23:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            24:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            25:  * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
        !            26:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
        !            27:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
        !            28:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
        !            29:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
        !            30:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
        !            31:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
        !            32:  * THE POSSIBILITY OF SUCH DAMAGE.
        !            33:  *
        !            34:  * $FreeBSD: src/sys/dev/lge/if_lge.c,v 1.6 2001/06/20 19:47:55 bmilekic Exp $
        !            35:  */
        !            36:
        !            37: /*
        !            38:  * Level 1 LXT1001 gigabit ethernet driver for FreeBSD. Public
        !            39:  * documentation not available, but ask me nicely.
        !            40:  *
        !            41:  * Written by Bill Paul <william.paul@windriver.com>
        !            42:  * Wind River Systems
        !            43:  */
        !            44:
        !            45: /*
        !            46:  * The Level 1 chip is used on some D-Link, SMC and Addtron NICs.
        !            47:  * It's a 64-bit PCI part that supports TCP/IP checksum offload,
        !            48:  * VLAN tagging/insertion, GMII and TBI (1000baseX) ports. There
        !            49:  * are three supported methods for data transfer between host and
        !            50:  * NIC: programmed I/O, traditional scatter/gather DMA and Packet
        !            51:  * Propulsion Technology (tm) DMA. The latter mechanism is a form
        !            52:  * of double buffer DMA where the packet data is copied to a
        !            53:  * pre-allocated DMA buffer who's physical address has been loaded
        !            54:  * into a table at device initialization time. The rationale is that
        !            55:  * the virtual to physical address translation needed for normal
        !            56:  * scatter/gather DMA is more expensive than the data copy needed
        !            57:  * for double buffering. This may be true in Windows NT and the like,
        !            58:  * but it isn't true for us, at least on the x86 arch. This driver
        !            59:  * uses the scatter/gather I/O method for both TX and RX.
        !            60:  *
        !            61:  * The LXT1001 only supports TCP/IP checksum offload on receive.
        !            62:  * Also, the VLAN tagging is done using a 16-entry table which allows
        !            63:  * the chip to perform hardware filtering based on VLAN tags. Sadly,
        !            64:  * our vlan support doesn't currently play well with this kind of
        !            65:  * hardware support.
        !            66:  *
        !            67:  * Special thanks to:
        !            68:  * - Jeff James at Intel, for arranging to have the LXT1001 manual
        !            69:  *   released (at long last)
        !            70:  * - Beny Chen at D-Link, for actually sending it to me
        !            71:  * - Brad Short and Keith Alexis at SMC, for sending me sample
        !            72:  *   SMC9462SX and SMC9462TX adapters for testing
        !            73:  * - Paul Saab at Y!, for not killing me (though it remains to be seen
        !            74:  *   if in fact he did me much of a favor)
        !            75:  */
        !            76:
        !            77: #include "bpfilter.h"
        !            78:
        !            79: #include <sys/param.h>
        !            80: #include <sys/systm.h>
        !            81: #include <sys/sockio.h>
        !            82: #include <sys/mbuf.h>
        !            83: #include <sys/malloc.h>
        !            84: #include <sys/kernel.h>
        !            85: #include <sys/device.h>
        !            86: #include <sys/socket.h>
        !            87:
        !            88: #include <net/if.h>
        !            89: #include <net/if_dl.h>
        !            90: #include <net/if_media.h>
        !            91:
        !            92: #ifdef INET
        !            93: #include <netinet/in.h>
        !            94: #include <netinet/in_systm.h>
        !            95: #include <netinet/in_var.h>
        !            96: #include <netinet/ip.h>
        !            97: #include <netinet/if_ether.h>
        !            98: #endif
        !            99:
        !           100: #if NBPFILTER > 0
        !           101: #include <net/bpf.h>
        !           102: #endif
        !           103:
        !           104: #include <uvm/uvm_extern.h>              /* for vtophys */
        !           105: #define        VTOPHYS(v)      vtophys((vaddr_t)(v))
        !           106:
        !           107: #include <dev/pci/pcireg.h>
        !           108: #include <dev/pci/pcivar.h>
        !           109: #include <dev/pci/pcidevs.h>
        !           110:
        !           111: #include <dev/mii/mii.h>
        !           112: #include <dev/mii/miivar.h>
        !           113:
        !           114: #define LGE_USEIOSPACE
        !           115:
        !           116: #include <dev/pci/if_lgereg.h>
        !           117:
        !           118: int lge_probe(struct device *, void *, void *);
        !           119: void lge_attach(struct device *, struct device *, void *);
        !           120:
        !           121: struct cfattach lge_ca = {
        !           122:        sizeof(struct lge_softc), lge_probe, lge_attach
        !           123: };
        !           124:
        !           125: struct cfdriver lge_cd = {
        !           126:        0, "lge", DV_IFNET
        !           127: };
        !           128:
        !           129: int lge_alloc_jumbo_mem(struct lge_softc *);
        !           130: void *lge_jalloc(struct lge_softc *);
        !           131: void lge_jfree(caddr_t, u_int, void *);
        !           132:
        !           133: int lge_newbuf(struct lge_softc *, struct lge_rx_desc *,
        !           134:                             struct mbuf *);
        !           135: int lge_encap(struct lge_softc *, struct mbuf *, u_int32_t *);
        !           136: void lge_rxeof(struct lge_softc *, int);
        !           137: void lge_txeof(struct lge_softc *);
        !           138: int lge_intr(void *);
        !           139: void lge_tick(void *);
        !           140: void lge_start(struct ifnet *);
        !           141: int lge_ioctl(struct ifnet *, u_long, caddr_t);
        !           142: void lge_init(void *);
        !           143: void lge_stop(struct lge_softc *);
        !           144: void lge_watchdog(struct ifnet *);
        !           145: void lge_shutdown(void *);
        !           146: int lge_ifmedia_upd(struct ifnet *);
        !           147: void lge_ifmedia_sts(struct ifnet *, struct ifmediareq *);
        !           148:
        !           149: void lge_eeprom_getword(struct lge_softc *, int, u_int16_t *);
        !           150: void lge_read_eeprom(struct lge_softc *, caddr_t, int, int, int);
        !           151:
        !           152: int lge_miibus_readreg(struct device *, int, int);
        !           153: void lge_miibus_writereg(struct device *, int, int, int);
        !           154: void lge_miibus_statchg(struct device *);
        !           155:
        !           156: void lge_setmulti(struct lge_softc *);
        !           157: void lge_reset(struct lge_softc *);
        !           158: int lge_list_rx_init(struct lge_softc *);
        !           159: int lge_list_tx_init(struct lge_softc *);
        !           160:
        !           161: #ifdef LGE_DEBUG
        !           162: #define DPRINTF(x)     if (lgedebug) printf x
        !           163: #define DPRINTFN(n,x)  if (lgedebug >= (n)) printf x
        !           164: int    lgedebug = 0;
        !           165: #else
        !           166: #define DPRINTF(x)
        !           167: #define DPRINTFN(n,x)
        !           168: #endif
        !           169:
        !           170: const struct pci_matchid lge_devices[] = {
        !           171:        { PCI_VENDOR_LEVEL1, PCI_PRODUCT_LEVEL1_LXT1001 }
        !           172: };
        !           173:
        !           174: #define LGE_SETBIT(sc, reg, x)                         \
        !           175:        CSR_WRITE_4(sc, reg,                            \
        !           176:                CSR_READ_4(sc, reg) | (x))
        !           177:
        !           178: #define LGE_CLRBIT(sc, reg, x)                         \
        !           179:        CSR_WRITE_4(sc, reg,                            \
        !           180:                CSR_READ_4(sc, reg) & ~(x))
        !           181:
        !           182: #define SIO_SET(x)                                     \
        !           183:        CSR_WRITE_4(sc, LGE_MEAR, CSR_READ_4(sc, LGE_MEAR) | x)
        !           184:
        !           185: #define SIO_CLR(x)                                     \
        !           186:        CSR_WRITE_4(sc, LGE_MEAR, CSR_READ_4(sc, LGE_MEAR) & ~x)
        !           187:
        !           188: /*
        !           189:  * Read a word of data stored in the EEPROM at address 'addr.'
        !           190:  */
        !           191: void
        !           192: lge_eeprom_getword(struct lge_softc *sc, int addr, u_int16_t *dest)
        !           193: {
        !           194:        int                     i;
        !           195:        u_int32_t               val;
        !           196:
        !           197:        CSR_WRITE_4(sc, LGE_EECTL, LGE_EECTL_CMD_READ|
        !           198:            LGE_EECTL_SINGLEACCESS|((addr >> 1) << 8));
        !           199:
        !           200:        for (i = 0; i < LGE_TIMEOUT; i++)
        !           201:                if (!(CSR_READ_4(sc, LGE_EECTL) & LGE_EECTL_CMD_READ))
        !           202:                        break;
        !           203:
        !           204:        if (i == LGE_TIMEOUT) {
        !           205:                printf("%s: EEPROM read timed out\n", sc->sc_dv.dv_xname);
        !           206:                return;
        !           207:        }
        !           208:
        !           209:        val = CSR_READ_4(sc, LGE_EEDATA);
        !           210:
        !           211:        if (addr & 1)
        !           212:                *dest = (val >> 16) & 0xFFFF;
        !           213:        else
        !           214:                *dest = val & 0xFFFF;
        !           215: }
        !           216:
        !           217: /*
        !           218:  * Read a sequence of words from the EEPROM.
        !           219:  */
        !           220: void
        !           221: lge_read_eeprom(struct lge_softc *sc, caddr_t dest, int off,
        !           222:     int cnt, int swap)
        !           223: {
        !           224:        int                     i;
        !           225:        u_int16_t               word = 0, *ptr;
        !           226:
        !           227:        for (i = 0; i < cnt; i++) {
        !           228:                lge_eeprom_getword(sc, off + i, &word);
        !           229:                ptr = (u_int16_t *)(dest + (i * 2));
        !           230:                if (swap)
        !           231:                        *ptr = ntohs(word);
        !           232:                else
        !           233:                        *ptr = word;
        !           234:        }
        !           235: }
        !           236:
        !           237: int
        !           238: lge_miibus_readreg(struct device *dev, int phy, int reg)
        !           239: {
        !           240:        struct lge_softc        *sc = (struct lge_softc *)dev;
        !           241:        int                     i;
        !           242:
        !           243:        /*
        !           244:         * If we have a non-PCS PHY, pretend that the internal
        !           245:         * autoneg stuff at PHY address 0 isn't there so that
        !           246:         * the miibus code will find only the GMII PHY.
        !           247:         */
        !           248:        if (sc->lge_pcs == 0 && phy == 0)
        !           249:                return (0);
        !           250:
        !           251:        CSR_WRITE_4(sc, LGE_GMIICTL, (phy << 8) | reg | LGE_GMIICMD_READ);
        !           252:
        !           253:        for (i = 0; i < LGE_TIMEOUT; i++)
        !           254:                if (!(CSR_READ_4(sc, LGE_GMIICTL) & LGE_GMIICTL_CMDBUSY))
        !           255:                        break;
        !           256:
        !           257:        if (i == LGE_TIMEOUT) {
        !           258:                printf("%s: PHY read timed out\n", sc->sc_dv.dv_xname);
        !           259:                return (0);
        !           260:        }
        !           261:
        !           262:        return (CSR_READ_4(sc, LGE_GMIICTL) >> 16);
        !           263: }
        !           264:
        !           265: void
        !           266: lge_miibus_writereg(struct device *dev, int phy, int reg, int data)
        !           267: {
        !           268:        struct lge_softc        *sc = (struct lge_softc *)dev;
        !           269:        int                     i;
        !           270:
        !           271:        CSR_WRITE_4(sc, LGE_GMIICTL,
        !           272:            (data << 16) | (phy << 8) | reg | LGE_GMIICMD_WRITE);
        !           273:
        !           274:        for (i = 0; i < LGE_TIMEOUT; i++)
        !           275:                if (!(CSR_READ_4(sc, LGE_GMIICTL) & LGE_GMIICTL_CMDBUSY))
        !           276:                        break;
        !           277:
        !           278:        if (i == LGE_TIMEOUT) {
        !           279:                printf("%s: PHY write timed out\n", sc->sc_dv.dv_xname);
        !           280:        }
        !           281: }
        !           282:
        !           283: void
        !           284: lge_miibus_statchg(struct device *dev)
        !           285: {
        !           286:        struct lge_softc        *sc = (struct lge_softc *)dev;
        !           287:        struct mii_data         *mii = &sc->lge_mii;
        !           288:
        !           289:        LGE_CLRBIT(sc, LGE_GMIIMODE, LGE_GMIIMODE_SPEED);
        !           290:        switch (IFM_SUBTYPE(mii->mii_media_active)) {
        !           291:        case IFM_1000_T:
        !           292:        case IFM_1000_SX:
        !           293:                LGE_SETBIT(sc, LGE_GMIIMODE, LGE_SPEED_1000);
        !           294:                break;
        !           295:        case IFM_100_TX:
        !           296:                LGE_SETBIT(sc, LGE_GMIIMODE, LGE_SPEED_100);
        !           297:                break;
        !           298:        case IFM_10_T:
        !           299:                LGE_SETBIT(sc, LGE_GMIIMODE, LGE_SPEED_10);
        !           300:                break;
        !           301:        default:
        !           302:                /*
        !           303:                 * Choose something, even if it's wrong. Clearing
        !           304:                 * all the bits will hose autoneg on the internal
        !           305:                 * PHY.
        !           306:                 */
        !           307:                LGE_SETBIT(sc, LGE_GMIIMODE, LGE_SPEED_1000);
        !           308:                break;
        !           309:        }
        !           310:
        !           311:        if ((mii->mii_media_active & IFM_GMASK) == IFM_FDX) {
        !           312:                LGE_SETBIT(sc, LGE_GMIIMODE, LGE_GMIIMODE_FDX);
        !           313:        } else {
        !           314:                LGE_CLRBIT(sc, LGE_GMIIMODE, LGE_GMIIMODE_FDX);
        !           315:        }
        !           316: }
        !           317:
        !           318: void
        !           319: lge_setmulti(struct lge_softc *sc)
        !           320: {
        !           321:        struct arpcom           *ac = &sc->arpcom;
        !           322:        struct ifnet            *ifp = &ac->ac_if;
        !           323:        struct ether_multi      *enm;
        !           324:        struct ether_multistep  step;
        !           325:        u_int32_t               h = 0, hashes[2] = { 0, 0 };
        !           326:
        !           327:        /* Make sure multicast hash table is enabled. */
        !           328:        CSR_WRITE_4(sc, LGE_MODE1, LGE_MODE1_SETRST_CTL1|LGE_MODE1_RX_MCAST);
        !           329:
        !           330: allmulti:
        !           331:        if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) {
        !           332:                CSR_WRITE_4(sc, LGE_MAR0, 0xFFFFFFFF);
        !           333:                CSR_WRITE_4(sc, LGE_MAR1, 0xFFFFFFFF);
        !           334:                return;
        !           335:        }
        !           336:
        !           337:        /* first, zot all the existing hash bits */
        !           338:        CSR_WRITE_4(sc, LGE_MAR0, 0);
        !           339:        CSR_WRITE_4(sc, LGE_MAR1, 0);
        !           340:
        !           341:        /* now program new ones */
        !           342:        ETHER_FIRST_MULTI(step, ac, enm);
        !           343:        while (enm != NULL) {
        !           344:                if (bcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) {
        !           345:                        ifp->if_flags |= IFF_ALLMULTI;
        !           346:                        goto allmulti;
        !           347:                }
        !           348:                h = (ether_crc32_be(enm->enm_addrlo, ETHER_ADDR_LEN) >> 26) &
        !           349:                    0x0000003F;
        !           350:                if (h < 32)
        !           351:                        hashes[0] |= (1 << h);
        !           352:                else
        !           353:                        hashes[1] |= (1 << (h - 32));
        !           354:                ETHER_NEXT_MULTI(step, enm);
        !           355:        }
        !           356:
        !           357:        CSR_WRITE_4(sc, LGE_MAR0, hashes[0]);
        !           358:        CSR_WRITE_4(sc, LGE_MAR1, hashes[1]);
        !           359: }
        !           360:
        !           361: void
        !           362: lge_reset(struct lge_softc *sc)
        !           363: {
        !           364:        int                     i;
        !           365:
        !           366:        LGE_SETBIT(sc, LGE_MODE1, LGE_MODE1_SETRST_CTL0|LGE_MODE1_SOFTRST);
        !           367:
        !           368:        for (i = 0; i < LGE_TIMEOUT; i++) {
        !           369:                if (!(CSR_READ_4(sc, LGE_MODE1) & LGE_MODE1_SOFTRST))
        !           370:                        break;
        !           371:        }
        !           372:
        !           373:        if (i == LGE_TIMEOUT)
        !           374:                printf("%s: reset never completed\n", sc->sc_dv.dv_xname);
        !           375:
        !           376:        /* Wait a little while for the chip to get its brains in order. */
        !           377:        DELAY(1000);
        !           378: }
        !           379:
        !           380: /*
        !           381:  * Probe for a Level 1 chip. Check the PCI vendor and device
        !           382:  * IDs against our list and return a device name if we find a match.
        !           383:  */
        !           384: int
        !           385: lge_probe(struct device *parent, void *match, void *aux)
        !           386: {
        !           387:        return (pci_matchbyid((struct pci_attach_args *)aux, lge_devices,
        !           388:            sizeof(lge_devices)/sizeof(lge_devices[0])));
        !           389: }
        !           390:
        !           391: /*
        !           392:  * Attach the interface. Allocate softc structures, do ifmedia
        !           393:  * setup and ethernet/BPF attach.
        !           394:  */
        !           395: void
        !           396: lge_attach(struct device *parent, struct device *self, void *aux)
        !           397: {
        !           398:        struct lge_softc        *sc = (struct lge_softc *)self;
        !           399:        struct pci_attach_args  *pa = aux;
        !           400:        pci_chipset_tag_t       pc = pa->pa_pc;
        !           401:        pci_intr_handle_t       ih;
        !           402:        const char              *intrstr = NULL;
        !           403:        bus_size_t              size;
        !           404:        bus_dma_segment_t       seg;
        !           405:        bus_dmamap_t            dmamap;
        !           406:        int                     rseg;
        !           407:        u_char                  eaddr[ETHER_ADDR_LEN];
        !           408:        pcireg_t                command;
        !           409: #ifndef LGE_USEIOSPACE
        !           410:        pcireg_t                memtype;
        !           411: #endif
        !           412:        struct ifnet            *ifp;
        !           413:        caddr_t                 kva;
        !           414:
        !           415:        /*
        !           416:         * Handle power management nonsense.
        !           417:         */
        !           418:        DPRINTFN(5, ("Preparing for conf read\n"));
        !           419:        command = pci_conf_read(pc, pa->pa_tag, LGE_PCI_CAPID) & 0x000000FF;
        !           420:        if (command == 0x01) {
        !           421:                command = pci_conf_read(pc, pa->pa_tag, LGE_PCI_PWRMGMTCTRL);
        !           422:                if (command & LGE_PSTATE_MASK) {
        !           423:                        pcireg_t        iobase, membase, irq;
        !           424:
        !           425:                        /* Save important PCI config data. */
        !           426:                        iobase = pci_conf_read(pc, pa->pa_tag, LGE_PCI_LOIO);
        !           427:                        membase = pci_conf_read(pc, pa->pa_tag, LGE_PCI_LOMEM);
        !           428:                        irq = pci_conf_read(pc, pa->pa_tag, LGE_PCI_INTLINE);
        !           429:
        !           430:                        /* Reset the power state. */
        !           431:                        printf("%s: chip is in D%d power mode "
        !           432:                               "-- setting to D0\n", sc->sc_dv.dv_xname,
        !           433:                               command & LGE_PSTATE_MASK);
        !           434:                        command &= 0xFFFFFFFC;
        !           435:                        pci_conf_write(pc, pa->pa_tag,
        !           436:                                       LGE_PCI_PWRMGMTCTRL, command);
        !           437:
        !           438:                        /* Restore PCI config data. */
        !           439:                        pci_conf_write(pc, pa->pa_tag, LGE_PCI_LOIO, iobase);
        !           440:                        pci_conf_write(pc, pa->pa_tag, LGE_PCI_LOMEM, membase);
        !           441:                        pci_conf_write(pc, pa->pa_tag, LGE_PCI_INTLINE, irq);
        !           442:                }
        !           443:        }
        !           444:
        !           445:        /*
        !           446:         * Map control/status registers.
        !           447:         */
        !           448:        DPRINTFN(5, ("Map control/status regs\n"));
        !           449:
        !           450:        DPRINTFN(5, ("pci_mapreg_map\n"));
        !           451: #ifdef LGE_USEIOSPACE
        !           452:        if (pci_mapreg_map(pa, LGE_PCI_LOIO, PCI_MAPREG_TYPE_IO, 0,
        !           453:            &sc->lge_btag, &sc->lge_bhandle, NULL, &size, 0)) {
        !           454:                printf(": can't map i/o space\n");
        !           455:                return;
        !           456:        }
        !           457: #else
        !           458:        memtype = pci_mapreg_type(pc, pa->pa_tag, LGE_PCI_LOMEM);
        !           459:        switch (memtype) {
        !           460:        case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT:
        !           461:        case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_64BIT:
        !           462:                if (pci_mapreg_map(pa, LGE_PCI_LOMEM,
        !           463:                                   memtype, 0, &sc->lge_btag, &sc->lge_bhandle,
        !           464:                                   NULL, &size, 0) == 0)
        !           465:                        break;
        !           466:        default:
        !           467:                printf(": can't map mem space\n");
        !           468:                return;
        !           469:        }
        !           470: #endif
        !           471:
        !           472:        DPRINTFN(5, ("pci_intr_map\n"));
        !           473:        if (pci_intr_map(pa, &ih)) {
        !           474:                printf(": couldn't map interrupt\n");
        !           475:                goto fail_1;
        !           476:        }
        !           477:
        !           478:        DPRINTFN(5, ("pci_intr_string\n"));
        !           479:        intrstr = pci_intr_string(pc, ih);
        !           480:        DPRINTFN(5, ("pci_intr_establish\n"));
        !           481:        sc->lge_intrhand = pci_intr_establish(pc, ih, IPL_NET, lge_intr, sc,
        !           482:                                              sc->sc_dv.dv_xname);
        !           483:        if (sc->lge_intrhand == NULL) {
        !           484:                printf(": couldn't establish interrupt");
        !           485:                if (intrstr != NULL)
        !           486:                        printf(" at %s", intrstr);
        !           487:                printf("\n");
        !           488:                goto fail_1;
        !           489:        }
        !           490:        printf(": %s", intrstr);
        !           491:
        !           492:        /* Reset the adapter. */
        !           493:        DPRINTFN(5, ("lge_reset\n"));
        !           494:        lge_reset(sc);
        !           495:
        !           496:        /*
        !           497:         * Get station address from the EEPROM.
        !           498:         */
        !           499:        DPRINTFN(5, ("lge_read_eeprom\n"));
        !           500:        lge_read_eeprom(sc, (caddr_t)&eaddr[0], LGE_EE_NODEADDR_0, 1, 0);
        !           501:        lge_read_eeprom(sc, (caddr_t)&eaddr[2], LGE_EE_NODEADDR_1, 1, 0);
        !           502:        lge_read_eeprom(sc, (caddr_t)&eaddr[4], LGE_EE_NODEADDR_2, 1, 0);
        !           503:
        !           504:        /*
        !           505:         * A Level 1 chip was detected. Inform the world.
        !           506:         */
        !           507:        printf(", address %s\n", ether_sprintf(eaddr));
        !           508:
        !           509:        bcopy(eaddr, (char *)&sc->arpcom.ac_enaddr, ETHER_ADDR_LEN);
        !           510:
        !           511:        sc->sc_dmatag = pa->pa_dmat;
        !           512:        DPRINTFN(5, ("bus_dmamem_alloc\n"));
        !           513:        if (bus_dmamem_alloc(sc->sc_dmatag, sizeof(struct lge_list_data),
        !           514:                             PAGE_SIZE, 0, &seg, 1, &rseg, BUS_DMA_NOWAIT)) {
        !           515:                printf("%s: can't alloc rx buffers\n", sc->sc_dv.dv_xname);
        !           516:                goto fail_2;
        !           517:        }
        !           518:        DPRINTFN(5, ("bus_dmamem_map\n"));
        !           519:        if (bus_dmamem_map(sc->sc_dmatag, &seg, rseg,
        !           520:                           sizeof(struct lge_list_data), &kva,
        !           521:                           BUS_DMA_NOWAIT)) {
        !           522:                printf("%s: can't map dma buffers (%d bytes)\n",
        !           523:                       sc->sc_dv.dv_xname, sizeof(struct lge_list_data));
        !           524:                goto fail_3;
        !           525:        }
        !           526:        DPRINTFN(5, ("bus_dmamem_create\n"));
        !           527:        if (bus_dmamap_create(sc->sc_dmatag, sizeof(struct lge_list_data), 1,
        !           528:                              sizeof(struct lge_list_data), 0,
        !           529:                              BUS_DMA_NOWAIT, &dmamap)) {
        !           530:                printf("%s: can't create dma map\n", sc->sc_dv.dv_xname);
        !           531:                goto fail_4;
        !           532:        }
        !           533:        DPRINTFN(5, ("bus_dmamem_load\n"));
        !           534:        if (bus_dmamap_load(sc->sc_dmatag, dmamap, kva,
        !           535:                            sizeof(struct lge_list_data), NULL,
        !           536:                            BUS_DMA_NOWAIT)) {
        !           537:                goto fail_5;
        !           538:        }
        !           539:
        !           540:        DPRINTFN(5, ("bzero\n"));
        !           541:        sc->lge_ldata = (struct lge_list_data *)kva;
        !           542:        bzero(sc->lge_ldata, sizeof(struct lge_list_data));
        !           543:
        !           544:        /* Try to allocate memory for jumbo buffers. */
        !           545:        DPRINTFN(5, ("lge_alloc_jumbo_mem\n"));
        !           546:        if (lge_alloc_jumbo_mem(sc)) {
        !           547:                printf("%s: jumbo buffer allocation failed\n",
        !           548:                       sc->sc_dv.dv_xname);
        !           549:                goto fail_5;
        !           550:        }
        !           551:
        !           552:        ifp = &sc->arpcom.ac_if;
        !           553:        ifp->if_softc = sc;
        !           554:        ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
        !           555:        ifp->if_ioctl = lge_ioctl;
        !           556:        ifp->if_start = lge_start;
        !           557:        ifp->if_watchdog = lge_watchdog;
        !           558:        ifp->if_baudrate = 1000000000;
        !           559:        ifp->if_hardmtu = LGE_JUMBO_MTU;
        !           560:        IFQ_SET_MAXLEN(&ifp->if_snd, LGE_TX_LIST_CNT - 1);
        !           561:        IFQ_SET_READY(&ifp->if_snd);
        !           562:        DPRINTFN(5, ("bcopy\n"));
        !           563:        bcopy(sc->sc_dv.dv_xname, ifp->if_xname, IFNAMSIZ);
        !           564:
        !           565:        ifp->if_capabilities = IFCAP_VLAN_MTU;
        !           566:
        !           567:        if (CSR_READ_4(sc, LGE_GMIIMODE) & LGE_GMIIMODE_PCSENH)
        !           568:                sc->lge_pcs = 1;
        !           569:        else
        !           570:                sc->lge_pcs = 0;
        !           571:
        !           572:        /*
        !           573:         * Do MII setup.
        !           574:         */
        !           575:        DPRINTFN(5, ("mii setup\n"));
        !           576:        sc->lge_mii.mii_ifp = ifp;
        !           577:        sc->lge_mii.mii_readreg = lge_miibus_readreg;
        !           578:        sc->lge_mii.mii_writereg = lge_miibus_writereg;
        !           579:        sc->lge_mii.mii_statchg = lge_miibus_statchg;
        !           580:        ifmedia_init(&sc->lge_mii.mii_media, 0, lge_ifmedia_upd,
        !           581:                     lge_ifmedia_sts);
        !           582:        mii_attach(&sc->sc_dv, &sc->lge_mii, 0xffffffff, MII_PHY_ANY,
        !           583:                   MII_OFFSET_ANY, 0);
        !           584:
        !           585:        if (LIST_FIRST(&sc->lge_mii.mii_phys) == NULL) {
        !           586:                printf("%s: no PHY found!\n", sc->sc_dv.dv_xname);
        !           587:                ifmedia_add(&sc->lge_mii.mii_media, IFM_ETHER|IFM_MANUAL,
        !           588:                            0, NULL);
        !           589:                ifmedia_set(&sc->lge_mii.mii_media, IFM_ETHER|IFM_MANUAL);
        !           590:        } else {
        !           591:                DPRINTFN(5, ("ifmedia_set\n"));
        !           592:                ifmedia_set(&sc->lge_mii.mii_media, IFM_ETHER|IFM_AUTO);
        !           593:        }
        !           594:
        !           595:        /*
        !           596:         * Call MI attach routine.
        !           597:         */
        !           598:        DPRINTFN(5, ("if_attach\n"));
        !           599:        if_attach(ifp);
        !           600:        DPRINTFN(5, ("ether_ifattach\n"));
        !           601:        ether_ifattach(ifp);
        !           602:        DPRINTFN(5, ("timeout_set\n"));
        !           603:        timeout_set(&sc->lge_timeout, lge_tick, sc);
        !           604:        timeout_add(&sc->lge_timeout, hz);
        !           605:        return;
        !           606:
        !           607: fail_5:
        !           608:        bus_dmamap_destroy(sc->sc_dmatag, dmamap);
        !           609:
        !           610: fail_4:
        !           611:        bus_dmamem_unmap(sc->sc_dmatag, kva,
        !           612:            sizeof(struct lge_list_data));
        !           613:
        !           614: fail_3:
        !           615:        bus_dmamem_free(sc->sc_dmatag, &seg, rseg);
        !           616:
        !           617: fail_2:
        !           618:        pci_intr_disestablish(pc, sc->lge_intrhand);
        !           619:
        !           620: fail_1:
        !           621:        bus_space_unmap(sc->lge_btag, sc->lge_bhandle, size);
        !           622: }
        !           623:
        !           624: /*
        !           625:  * Initialize the transmit descriptors.
        !           626:  */
        !           627: int
        !           628: lge_list_tx_init(struct lge_softc *sc)
        !           629: {
        !           630:        struct lge_list_data    *ld;
        !           631:        struct lge_ring_data    *cd;
        !           632:        int                     i;
        !           633:
        !           634:        cd = &sc->lge_cdata;
        !           635:        ld = sc->lge_ldata;
        !           636:        for (i = 0; i < LGE_TX_LIST_CNT; i++) {
        !           637:                ld->lge_tx_list[i].lge_mbuf = NULL;
        !           638:                ld->lge_tx_list[i].lge_ctl = 0;
        !           639:        }
        !           640:
        !           641:        cd->lge_tx_prod = cd->lge_tx_cons = 0;
        !           642:
        !           643:        return (0);
        !           644: }
        !           645:
        !           646:
        !           647: /*
        !           648:  * Initialize the RX descriptors and allocate mbufs for them. Note that
        !           649:  * we arralge the descriptors in a closed ring, so that the last descriptor
        !           650:  * points back to the first.
        !           651:  */
        !           652: int
        !           653: lge_list_rx_init(struct lge_softc *sc)
        !           654: {
        !           655:        struct lge_list_data    *ld;
        !           656:        struct lge_ring_data    *cd;
        !           657:        int                     i;
        !           658:
        !           659:        ld = sc->lge_ldata;
        !           660:        cd = &sc->lge_cdata;
        !           661:
        !           662:        cd->lge_rx_prod = cd->lge_rx_cons = 0;
        !           663:
        !           664:        CSR_WRITE_4(sc, LGE_RXDESC_ADDR_HI, 0);
        !           665:
        !           666:        for (i = 0; i < LGE_RX_LIST_CNT; i++) {
        !           667:                if (CSR_READ_1(sc, LGE_RXCMDFREE_8BIT) == 0)
        !           668:                        break;
        !           669:                if (lge_newbuf(sc, &ld->lge_rx_list[i], NULL) == ENOBUFS)
        !           670:                        return (ENOBUFS);
        !           671:        }
        !           672:
        !           673:        /* Clear possible 'rx command queue empty' interrupt. */
        !           674:        CSR_READ_4(sc, LGE_ISR);
        !           675:
        !           676:        return (0);
        !           677: }
        !           678:
        !           679: /*
        !           680:  * Initialize an RX descriptor and attach an MBUF cluster.
        !           681:  */
        !           682: int
        !           683: lge_newbuf(struct lge_softc *sc, struct lge_rx_desc *c, struct mbuf *m)
        !           684: {
        !           685:        struct mbuf             *m_new = NULL;
        !           686:
        !           687:        if (m == NULL) {
        !           688:                caddr_t buf = NULL;
        !           689:
        !           690:                MGETHDR(m_new, M_DONTWAIT, MT_DATA);
        !           691:                if (m_new == NULL)
        !           692:                        return (ENOBUFS);
        !           693:
        !           694:                /* Allocate the jumbo buffer */
        !           695:                buf = lge_jalloc(sc);
        !           696:                if (buf == NULL) {
        !           697:                        m_freem(m_new);
        !           698:                        return (ENOBUFS);
        !           699:                }
        !           700:
        !           701:                /* Attach the buffer to the mbuf */
        !           702:                m_new->m_len = m_new->m_pkthdr.len = LGE_JLEN;
        !           703:                MEXTADD(m_new, buf, LGE_JLEN, 0, lge_jfree, sc);
        !           704:        } else {
        !           705:                /*
        !           706:                 * We're re-using a previously allocated mbuf;
        !           707:                 * be sure to re-init pointers and lengths to
        !           708:                 * default values.
        !           709:                 */
        !           710:                m_new = m;
        !           711:                m_new->m_len = m_new->m_pkthdr.len = LGE_JLEN;
        !           712:                m_new->m_data = m_new->m_ext.ext_buf;
        !           713:        }
        !           714:
        !           715:        /*
        !           716:         * Adjust alignment so packet payload begins on a
        !           717:         * longword boundary. Mandatory for Alpha, useful on
        !           718:         * x86 too.
        !           719:        */
        !           720:        m_adj(m_new, ETHER_ALIGN);
        !           721:
        !           722:        c->lge_mbuf = m_new;
        !           723:        c->lge_fragptr_hi = 0;
        !           724:        c->lge_fragptr_lo = VTOPHYS(mtod(m_new, caddr_t));
        !           725:        c->lge_fraglen = m_new->m_len;
        !           726:        c->lge_ctl = m_new->m_len | LGE_RXCTL_WANTINTR | LGE_FRAGCNT(1);
        !           727:        c->lge_sts = 0;
        !           728:
        !           729:        /*
        !           730:         * Put this buffer in the RX command FIFO. To do this,
        !           731:         * we just write the physical address of the descriptor
        !           732:         * into the RX descriptor address registers. Note that
        !           733:         * there are two registers, one high DWORD and one low
        !           734:         * DWORD, which lets us specify a 64-bit address if
        !           735:         * desired. We only use a 32-bit address for now.
        !           736:         * Writing to the low DWORD register is what actually
        !           737:         * causes the command to be issued, so we do that
        !           738:         * last.
        !           739:         */
        !           740:        CSR_WRITE_4(sc, LGE_RXDESC_ADDR_LO, VTOPHYS(c));
        !           741:        LGE_INC(sc->lge_cdata.lge_rx_prod, LGE_RX_LIST_CNT);
        !           742:
        !           743:        return (0);
        !           744: }
        !           745:
        !           746: int
        !           747: lge_alloc_jumbo_mem(struct lge_softc *sc)
        !           748: {
        !           749:        caddr_t                 ptr, kva;
        !           750:        bus_dma_segment_t       seg;
        !           751:        bus_dmamap_t            dmamap;
        !           752:        int                     i, rseg, state, error;
        !           753:        struct lge_jpool_entry   *entry;
        !           754:
        !           755:        state = error = 0;
        !           756:
        !           757:        /* Grab a big chunk o' storage. */
        !           758:        if (bus_dmamem_alloc(sc->sc_dmatag, LGE_JMEM, PAGE_SIZE, 0,
        !           759:                             &seg, 1, &rseg, BUS_DMA_NOWAIT)) {
        !           760:                printf("%s: can't alloc rx buffers\n", sc->sc_dv.dv_xname);
        !           761:                return (ENOBUFS);
        !           762:        }
        !           763:
        !           764:        state = 1;
        !           765:        if (bus_dmamem_map(sc->sc_dmatag, &seg, rseg, LGE_JMEM, &kva,
        !           766:                           BUS_DMA_NOWAIT)) {
        !           767:                printf("%s: can't map dma buffers (%d bytes)\n",
        !           768:                       sc->sc_dv.dv_xname, LGE_JMEM);
        !           769:                error = ENOBUFS;
        !           770:                goto out;
        !           771:        }
        !           772:
        !           773:        state = 2;
        !           774:        if (bus_dmamap_create(sc->sc_dmatag, LGE_JMEM, 1,
        !           775:                              LGE_JMEM, 0, BUS_DMA_NOWAIT, &dmamap)) {
        !           776:                printf("%s: can't create dma map\n", sc->sc_dv.dv_xname);
        !           777:                error = ENOBUFS;
        !           778:                goto out;
        !           779:        }
        !           780:
        !           781:        state = 3;
        !           782:        if (bus_dmamap_load(sc->sc_dmatag, dmamap, kva, LGE_JMEM,
        !           783:                            NULL, BUS_DMA_NOWAIT)) {
        !           784:                printf("%s: can't load dma map\n", sc->sc_dv.dv_xname);
        !           785:                error = ENOBUFS;
        !           786:                goto out;
        !           787:         }
        !           788:
        !           789:        state = 4;
        !           790:        sc->lge_cdata.lge_jumbo_buf = (caddr_t)kva;
        !           791:        DPRINTFN(1,("lge_jumbo_buf = 0x%08X\n", sc->lge_cdata.lge_jumbo_buf));
        !           792:        DPRINTFN(1,("LGE_JLEN = 0x%08X\n", LGE_JLEN));
        !           793:
        !           794:        LIST_INIT(&sc->lge_jfree_listhead);
        !           795:        LIST_INIT(&sc->lge_jinuse_listhead);
        !           796:
        !           797:        /*
        !           798:         * Now divide it up into 9K pieces and save the addresses
        !           799:         * in an array.
        !           800:         */
        !           801:        ptr = sc->lge_cdata.lge_jumbo_buf;
        !           802:        for (i = 0; i < LGE_JSLOTS; i++) {
        !           803:                sc->lge_cdata.lge_jslots[i] = ptr;
        !           804:                ptr += LGE_JLEN;
        !           805:                entry = malloc(sizeof(struct lge_jpool_entry),
        !           806:                    M_DEVBUF, M_NOWAIT);
        !           807:                if (entry == NULL) {
        !           808:                        sc->lge_cdata.lge_jumbo_buf = NULL;
        !           809:                        printf("%s: no memory for jumbo buffer queue!\n",
        !           810:                               sc->sc_dv.dv_xname);
        !           811:                        error = ENOBUFS;
        !           812:                        goto out;
        !           813:                }
        !           814:                entry->slot = i;
        !           815:                LIST_INSERT_HEAD(&sc->lge_jfree_listhead,
        !           816:                                 entry, jpool_entries);
        !           817:        }
        !           818: out:
        !           819:        if (error != 0) {
        !           820:                switch (state) {
        !           821:                case 4:
        !           822:                        bus_dmamap_unload(sc->sc_dmatag, dmamap);
        !           823:                case 3:
        !           824:                        bus_dmamap_destroy(sc->sc_dmatag, dmamap);
        !           825:                case 2:
        !           826:                        bus_dmamem_unmap(sc->sc_dmatag, kva, LGE_JMEM);
        !           827:                case 1:
        !           828:                        bus_dmamem_free(sc->sc_dmatag, &seg, rseg);
        !           829:                        break;
        !           830:                default:
        !           831:                        break;
        !           832:                }
        !           833:        }
        !           834:
        !           835:        return (error);
        !           836: }
        !           837:
        !           838: /*
        !           839:  * Allocate a jumbo buffer.
        !           840:  */
        !           841: void *
        !           842: lge_jalloc(struct lge_softc *sc)
        !           843: {
        !           844:        struct lge_jpool_entry   *entry;
        !           845:
        !           846:        entry = LIST_FIRST(&sc->lge_jfree_listhead);
        !           847:
        !           848:        if (entry == NULL)
        !           849:                return (NULL);
        !           850:
        !           851:        LIST_REMOVE(entry, jpool_entries);
        !           852:        LIST_INSERT_HEAD(&sc->lge_jinuse_listhead, entry, jpool_entries);
        !           853:        return (sc->lge_cdata.lge_jslots[entry->slot]);
        !           854: }
        !           855:
        !           856: /*
        !           857:  * Release a jumbo buffer.
        !           858:  */
        !           859: void
        !           860: lge_jfree(caddr_t buf, u_int size, void *arg)
        !           861: {
        !           862:        struct lge_softc        *sc;
        !           863:        int                     i;
        !           864:        struct lge_jpool_entry   *entry;
        !           865:
        !           866:        /* Extract the softc struct pointer. */
        !           867:        sc = (struct lge_softc *)arg;
        !           868:
        !           869:        if (sc == NULL)
        !           870:                panic("lge_jfree: can't find softc pointer!");
        !           871:
        !           872:        /* calculate the slot this buffer belongs to */
        !           873:        i = ((vaddr_t)buf - (vaddr_t)sc->lge_cdata.lge_jumbo_buf) / LGE_JLEN;
        !           874:
        !           875:        if ((i < 0) || (i >= LGE_JSLOTS))
        !           876:                panic("lge_jfree: asked to free buffer that we don't manage!");
        !           877:
        !           878:        entry = LIST_FIRST(&sc->lge_jinuse_listhead);
        !           879:        if (entry == NULL)
        !           880:                panic("lge_jfree: buffer not in use!");
        !           881:        entry->slot = i;
        !           882:        LIST_REMOVE(entry, jpool_entries);
        !           883:        LIST_INSERT_HEAD(&sc->lge_jfree_listhead, entry, jpool_entries);
        !           884: }
        !           885:
        !           886: /*
        !           887:  * A frame has been uploaded: pass the resulting mbuf chain up to
        !           888:  * the higher level protocols.
        !           889:  */
        !           890: void
        !           891: lge_rxeof(struct lge_softc *sc, int cnt)
        !           892: {
        !           893:         struct mbuf            *m;
        !           894:         struct ifnet           *ifp;
        !           895:        struct lge_rx_desc      *cur_rx;
        !           896:        int                     c, i, total_len = 0;
        !           897:        u_int32_t               rxsts, rxctl;
        !           898:
        !           899:        ifp = &sc->arpcom.ac_if;
        !           900:
        !           901:        /* Find out how many frames were processed. */
        !           902:        c = cnt;
        !           903:        i = sc->lge_cdata.lge_rx_cons;
        !           904:
        !           905:        /* Suck them in. */
        !           906:        while(c) {
        !           907:                struct mbuf             *m0 = NULL;
        !           908:
        !           909:                cur_rx = &sc->lge_ldata->lge_rx_list[i];
        !           910:                rxctl = cur_rx->lge_ctl;
        !           911:                rxsts = cur_rx->lge_sts;
        !           912:                m = cur_rx->lge_mbuf;
        !           913:                cur_rx->lge_mbuf = NULL;
        !           914:                total_len = LGE_RXBYTES(cur_rx);
        !           915:                LGE_INC(i, LGE_RX_LIST_CNT);
        !           916:                c--;
        !           917:
        !           918:                /*
        !           919:                 * If an error occurs, update stats, clear the
        !           920:                 * status word and leave the mbuf cluster in place:
        !           921:                 * it should simply get re-used next time this descriptor
        !           922:                 * comes up in the ring.
        !           923:                 */
        !           924:                if (rxctl & LGE_RXCTL_ERRMASK) {
        !           925:                        ifp->if_ierrors++;
        !           926:                        lge_newbuf(sc, &LGE_RXTAIL(sc), m);
        !           927:                        continue;
        !           928:                }
        !           929:
        !           930:                if (lge_newbuf(sc, &LGE_RXTAIL(sc), NULL) == ENOBUFS) {
        !           931:                        m0 = m_devget(mtod(m, char *), total_len, ETHER_ALIGN,
        !           932:                            ifp, NULL);
        !           933:                        lge_newbuf(sc, &LGE_RXTAIL(sc), m);
        !           934:                        if (m0 == NULL) {
        !           935:                                ifp->if_ierrors++;
        !           936:                                continue;
        !           937:                        }
        !           938:                        m = m0;
        !           939:                } else {
        !           940:                        m->m_pkthdr.rcvif = ifp;
        !           941:                        m->m_pkthdr.len = m->m_len = total_len;
        !           942:                }
        !           943:
        !           944:                ifp->if_ipackets++;
        !           945:
        !           946: #if NBPFILTER > 0
        !           947:                /*
        !           948:                 * Handle BPF listeners. Let the BPF user see the packet.
        !           949:                 */
        !           950:                if (ifp->if_bpf)
        !           951:                        bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
        !           952: #endif
        !           953:
        !           954:                /* Do IP checksum checking. */
        !           955:                if (rxsts & LGE_RXSTS_ISIP) {
        !           956:                        if (!(rxsts & LGE_RXSTS_IPCSUMERR))
        !           957:                                m->m_pkthdr.csum_flags |= M_IPV4_CSUM_IN_OK;
        !           958:                }
        !           959:                if (rxsts & LGE_RXSTS_ISTCP) {
        !           960:                        if (!(rxsts & LGE_RXSTS_TCPCSUMERR))
        !           961:                                m->m_pkthdr.csum_flags |= M_TCP_CSUM_IN_OK;
        !           962:                }
        !           963:                if (rxsts & LGE_RXSTS_ISUDP) {
        !           964:                        if (!(rxsts & LGE_RXSTS_UDPCSUMERR))
        !           965:                                m->m_pkthdr.csum_flags |= M_UDP_CSUM_IN_OK;
        !           966:                }
        !           967:
        !           968:                ether_input_mbuf(ifp, m);
        !           969:        }
        !           970:
        !           971:        sc->lge_cdata.lge_rx_cons = i;
        !           972: }
        !           973:
        !           974: /*
        !           975:  * A frame was downloaded to the chip. It's safe for us to clean up
        !           976:  * the list buffers.
        !           977:  */
        !           978:
        !           979: void
        !           980: lge_txeof(struct lge_softc *sc)
        !           981: {
        !           982:        struct lge_tx_desc      *cur_tx = NULL;
        !           983:        struct ifnet            *ifp;
        !           984:        u_int32_t               idx, txdone;
        !           985:
        !           986:        ifp = &sc->arpcom.ac_if;
        !           987:
        !           988:        /* Clear the timeout timer. */
        !           989:        ifp->if_timer = 0;
        !           990:
        !           991:        /*
        !           992:         * Go through our tx list and free mbufs for those
        !           993:         * frames that have been transmitted.
        !           994:         */
        !           995:        idx = sc->lge_cdata.lge_tx_cons;
        !           996:        txdone = CSR_READ_1(sc, LGE_TXDMADONE_8BIT);
        !           997:
        !           998:        while (idx != sc->lge_cdata.lge_tx_prod && txdone) {
        !           999:                cur_tx = &sc->lge_ldata->lge_tx_list[idx];
        !          1000:
        !          1001:                ifp->if_opackets++;
        !          1002:                if (cur_tx->lge_mbuf != NULL) {
        !          1003:                        m_freem(cur_tx->lge_mbuf);
        !          1004:                        cur_tx->lge_mbuf = NULL;
        !          1005:                }
        !          1006:                cur_tx->lge_ctl = 0;
        !          1007:
        !          1008:                txdone--;
        !          1009:                LGE_INC(idx, LGE_TX_LIST_CNT);
        !          1010:                ifp->if_timer = 0;
        !          1011:        }
        !          1012:
        !          1013:        sc->lge_cdata.lge_tx_cons = idx;
        !          1014:
        !          1015:        if (cur_tx != NULL)
        !          1016:                ifp->if_flags &= ~IFF_OACTIVE;
        !          1017: }
        !          1018:
        !          1019: void
        !          1020: lge_tick(void *xsc)
        !          1021: {
        !          1022:        struct lge_softc        *sc = xsc;
        !          1023:        struct mii_data         *mii = &sc->lge_mii;
        !          1024:        struct ifnet            *ifp = &sc->arpcom.ac_if;
        !          1025:        int                     s;
        !          1026:
        !          1027:        s = splnet();
        !          1028:
        !          1029:        CSR_WRITE_4(sc, LGE_STATSIDX, LGE_STATS_SINGLE_COLL_PKTS);
        !          1030:        ifp->if_collisions += CSR_READ_4(sc, LGE_STATSVAL);
        !          1031:        CSR_WRITE_4(sc, LGE_STATSIDX, LGE_STATS_MULTI_COLL_PKTS);
        !          1032:        ifp->if_collisions += CSR_READ_4(sc, LGE_STATSVAL);
        !          1033:
        !          1034:        if (!sc->lge_link) {
        !          1035:                mii_tick(mii);
        !          1036:                if (mii->mii_media_status & IFM_ACTIVE &&
        !          1037:                    IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) {
        !          1038:                        sc->lge_link++;
        !          1039:                        if (!IFQ_IS_EMPTY(&ifp->if_snd))
        !          1040:                                lge_start(ifp);
        !          1041:                }
        !          1042:        }
        !          1043:
        !          1044:        timeout_add(&sc->lge_timeout, hz);
        !          1045:
        !          1046:        splx(s);
        !          1047: }
        !          1048:
        !          1049: int
        !          1050: lge_intr(void *arg)
        !          1051: {
        !          1052:        struct lge_softc        *sc;
        !          1053:        struct ifnet            *ifp;
        !          1054:        u_int32_t               status;
        !          1055:        int                     claimed = 0;
        !          1056:
        !          1057:        sc = arg;
        !          1058:        ifp = &sc->arpcom.ac_if;
        !          1059:
        !          1060:        /* Supress unwanted interrupts */
        !          1061:        if (!(ifp->if_flags & IFF_UP)) {
        !          1062:                lge_stop(sc);
        !          1063:                return (0);
        !          1064:        }
        !          1065:
        !          1066:        for (;;) {
        !          1067:                /*
        !          1068:                 * Reading the ISR register clears all interrupts, and
        !          1069:                 * clears the 'interrupts enabled' bit in the IMR
        !          1070:                 * register.
        !          1071:                 */
        !          1072:                status = CSR_READ_4(sc, LGE_ISR);
        !          1073:
        !          1074:                if ((status & LGE_INTRS) == 0)
        !          1075:                        break;
        !          1076:
        !          1077:                claimed = 1;
        !          1078:
        !          1079:                if ((status & (LGE_ISR_TXCMDFIFO_EMPTY|LGE_ISR_TXDMA_DONE)))
        !          1080:                        lge_txeof(sc);
        !          1081:
        !          1082:                if (status & LGE_ISR_RXDMA_DONE)
        !          1083:                        lge_rxeof(sc, LGE_RX_DMACNT(status));
        !          1084:
        !          1085:                if (status & LGE_ISR_RXCMDFIFO_EMPTY)
        !          1086:                        lge_init(sc);
        !          1087:
        !          1088:                if (status & LGE_ISR_PHY_INTR) {
        !          1089:                        sc->lge_link = 0;
        !          1090:                        timeout_del(&sc->lge_timeout);
        !          1091:                        lge_tick(sc);
        !          1092:                }
        !          1093:        }
        !          1094:
        !          1095:        /* Re-enable interrupts. */
        !          1096:        CSR_WRITE_4(sc, LGE_IMR, LGE_IMR_SETRST_CTL0|LGE_IMR_INTR_ENB);
        !          1097:
        !          1098:        if (!IFQ_IS_EMPTY(&ifp->if_snd))
        !          1099:                lge_start(ifp);
        !          1100:
        !          1101:        return (claimed);
        !          1102: }
        !          1103:
        !          1104: /*
        !          1105:  * Encapsulate an mbuf chain in a descriptor by coupling the mbuf data
        !          1106:  * pointers to the fragment pointers.
        !          1107:  */
        !          1108: int
        !          1109: lge_encap(struct lge_softc *sc, struct mbuf *m_head, u_int32_t *txidx)
        !          1110: {
        !          1111:        struct lge_frag         *f = NULL;
        !          1112:        struct lge_tx_desc      *cur_tx;
        !          1113:        struct mbuf             *m;
        !          1114:        int                     frag = 0, tot_len = 0;
        !          1115:
        !          1116:        /*
        !          1117:         * Start packing the mbufs in this chain into
        !          1118:         * the fragment pointers. Stop when we run out
        !          1119:         * of fragments or hit the end of the mbuf chain.
        !          1120:         */
        !          1121:        m = m_head;
        !          1122:        cur_tx = &sc->lge_ldata->lge_tx_list[*txidx];
        !          1123:        frag = 0;
        !          1124:
        !          1125:        for (m = m_head; m != NULL; m = m->m_next) {
        !          1126:                if (m->m_len != 0) {
        !          1127:                        tot_len += m->m_len;
        !          1128:                        f = &cur_tx->lge_frags[frag];
        !          1129:                        f->lge_fraglen = m->m_len;
        !          1130:                        f->lge_fragptr_lo = VTOPHYS(mtod(m, vaddr_t));
        !          1131:                        f->lge_fragptr_hi = 0;
        !          1132:                        frag++;
        !          1133:                }
        !          1134:        }
        !          1135:
        !          1136:        if (m != NULL)
        !          1137:                return (ENOBUFS);
        !          1138:
        !          1139:        cur_tx->lge_mbuf = m_head;
        !          1140:        cur_tx->lge_ctl = LGE_TXCTL_WANTINTR|LGE_FRAGCNT(frag)|tot_len;
        !          1141:        LGE_INC((*txidx), LGE_TX_LIST_CNT);
        !          1142:
        !          1143:        /* Queue for transmit */
        !          1144:        CSR_WRITE_4(sc, LGE_TXDESC_ADDR_LO, VTOPHYS(cur_tx));
        !          1145:
        !          1146:        return (0);
        !          1147: }
        !          1148:
        !          1149: /*
        !          1150:  * Main transmit routine. To avoid having to do mbuf copies, we put pointers
        !          1151:  * to the mbuf data regions directly in the transmit lists. We also save a
        !          1152:  * copy of the pointers since the transmit list fragment pointers are
        !          1153:  * physical addresses.
        !          1154:  */
        !          1155:
        !          1156: void
        !          1157: lge_start(struct ifnet *ifp)
        !          1158: {
        !          1159:        struct lge_softc        *sc;
        !          1160:        struct mbuf             *m_head = NULL;
        !          1161:        u_int32_t               idx;
        !          1162:        int                     pkts = 0;
        !          1163:
        !          1164:        sc = ifp->if_softc;
        !          1165:
        !          1166:        if (!sc->lge_link)
        !          1167:                return;
        !          1168:
        !          1169:        idx = sc->lge_cdata.lge_tx_prod;
        !          1170:
        !          1171:        if (ifp->if_flags & IFF_OACTIVE)
        !          1172:                return;
        !          1173:
        !          1174:        while(sc->lge_ldata->lge_tx_list[idx].lge_mbuf == NULL) {
        !          1175:                if (CSR_READ_1(sc, LGE_TXCMDFREE_8BIT) == 0)
        !          1176:                        break;
        !          1177:
        !          1178:                IFQ_POLL(&ifp->if_snd, m_head);
        !          1179:                if (m_head == NULL)
        !          1180:                        break;
        !          1181:
        !          1182:                if (lge_encap(sc, m_head, &idx)) {
        !          1183:                        ifp->if_flags |= IFF_OACTIVE;
        !          1184:                        break;
        !          1185:                }
        !          1186:
        !          1187:                /* now we are committed to transmit the packet */
        !          1188:                IFQ_DEQUEUE(&ifp->if_snd, m_head);
        !          1189:                pkts++;
        !          1190:
        !          1191: #if NBPFILTER > 0
        !          1192:                /*
        !          1193:                 * If there's a BPF listener, bounce a copy of this frame
        !          1194:                 * to him.
        !          1195:                 */
        !          1196:                if (ifp->if_bpf)
        !          1197:                        bpf_mtap(ifp->if_bpf, m_head, BPF_DIRECTION_OUT);
        !          1198: #endif
        !          1199:        }
        !          1200:        if (pkts == 0)
        !          1201:                return;
        !          1202:
        !          1203:        sc->lge_cdata.lge_tx_prod = idx;
        !          1204:
        !          1205:        /*
        !          1206:         * Set a timeout in case the chip goes out to lunch.
        !          1207:         */
        !          1208:        ifp->if_timer = 5;
        !          1209: }
        !          1210:
        !          1211: void
        !          1212: lge_init(void *xsc)
        !          1213: {
        !          1214:        struct lge_softc        *sc = xsc;
        !          1215:        struct ifnet            *ifp = &sc->arpcom.ac_if;
        !          1216:        int                     s;
        !          1217:
        !          1218:        s = splnet();
        !          1219:
        !          1220:        /*
        !          1221:         * Cancel pending I/O and free all RX/TX buffers.
        !          1222:         */
        !          1223:        lge_stop(sc);
        !          1224:        lge_reset(sc);
        !          1225:
        !          1226:        /* Set MAC address */
        !          1227:        CSR_WRITE_4(sc, LGE_PAR0, *(u_int32_t *)(&sc->arpcom.ac_enaddr[0]));
        !          1228:        CSR_WRITE_4(sc, LGE_PAR1, *(u_int32_t *)(&sc->arpcom.ac_enaddr[4]));
        !          1229:
        !          1230:        /* Init circular RX list. */
        !          1231:        if (lge_list_rx_init(sc) == ENOBUFS) {
        !          1232:                printf("%s: initialization failed: no "
        !          1233:                       "memory for rx buffers\n", sc->sc_dv.dv_xname);
        !          1234:                lge_stop(sc);
        !          1235:                splx(s);
        !          1236:                return;
        !          1237:        }
        !          1238:
        !          1239:        /*
        !          1240:         * Init tx descriptors.
        !          1241:         */
        !          1242:        lge_list_tx_init(sc);
        !          1243:
        !          1244:        /* Set initial value for MODE1 register. */
        !          1245:        CSR_WRITE_4(sc, LGE_MODE1, LGE_MODE1_RX_UCAST|
        !          1246:            LGE_MODE1_TX_CRC|LGE_MODE1_TXPAD|
        !          1247:            LGE_MODE1_RX_FLOWCTL|LGE_MODE1_SETRST_CTL0|
        !          1248:            LGE_MODE1_SETRST_CTL1|LGE_MODE1_SETRST_CTL2);
        !          1249:
        !          1250:         /* If we want promiscuous mode, set the allframes bit. */
        !          1251:        if (ifp->if_flags & IFF_PROMISC) {
        !          1252:                CSR_WRITE_4(sc, LGE_MODE1,
        !          1253:                    LGE_MODE1_SETRST_CTL1|LGE_MODE1_RX_PROMISC);
        !          1254:        } else {
        !          1255:                CSR_WRITE_4(sc, LGE_MODE1, LGE_MODE1_RX_PROMISC);
        !          1256:        }
        !          1257:
        !          1258:        /*
        !          1259:         * Set the capture broadcast bit to capture broadcast frames.
        !          1260:         */
        !          1261:        if (ifp->if_flags & IFF_BROADCAST) {
        !          1262:                CSR_WRITE_4(sc, LGE_MODE1,
        !          1263:                    LGE_MODE1_SETRST_CTL1|LGE_MODE1_RX_BCAST);
        !          1264:        } else {
        !          1265:                CSR_WRITE_4(sc, LGE_MODE1, LGE_MODE1_RX_BCAST);
        !          1266:        }
        !          1267:
        !          1268:        /* Packet padding workaround? */
        !          1269:        CSR_WRITE_4(sc, LGE_MODE1, LGE_MODE1_SETRST_CTL1|LGE_MODE1_RMVPAD);
        !          1270:
        !          1271:        /* No error frames */
        !          1272:        CSR_WRITE_4(sc, LGE_MODE1, LGE_MODE1_RX_ERRPKTS);
        !          1273:
        !          1274:        /* Receive large frames */
        !          1275:        CSR_WRITE_4(sc, LGE_MODE1, LGE_MODE1_SETRST_CTL1|LGE_MODE1_RX_GIANTS);
        !          1276:
        !          1277:        /* Workaround: disable RX/TX flow control */
        !          1278:        CSR_WRITE_4(sc, LGE_MODE1, LGE_MODE1_TX_FLOWCTL);
        !          1279:        CSR_WRITE_4(sc, LGE_MODE1, LGE_MODE1_RX_FLOWCTL);
        !          1280:
        !          1281:        /* Make sure to strip CRC from received frames */
        !          1282:        CSR_WRITE_4(sc, LGE_MODE1, LGE_MODE1_RX_CRC);
        !          1283:
        !          1284:        /* Turn off magic packet mode */
        !          1285:        CSR_WRITE_4(sc, LGE_MODE1, LGE_MODE1_MPACK_ENB);
        !          1286:
        !          1287:        /* Turn off all VLAN stuff */
        !          1288:        CSR_WRITE_4(sc, LGE_MODE1, LGE_MODE1_VLAN_RX|LGE_MODE1_VLAN_TX|
        !          1289:            LGE_MODE1_VLAN_STRIP|LGE_MODE1_VLAN_INSERT);
        !          1290:
        !          1291:        /* Workarond: FIFO overflow */
        !          1292:        CSR_WRITE_2(sc, LGE_RXFIFO_HIWAT, 0x3FFF);
        !          1293:        CSR_WRITE_4(sc, LGE_IMR, LGE_IMR_SETRST_CTL1|LGE_IMR_RXFIFO_WAT);
        !          1294:
        !          1295:        /*
        !          1296:         * Load the multicast filter.
        !          1297:         */
        !          1298:        lge_setmulti(sc);
        !          1299:
        !          1300:        /*
        !          1301:         * Enable hardware checksum validation for all received IPv4
        !          1302:         * packets, do not reject packets with bad checksums.
        !          1303:         */
        !          1304:        CSR_WRITE_4(sc, LGE_MODE2, LGE_MODE2_RX_IPCSUM|
        !          1305:            LGE_MODE2_RX_TCPCSUM|LGE_MODE2_RX_UDPCSUM|
        !          1306:            LGE_MODE2_RX_ERRCSUM);
        !          1307:
        !          1308:        /*
        !          1309:         * Enable the delivery of PHY interrupts based on
        !          1310:         * link/speed/duplex status chalges.
        !          1311:         */
        !          1312:        CSR_WRITE_4(sc, LGE_MODE1, LGE_MODE1_SETRST_CTL0|LGE_MODE1_GMIIPOLL);
        !          1313:
        !          1314:        /* Enable receiver and transmitter. */
        !          1315:        CSR_WRITE_4(sc, LGE_RXDESC_ADDR_HI, 0);
        !          1316:        CSR_WRITE_4(sc, LGE_MODE1, LGE_MODE1_SETRST_CTL1|LGE_MODE1_RX_ENB);
        !          1317:
        !          1318:        CSR_WRITE_4(sc, LGE_TXDESC_ADDR_HI, 0);
        !          1319:        CSR_WRITE_4(sc, LGE_MODE1, LGE_MODE1_SETRST_CTL1|LGE_MODE1_TX_ENB);
        !          1320:
        !          1321:        /*
        !          1322:         * Enable interrupts.
        !          1323:         */
        !          1324:        CSR_WRITE_4(sc, LGE_IMR, LGE_IMR_SETRST_CTL0|
        !          1325:            LGE_IMR_SETRST_CTL1|LGE_IMR_INTR_ENB|LGE_INTRS);
        !          1326:
        !          1327:        lge_ifmedia_upd(ifp);
        !          1328:
        !          1329:        ifp->if_flags |= IFF_RUNNING;
        !          1330:        ifp->if_flags &= ~IFF_OACTIVE;
        !          1331:
        !          1332:        splx(s);
        !          1333:
        !          1334:        timeout_add(&sc->lge_timeout, hz);
        !          1335: }
        !          1336:
        !          1337: /*
        !          1338:  * Set media options.
        !          1339:  */
        !          1340: int
        !          1341: lge_ifmedia_upd(struct ifnet *ifp)
        !          1342: {
        !          1343:        struct lge_softc        *sc = ifp->if_softc;
        !          1344:        struct mii_data         *mii = &sc->lge_mii;
        !          1345:
        !          1346:        sc->lge_link = 0;
        !          1347:        if (mii->mii_instance) {
        !          1348:                struct mii_softc *miisc;
        !          1349:                LIST_FOREACH(miisc, &mii->mii_phys, mii_list)
        !          1350:                        mii_phy_reset(miisc);
        !          1351:        }
        !          1352:        mii_mediachg(mii);
        !          1353:
        !          1354:        return (0);
        !          1355: }
        !          1356:
        !          1357: /*
        !          1358:  * Report current media status.
        !          1359:  */
        !          1360: void
        !          1361: lge_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
        !          1362: {
        !          1363:        struct lge_softc        *sc = ifp->if_softc;
        !          1364:        struct mii_data         *mii = &sc->lge_mii;
        !          1365:
        !          1366:        mii_pollstat(mii);
        !          1367:        ifmr->ifm_active = mii->mii_media_active;
        !          1368:        ifmr->ifm_status = mii->mii_media_status;
        !          1369: }
        !          1370:
        !          1371: int
        !          1372: lge_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
        !          1373: {
        !          1374:        struct lge_softc        *sc = ifp->if_softc;
        !          1375:        struct ifreq            *ifr = (struct ifreq *) data;
        !          1376:        struct ifaddr           *ifa = (struct ifaddr *)data;
        !          1377:        struct mii_data         *mii;
        !          1378:        int                     s, error = 0;
        !          1379:
        !          1380:        s = splnet();
        !          1381:
        !          1382:        switch(command) {
        !          1383:        case SIOCSIFADDR:
        !          1384:                ifp->if_flags |= IFF_UP;
        !          1385:                if (!(ifp->if_flags & IFF_RUNNING))
        !          1386:                        lge_init(sc);
        !          1387: #ifdef INET
        !          1388:                if (ifa->ifa_addr->sa_family == AF_INET)
        !          1389:                        arp_ifinit(&sc->arpcom, ifa);
        !          1390: #endif /* INET */
        !          1391:                break;
        !          1392:        case SIOCSIFMTU:
        !          1393:                if (ifr->ifr_mtu < ETHERMIN || ifr->ifr_mtu > ifp->if_hardmtu)
        !          1394:                        error = EINVAL;
        !          1395:                else if (ifp->if_mtu != ifr->ifr_mtu)
        !          1396:                        ifp->if_mtu = ifr->ifr_mtu;
        !          1397:                break;
        !          1398:        case SIOCSIFFLAGS:
        !          1399:                if (ifp->if_flags & IFF_UP) {
        !          1400:                        if (ifp->if_flags & IFF_RUNNING &&
        !          1401:                            ifp->if_flags & IFF_PROMISC &&
        !          1402:                            !(sc->lge_if_flags & IFF_PROMISC)) {
        !          1403:                                CSR_WRITE_4(sc, LGE_MODE1,
        !          1404:                                    LGE_MODE1_SETRST_CTL1|
        !          1405:                                    LGE_MODE1_RX_PROMISC);
        !          1406:                                lge_setmulti(sc);
        !          1407:                        } else if (ifp->if_flags & IFF_RUNNING &&
        !          1408:                            !(ifp->if_flags & IFF_PROMISC) &&
        !          1409:                            sc->lge_if_flags & IFF_PROMISC) {
        !          1410:                                CSR_WRITE_4(sc, LGE_MODE1,
        !          1411:                                    LGE_MODE1_RX_PROMISC);
        !          1412:                                lge_setmulti(sc);
        !          1413:                        } else if (ifp->if_flags & IFF_RUNNING &&
        !          1414:                            (ifp->if_flags ^ sc->lge_if_flags) & IFF_ALLMULTI) {
        !          1415:                                lge_setmulti(sc);
        !          1416:                        } else {
        !          1417:                                if (!(ifp->if_flags & IFF_RUNNING))
        !          1418:                                        lge_init(sc);
        !          1419:                        }
        !          1420:                } else {
        !          1421:                        if (ifp->if_flags & IFF_RUNNING)
        !          1422:                                lge_stop(sc);
        !          1423:                }
        !          1424:                sc->lge_if_flags = ifp->if_flags;
        !          1425:                break;
        !          1426:        case SIOCADDMULTI:
        !          1427:        case SIOCDELMULTI:
        !          1428:                error = (command == SIOCADDMULTI)
        !          1429:                        ? ether_addmulti(ifr, &sc->arpcom)
        !          1430:                        : ether_delmulti(ifr, &sc->arpcom);
        !          1431:
        !          1432:                if (error == ENETRESET) {
        !          1433:                        if (ifp->if_flags & IFF_RUNNING)
        !          1434:                                lge_setmulti(sc);
        !          1435:                        error = 0;
        !          1436:                }
        !          1437:                break;
        !          1438:        case SIOCGIFMEDIA:
        !          1439:        case SIOCSIFMEDIA:
        !          1440:                mii = &sc->lge_mii;
        !          1441:                error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command);
        !          1442:                break;
        !          1443:        default:
        !          1444:                error = ENOTTY;
        !          1445:                break;
        !          1446:        }
        !          1447:
        !          1448:        splx(s);
        !          1449:
        !          1450:        return (error);
        !          1451: }
        !          1452:
        !          1453: void
        !          1454: lge_watchdog(struct ifnet *ifp)
        !          1455: {
        !          1456:        struct lge_softc        *sc;
        !          1457:
        !          1458:        sc = ifp->if_softc;
        !          1459:
        !          1460:        ifp->if_oerrors++;
        !          1461:        printf("%s: watchdog timeout\n", sc->sc_dv.dv_xname);
        !          1462:
        !          1463:        lge_stop(sc);
        !          1464:        lge_reset(sc);
        !          1465:        lge_init(sc);
        !          1466:
        !          1467:        if (!IFQ_IS_EMPTY(&ifp->if_snd))
        !          1468:                lge_start(ifp);
        !          1469: }
        !          1470:
        !          1471: /*
        !          1472:  * Stop the adapter and free any mbufs allocated to the
        !          1473:  * RX and TX lists.
        !          1474:  */
        !          1475: void
        !          1476: lge_stop(struct lge_softc *sc)
        !          1477: {
        !          1478:        int                     i;
        !          1479:        struct ifnet            *ifp;
        !          1480:
        !          1481:        ifp = &sc->arpcom.ac_if;
        !          1482:        ifp->if_timer = 0;
        !          1483:        timeout_del(&sc->lge_timeout);
        !          1484:
        !          1485:        ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
        !          1486:
        !          1487:        CSR_WRITE_4(sc, LGE_IMR, LGE_IMR_INTR_ENB);
        !          1488:
        !          1489:        /* Disable receiver and transmitter. */
        !          1490:        CSR_WRITE_4(sc, LGE_MODE1, LGE_MODE1_RX_ENB|LGE_MODE1_TX_ENB);
        !          1491:        sc->lge_link = 0;
        !          1492:
        !          1493:        /*
        !          1494:         * Free data in the RX lists.
        !          1495:         */
        !          1496:        for (i = 0; i < LGE_RX_LIST_CNT; i++) {
        !          1497:                if (sc->lge_ldata->lge_rx_list[i].lge_mbuf != NULL) {
        !          1498:                        m_freem(sc->lge_ldata->lge_rx_list[i].lge_mbuf);
        !          1499:                        sc->lge_ldata->lge_rx_list[i].lge_mbuf = NULL;
        !          1500:                }
        !          1501:        }
        !          1502:        bzero((char *)&sc->lge_ldata->lge_rx_list,
        !          1503:                sizeof(sc->lge_ldata->lge_rx_list));
        !          1504:
        !          1505:        /*
        !          1506:         * Free the TX list buffers.
        !          1507:         */
        !          1508:        for (i = 0; i < LGE_TX_LIST_CNT; i++) {
        !          1509:                if (sc->lge_ldata->lge_tx_list[i].lge_mbuf != NULL) {
        !          1510:                        m_freem(sc->lge_ldata->lge_tx_list[i].lge_mbuf);
        !          1511:                        sc->lge_ldata->lge_tx_list[i].lge_mbuf = NULL;
        !          1512:                }
        !          1513:        }
        !          1514:
        !          1515:        bzero((char *)&sc->lge_ldata->lge_tx_list,
        !          1516:                sizeof(sc->lge_ldata->lge_tx_list));
        !          1517: }
        !          1518:
        !          1519: /*
        !          1520:  * Stop all chip I/O so that the kernel's probe routines don't
        !          1521:  * get confused by errant DMAs when rebooting.
        !          1522:  */
        !          1523: void
        !          1524: lge_shutdown(void *xsc)
        !          1525: {
        !          1526:        struct lge_softc        *sc = (struct lge_softc *)xsc;
        !          1527:
        !          1528:        lge_reset(sc);
        !          1529:        lge_stop(sc);
        !          1530: }

CVSweb