if_nfe.c revision 164360
1159967Sobrien/* $OpenBSD: if_nfe.c,v 1.54 2006/04/07 12:38:12 jsg Exp $ */ 2159952Sobrien 3159952Sobrien/*- 4159967Sobrien * Copyright (c) 2006 Shigeaki Tagashira <shigeaki@se.hiroshima-u.ac.jp> 5159952Sobrien * Copyright (c) 2006 Damien Bergamini <damien.bergamini@free.fr> 6159952Sobrien * Copyright (c) 2005, 2006 Jonathan Gray <jsg@openbsd.org> 7159952Sobrien * 8159952Sobrien * Permission to use, copy, modify, and distribute this software for any 9159952Sobrien * purpose with or without fee is hereby granted, provided that the above 10159952Sobrien * copyright notice and this permission notice appear in all copies. 11159952Sobrien * 12159952Sobrien * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 13159952Sobrien * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 14159952Sobrien * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 15159952Sobrien * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 16159952Sobrien * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 17159952Sobrien * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 18159952Sobrien * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 19159952Sobrien */ 20159952Sobrien 21159952Sobrien/* Driver for NVIDIA nForce MCP Fast Ethernet and Gigabit Ethernet */ 22159952Sobrien 23159967Sobrien#include <sys/cdefs.h> 24159967Sobrien__FBSDID("$FreeBSD: head/sys/dev/nfe/if_nfe.c 164360 2006-11-17 16:49:40Z obrien $"); 25159952Sobrien 26159967Sobrien/* Uncomment the following line to enable polling. */ 27163503Sobrien/* #define DEVICE_POLLING */ 28159967Sobrien 29163503Sobrien#define NFE_NO_JUMBO 30163503Sobrien#define NFE_CSUM 31163503Sobrien#define NFE_CSUM_FEATURES (CSUM_IP | CSUM_TCP | CSUM_UDP) 32163503Sobrien#define NVLAN 0 33159967Sobrien 34159967Sobrien#ifdef HAVE_KERNEL_OPTION_HEADERS 35159967Sobrien#include "opt_device_polling.h" 36159967Sobrien#endif 37159967Sobrien 38159952Sobrien#include <sys/param.h> 39159952Sobrien#include <sys/endian.h> 40159952Sobrien#include <sys/systm.h> 41159952Sobrien#include <sys/sockio.h> 42159952Sobrien#include <sys/mbuf.h> 43159952Sobrien#include <sys/malloc.h> 44159967Sobrien#include <sys/module.h> 45159952Sobrien#include <sys/kernel.h> 46159952Sobrien#include <sys/socket.h> 47159967Sobrien#include <sys/taskqueue.h> 48159952Sobrien 49159952Sobrien#include <net/if.h> 50159967Sobrien#include <net/if_arp.h> 51159967Sobrien#include <net/ethernet.h> 52159952Sobrien#include <net/if_dl.h> 53159952Sobrien#include <net/if_media.h> 54159952Sobrien#include <net/if_types.h> 55159952Sobrien#include <net/if_vlan_var.h> 56159952Sobrien 57159952Sobrien#include <net/bpf.h> 58159952Sobrien 59159967Sobrien#include <machine/bus.h> 60159967Sobrien#include <machine/resource.h> 61159967Sobrien#include <sys/bus.h> 62159967Sobrien#include <sys/rman.h> 63159967Sobrien 64159952Sobrien#include <dev/mii/mii.h> 65159952Sobrien#include <dev/mii/miivar.h> 66159952Sobrien 67159952Sobrien#include <dev/pci/pcireg.h> 68159952Sobrien#include <dev/pci/pcivar.h> 69159952Sobrien 70159967Sobrien#include <dev/nfe/if_nfereg.h> 71159967Sobrien#include <dev/nfe/if_nfevar.h> 72159952Sobrien 73159967SobrienMODULE_DEPEND(nfe, pci, 1, 1, 1); 74159967SobrienMODULE_DEPEND(nfe, ether, 1, 1, 1); 75159967SobrienMODULE_DEPEND(nfe, miibus, 1, 1, 1); 76159967Sobrien#include "miibus_if.h" 77159952Sobrien 78163503Sobrienstatic int nfe_probe(device_t); 79163503Sobrienstatic int nfe_attach(device_t); 80163503Sobrienstatic int nfe_detach(device_t); 81163503Sobrienstatic void nfe_shutdown(device_t); 82163503Sobrienstatic int nfe_miibus_readreg(device_t, int, int); 83163503Sobrienstatic int nfe_miibus_writereg(device_t, int, int, int); 84163503Sobrienstatic void nfe_miibus_statchg(device_t); 85163503Sobrienstatic int nfe_ioctl(struct ifnet *, u_long, caddr_t); 86163503Sobrienstatic void nfe_intr(void *); 87159967Sobrienstatic void nfe_txdesc32_sync(struct nfe_softc *, struct nfe_desc32 *, int); 88159967Sobrienstatic void nfe_txdesc64_sync(struct nfe_softc *, struct nfe_desc64 *, int); 89159967Sobrienstatic void nfe_txdesc32_rsync(struct nfe_softc *, int, int, int); 90159967Sobrienstatic void nfe_txdesc64_rsync(struct nfe_softc *, int, int, int); 91159967Sobrienstatic void nfe_rxdesc32_sync(struct nfe_softc *, struct nfe_desc32 *, int); 92159967Sobrienstatic void nfe_rxdesc64_sync(struct nfe_softc *, struct nfe_desc64 *, int); 93159967Sobrienstatic void nfe_rxeof(struct nfe_softc *); 94159967Sobrienstatic void nfe_txeof(struct nfe_softc *); 95159967Sobrienstatic int nfe_encap(struct nfe_softc *, struct mbuf *); 96159967Sobrienstatic struct nfe_jbuf *nfe_jalloc(struct nfe_softc *); 97159967Sobrienstatic void nfe_jfree(void *, void *); 98159967Sobrienstatic int nfe_jpool_alloc(struct nfe_softc *); 99159967Sobrienstatic void nfe_jpool_free(struct nfe_softc *); 100159967Sobrienstatic void nfe_setmulti(struct nfe_softc *); 101159967Sobrienstatic void nfe_start(struct ifnet *); 102159967Sobrienstatic void nfe_start_locked(struct ifnet *); 103159967Sobrienstatic void nfe_watchdog(struct ifnet *); 104159967Sobrienstatic void nfe_init(void *); 105159967Sobrienstatic void nfe_init_locked(void *); 106159967Sobrienstatic void nfe_stop(struct ifnet *, int); 107159967Sobrienstatic int nfe_alloc_rx_ring(struct nfe_softc *, struct nfe_rx_ring *); 108159967Sobrienstatic void nfe_reset_rx_ring(struct nfe_softc *, struct nfe_rx_ring *); 109159967Sobrienstatic void nfe_free_rx_ring(struct nfe_softc *, struct nfe_rx_ring *); 110159967Sobrienstatic int nfe_alloc_tx_ring(struct nfe_softc *, struct nfe_tx_ring *); 111159967Sobrienstatic void nfe_reset_tx_ring(struct nfe_softc *, struct nfe_tx_ring *); 112159967Sobrienstatic void nfe_free_tx_ring(struct nfe_softc *, struct nfe_tx_ring *); 113159967Sobrienstatic int nfe_ifmedia_upd(struct ifnet *); 114159967Sobrienstatic int nfe_ifmedia_upd_locked(struct ifnet *); 115159967Sobrienstatic void nfe_ifmedia_sts(struct ifnet *, struct ifmediareq *); 116159967Sobrienstatic void nfe_tick(void *); 117159967Sobrienstatic void nfe_tick_locked(struct nfe_softc *); 118159967Sobrienstatic void nfe_get_macaddr(struct nfe_softc *, u_char *); 119159967Sobrienstatic void nfe_set_macaddr(struct nfe_softc *, u_char *); 120159967Sobrienstatic void nfe_dma_map_segs (void *, bus_dma_segment_t *, int, int); 121159967Sobrien#ifdef DEVICE_POLLING 122159967Sobrienstatic void nfe_poll_locked(struct ifnet *, enum poll_cmd, int); 123159967Sobrien#endif 124159952Sobrien 125159952Sobrien#ifdef NFE_DEBUG 126159952Sobrienint nfedebug = 0; 127163503Sobrien#define DPRINTF(x) do { if (nfedebug) printf x; } while (0) 128163503Sobrien#define DPRINTFN(n,x) do { if (nfedebug >= (n)) printf x; } while (0) 129159952Sobrien#else 130163503Sobrien#define DPRINTF(x) 131163503Sobrien#define DPRINTFN(n,x) 132159952Sobrien#endif 133159952Sobrien 134159967Sobrien#define NFE_LOCK(_sc) mtx_lock(&(_sc)->nfe_mtx) 135159967Sobrien#define NFE_UNLOCK(_sc) mtx_unlock(&(_sc)->nfe_mtx) 136159967Sobrien#define NFE_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->nfe_mtx, MA_OWNED) 137159967Sobrien 138163503Sobrien#define letoh16(x) le16toh(x) 139159967Sobrien 140159967Sobrien#define NV_RID 0x10 141159967Sobrien 142159967Sobrienstatic device_method_t nfe_methods[] = { 143159967Sobrien /* Device interface */ 144159967Sobrien DEVMETHOD(device_probe, nfe_probe), 145159967Sobrien DEVMETHOD(device_attach, nfe_attach), 146159967Sobrien DEVMETHOD(device_detach, nfe_detach), 147159967Sobrien DEVMETHOD(device_shutdown, nfe_shutdown), 148159967Sobrien 149159967Sobrien /* bus interface */ 150159967Sobrien DEVMETHOD(bus_print_child, bus_generic_print_child), 151159967Sobrien DEVMETHOD(bus_driver_added, bus_generic_driver_added), 152159967Sobrien 153159967Sobrien /* MII interface */ 154159967Sobrien DEVMETHOD(miibus_readreg, nfe_miibus_readreg), 155159967Sobrien DEVMETHOD(miibus_writereg, nfe_miibus_writereg), 156163503Sobrien DEVMETHOD(miibus_statchg, nfe_miibus_statchg), 157159967Sobrien 158159967Sobrien { 0, 0 } 159159952Sobrien}; 160159952Sobrien 161159967Sobrienstatic driver_t nfe_driver = { 162159967Sobrien "nfe", 163159967Sobrien nfe_methods, 164159967Sobrien sizeof(struct nfe_softc) 165159967Sobrien}; 166159967Sobrien 167159967Sobrienstatic devclass_t nfe_devclass; 168159967Sobrien 169159967SobrienDRIVER_MODULE(nfe, pci, nfe_driver, nfe_devclass, 0, 0); 170159967SobrienDRIVER_MODULE(miibus, nfe, miibus_driver, miibus_devclass, 0, 0); 171159967Sobrien 172159967Sobrienstatic struct nfe_type nfe_devs[] = { 173159967Sobrien {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE_LAN, 174163503Sobrien "NVIDIA nForce MCP Networking Adapter"}, 175159967Sobrien {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE2_LAN, 176163503Sobrien "NVIDIA nForce2 MCP2 Networking Adapter"}, 177159967Sobrien {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE2_400_LAN1, 178163503Sobrien "NVIDIA nForce2 400 MCP4 Networking Adapter"}, 179159967Sobrien {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE2_400_LAN2, 180163503Sobrien "NVIDIA nForce2 400 MCP5 Networking Adapter"}, 181163437Sobrien {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE3_LAN1, 182163503Sobrien "NVIDIA nForce3 MCP3 Networking Adapter"}, 183159967Sobrien {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE3_250_LAN, 184163503Sobrien "NVIDIA nForce3 250 MCP6 Networking Adapter"}, 185159967Sobrien {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE3_LAN4, 186163503Sobrien "NVIDIA nForce3 MCP7 Networking Adapter"}, 187159967Sobrien {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE4_LAN1, 188163503Sobrien "NVIDIA nForce4 CK804 MCP8 Networking Adapter"}, 189159967Sobrien {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE4_LAN2, 190163503Sobrien "NVIDIA nForce4 CK804 MCP9 Networking Adapter"}, 191159967Sobrien {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP04_LAN1, 192163503Sobrien "NVIDIA nForce MCP04 Networking Adapter"}, // MCP10 193159967Sobrien {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP04_LAN2, 194163503Sobrien "NVIDIA nForce MCP04 Networking Adapter"}, // MCP11 195159967Sobrien {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE430_LAN1, 196163503Sobrien "NVIDIA nForce 430 MCP12 Networking Adapter"}, 197159967Sobrien {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE430_LAN2, 198163503Sobrien "NVIDIA nForce 430 MCP13 Networking Adapter"}, 199159967Sobrien {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP55_LAN1, 200163503Sobrien "NVIDIA nForce MCP55 Networking Adapter"}, 201159967Sobrien {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP55_LAN2, 202163503Sobrien "NVIDIA nForce MCP55 Networking Adapter"}, 203162212Sobrien {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP61_LAN1, 204163503Sobrien "NVIDIA nForce MCP61 Networking Adapter"}, 205162212Sobrien {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP61_LAN2, 206163503Sobrien "NVIDIA nForce MCP61 Networking Adapter"}, 207162212Sobrien {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP61_LAN3, 208163503Sobrien "NVIDIA nForce MCP61 Networking Adapter"}, 209162212Sobrien {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP61_LAN2, 210163503Sobrien "NVIDIA nForce MCP61 Networking Adapter"}, 211162212Sobrien {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP65_LAN1, 212163503Sobrien "NVIDIA nForce MCP65 Networking Adapter"}, 213162212Sobrien {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP65_LAN2, 214163503Sobrien "NVIDIA nForce MCP65 Networking Adapter"}, 215162212Sobrien {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP65_LAN3, 216163503Sobrien "NVIDIA nForce MCP65 Networking Adapter"}, 217162212Sobrien {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP65_LAN2, 218163503Sobrien "NVIDIA nForce MCP65 Networking Adapter"}, 219159967Sobrien {0, 0, NULL} 220159967Sobrien}; 221159967Sobrien 222159967Sobrien 223159967Sobrien/* Probe for supported hardware ID's */ 224159967Sobrienstatic int 225159967Sobriennfe_probe(device_t dev) 226159952Sobrien{ 227159967Sobrien struct nfe_type *t; 228159967Sobrien 229159967Sobrien t = nfe_devs; 230159967Sobrien /* Check for matching PCI DEVICE ID's */ 231159967Sobrien while (t->name != NULL) { 232159967Sobrien if ((pci_get_vendor(dev) == t->vid_id) && 233159967Sobrien (pci_get_device(dev) == t->dev_id)) { 234159967Sobrien device_set_desc(dev, t->name); 235159967Sobrien return (0); 236159967Sobrien } 237159967Sobrien t++; 238159967Sobrien } 239159967Sobrien 240159967Sobrien return (ENXIO); 241159952Sobrien} 242159952Sobrien 243163503Sobrien 244159967Sobrienstatic int 245159967Sobriennfe_attach(device_t dev) 246159952Sobrien{ 247159967Sobrien struct nfe_softc *sc; 248159952Sobrien struct ifnet *ifp; 249159967Sobrien int unit, error = 0, rid; 250159952Sobrien 251159967Sobrien sc = device_get_softc(dev); 252159967Sobrien unit = device_get_unit(dev); 253159967Sobrien sc->nfe_dev = dev; 254159967Sobrien sc->nfe_unit = unit; 255159952Sobrien 256159967Sobrien mtx_init(&sc->nfe_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK, 257159967Sobrien MTX_DEF | MTX_RECURSE); 258159967Sobrien callout_init_mtx(&sc->nfe_stat_ch, &sc->nfe_mtx, 0); 259159967Sobrien 260163503Sobrien pci_enable_busmaster(dev); 261159967Sobrien 262159967Sobrien rid = NV_RID; 263159967Sobrien sc->nfe_res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, 264159967Sobrien 0, ~0, 1, RF_ACTIVE); 265159967Sobrien 266159967Sobrien if (sc->nfe_res == NULL) { 267159967Sobrien printf ("nfe%d: couldn't map ports/memory\n", unit); 268159967Sobrien error = ENXIO; 269159967Sobrien goto fail; 270159952Sobrien } 271159952Sobrien 272159967Sobrien sc->nfe_memt = rman_get_bustag(sc->nfe_res); 273159967Sobrien sc->nfe_memh = rman_get_bushandle(sc->nfe_res); 274159967Sobrien 275159967Sobrien /* Allocate interrupt */ 276159967Sobrien rid = 0; 277159967Sobrien sc->nfe_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 278159967Sobrien 0, ~0, 1, RF_SHAREABLE | RF_ACTIVE); 279159967Sobrien 280159967Sobrien if (sc->nfe_irq == NULL) { 281159967Sobrien printf("nfe%d: couldn't map interrupt\n", unit); 282159967Sobrien error = ENXIO; 283159967Sobrien goto fail; 284159952Sobrien } 285159952Sobrien 286159967Sobrien nfe_get_macaddr(sc, sc->eaddr); 287159952Sobrien 288159967Sobrien sc->nfe_flags = 0; 289159952Sobrien 290159967Sobrien switch (pci_get_device(dev)) { 291159952Sobrien case PCI_PRODUCT_NVIDIA_NFORCE3_LAN2: 292159952Sobrien case PCI_PRODUCT_NVIDIA_NFORCE3_LAN3: 293159952Sobrien case PCI_PRODUCT_NVIDIA_NFORCE3_LAN4: 294159952Sobrien case PCI_PRODUCT_NVIDIA_NFORCE3_LAN5: 295159967Sobrien sc->nfe_flags |= NFE_JUMBO_SUP | NFE_HW_CSUM; 296159952Sobrien break; 297159952Sobrien case PCI_PRODUCT_NVIDIA_MCP51_LAN1: 298159952Sobrien case PCI_PRODUCT_NVIDIA_MCP51_LAN2: 299159967Sobrien sc->nfe_flags |= NFE_40BIT_ADDR; 300159952Sobrien break; 301159952Sobrien case PCI_PRODUCT_NVIDIA_CK804_LAN1: 302159952Sobrien case PCI_PRODUCT_NVIDIA_CK804_LAN2: 303159952Sobrien case PCI_PRODUCT_NVIDIA_MCP04_LAN1: 304159952Sobrien case PCI_PRODUCT_NVIDIA_MCP04_LAN2: 305159967Sobrien sc->nfe_flags |= NFE_JUMBO_SUP | NFE_40BIT_ADDR | NFE_HW_CSUM; 306159952Sobrien break; 307159952Sobrien case PCI_PRODUCT_NVIDIA_MCP55_LAN1: 308159952Sobrien case PCI_PRODUCT_NVIDIA_MCP55_LAN2: 309163503Sobrien sc->nfe_flags |= NFE_JUMBO_SUP | NFE_40BIT_ADDR | NFE_HW_CSUM | 310163503Sobrien NFE_HW_VLAN; 311159952Sobrien break; 312162212Sobrien case PCI_PRODUCT_NVIDIA_MCP61_LAN1: 313162212Sobrien case PCI_PRODUCT_NVIDIA_MCP61_LAN2: 314162212Sobrien case PCI_PRODUCT_NVIDIA_MCP61_LAN3: 315162212Sobrien case PCI_PRODUCT_NVIDIA_MCP61_LAN4: 316162212Sobrien sc->nfe_flags |= NFE_40BIT_ADDR; 317162212Sobrien break; 318162212Sobrien case PCI_PRODUCT_NVIDIA_MCP65_LAN1: 319162212Sobrien case PCI_PRODUCT_NVIDIA_MCP65_LAN2: 320162212Sobrien case PCI_PRODUCT_NVIDIA_MCP65_LAN3: 321162212Sobrien case PCI_PRODUCT_NVIDIA_MCP65_LAN4: 322162212Sobrien sc->nfe_flags |= NFE_JUMBO_SUP | NFE_40BIT_ADDR | NFE_HW_CSUM; 323163503Sobrien break; 324159952Sobrien } 325159952Sobrien 326159952Sobrien#ifndef NFE_NO_JUMBO 327159952Sobrien /* enable jumbo frames for adapters that support it */ 328159967Sobrien if (sc->nfe_flags & NFE_JUMBO_SUP) 329159967Sobrien sc->nfe_flags |= NFE_USE_JUMBO; 330159952Sobrien#endif 331159952Sobrien 332159952Sobrien /* 333159967Sobrien * Allocate the parent bus DMA tag appropriate for PCI. 334159967Sobrien */ 335163503Sobrien#define NFE_NSEG_NEW 32 336159967Sobrien error = bus_dma_tag_create(NULL, /* parent */ 337163503Sobrien 1, 0, /* alignment, boundary */ 338163503Sobrien BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 339163503Sobrien BUS_SPACE_MAXADDR, /* highaddr */ 340163503Sobrien NULL, NULL, /* filter, filterarg */ 341163503Sobrien MAXBSIZE, NFE_NSEG_NEW, /* maxsize, nsegments */ 342163503Sobrien BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ 343163503Sobrien BUS_DMA_ALLOCNOW, /* flags */ 344163503Sobrien NULL, NULL, /* lockfunc, lockarg */ 345163503Sobrien &sc->nfe_parent_tag); 346159967Sobrien if (error) 347159967Sobrien goto fail; 348159967Sobrien 349159967Sobrien /* 350159952Sobrien * Allocate Tx and Rx rings. 351159952Sobrien */ 352159952Sobrien if (nfe_alloc_tx_ring(sc, &sc->txq) != 0) { 353159967Sobrien printf("nfe%d: could not allocate Tx ring\n", unit); 354159967Sobrien error = ENXIO; 355159967Sobrien goto fail; 356159952Sobrien } 357159952Sobrien 358159952Sobrien if (nfe_alloc_rx_ring(sc, &sc->rxq) != 0) { 359159967Sobrien printf("nfe%d: could not allocate Rx ring\n", unit); 360159952Sobrien nfe_free_tx_ring(sc, &sc->txq); 361159967Sobrien error = ENXIO; 362159967Sobrien goto fail; 363159952Sobrien } 364159952Sobrien 365159967Sobrien ifp = sc->nfe_ifp = if_alloc(IFT_ETHER); 366159967Sobrien if (ifp == NULL) { 367159967Sobrien printf("nfe%d: can not if_alloc()\n", unit); 368159967Sobrien error = ENOSPC; 369159967Sobrien goto fail; 370159967Sobrien } 371159967Sobrien 372159952Sobrien ifp->if_softc = sc; 373159967Sobrien if_initname(ifp, device_get_name(dev), device_get_unit(dev)); 374159967Sobrien ifp->if_mtu = ETHERMTU; 375159952Sobrien ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 376159952Sobrien ifp->if_ioctl = nfe_ioctl; 377159952Sobrien ifp->if_start = nfe_start; 378159967Sobrien /* ifp->if_hwassist = NFE_CSUM_FEATURES; */ 379159952Sobrien ifp->if_watchdog = nfe_watchdog; 380159952Sobrien ifp->if_init = nfe_init; 381159952Sobrien ifp->if_baudrate = IF_Gbps(1); 382159967Sobrien ifp->if_snd.ifq_maxlen = NFE_IFQ_MAXLEN; 383159952Sobrien 384159952Sobrien ifp->if_capabilities = IFCAP_VLAN_MTU; 385159952Sobrien#if NVLAN > 0 386159967Sobrien if (sc->nfe_flags & NFE_HW_VLAN) 387159952Sobrien ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING; 388159952Sobrien#endif 389159952Sobrien#ifdef NFE_CSUM 390159967Sobrien if (sc->nfe_flags & NFE_HW_CSUM) { 391159967Sobrien ifp->if_capabilities |= IFCAP_HWCSUM; 392159952Sobrien } 393159952Sobrien#endif 394159967Sobrien ifp->if_capenable = ifp->if_capabilities; 395159952Sobrien 396159967Sobrien#ifdef DEVICE_POLLING 397159967Sobrien ifp->if_capabilities |= IFCAP_POLLING; 398159967Sobrien#endif 399159952Sobrien 400159967Sobrien /* Do MII setup */ 401163503Sobrien if (mii_phy_probe(dev, &sc->nfe_miibus, nfe_ifmedia_upd, 402163503Sobrien nfe_ifmedia_sts)) { 403159967Sobrien printf("nfe%d: MII without any phy!\n", unit); 404159967Sobrien error = ENXIO; 405159967Sobrien goto fail; 406159967Sobrien } 407159952Sobrien 408159967Sobrien ether_ifattach(ifp, sc->eaddr); 409159952Sobrien 410163503Sobrien error = bus_setup_intr(dev, sc->nfe_irq, INTR_TYPE_NET | INTR_MPSAFE, 411159967Sobrien nfe_intr, sc, &sc->nfe_intrhand); 412159952Sobrien 413159967Sobrien if (error) { 414159967Sobrien printf("nfe%d: couldn't set up irq\n", unit); 415159967Sobrien ether_ifdetach(ifp); 416159967Sobrien goto fail; 417159967Sobrien } 418159967Sobrien 419159967Sobrienfail: 420159967Sobrien if (error) 421159967Sobrien nfe_detach(dev); 422159967Sobrien 423159967Sobrien return (error); 424159952Sobrien} 425159952Sobrien 426159967Sobrien 427159967Sobrienstatic int 428159967Sobriennfe_detach(device_t dev) 429159952Sobrien{ 430163503Sobrien struct nfe_softc *sc; 431163503Sobrien struct ifnet *ifp; 432163503Sobrien u_char eaddr[ETHER_ADDR_LEN]; 433163503Sobrien int i; 434159952Sobrien 435159967Sobrien sc = device_get_softc(dev); 436159967Sobrien KASSERT(mtx_initialized(&sc->nfe_mtx), ("nfe mutex not initialized")); 437159967Sobrien ifp = sc->nfe_ifp; 438159967Sobrien 439159967Sobrien#ifdef DEVICE_POLLING 440159967Sobrien if (ifp->if_capenable & IFCAP_POLLING) 441159967Sobrien ether_poll_deregister(ifp); 442159967Sobrien#endif 443159967Sobrien 444159967Sobrien for (i = 0; i < ETHER_ADDR_LEN; i++) { 445159967Sobrien eaddr[i] = sc->eaddr[5 - i]; 446159952Sobrien } 447159967Sobrien nfe_set_macaddr(sc, eaddr); 448159967Sobrien 449159967Sobrien if (device_is_attached(dev)) { 450159967Sobrien nfe_stop(ifp, 1); 451159967Sobrien ifp->if_flags &= ~IFF_UP; 452159967Sobrien callout_drain(&sc->nfe_stat_ch); 453159967Sobrien ether_ifdetach(ifp); 454159967Sobrien } 455159967Sobrien 456159967Sobrien if (ifp) 457159967Sobrien if_free(ifp); 458159967Sobrien if (sc->nfe_miibus) 459159967Sobrien device_delete_child(dev, sc->nfe_miibus); 460159967Sobrien bus_generic_detach(dev); 461159967Sobrien 462159967Sobrien if (sc->nfe_intrhand) 463159967Sobrien bus_teardown_intr(dev, sc->nfe_irq, sc->nfe_intrhand); 464159967Sobrien if (sc->nfe_irq) 465159967Sobrien bus_release_resource(dev, SYS_RES_IRQ, 0, sc->nfe_irq); 466159967Sobrien if (sc->nfe_res) 467159967Sobrien bus_release_resource(dev, SYS_RES_MEMORY, NV_RID, sc->nfe_res); 468159967Sobrien 469159967Sobrien nfe_free_tx_ring(sc, &sc->txq); 470159967Sobrien nfe_free_rx_ring(sc, &sc->rxq); 471159967Sobrien 472159967Sobrien if (sc->nfe_parent_tag) 473159967Sobrien bus_dma_tag_destroy(sc->nfe_parent_tag); 474159967Sobrien 475159967Sobrien mtx_destroy(&sc->nfe_mtx); 476159967Sobrien 477159967Sobrien return (0); 478159952Sobrien} 479159952Sobrien 480159967Sobrien 481159967Sobrienstatic void 482159967Sobriennfe_miibus_statchg(device_t dev) 483159952Sobrien{ 484159967Sobrien struct nfe_softc *sc; 485159967Sobrien struct mii_data *mii; 486159967Sobrien u_int32_t phy, seed, misc = NFE_MISC1_MAGIC, link = NFE_MEDIA_SET; 487159952Sobrien 488159967Sobrien sc = device_get_softc(dev); 489159967Sobrien mii = device_get_softc(sc->nfe_miibus); 490159967Sobrien 491159952Sobrien phy = NFE_READ(sc, NFE_PHY_IFACE); 492159952Sobrien phy &= ~(NFE_PHY_HDX | NFE_PHY_100TX | NFE_PHY_1000T); 493159952Sobrien 494159952Sobrien seed = NFE_READ(sc, NFE_RNDSEED); 495159952Sobrien seed &= ~NFE_SEED_MASK; 496159952Sobrien 497159952Sobrien if ((mii->mii_media_active & IFM_GMASK) == IFM_HDX) { 498159952Sobrien phy |= NFE_PHY_HDX; /* half-duplex */ 499159952Sobrien misc |= NFE_MISC1_HDX; 500159952Sobrien } 501159952Sobrien 502159952Sobrien switch (IFM_SUBTYPE(mii->mii_media_active)) { 503159952Sobrien case IFM_1000_T: /* full-duplex only */ 504159952Sobrien link |= NFE_MEDIA_1000T; 505159952Sobrien seed |= NFE_SEED_1000T; 506159952Sobrien phy |= NFE_PHY_1000T; 507159952Sobrien break; 508159952Sobrien case IFM_100_TX: 509159952Sobrien link |= NFE_MEDIA_100TX; 510159952Sobrien seed |= NFE_SEED_100TX; 511159952Sobrien phy |= NFE_PHY_100TX; 512159952Sobrien break; 513159952Sobrien case IFM_10_T: 514159952Sobrien link |= NFE_MEDIA_10T; 515159952Sobrien seed |= NFE_SEED_10T; 516159952Sobrien break; 517159952Sobrien } 518159952Sobrien 519159952Sobrien NFE_WRITE(sc, NFE_RNDSEED, seed); /* XXX: gigabit NICs only? */ 520159952Sobrien 521159952Sobrien NFE_WRITE(sc, NFE_PHY_IFACE, phy); 522159952Sobrien NFE_WRITE(sc, NFE_MISC1, misc); 523159952Sobrien NFE_WRITE(sc, NFE_LINKSPEED, link); 524159952Sobrien} 525159952Sobrien 526163503Sobrien 527159967Sobrienstatic int 528159967Sobriennfe_miibus_readreg(device_t dev, int phy, int reg) 529159952Sobrien{ 530159967Sobrien struct nfe_softc *sc = device_get_softc(dev); 531159967Sobrien u_int32_t val; 532159952Sobrien int ntries; 533159952Sobrien 534159952Sobrien NFE_WRITE(sc, NFE_PHY_STATUS, 0xf); 535159952Sobrien 536159952Sobrien if (NFE_READ(sc, NFE_PHY_CTL) & NFE_PHY_BUSY) { 537159952Sobrien NFE_WRITE(sc, NFE_PHY_CTL, NFE_PHY_BUSY); 538159952Sobrien DELAY(100); 539159952Sobrien } 540159952Sobrien 541159952Sobrien NFE_WRITE(sc, NFE_PHY_CTL, (phy << NFE_PHYADD_SHIFT) | reg); 542159952Sobrien 543159952Sobrien for (ntries = 0; ntries < 1000; ntries++) { 544159952Sobrien DELAY(100); 545159952Sobrien if (!(NFE_READ(sc, NFE_PHY_CTL) & NFE_PHY_BUSY)) 546159952Sobrien break; 547159952Sobrien } 548159952Sobrien if (ntries == 1000) { 549159967Sobrien DPRINTFN(2, ("nfe%d: timeout waiting for PHY\n", sc->nfe_unit)); 550159952Sobrien return 0; 551159952Sobrien } 552159952Sobrien 553159952Sobrien if (NFE_READ(sc, NFE_PHY_STATUS) & NFE_PHY_ERROR) { 554159967Sobrien DPRINTFN(2, ("nfe%d: could not read PHY\n", sc->nfe_unit)); 555159952Sobrien return 0; 556159952Sobrien } 557159952Sobrien 558159952Sobrien val = NFE_READ(sc, NFE_PHY_DATA); 559159952Sobrien if (val != 0xffffffff && val != 0) 560159952Sobrien sc->mii_phyaddr = phy; 561159952Sobrien 562163503Sobrien DPRINTFN(2, ("nfe%d: mii read phy %d reg 0x%x ret 0x%x\n", 563163503Sobrien sc->nfe_unit, phy, reg, val)); 564159952Sobrien 565159952Sobrien return val; 566159952Sobrien} 567159952Sobrien 568163503Sobrien 569159967Sobrienstatic int 570159967Sobriennfe_miibus_writereg(device_t dev, int phy, int reg, int val) 571159952Sobrien{ 572159967Sobrien struct nfe_softc *sc = device_get_softc(dev); 573159967Sobrien u_int32_t ctl; 574163503Sobrien int ntries; 575159952Sobrien 576159952Sobrien NFE_WRITE(sc, NFE_PHY_STATUS, 0xf); 577159952Sobrien 578159952Sobrien if (NFE_READ(sc, NFE_PHY_CTL) & NFE_PHY_BUSY) { 579159952Sobrien NFE_WRITE(sc, NFE_PHY_CTL, NFE_PHY_BUSY); 580159952Sobrien DELAY(100); 581159952Sobrien } 582159952Sobrien 583159952Sobrien NFE_WRITE(sc, NFE_PHY_DATA, val); 584159952Sobrien ctl = NFE_PHY_WRITE | (phy << NFE_PHYADD_SHIFT) | reg; 585159952Sobrien NFE_WRITE(sc, NFE_PHY_CTL, ctl); 586159952Sobrien 587159952Sobrien for (ntries = 0; ntries < 1000; ntries++) { 588159952Sobrien DELAY(100); 589159952Sobrien if (!(NFE_READ(sc, NFE_PHY_CTL) & NFE_PHY_BUSY)) 590159952Sobrien break; 591159952Sobrien } 592159952Sobrien#ifdef NFE_DEBUG 593159952Sobrien if (nfedebug >= 2 && ntries == 1000) 594159952Sobrien printf("could not write to PHY\n"); 595159952Sobrien#endif 596159967Sobrien return 0; 597159952Sobrien} 598159952Sobrien 599163503Sobrien 600159967Sobrienstatic int 601159967Sobriennfe_alloc_rx_ring(struct nfe_softc *sc, struct nfe_rx_ring *ring) 602159952Sobrien{ 603159967Sobrien struct nfe_desc32 *desc32; 604159967Sobrien struct nfe_desc64 *desc64; 605159967Sobrien struct nfe_rx_data *data; 606159967Sobrien struct nfe_jbuf *jbuf; 607159967Sobrien void **desc; 608159967Sobrien bus_addr_t physaddr; 609159967Sobrien int i, error, descsize; 610159967Sobrien 611159967Sobrien if (sc->nfe_flags & NFE_40BIT_ADDR) { 612159967Sobrien desc = (void **)&ring->desc64; 613159967Sobrien descsize = sizeof (struct nfe_desc64); 614159967Sobrien } else { 615159967Sobrien desc = (void **)&ring->desc32; 616159967Sobrien descsize = sizeof (struct nfe_desc32); 617159967Sobrien } 618159967Sobrien 619159967Sobrien ring->cur = ring->next = 0; 620159967Sobrien ring->bufsz = MCLBYTES; 621159967Sobrien 622163503Sobrien error = bus_dma_tag_create(sc->nfe_parent_tag, 623163503Sobrien PAGE_SIZE, 0, /* alignment, boundary */ 624163503Sobrien BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 625163503Sobrien BUS_SPACE_MAXADDR, /* highaddr */ 626163503Sobrien NULL, NULL, /* filter, filterarg */ 627163503Sobrien NFE_RX_RING_COUNT * descsize, 1, /* maxsize, nsegments */ 628163503Sobrien NFE_RX_RING_COUNT * descsize, /* maxsegsize */ 629163503Sobrien BUS_DMA_ALLOCNOW, /* flags */ 630163503Sobrien NULL, NULL, /* lockfunc, lockarg */ 631163503Sobrien &ring->rx_desc_tag); 632159967Sobrien if (error != 0) { 633159967Sobrien printf("nfe%d: could not create desc DMA tag\n", sc->nfe_unit); 634159967Sobrien goto fail; 635159967Sobrien } 636159967Sobrien 637159967Sobrien /* allocate memory to desc */ 638163503Sobrien error = bus_dmamem_alloc(ring->rx_desc_tag, (void **)desc, 639163503Sobrien BUS_DMA_NOWAIT, &ring->rx_desc_map); 640159967Sobrien if (error != 0) { 641159967Sobrien printf("nfe%d: could not create desc DMA map\n", sc->nfe_unit); 642159967Sobrien goto fail; 643159967Sobrien } 644159967Sobrien 645159967Sobrien /* map desc to device visible address space */ 646159967Sobrien error = bus_dmamap_load(ring->rx_desc_tag, ring->rx_desc_map, *desc, 647163503Sobrien NFE_RX_RING_COUNT * descsize, nfe_dma_map_segs, 648163503Sobrien &ring->rx_desc_segs, BUS_DMA_NOWAIT); 649159967Sobrien if (error != 0) { 650159967Sobrien printf("nfe%d: could not load desc DMA map\n", sc->nfe_unit); 651159967Sobrien goto fail; 652159967Sobrien } 653159967Sobrien 654159967Sobrien bzero(*desc, NFE_RX_RING_COUNT * descsize); 655159967Sobrien ring->rx_desc_addr = ring->rx_desc_segs.ds_addr; 656159967Sobrien ring->physaddr = ring->rx_desc_addr; 657159967Sobrien 658159967Sobrien if (sc->nfe_flags & NFE_USE_JUMBO) { 659159967Sobrien ring->bufsz = NFE_JBYTES; 660159967Sobrien if ((error = nfe_jpool_alloc(sc)) != 0) { 661163503Sobrien printf("nfe%d: could not allocate jumbo frames\n", 662163503Sobrien sc->nfe_unit); 663159967Sobrien goto fail; 664159967Sobrien } 665159967Sobrien } 666159967Sobrien 667159967Sobrien /* 668159967Sobrien * Pre-allocate Rx buffers and populate Rx ring. 669159967Sobrien */ 670159967Sobrien for (i = 0; i < NFE_RX_RING_COUNT; i++) { 671159967Sobrien data = &sc->rxq.data[i]; 672159967Sobrien 673159967Sobrien MGETHDR(data->m, M_DONTWAIT, MT_DATA); 674159967Sobrien if (data->m == NULL) { 675163503Sobrien printf("nfe%d: could not allocate rx mbuf\n", 676163503Sobrien sc->nfe_unit); 677159967Sobrien error = ENOMEM; 678159967Sobrien goto fail; 679159967Sobrien } 680159967Sobrien 681159967Sobrien if (sc->nfe_flags & NFE_USE_JUMBO) { 682159967Sobrien if ((jbuf = nfe_jalloc(sc)) == NULL) { 683163503Sobrien printf("nfe%d: could not allocate jumbo buffer\n", 684163503Sobrien sc->nfe_unit); 685159967Sobrien goto fail; 686159967Sobrien } 687159967Sobrien data->m->m_data = (void *)jbuf->buf; 688159967Sobrien data->m->m_len = data->m->m_pkthdr.len = NFE_JBYTES; 689163503Sobrien MEXTADD(data->m, jbuf->buf, NFE_JBYTES, nfe_jfree, 690163503Sobrien (struct nfe_softc *)sc, 0, EXT_NET_DRV); 691159967Sobrien /* m_adj(data->m, ETHER_ALIGN); */ 692159967Sobrien physaddr = jbuf->physaddr; 693159967Sobrien } else { 694163503Sobrien error = bus_dma_tag_create(sc->nfe_parent_tag, 695163503Sobrien ETHER_ALIGN, 0, /* alignment, boundary */ 696163503Sobrien BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 697163503Sobrien BUS_SPACE_MAXADDR, /* highaddr */ 698163503Sobrien NULL, NULL, /* filter, filterarg */ 699163503Sobrien MCLBYTES, 1, /* maxsize, nsegments */ 700163503Sobrien MCLBYTES, /* maxsegsize */ 701163503Sobrien BUS_DMA_ALLOCNOW, /* flags */ 702163503Sobrien NULL, NULL, /* lockfunc, lockarg */ 703163503Sobrien &data->rx_data_tag); 704163503Sobrien if (error != 0) { 705163503Sobrien printf("nfe%d: could not create DMA map\n", 706163503Sobrien sc->nfe_unit); 707163503Sobrien goto fail; 708163503Sobrien } 709159967Sobrien 710163503Sobrien error = bus_dmamap_create(data->rx_data_tag, 0, 711163503Sobrien &data->rx_data_map); 712163503Sobrien if (error != 0) { 713163503Sobrien printf("nfe%d: could not allocate mbuf cluster\n", 714163503Sobrien sc->nfe_unit); 715163503Sobrien goto fail; 716163503Sobrien } 717159967Sobrien 718163503Sobrien MCLGET(data->m, M_DONTWAIT); 719163503Sobrien if (!(data->m->m_flags & M_EXT)) { 720163503Sobrien error = ENOMEM; 721163503Sobrien goto fail; 722163503Sobrien } 723159967Sobrien 724163503Sobrien error = bus_dmamap_load(data->rx_data_tag, 725163503Sobrien data->rx_data_map, mtod(data->m, void *), MCLBYTES, 726163503Sobrien nfe_dma_map_segs, &data->rx_data_segs, 727163503Sobrien BUS_DMA_NOWAIT); 728163503Sobrien if (error != 0) { 729163503Sobrien printf("nfe%d: could not load rx buf DMA map\n", 730163503Sobrien sc->nfe_unit); 731163503Sobrien goto fail; 732163503Sobrien } 733159967Sobrien 734163503Sobrien data->rx_data_addr = data->rx_data_segs.ds_addr; 735163503Sobrien physaddr = data->rx_data_addr; 736159967Sobrien 737159967Sobrien } 738159967Sobrien 739159967Sobrien if (sc->nfe_flags & NFE_40BIT_ADDR) { 740159967Sobrien desc64 = &sc->rxq.desc64[i]; 741159967Sobrien#if defined(__LP64__) 742159967Sobrien desc64->physaddr[0] = htole32(physaddr >> 32); 743159967Sobrien#endif 744159967Sobrien desc64->physaddr[1] = htole32(physaddr & 0xffffffff); 745159967Sobrien desc64->length = htole16(sc->rxq.bufsz); 746159967Sobrien desc64->flags = htole16(NFE_RX_READY); 747159967Sobrien } else { 748159967Sobrien desc32 = &sc->rxq.desc32[i]; 749159967Sobrien desc32->physaddr = htole32(physaddr); 750159967Sobrien desc32->length = htole16(sc->rxq.bufsz); 751159967Sobrien desc32->flags = htole16(NFE_RX_READY); 752159967Sobrien } 753159967Sobrien 754159967Sobrien } 755159967Sobrien 756163503Sobrien bus_dmamap_sync(ring->rx_desc_tag, ring->rx_desc_map, 757163503Sobrien BUS_DMASYNC_PREWRITE); 758159967Sobrien 759159967Sobrien return 0; 760159967Sobrien 761159967Sobrienfail: nfe_free_rx_ring(sc, ring); 762159967Sobrien 763159967Sobrien return error; 764159967Sobrien} 765159967Sobrien 766163503Sobrien 767159967Sobrienstatic int 768159967Sobriennfe_jpool_alloc(struct nfe_softc *sc) 769159967Sobrien{ 770159967Sobrien struct nfe_rx_ring *ring = &sc->rxq; 771159967Sobrien struct nfe_jbuf *jbuf; 772159967Sobrien bus_addr_t physaddr; 773159967Sobrien caddr_t buf; 774159967Sobrien int i, error; 775159967Sobrien 776159967Sobrien /* 777159967Sobrien * Allocate a big chunk of DMA'able memory. 778159967Sobrien */ 779163503Sobrien error = bus_dma_tag_create(sc->nfe_parent_tag, 780163503Sobrien PAGE_SIZE, 0, /* alignment, boundary */ 781163503Sobrien BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 782163503Sobrien BUS_SPACE_MAXADDR, /* highaddr */ 783163503Sobrien NULL, NULL, /* filter, filterarg */ 784163503Sobrien NFE_JPOOL_SIZE, 1, /* maxsize, nsegments */ 785163503Sobrien NFE_JPOOL_SIZE, /* maxsegsize */ 786163503Sobrien BUS_DMA_ALLOCNOW, /* flags */ 787163503Sobrien NULL, NULL, /* lockfunc, lockarg */ 788163503Sobrien &ring->rx_jumbo_tag); 789159967Sobrien if (error != 0) { 790159967Sobrien printf("nfe%d: could not create jumbo DMA tag\n", sc->nfe_unit); 791159967Sobrien goto fail; 792159967Sobrien } 793163503Sobrien 794163503Sobrien error = bus_dmamem_alloc(ring->rx_jumbo_tag, (void **)&ring->jpool, 795163503Sobrien BUS_DMA_NOWAIT, &ring->rx_jumbo_map); 796159967Sobrien if (error != 0) { 797163503Sobrien printf("nfe%d: could not create jumbo DMA memory\n", 798163503Sobrien sc->nfe_unit); 799159967Sobrien goto fail; 800159967Sobrien } 801159967Sobrien 802163503Sobrien error = bus_dmamap_load(ring->rx_jumbo_tag, ring->rx_jumbo_map, 803163503Sobrien ring->jpool, NFE_JPOOL_SIZE, nfe_dma_map_segs, &ring->rx_jumbo_segs, 804163503Sobrien BUS_DMA_NOWAIT); 805159967Sobrien if (error != 0) { 806159967Sobrien printf("nfe%d: could not load jumbo DMA map\n", sc->nfe_unit); 807159967Sobrien goto fail; 808159967Sobrien } 809159967Sobrien 810159967Sobrien /* ..and split it into 9KB chunks */ 811159967Sobrien SLIST_INIT(&ring->jfreelist); 812159967Sobrien 813159967Sobrien buf = ring->jpool; 814159967Sobrien ring->rx_jumbo_addr = ring->rx_jumbo_segs.ds_addr; 815159967Sobrien physaddr = ring->rx_jumbo_addr; 816159967Sobrien 817159967Sobrien for (i = 0; i < NFE_JPOOL_COUNT; i++) { 818159967Sobrien jbuf = &ring->jbuf[i]; 819159967Sobrien 820159967Sobrien jbuf->buf = buf; 821159967Sobrien jbuf->physaddr = physaddr; 822159967Sobrien 823159967Sobrien SLIST_INSERT_HEAD(&ring->jfreelist, jbuf, jnext); 824159967Sobrien 825159967Sobrien buf += NFE_JBYTES; 826159967Sobrien physaddr += NFE_JBYTES; 827159967Sobrien } 828159967Sobrien 829159967Sobrien return 0; 830159967Sobrien 831159967Sobrienfail: nfe_jpool_free(sc); 832159967Sobrien return error; 833159967Sobrien} 834159967Sobrien 835159967Sobrien 836159967Sobrienstatic void 837159967Sobriennfe_jpool_free(struct nfe_softc *sc) 838159967Sobrien{ 839159967Sobrien struct nfe_rx_ring *ring = &sc->rxq; 840159967Sobrien 841159967Sobrien if (ring->jpool != NULL) { 842159967Sobrien#if 0 843163503Sobrien bus_dmamem_unmap(ring->rx_jumbo_tag, ring->jpool, 844163503Sobrien NFE_JPOOL_SIZE); 845159967Sobrien#endif 846163503Sobrien bus_dmamem_free(ring->rx_jumbo_tag, &ring->rx_jumbo_segs, 847163503Sobrien ring->rx_jumbo_map); 848159967Sobrien } 849159967Sobrien if (ring->rx_jumbo_map != NULL) { 850163503Sobrien bus_dmamap_sync(ring->rx_jumbo_tag, ring->rx_jumbo_map, 851163503Sobrien BUS_DMASYNC_POSTWRITE); 852159967Sobrien bus_dmamap_unload(ring->rx_jumbo_tag, ring->rx_jumbo_map); 853159967Sobrien bus_dmamap_destroy(ring->rx_jumbo_tag, ring->rx_jumbo_map); 854159967Sobrien } 855159967Sobrien} 856159967Sobrien 857163503Sobrien 858159967Sobrienstatic struct nfe_jbuf * 859159967Sobriennfe_jalloc(struct nfe_softc *sc) 860159967Sobrien{ 861159967Sobrien struct nfe_jbuf *jbuf; 862159967Sobrien 863159967Sobrien jbuf = SLIST_FIRST(&sc->rxq.jfreelist); 864159967Sobrien if (jbuf == NULL) 865159967Sobrien return NULL; 866159967Sobrien SLIST_REMOVE_HEAD(&sc->rxq.jfreelist, jnext); 867159967Sobrien return jbuf; 868159967Sobrien} 869159967Sobrien 870163503Sobrien 871159967Sobrien/* 872159967Sobrien * This is called automatically by the network stack when the mbuf is freed. 873159967Sobrien * Caution must be taken that the NIC might be reset by the time the mbuf is 874159967Sobrien * freed. 875159967Sobrien */ 876159967Sobrienstatic void 877159967Sobriennfe_jfree(void *buf, void *arg) 878159967Sobrien{ 879159952Sobrien struct nfe_softc *sc = arg; 880159967Sobrien struct nfe_jbuf *jbuf; 881159967Sobrien int i; 882159952Sobrien 883159967Sobrien /* find the jbuf from the base pointer */ 884159967Sobrien i = ((vm_offset_t)buf - (vm_offset_t)sc->rxq.jpool) / NFE_JBYTES; 885159967Sobrien if (i < 0 || i >= NFE_JPOOL_COUNT) { 886163503Sobrien printf("nfe%d: request to free a buffer (%p) not managed by us\n", 887163503Sobrien sc->nfe_unit, buf); 888159967Sobrien return; 889159967Sobrien } 890159967Sobrien jbuf = &sc->rxq.jbuf[i]; 891159952Sobrien 892159967Sobrien /* ..and put it back in the free list */ 893159967Sobrien SLIST_INSERT_HEAD(&sc->rxq.jfreelist, jbuf, jnext); 894159967Sobrien} 895159952Sobrien 896159967Sobrien 897159967Sobrienstatic void 898159967Sobriennfe_reset_rx_ring(struct nfe_softc *sc, struct nfe_rx_ring *ring) 899159967Sobrien{ 900159967Sobrien int i; 901159967Sobrien 902159967Sobrien for (i = 0; i < NFE_RX_RING_COUNT; i++) { 903159967Sobrien if (sc->nfe_flags & NFE_40BIT_ADDR) { 904159967Sobrien ring->desc64[i].length = htole16(ring->bufsz); 905159967Sobrien ring->desc64[i].flags = htole16(NFE_RX_READY); 906159967Sobrien } else { 907159967Sobrien ring->desc32[i].length = htole16(ring->bufsz); 908159967Sobrien ring->desc32[i].flags = htole16(NFE_RX_READY); 909159967Sobrien } 910159952Sobrien } 911159952Sobrien 912163503Sobrien bus_dmamap_sync(ring->rx_desc_tag, ring->rx_desc_map, 913163503Sobrien BUS_DMASYNC_PREWRITE); 914159952Sobrien 915159967Sobrien ring->cur = ring->next = 0; 916159967Sobrien} 917159967Sobrien 918159967Sobrien 919159967Sobrienstatic void 920159967Sobriennfe_free_rx_ring(struct nfe_softc *sc, struct nfe_rx_ring *ring) 921159967Sobrien{ 922159967Sobrien struct nfe_rx_data *data; 923159967Sobrien void *desc; 924159967Sobrien int i, descsize; 925159967Sobrien 926159967Sobrien if (sc->nfe_flags & NFE_40BIT_ADDR) { 927159967Sobrien desc = ring->desc64; 928159967Sobrien descsize = sizeof (struct nfe_desc64); 929159967Sobrien } else { 930159967Sobrien desc = ring->desc32; 931159967Sobrien descsize = sizeof (struct nfe_desc32); 932159952Sobrien } 933159952Sobrien 934159967Sobrien if (desc != NULL) { 935163503Sobrien bus_dmamap_sync(ring->rx_desc_tag, ring->rx_desc_map, 936163503Sobrien BUS_DMASYNC_POSTWRITE); 937159967Sobrien bus_dmamap_unload(ring->rx_desc_tag, ring->rx_desc_map); 938159967Sobrien bus_dmamem_free(ring->rx_desc_tag, desc, ring->rx_desc_map); 939159967Sobrien bus_dma_tag_destroy(ring->rx_desc_tag); 940159967Sobrien } 941159967Sobrien 942159967Sobrien if (sc->nfe_flags & NFE_USE_JUMBO) { 943163503Sobrien nfe_jpool_free(sc); 944159967Sobrien } else { 945163503Sobrien for (i = 0; i < NFE_RX_RING_COUNT; i++) { 946163503Sobrien data = &ring->data[i]; 947159967Sobrien 948163503Sobrien if (data->rx_data_map != NULL) { 949163503Sobrien bus_dmamap_sync(data->rx_data_tag, 950163503Sobrien data->rx_data_map, BUS_DMASYNC_POSTREAD); 951163503Sobrien bus_dmamap_unload(data->rx_data_tag, 952163503Sobrien data->rx_data_map); 953163503Sobrien bus_dmamap_destroy(data->rx_data_tag, 954163503Sobrien data->rx_data_map); 955163503Sobrien bus_dma_tag_destroy(data->rx_data_tag); 956163503Sobrien } 957163503Sobrien 958163503Sobrien if (data->m != NULL) 959163503Sobrien m_freem(data->m); 960163503Sobrien } 961159967Sobrien } 962159952Sobrien} 963159952Sobrien 964163503Sobrien 965159967Sobrienstatic int 966159967Sobriennfe_alloc_tx_ring(struct nfe_softc *sc, struct nfe_tx_ring *ring) 967159952Sobrien{ 968159967Sobrien int i, error; 969159967Sobrien void **desc; 970159967Sobrien int descsize; 971159952Sobrien 972159967Sobrien if (sc->nfe_flags & NFE_40BIT_ADDR) { 973159967Sobrien desc = (void **)&ring->desc64; 974159967Sobrien descsize = sizeof (struct nfe_desc64); 975159967Sobrien } else { 976159967Sobrien desc = (void **)&ring->desc32; 977159967Sobrien descsize = sizeof (struct nfe_desc32); 978159967Sobrien } 979159952Sobrien 980159967Sobrien ring->queued = 0; 981159967Sobrien ring->cur = ring->next = 0; 982159967Sobrien 983163503Sobrien error = bus_dma_tag_create(sc->nfe_parent_tag, 984163503Sobrien PAGE_SIZE, 0, /* alignment, boundary */ 985163503Sobrien BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 986163503Sobrien BUS_SPACE_MAXADDR, /* highaddr */ 987163503Sobrien NULL, NULL, /* filter, filterarg */ 988163503Sobrien NFE_TX_RING_COUNT * descsize, 1, /* maxsize, nsegments */ 989163503Sobrien NFE_TX_RING_COUNT * descsize, /* maxsegsize */ 990163503Sobrien BUS_DMA_ALLOCNOW, /* flags */ 991163503Sobrien NULL, NULL, /* lockfunc, lockarg */ 992163503Sobrien &ring->tx_desc_tag); 993159967Sobrien if (error != 0) { 994159967Sobrien printf("nfe%d: could not create desc DMA tag\n", sc->nfe_unit); 995159967Sobrien goto fail; 996159952Sobrien } 997159952Sobrien 998163503Sobrien error = bus_dmamem_alloc(ring->tx_desc_tag, (void **)desc, 999163503Sobrien BUS_DMA_NOWAIT, &ring->tx_desc_map); 1000159967Sobrien if (error != 0) { 1001159967Sobrien printf("nfe%d: could not create desc DMA map\n", sc->nfe_unit); 1002159967Sobrien goto fail; 1003159967Sobrien } 1004159967Sobrien 1005159967Sobrien error = bus_dmamap_load(ring->tx_desc_tag, ring->tx_desc_map, *desc, 1006163503Sobrien NFE_TX_RING_COUNT * descsize, nfe_dma_map_segs, &ring->tx_desc_segs, 1007163503Sobrien BUS_DMA_NOWAIT); 1008159967Sobrien if (error != 0) { 1009159967Sobrien printf("nfe%d: could not load desc DMA map\n", sc->nfe_unit); 1010159967Sobrien goto fail; 1011159967Sobrien } 1012159967Sobrien 1013159967Sobrien bzero(*desc, NFE_TX_RING_COUNT * descsize); 1014159967Sobrien 1015159967Sobrien ring->tx_desc_addr = ring->tx_desc_segs.ds_addr; 1016159967Sobrien ring->physaddr = ring->tx_desc_addr; 1017159967Sobrien 1018163503Sobrien error = bus_dma_tag_create(sc->nfe_parent_tag, 1019163503Sobrien ETHER_ALIGN, 0, 1020163503Sobrien BUS_SPACE_MAXADDR_32BIT, 1021163503Sobrien BUS_SPACE_MAXADDR, 1022163503Sobrien NULL, NULL, 1023163503Sobrien NFE_JBYTES, NFE_MAX_SCATTER, 1024163503Sobrien NFE_JBYTES, 1025163503Sobrien BUS_DMA_ALLOCNOW, 1026163503Sobrien NULL, NULL, 1027163503Sobrien &ring->tx_data_tag); 1028159967Sobrien if (error != 0) { 1029159967Sobrien printf("nfe%d: could not create DMA tag\n", sc->nfe_unit); 1030159967Sobrien goto fail; 1031159967Sobrien } 1032159967Sobrien 1033159967Sobrien for (i = 0; i < NFE_TX_RING_COUNT; i++) { 1034163503Sobrien error = bus_dmamap_create(ring->tx_data_tag, 0, 1035163503Sobrien &ring->data[i].tx_data_map); 1036159967Sobrien if (error != 0) { 1037163503Sobrien printf("nfe%d: could not create DMA map\n", 1038163503Sobrien sc->nfe_unit); 1039159967Sobrien goto fail; 1040159967Sobrien } 1041159967Sobrien } 1042159967Sobrien 1043159967Sobrien return 0; 1044159967Sobrien 1045159967Sobrienfail: nfe_free_tx_ring(sc, ring); 1046159967Sobrien return error; 1047159967Sobrien} 1048159967Sobrien 1049159967Sobrien 1050159967Sobrienstatic void 1051159967Sobriennfe_reset_tx_ring(struct nfe_softc *sc, struct nfe_tx_ring *ring) 1052159967Sobrien{ 1053159967Sobrien struct nfe_tx_data *data; 1054159967Sobrien int i; 1055159967Sobrien 1056159967Sobrien for (i = 0; i < NFE_TX_RING_COUNT; i++) { 1057159967Sobrien if (sc->nfe_flags & NFE_40BIT_ADDR) 1058159967Sobrien ring->desc64[i].flags = 0; 1059159967Sobrien else 1060159967Sobrien ring->desc32[i].flags = 0; 1061159967Sobrien 1062159967Sobrien data = &ring->data[i]; 1063159967Sobrien 1064159967Sobrien if (data->m != NULL) { 1065163503Sobrien bus_dmamap_sync(ring->tx_data_tag, data->active, 1066163503Sobrien BUS_DMASYNC_POSTWRITE); 1067159967Sobrien bus_dmamap_unload(ring->tx_data_tag, data->active); 1068159967Sobrien m_freem(data->m); 1069159967Sobrien data->m = NULL; 1070159967Sobrien } 1071159967Sobrien } 1072159967Sobrien 1073163503Sobrien bus_dmamap_sync(ring->tx_desc_tag, ring->tx_desc_map, 1074163503Sobrien BUS_DMASYNC_PREWRITE); 1075159967Sobrien 1076159967Sobrien ring->queued = 0; 1077159967Sobrien ring->cur = ring->next = 0; 1078159967Sobrien} 1079159967Sobrien 1080163503Sobrien 1081159967Sobrienstatic void 1082159967Sobriennfe_free_tx_ring(struct nfe_softc *sc, struct nfe_tx_ring *ring) 1083159967Sobrien{ 1084159967Sobrien struct nfe_tx_data *data; 1085159967Sobrien void *desc; 1086159967Sobrien int i, descsize; 1087159967Sobrien 1088159967Sobrien if (sc->nfe_flags & NFE_40BIT_ADDR) { 1089159967Sobrien desc = ring->desc64; 1090159967Sobrien descsize = sizeof (struct nfe_desc64); 1091159967Sobrien } else { 1092159967Sobrien desc = ring->desc32; 1093159967Sobrien descsize = sizeof (struct nfe_desc32); 1094159967Sobrien } 1095159967Sobrien 1096159967Sobrien if (desc != NULL) { 1097163503Sobrien bus_dmamap_sync(ring->tx_desc_tag, ring->tx_desc_map, 1098163503Sobrien BUS_DMASYNC_POSTWRITE); 1099159967Sobrien bus_dmamap_unload(ring->tx_desc_tag, ring->tx_desc_map); 1100159967Sobrien bus_dmamem_free(ring->tx_desc_tag, desc, ring->tx_desc_map); 1101159967Sobrien bus_dma_tag_destroy(ring->tx_desc_tag); 1102159967Sobrien } 1103159967Sobrien 1104159967Sobrien for (i = 0; i < NFE_TX_RING_COUNT; i++) { 1105159967Sobrien data = &ring->data[i]; 1106159967Sobrien 1107159967Sobrien if (data->m != NULL) { 1108163503Sobrien bus_dmamap_sync(ring->tx_data_tag, data->active, 1109163503Sobrien BUS_DMASYNC_POSTWRITE); 1110159967Sobrien bus_dmamap_unload(ring->tx_data_tag, data->active); 1111159967Sobrien m_freem(data->m); 1112159967Sobrien } 1113159967Sobrien } 1114159967Sobrien 1115159967Sobrien /* ..and now actually destroy the DMA mappings */ 1116159967Sobrien for (i = 0; i < NFE_TX_RING_COUNT; i++) { 1117159967Sobrien data = &ring->data[i]; 1118159967Sobrien if (data->tx_data_map == NULL) 1119159967Sobrien continue; 1120159967Sobrien bus_dmamap_destroy(ring->tx_data_tag, data->tx_data_map); 1121159967Sobrien } 1122159967Sobrien 1123159967Sobrien bus_dma_tag_destroy(ring->tx_data_tag); 1124159967Sobrien} 1125159967Sobrien 1126159967Sobrien#ifdef DEVICE_POLLING 1127159967Sobrienstatic poll_handler_t nfe_poll; 1128159967Sobrien 1129163503Sobrien 1130159967Sobrienstatic void 1131159967Sobriennfe_poll(struct ifnet *ifp, enum poll_cmd cmd, int count) 1132159967Sobrien{ 1133164360Sobrien struct nfe_softc *sc = ifp->if_softc; 1134159967Sobrien 1135159967Sobrien NFE_LOCK(sc); 1136159967Sobrien if (ifp->if_drv_flags & IFF_DRV_RUNNING) 1137159967Sobrien nfe_poll_locked(ifp, cmd, count); 1138159967Sobrien NFE_UNLOCK(sc); 1139159967Sobrien} 1140159967Sobrien 1141159967Sobrien 1142159967Sobrienstatic void 1143159967Sobriennfe_poll_locked(struct ifnet *ifp, enum poll_cmd cmd, int count) 1144159967Sobrien{ 1145164360Sobrien struct nfe_softc *sc = ifp->if_softc; 1146159967Sobrien u_int32_t r; 1147159967Sobrien 1148159967Sobrien NFE_LOCK_ASSERT(sc); 1149159967Sobrien 1150159967Sobrien if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) { 1151159967Sobrien return; 1152159967Sobrien } 1153159967Sobrien 1154159967Sobrien sc->rxcycles = count; 1155159967Sobrien nfe_rxeof(sc); 1156159967Sobrien nfe_txeof(sc); 1157159967Sobrien if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) 1158159967Sobrien nfe_start_locked(ifp); 1159159967Sobrien 1160159967Sobrien if (cmd == POLL_AND_CHECK_STATUS) { 1161163503Sobrien if ((r = NFE_READ(sc, NFE_IRQ_STATUS)) == 0) { 1162163503Sobrien return; 1163163503Sobrien } 1164163503Sobrien NFE_WRITE(sc, NFE_IRQ_STATUS, r); 1165159967Sobrien 1166163503Sobrien if (r & NFE_IRQ_LINK) { 1167163503Sobrien NFE_READ(sc, NFE_PHY_STATUS); 1168163503Sobrien NFE_WRITE(sc, NFE_PHY_STATUS, 0xf); 1169163503Sobrien DPRINTF(("nfe%d: link state changed\n", sc->nfe_unit)); 1170163503Sobrien } 1171159967Sobrien } 1172159967Sobrien} 1173159967Sobrien#endif /* DEVICE_POLLING */ 1174159967Sobrien 1175159967Sobrien 1176159967Sobrienstatic int 1177159967Sobriennfe_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 1178159967Sobrien{ 1179163503Sobrien struct nfe_softc *sc = ifp->if_softc; 1180163503Sobrien struct ifreq *ifr = (struct ifreq *) data; 1181163503Sobrien struct mii_data *mii; 1182163503Sobrien int error = 0; 1183159967Sobrien 1184159952Sobrien switch (cmd) { 1185159952Sobrien case SIOCSIFMTU: 1186159952Sobrien if (ifr->ifr_mtu < ETHERMIN || 1187159967Sobrien ((sc->nfe_flags & NFE_USE_JUMBO) && 1188159952Sobrien ifr->ifr_mtu > ETHERMTU_JUMBO) || 1189159967Sobrien (!(sc->nfe_flags & NFE_USE_JUMBO) && 1190163503Sobrien ifr->ifr_mtu > ETHERMTU)) { 1191159952Sobrien error = EINVAL; 1192163503Sobrien } else if (ifp->if_mtu != ifr->ifr_mtu) { 1193159952Sobrien ifp->if_mtu = ifr->ifr_mtu; 1194159967Sobrien ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 1195159967Sobrien nfe_init(sc); 1196159967Sobrien } 1197159952Sobrien break; 1198159952Sobrien case SIOCSIFFLAGS: 1199159967Sobrien NFE_LOCK(sc); 1200159952Sobrien if (ifp->if_flags & IFF_UP) { 1201159952Sobrien /* 1202159952Sobrien * If only the PROMISC or ALLMULTI flag changes, then 1203159952Sobrien * don't do a full re-init of the chip, just update 1204159952Sobrien * the Rx filter. 1205159952Sobrien */ 1206159967Sobrien if ((ifp->if_drv_flags & IFF_DRV_RUNNING) && 1207159967Sobrien ((ifp->if_flags ^ sc->nfe_if_flags) & 1208159967Sobrien (IFF_ALLMULTI | IFF_PROMISC)) != 0) 1209159952Sobrien nfe_setmulti(sc); 1210159967Sobrien else 1211159967Sobrien nfe_init_locked(sc); 1212159952Sobrien } else { 1213159967Sobrien if (ifp->if_drv_flags & IFF_DRV_RUNNING) 1214159952Sobrien nfe_stop(ifp, 1); 1215159952Sobrien } 1216159967Sobrien sc->nfe_if_flags = ifp->if_flags; 1217159967Sobrien NFE_UNLOCK(sc); 1218159967Sobrien error = 0; 1219159952Sobrien break; 1220159952Sobrien case SIOCADDMULTI: 1221159952Sobrien case SIOCDELMULTI: 1222159967Sobrien if (ifp->if_drv_flags & IFF_DRV_RUNNING) { 1223159967Sobrien NFE_LOCK(sc); 1224159967Sobrien nfe_setmulti(sc); 1225159967Sobrien NFE_UNLOCK(sc); 1226159952Sobrien error = 0; 1227159952Sobrien } 1228159952Sobrien break; 1229159952Sobrien case SIOCSIFMEDIA: 1230159952Sobrien case SIOCGIFMEDIA: 1231159967Sobrien mii = device_get_softc(sc->nfe_miibus); 1232159967Sobrien error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, cmd); 1233159952Sobrien break; 1234159967Sobrien case SIOCSIFCAP: 1235163503Sobrien { 1236159967Sobrien int mask = ifr->ifr_reqcap ^ ifp->if_capenable; 1237159967Sobrien#ifdef DEVICE_POLLING 1238159967Sobrien if (mask & IFCAP_POLLING) { 1239159967Sobrien if (ifr->ifr_reqcap & IFCAP_POLLING) { 1240159967Sobrien error = ether_poll_register(nfe_poll, ifp); 1241159967Sobrien if (error) 1242159967Sobrien return(error); 1243159967Sobrien NFE_LOCK(sc); 1244159967Sobrien NFE_WRITE(sc, NFE_IRQ_MASK, 0); 1245163503Sobrien ifp->if_capenable |= IFCAP_POLLING; 1246159967Sobrien NFE_UNLOCK(sc); 1247159967Sobrien } else { 1248159967Sobrien error = ether_poll_deregister(ifp); 1249159967Sobrien /* Enable interrupt even in error case */ 1250159967Sobrien NFE_LOCK(sc); 1251159967Sobrien NFE_WRITE(sc, NFE_IRQ_MASK, NFE_IRQ_WANTED); 1252159967Sobrien ifp->if_capenable &= ~IFCAP_POLLING; 1253159967Sobrien NFE_UNLOCK(sc); 1254159967Sobrien } 1255159967Sobrien } 1256163503Sobrien#endif /* DEVICE_POLLING */ 1257159967Sobrien if (mask & IFCAP_HWCSUM) { 1258159967Sobrien ifp->if_capenable ^= IFCAP_HWCSUM; 1259159967Sobrien if (IFCAP_HWCSUM & ifp->if_capenable && 1260159967Sobrien IFCAP_HWCSUM & ifp->if_capabilities) 1261159967Sobrien ifp->if_hwassist = NFE_CSUM_FEATURES; 1262159967Sobrien else 1263159967Sobrien ifp->if_hwassist = 0; 1264159967Sobrien } 1265163503Sobrien } 1266159967Sobrien break; 1267159967Sobrien 1268159952Sobrien default: 1269159967Sobrien error = ether_ioctl(ifp, cmd, data); 1270159967Sobrien break; 1271159952Sobrien } 1272159952Sobrien 1273159952Sobrien return error; 1274159952Sobrien} 1275159952Sobrien 1276159967Sobrien 1277163503Sobrienstatic void 1278163503Sobriennfe_intr(void *arg) 1279159967Sobrien{ 1280159967Sobrien struct nfe_softc *sc = arg; 1281159967Sobrien struct ifnet *ifp = sc->nfe_ifp; 1282159967Sobrien u_int32_t r; 1283159967Sobrien 1284163503Sobrien NFE_LOCK(sc); 1285159967Sobrien 1286159967Sobrien#ifdef DEVICE_POLLING 1287159967Sobrien if (ifp->if_capenable & IFCAP_POLLING) { 1288159967Sobrien NFE_UNLOCK(sc); 1289159967Sobrien return; 1290159967Sobrien } 1291159967Sobrien#endif 1292159967Sobrien 1293159967Sobrien if ((r = NFE_READ(sc, NFE_IRQ_STATUS)) == 0) { 1294163503Sobrien NFE_UNLOCK(sc); 1295159967Sobrien return; /* not for us */ 1296159967Sobrien } 1297159967Sobrien NFE_WRITE(sc, NFE_IRQ_STATUS, r); 1298159967Sobrien 1299159967Sobrien DPRINTFN(5, ("nfe_intr: interrupt register %x\n", r)); 1300159967Sobrien 1301159967Sobrien NFE_WRITE(sc, NFE_IRQ_MASK, 0); 1302159967Sobrien 1303159967Sobrien if (r & NFE_IRQ_LINK) { 1304159967Sobrien NFE_READ(sc, NFE_PHY_STATUS); 1305159967Sobrien NFE_WRITE(sc, NFE_PHY_STATUS, 0xf); 1306159967Sobrien DPRINTF(("nfe%d: link state changed\n", sc->nfe_unit)); 1307159967Sobrien } 1308159967Sobrien 1309159967Sobrien if (ifp->if_drv_flags & IFF_DRV_RUNNING) { 1310159967Sobrien /* check Rx ring */ 1311159967Sobrien nfe_rxeof(sc); 1312159967Sobrien /* check Tx ring */ 1313159967Sobrien nfe_txeof(sc); 1314159967Sobrien } 1315159967Sobrien 1316163503Sobrien NFE_WRITE(sc, NFE_IRQ_MASK, NFE_IRQ_WANTED); 1317159967Sobrien 1318159967Sobrien if (ifp->if_drv_flags & IFF_DRV_RUNNING && 1319159967Sobrien !IFQ_DRV_IS_EMPTY(&ifp->if_snd)) 1320159967Sobrien nfe_start_locked(ifp); 1321159967Sobrien 1322159967Sobrien NFE_UNLOCK(sc); 1323159967Sobrien 1324159967Sobrien return; 1325159967Sobrien} 1326159967Sobrien 1327163503Sobrien 1328159967Sobrienstatic void 1329159952Sobriennfe_txdesc32_sync(struct nfe_softc *sc, struct nfe_desc32 *desc32, int ops) 1330159952Sobrien{ 1331163503Sobrien 1332159967Sobrien bus_dmamap_sync(sc->txq.tx_desc_tag, sc->txq.tx_desc_map, ops); 1333159952Sobrien} 1334159952Sobrien 1335163503Sobrien 1336159967Sobrienstatic void 1337159952Sobriennfe_txdesc64_sync(struct nfe_softc *sc, struct nfe_desc64 *desc64, int ops) 1338159952Sobrien{ 1339163503Sobrien 1340159967Sobrien bus_dmamap_sync(sc->txq.tx_desc_tag, sc->txq.tx_desc_map, ops); 1341159952Sobrien} 1342159952Sobrien 1343163503Sobrien 1344159967Sobrienstatic void 1345159952Sobriennfe_txdesc32_rsync(struct nfe_softc *sc, int start, int end, int ops) 1346159952Sobrien{ 1347163503Sobrien 1348159967Sobrien bus_dmamap_sync(sc->txq.tx_desc_tag, sc->txq.tx_desc_map, ops); 1349159952Sobrien} 1350159952Sobrien 1351163503Sobrien 1352159967Sobrienstatic void 1353159952Sobriennfe_txdesc64_rsync(struct nfe_softc *sc, int start, int end, int ops) 1354159952Sobrien{ 1355163503Sobrien 1356159967Sobrien bus_dmamap_sync(sc->txq.tx_desc_tag, sc->txq.tx_desc_map, ops); 1357159952Sobrien} 1358159952Sobrien 1359163503Sobrien 1360159967Sobrienstatic void 1361159952Sobriennfe_rxdesc32_sync(struct nfe_softc *sc, struct nfe_desc32 *desc32, int ops) 1362159952Sobrien{ 1363163503Sobrien 1364159967Sobrien bus_dmamap_sync(sc->rxq.rx_desc_tag, sc->rxq.rx_desc_map, ops); 1365159952Sobrien} 1366159952Sobrien 1367163503Sobrien 1368159967Sobrienstatic void 1369159952Sobriennfe_rxdesc64_sync(struct nfe_softc *sc, struct nfe_desc64 *desc64, int ops) 1370159952Sobrien{ 1371159967Sobrien 1372159967Sobrien bus_dmamap_sync(sc->rxq.rx_desc_tag, sc->rxq.rx_desc_map, ops); 1373159952Sobrien} 1374159952Sobrien 1375163503Sobrien 1376163503Sobrienstatic void 1377163503Sobriennfe_rxeof(struct nfe_softc *sc) 1378159952Sobrien{ 1379159967Sobrien struct ifnet *ifp = sc->nfe_ifp; 1380159967Sobrien struct nfe_desc32 *desc32=NULL; 1381159967Sobrien struct nfe_desc64 *desc64=NULL; 1382159952Sobrien struct nfe_rx_data *data; 1383159952Sobrien struct nfe_jbuf *jbuf; 1384159952Sobrien struct mbuf *m, *mnew; 1385159952Sobrien bus_addr_t physaddr; 1386159967Sobrien u_int16_t flags; 1387159952Sobrien int error, len; 1388159967Sobrien#if NVLAN > 1 1389159967Sobrien u_int16_t vlan_tag = 0; 1390159967Sobrien int have_tag = 0; 1391159967Sobrien#endif 1392159952Sobrien 1393159967Sobrien NFE_LOCK_ASSERT(sc); 1394159967Sobrien 1395159952Sobrien for (;;) { 1396159967Sobrien 1397159967Sobrien#ifdef DEVICE_POLLING 1398159967Sobrien if (ifp->if_capenable & IFCAP_POLLING) { 1399159967Sobrien if (sc->rxcycles <= 0) 1400159967Sobrien break; 1401159967Sobrien sc->rxcycles--; 1402159967Sobrien } 1403159967Sobrien#endif 1404159967Sobrien 1405159952Sobrien data = &sc->rxq.data[sc->rxq.cur]; 1406159952Sobrien 1407159967Sobrien if (sc->nfe_flags & NFE_40BIT_ADDR) { 1408159952Sobrien desc64 = &sc->rxq.desc64[sc->rxq.cur]; 1409159952Sobrien nfe_rxdesc64_sync(sc, desc64, BUS_DMASYNC_POSTREAD); 1410159952Sobrien 1411159952Sobrien flags = letoh16(desc64->flags); 1412159952Sobrien len = letoh16(desc64->length) & 0x3fff; 1413159967Sobrien 1414159967Sobrien#if NVLAN > 1 1415159967Sobrien if (flags & NFE_TX_VLAN_TAG) { 1416159967Sobrien have_tag = 1; 1417159967Sobrien vlan_tag = desc64->vtag; 1418159967Sobrien } 1419159967Sobrien#endif 1420159967Sobrien 1421159952Sobrien } else { 1422159952Sobrien desc32 = &sc->rxq.desc32[sc->rxq.cur]; 1423159952Sobrien nfe_rxdesc32_sync(sc, desc32, BUS_DMASYNC_POSTREAD); 1424159952Sobrien 1425159952Sobrien flags = letoh16(desc32->flags); 1426159952Sobrien len = letoh16(desc32->length) & 0x3fff; 1427159952Sobrien } 1428159952Sobrien 1429159952Sobrien if (flags & NFE_RX_READY) 1430159952Sobrien break; 1431159952Sobrien 1432159967Sobrien if ((sc->nfe_flags & (NFE_JUMBO_SUP | NFE_40BIT_ADDR)) == 0) { 1433159952Sobrien if (!(flags & NFE_RX_VALID_V1)) 1434159952Sobrien goto skip; 1435159952Sobrien if ((flags & NFE_RX_FIXME_V1) == NFE_RX_FIXME_V1) { 1436159952Sobrien flags &= ~NFE_RX_ERROR; 1437159952Sobrien len--; /* fix buffer length */ 1438159952Sobrien } 1439159952Sobrien } else { 1440159952Sobrien if (!(flags & NFE_RX_VALID_V2)) 1441159952Sobrien goto skip; 1442159952Sobrien 1443159952Sobrien if ((flags & NFE_RX_FIXME_V2) == NFE_RX_FIXME_V2) { 1444159952Sobrien flags &= ~NFE_RX_ERROR; 1445159952Sobrien len--; /* fix buffer length */ 1446159952Sobrien } 1447159952Sobrien } 1448159952Sobrien 1449159952Sobrien if (flags & NFE_RX_ERROR) { 1450159952Sobrien ifp->if_ierrors++; 1451159952Sobrien goto skip; 1452159952Sobrien } 1453159952Sobrien 1454159952Sobrien /* 1455159952Sobrien * Try to allocate a new mbuf for this ring element and load 1456159952Sobrien * it before processing the current mbuf. If the ring element 1457159952Sobrien * cannot be loaded, drop the received packet and reuse the 1458159952Sobrien * old mbuf. In the unlikely case that the old mbuf can't be 1459159952Sobrien * reloaded either, explicitly panic. 1460159952Sobrien */ 1461159952Sobrien MGETHDR(mnew, M_DONTWAIT, MT_DATA); 1462159952Sobrien if (mnew == NULL) { 1463159952Sobrien ifp->if_ierrors++; 1464159952Sobrien goto skip; 1465159952Sobrien } 1466159952Sobrien 1467159967Sobrien if (sc->nfe_flags & NFE_USE_JUMBO) { 1468159952Sobrien if ((jbuf = nfe_jalloc(sc)) == NULL) { 1469159952Sobrien m_freem(mnew); 1470159952Sobrien ifp->if_ierrors++; 1471159952Sobrien goto skip; 1472159952Sobrien } 1473159967Sobrien mnew->m_data = (void *)jbuf->buf; 1474159967Sobrien mnew->m_len = mnew->m_pkthdr.len = NFE_JBYTES; 1475159967Sobrien MEXTADD(mnew, jbuf->buf, NFE_JBYTES, nfe_jfree, 1476159967Sobrien (struct nfe_softc *)sc, 0 , EXT_NET_DRV); 1477159952Sobrien 1478159967Sobrien bus_dmamap_sync(sc->rxq.rx_jumbo_tag, 1479159967Sobrien sc->rxq.rx_jumbo_map, BUS_DMASYNC_POSTREAD); 1480159952Sobrien physaddr = jbuf->physaddr; 1481159952Sobrien } else { 1482159952Sobrien MCLGET(mnew, M_DONTWAIT); 1483159952Sobrien if (!(mnew->m_flags & M_EXT)) { 1484159952Sobrien m_freem(mnew); 1485159952Sobrien ifp->if_ierrors++; 1486159952Sobrien goto skip; 1487159952Sobrien } 1488159952Sobrien 1489159967Sobrien bus_dmamap_sync(data->rx_data_tag, data->rx_data_map, 1490159967Sobrien BUS_DMASYNC_POSTREAD); 1491159967Sobrien bus_dmamap_unload(data->rx_data_tag, data->rx_data_map); 1492159967Sobrien error = bus_dmamap_load(data->rx_data_tag, 1493159967Sobrien data->rx_data_map, mtod(mnew, void *), MCLBYTES, 1494159967Sobrien nfe_dma_map_segs, &data->rx_data_segs, 1495159967Sobrien BUS_DMA_NOWAIT); 1496159952Sobrien if (error != 0) { 1497159952Sobrien m_freem(mnew); 1498159952Sobrien 1499159952Sobrien /* try to reload the old mbuf */ 1500159967Sobrien error = bus_dmamap_load(data->rx_data_tag, 1501159967Sobrien data->rx_data_map, mtod(data->m, void *), 1502159967Sobrien MCLBYTES, nfe_dma_map_segs, 1503159967Sobrien &data->rx_data_segs, BUS_DMA_NOWAIT); 1504159952Sobrien if (error != 0) { 1505159952Sobrien /* very unlikely that it will fail.. */ 1506159967Sobrien panic("nfe%d: could not load old rx mbuf", 1507159967Sobrien sc->nfe_unit); 1508159952Sobrien } 1509159952Sobrien ifp->if_ierrors++; 1510159952Sobrien goto skip; 1511159952Sobrien } 1512159967Sobrien data->rx_data_addr = data->rx_data_segs.ds_addr; 1513159967Sobrien physaddr = data->rx_data_addr; 1514159952Sobrien } 1515159952Sobrien 1516159952Sobrien /* 1517159952Sobrien * New mbuf successfully loaded, update Rx ring and continue 1518159952Sobrien * processing. 1519159952Sobrien */ 1520159952Sobrien m = data->m; 1521159952Sobrien data->m = mnew; 1522159952Sobrien 1523159952Sobrien /* finalize mbuf */ 1524159952Sobrien m->m_pkthdr.len = m->m_len = len; 1525159952Sobrien m->m_pkthdr.rcvif = ifp; 1526159952Sobrien 1527159967Sobrien 1528159967Sobrien#if defined(NFE_CSUM) 1529159967Sobrien if ((sc->nfe_flags & NFE_HW_CSUM) && (flags & NFE_RX_CSUMOK)) { 1530159967Sobrien m->m_pkthdr.csum_flags |= CSUM_IP_CHECKED; 1531159967Sobrien if (flags & NFE_RX_IP_CSUMOK_V2) { 1532159967Sobrien m->m_pkthdr.csum_flags |= CSUM_IP_VALID; 1533159967Sobrien } 1534159967Sobrien if (flags & NFE_RX_UDP_CSUMOK_V2 || 1535159967Sobrien flags & NFE_RX_TCP_CSUMOK_V2) { 1536159967Sobrien m->m_pkthdr.csum_flags |= 1537163503Sobrien CSUM_DATA_VALID | CSUM_PSEUDO_HDR; 1538159967Sobrien m->m_pkthdr.csum_data = 0xffff; 1539159967Sobrien } 1540159952Sobrien } 1541159952Sobrien#endif 1542159952Sobrien 1543159967Sobrien#if NVLAN > 1 1544159967Sobrien if (have_tag) { 1545162375Sandre m->m_pkthdr.ether_vtag = vlan_tag; 1546162375Sandre m->m_flags |= M_VLANTAG; 1547159967Sobrien } 1548159952Sobrien#endif 1549159967Sobrien 1550159952Sobrien ifp->if_ipackets++; 1551159952Sobrien 1552159967Sobrien NFE_UNLOCK(sc); 1553159967Sobrien (*ifp->if_input)(ifp, m); 1554159967Sobrien NFE_LOCK(sc); 1555159967Sobrien 1556159952Sobrien /* update mapping address in h/w descriptor */ 1557159967Sobrien if (sc->nfe_flags & NFE_40BIT_ADDR) { 1558159952Sobrien#if defined(__LP64__) 1559159952Sobrien desc64->physaddr[0] = htole32(physaddr >> 32); 1560159952Sobrien#endif 1561159952Sobrien desc64->physaddr[1] = htole32(physaddr & 0xffffffff); 1562159952Sobrien } else { 1563159952Sobrien desc32->physaddr = htole32(physaddr); 1564159952Sobrien } 1565159952Sobrien 1566159967Sobrienskip: if (sc->nfe_flags & NFE_40BIT_ADDR) { 1567159952Sobrien desc64->length = htole16(sc->rxq.bufsz); 1568159952Sobrien desc64->flags = htole16(NFE_RX_READY); 1569159952Sobrien 1570159952Sobrien nfe_rxdesc64_sync(sc, desc64, BUS_DMASYNC_PREWRITE); 1571159952Sobrien } else { 1572159952Sobrien desc32->length = htole16(sc->rxq.bufsz); 1573159952Sobrien desc32->flags = htole16(NFE_RX_READY); 1574159952Sobrien 1575159952Sobrien nfe_rxdesc32_sync(sc, desc32, BUS_DMASYNC_PREWRITE); 1576159952Sobrien } 1577159952Sobrien 1578159952Sobrien sc->rxq.cur = (sc->rxq.cur + 1) % NFE_RX_RING_COUNT; 1579159952Sobrien } 1580159952Sobrien} 1581159952Sobrien 1582163503Sobrien 1583163503Sobrienstatic void 1584163503Sobriennfe_txeof(struct nfe_softc *sc) 1585159952Sobrien{ 1586159967Sobrien struct ifnet *ifp = sc->nfe_ifp; 1587159952Sobrien struct nfe_desc32 *desc32; 1588159952Sobrien struct nfe_desc64 *desc64; 1589159952Sobrien struct nfe_tx_data *data = NULL; 1590159967Sobrien u_int16_t flags; 1591159952Sobrien 1592159967Sobrien NFE_LOCK_ASSERT(sc); 1593159967Sobrien 1594159952Sobrien while (sc->txq.next != sc->txq.cur) { 1595159967Sobrien if (sc->nfe_flags & NFE_40BIT_ADDR) { 1596159952Sobrien desc64 = &sc->txq.desc64[sc->txq.next]; 1597159952Sobrien nfe_txdesc64_sync(sc, desc64, BUS_DMASYNC_POSTREAD); 1598159952Sobrien 1599159952Sobrien flags = letoh16(desc64->flags); 1600159952Sobrien } else { 1601159952Sobrien desc32 = &sc->txq.desc32[sc->txq.next]; 1602159952Sobrien nfe_txdesc32_sync(sc, desc32, BUS_DMASYNC_POSTREAD); 1603159952Sobrien 1604159952Sobrien flags = letoh16(desc32->flags); 1605159952Sobrien } 1606159952Sobrien 1607159952Sobrien if (flags & NFE_TX_VALID) 1608159952Sobrien break; 1609159952Sobrien 1610159952Sobrien data = &sc->txq.data[sc->txq.next]; 1611159952Sobrien 1612159967Sobrien if ((sc->nfe_flags & (NFE_JUMBO_SUP | NFE_40BIT_ADDR)) == 0) { 1613159952Sobrien if (!(flags & NFE_TX_LASTFRAG_V1) && data->m == NULL) 1614159952Sobrien goto skip; 1615159952Sobrien 1616159952Sobrien if ((flags & NFE_TX_ERROR_V1) != 0) { 1617159967Sobrien printf("nfe%d: tx v1 error 0x%4b\n", 1618163503Sobrien sc->nfe_unit, flags, NFE_V1_TXERR); 1619159967Sobrien 1620159952Sobrien ifp->if_oerrors++; 1621159952Sobrien } else 1622159952Sobrien ifp->if_opackets++; 1623159952Sobrien } else { 1624159952Sobrien if (!(flags & NFE_TX_LASTFRAG_V2) && data->m == NULL) 1625159952Sobrien goto skip; 1626159952Sobrien 1627159952Sobrien if ((flags & NFE_TX_ERROR_V2) != 0) { 1628159967Sobrien printf("nfe%d: tx v1 error 0x%4b\n", 1629163503Sobrien sc->nfe_unit, flags, NFE_V2_TXERR); 1630159967Sobrien 1631159952Sobrien ifp->if_oerrors++; 1632159952Sobrien } else 1633159952Sobrien ifp->if_opackets++; 1634159952Sobrien } 1635159952Sobrien 1636159952Sobrien if (data->m == NULL) { /* should not get there */ 1637163503Sobrien printf("nfe%d: last fragment bit w/o associated mbuf!\n", 1638159967Sobrien sc->nfe_unit); 1639159952Sobrien goto skip; 1640159952Sobrien } 1641159952Sobrien 1642159952Sobrien /* last fragment of the mbuf chain transmitted */ 1643159967Sobrien bus_dmamap_sync(sc->txq.tx_data_tag, data->active, 1644159967Sobrien BUS_DMASYNC_POSTWRITE); 1645159967Sobrien bus_dmamap_unload(sc->txq.tx_data_tag, data->active); 1646159952Sobrien m_freem(data->m); 1647159952Sobrien data->m = NULL; 1648159952Sobrien 1649159952Sobrien ifp->if_timer = 0; 1650159952Sobrien 1651159952Sobrienskip: sc->txq.queued--; 1652159952Sobrien sc->txq.next = (sc->txq.next + 1) % NFE_TX_RING_COUNT; 1653159952Sobrien } 1654159952Sobrien 1655159952Sobrien if (data != NULL) { /* at least one slot freed */ 1656159967Sobrien ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 1657159967Sobrien nfe_start_locked(ifp); 1658159952Sobrien } 1659159952Sobrien} 1660159952Sobrien 1661163503Sobrien 1662163503Sobrienstatic int 1663163503Sobriennfe_encap(struct nfe_softc *sc, struct mbuf *m0) 1664159952Sobrien{ 1665159967Sobrien struct nfe_desc32 *desc32=NULL; 1666159967Sobrien struct nfe_desc64 *desc64=NULL; 1667159967Sobrien struct nfe_tx_data *data=NULL; 1668159952Sobrien bus_dmamap_t map; 1669163503Sobrien bus_dma_segment_t segs[NFE_MAX_SCATTER]; 1670163503Sobrien int error, i, nsegs; 1671159967Sobrien u_int16_t flags = NFE_TX_VALID; 1672159952Sobrien 1673159967Sobrien map = sc->txq.data[sc->txq.cur].tx_data_map; 1674159952Sobrien 1675159967Sobrien error = bus_dmamap_load_mbuf_sg(sc->txq.tx_data_tag, map, m0, segs, 1676159967Sobrien &nsegs, BUS_DMA_NOWAIT); 1677159967Sobrien 1678159952Sobrien if (error != 0) { 1679159967Sobrien printf("nfe%d: could not map mbuf (error %d)\n", sc->nfe_unit, 1680159967Sobrien error); 1681159952Sobrien return error; 1682159952Sobrien } 1683159952Sobrien 1684159967Sobrien if (sc->txq.queued + nsegs >= NFE_TX_RING_COUNT - 1) { 1685159967Sobrien bus_dmamap_unload(sc->txq.tx_data_tag, map); 1686159952Sobrien return ENOBUFS; 1687159952Sobrien } 1688159952Sobrien 1689159967Sobrien 1690159952Sobrien#ifdef NFE_CSUM 1691159967Sobrien if (m0->m_pkthdr.csum_flags & CSUM_IP) 1692159952Sobrien flags |= NFE_TX_IP_CSUM; 1693159967Sobrien if (m0->m_pkthdr.csum_flags & CSUM_TCP) 1694159952Sobrien flags |= NFE_TX_TCP_CSUM; 1695159967Sobrien if (m0->m_pkthdr.csum_flags & CSUM_UDP) 1696159967Sobrien flags |= NFE_TX_TCP_CSUM; 1697159952Sobrien#endif 1698159952Sobrien 1699159967Sobrien for (i = 0; i < nsegs; i++) { 1700159952Sobrien data = &sc->txq.data[sc->txq.cur]; 1701159952Sobrien 1702159967Sobrien if (sc->nfe_flags & NFE_40BIT_ADDR) { 1703159952Sobrien desc64 = &sc->txq.desc64[sc->txq.cur]; 1704159952Sobrien#if defined(__LP64__) 1705159967Sobrien desc64->physaddr[0] = htole32(segs[i].ds_addr >> 32); 1706159952Sobrien#endif 1707159967Sobrien desc64->physaddr[1] = htole32(segs[i].ds_addr & 1708159967Sobrien 0xffffffff); 1709159967Sobrien desc64->length = htole16(segs[i].ds_len - 1); 1710159952Sobrien desc64->flags = htole16(flags); 1711159952Sobrien#if NVLAN > 0 1712162375Sandre if (m0->m_flags & M_VLANTAG) 1713162375Sandre desc64->vtag = htole32(NFE_TX_VTAG | 1714162375Sandre m0->m_pkthdr.ether_vtag); 1715159952Sobrien#endif 1716159952Sobrien } else { 1717159952Sobrien desc32 = &sc->txq.desc32[sc->txq.cur]; 1718159952Sobrien 1719159967Sobrien desc32->physaddr = htole32(segs[i].ds_addr); 1720159967Sobrien desc32->length = htole16(segs[i].ds_len - 1); 1721159952Sobrien desc32->flags = htole16(flags); 1722159952Sobrien } 1723159952Sobrien 1724159952Sobrien /* csum flags and vtag belong to the first fragment only */ 1725159967Sobrien if (nsegs > 1) { 1726159952Sobrien flags &= ~(NFE_TX_IP_CSUM | NFE_TX_TCP_CSUM); 1727159952Sobrien } 1728163503Sobrien 1729159952Sobrien sc->txq.queued++; 1730159952Sobrien sc->txq.cur = (sc->txq.cur + 1) % NFE_TX_RING_COUNT; 1731159952Sobrien } 1732159952Sobrien 1733159952Sobrien /* the whole mbuf chain has been DMA mapped, fix last descriptor */ 1734159967Sobrien if (sc->nfe_flags & NFE_40BIT_ADDR) { 1735159952Sobrien flags |= NFE_TX_LASTFRAG_V2; 1736159952Sobrien desc64->flags = htole16(flags); 1737159952Sobrien } else { 1738159967Sobrien if (sc->nfe_flags & NFE_JUMBO_SUP) 1739159952Sobrien flags |= NFE_TX_LASTFRAG_V2; 1740159952Sobrien else 1741159952Sobrien flags |= NFE_TX_LASTFRAG_V1; 1742159952Sobrien desc32->flags = htole16(flags); 1743159952Sobrien } 1744159952Sobrien 1745159952Sobrien data->m = m0; 1746159952Sobrien data->active = map; 1747159967Sobrien data->nsegs = nsegs; 1748159952Sobrien 1749159967Sobrien bus_dmamap_sync(sc->txq.tx_data_tag, map, BUS_DMASYNC_PREWRITE); 1750159952Sobrien 1751159952Sobrien return 0; 1752159952Sobrien} 1753159952Sobrien 1754159967Sobrien 1755163503Sobrienstatic void 1756163503Sobriennfe_setmulti(struct nfe_softc *sc) 1757159952Sobrien{ 1758159967Sobrien struct ifnet *ifp = sc->nfe_ifp; 1759163503Sobrien struct ifmultiaddr *ifma; 1760163503Sobrien int i; 1761163503Sobrien u_int32_t filter = NFE_RXFILTER_MAGIC; 1762159967Sobrien u_int8_t addr[ETHER_ADDR_LEN], mask[ETHER_ADDR_LEN]; 1763163503Sobrien u_int8_t etherbroadcastaddr[ETHER_ADDR_LEN] = { 1764163503Sobrien 0xff, 0xff, 0xff, 0xff, 0xff, 0xff 1765163503Sobrien }; 1766159967Sobrien 1767159967Sobrien NFE_LOCK_ASSERT(sc); 1768159967Sobrien 1769159967Sobrien if ((ifp->if_flags & (IFF_ALLMULTI | IFF_PROMISC)) != 0) { 1770159967Sobrien bzero(addr, ETHER_ADDR_LEN); 1771159967Sobrien bzero(mask, ETHER_ADDR_LEN); 1772159967Sobrien goto done; 1773159967Sobrien } 1774159967Sobrien 1775159967Sobrien bcopy(etherbroadcastaddr, addr, ETHER_ADDR_LEN); 1776159967Sobrien bcopy(etherbroadcastaddr, mask, ETHER_ADDR_LEN); 1777159967Sobrien 1778159967Sobrien IF_ADDR_LOCK(ifp); 1779159967Sobrien TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { 1780159967Sobrien u_char *addrp; 1781159967Sobrien 1782159967Sobrien if (ifma->ifma_addr->sa_family != AF_LINK) 1783159967Sobrien continue; 1784159967Sobrien 1785159967Sobrien addrp = LLADDR((struct sockaddr_dl *) ifma->ifma_addr); 1786159967Sobrien for (i = 0; i < ETHER_ADDR_LEN; i++) { 1787159967Sobrien u_int8_t mcaddr = addrp[i]; 1788159967Sobrien addr[i] &= mcaddr; 1789159967Sobrien mask[i] &= ~mcaddr; 1790159967Sobrien } 1791159967Sobrien } 1792159967Sobrien IF_ADDR_UNLOCK(ifp); 1793159967Sobrien 1794159967Sobrien for (i = 0; i < ETHER_ADDR_LEN; i++) { 1795159967Sobrien mask[i] |= addr[i]; 1796159967Sobrien } 1797159967Sobrien 1798159967Sobriendone: 1799159967Sobrien addr[0] |= 0x01; /* make sure multicast bit is set */ 1800159967Sobrien 1801159967Sobrien NFE_WRITE(sc, NFE_MULTIADDR_HI, 1802159967Sobrien addr[3] << 24 | addr[2] << 16 | addr[1] << 8 | addr[0]); 1803159967Sobrien NFE_WRITE(sc, NFE_MULTIADDR_LO, 1804159967Sobrien addr[5] << 8 | addr[4]); 1805159967Sobrien NFE_WRITE(sc, NFE_MULTIMASK_HI, 1806159967Sobrien mask[3] << 24 | mask[2] << 16 | mask[1] << 8 | mask[0]); 1807159967Sobrien NFE_WRITE(sc, NFE_MULTIMASK_LO, 1808159967Sobrien mask[5] << 8 | mask[4]); 1809159967Sobrien 1810159967Sobrien filter |= (ifp->if_flags & IFF_PROMISC) ? NFE_PROMISC : NFE_U2M; 1811159967Sobrien NFE_WRITE(sc, NFE_RXFILTER, filter); 1812159967Sobrien} 1813159967Sobrien 1814163503Sobrien 1815163503Sobrienstatic void 1816163503Sobriennfe_start(struct ifnet *ifp) 1817159967Sobrien{ 1818159967Sobrien struct nfe_softc *sc; 1819159967Sobrien 1820159967Sobrien sc = ifp->if_softc; 1821159967Sobrien NFE_LOCK(sc); 1822159967Sobrien nfe_start_locked(ifp); 1823159967Sobrien NFE_UNLOCK(sc); 1824159967Sobrien} 1825159967Sobrien 1826163503Sobrien 1827163503Sobrienstatic void 1828163503Sobriennfe_start_locked(struct ifnet *ifp) 1829159967Sobrien{ 1830159952Sobrien struct nfe_softc *sc = ifp->if_softc; 1831163503Sobrien struct mbuf *m0; 1832159952Sobrien int old = sc->txq.cur; 1833159952Sobrien 1834159967Sobrien if (!sc->nfe_link || ifp->if_drv_flags & IFF_DRV_OACTIVE) { 1835159967Sobrien return; 1836159967Sobrien } 1837159967Sobrien 1838159952Sobrien for (;;) { 1839159952Sobrien IFQ_POLL(&ifp->if_snd, m0); 1840159952Sobrien if (m0 == NULL) 1841159952Sobrien break; 1842159952Sobrien 1843159952Sobrien if (nfe_encap(sc, m0) != 0) { 1844159967Sobrien ifp->if_drv_flags |= IFF_DRV_OACTIVE; 1845159952Sobrien break; 1846159952Sobrien } 1847159952Sobrien 1848159952Sobrien /* packet put in h/w queue, remove from s/w queue */ 1849159952Sobrien IFQ_DEQUEUE(&ifp->if_snd, m0); 1850159952Sobrien 1851159967Sobrien BPF_MTAP(ifp, m0); 1852159952Sobrien } 1853159967Sobrien if (sc->txq.cur == old) { /* nothing sent */ 1854159952Sobrien return; 1855159967Sobrien } 1856159952Sobrien 1857159967Sobrien if (sc->nfe_flags & NFE_40BIT_ADDR) 1858159952Sobrien nfe_txdesc64_rsync(sc, old, sc->txq.cur, BUS_DMASYNC_PREWRITE); 1859159952Sobrien else 1860159952Sobrien nfe_txdesc32_rsync(sc, old, sc->txq.cur, BUS_DMASYNC_PREWRITE); 1861159952Sobrien 1862159952Sobrien /* kick Tx */ 1863159952Sobrien NFE_WRITE(sc, NFE_RXTX_CTL, NFE_RXTX_KICKTX | sc->rxtxctl); 1864159952Sobrien 1865159952Sobrien /* 1866159952Sobrien * Set a timeout in case the chip goes out to lunch. 1867159952Sobrien */ 1868159952Sobrien ifp->if_timer = 5; 1869159967Sobrien 1870159967Sobrien return; 1871159952Sobrien} 1872159952Sobrien 1873163503Sobrien 1874163503Sobrienstatic void 1875163503Sobriennfe_watchdog(struct ifnet *ifp) 1876159952Sobrien{ 1877159952Sobrien struct nfe_softc *sc = ifp->if_softc; 1878159952Sobrien 1879159967Sobrien printf("nfe%d: watchdog timeout\n", sc->nfe_unit); 1880159952Sobrien 1881159967Sobrien ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 1882159967Sobrien nfe_init(sc); 1883159952Sobrien ifp->if_oerrors++; 1884159967Sobrien 1885159967Sobrien return; 1886159952Sobrien} 1887159952Sobrien 1888163503Sobrien 1889163503Sobrienstatic void 1890163503Sobriennfe_init(void *xsc) 1891159952Sobrien{ 1892159967Sobrien struct nfe_softc *sc = xsc; 1893159952Sobrien 1894159967Sobrien NFE_LOCK(sc); 1895159967Sobrien nfe_init_locked(sc); 1896159967Sobrien NFE_UNLOCK(sc); 1897159967Sobrien 1898159967Sobrien return; 1899159967Sobrien} 1900159967Sobrien 1901163503Sobrien 1902163503Sobrienstatic void 1903163503Sobriennfe_init_locked(void *xsc) 1904159967Sobrien{ 1905159967Sobrien struct nfe_softc *sc = xsc; 1906159967Sobrien struct ifnet *ifp = sc->nfe_ifp; 1907159967Sobrien struct mii_data *mii; 1908159967Sobrien u_int32_t tmp; 1909159967Sobrien 1910159967Sobrien NFE_LOCK_ASSERT(sc); 1911159967Sobrien 1912159967Sobrien mii = device_get_softc(sc->nfe_miibus); 1913159967Sobrien 1914159967Sobrien if (ifp->if_drv_flags & IFF_DRV_RUNNING) { 1915159967Sobrien return; 1916159967Sobrien } 1917159967Sobrien 1918159952Sobrien nfe_stop(ifp, 0); 1919159952Sobrien 1920159952Sobrien NFE_WRITE(sc, NFE_TX_UNK, 0); 1921159952Sobrien NFE_WRITE(sc, NFE_STATUS, 0); 1922159952Sobrien 1923159952Sobrien sc->rxtxctl = NFE_RXTX_BIT2; 1924159967Sobrien if (sc->nfe_flags & NFE_40BIT_ADDR) 1925159952Sobrien sc->rxtxctl |= NFE_RXTX_V3MAGIC; 1926159967Sobrien else if (sc->nfe_flags & NFE_JUMBO_SUP) 1927159952Sobrien sc->rxtxctl |= NFE_RXTX_V2MAGIC; 1928159952Sobrien#ifdef NFE_CSUM 1929159967Sobrien if (sc->nfe_flags & NFE_HW_CSUM) 1930159952Sobrien sc->rxtxctl |= NFE_RXTX_RXCSUM; 1931159952Sobrien#endif 1932159967Sobrien 1933159952Sobrien#if NVLAN > 0 1934159952Sobrien /* 1935159952Sobrien * Although the adapter is capable of stripping VLAN tags from received 1936159952Sobrien * frames (NFE_RXTX_VTAG_STRIP), we do not enable this functionality on 1937159952Sobrien * purpose. This will be done in software by our network stack. 1938159952Sobrien */ 1939159967Sobrien if (sc->nfe_flags & NFE_HW_VLAN) 1940159952Sobrien sc->rxtxctl |= NFE_RXTX_VTAG_INSERT; 1941159952Sobrien#endif 1942159967Sobrien 1943159952Sobrien NFE_WRITE(sc, NFE_RXTX_CTL, NFE_RXTX_RESET | sc->rxtxctl); 1944159952Sobrien DELAY(10); 1945159952Sobrien NFE_WRITE(sc, NFE_RXTX_CTL, sc->rxtxctl); 1946159952Sobrien 1947159952Sobrien#if NVLAN 1948159967Sobrien if (sc->nfe_flags & NFE_HW_VLAN) 1949159952Sobrien NFE_WRITE(sc, NFE_VTAG_CTL, NFE_VTAG_ENABLE); 1950159952Sobrien#endif 1951159952Sobrien 1952159952Sobrien NFE_WRITE(sc, NFE_SETUP_R6, 0); 1953159952Sobrien 1954159952Sobrien /* set MAC address */ 1955159967Sobrien nfe_set_macaddr(sc, sc->eaddr); 1956159952Sobrien 1957159952Sobrien /* tell MAC where rings are in memory */ 1958159952Sobrien#ifdef __LP64__ 1959159952Sobrien NFE_WRITE(sc, NFE_RX_RING_ADDR_HI, sc->rxq.physaddr >> 32); 1960159952Sobrien#endif 1961159952Sobrien NFE_WRITE(sc, NFE_RX_RING_ADDR_LO, sc->rxq.physaddr & 0xffffffff); 1962159952Sobrien#ifdef __LP64__ 1963159952Sobrien NFE_WRITE(sc, NFE_TX_RING_ADDR_HI, sc->txq.physaddr >> 32); 1964159952Sobrien#endif 1965159952Sobrien NFE_WRITE(sc, NFE_TX_RING_ADDR_LO, sc->txq.physaddr & 0xffffffff); 1966159952Sobrien 1967159952Sobrien NFE_WRITE(sc, NFE_RING_SIZE, 1968159952Sobrien (NFE_RX_RING_COUNT - 1) << 16 | 1969159952Sobrien (NFE_TX_RING_COUNT - 1)); 1970159952Sobrien 1971159952Sobrien NFE_WRITE(sc, NFE_RXBUFSZ, sc->rxq.bufsz); 1972159952Sobrien 1973159952Sobrien /* force MAC to wakeup */ 1974159952Sobrien tmp = NFE_READ(sc, NFE_PWR_STATE); 1975159952Sobrien NFE_WRITE(sc, NFE_PWR_STATE, tmp | NFE_PWR_WAKEUP); 1976159952Sobrien DELAY(10); 1977159952Sobrien tmp = NFE_READ(sc, NFE_PWR_STATE); 1978159952Sobrien NFE_WRITE(sc, NFE_PWR_STATE, tmp | NFE_PWR_VALID); 1979159952Sobrien 1980159952Sobrien#if 1 1981159952Sobrien /* configure interrupts coalescing/mitigation */ 1982159952Sobrien NFE_WRITE(sc, NFE_IMTIMER, NFE_IM_DEFAULT); 1983159952Sobrien#else 1984159952Sobrien /* no interrupt mitigation: one interrupt per packet */ 1985159952Sobrien NFE_WRITE(sc, NFE_IMTIMER, 970); 1986159952Sobrien#endif 1987159952Sobrien 1988159952Sobrien NFE_WRITE(sc, NFE_SETUP_R1, NFE_R1_MAGIC); 1989159952Sobrien NFE_WRITE(sc, NFE_SETUP_R2, NFE_R2_MAGIC); 1990159952Sobrien NFE_WRITE(sc, NFE_SETUP_R6, NFE_R6_MAGIC); 1991159952Sobrien 1992159952Sobrien /* update MAC knowledge of PHY; generates a NFE_IRQ_LINK interrupt */ 1993159952Sobrien NFE_WRITE(sc, NFE_STATUS, sc->mii_phyaddr << 24 | NFE_STATUS_MAGIC); 1994159952Sobrien 1995159952Sobrien NFE_WRITE(sc, NFE_SETUP_R4, NFE_R4_MAGIC); 1996159952Sobrien NFE_WRITE(sc, NFE_WOL_CTL, NFE_WOL_MAGIC); 1997159952Sobrien 1998159952Sobrien sc->rxtxctl &= ~NFE_RXTX_BIT2; 1999159952Sobrien NFE_WRITE(sc, NFE_RXTX_CTL, sc->rxtxctl); 2000159952Sobrien DELAY(10); 2001159952Sobrien NFE_WRITE(sc, NFE_RXTX_CTL, NFE_RXTX_BIT1 | sc->rxtxctl); 2002159952Sobrien 2003159952Sobrien /* set Rx filter */ 2004159952Sobrien nfe_setmulti(sc); 2005159952Sobrien 2006159952Sobrien nfe_ifmedia_upd(ifp); 2007159952Sobrien 2008159967Sobrien nfe_tick_locked(sc); 2009159967Sobrien 2010159952Sobrien /* enable Rx */ 2011159952Sobrien NFE_WRITE(sc, NFE_RX_CTL, NFE_RX_START); 2012159952Sobrien 2013159952Sobrien /* enable Tx */ 2014159952Sobrien NFE_WRITE(sc, NFE_TX_CTL, NFE_TX_START); 2015159952Sobrien 2016159952Sobrien NFE_WRITE(sc, NFE_PHY_STATUS, 0xf); 2017159952Sobrien 2018159967Sobrien#ifdef DEVICE_POLLING 2019159967Sobrien if (ifp->if_capenable & IFCAP_POLLING) 2020159967Sobrien NFE_WRITE(sc, NFE_IRQ_MASK, 0); 2021159967Sobrien else 2022159967Sobrien#endif 2023159967Sobrien NFE_WRITE(sc, NFE_IRQ_MASK, NFE_IRQ_WANTED); /* enable interrupts */ 2024159952Sobrien 2025159967Sobrien ifp->if_drv_flags |= IFF_DRV_RUNNING; 2026159967Sobrien ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 2027159952Sobrien 2028159967Sobrien sc->nfe_link = 0; 2029159952Sobrien 2030159967Sobrien return; 2031159952Sobrien} 2032159952Sobrien 2033163503Sobrien 2034163503Sobrienstatic void 2035163503Sobriennfe_stop(struct ifnet *ifp, int disable) 2036159952Sobrien{ 2037159952Sobrien struct nfe_softc *sc = ifp->if_softc; 2038159967Sobrien struct mii_data *mii; 2039159952Sobrien 2040159967Sobrien NFE_LOCK_ASSERT(sc); 2041159952Sobrien 2042159952Sobrien ifp->if_timer = 0; 2043159967Sobrien ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); 2044159952Sobrien 2045159967Sobrien mii = device_get_softc(sc->nfe_miibus); 2046159952Sobrien 2047159967Sobrien callout_stop(&sc->nfe_stat_ch); 2048159967Sobrien 2049159952Sobrien /* abort Tx */ 2050159952Sobrien NFE_WRITE(sc, NFE_TX_CTL, 0); 2051159952Sobrien 2052159952Sobrien /* disable Rx */ 2053159952Sobrien NFE_WRITE(sc, NFE_RX_CTL, 0); 2054159952Sobrien 2055159952Sobrien /* disable interrupts */ 2056159952Sobrien NFE_WRITE(sc, NFE_IRQ_MASK, 0); 2057159952Sobrien 2058159967Sobrien sc->nfe_link = 0; 2059159967Sobrien 2060159952Sobrien /* reset Tx and Rx rings */ 2061159952Sobrien nfe_reset_tx_ring(sc, &sc->txq); 2062159952Sobrien nfe_reset_rx_ring(sc, &sc->rxq); 2063159952Sobrien 2064159967Sobrien return; 2065159952Sobrien} 2066159952Sobrien 2067163503Sobrien 2068163503Sobrienstatic int 2069163503Sobriennfe_ifmedia_upd(struct ifnet *ifp) 2070159952Sobrien{ 2071159967Sobrien struct nfe_softc *sc = ifp->if_softc; 2072159952Sobrien 2073159967Sobrien NFE_LOCK(sc); 2074159967Sobrien nfe_ifmedia_upd_locked(ifp); 2075159967Sobrien NFE_UNLOCK(sc); 2076159967Sobrien return (0); 2077159952Sobrien} 2078159952Sobrien 2079163503Sobrien 2080163503Sobrienstatic int 2081163503Sobriennfe_ifmedia_upd_locked(struct ifnet *ifp) 2082159952Sobrien{ 2083163503Sobrien struct nfe_softc *sc = ifp->if_softc; 2084163503Sobrien struct mii_data *mii; 2085159952Sobrien 2086159967Sobrien NFE_LOCK_ASSERT(sc); 2087159952Sobrien 2088159967Sobrien mii = device_get_softc(sc->nfe_miibus); 2089159952Sobrien 2090159967Sobrien if (mii->mii_instance) { 2091159967Sobrien struct mii_softc *miisc; 2092159967Sobrien for (miisc = LIST_FIRST(&mii->mii_phys); miisc != NULL; 2093159967Sobrien miisc = LIST_NEXT(miisc, mii_list)) { 2094159967Sobrien mii_phy_reset(miisc); 2095159952Sobrien } 2096159952Sobrien } 2097159967Sobrien mii_mediachg(mii); 2098159967Sobrien 2099159967Sobrien return (0); 2100159952Sobrien} 2101159952Sobrien 2102163503Sobrien 2103163503Sobrienstatic void 2104163503Sobriennfe_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr) 2105159952Sobrien{ 2106163503Sobrien struct nfe_softc *sc; 2107163503Sobrien struct mii_data *mii; 2108159952Sobrien 2109159967Sobrien sc = ifp->if_softc; 2110159952Sobrien 2111159967Sobrien NFE_LOCK(sc); 2112159967Sobrien mii = device_get_softc(sc->nfe_miibus); 2113159967Sobrien mii_pollstat(mii); 2114159967Sobrien NFE_UNLOCK(sc); 2115159952Sobrien 2116159967Sobrien ifmr->ifm_active = mii->mii_media_active; 2117159967Sobrien ifmr->ifm_status = mii->mii_media_status; 2118159952Sobrien 2119159967Sobrien return; 2120159952Sobrien} 2121159952Sobrien 2122163503Sobrien 2123159967Sobrienstatic void 2124159967Sobriennfe_tick(void *xsc) 2125159952Sobrien{ 2126159967Sobrien struct nfe_softc *sc; 2127159952Sobrien 2128159967Sobrien sc = xsc; 2129159952Sobrien 2130159967Sobrien NFE_LOCK(sc); 2131159967Sobrien nfe_tick_locked(sc); 2132159967Sobrien NFE_UNLOCK(sc); 2133159952Sobrien} 2134159952Sobrien 2135159952Sobrien 2136163503Sobrienvoid 2137163503Sobriennfe_tick_locked(struct nfe_softc *arg) 2138159952Sobrien{ 2139163503Sobrien struct nfe_softc *sc; 2140163503Sobrien struct mii_data *mii; 2141163503Sobrien struct ifnet *ifp; 2142159952Sobrien 2143159967Sobrien sc = arg; 2144159952Sobrien 2145163503Sobrien NFE_LOCK_ASSERT(sc); 2146159952Sobrien 2147159967Sobrien ifp = sc->nfe_ifp; 2148159952Sobrien 2149159967Sobrien mii = device_get_softc(sc->nfe_miibus); 2150159967Sobrien mii_tick(mii); 2151159952Sobrien 2152159967Sobrien if (!sc->nfe_link) { 2153159967Sobrien if (mii->mii_media_status & IFM_ACTIVE && 2154159967Sobrien IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) { 2155159967Sobrien sc->nfe_link++; 2156159967Sobrien if (IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_T 2157159967Sobrien && bootverbose) 2158159967Sobrien if_printf(sc->nfe_ifp, "gigabit link up\n"); 2159159967Sobrien if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) 2160159967Sobrien nfe_start_locked(ifp); 2161159952Sobrien } 2162159952Sobrien } 2163159967Sobrien callout_reset(&sc->nfe_stat_ch, hz, nfe_tick, sc); 2164159952Sobrien 2165159967Sobrien return; 2166159952Sobrien} 2167159952Sobrien 2168159952Sobrien 2169163503Sobrienstatic void 2170163503Sobriennfe_shutdown(device_t dev) 2171159952Sobrien{ 2172159967Sobrien struct nfe_softc *sc; 2173159967Sobrien struct ifnet *ifp; 2174159952Sobrien 2175159967Sobrien sc = device_get_softc(dev); 2176159952Sobrien 2177159967Sobrien NFE_LOCK(sc); 2178159967Sobrien ifp = sc->nfe_ifp; 2179159967Sobrien nfe_stop(ifp,0); 2180159967Sobrien /* nfe_reset(sc); */ 2181159967Sobrien NFE_UNLOCK(sc); 2182159952Sobrien 2183159967Sobrien return; 2184159952Sobrien} 2185159952Sobrien 2186159952Sobrien 2187163503Sobrienstatic void 2188163503Sobriennfe_get_macaddr(struct nfe_softc *sc, u_char *addr) 2189159952Sobrien{ 2190159952Sobrien uint32_t tmp; 2191159952Sobrien 2192159952Sobrien tmp = NFE_READ(sc, NFE_MACADDR_LO); 2193159952Sobrien addr[0] = (tmp >> 8) & 0xff; 2194159952Sobrien addr[1] = (tmp & 0xff); 2195159952Sobrien 2196159952Sobrien tmp = NFE_READ(sc, NFE_MACADDR_HI); 2197159952Sobrien addr[2] = (tmp >> 24) & 0xff; 2198159952Sobrien addr[3] = (tmp >> 16) & 0xff; 2199159952Sobrien addr[4] = (tmp >> 8) & 0xff; 2200159952Sobrien addr[5] = (tmp & 0xff); 2201159952Sobrien} 2202159952Sobrien 2203163503Sobrien 2204163503Sobrienstatic void 2205163503Sobriennfe_set_macaddr(struct nfe_softc *sc, u_char *addr) 2206159952Sobrien{ 2207159967Sobrien 2208159967Sobrien NFE_WRITE(sc, NFE_MACADDR_LO, addr[5] << 8 | addr[4]); 2209159967Sobrien NFE_WRITE(sc, NFE_MACADDR_HI, addr[3] << 24 | addr[2] << 16 | 2210159967Sobrien addr[1] << 8 | addr[0]); 2211159952Sobrien} 2212159952Sobrien 2213163503Sobrien 2214159967Sobrien/* 2215159967Sobrien * Map a single buffer address. 2216159967Sobrien */ 2217159967Sobrien 2218159967Sobrienstatic void 2219159967Sobriennfe_dma_map_segs(arg, segs, nseg, error) 2220159967Sobrien void *arg; 2221159967Sobrien bus_dma_segment_t *segs; 2222159967Sobrien int error, nseg; 2223159952Sobrien{ 2224159952Sobrien 2225159967Sobrien if (error) 2226159967Sobrien return; 2227159952Sobrien 2228159967Sobrien KASSERT(nseg == 1, ("too many DMA segments, %d should be 1", nseg)); 2229159967Sobrien 2230159967Sobrien *(bus_dma_segment_t *)arg = *segs; 2231159967Sobrien 2232159967Sobrien return; 2233159952Sobrien} 2234