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

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

1.1     ! nbrk        1: /*     $OpenBSD: if_nfe.c,v 1.69 2007/03/02 00:16:59 jsg Exp $ */
        !             2:
        !             3: /*-
        !             4:  * Copyright (c) 2006, 2007 Damien Bergamini <damien.bergamini@free.fr>
        !             5:  * Copyright (c) 2005, 2006 Jonathan Gray <jsg@openbsd.org>
        !             6:  *
        !             7:  * Permission to use, copy, modify, and distribute this software for any
        !             8:  * purpose with or without fee is hereby granted, provided that the above
        !             9:  * copyright notice and this permission notice appear in all copies.
        !            10:  *
        !            11:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
        !            12:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
        !            13:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
        !            14:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
        !            15:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
        !            16:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
        !            17:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
        !            18:  */
        !            19:
        !            20: /* Driver for NVIDIA nForce MCP Fast Ethernet and Gigabit Ethernet */
        !            21:
        !            22: #include "bpfilter.h"
        !            23: #include "vlan.h"
        !            24:
        !            25: #include <sys/param.h>
        !            26: #include <sys/endian.h>
        !            27: #include <sys/systm.h>
        !            28: #include <sys/types.h>
        !            29: #include <sys/sockio.h>
        !            30: #include <sys/mbuf.h>
        !            31: #include <sys/queue.h>
        !            32: #include <sys/malloc.h>
        !            33: #include <sys/kernel.h>
        !            34: #include <sys/device.h>
        !            35: #include <sys/timeout.h>
        !            36: #include <sys/socket.h>
        !            37:
        !            38: #include <machine/bus.h>
        !            39:
        !            40: #include <net/if.h>
        !            41: #include <net/if_dl.h>
        !            42: #include <net/if_media.h>
        !            43:
        !            44: #ifdef INET
        !            45: #include <netinet/in.h>
        !            46: #include <netinet/in_systm.h>
        !            47: #include <netinet/in_var.h>
        !            48: #include <netinet/ip.h>
        !            49: #include <netinet/if_ether.h>
        !            50: #endif
        !            51:
        !            52: #if NVLAN > 0
        !            53: #include <net/if_types.h>
        !            54: #include <net/if_vlan_var.h>
        !            55: #endif
        !            56:
        !            57: #if NBPFILTER > 0
        !            58: #include <net/bpf.h>
        !            59: #endif
        !            60:
        !            61: #include <dev/mii/mii.h>
        !            62: #include <dev/mii/miivar.h>
        !            63:
        !            64: #include <dev/pci/pcireg.h>
        !            65: #include <dev/pci/pcivar.h>
        !            66: #include <dev/pci/pcidevs.h>
        !            67:
        !            68: #include <dev/pci/if_nfereg.h>
        !            69: #include <dev/pci/if_nfevar.h>
        !            70:
        !            71: int    nfe_match(struct device *, void *, void *);
        !            72: void   nfe_attach(struct device *, struct device *, void *);
        !            73: void   nfe_power(int, void *);
        !            74: void   nfe_miibus_statchg(struct device *);
        !            75: int    nfe_miibus_readreg(struct device *, int, int);
        !            76: void   nfe_miibus_writereg(struct device *, int, int, int);
        !            77: int    nfe_intr(void *);
        !            78: int    nfe_ioctl(struct ifnet *, u_long, caddr_t);
        !            79: void   nfe_txdesc32_sync(struct nfe_softc *, struct nfe_desc32 *, int);
        !            80: void   nfe_txdesc64_sync(struct nfe_softc *, struct nfe_desc64 *, int);
        !            81: void   nfe_txdesc32_rsync(struct nfe_softc *, int, int, int);
        !            82: void   nfe_txdesc64_rsync(struct nfe_softc *, int, int, int);
        !            83: void   nfe_rxdesc32_sync(struct nfe_softc *, struct nfe_desc32 *, int);
        !            84: void   nfe_rxdesc64_sync(struct nfe_softc *, struct nfe_desc64 *, int);
        !            85: void   nfe_rxeof(struct nfe_softc *);
        !            86: void   nfe_txeof(struct nfe_softc *);
        !            87: int    nfe_encap(struct nfe_softc *, struct mbuf *);
        !            88: void   nfe_start(struct ifnet *);
        !            89: void   nfe_watchdog(struct ifnet *);
        !            90: int    nfe_init(struct ifnet *);
        !            91: void   nfe_stop(struct ifnet *, int);
        !            92: struct nfe_jbuf *nfe_jalloc(struct nfe_softc *);
        !            93: void   nfe_jfree(caddr_t, u_int, void *);
        !            94: int    nfe_jpool_alloc(struct nfe_softc *);
        !            95: void   nfe_jpool_free(struct nfe_softc *);
        !            96: int    nfe_alloc_rx_ring(struct nfe_softc *, struct nfe_rx_ring *);
        !            97: void   nfe_reset_rx_ring(struct nfe_softc *, struct nfe_rx_ring *);
        !            98: void   nfe_free_rx_ring(struct nfe_softc *, struct nfe_rx_ring *);
        !            99: int    nfe_alloc_tx_ring(struct nfe_softc *, struct nfe_tx_ring *);
        !           100: void   nfe_reset_tx_ring(struct nfe_softc *, struct nfe_tx_ring *);
        !           101: void   nfe_free_tx_ring(struct nfe_softc *, struct nfe_tx_ring *);
        !           102: int    nfe_ifmedia_upd(struct ifnet *);
        !           103: void   nfe_ifmedia_sts(struct ifnet *, struct ifmediareq *);
        !           104: void   nfe_setmulti(struct nfe_softc *);
        !           105: void   nfe_get_macaddr(struct nfe_softc *, uint8_t *);
        !           106: void   nfe_set_macaddr(struct nfe_softc *, const uint8_t *);
        !           107: void   nfe_tick(void *);
        !           108:
        !           109: struct cfattach nfe_ca = {
        !           110:        sizeof (struct nfe_softc), nfe_match, nfe_attach
        !           111: };
        !           112:
        !           113: struct cfdriver nfe_cd = {
        !           114:        NULL, "nfe", DV_IFNET
        !           115: };
        !           116:
        !           117: #ifdef NFE_DEBUG
        !           118: int nfedebug = 0;
        !           119: #define DPRINTF(x)     do { if (nfedebug) printf x; } while (0)
        !           120: #define DPRINTFN(n,x)  do { if (nfedebug >= (n)) printf x; } while (0)
        !           121: #else
        !           122: #define DPRINTF(x)
        !           123: #define DPRINTFN(n,x)
        !           124: #endif
        !           125:
        !           126: const struct pci_matchid nfe_devices[] = {
        !           127:        { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE_LAN },
        !           128:        { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE2_LAN },
        !           129:        { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE3_LAN1 },
        !           130:        { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE3_LAN2 },
        !           131:        { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE3_LAN3 },
        !           132:        { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE3_LAN4 },
        !           133:        { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE3_LAN5 },
        !           134:        { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_CK804_LAN1 },
        !           135:        { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_CK804_LAN2 },
        !           136:        { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP04_LAN1 },
        !           137:        { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP04_LAN2 },
        !           138:        { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP51_LAN1 },
        !           139:        { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP51_LAN2 },
        !           140:        { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP55_LAN1 },
        !           141:        { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP55_LAN2 },
        !           142:        { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP61_LAN1 },
        !           143:        { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP61_LAN2 },
        !           144:        { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP61_LAN3 },
        !           145:        { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP61_LAN4 },
        !           146:        { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP65_LAN1 },
        !           147:        { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP65_LAN2 },
        !           148:        { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP65_LAN3 },
        !           149:        { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP65_LAN4 },
        !           150:        { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP67_LAN1 },
        !           151:        { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP67_LAN2 },
        !           152:        { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP67_LAN3 },
        !           153:        { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP67_LAN4 }
        !           154: };
        !           155:
        !           156: int
        !           157: nfe_match(struct device *dev, void *match, void *aux)
        !           158: {
        !           159:        return pci_matchbyid((struct pci_attach_args *)aux, nfe_devices,
        !           160:            sizeof (nfe_devices) / sizeof (nfe_devices[0]));
        !           161: }
        !           162:
        !           163: void
        !           164: nfe_attach(struct device *parent, struct device *self, void *aux)
        !           165: {
        !           166:        struct nfe_softc *sc = (struct nfe_softc *)self;
        !           167:        struct pci_attach_args *pa = aux;
        !           168:        pci_chipset_tag_t pc = pa->pa_pc;
        !           169:        pci_intr_handle_t ih;
        !           170:        const char *intrstr;
        !           171:        struct ifnet *ifp;
        !           172:        bus_size_t memsize;
        !           173:        pcireg_t memtype;
        !           174:
        !           175:        memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, NFE_PCI_BA);
        !           176:        switch (memtype) {
        !           177:        case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT:
        !           178:        case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_64BIT:
        !           179:                if (pci_mapreg_map(pa, NFE_PCI_BA, memtype, 0, &sc->sc_memt,
        !           180:                    &sc->sc_memh, NULL, &memsize, 0) == 0)
        !           181:                        break;
        !           182:                /* FALLTHROUGH */
        !           183:        default:
        !           184:                printf(": could not map mem space\n");
        !           185:                return;
        !           186:        }
        !           187:
        !           188:        if (pci_intr_map(pa, &ih) != 0) {
        !           189:                printf(": could not map interrupt\n");
        !           190:                return;
        !           191:        }
        !           192:
        !           193:        intrstr = pci_intr_string(pc, ih);
        !           194:        sc->sc_ih = pci_intr_establish(pc, ih, IPL_NET, nfe_intr, sc,
        !           195:            sc->sc_dev.dv_xname);
        !           196:        if (sc->sc_ih == NULL) {
        !           197:                printf(": could not establish interrupt");
        !           198:                if (intrstr != NULL)
        !           199:                        printf(" at %s", intrstr);
        !           200:                printf("\n");
        !           201:                return;
        !           202:        }
        !           203:        printf(": %s", intrstr);
        !           204:
        !           205:        sc->sc_dmat = pa->pa_dmat;
        !           206:
        !           207:        nfe_get_macaddr(sc, sc->sc_arpcom.ac_enaddr);
        !           208:        printf(", address %s\n", ether_sprintf(sc->sc_arpcom.ac_enaddr));
        !           209:
        !           210:        sc->sc_flags = 0;
        !           211:
        !           212:        switch (PCI_PRODUCT(pa->pa_id)) {
        !           213:        case PCI_PRODUCT_NVIDIA_NFORCE3_LAN2:
        !           214:        case PCI_PRODUCT_NVIDIA_NFORCE3_LAN3:
        !           215:        case PCI_PRODUCT_NVIDIA_NFORCE3_LAN4:
        !           216:        case PCI_PRODUCT_NVIDIA_NFORCE3_LAN5:
        !           217:                sc->sc_flags |= NFE_JUMBO_SUP | NFE_HW_CSUM;
        !           218:                break;
        !           219:        case PCI_PRODUCT_NVIDIA_MCP51_LAN1:
        !           220:        case PCI_PRODUCT_NVIDIA_MCP51_LAN2:
        !           221:        case PCI_PRODUCT_NVIDIA_MCP61_LAN1:
        !           222:        case PCI_PRODUCT_NVIDIA_MCP61_LAN2:
        !           223:        case PCI_PRODUCT_NVIDIA_MCP61_LAN3:
        !           224:        case PCI_PRODUCT_NVIDIA_MCP61_LAN4:
        !           225:        case PCI_PRODUCT_NVIDIA_MCP67_LAN1:
        !           226:        case PCI_PRODUCT_NVIDIA_MCP67_LAN2:
        !           227:        case PCI_PRODUCT_NVIDIA_MCP67_LAN3:
        !           228:        case PCI_PRODUCT_NVIDIA_MCP67_LAN4:
        !           229:                sc->sc_flags |= NFE_40BIT_ADDR;
        !           230:                break;
        !           231:        case PCI_PRODUCT_NVIDIA_CK804_LAN1:
        !           232:        case PCI_PRODUCT_NVIDIA_CK804_LAN2:
        !           233:        case PCI_PRODUCT_NVIDIA_MCP04_LAN1:
        !           234:        case PCI_PRODUCT_NVIDIA_MCP04_LAN2:
        !           235:                sc->sc_flags |= NFE_JUMBO_SUP | NFE_40BIT_ADDR | NFE_HW_CSUM;
        !           236:                break;
        !           237:        case PCI_PRODUCT_NVIDIA_MCP65_LAN1:
        !           238:        case PCI_PRODUCT_NVIDIA_MCP65_LAN2:
        !           239:        case PCI_PRODUCT_NVIDIA_MCP65_LAN3:
        !           240:        case PCI_PRODUCT_NVIDIA_MCP65_LAN4:
        !           241:                sc->sc_flags |= NFE_JUMBO_SUP | NFE_40BIT_ADDR;
        !           242:                break;
        !           243:        case PCI_PRODUCT_NVIDIA_MCP55_LAN1:
        !           244:        case PCI_PRODUCT_NVIDIA_MCP55_LAN2:
        !           245:                sc->sc_flags |= NFE_JUMBO_SUP | NFE_40BIT_ADDR | NFE_HW_CSUM |
        !           246:                    NFE_HW_VLAN;
        !           247:                break;
        !           248:        }
        !           249:
        !           250:        /* enable jumbo frames for adapters that support it */
        !           251:        if (sc->sc_flags & NFE_JUMBO_SUP)
        !           252:                sc->sc_flags |= NFE_USE_JUMBO;
        !           253:
        !           254:        /*
        !           255:         * Allocate Tx and Rx rings.
        !           256:         */
        !           257:        if (nfe_alloc_tx_ring(sc, &sc->txq) != 0) {
        !           258:                printf("%s: could not allocate Tx ring\n",
        !           259:                    sc->sc_dev.dv_xname);
        !           260:                return;
        !           261:        }
        !           262:
        !           263:        if (nfe_alloc_rx_ring(sc, &sc->rxq) != 0) {
        !           264:                printf("%s: could not allocate Rx ring\n",
        !           265:                    sc->sc_dev.dv_xname);
        !           266:                nfe_free_tx_ring(sc, &sc->txq);
        !           267:                return;
        !           268:        }
        !           269:
        !           270:        ifp = &sc->sc_arpcom.ac_if;
        !           271:        ifp->if_softc = sc;
        !           272:        ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
        !           273:        ifp->if_ioctl = nfe_ioctl;
        !           274:        ifp->if_start = nfe_start;
        !           275:        ifp->if_watchdog = nfe_watchdog;
        !           276:        ifp->if_init = nfe_init;
        !           277:        ifp->if_baudrate = IF_Gbps(1);
        !           278:        IFQ_SET_MAXLEN(&ifp->if_snd, NFE_IFQ_MAXLEN);
        !           279:        IFQ_SET_READY(&ifp->if_snd);
        !           280:        strlcpy(ifp->if_xname, sc->sc_dev.dv_xname, IFNAMSIZ);
        !           281:
        !           282:        ifp->if_capabilities = IFCAP_VLAN_MTU;
        !           283:
        !           284:        if (sc->sc_flags & NFE_USE_JUMBO)
        !           285:                ifp->if_hardmtu = NFE_JUMBO_MTU;
        !           286:
        !           287: #if NVLAN > 0
        !           288:        if (sc->sc_flags & NFE_HW_VLAN)
        !           289:                ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING;
        !           290: #endif
        !           291:        if (sc->sc_flags & NFE_HW_CSUM) {
        !           292:                ifp->if_capabilities |= IFCAP_CSUM_IPv4 | IFCAP_CSUM_TCPv4 |
        !           293:                    IFCAP_CSUM_UDPv4;
        !           294:        }
        !           295:
        !           296:        sc->sc_mii.mii_ifp = ifp;
        !           297:        sc->sc_mii.mii_readreg = nfe_miibus_readreg;
        !           298:        sc->sc_mii.mii_writereg = nfe_miibus_writereg;
        !           299:        sc->sc_mii.mii_statchg = nfe_miibus_statchg;
        !           300:
        !           301:        ifmedia_init(&sc->sc_mii.mii_media, 0, nfe_ifmedia_upd,
        !           302:            nfe_ifmedia_sts);
        !           303:        mii_attach(self, &sc->sc_mii, 0xffffffff, MII_PHY_ANY,
        !           304:            MII_OFFSET_ANY, 0);
        !           305:        if (LIST_FIRST(&sc->sc_mii.mii_phys) == NULL) {
        !           306:                printf("%s: no PHY found!\n", sc->sc_dev.dv_xname);
        !           307:                ifmedia_add(&sc->sc_mii.mii_media, IFM_ETHER | IFM_MANUAL,
        !           308:                    0, NULL);
        !           309:                ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER | IFM_MANUAL);
        !           310:        } else
        !           311:                ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER | IFM_AUTO);
        !           312:
        !           313:        if_attach(ifp);
        !           314:        ether_ifattach(ifp);
        !           315:
        !           316:        timeout_set(&sc->sc_tick_ch, nfe_tick, sc);
        !           317:
        !           318:        sc->sc_powerhook = powerhook_establish(nfe_power, sc);
        !           319: }
        !           320:
        !           321: void
        !           322: nfe_power(int why, void *arg)
        !           323: {
        !           324:        struct nfe_softc *sc = arg;
        !           325:        struct ifnet *ifp;
        !           326:
        !           327:        if (why == PWR_RESUME) {
        !           328:                ifp = &sc->sc_arpcom.ac_if;
        !           329:                if (ifp->if_flags & IFF_UP) {
        !           330:                        nfe_init(ifp);
        !           331:                        if (ifp->if_flags & IFF_RUNNING)
        !           332:                                nfe_start(ifp);
        !           333:                }
        !           334:        }
        !           335: }
        !           336:
        !           337: void
        !           338: nfe_miibus_statchg(struct device *dev)
        !           339: {
        !           340:        struct nfe_softc *sc = (struct nfe_softc *)dev;
        !           341:        struct mii_data *mii = &sc->sc_mii;
        !           342:        uint32_t phy, seed, misc = NFE_MISC1_MAGIC, link = NFE_MEDIA_SET;
        !           343:
        !           344:        phy = NFE_READ(sc, NFE_PHY_IFACE);
        !           345:        phy &= ~(NFE_PHY_HDX | NFE_PHY_100TX | NFE_PHY_1000T);
        !           346:
        !           347:        seed = NFE_READ(sc, NFE_RNDSEED);
        !           348:        seed &= ~NFE_SEED_MASK;
        !           349:
        !           350:        if ((mii->mii_media_active & IFM_GMASK) == IFM_HDX) {
        !           351:                phy  |= NFE_PHY_HDX;    /* half-duplex */
        !           352:                misc |= NFE_MISC1_HDX;
        !           353:        }
        !           354:
        !           355:        switch (IFM_SUBTYPE(mii->mii_media_active)) {
        !           356:        case IFM_1000_T:        /* full-duplex only */
        !           357:                link |= NFE_MEDIA_1000T;
        !           358:                seed |= NFE_SEED_1000T;
        !           359:                phy  |= NFE_PHY_1000T;
        !           360:                break;
        !           361:        case IFM_100_TX:
        !           362:                link |= NFE_MEDIA_100TX;
        !           363:                seed |= NFE_SEED_100TX;
        !           364:                phy  |= NFE_PHY_100TX;
        !           365:                break;
        !           366:        case IFM_10_T:
        !           367:                link |= NFE_MEDIA_10T;
        !           368:                seed |= NFE_SEED_10T;
        !           369:                break;
        !           370:        }
        !           371:
        !           372:        NFE_WRITE(sc, NFE_RNDSEED, seed);       /* XXX: gigabit NICs only? */
        !           373:
        !           374:        NFE_WRITE(sc, NFE_PHY_IFACE, phy);
        !           375:        NFE_WRITE(sc, NFE_MISC1, misc);
        !           376:        NFE_WRITE(sc, NFE_LINKSPEED, link);
        !           377: }
        !           378:
        !           379: int
        !           380: nfe_miibus_readreg(struct device *dev, int phy, int reg)
        !           381: {
        !           382:        struct nfe_softc *sc = (struct nfe_softc *)dev;
        !           383:        uint32_t val;
        !           384:        int ntries;
        !           385:
        !           386:        NFE_WRITE(sc, NFE_PHY_STATUS, 0xf);
        !           387:
        !           388:        if (NFE_READ(sc, NFE_PHY_CTL) & NFE_PHY_BUSY) {
        !           389:                NFE_WRITE(sc, NFE_PHY_CTL, NFE_PHY_BUSY);
        !           390:                DELAY(100);
        !           391:        }
        !           392:
        !           393:        NFE_WRITE(sc, NFE_PHY_CTL, (phy << NFE_PHYADD_SHIFT) | reg);
        !           394:
        !           395:        for (ntries = 0; ntries < 1000; ntries++) {
        !           396:                DELAY(100);
        !           397:                if (!(NFE_READ(sc, NFE_PHY_CTL) & NFE_PHY_BUSY))
        !           398:                        break;
        !           399:        }
        !           400:        if (ntries == 1000) {
        !           401:                DPRINTFN(2, ("%s: timeout waiting for PHY\n",
        !           402:                    sc->sc_dev.dv_xname));
        !           403:                return 0;
        !           404:        }
        !           405:
        !           406:        if (NFE_READ(sc, NFE_PHY_STATUS) & NFE_PHY_ERROR) {
        !           407:                DPRINTFN(2, ("%s: could not read PHY\n",
        !           408:                    sc->sc_dev.dv_xname));
        !           409:                return 0;
        !           410:        }
        !           411:
        !           412:        val = NFE_READ(sc, NFE_PHY_DATA);
        !           413:        if (val != 0xffffffff && val != 0)
        !           414:                sc->mii_phyaddr = phy;
        !           415:
        !           416:        DPRINTFN(2, ("%s: mii read phy %d reg 0x%x ret 0x%x\n",
        !           417:            sc->sc_dev.dv_xname, phy, reg, val));
        !           418:
        !           419:        return val;
        !           420: }
        !           421:
        !           422: void
        !           423: nfe_miibus_writereg(struct device *dev, int phy, int reg, int val)
        !           424: {
        !           425:        struct nfe_softc *sc = (struct nfe_softc *)dev;
        !           426:        uint32_t ctl;
        !           427:        int ntries;
        !           428:
        !           429:        NFE_WRITE(sc, NFE_PHY_STATUS, 0xf);
        !           430:
        !           431:        if (NFE_READ(sc, NFE_PHY_CTL) & NFE_PHY_BUSY) {
        !           432:                NFE_WRITE(sc, NFE_PHY_CTL, NFE_PHY_BUSY);
        !           433:                DELAY(100);
        !           434:        }
        !           435:
        !           436:        NFE_WRITE(sc, NFE_PHY_DATA, val);
        !           437:        ctl = NFE_PHY_WRITE | (phy << NFE_PHYADD_SHIFT) | reg;
        !           438:        NFE_WRITE(sc, NFE_PHY_CTL, ctl);
        !           439:
        !           440:        for (ntries = 0; ntries < 1000; ntries++) {
        !           441:                DELAY(100);
        !           442:                if (!(NFE_READ(sc, NFE_PHY_CTL) & NFE_PHY_BUSY))
        !           443:                        break;
        !           444:        }
        !           445: #ifdef NFE_DEBUG
        !           446:        if (nfedebug >= 2 && ntries == 1000)
        !           447:                printf("could not write to PHY\n");
        !           448: #endif
        !           449: }
        !           450:
        !           451: int
        !           452: nfe_intr(void *arg)
        !           453: {
        !           454:        struct nfe_softc *sc = arg;
        !           455:        struct ifnet *ifp = &sc->sc_arpcom.ac_if;
        !           456:        uint32_t r;
        !           457:
        !           458:        if ((r = NFE_READ(sc, NFE_IRQ_STATUS)) == 0)
        !           459:                return 0;       /* not for us */
        !           460:        NFE_WRITE(sc, NFE_IRQ_STATUS, r);
        !           461:
        !           462:        DPRINTFN(5, ("nfe_intr: interrupt register %x\n", r));
        !           463:
        !           464:        if (r & NFE_IRQ_LINK) {
        !           465:                NFE_READ(sc, NFE_PHY_STATUS);
        !           466:                NFE_WRITE(sc, NFE_PHY_STATUS, 0xf);
        !           467:                DPRINTF(("%s: link state changed\n", sc->sc_dev.dv_xname));
        !           468:        }
        !           469:
        !           470:        if (ifp->if_flags & IFF_RUNNING) {
        !           471:                /* check Rx ring */
        !           472:                nfe_rxeof(sc);
        !           473:
        !           474:                /* check Tx ring */
        !           475:                nfe_txeof(sc);
        !           476:        }
        !           477:
        !           478:        return 1;
        !           479: }
        !           480:
        !           481: int
        !           482: nfe_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
        !           483: {
        !           484:        struct nfe_softc *sc = ifp->if_softc;
        !           485:        struct ifreq *ifr = (struct ifreq *)data;
        !           486:        struct ifaddr *ifa = (struct ifaddr *)data;
        !           487:        int s, error = 0;
        !           488:
        !           489:        s = splnet();
        !           490:
        !           491:        if ((error = ether_ioctl(ifp, &sc->sc_arpcom, cmd, data)) > 0) {
        !           492:                splx(s);
        !           493:                return error;
        !           494:        }
        !           495:
        !           496:        switch (cmd) {
        !           497:        case SIOCSIFADDR:
        !           498:                ifp->if_flags |= IFF_UP;
        !           499:                if (!(ifp->if_flags & IFF_RUNNING))
        !           500:                        nfe_init(ifp);
        !           501: #ifdef INET
        !           502:                if (ifa->ifa_addr->sa_family == AF_INET)
        !           503:                        arp_ifinit(&sc->sc_arpcom, ifa);
        !           504: #endif
        !           505:                break;
        !           506:        case SIOCSIFMTU:
        !           507:                if (ifr->ifr_mtu < ETHERMIN || ifr->ifr_mtu > ifp->if_hardmtu)
        !           508:                        error = EINVAL;
        !           509:                else if (ifp->if_mtu != ifr->ifr_mtu)
        !           510:                        ifp->if_mtu = ifr->ifr_mtu;
        !           511:                break;
        !           512:        case SIOCSIFFLAGS:
        !           513:                if (ifp->if_flags & IFF_UP) {
        !           514:                        /*
        !           515:                         * If only the PROMISC or ALLMULTI flag changes, then
        !           516:                         * don't do a full re-init of the chip, just update
        !           517:                         * the Rx filter.
        !           518:                         */
        !           519:                        if ((ifp->if_flags & IFF_RUNNING) &&
        !           520:                            ((ifp->if_flags ^ sc->sc_if_flags) &
        !           521:                             (IFF_ALLMULTI | IFF_PROMISC)) != 0) {
        !           522:                                nfe_setmulti(sc);
        !           523:                        } else {
        !           524:                                if (!(ifp->if_flags & IFF_RUNNING))
        !           525:                                        nfe_init(ifp);
        !           526:                        }
        !           527:                } else {
        !           528:                        if (ifp->if_flags & IFF_RUNNING)
        !           529:                                nfe_stop(ifp, 1);
        !           530:                }
        !           531:                sc->sc_if_flags = ifp->if_flags;
        !           532:                break;
        !           533:        case SIOCADDMULTI:
        !           534:        case SIOCDELMULTI:
        !           535:                error = (cmd == SIOCADDMULTI) ?
        !           536:                    ether_addmulti(ifr, &sc->sc_arpcom) :
        !           537:                    ether_delmulti(ifr, &sc->sc_arpcom);
        !           538:
        !           539:                if (error == ENETRESET) {
        !           540:                        if (ifp->if_flags & IFF_RUNNING)
        !           541:                                nfe_setmulti(sc);
        !           542:                        error = 0;
        !           543:                }
        !           544:                break;
        !           545:        case SIOCSIFMEDIA:
        !           546:        case SIOCGIFMEDIA:
        !           547:                error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii.mii_media, cmd);
        !           548:                break;
        !           549:        default:
        !           550:                error = ENOTTY;
        !           551:        }
        !           552:
        !           553:        splx(s);
        !           554:
        !           555:        return error;
        !           556: }
        !           557:
        !           558: void
        !           559: nfe_txdesc32_sync(struct nfe_softc *sc, struct nfe_desc32 *desc32, int ops)
        !           560: {
        !           561:        bus_dmamap_sync(sc->sc_dmat, sc->txq.map,
        !           562:            (caddr_t)desc32 - (caddr_t)sc->txq.desc32,
        !           563:            sizeof (struct nfe_desc32), ops);
        !           564: }
        !           565:
        !           566: void
        !           567: nfe_txdesc64_sync(struct nfe_softc *sc, struct nfe_desc64 *desc64, int ops)
        !           568: {
        !           569:        bus_dmamap_sync(sc->sc_dmat, sc->txq.map,
        !           570:            (caddr_t)desc64 - (caddr_t)sc->txq.desc64,
        !           571:            sizeof (struct nfe_desc64), ops);
        !           572: }
        !           573:
        !           574: void
        !           575: nfe_txdesc32_rsync(struct nfe_softc *sc, int start, int end, int ops)
        !           576: {
        !           577:        if (end > start) {
        !           578:                bus_dmamap_sync(sc->sc_dmat, sc->txq.map,
        !           579:                    (caddr_t)&sc->txq.desc32[start] - (caddr_t)sc->txq.desc32,
        !           580:                    (caddr_t)&sc->txq.desc32[end] -
        !           581:                    (caddr_t)&sc->txq.desc32[start], ops);
        !           582:                return;
        !           583:        }
        !           584:        /* sync from 'start' to end of ring */
        !           585:        bus_dmamap_sync(sc->sc_dmat, sc->txq.map,
        !           586:            (caddr_t)&sc->txq.desc32[start] - (caddr_t)sc->txq.desc32,
        !           587:            (caddr_t)&sc->txq.desc32[NFE_TX_RING_COUNT] -
        !           588:            (caddr_t)&sc->txq.desc32[start], ops);
        !           589:
        !           590:        /* sync from start of ring to 'end' */
        !           591:        bus_dmamap_sync(sc->sc_dmat, sc->txq.map, 0,
        !           592:            (caddr_t)&sc->txq.desc32[end] - (caddr_t)sc->txq.desc32, ops);
        !           593: }
        !           594:
        !           595: void
        !           596: nfe_txdesc64_rsync(struct nfe_softc *sc, int start, int end, int ops)
        !           597: {
        !           598:        if (end > start) {
        !           599:                bus_dmamap_sync(sc->sc_dmat, sc->txq.map,
        !           600:                    (caddr_t)&sc->txq.desc64[start] - (caddr_t)sc->txq.desc64,
        !           601:                    (caddr_t)&sc->txq.desc64[end] -
        !           602:                    (caddr_t)&sc->txq.desc64[start], ops);
        !           603:                return;
        !           604:        }
        !           605:        /* sync from 'start' to end of ring */
        !           606:        bus_dmamap_sync(sc->sc_dmat, sc->txq.map,
        !           607:            (caddr_t)&sc->txq.desc64[start] - (caddr_t)sc->txq.desc64,
        !           608:            (caddr_t)&sc->txq.desc64[NFE_TX_RING_COUNT] -
        !           609:            (caddr_t)&sc->txq.desc64[start], ops);
        !           610:
        !           611:        /* sync from start of ring to 'end' */
        !           612:        bus_dmamap_sync(sc->sc_dmat, sc->txq.map, 0,
        !           613:            (caddr_t)&sc->txq.desc64[end] - (caddr_t)sc->txq.desc64, ops);
        !           614: }
        !           615:
        !           616: void
        !           617: nfe_rxdesc32_sync(struct nfe_softc *sc, struct nfe_desc32 *desc32, int ops)
        !           618: {
        !           619:        bus_dmamap_sync(sc->sc_dmat, sc->rxq.map,
        !           620:            (caddr_t)desc32 - (caddr_t)sc->rxq.desc32,
        !           621:            sizeof (struct nfe_desc32), ops);
        !           622: }
        !           623:
        !           624: void
        !           625: nfe_rxdesc64_sync(struct nfe_softc *sc, struct nfe_desc64 *desc64, int ops)
        !           626: {
        !           627:        bus_dmamap_sync(sc->sc_dmat, sc->rxq.map,
        !           628:            (caddr_t)desc64 - (caddr_t)sc->rxq.desc64,
        !           629:            sizeof (struct nfe_desc64), ops);
        !           630: }
        !           631:
        !           632: void
        !           633: nfe_rxeof(struct nfe_softc *sc)
        !           634: {
        !           635:        struct ifnet *ifp = &sc->sc_arpcom.ac_if;
        !           636:        struct nfe_desc32 *desc32;
        !           637:        struct nfe_desc64 *desc64;
        !           638:        struct nfe_rx_data *data;
        !           639:        struct nfe_jbuf *jbuf;
        !           640:        struct mbuf *m, *mnew;
        !           641:        bus_addr_t physaddr;
        !           642:        uint16_t flags;
        !           643:        int error, len;
        !           644:
        !           645:        for (;;) {
        !           646:                data = &sc->rxq.data[sc->rxq.cur];
        !           647:
        !           648:                if (sc->sc_flags & NFE_40BIT_ADDR) {
        !           649:                        desc64 = &sc->rxq.desc64[sc->rxq.cur];
        !           650:                        nfe_rxdesc64_sync(sc, desc64, BUS_DMASYNC_POSTREAD);
        !           651:
        !           652:                        flags = letoh16(desc64->flags);
        !           653:                        len = letoh16(desc64->length) & 0x3fff;
        !           654:                } else {
        !           655:                        desc32 = &sc->rxq.desc32[sc->rxq.cur];
        !           656:                        nfe_rxdesc32_sync(sc, desc32, BUS_DMASYNC_POSTREAD);
        !           657:
        !           658:                        flags = letoh16(desc32->flags);
        !           659:                        len = letoh16(desc32->length) & 0x3fff;
        !           660:                }
        !           661:
        !           662:                if (flags & NFE_RX_READY)
        !           663:                        break;
        !           664:
        !           665:                if ((sc->sc_flags & (NFE_JUMBO_SUP | NFE_40BIT_ADDR)) == 0) {
        !           666:                        if (!(flags & NFE_RX_VALID_V1))
        !           667:                                goto skip;
        !           668:
        !           669:                        if ((flags & NFE_RX_FIXME_V1) == NFE_RX_FIXME_V1) {
        !           670:                                flags &= ~NFE_RX_ERROR;
        !           671:                                len--;  /* fix buffer length */
        !           672:                        }
        !           673:                } else {
        !           674:                        if (!(flags & NFE_RX_VALID_V2))
        !           675:                                goto skip;
        !           676:
        !           677:                        if ((flags & NFE_RX_FIXME_V2) == NFE_RX_FIXME_V2) {
        !           678:                                flags &= ~NFE_RX_ERROR;
        !           679:                                len--;  /* fix buffer length */
        !           680:                        }
        !           681:                }
        !           682:
        !           683:                if (flags & NFE_RX_ERROR) {
        !           684:                        ifp->if_ierrors++;
        !           685:                        goto skip;
        !           686:                }
        !           687:
        !           688:                /*
        !           689:                 * Try to allocate a new mbuf for this ring element and load
        !           690:                 * it before processing the current mbuf. If the ring element
        !           691:                 * cannot be loaded, drop the received packet and reuse the
        !           692:                 * old mbuf. In the unlikely case that the old mbuf can't be
        !           693:                 * reloaded either, explicitly panic.
        !           694:                 */
        !           695:                MGETHDR(mnew, M_DONTWAIT, MT_DATA);
        !           696:                if (mnew == NULL) {
        !           697:                        ifp->if_ierrors++;
        !           698:                        goto skip;
        !           699:                }
        !           700:
        !           701:                if (sc->sc_flags & NFE_USE_JUMBO) {
        !           702:                        if ((jbuf = nfe_jalloc(sc)) == NULL) {
        !           703:                                m_freem(mnew);
        !           704:                                ifp->if_ierrors++;
        !           705:                                goto skip;
        !           706:                        }
        !           707:                        MEXTADD(mnew, jbuf->buf, NFE_JBYTES, 0, nfe_jfree, sc);
        !           708:
        !           709:                        bus_dmamap_sync(sc->sc_dmat, sc->rxq.jmap,
        !           710:                            mtod(data->m, caddr_t) - sc->rxq.jpool, NFE_JBYTES,
        !           711:                            BUS_DMASYNC_POSTREAD);
        !           712:
        !           713:                        physaddr = jbuf->physaddr;
        !           714:                } else {
        !           715:                        MCLGET(mnew, M_DONTWAIT);
        !           716:                        if (!(mnew->m_flags & M_EXT)) {
        !           717:                                m_freem(mnew);
        !           718:                                ifp->if_ierrors++;
        !           719:                                goto skip;
        !           720:                        }
        !           721:
        !           722:                        bus_dmamap_sync(sc->sc_dmat, data->map, 0,
        !           723:                            data->map->dm_mapsize, BUS_DMASYNC_POSTREAD);
        !           724:                        bus_dmamap_unload(sc->sc_dmat, data->map);
        !           725:
        !           726:                        error = bus_dmamap_load(sc->sc_dmat, data->map,
        !           727:                            mtod(mnew, void *), MCLBYTES, NULL,
        !           728:                            BUS_DMA_READ | BUS_DMA_NOWAIT);
        !           729:                        if (error != 0) {
        !           730:                                m_freem(mnew);
        !           731:
        !           732:                                /* try to reload the old mbuf */
        !           733:                                error = bus_dmamap_load(sc->sc_dmat, data->map,
        !           734:                                    mtod(data->m, void *), MCLBYTES, NULL,
        !           735:                                    BUS_DMA_READ | BUS_DMA_NOWAIT);
        !           736:                                if (error != 0) {
        !           737:                                        /* very unlikely that it will fail.. */
        !           738:                                        panic("%s: could not load old rx mbuf",
        !           739:                                            sc->sc_dev.dv_xname);
        !           740:                                }
        !           741:                                ifp->if_ierrors++;
        !           742:                                goto skip;
        !           743:                        }
        !           744:                        physaddr = data->map->dm_segs[0].ds_addr;
        !           745:                }
        !           746:
        !           747:                /*
        !           748:                 * New mbuf successfully loaded, update Rx ring and continue
        !           749:                 * processing.
        !           750:                 */
        !           751:                m = data->m;
        !           752:                data->m = mnew;
        !           753:
        !           754:                /* finalize mbuf */
        !           755:                m->m_pkthdr.len = m->m_len = len;
        !           756:                m->m_pkthdr.rcvif = ifp;
        !           757:
        !           758:                if ((sc->sc_flags & NFE_HW_CSUM) &&
        !           759:                    (flags & NFE_RX_IP_CSUMOK)) {
        !           760:                        m->m_pkthdr.csum_flags |= M_IPV4_CSUM_IN_OK;
        !           761:                        if (flags & NFE_RX_UDP_CSUMOK)
        !           762:                                m->m_pkthdr.csum_flags |= M_UDP_CSUM_IN_OK;
        !           763:                        if (flags & NFE_RX_TCP_CSUMOK)
        !           764:                                m->m_pkthdr.csum_flags |= M_TCP_CSUM_IN_OK;
        !           765:                }
        !           766:
        !           767: #if NBPFILTER > 0
        !           768:                if (ifp->if_bpf)
        !           769:                        bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
        !           770: #endif
        !           771:                ifp->if_ipackets++;
        !           772:                ether_input_mbuf(ifp, m);
        !           773:
        !           774:                /* update mapping address in h/w descriptor */
        !           775:                if (sc->sc_flags & NFE_40BIT_ADDR) {
        !           776: #if defined(__LP64__)
        !           777:                        desc64->physaddr[0] = htole32(physaddr >> 32);
        !           778: #endif
        !           779:                        desc64->physaddr[1] = htole32(physaddr & 0xffffffff);
        !           780:                } else {
        !           781:                        desc32->physaddr = htole32(physaddr);
        !           782:                }
        !           783:
        !           784: skip:          if (sc->sc_flags & NFE_40BIT_ADDR) {
        !           785:                        desc64->length = htole16(sc->rxq.bufsz);
        !           786:                        desc64->flags = htole16(NFE_RX_READY);
        !           787:
        !           788:                        nfe_rxdesc64_sync(sc, desc64, BUS_DMASYNC_PREWRITE);
        !           789:                } else {
        !           790:                        desc32->length = htole16(sc->rxq.bufsz);
        !           791:                        desc32->flags = htole16(NFE_RX_READY);
        !           792:
        !           793:                        nfe_rxdesc32_sync(sc, desc32, BUS_DMASYNC_PREWRITE);
        !           794:                }
        !           795:
        !           796:                sc->rxq.cur = (sc->rxq.cur + 1) % NFE_RX_RING_COUNT;
        !           797:        }
        !           798: }
        !           799:
        !           800: void
        !           801: nfe_txeof(struct nfe_softc *sc)
        !           802: {
        !           803:        struct ifnet *ifp = &sc->sc_arpcom.ac_if;
        !           804:        struct nfe_desc32 *desc32;
        !           805:        struct nfe_desc64 *desc64;
        !           806:        struct nfe_tx_data *data = NULL;
        !           807:        uint16_t flags;
        !           808:
        !           809:        while (sc->txq.next != sc->txq.cur) {
        !           810:                if (sc->sc_flags & NFE_40BIT_ADDR) {
        !           811:                        desc64 = &sc->txq.desc64[sc->txq.next];
        !           812:                        nfe_txdesc64_sync(sc, desc64, BUS_DMASYNC_POSTREAD);
        !           813:
        !           814:                        flags = letoh16(desc64->flags);
        !           815:                } else {
        !           816:                        desc32 = &sc->txq.desc32[sc->txq.next];
        !           817:                        nfe_txdesc32_sync(sc, desc32, BUS_DMASYNC_POSTREAD);
        !           818:
        !           819:                        flags = letoh16(desc32->flags);
        !           820:                }
        !           821:
        !           822:                if (flags & NFE_TX_VALID)
        !           823:                        break;
        !           824:
        !           825:                data = &sc->txq.data[sc->txq.next];
        !           826:
        !           827:                if ((sc->sc_flags & (NFE_JUMBO_SUP | NFE_40BIT_ADDR)) == 0) {
        !           828:                        if (!(flags & NFE_TX_LASTFRAG_V1) && data->m == NULL)
        !           829:                                goto skip;
        !           830:
        !           831:                        if ((flags & NFE_TX_ERROR_V1) != 0) {
        !           832:                                printf("%s: tx v1 error 0x%04b\n",
        !           833:                                    sc->sc_dev.dv_xname, flags, NFE_V1_TXERR);
        !           834:                                ifp->if_oerrors++;
        !           835:                        } else
        !           836:                                ifp->if_opackets++;
        !           837:                } else {
        !           838:                        if (!(flags & NFE_TX_LASTFRAG_V2) && data->m == NULL)
        !           839:                                goto skip;
        !           840:
        !           841:                        if ((flags & NFE_TX_ERROR_V2) != 0) {
        !           842:                                printf("%s: tx v2 error 0x%04b\n",
        !           843:                                    sc->sc_dev.dv_xname, flags, NFE_V2_TXERR);
        !           844:                                ifp->if_oerrors++;
        !           845:                        } else
        !           846:                                ifp->if_opackets++;
        !           847:                }
        !           848:
        !           849:                if (data->m == NULL) {  /* should not get there */
        !           850:                        printf("%s: last fragment bit w/o associated mbuf!\n",
        !           851:                            sc->sc_dev.dv_xname);
        !           852:                        goto skip;
        !           853:                }
        !           854:
        !           855:                /* last fragment of the mbuf chain transmitted */
        !           856:                bus_dmamap_sync(sc->sc_dmat, data->active, 0,
        !           857:                    data->active->dm_mapsize, BUS_DMASYNC_POSTWRITE);
        !           858:                bus_dmamap_unload(sc->sc_dmat, data->active);
        !           859:                m_freem(data->m);
        !           860:                data->m = NULL;
        !           861:
        !           862:                ifp->if_timer = 0;
        !           863:
        !           864: skip:          sc->txq.queued--;
        !           865:                sc->txq.next = (sc->txq.next + 1) % NFE_TX_RING_COUNT;
        !           866:        }
        !           867:
        !           868:        if (data != NULL) {     /* at least one slot freed */
        !           869:                ifp->if_flags &= ~IFF_OACTIVE;
        !           870:                nfe_start(ifp);
        !           871:        }
        !           872: }
        !           873:
        !           874: int
        !           875: nfe_encap(struct nfe_softc *sc, struct mbuf *m0)
        !           876: {
        !           877:        struct nfe_desc32 *desc32;
        !           878:        struct nfe_desc64 *desc64;
        !           879:        struct nfe_tx_data *data;
        !           880:        bus_dmamap_t map;
        !           881:        uint16_t flags = 0;
        !           882: #if NVLAN > 0
        !           883:        uint32_t vtag = 0;
        !           884: #endif
        !           885:        int error, i, first = sc->txq.cur;
        !           886:
        !           887:        map = sc->txq.data[first].map;
        !           888:
        !           889:        error = bus_dmamap_load_mbuf(sc->sc_dmat, map, m0, BUS_DMA_NOWAIT);
        !           890:        if (error != 0) {
        !           891:                printf("%s: could not map mbuf (error %d)\n",
        !           892:                    sc->sc_dev.dv_xname, error);
        !           893:                return error;
        !           894:        }
        !           895:
        !           896:        if (sc->txq.queued + map->dm_nsegs >= NFE_TX_RING_COUNT - 1) {
        !           897:                bus_dmamap_unload(sc->sc_dmat, map);
        !           898:                return ENOBUFS;
        !           899:        }
        !           900:
        !           901: #if NVLAN > 0
        !           902:        /* setup h/w VLAN tagging */
        !           903:        if ((m0->m_flags & (M_PROTO1 | M_PKTHDR)) == (M_PROTO1 | M_PKTHDR) &&
        !           904:            m0->m_pkthdr.rcvif != NULL) {
        !           905:                struct ifvlan *ifv = m0->m_pkthdr.rcvif->if_softc;
        !           906:                vtag = NFE_TX_VTAG | htons(ifv->ifv_tag);
        !           907:        }
        !           908: #endif
        !           909:        if (m0->m_pkthdr.csum_flags & M_IPV4_CSUM_OUT)
        !           910:                flags |= NFE_TX_IP_CSUM;
        !           911:        if (m0->m_pkthdr.csum_flags & (M_TCPV4_CSUM_OUT | M_UDPV4_CSUM_OUT))
        !           912:                flags |= NFE_TX_TCP_UDP_CSUM;
        !           913:
        !           914:        for (i = 0; i < map->dm_nsegs; i++) {
        !           915:                data = &sc->txq.data[sc->txq.cur];
        !           916:
        !           917:                if (sc->sc_flags & NFE_40BIT_ADDR) {
        !           918:                        desc64 = &sc->txq.desc64[sc->txq.cur];
        !           919: #if defined(__LP64__)
        !           920:                        desc64->physaddr[0] =
        !           921:                            htole32(map->dm_segs[i].ds_addr >> 32);
        !           922: #endif
        !           923:                        desc64->physaddr[1] =
        !           924:                            htole32(map->dm_segs[i].ds_addr & 0xffffffff);
        !           925:                        desc64->length = htole16(map->dm_segs[i].ds_len - 1);
        !           926:                        desc64->flags = htole16(flags);
        !           927: #if NVLAN > 0
        !           928:                        desc64->vtag = htole32(vtag);
        !           929: #endif
        !           930:                } else {
        !           931:                        desc32 = &sc->txq.desc32[sc->txq.cur];
        !           932:
        !           933:                        desc32->physaddr = htole32(map->dm_segs[i].ds_addr);
        !           934:                        desc32->length = htole16(map->dm_segs[i].ds_len - 1);
        !           935:                        desc32->flags = htole16(flags);
        !           936:                }
        !           937:
        !           938:                if (map->dm_nsegs > 1) {
        !           939:                        /*
        !           940:                         * Checksum flags and vtag belong to the first fragment
        !           941:                         * only.
        !           942:                         */
        !           943:                        flags &= ~(NFE_TX_IP_CSUM | NFE_TX_TCP_UDP_CSUM);
        !           944: #if NVLAN > 0
        !           945:                        vtag = 0;
        !           946: #endif
        !           947:                        /*
        !           948:                         * Setting of the valid bit in the first descriptor is
        !           949:                         * deferred until the whole chain is fully setup.
        !           950:                         */
        !           951:                        flags |= NFE_TX_VALID;
        !           952:                }
        !           953:
        !           954:                sc->txq.queued++;
        !           955:                sc->txq.cur = (sc->txq.cur + 1) % NFE_TX_RING_COUNT;
        !           956:        }
        !           957:
        !           958:        /* the whole mbuf chain has been setup */
        !           959:        if (sc->sc_flags & NFE_40BIT_ADDR) {
        !           960:                /* fix last descriptor */
        !           961:                flags |= NFE_TX_LASTFRAG_V2;
        !           962:                desc64->flags = htole16(flags);
        !           963:
        !           964:                /* finally, set the valid bit in the first descriptor */
        !           965:                sc->txq.desc64[first].flags |= htole16(NFE_TX_VALID);
        !           966:        } else {
        !           967:                /* fix last descriptor */
        !           968:                if (sc->sc_flags & NFE_JUMBO_SUP)
        !           969:                        flags |= NFE_TX_LASTFRAG_V2;
        !           970:                else
        !           971:                        flags |= NFE_TX_LASTFRAG_V1;
        !           972:                desc32->flags = htole16(flags);
        !           973:
        !           974:                /* finally, set the valid bit in the first descriptor */
        !           975:                sc->txq.desc32[first].flags |= htole16(NFE_TX_VALID);
        !           976:        }
        !           977:
        !           978:        data->m = m0;
        !           979:        data->active = map;
        !           980:
        !           981:        bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize,
        !           982:            BUS_DMASYNC_PREWRITE);
        !           983:
        !           984:        return 0;
        !           985: }
        !           986:
        !           987: void
        !           988: nfe_start(struct ifnet *ifp)
        !           989: {
        !           990:        struct nfe_softc *sc = ifp->if_softc;
        !           991:        int old = sc->txq.cur;
        !           992:        struct mbuf *m0;
        !           993:
        !           994:        for (;;) {
        !           995:                IFQ_POLL(&ifp->if_snd, m0);
        !           996:                if (m0 == NULL)
        !           997:                        break;
        !           998:
        !           999:                if (nfe_encap(sc, m0) != 0) {
        !          1000:                        ifp->if_flags |= IFF_OACTIVE;
        !          1001:                        break;
        !          1002:                }
        !          1003:
        !          1004:                /* packet put in h/w queue, remove from s/w queue */
        !          1005:                IFQ_DEQUEUE(&ifp->if_snd, m0);
        !          1006:
        !          1007: #if NBPFILTER > 0
        !          1008:                if (ifp->if_bpf != NULL)
        !          1009:                        bpf_mtap(ifp->if_bpf, m0, BPF_DIRECTION_OUT);
        !          1010: #endif
        !          1011:        }
        !          1012:        if (sc->txq.cur == old) /* nothing sent */
        !          1013:                return;
        !          1014:
        !          1015:        if (sc->sc_flags & NFE_40BIT_ADDR)
        !          1016:                nfe_txdesc64_rsync(sc, old, sc->txq.cur, BUS_DMASYNC_PREWRITE);
        !          1017:        else
        !          1018:                nfe_txdesc32_rsync(sc, old, sc->txq.cur, BUS_DMASYNC_PREWRITE);
        !          1019:
        !          1020:        /* kick Tx */
        !          1021:        NFE_WRITE(sc, NFE_RXTX_CTL, NFE_RXTX_KICKTX | sc->rxtxctl);
        !          1022:
        !          1023:        /*
        !          1024:         * Set a timeout in case the chip goes out to lunch.
        !          1025:         */
        !          1026:        ifp->if_timer = 5;
        !          1027: }
        !          1028:
        !          1029: void
        !          1030: nfe_watchdog(struct ifnet *ifp)
        !          1031: {
        !          1032:        struct nfe_softc *sc = ifp->if_softc;
        !          1033:
        !          1034:        printf("%s: watchdog timeout\n", sc->sc_dev.dv_xname);
        !          1035:
        !          1036:        nfe_init(ifp);
        !          1037:
        !          1038:        ifp->if_oerrors++;
        !          1039: }
        !          1040:
        !          1041: int
        !          1042: nfe_init(struct ifnet *ifp)
        !          1043: {
        !          1044:        struct nfe_softc *sc = ifp->if_softc;
        !          1045:        uint32_t tmp;
        !          1046:
        !          1047:        nfe_stop(ifp, 0);
        !          1048:
        !          1049:        NFE_WRITE(sc, NFE_TX_UNK, 0);
        !          1050:        NFE_WRITE(sc, NFE_STATUS, 0);
        !          1051:
        !          1052:        sc->rxtxctl = NFE_RXTX_BIT2;
        !          1053:        if (sc->sc_flags & NFE_40BIT_ADDR)
        !          1054:                sc->rxtxctl |= NFE_RXTX_V3MAGIC;
        !          1055:        else if (sc->sc_flags & NFE_JUMBO_SUP)
        !          1056:                sc->rxtxctl |= NFE_RXTX_V2MAGIC;
        !          1057:        if (sc->sc_flags & NFE_HW_CSUM)
        !          1058:                sc->rxtxctl |= NFE_RXTX_RXCSUM;
        !          1059: #if NVLAN > 0
        !          1060:        /*
        !          1061:         * Although the adapter is capable of stripping VLAN tags from received
        !          1062:         * frames (NFE_RXTX_VTAG_STRIP), we do not enable this functionality on
        !          1063:         * purpose.  This will be done in software by our network stack.
        !          1064:         */
        !          1065:        if (sc->sc_flags & NFE_HW_VLAN)
        !          1066:                sc->rxtxctl |= NFE_RXTX_VTAG_INSERT;
        !          1067: #endif
        !          1068:        NFE_WRITE(sc, NFE_RXTX_CTL, NFE_RXTX_RESET | sc->rxtxctl);
        !          1069:        DELAY(10);
        !          1070:        NFE_WRITE(sc, NFE_RXTX_CTL, sc->rxtxctl);
        !          1071:
        !          1072: #if NVLAN
        !          1073:        if (sc->sc_flags & NFE_HW_VLAN)
        !          1074:                NFE_WRITE(sc, NFE_VTAG_CTL, NFE_VTAG_ENABLE);
        !          1075: #endif
        !          1076:
        !          1077:        NFE_WRITE(sc, NFE_SETUP_R6, 0);
        !          1078:
        !          1079:        /* set MAC address */
        !          1080:        nfe_set_macaddr(sc, sc->sc_arpcom.ac_enaddr);
        !          1081:
        !          1082:        /* tell MAC where rings are in memory */
        !          1083: #ifdef __LP64__
        !          1084:        NFE_WRITE(sc, NFE_RX_RING_ADDR_HI, sc->rxq.physaddr >> 32);
        !          1085: #endif
        !          1086:        NFE_WRITE(sc, NFE_RX_RING_ADDR_LO, sc->rxq.physaddr & 0xffffffff);
        !          1087: #ifdef __LP64__
        !          1088:        NFE_WRITE(sc, NFE_TX_RING_ADDR_HI, sc->txq.physaddr >> 32);
        !          1089: #endif
        !          1090:        NFE_WRITE(sc, NFE_TX_RING_ADDR_LO, sc->txq.physaddr & 0xffffffff);
        !          1091:
        !          1092:        NFE_WRITE(sc, NFE_RING_SIZE,
        !          1093:            (NFE_RX_RING_COUNT - 1) << 16 |
        !          1094:            (NFE_TX_RING_COUNT - 1));
        !          1095:
        !          1096:        NFE_WRITE(sc, NFE_RXBUFSZ, sc->rxq.bufsz);
        !          1097:
        !          1098:        /* force MAC to wakeup */
        !          1099:        tmp = NFE_READ(sc, NFE_PWR_STATE);
        !          1100:        NFE_WRITE(sc, NFE_PWR_STATE, tmp | NFE_PWR_WAKEUP);
        !          1101:        DELAY(10);
        !          1102:        tmp = NFE_READ(sc, NFE_PWR_STATE);
        !          1103:        NFE_WRITE(sc, NFE_PWR_STATE, tmp | NFE_PWR_VALID);
        !          1104:
        !          1105: #if 1
        !          1106:        /* configure interrupts coalescing/mitigation */
        !          1107:        NFE_WRITE(sc, NFE_IMTIMER, NFE_IM_DEFAULT);
        !          1108: #else
        !          1109:        /* no interrupt mitigation: one interrupt per packet */
        !          1110:        NFE_WRITE(sc, NFE_IMTIMER, 970);
        !          1111: #endif
        !          1112:
        !          1113:        NFE_WRITE(sc, NFE_SETUP_R1, NFE_R1_MAGIC);
        !          1114:        NFE_WRITE(sc, NFE_SETUP_R2, NFE_R2_MAGIC);
        !          1115:        NFE_WRITE(sc, NFE_SETUP_R6, NFE_R6_MAGIC);
        !          1116:
        !          1117:        /* update MAC knowledge of PHY; generates a NFE_IRQ_LINK interrupt */
        !          1118:        NFE_WRITE(sc, NFE_STATUS, sc->mii_phyaddr << 24 | NFE_STATUS_MAGIC);
        !          1119:
        !          1120:        NFE_WRITE(sc, NFE_SETUP_R4, NFE_R4_MAGIC);
        !          1121:        NFE_WRITE(sc, NFE_WOL_CTL, NFE_WOL_ENABLE);
        !          1122:
        !          1123:        sc->rxtxctl &= ~NFE_RXTX_BIT2;
        !          1124:        NFE_WRITE(sc, NFE_RXTX_CTL, sc->rxtxctl);
        !          1125:        DELAY(10);
        !          1126:        NFE_WRITE(sc, NFE_RXTX_CTL, NFE_RXTX_BIT1 | sc->rxtxctl);
        !          1127:
        !          1128:        /* set Rx filter */
        !          1129:        nfe_setmulti(sc);
        !          1130:
        !          1131:        nfe_ifmedia_upd(ifp);
        !          1132:
        !          1133:        /* enable Rx */
        !          1134:        NFE_WRITE(sc, NFE_RX_CTL, NFE_RX_START);
        !          1135:
        !          1136:        /* enable Tx */
        !          1137:        NFE_WRITE(sc, NFE_TX_CTL, NFE_TX_START);
        !          1138:
        !          1139:        NFE_WRITE(sc, NFE_PHY_STATUS, 0xf);
        !          1140:
        !          1141:        /* enable interrupts */
        !          1142:        NFE_WRITE(sc, NFE_IRQ_MASK, NFE_IRQ_WANTED);
        !          1143:
        !          1144:        timeout_add(&sc->sc_tick_ch, hz);
        !          1145:
        !          1146:        ifp->if_flags |= IFF_RUNNING;
        !          1147:        ifp->if_flags &= ~IFF_OACTIVE;
        !          1148:
        !          1149:        return 0;
        !          1150: }
        !          1151:
        !          1152: void
        !          1153: nfe_stop(struct ifnet *ifp, int disable)
        !          1154: {
        !          1155:        struct nfe_softc *sc = ifp->if_softc;
        !          1156:
        !          1157:        timeout_del(&sc->sc_tick_ch);
        !          1158:
        !          1159:        ifp->if_timer = 0;
        !          1160:        ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
        !          1161:
        !          1162:        mii_down(&sc->sc_mii);
        !          1163:
        !          1164:        /* abort Tx */
        !          1165:        NFE_WRITE(sc, NFE_TX_CTL, 0);
        !          1166:
        !          1167:        /* disable Rx */
        !          1168:        NFE_WRITE(sc, NFE_RX_CTL, 0);
        !          1169:
        !          1170:        /* disable interrupts */
        !          1171:        NFE_WRITE(sc, NFE_IRQ_MASK, 0);
        !          1172:
        !          1173:        /* reset Tx and Rx rings */
        !          1174:        nfe_reset_tx_ring(sc, &sc->txq);
        !          1175:        nfe_reset_rx_ring(sc, &sc->rxq);
        !          1176: }
        !          1177:
        !          1178: int
        !          1179: nfe_alloc_rx_ring(struct nfe_softc *sc, struct nfe_rx_ring *ring)
        !          1180: {
        !          1181:        struct nfe_desc32 *desc32;
        !          1182:        struct nfe_desc64 *desc64;
        !          1183:        struct nfe_rx_data *data;
        !          1184:        struct nfe_jbuf *jbuf;
        !          1185:        void **desc;
        !          1186:        bus_addr_t physaddr;
        !          1187:        int i, nsegs, error, descsize;
        !          1188:
        !          1189:        if (sc->sc_flags & NFE_40BIT_ADDR) {
        !          1190:                desc = (void **)&ring->desc64;
        !          1191:                descsize = sizeof (struct nfe_desc64);
        !          1192:        } else {
        !          1193:                desc = (void **)&ring->desc32;
        !          1194:                descsize = sizeof (struct nfe_desc32);
        !          1195:        }
        !          1196:
        !          1197:        ring->cur = ring->next = 0;
        !          1198:        ring->bufsz = MCLBYTES;
        !          1199:
        !          1200:        error = bus_dmamap_create(sc->sc_dmat, NFE_RX_RING_COUNT * descsize, 1,
        !          1201:            NFE_RX_RING_COUNT * descsize, 0, BUS_DMA_NOWAIT, &ring->map);
        !          1202:        if (error != 0) {
        !          1203:                printf("%s: could not create desc DMA map\n",
        !          1204:                    sc->sc_dev.dv_xname);
        !          1205:                goto fail;
        !          1206:        }
        !          1207:
        !          1208:        error = bus_dmamem_alloc(sc->sc_dmat, NFE_RX_RING_COUNT * descsize,
        !          1209:            PAGE_SIZE, 0, &ring->seg, 1, &nsegs, BUS_DMA_NOWAIT);
        !          1210:        if (error != 0) {
        !          1211:                printf("%s: could not allocate DMA memory\n",
        !          1212:                    sc->sc_dev.dv_xname);
        !          1213:                goto fail;
        !          1214:        }
        !          1215:
        !          1216:        error = bus_dmamem_map(sc->sc_dmat, &ring->seg, nsegs,
        !          1217:            NFE_RX_RING_COUNT * descsize, (caddr_t *)desc, BUS_DMA_NOWAIT);
        !          1218:        if (error != 0) {
        !          1219:                printf("%s: could not map desc DMA memory\n",
        !          1220:                    sc->sc_dev.dv_xname);
        !          1221:                goto fail;
        !          1222:        }
        !          1223:
        !          1224:        error = bus_dmamap_load(sc->sc_dmat, ring->map, *desc,
        !          1225:            NFE_RX_RING_COUNT * descsize, NULL, BUS_DMA_NOWAIT);
        !          1226:        if (error != 0) {
        !          1227:                printf("%s: could not load desc DMA map\n",
        !          1228:                    sc->sc_dev.dv_xname);
        !          1229:                goto fail;
        !          1230:        }
        !          1231:
        !          1232:        bzero(*desc, NFE_RX_RING_COUNT * descsize);
        !          1233:        ring->physaddr = ring->map->dm_segs[0].ds_addr;
        !          1234:
        !          1235:        if (sc->sc_flags & NFE_USE_JUMBO) {
        !          1236:                ring->bufsz = NFE_JBYTES;
        !          1237:                if ((error = nfe_jpool_alloc(sc)) != 0) {
        !          1238:                        printf("%s: could not allocate jumbo frames\n",
        !          1239:                            sc->sc_dev.dv_xname);
        !          1240:                        goto fail;
        !          1241:                }
        !          1242:        }
        !          1243:
        !          1244:        /*
        !          1245:         * Pre-allocate Rx buffers and populate Rx ring.
        !          1246:         */
        !          1247:        for (i = 0; i < NFE_RX_RING_COUNT; i++) {
        !          1248:                data = &sc->rxq.data[i];
        !          1249:
        !          1250:                MGETHDR(data->m, M_DONTWAIT, MT_DATA);
        !          1251:                if (data->m == NULL) {
        !          1252:                        printf("%s: could not allocate rx mbuf\n",
        !          1253:                            sc->sc_dev.dv_xname);
        !          1254:                        error = ENOMEM;
        !          1255:                        goto fail;
        !          1256:                }
        !          1257:
        !          1258:                if (sc->sc_flags & NFE_USE_JUMBO) {
        !          1259:                        if ((jbuf = nfe_jalloc(sc)) == NULL) {
        !          1260:                                printf("%s: could not allocate jumbo buffer\n",
        !          1261:                                    sc->sc_dev.dv_xname);
        !          1262:                                goto fail;
        !          1263:                        }
        !          1264:                        MEXTADD(data->m, jbuf->buf, NFE_JBYTES, 0, nfe_jfree,
        !          1265:                            sc);
        !          1266:
        !          1267:                        physaddr = jbuf->physaddr;
        !          1268:                } else {
        !          1269:                        error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1,
        !          1270:                            MCLBYTES, 0, BUS_DMA_NOWAIT, &data->map);
        !          1271:                        if (error != 0) {
        !          1272:                                printf("%s: could not create DMA map\n",
        !          1273:                                    sc->sc_dev.dv_xname);
        !          1274:                                goto fail;
        !          1275:                        }
        !          1276:                        MCLGET(data->m, M_DONTWAIT);
        !          1277:                        if (!(data->m->m_flags & M_EXT)) {
        !          1278:                                printf("%s: could not allocate mbuf cluster\n",
        !          1279:                                    sc->sc_dev.dv_xname);
        !          1280:                                error = ENOMEM;
        !          1281:                                goto fail;
        !          1282:                        }
        !          1283:
        !          1284:                        error = bus_dmamap_load(sc->sc_dmat, data->map,
        !          1285:                            mtod(data->m, void *), MCLBYTES, NULL,
        !          1286:                            BUS_DMA_READ | BUS_DMA_NOWAIT);
        !          1287:                        if (error != 0) {
        !          1288:                                printf("%s: could not load rx buf DMA map",
        !          1289:                                    sc->sc_dev.dv_xname);
        !          1290:                                goto fail;
        !          1291:                        }
        !          1292:                        physaddr = data->map->dm_segs[0].ds_addr;
        !          1293:                }
        !          1294:
        !          1295:                if (sc->sc_flags & NFE_40BIT_ADDR) {
        !          1296:                        desc64 = &sc->rxq.desc64[i];
        !          1297: #if defined(__LP64__)
        !          1298:                        desc64->physaddr[0] = htole32(physaddr >> 32);
        !          1299: #endif
        !          1300:                        desc64->physaddr[1] = htole32(physaddr & 0xffffffff);
        !          1301:                        desc64->length = htole16(sc->rxq.bufsz);
        !          1302:                        desc64->flags = htole16(NFE_RX_READY);
        !          1303:                } else {
        !          1304:                        desc32 = &sc->rxq.desc32[i];
        !          1305:                        desc32->physaddr = htole32(physaddr);
        !          1306:                        desc32->length = htole16(sc->rxq.bufsz);
        !          1307:                        desc32->flags = htole16(NFE_RX_READY);
        !          1308:                }
        !          1309:        }
        !          1310:
        !          1311:        bus_dmamap_sync(sc->sc_dmat, ring->map, 0, ring->map->dm_mapsize,
        !          1312:            BUS_DMASYNC_PREWRITE);
        !          1313:
        !          1314:        return 0;
        !          1315:
        !          1316: fail:  nfe_free_rx_ring(sc, ring);
        !          1317:        return error;
        !          1318: }
        !          1319:
        !          1320: void
        !          1321: nfe_reset_rx_ring(struct nfe_softc *sc, struct nfe_rx_ring *ring)
        !          1322: {
        !          1323:        int i;
        !          1324:
        !          1325:        for (i = 0; i < NFE_RX_RING_COUNT; i++) {
        !          1326:                if (sc->sc_flags & NFE_40BIT_ADDR) {
        !          1327:                        ring->desc64[i].length = htole16(ring->bufsz);
        !          1328:                        ring->desc64[i].flags = htole16(NFE_RX_READY);
        !          1329:                } else {
        !          1330:                        ring->desc32[i].length = htole16(ring->bufsz);
        !          1331:                        ring->desc32[i].flags = htole16(NFE_RX_READY);
        !          1332:                }
        !          1333:        }
        !          1334:
        !          1335:        bus_dmamap_sync(sc->sc_dmat, ring->map, 0, ring->map->dm_mapsize,
        !          1336:            BUS_DMASYNC_PREWRITE);
        !          1337:
        !          1338:        ring->cur = ring->next = 0;
        !          1339: }
        !          1340:
        !          1341: void
        !          1342: nfe_free_rx_ring(struct nfe_softc *sc, struct nfe_rx_ring *ring)
        !          1343: {
        !          1344:        struct nfe_rx_data *data;
        !          1345:        void *desc;
        !          1346:        int i, descsize;
        !          1347:
        !          1348:        if (sc->sc_flags & NFE_40BIT_ADDR) {
        !          1349:                desc = ring->desc64;
        !          1350:                descsize = sizeof (struct nfe_desc64);
        !          1351:        } else {
        !          1352:                desc = ring->desc32;
        !          1353:                descsize = sizeof (struct nfe_desc32);
        !          1354:        }
        !          1355:
        !          1356:        if (desc != NULL) {
        !          1357:                bus_dmamap_sync(sc->sc_dmat, ring->map, 0,
        !          1358:                    ring->map->dm_mapsize, BUS_DMASYNC_POSTWRITE);
        !          1359:                bus_dmamap_unload(sc->sc_dmat, ring->map);
        !          1360:                bus_dmamem_unmap(sc->sc_dmat, (caddr_t)desc,
        !          1361:                    NFE_RX_RING_COUNT * descsize);
        !          1362:                bus_dmamem_free(sc->sc_dmat, &ring->seg, 1);
        !          1363:        }
        !          1364:
        !          1365:        for (i = 0; i < NFE_RX_RING_COUNT; i++) {
        !          1366:                data = &ring->data[i];
        !          1367:
        !          1368:                if (data->map != NULL) {
        !          1369:                        bus_dmamap_sync(sc->sc_dmat, data->map, 0,
        !          1370:                            data->map->dm_mapsize, BUS_DMASYNC_POSTREAD);
        !          1371:                        bus_dmamap_unload(sc->sc_dmat, data->map);
        !          1372:                        bus_dmamap_destroy(sc->sc_dmat, data->map);
        !          1373:                }
        !          1374:                if (data->m != NULL)
        !          1375:                        m_freem(data->m);
        !          1376:        }
        !          1377: }
        !          1378:
        !          1379: struct nfe_jbuf *
        !          1380: nfe_jalloc(struct nfe_softc *sc)
        !          1381: {
        !          1382:        struct nfe_jbuf *jbuf;
        !          1383:
        !          1384:        jbuf = SLIST_FIRST(&sc->rxq.jfreelist);
        !          1385:        if (jbuf == NULL)
        !          1386:                return NULL;
        !          1387:        SLIST_REMOVE_HEAD(&sc->rxq.jfreelist, jnext);
        !          1388:        return jbuf;
        !          1389: }
        !          1390:
        !          1391: /*
        !          1392:  * This is called automatically by the network stack when the mbuf is freed.
        !          1393:  * Caution must be taken that the NIC might be reset by the time the mbuf is
        !          1394:  * freed.
        !          1395:  */
        !          1396: void
        !          1397: nfe_jfree(caddr_t buf, u_int size, void *arg)
        !          1398: {
        !          1399:        struct nfe_softc *sc = arg;
        !          1400:        struct nfe_jbuf *jbuf;
        !          1401:        int i;
        !          1402:
        !          1403:        /* find the jbuf from the base pointer */
        !          1404:        i = (buf - sc->rxq.jpool) / NFE_JBYTES;
        !          1405:        if (i < 0 || i >= NFE_JPOOL_COUNT) {
        !          1406:                printf("%s: request to free a buffer (%p) not managed by us\n",
        !          1407:                    sc->sc_dev.dv_xname, buf);
        !          1408:                return;
        !          1409:        }
        !          1410:        jbuf = &sc->rxq.jbuf[i];
        !          1411:
        !          1412:        /* ..and put it back in the free list */
        !          1413:        SLIST_INSERT_HEAD(&sc->rxq.jfreelist, jbuf, jnext);
        !          1414: }
        !          1415:
        !          1416: int
        !          1417: nfe_jpool_alloc(struct nfe_softc *sc)
        !          1418: {
        !          1419:        struct nfe_rx_ring *ring = &sc->rxq;
        !          1420:        struct nfe_jbuf *jbuf;
        !          1421:        bus_addr_t physaddr;
        !          1422:        caddr_t buf;
        !          1423:        int i, nsegs, error;
        !          1424:
        !          1425:        /*
        !          1426:         * Allocate a big chunk of DMA'able memory.
        !          1427:         */
        !          1428:        error = bus_dmamap_create(sc->sc_dmat, NFE_JPOOL_SIZE, 1,
        !          1429:            NFE_JPOOL_SIZE, 0, BUS_DMA_NOWAIT, &ring->jmap);
        !          1430:        if (error != 0) {
        !          1431:                printf("%s: could not create jumbo DMA map\n",
        !          1432:                    sc->sc_dev.dv_xname);
        !          1433:                goto fail;
        !          1434:        }
        !          1435:
        !          1436:        error = bus_dmamem_alloc(sc->sc_dmat, NFE_JPOOL_SIZE, PAGE_SIZE, 0,
        !          1437:            &ring->jseg, 1, &nsegs, BUS_DMA_NOWAIT);
        !          1438:        if (error != 0) {
        !          1439:                printf("%s could not allocate jumbo DMA memory\n",
        !          1440:                    sc->sc_dev.dv_xname);
        !          1441:                goto fail;
        !          1442:        }
        !          1443:
        !          1444:        error = bus_dmamem_map(sc->sc_dmat, &ring->jseg, nsegs, NFE_JPOOL_SIZE,
        !          1445:            &ring->jpool, BUS_DMA_NOWAIT);
        !          1446:        if (error != 0) {
        !          1447:                printf("%s: could not map jumbo DMA memory\n",
        !          1448:                    sc->sc_dev.dv_xname);
        !          1449:                goto fail;
        !          1450:        }
        !          1451:
        !          1452:        error = bus_dmamap_load(sc->sc_dmat, ring->jmap, ring->jpool,
        !          1453:            NFE_JPOOL_SIZE, NULL, BUS_DMA_READ | BUS_DMA_NOWAIT);
        !          1454:        if (error != 0) {
        !          1455:                printf("%s: could not load jumbo DMA map\n",
        !          1456:                    sc->sc_dev.dv_xname);
        !          1457:                goto fail;
        !          1458:        }
        !          1459:
        !          1460:        /* ..and split it into 9KB chunks */
        !          1461:        SLIST_INIT(&ring->jfreelist);
        !          1462:
        !          1463:        buf = ring->jpool;
        !          1464:        physaddr = ring->jmap->dm_segs[0].ds_addr;
        !          1465:        for (i = 0; i < NFE_JPOOL_COUNT; i++) {
        !          1466:                jbuf = &ring->jbuf[i];
        !          1467:
        !          1468:                jbuf->buf = buf;
        !          1469:                jbuf->physaddr = physaddr;
        !          1470:
        !          1471:                SLIST_INSERT_HEAD(&ring->jfreelist, jbuf, jnext);
        !          1472:
        !          1473:                buf += NFE_JBYTES;
        !          1474:                physaddr += NFE_JBYTES;
        !          1475:        }
        !          1476:
        !          1477:        return 0;
        !          1478:
        !          1479: fail:  nfe_jpool_free(sc);
        !          1480:        return error;
        !          1481: }
        !          1482:
        !          1483: void
        !          1484: nfe_jpool_free(struct nfe_softc *sc)
        !          1485: {
        !          1486:        struct nfe_rx_ring *ring = &sc->rxq;
        !          1487:
        !          1488:        if (ring->jmap != NULL) {
        !          1489:                bus_dmamap_sync(sc->sc_dmat, ring->jmap, 0,
        !          1490:                    ring->jmap->dm_mapsize, BUS_DMASYNC_POSTWRITE);
        !          1491:                bus_dmamap_unload(sc->sc_dmat, ring->jmap);
        !          1492:                bus_dmamap_destroy(sc->sc_dmat, ring->jmap);
        !          1493:        }
        !          1494:        if (ring->jpool != NULL) {
        !          1495:                bus_dmamem_unmap(sc->sc_dmat, ring->jpool, NFE_JPOOL_SIZE);
        !          1496:                bus_dmamem_free(sc->sc_dmat, &ring->jseg, 1);
        !          1497:        }
        !          1498: }
        !          1499:
        !          1500: int
        !          1501: nfe_alloc_tx_ring(struct nfe_softc *sc, struct nfe_tx_ring *ring)
        !          1502: {
        !          1503:        int i, nsegs, error;
        !          1504:        void **desc;
        !          1505:        int descsize;
        !          1506:
        !          1507:        if (sc->sc_flags & NFE_40BIT_ADDR) {
        !          1508:                desc = (void **)&ring->desc64;
        !          1509:                descsize = sizeof (struct nfe_desc64);
        !          1510:        } else {
        !          1511:                desc = (void **)&ring->desc32;
        !          1512:                descsize = sizeof (struct nfe_desc32);
        !          1513:        }
        !          1514:
        !          1515:        ring->queued = 0;
        !          1516:        ring->cur = ring->next = 0;
        !          1517:
        !          1518:        error = bus_dmamap_create(sc->sc_dmat, NFE_TX_RING_COUNT * descsize, 1,
        !          1519:            NFE_TX_RING_COUNT * descsize, 0, BUS_DMA_NOWAIT, &ring->map);
        !          1520:
        !          1521:        if (error != 0) {
        !          1522:                printf("%s: could not create desc DMA map\n",
        !          1523:                    sc->sc_dev.dv_xname);
        !          1524:                goto fail;
        !          1525:        }
        !          1526:
        !          1527:        error = bus_dmamem_alloc(sc->sc_dmat, NFE_TX_RING_COUNT * descsize,
        !          1528:            PAGE_SIZE, 0, &ring->seg, 1, &nsegs, BUS_DMA_NOWAIT);
        !          1529:        if (error != 0) {
        !          1530:                printf("%s: could not allocate DMA memory\n",
        !          1531:                    sc->sc_dev.dv_xname);
        !          1532:                goto fail;
        !          1533:        }
        !          1534:
        !          1535:        error = bus_dmamem_map(sc->sc_dmat, &ring->seg, nsegs,
        !          1536:            NFE_TX_RING_COUNT * descsize, (caddr_t *)desc, BUS_DMA_NOWAIT);
        !          1537:        if (error != 0) {
        !          1538:                printf("%s: could not map desc DMA memory\n",
        !          1539:                    sc->sc_dev.dv_xname);
        !          1540:                goto fail;
        !          1541:        }
        !          1542:
        !          1543:        error = bus_dmamap_load(sc->sc_dmat, ring->map, *desc,
        !          1544:            NFE_TX_RING_COUNT * descsize, NULL, BUS_DMA_NOWAIT);
        !          1545:        if (error != 0) {
        !          1546:                printf("%s: could not load desc DMA map\n",
        !          1547:                    sc->sc_dev.dv_xname);
        !          1548:                goto fail;
        !          1549:        }
        !          1550:
        !          1551:        bzero(*desc, NFE_TX_RING_COUNT * descsize);
        !          1552:        ring->physaddr = ring->map->dm_segs[0].ds_addr;
        !          1553:
        !          1554:        for (i = 0; i < NFE_TX_RING_COUNT; i++) {
        !          1555:                error = bus_dmamap_create(sc->sc_dmat, NFE_JBYTES,
        !          1556:                    NFE_MAX_SCATTER, NFE_JBYTES, 0, BUS_DMA_NOWAIT,
        !          1557:                    &ring->data[i].map);
        !          1558:                if (error != 0) {
        !          1559:                        printf("%s: could not create DMA map\n",
        !          1560:                            sc->sc_dev.dv_xname);
        !          1561:                        goto fail;
        !          1562:                }
        !          1563:        }
        !          1564:
        !          1565:        return 0;
        !          1566:
        !          1567: fail:  nfe_free_tx_ring(sc, ring);
        !          1568:        return error;
        !          1569: }
        !          1570:
        !          1571: void
        !          1572: nfe_reset_tx_ring(struct nfe_softc *sc, struct nfe_tx_ring *ring)
        !          1573: {
        !          1574:        struct nfe_tx_data *data;
        !          1575:        int i;
        !          1576:
        !          1577:        for (i = 0; i < NFE_TX_RING_COUNT; i++) {
        !          1578:                if (sc->sc_flags & NFE_40BIT_ADDR)
        !          1579:                        ring->desc64[i].flags = 0;
        !          1580:                else
        !          1581:                        ring->desc32[i].flags = 0;
        !          1582:
        !          1583:                data = &ring->data[i];
        !          1584:
        !          1585:                if (data->m != NULL) {
        !          1586:                        bus_dmamap_sync(sc->sc_dmat, data->active, 0,
        !          1587:                            data->active->dm_mapsize, BUS_DMASYNC_POSTWRITE);
        !          1588:                        bus_dmamap_unload(sc->sc_dmat, data->active);
        !          1589:                        m_freem(data->m);
        !          1590:                        data->m = NULL;
        !          1591:                }
        !          1592:        }
        !          1593:
        !          1594:        bus_dmamap_sync(sc->sc_dmat, ring->map, 0, ring->map->dm_mapsize,
        !          1595:            BUS_DMASYNC_PREWRITE);
        !          1596:
        !          1597:        ring->queued = 0;
        !          1598:        ring->cur = ring->next = 0;
        !          1599: }
        !          1600:
        !          1601: void
        !          1602: nfe_free_tx_ring(struct nfe_softc *sc, struct nfe_tx_ring *ring)
        !          1603: {
        !          1604:        struct nfe_tx_data *data;
        !          1605:        void *desc;
        !          1606:        int i, descsize;
        !          1607:
        !          1608:        if (sc->sc_flags & NFE_40BIT_ADDR) {
        !          1609:                desc = ring->desc64;
        !          1610:                descsize = sizeof (struct nfe_desc64);
        !          1611:        } else {
        !          1612:                desc = ring->desc32;
        !          1613:                descsize = sizeof (struct nfe_desc32);
        !          1614:        }
        !          1615:
        !          1616:        if (desc != NULL) {
        !          1617:                bus_dmamap_sync(sc->sc_dmat, ring->map, 0,
        !          1618:                    ring->map->dm_mapsize, BUS_DMASYNC_POSTWRITE);
        !          1619:                bus_dmamap_unload(sc->sc_dmat, ring->map);
        !          1620:                bus_dmamem_unmap(sc->sc_dmat, (caddr_t)desc,
        !          1621:                    NFE_TX_RING_COUNT * descsize);
        !          1622:                bus_dmamem_free(sc->sc_dmat, &ring->seg, 1);
        !          1623:        }
        !          1624:
        !          1625:        for (i = 0; i < NFE_TX_RING_COUNT; i++) {
        !          1626:                data = &ring->data[i];
        !          1627:
        !          1628:                if (data->m != NULL) {
        !          1629:                        bus_dmamap_sync(sc->sc_dmat, data->active, 0,
        !          1630:                            data->active->dm_mapsize, BUS_DMASYNC_POSTWRITE);
        !          1631:                        bus_dmamap_unload(sc->sc_dmat, data->active);
        !          1632:                        m_freem(data->m);
        !          1633:                }
        !          1634:        }
        !          1635:
        !          1636:        /* ..and now actually destroy the DMA mappings */
        !          1637:        for (i = 0; i < NFE_TX_RING_COUNT; i++) {
        !          1638:                data = &ring->data[i];
        !          1639:                if (data->map == NULL)
        !          1640:                        continue;
        !          1641:                bus_dmamap_destroy(sc->sc_dmat, data->map);
        !          1642:        }
        !          1643: }
        !          1644:
        !          1645: int
        !          1646: nfe_ifmedia_upd(struct ifnet *ifp)
        !          1647: {
        !          1648:        struct nfe_softc *sc = ifp->if_softc;
        !          1649:        struct mii_data *mii = &sc->sc_mii;
        !          1650:        struct mii_softc *miisc;
        !          1651:
        !          1652:        if (mii->mii_instance != 0) {
        !          1653:                LIST_FOREACH(miisc, &mii->mii_phys, mii_list)
        !          1654:                        mii_phy_reset(miisc);
        !          1655:        }
        !          1656:        return mii_mediachg(mii);
        !          1657: }
        !          1658:
        !          1659: void
        !          1660: nfe_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
        !          1661: {
        !          1662:        struct nfe_softc *sc = ifp->if_softc;
        !          1663:        struct mii_data *mii = &sc->sc_mii;
        !          1664:
        !          1665:        mii_pollstat(mii);
        !          1666:        ifmr->ifm_status = mii->mii_media_status;
        !          1667:        ifmr->ifm_active = mii->mii_media_active;
        !          1668: }
        !          1669:
        !          1670: void
        !          1671: nfe_setmulti(struct nfe_softc *sc)
        !          1672: {
        !          1673:        struct arpcom *ac = &sc->sc_arpcom;
        !          1674:        struct ifnet *ifp = &ac->ac_if;
        !          1675:        struct ether_multi *enm;
        !          1676:        struct ether_multistep step;
        !          1677:        uint8_t addr[ETHER_ADDR_LEN], mask[ETHER_ADDR_LEN];
        !          1678:        uint32_t filter = NFE_RXFILTER_MAGIC;
        !          1679:        int i;
        !          1680:
        !          1681:        if ((ifp->if_flags & (IFF_ALLMULTI | IFF_PROMISC)) != 0) {
        !          1682:                bzero(addr, ETHER_ADDR_LEN);
        !          1683:                bzero(mask, ETHER_ADDR_LEN);
        !          1684:                goto done;
        !          1685:        }
        !          1686:
        !          1687:        bcopy(etherbroadcastaddr, addr, ETHER_ADDR_LEN);
        !          1688:        bcopy(etherbroadcastaddr, mask, ETHER_ADDR_LEN);
        !          1689:
        !          1690:        ETHER_FIRST_MULTI(step, ac, enm);
        !          1691:        while (enm != NULL) {
        !          1692:                if (bcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) {
        !          1693:                        ifp->if_flags |= IFF_ALLMULTI;
        !          1694:                        bzero(addr, ETHER_ADDR_LEN);
        !          1695:                        bzero(mask, ETHER_ADDR_LEN);
        !          1696:                        goto done;
        !          1697:                }
        !          1698:                for (i = 0; i < ETHER_ADDR_LEN; i++) {
        !          1699:                        addr[i] &=  enm->enm_addrlo[i];
        !          1700:                        mask[i] &= ~enm->enm_addrlo[i];
        !          1701:                }
        !          1702:                ETHER_NEXT_MULTI(step, enm);
        !          1703:        }
        !          1704:        for (i = 0; i < ETHER_ADDR_LEN; i++)
        !          1705:                mask[i] |= addr[i];
        !          1706:
        !          1707: done:
        !          1708:        addr[0] |= 0x01;        /* make sure multicast bit is set */
        !          1709:
        !          1710:        NFE_WRITE(sc, NFE_MULTIADDR_HI,
        !          1711:            addr[3] << 24 | addr[2] << 16 | addr[1] << 8 | addr[0]);
        !          1712:        NFE_WRITE(sc, NFE_MULTIADDR_LO,
        !          1713:            addr[5] <<  8 | addr[4]);
        !          1714:        NFE_WRITE(sc, NFE_MULTIMASK_HI,
        !          1715:            mask[3] << 24 | mask[2] << 16 | mask[1] << 8 | mask[0]);
        !          1716:        NFE_WRITE(sc, NFE_MULTIMASK_LO,
        !          1717:            mask[5] <<  8 | mask[4]);
        !          1718:
        !          1719:        filter |= (ifp->if_flags & IFF_PROMISC) ? NFE_PROMISC : NFE_U2M;
        !          1720:        NFE_WRITE(sc, NFE_RXFILTER, filter);
        !          1721: }
        !          1722:
        !          1723: void
        !          1724: nfe_get_macaddr(struct nfe_softc *sc, uint8_t *addr)
        !          1725: {
        !          1726:        uint32_t tmp;
        !          1727:
        !          1728:        tmp = NFE_READ(sc, NFE_MACADDR_LO);
        !          1729:        addr[0] = (tmp >> 8) & 0xff;
        !          1730:        addr[1] = (tmp & 0xff);
        !          1731:
        !          1732:        tmp = NFE_READ(sc, NFE_MACADDR_HI);
        !          1733:        addr[2] = (tmp >> 24) & 0xff;
        !          1734:        addr[3] = (tmp >> 16) & 0xff;
        !          1735:        addr[4] = (tmp >>  8) & 0xff;
        !          1736:        addr[5] = (tmp & 0xff);
        !          1737: }
        !          1738:
        !          1739: void
        !          1740: nfe_set_macaddr(struct nfe_softc *sc, const uint8_t *addr)
        !          1741: {
        !          1742:        NFE_WRITE(sc, NFE_MACADDR_LO,
        !          1743:            addr[5] <<  8 | addr[4]);
        !          1744:        NFE_WRITE(sc, NFE_MACADDR_HI,
        !          1745:            addr[3] << 24 | addr[2] << 16 | addr[1] << 8 | addr[0]);
        !          1746: }
        !          1747:
        !          1748: void
        !          1749: nfe_tick(void *arg)
        !          1750: {
        !          1751:        struct nfe_softc *sc = arg;
        !          1752:        int s;
        !          1753:
        !          1754:        s = splnet();
        !          1755:        mii_tick(&sc->sc_mii);
        !          1756:        splx(s);
        !          1757:
        !          1758:        timeout_add(&sc->sc_tick_ch, hz);
        !          1759: }

CVSweb