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