if_nfe.c revision 175418
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 175418 2008-01-17 23:37:47Z jhb $"); 25159952Sobrien 26159967Sobrien#ifdef HAVE_KERNEL_OPTION_HEADERS 27159967Sobrien#include "opt_device_polling.h" 28159967Sobrien#endif 29159967Sobrien 30159952Sobrien#include <sys/param.h> 31159952Sobrien#include <sys/endian.h> 32159952Sobrien#include <sys/systm.h> 33159952Sobrien#include <sys/sockio.h> 34159952Sobrien#include <sys/mbuf.h> 35159952Sobrien#include <sys/malloc.h> 36159967Sobrien#include <sys/module.h> 37159952Sobrien#include <sys/kernel.h> 38170589Syongari#include <sys/queue.h> 39159952Sobrien#include <sys/socket.h> 40170589Syongari#include <sys/sysctl.h> 41159967Sobrien#include <sys/taskqueue.h> 42159952Sobrien 43159952Sobrien#include <net/if.h> 44159967Sobrien#include <net/if_arp.h> 45159967Sobrien#include <net/ethernet.h> 46159952Sobrien#include <net/if_dl.h> 47159952Sobrien#include <net/if_media.h> 48159952Sobrien#include <net/if_types.h> 49159952Sobrien#include <net/if_vlan_var.h> 50159952Sobrien 51159952Sobrien#include <net/bpf.h> 52159952Sobrien 53159967Sobrien#include <machine/bus.h> 54159967Sobrien#include <machine/resource.h> 55159967Sobrien#include <sys/bus.h> 56159967Sobrien#include <sys/rman.h> 57159967Sobrien 58159952Sobrien#include <dev/mii/mii.h> 59159952Sobrien#include <dev/mii/miivar.h> 60159952Sobrien 61159952Sobrien#include <dev/pci/pcireg.h> 62159952Sobrien#include <dev/pci/pcivar.h> 63159952Sobrien 64159967Sobrien#include <dev/nfe/if_nfereg.h> 65159967Sobrien#include <dev/nfe/if_nfevar.h> 66159952Sobrien 67159967SobrienMODULE_DEPEND(nfe, pci, 1, 1, 1); 68159967SobrienMODULE_DEPEND(nfe, ether, 1, 1, 1); 69159967SobrienMODULE_DEPEND(nfe, miibus, 1, 1, 1); 70170589Syongari 71170589Syongari/* "device miibus" required. See GENERIC if you get errors here. */ 72159967Sobrien#include "miibus_if.h" 73159952Sobrien 74163503Sobrienstatic int nfe_probe(device_t); 75163503Sobrienstatic int nfe_attach(device_t); 76163503Sobrienstatic int nfe_detach(device_t); 77170589Syongaristatic int nfe_suspend(device_t); 78170589Syongaristatic int nfe_resume(device_t); 79173839Syongaristatic int nfe_shutdown(device_t); 80170589Syongaristatic void nfe_power(struct nfe_softc *); 81163503Sobrienstatic int nfe_miibus_readreg(device_t, int, int); 82163503Sobrienstatic int nfe_miibus_writereg(device_t, int, int, int); 83163503Sobrienstatic void nfe_miibus_statchg(device_t); 84170589Syongaristatic void nfe_link_task(void *, int); 85170589Syongaristatic void nfe_set_intr(struct nfe_softc *); 86170589Syongaristatic __inline void nfe_enable_intr(struct nfe_softc *); 87170589Syongaristatic __inline void nfe_disable_intr(struct nfe_softc *); 88163503Sobrienstatic int nfe_ioctl(struct ifnet *, u_long, caddr_t); 89170589Syongaristatic void nfe_alloc_msix(struct nfe_softc *, int); 90170589Syongaristatic int nfe_intr(void *); 91170589Syongaristatic void nfe_int_task(void *, int); 92170589Syongaristatic void *nfe_jalloc(struct nfe_softc *); 93170589Syongaristatic void nfe_jfree(void *, void *); 94170589Syongaristatic __inline void nfe_discard_rxbuf(struct nfe_softc *, int); 95170589Syongaristatic __inline void nfe_discard_jrxbuf(struct nfe_softc *, int); 96170589Syongaristatic int nfe_newbuf(struct nfe_softc *, int); 97170589Syongaristatic int nfe_jnewbuf(struct nfe_softc *, int); 98170589Syongaristatic int nfe_rxeof(struct nfe_softc *, int); 99170589Syongaristatic int nfe_jrxeof(struct nfe_softc *, int); 100159967Sobrienstatic void nfe_txeof(struct nfe_softc *); 101170589Syongaristatic int nfe_encap(struct nfe_softc *, struct mbuf **); 102159967Sobrienstatic void nfe_setmulti(struct nfe_softc *); 103170589Syongaristatic void nfe_tx_task(void *, int); 104159967Sobrienstatic void nfe_start(struct ifnet *); 105159967Sobrienstatic void nfe_watchdog(struct ifnet *); 106159967Sobrienstatic void nfe_init(void *); 107159967Sobrienstatic void nfe_init_locked(void *); 108170589Syongaristatic void nfe_stop(struct ifnet *); 109159967Sobrienstatic int nfe_alloc_rx_ring(struct nfe_softc *, struct nfe_rx_ring *); 110171559Syongaristatic void nfe_alloc_jrx_ring(struct nfe_softc *, struct nfe_jrx_ring *); 111170589Syongaristatic int nfe_init_rx_ring(struct nfe_softc *, struct nfe_rx_ring *); 112170589Syongaristatic int nfe_init_jrx_ring(struct nfe_softc *, struct nfe_jrx_ring *); 113159967Sobrienstatic void nfe_free_rx_ring(struct nfe_softc *, struct nfe_rx_ring *); 114170589Syongaristatic void nfe_free_jrx_ring(struct nfe_softc *, struct nfe_jrx_ring *); 115159967Sobrienstatic int nfe_alloc_tx_ring(struct nfe_softc *, struct nfe_tx_ring *); 116170589Syongaristatic void nfe_init_tx_ring(struct nfe_softc *, struct nfe_tx_ring *); 117159967Sobrienstatic void nfe_free_tx_ring(struct nfe_softc *, struct nfe_tx_ring *); 118159967Sobrienstatic int nfe_ifmedia_upd(struct ifnet *); 119159967Sobrienstatic void nfe_ifmedia_sts(struct ifnet *, struct ifmediareq *); 120159967Sobrienstatic void nfe_tick(void *); 121170589Syongaristatic void nfe_get_macaddr(struct nfe_softc *, uint8_t *); 122170589Syongaristatic void nfe_set_macaddr(struct nfe_softc *, uint8_t *); 123170589Syongaristatic void nfe_dma_map_segs(void *, bus_dma_segment_t *, int, int); 124159952Sobrien 125170589Syongaristatic int sysctl_int_range(SYSCTL_HANDLER_ARGS, int, int); 126170589Syongaristatic int sysctl_hw_nfe_proc_limit(SYSCTL_HANDLER_ARGS); 127170589Syongari 128159952Sobrien#ifdef NFE_DEBUG 129170589Syongaristatic int nfedebug = 0; 130170589Syongari#define DPRINTF(sc, ...) do { \ 131170589Syongari if (nfedebug) \ 132170589Syongari device_printf((sc)->nfe_dev, __VA_ARGS__); \ 133170589Syongari} while (0) 134170589Syongari#define DPRINTFN(sc, n, ...) do { \ 135170589Syongari if (nfedebug >= (n)) \ 136170589Syongari device_printf((sc)->nfe_dev, __VA_ARGS__); \ 137170589Syongari} while (0) 138159952Sobrien#else 139170589Syongari#define DPRINTF(sc, ...) 140170589Syongari#define DPRINTFN(sc, n, ...) 141159952Sobrien#endif 142159952Sobrien 143159967Sobrien#define NFE_LOCK(_sc) mtx_lock(&(_sc)->nfe_mtx) 144159967Sobrien#define NFE_UNLOCK(_sc) mtx_unlock(&(_sc)->nfe_mtx) 145159967Sobrien#define NFE_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->nfe_mtx, MA_OWNED) 146159967Sobrien 147170589Syongari#define NFE_JLIST_LOCK(_sc) mtx_lock(&(_sc)->nfe_jlist_mtx) 148170589Syongari#define NFE_JLIST_UNLOCK(_sc) mtx_unlock(&(_sc)->nfe_jlist_mtx) 149159967Sobrien 150170589Syongari/* Tunables. */ 151170589Syongaristatic int msi_disable = 0; 152170589Syongaristatic int msix_disable = 0; 153171559Syongaristatic int jumbo_disable = 0; 154170589SyongariTUNABLE_INT("hw.nfe.msi_disable", &msi_disable); 155170589SyongariTUNABLE_INT("hw.nfe.msix_disable", &msix_disable); 156171559SyongariTUNABLE_INT("hw.nfe.jumbo_disable", &jumbo_disable); 157159967Sobrien 158159967Sobrienstatic device_method_t nfe_methods[] = { 159159967Sobrien /* Device interface */ 160159967Sobrien DEVMETHOD(device_probe, nfe_probe), 161159967Sobrien DEVMETHOD(device_attach, nfe_attach), 162159967Sobrien DEVMETHOD(device_detach, nfe_detach), 163170589Syongari DEVMETHOD(device_suspend, nfe_suspend), 164170589Syongari DEVMETHOD(device_resume, nfe_resume), 165159967Sobrien DEVMETHOD(device_shutdown, nfe_shutdown), 166159967Sobrien 167159967Sobrien /* bus interface */ 168159967Sobrien DEVMETHOD(bus_print_child, bus_generic_print_child), 169159967Sobrien DEVMETHOD(bus_driver_added, bus_generic_driver_added), 170159967Sobrien 171159967Sobrien /* MII interface */ 172159967Sobrien DEVMETHOD(miibus_readreg, nfe_miibus_readreg), 173159967Sobrien DEVMETHOD(miibus_writereg, nfe_miibus_writereg), 174163503Sobrien DEVMETHOD(miibus_statchg, nfe_miibus_statchg), 175159967Sobrien 176170589Syongari { NULL, NULL } 177159952Sobrien}; 178159952Sobrien 179159967Sobrienstatic driver_t nfe_driver = { 180159967Sobrien "nfe", 181159967Sobrien nfe_methods, 182159967Sobrien sizeof(struct nfe_softc) 183159967Sobrien}; 184159967Sobrien 185159967Sobrienstatic devclass_t nfe_devclass; 186159967Sobrien 187159967SobrienDRIVER_MODULE(nfe, pci, nfe_driver, nfe_devclass, 0, 0); 188159967SobrienDRIVER_MODULE(miibus, nfe, miibus_driver, miibus_devclass, 0, 0); 189159967Sobrien 190159967Sobrienstatic struct nfe_type nfe_devs[] = { 191159967Sobrien {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE_LAN, 192163503Sobrien "NVIDIA nForce MCP Networking Adapter"}, 193159967Sobrien {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE2_LAN, 194163503Sobrien "NVIDIA nForce2 MCP2 Networking Adapter"}, 195159967Sobrien {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE2_400_LAN1, 196163503Sobrien "NVIDIA nForce2 400 MCP4 Networking Adapter"}, 197159967Sobrien {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE2_400_LAN2, 198163503Sobrien "NVIDIA nForce2 400 MCP5 Networking Adapter"}, 199163437Sobrien {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE3_LAN1, 200163503Sobrien "NVIDIA nForce3 MCP3 Networking Adapter"}, 201159967Sobrien {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE3_250_LAN, 202163503Sobrien "NVIDIA nForce3 250 MCP6 Networking Adapter"}, 203159967Sobrien {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE3_LAN4, 204163503Sobrien "NVIDIA nForce3 MCP7 Networking Adapter"}, 205159967Sobrien {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE4_LAN1, 206163503Sobrien "NVIDIA nForce4 CK804 MCP8 Networking Adapter"}, 207159967Sobrien {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE4_LAN2, 208163503Sobrien "NVIDIA nForce4 CK804 MCP9 Networking Adapter"}, 209159967Sobrien {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP04_LAN1, 210170589Syongari "NVIDIA nForce MCP04 Networking Adapter"}, /* MCP10 */ 211159967Sobrien {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP04_LAN2, 212170589Syongari "NVIDIA nForce MCP04 Networking Adapter"}, /* MCP11 */ 213159967Sobrien {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE430_LAN1, 214163503Sobrien "NVIDIA nForce 430 MCP12 Networking Adapter"}, 215159967Sobrien {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE430_LAN2, 216163503Sobrien "NVIDIA nForce 430 MCP13 Networking Adapter"}, 217159967Sobrien {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP55_LAN1, 218163503Sobrien "NVIDIA nForce MCP55 Networking Adapter"}, 219159967Sobrien {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP55_LAN2, 220163503Sobrien "NVIDIA nForce MCP55 Networking Adapter"}, 221162212Sobrien {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP61_LAN1, 222163503Sobrien "NVIDIA nForce MCP61 Networking Adapter"}, 223162212Sobrien {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP61_LAN2, 224163503Sobrien "NVIDIA nForce MCP61 Networking Adapter"}, 225162212Sobrien {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP61_LAN3, 226163503Sobrien "NVIDIA nForce MCP61 Networking Adapter"}, 227170589Syongari {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP61_LAN4, 228163503Sobrien "NVIDIA nForce MCP61 Networking Adapter"}, 229162212Sobrien {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP65_LAN1, 230163503Sobrien "NVIDIA nForce MCP65 Networking Adapter"}, 231162212Sobrien {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP65_LAN2, 232163503Sobrien "NVIDIA nForce MCP65 Networking Adapter"}, 233162212Sobrien {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP65_LAN3, 234163503Sobrien "NVIDIA nForce MCP65 Networking Adapter"}, 235170589Syongari {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP65_LAN4, 236163503Sobrien "NVIDIA nForce MCP65 Networking Adapter"}, 237170589Syongari {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP67_LAN1, 238170589Syongari "NVIDIA nForce MCP67 Networking Adapter"}, 239170589Syongari {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP67_LAN2, 240170589Syongari "NVIDIA nForce MCP67 Networking Adapter"}, 241170589Syongari {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP67_LAN3, 242170589Syongari "NVIDIA nForce MCP67 Networking Adapter"}, 243170589Syongari {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP67_LAN4, 244170589Syongari "NVIDIA nForce MCP67 Networking Adapter"}, 245159967Sobrien {0, 0, NULL} 246159967Sobrien}; 247159967Sobrien 248159967Sobrien 249159967Sobrien/* Probe for supported hardware ID's */ 250159967Sobrienstatic int 251159967Sobriennfe_probe(device_t dev) 252159952Sobrien{ 253159967Sobrien struct nfe_type *t; 254159967Sobrien 255159967Sobrien t = nfe_devs; 256159967Sobrien /* Check for matching PCI DEVICE ID's */ 257159967Sobrien while (t->name != NULL) { 258159967Sobrien if ((pci_get_vendor(dev) == t->vid_id) && 259159967Sobrien (pci_get_device(dev) == t->dev_id)) { 260159967Sobrien device_set_desc(dev, t->name); 261170589Syongari return (BUS_PROBE_DEFAULT); 262159967Sobrien } 263159967Sobrien t++; 264159967Sobrien } 265159967Sobrien 266159967Sobrien return (ENXIO); 267159952Sobrien} 268159952Sobrien 269170589Syongaristatic void 270170589Syongarinfe_alloc_msix(struct nfe_softc *sc, int count) 271170589Syongari{ 272170589Syongari int rid; 273163503Sobrien 274170589Syongari rid = PCIR_BAR(2); 275170589Syongari sc->nfe_msix_res = bus_alloc_resource_any(sc->nfe_dev, SYS_RES_MEMORY, 276170589Syongari &rid, RF_ACTIVE); 277170589Syongari if (sc->nfe_msix_res == NULL) { 278170589Syongari device_printf(sc->nfe_dev, 279170589Syongari "couldn't allocate MSIX table resource\n"); 280170589Syongari return; 281170589Syongari } 282170589Syongari rid = PCIR_BAR(3); 283170589Syongari sc->nfe_msix_pba_res = bus_alloc_resource_any(sc->nfe_dev, 284170589Syongari SYS_RES_MEMORY, &rid, RF_ACTIVE); 285170589Syongari if (sc->nfe_msix_pba_res == NULL) { 286170589Syongari device_printf(sc->nfe_dev, 287170589Syongari "couldn't allocate MSIX PBA resource\n"); 288170589Syongari bus_release_resource(sc->nfe_dev, SYS_RES_MEMORY, PCIR_BAR(2), 289170589Syongari sc->nfe_msix_res); 290170589Syongari sc->nfe_msix_res = NULL; 291170589Syongari return; 292170589Syongari } 293170589Syongari 294170589Syongari if (pci_alloc_msix(sc->nfe_dev, &count) == 0) { 295170589Syongari if (count == NFE_MSI_MESSAGES) { 296170589Syongari if (bootverbose) 297170589Syongari device_printf(sc->nfe_dev, 298170589Syongari "Using %d MSIX messages\n", count); 299170589Syongari sc->nfe_msix = 1; 300170589Syongari } else { 301170589Syongari if (bootverbose) 302170589Syongari device_printf(sc->nfe_dev, 303170589Syongari "couldn't allocate MSIX\n"); 304170589Syongari pci_release_msi(sc->nfe_dev); 305170589Syongari bus_release_resource(sc->nfe_dev, SYS_RES_MEMORY, 306170589Syongari PCIR_BAR(3), sc->nfe_msix_pba_res); 307170589Syongari bus_release_resource(sc->nfe_dev, SYS_RES_MEMORY, 308170589Syongari PCIR_BAR(2), sc->nfe_msix_res); 309170589Syongari sc->nfe_msix_pba_res = NULL; 310170589Syongari sc->nfe_msix_res = NULL; 311170589Syongari } 312170589Syongari } 313170589Syongari} 314170589Syongari 315159967Sobrienstatic int 316159967Sobriennfe_attach(device_t dev) 317159952Sobrien{ 318159967Sobrien struct nfe_softc *sc; 319159952Sobrien struct ifnet *ifp; 320170589Syongari bus_addr_t dma_addr_max; 321170589Syongari int error = 0, i, msic, reg, rid; 322159952Sobrien 323159967Sobrien sc = device_get_softc(dev); 324159967Sobrien sc->nfe_dev = dev; 325159952Sobrien 326159967Sobrien mtx_init(&sc->nfe_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK, 327170589Syongari MTX_DEF); 328170589Syongari mtx_init(&sc->nfe_jlist_mtx, "nfe_jlist_mtx", NULL, MTX_DEF); 329159967Sobrien callout_init_mtx(&sc->nfe_stat_ch, &sc->nfe_mtx, 0); 330170589Syongari TASK_INIT(&sc->nfe_link_task, 0, nfe_link_task, sc); 331170589Syongari SLIST_INIT(&sc->nfe_jfree_listhead); 332170589Syongari SLIST_INIT(&sc->nfe_jinuse_listhead); 333159967Sobrien 334163503Sobrien pci_enable_busmaster(dev); 335159967Sobrien 336170589Syongari rid = PCIR_BAR(0); 337170589Syongari sc->nfe_res[0] = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 338170589Syongari RF_ACTIVE); 339170589Syongari if (sc->nfe_res[0] == NULL) { 340170589Syongari device_printf(dev, "couldn't map memory resources\n"); 341170589Syongari mtx_destroy(&sc->nfe_mtx); 342170589Syongari return (ENXIO); 343170589Syongari } 344159967Sobrien 345170589Syongari if (pci_find_extcap(dev, PCIY_EXPRESS, ®) == 0) { 346170589Syongari uint16_t v, width; 347170589Syongari 348170589Syongari v = pci_read_config(dev, reg + 0x08, 2); 349170589Syongari /* Change max. read request size to 4096. */ 350170589Syongari v &= ~(7 << 12); 351170589Syongari v |= (5 << 12); 352170589Syongari pci_write_config(dev, reg + 0x08, v, 2); 353170589Syongari 354170589Syongari v = pci_read_config(dev, reg + 0x0c, 2); 355170589Syongari /* link capability */ 356170589Syongari v = (v >> 4) & 0x0f; 357170589Syongari width = pci_read_config(dev, reg + 0x12, 2); 358170589Syongari /* negotiated link width */ 359170589Syongari width = (width >> 4) & 0x3f; 360170589Syongari if (v != width) 361170589Syongari device_printf(sc->nfe_dev, 362170589Syongari "warning, negotiated width of link(x%d) != " 363170589Syongari "max. width of link(x%d)\n", width, v); 364159952Sobrien } 365159952Sobrien 366159967Sobrien /* Allocate interrupt */ 367170589Syongari if (msix_disable == 0 || msi_disable == 0) { 368170589Syongari if (msix_disable == 0 && 369170589Syongari (msic = pci_msix_count(dev)) == NFE_MSI_MESSAGES) 370170589Syongari nfe_alloc_msix(sc, msic); 371170589Syongari if (msi_disable == 0 && sc->nfe_msix == 0 && 372170589Syongari (msic = pci_msi_count(dev)) == NFE_MSI_MESSAGES && 373170589Syongari pci_alloc_msi(dev, &msic) == 0) { 374170589Syongari if (msic == NFE_MSI_MESSAGES) { 375170589Syongari if (bootverbose) 376170589Syongari device_printf(dev, 377170589Syongari "Using %d MSI messages\n", msic); 378170589Syongari sc->nfe_msi = 1; 379170589Syongari } else 380170589Syongari pci_release_msi(dev); 381170589Syongari } 382170589Syongari } 383159967Sobrien 384170589Syongari if (sc->nfe_msix == 0 && sc->nfe_msi == 0) { 385170589Syongari rid = 0; 386170589Syongari sc->nfe_irq[0] = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, 387170589Syongari RF_SHAREABLE | RF_ACTIVE); 388170589Syongari if (sc->nfe_irq[0] == NULL) { 389170589Syongari device_printf(dev, "couldn't allocate IRQ resources\n"); 390170589Syongari error = ENXIO; 391170589Syongari goto fail; 392170589Syongari } 393170589Syongari } else { 394170589Syongari for (i = 0, rid = 1; i < NFE_MSI_MESSAGES; i++, rid++) { 395170589Syongari sc->nfe_irq[i] = bus_alloc_resource_any(dev, 396170589Syongari SYS_RES_IRQ, &rid, RF_ACTIVE); 397170589Syongari if (sc->nfe_irq[i] == NULL) { 398170589Syongari device_printf(dev, 399170589Syongari "couldn't allocate IRQ resources for " 400170589Syongari "message %d\n", rid); 401170589Syongari error = ENXIO; 402170589Syongari goto fail; 403170589Syongari } 404170589Syongari } 405170589Syongari /* Map interrupts to vector 0. */ 406170589Syongari if (sc->nfe_msix != 0) { 407170589Syongari NFE_WRITE(sc, NFE_MSIX_MAP0, 0); 408170589Syongari NFE_WRITE(sc, NFE_MSIX_MAP1, 0); 409170589Syongari } else if (sc->nfe_msi != 0) { 410170589Syongari NFE_WRITE(sc, NFE_MSI_MAP0, 0); 411170589Syongari NFE_WRITE(sc, NFE_MSI_MAP1, 0); 412170589Syongari } 413159952Sobrien } 414159952Sobrien 415170589Syongari /* Set IRQ status/mask register. */ 416170589Syongari sc->nfe_irq_status = NFE_IRQ_STATUS; 417170589Syongari sc->nfe_irq_mask = NFE_IRQ_MASK; 418170589Syongari sc->nfe_intrs = NFE_IRQ_WANTED; 419170589Syongari sc->nfe_nointrs = 0; 420170589Syongari if (sc->nfe_msix != 0) { 421170589Syongari sc->nfe_irq_status = NFE_MSIX_IRQ_STATUS; 422170589Syongari sc->nfe_nointrs = NFE_IRQ_WANTED; 423170589Syongari } else if (sc->nfe_msi != 0) { 424170589Syongari sc->nfe_irq_mask = NFE_MSI_IRQ_MASK; 425170589Syongari sc->nfe_intrs = NFE_MSI_VECTOR_0_ENABLED; 426170589Syongari } 427159952Sobrien 428170589Syongari sc->nfe_devid = pci_get_device(dev); 429170589Syongari sc->nfe_revid = pci_get_revid(dev); 430159967Sobrien sc->nfe_flags = 0; 431159952Sobrien 432170589Syongari switch (sc->nfe_devid) { 433159952Sobrien case PCI_PRODUCT_NVIDIA_NFORCE3_LAN2: 434159952Sobrien case PCI_PRODUCT_NVIDIA_NFORCE3_LAN3: 435159952Sobrien case PCI_PRODUCT_NVIDIA_NFORCE3_LAN4: 436159952Sobrien case PCI_PRODUCT_NVIDIA_NFORCE3_LAN5: 437159967Sobrien sc->nfe_flags |= NFE_JUMBO_SUP | NFE_HW_CSUM; 438159952Sobrien break; 439159952Sobrien case PCI_PRODUCT_NVIDIA_MCP51_LAN1: 440159952Sobrien case PCI_PRODUCT_NVIDIA_MCP51_LAN2: 441170589Syongari sc->nfe_flags |= NFE_40BIT_ADDR | NFE_PWR_MGMT; 442159952Sobrien break; 443159952Sobrien case PCI_PRODUCT_NVIDIA_CK804_LAN1: 444159952Sobrien case PCI_PRODUCT_NVIDIA_CK804_LAN2: 445159952Sobrien case PCI_PRODUCT_NVIDIA_MCP04_LAN1: 446159952Sobrien case PCI_PRODUCT_NVIDIA_MCP04_LAN2: 447159967Sobrien sc->nfe_flags |= NFE_JUMBO_SUP | NFE_40BIT_ADDR | NFE_HW_CSUM; 448159952Sobrien break; 449159952Sobrien case PCI_PRODUCT_NVIDIA_MCP55_LAN1: 450159952Sobrien case PCI_PRODUCT_NVIDIA_MCP55_LAN2: 451163503Sobrien sc->nfe_flags |= NFE_JUMBO_SUP | NFE_40BIT_ADDR | NFE_HW_CSUM | 452170589Syongari NFE_HW_VLAN | NFE_PWR_MGMT | NFE_TX_FLOW_CTRL; 453159952Sobrien break; 454170589Syongari 455162212Sobrien case PCI_PRODUCT_NVIDIA_MCP61_LAN1: 456162212Sobrien case PCI_PRODUCT_NVIDIA_MCP61_LAN2: 457162212Sobrien case PCI_PRODUCT_NVIDIA_MCP61_LAN3: 458162212Sobrien case PCI_PRODUCT_NVIDIA_MCP61_LAN4: 459170589Syongari case PCI_PRODUCT_NVIDIA_MCP67_LAN1: 460170589Syongari case PCI_PRODUCT_NVIDIA_MCP67_LAN2: 461170589Syongari case PCI_PRODUCT_NVIDIA_MCP67_LAN3: 462170589Syongari case PCI_PRODUCT_NVIDIA_MCP67_LAN4: 463170589Syongari sc->nfe_flags |= NFE_40BIT_ADDR | NFE_PWR_MGMT | 464173377Syongari NFE_CORRECT_MACADDR | NFE_TX_FLOW_CTRL; 465162212Sobrien break; 466162212Sobrien case PCI_PRODUCT_NVIDIA_MCP65_LAN1: 467162212Sobrien case PCI_PRODUCT_NVIDIA_MCP65_LAN2: 468162212Sobrien case PCI_PRODUCT_NVIDIA_MCP65_LAN3: 469162212Sobrien case PCI_PRODUCT_NVIDIA_MCP65_LAN4: 470170589Syongari sc->nfe_flags |= NFE_JUMBO_SUP | NFE_40BIT_ADDR | 471173377Syongari NFE_PWR_MGMT | NFE_CORRECT_MACADDR | NFE_TX_FLOW_CTRL; 472163503Sobrien break; 473159952Sobrien } 474159952Sobrien 475170589Syongari nfe_power(sc); 476170589Syongari /* Check for reversed ethernet address */ 477170589Syongari if ((NFE_READ(sc, NFE_TX_UNK) & NFE_MAC_ADDR_INORDER) != 0) 478170589Syongari sc->nfe_flags |= NFE_CORRECT_MACADDR; 479170589Syongari nfe_get_macaddr(sc, sc->eaddr); 480159952Sobrien /* 481159967Sobrien * Allocate the parent bus DMA tag appropriate for PCI. 482159967Sobrien */ 483170589Syongari dma_addr_max = BUS_SPACE_MAXADDR_32BIT; 484170589Syongari if ((sc->nfe_flags & NFE_40BIT_ADDR) != 0) 485170589Syongari dma_addr_max = NFE_DMA_MAXADDR; 486170589Syongari error = bus_dma_tag_create( 487170589Syongari bus_get_dma_tag(sc->nfe_dev), /* parent */ 488163503Sobrien 1, 0, /* alignment, boundary */ 489170589Syongari dma_addr_max, /* lowaddr */ 490163503Sobrien BUS_SPACE_MAXADDR, /* highaddr */ 491163503Sobrien NULL, NULL, /* filter, filterarg */ 492170589Syongari BUS_SPACE_MAXSIZE_32BIT, 0, /* maxsize, nsegments */ 493163503Sobrien BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ 494170589Syongari 0, /* flags */ 495163503Sobrien NULL, NULL, /* lockfunc, lockarg */ 496163503Sobrien &sc->nfe_parent_tag); 497159967Sobrien if (error) 498159967Sobrien goto fail; 499159967Sobrien 500164650Sobrien ifp = sc->nfe_ifp = if_alloc(IFT_ETHER); 501164650Sobrien if (ifp == NULL) { 502170589Syongari device_printf(dev, "can not if_alloc()\n"); 503164650Sobrien error = ENOSPC; 504164650Sobrien goto fail; 505164650Sobrien } 506170589Syongari TASK_INIT(&sc->nfe_tx_task, 1, nfe_tx_task, ifp); 507164650Sobrien 508159967Sobrien /* 509159952Sobrien * Allocate Tx and Rx rings. 510159952Sobrien */ 511170589Syongari if ((error = nfe_alloc_tx_ring(sc, &sc->txq)) != 0) 512159967Sobrien goto fail; 513159952Sobrien 514170589Syongari if ((error = nfe_alloc_rx_ring(sc, &sc->rxq)) != 0) 515159967Sobrien goto fail; 516170589Syongari 517171559Syongari nfe_alloc_jrx_ring(sc, &sc->jrxq); 518170589Syongari 519170589Syongari SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), 520170589Syongari SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), 521170589Syongari OID_AUTO, "process_limit", CTLTYPE_INT | CTLFLAG_RW, 522170589Syongari &sc->nfe_process_limit, 0, sysctl_hw_nfe_proc_limit, "I", 523170589Syongari "max number of Rx events to process"); 524170589Syongari 525170589Syongari sc->nfe_process_limit = NFE_PROC_DEFAULT; 526170589Syongari error = resource_int_value(device_get_name(dev), device_get_unit(dev), 527170589Syongari "process_limit", &sc->nfe_process_limit); 528170589Syongari if (error == 0) { 529170589Syongari if (sc->nfe_process_limit < NFE_PROC_MIN || 530170589Syongari sc->nfe_process_limit > NFE_PROC_MAX) { 531170589Syongari device_printf(dev, "process_limit value out of range; " 532170589Syongari "using default: %d\n", NFE_PROC_DEFAULT); 533170589Syongari sc->nfe_process_limit = NFE_PROC_DEFAULT; 534170589Syongari } 535159952Sobrien } 536159952Sobrien 537159952Sobrien ifp->if_softc = sc; 538159967Sobrien if_initname(ifp, device_get_name(dev), device_get_unit(dev)); 539170589Syongari ifp->if_mtu = ETHERMTU; 540159952Sobrien ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 541159952Sobrien ifp->if_ioctl = nfe_ioctl; 542159952Sobrien ifp->if_start = nfe_start; 543170589Syongari ifp->if_hwassist = 0; 544170589Syongari ifp->if_capabilities = 0; 545170589Syongari ifp->if_watchdog = NULL; 546159952Sobrien ifp->if_init = nfe_init; 547170589Syongari IFQ_SET_MAXLEN(&ifp->if_snd, NFE_TX_RING_COUNT - 1); 548170589Syongari ifp->if_snd.ifq_drv_maxlen = NFE_TX_RING_COUNT - 1; 549170589Syongari IFQ_SET_READY(&ifp->if_snd); 550159952Sobrien 551170589Syongari if (sc->nfe_flags & NFE_HW_CSUM) { 552170589Syongari ifp->if_capabilities |= IFCAP_HWCSUM | IFCAP_TSO4; 553170589Syongari ifp->if_hwassist |= NFE_CSUM_FEATURES | CSUM_TSO; 554170589Syongari } 555170589Syongari ifp->if_capenable = ifp->if_capabilities; 556164650Sobrien 557170589Syongari sc->nfe_framesize = ifp->if_mtu + NFE_RX_HEADERS; 558170589Syongari /* VLAN capability setup. */ 559170589Syongari ifp->if_capabilities |= IFCAP_VLAN_MTU; 560170589Syongari if ((sc->nfe_flags & NFE_HW_VLAN) != 0) { 561159952Sobrien ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING; 562170589Syongari if ((ifp->if_capabilities & IFCAP_HWCSUM) != 0) 563170589Syongari ifp->if_capabilities |= IFCAP_VLAN_HWCSUM; 564159952Sobrien } 565159967Sobrien ifp->if_capenable = ifp->if_capabilities; 566159952Sobrien 567170589Syongari /* 568170589Syongari * Tell the upper layer(s) we support long frames. 569170589Syongari * Must appear after the call to ether_ifattach() because 570170589Syongari * ether_ifattach() sets ifi_hdrlen to the default value. 571170589Syongari */ 572170589Syongari ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header); 573170589Syongari 574159967Sobrien#ifdef DEVICE_POLLING 575159967Sobrien ifp->if_capabilities |= IFCAP_POLLING; 576159967Sobrien#endif 577159952Sobrien 578159967Sobrien /* Do MII setup */ 579163503Sobrien if (mii_phy_probe(dev, &sc->nfe_miibus, nfe_ifmedia_upd, 580163503Sobrien nfe_ifmedia_sts)) { 581170589Syongari device_printf(dev, "MII without any phy!\n"); 582159967Sobrien error = ENXIO; 583159967Sobrien goto fail; 584159967Sobrien } 585159967Sobrien ether_ifattach(ifp, sc->eaddr); 586159952Sobrien 587170589Syongari TASK_INIT(&sc->nfe_int_task, 0, nfe_int_task, sc); 588170589Syongari sc->nfe_tq = taskqueue_create_fast("nfe_taskq", M_WAITOK, 589170589Syongari taskqueue_thread_enqueue, &sc->nfe_tq); 590170589Syongari taskqueue_start_threads(&sc->nfe_tq, 1, PI_NET, "%s taskq", 591170589Syongari device_get_nameunit(sc->nfe_dev)); 592170589Syongari error = 0; 593170589Syongari if (sc->nfe_msi == 0 && sc->nfe_msix == 0) { 594170589Syongari error = bus_setup_intr(dev, sc->nfe_irq[0], 595170589Syongari INTR_TYPE_NET | INTR_MPSAFE, nfe_intr, NULL, sc, 596170589Syongari &sc->nfe_intrhand[0]); 597170589Syongari } else { 598170589Syongari for (i = 0; i < NFE_MSI_MESSAGES; i++) { 599170589Syongari error = bus_setup_intr(dev, sc->nfe_irq[i], 600170589Syongari INTR_TYPE_NET | INTR_MPSAFE, nfe_intr, NULL, sc, 601170589Syongari &sc->nfe_intrhand[i]); 602170589Syongari if (error != 0) 603170589Syongari break; 604170589Syongari } 605170589Syongari } 606159967Sobrien if (error) { 607170589Syongari device_printf(dev, "couldn't set up irq\n"); 608170589Syongari taskqueue_free(sc->nfe_tq); 609170589Syongari sc->nfe_tq = NULL; 610159967Sobrien ether_ifdetach(ifp); 611159967Sobrien goto fail; 612159967Sobrien } 613159967Sobrien 614159967Sobrienfail: 615159967Sobrien if (error) 616159967Sobrien nfe_detach(dev); 617159967Sobrien 618159967Sobrien return (error); 619159952Sobrien} 620159952Sobrien 621159967Sobrien 622159967Sobrienstatic int 623159967Sobriennfe_detach(device_t dev) 624159952Sobrien{ 625163503Sobrien struct nfe_softc *sc; 626163503Sobrien struct ifnet *ifp; 627170589Syongari uint8_t eaddr[ETHER_ADDR_LEN]; 628170589Syongari int i, rid; 629159952Sobrien 630159967Sobrien sc = device_get_softc(dev); 631159967Sobrien KASSERT(mtx_initialized(&sc->nfe_mtx), ("nfe mutex not initialized")); 632159967Sobrien ifp = sc->nfe_ifp; 633159967Sobrien 634159967Sobrien#ifdef DEVICE_POLLING 635170589Syongari if (ifp != NULL && ifp->if_capenable & IFCAP_POLLING) 636159967Sobrien ether_poll_deregister(ifp); 637159967Sobrien#endif 638159967Sobrien if (device_is_attached(dev)) { 639164649Sobrien NFE_LOCK(sc); 640170589Syongari nfe_stop(ifp); 641159967Sobrien ifp->if_flags &= ~IFF_UP; 642164649Sobrien NFE_UNLOCK(sc); 643159967Sobrien callout_drain(&sc->nfe_stat_ch); 644170589Syongari taskqueue_drain(taskqueue_fast, &sc->nfe_tx_task); 645170589Syongari taskqueue_drain(taskqueue_swi, &sc->nfe_link_task); 646159967Sobrien ether_ifdetach(ifp); 647159967Sobrien } 648159967Sobrien 649170589Syongari if (ifp) { 650170589Syongari /* restore ethernet address */ 651170589Syongari if ((sc->nfe_flags & NFE_CORRECT_MACADDR) == 0) { 652170589Syongari for (i = 0; i < ETHER_ADDR_LEN; i++) { 653170589Syongari eaddr[i] = sc->eaddr[5 - i]; 654170589Syongari } 655170589Syongari } else 656170589Syongari bcopy(sc->eaddr, eaddr, ETHER_ADDR_LEN); 657170589Syongari nfe_set_macaddr(sc, eaddr); 658159967Sobrien if_free(ifp); 659170589Syongari } 660159967Sobrien if (sc->nfe_miibus) 661159967Sobrien device_delete_child(dev, sc->nfe_miibus); 662159967Sobrien bus_generic_detach(dev); 663170589Syongari if (sc->nfe_tq != NULL) { 664170589Syongari taskqueue_drain(sc->nfe_tq, &sc->nfe_int_task); 665170589Syongari taskqueue_free(sc->nfe_tq); 666170589Syongari sc->nfe_tq = NULL; 667170589Syongari } 668159967Sobrien 669170589Syongari for (i = 0; i < NFE_MSI_MESSAGES; i++) { 670170589Syongari if (sc->nfe_intrhand[i] != NULL) { 671170589Syongari bus_teardown_intr(dev, sc->nfe_irq[i], 672170589Syongari sc->nfe_intrhand[i]); 673170589Syongari sc->nfe_intrhand[i] = NULL; 674170589Syongari } 675170589Syongari } 676159967Sobrien 677170589Syongari if (sc->nfe_msi == 0 && sc->nfe_msix == 0) { 678170589Syongari if (sc->nfe_irq[0] != NULL) 679170589Syongari bus_release_resource(dev, SYS_RES_IRQ, 0, 680170589Syongari sc->nfe_irq[0]); 681170589Syongari } else { 682170589Syongari for (i = 0, rid = 1; i < NFE_MSI_MESSAGES; i++, rid++) { 683170589Syongari if (sc->nfe_irq[i] != NULL) { 684170589Syongari bus_release_resource(dev, SYS_RES_IRQ, rid, 685170589Syongari sc->nfe_irq[i]); 686170589Syongari sc->nfe_irq[i] = NULL; 687170589Syongari } 688170589Syongari } 689170589Syongari pci_release_msi(dev); 690170589Syongari } 691170589Syongari if (sc->nfe_msix_pba_res != NULL) { 692170589Syongari bus_release_resource(dev, SYS_RES_MEMORY, PCIR_BAR(3), 693170589Syongari sc->nfe_msix_pba_res); 694170589Syongari sc->nfe_msix_pba_res = NULL; 695170589Syongari } 696170589Syongari if (sc->nfe_msix_res != NULL) { 697170589Syongari bus_release_resource(dev, SYS_RES_MEMORY, PCIR_BAR(2), 698170589Syongari sc->nfe_msix_res); 699170589Syongari sc->nfe_msix_res = NULL; 700170589Syongari } 701170589Syongari if (sc->nfe_res[0] != NULL) { 702170589Syongari bus_release_resource(dev, SYS_RES_MEMORY, PCIR_BAR(0), 703170589Syongari sc->nfe_res[0]); 704170589Syongari sc->nfe_res[0] = NULL; 705170589Syongari } 706170589Syongari 707159967Sobrien nfe_free_tx_ring(sc, &sc->txq); 708159967Sobrien nfe_free_rx_ring(sc, &sc->rxq); 709170589Syongari nfe_free_jrx_ring(sc, &sc->jrxq); 710159967Sobrien 711170589Syongari if (sc->nfe_parent_tag) { 712159967Sobrien bus_dma_tag_destroy(sc->nfe_parent_tag); 713170589Syongari sc->nfe_parent_tag = NULL; 714170589Syongari } 715159967Sobrien 716170589Syongari mtx_destroy(&sc->nfe_jlist_mtx); 717159967Sobrien mtx_destroy(&sc->nfe_mtx); 718159967Sobrien 719159967Sobrien return (0); 720159952Sobrien} 721159952Sobrien 722159967Sobrien 723170589Syongaristatic int 724170589Syongarinfe_suspend(device_t dev) 725170589Syongari{ 726170589Syongari struct nfe_softc *sc; 727170589Syongari 728170589Syongari sc = device_get_softc(dev); 729170589Syongari 730170589Syongari NFE_LOCK(sc); 731170589Syongari nfe_stop(sc->nfe_ifp); 732170589Syongari sc->nfe_suspended = 1; 733170589Syongari NFE_UNLOCK(sc); 734170589Syongari 735170589Syongari return (0); 736170589Syongari} 737170589Syongari 738170589Syongari 739170589Syongaristatic int 740170589Syongarinfe_resume(device_t dev) 741170589Syongari{ 742170589Syongari struct nfe_softc *sc; 743170589Syongari struct ifnet *ifp; 744170589Syongari 745170589Syongari sc = device_get_softc(dev); 746170589Syongari 747170589Syongari NFE_LOCK(sc); 748170589Syongari ifp = sc->nfe_ifp; 749170589Syongari if (ifp->if_flags & IFF_UP) 750170589Syongari nfe_init_locked(sc); 751170589Syongari sc->nfe_suspended = 0; 752170589Syongari NFE_UNLOCK(sc); 753170589Syongari 754170589Syongari return (0); 755170589Syongari} 756170589Syongari 757170589Syongari 758170589Syongari/* Take PHY/NIC out of powerdown, from Linux */ 759159967Sobrienstatic void 760170589Syongarinfe_power(struct nfe_softc *sc) 761170589Syongari{ 762170589Syongari uint32_t pwr; 763170589Syongari 764170589Syongari if ((sc->nfe_flags & NFE_PWR_MGMT) == 0) 765170589Syongari return; 766170589Syongari NFE_WRITE(sc, NFE_RXTX_CTL, NFE_RXTX_RESET | NFE_RXTX_BIT2); 767170589Syongari NFE_WRITE(sc, NFE_MAC_RESET, NFE_MAC_RESET_MAGIC); 768170589Syongari DELAY(100); 769170589Syongari NFE_WRITE(sc, NFE_MAC_RESET, 0); 770170589Syongari DELAY(100); 771170589Syongari NFE_WRITE(sc, NFE_RXTX_CTL, NFE_RXTX_BIT2); 772170589Syongari pwr = NFE_READ(sc, NFE_PWR2_CTL); 773170589Syongari pwr &= ~NFE_PWR2_WAKEUP_MASK; 774170589Syongari if (sc->nfe_revid >= 0xa3 && 775170589Syongari (sc->nfe_devid == PCI_PRODUCT_NVIDIA_NFORCE430_LAN1 || 776170589Syongari sc->nfe_devid == PCI_PRODUCT_NVIDIA_NFORCE430_LAN2)) 777170589Syongari pwr |= NFE_PWR2_REVA3; 778170589Syongari NFE_WRITE(sc, NFE_PWR2_CTL, pwr); 779170589Syongari} 780170589Syongari 781170589Syongari 782170589Syongaristatic void 783159967Sobriennfe_miibus_statchg(device_t dev) 784159952Sobrien{ 785159967Sobrien struct nfe_softc *sc; 786170589Syongari 787170589Syongari sc = device_get_softc(dev); 788170589Syongari taskqueue_enqueue(taskqueue_swi, &sc->nfe_link_task); 789170589Syongari} 790170589Syongari 791170589Syongari 792170589Syongaristatic void 793170589Syongarinfe_link_task(void *arg, int pending) 794170589Syongari{ 795170589Syongari struct nfe_softc *sc; 796159967Sobrien struct mii_data *mii; 797170589Syongari struct ifnet *ifp; 798170589Syongari uint32_t phy, seed, misc = NFE_MISC1_MAGIC, link = NFE_MEDIA_SET; 799170589Syongari uint32_t gmask, rxctl, txctl, val; 800159952Sobrien 801170589Syongari sc = (struct nfe_softc *)arg; 802170589Syongari 803170589Syongari NFE_LOCK(sc); 804170589Syongari 805159967Sobrien mii = device_get_softc(sc->nfe_miibus); 806170589Syongari ifp = sc->nfe_ifp; 807170589Syongari if (mii == NULL || ifp == NULL) { 808170589Syongari NFE_UNLOCK(sc); 809170589Syongari return; 810170589Syongari } 811159967Sobrien 812170589Syongari if (mii->mii_media_status & IFM_ACTIVE) { 813170589Syongari if (IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) 814170589Syongari sc->nfe_link = 1; 815170589Syongari } else 816170589Syongari sc->nfe_link = 0; 817170589Syongari 818159952Sobrien phy = NFE_READ(sc, NFE_PHY_IFACE); 819159952Sobrien phy &= ~(NFE_PHY_HDX | NFE_PHY_100TX | NFE_PHY_1000T); 820159952Sobrien 821159952Sobrien seed = NFE_READ(sc, NFE_RNDSEED); 822159952Sobrien seed &= ~NFE_SEED_MASK; 823159952Sobrien 824170589Syongari if (((mii->mii_media_active & IFM_GMASK) & IFM_FDX) == 0) { 825159952Sobrien phy |= NFE_PHY_HDX; /* half-duplex */ 826159952Sobrien misc |= NFE_MISC1_HDX; 827159952Sobrien } 828159952Sobrien 829159952Sobrien switch (IFM_SUBTYPE(mii->mii_media_active)) { 830159952Sobrien case IFM_1000_T: /* full-duplex only */ 831159952Sobrien link |= NFE_MEDIA_1000T; 832159952Sobrien seed |= NFE_SEED_1000T; 833159952Sobrien phy |= NFE_PHY_1000T; 834159952Sobrien break; 835159952Sobrien case IFM_100_TX: 836159952Sobrien link |= NFE_MEDIA_100TX; 837159952Sobrien seed |= NFE_SEED_100TX; 838159952Sobrien phy |= NFE_PHY_100TX; 839159952Sobrien break; 840159952Sobrien case IFM_10_T: 841159952Sobrien link |= NFE_MEDIA_10T; 842159952Sobrien seed |= NFE_SEED_10T; 843159952Sobrien break; 844159952Sobrien } 845159952Sobrien 846170589Syongari if ((phy & 0x10000000) != 0) { 847170589Syongari if (IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_T) 848170589Syongari val = NFE_R1_MAGIC_1000; 849170589Syongari else 850170589Syongari val = NFE_R1_MAGIC_10_100; 851170589Syongari } else 852170589Syongari val = NFE_R1_MAGIC_DEFAULT; 853170589Syongari NFE_WRITE(sc, NFE_SETUP_R1, val); 854170589Syongari 855159952Sobrien NFE_WRITE(sc, NFE_RNDSEED, seed); /* XXX: gigabit NICs only? */ 856159952Sobrien 857159952Sobrien NFE_WRITE(sc, NFE_PHY_IFACE, phy); 858159952Sobrien NFE_WRITE(sc, NFE_MISC1, misc); 859159952Sobrien NFE_WRITE(sc, NFE_LINKSPEED, link); 860170589Syongari 861170589Syongari gmask = mii->mii_media_active & IFM_GMASK; 862170589Syongari if ((gmask & IFM_FDX) != 0) { 863170589Syongari /* It seems all hardwares supports Rx pause frames. */ 864170589Syongari val = NFE_READ(sc, NFE_RXFILTER); 865170589Syongari if ((gmask & IFM_FLAG0) != 0) 866170589Syongari val |= NFE_PFF_RX_PAUSE; 867170589Syongari else 868170589Syongari val &= ~NFE_PFF_RX_PAUSE; 869170589Syongari NFE_WRITE(sc, NFE_RXFILTER, val); 870170589Syongari if ((sc->nfe_flags & NFE_TX_FLOW_CTRL) != 0) { 871170589Syongari val = NFE_READ(sc, NFE_MISC1); 872170589Syongari if ((gmask & IFM_FLAG1) != 0) { 873170589Syongari NFE_WRITE(sc, NFE_TX_PAUSE_FRAME, 874170589Syongari NFE_TX_PAUSE_FRAME_ENABLE); 875170589Syongari val |= NFE_MISC1_TX_PAUSE; 876170589Syongari } else { 877170589Syongari val &= ~NFE_MISC1_TX_PAUSE; 878170589Syongari NFE_WRITE(sc, NFE_TX_PAUSE_FRAME, 879170589Syongari NFE_TX_PAUSE_FRAME_DISABLE); 880170589Syongari } 881170589Syongari NFE_WRITE(sc, NFE_MISC1, val); 882170589Syongari } 883170589Syongari } else { 884170589Syongari /* disable rx/tx pause frames */ 885170589Syongari val = NFE_READ(sc, NFE_RXFILTER); 886170589Syongari val &= ~NFE_PFF_RX_PAUSE; 887170589Syongari NFE_WRITE(sc, NFE_RXFILTER, val); 888170589Syongari if ((sc->nfe_flags & NFE_TX_FLOW_CTRL) != 0) { 889170589Syongari NFE_WRITE(sc, NFE_TX_PAUSE_FRAME, 890170589Syongari NFE_TX_PAUSE_FRAME_DISABLE); 891170589Syongari val = NFE_READ(sc, NFE_MISC1); 892170589Syongari val &= ~NFE_MISC1_TX_PAUSE; 893170589Syongari NFE_WRITE(sc, NFE_MISC1, val); 894170589Syongari } 895170589Syongari } 896170589Syongari 897170589Syongari txctl = NFE_READ(sc, NFE_TX_CTL); 898170589Syongari rxctl = NFE_READ(sc, NFE_RX_CTL); 899170589Syongari if (sc->nfe_link != 0 && (ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) { 900170589Syongari txctl |= NFE_TX_START; 901170589Syongari rxctl |= NFE_RX_START; 902170589Syongari } else { 903170589Syongari txctl &= ~NFE_TX_START; 904170589Syongari rxctl &= ~NFE_RX_START; 905170589Syongari } 906172164Syongari NFE_WRITE(sc, NFE_TX_CTL, txctl); 907172164Syongari NFE_WRITE(sc, NFE_RX_CTL, rxctl); 908170589Syongari 909170589Syongari NFE_UNLOCK(sc); 910159952Sobrien} 911159952Sobrien 912163503Sobrien 913159967Sobrienstatic int 914159967Sobriennfe_miibus_readreg(device_t dev, int phy, int reg) 915159952Sobrien{ 916159967Sobrien struct nfe_softc *sc = device_get_softc(dev); 917170589Syongari uint32_t val; 918159952Sobrien int ntries; 919159952Sobrien 920159952Sobrien NFE_WRITE(sc, NFE_PHY_STATUS, 0xf); 921159952Sobrien 922159952Sobrien if (NFE_READ(sc, NFE_PHY_CTL) & NFE_PHY_BUSY) { 923159952Sobrien NFE_WRITE(sc, NFE_PHY_CTL, NFE_PHY_BUSY); 924159952Sobrien DELAY(100); 925159952Sobrien } 926159952Sobrien 927159952Sobrien NFE_WRITE(sc, NFE_PHY_CTL, (phy << NFE_PHYADD_SHIFT) | reg); 928159952Sobrien 929170589Syongari for (ntries = 0; ntries < NFE_TIMEOUT; ntries++) { 930159952Sobrien DELAY(100); 931159952Sobrien if (!(NFE_READ(sc, NFE_PHY_CTL) & NFE_PHY_BUSY)) 932159952Sobrien break; 933159952Sobrien } 934170589Syongari if (ntries == NFE_TIMEOUT) { 935170589Syongari DPRINTFN(sc, 2, "timeout waiting for PHY\n"); 936159952Sobrien return 0; 937159952Sobrien } 938159952Sobrien 939159952Sobrien if (NFE_READ(sc, NFE_PHY_STATUS) & NFE_PHY_ERROR) { 940170589Syongari DPRINTFN(sc, 2, "could not read PHY\n"); 941159952Sobrien return 0; 942159952Sobrien } 943159952Sobrien 944159952Sobrien val = NFE_READ(sc, NFE_PHY_DATA); 945159952Sobrien if (val != 0xffffffff && val != 0) 946159952Sobrien sc->mii_phyaddr = phy; 947159952Sobrien 948170589Syongari DPRINTFN(sc, 2, "mii read phy %d reg 0x%x ret 0x%x\n", phy, reg, val); 949159952Sobrien 950170589Syongari return (val); 951159952Sobrien} 952159952Sobrien 953163503Sobrien 954159967Sobrienstatic int 955159967Sobriennfe_miibus_writereg(device_t dev, int phy, int reg, int val) 956159952Sobrien{ 957159967Sobrien struct nfe_softc *sc = device_get_softc(dev); 958170589Syongari uint32_t ctl; 959163503Sobrien int ntries; 960159952Sobrien 961159952Sobrien NFE_WRITE(sc, NFE_PHY_STATUS, 0xf); 962159952Sobrien 963159952Sobrien if (NFE_READ(sc, NFE_PHY_CTL) & NFE_PHY_BUSY) { 964159952Sobrien NFE_WRITE(sc, NFE_PHY_CTL, NFE_PHY_BUSY); 965159952Sobrien DELAY(100); 966159952Sobrien } 967159952Sobrien 968159952Sobrien NFE_WRITE(sc, NFE_PHY_DATA, val); 969159952Sobrien ctl = NFE_PHY_WRITE | (phy << NFE_PHYADD_SHIFT) | reg; 970159952Sobrien NFE_WRITE(sc, NFE_PHY_CTL, ctl); 971159952Sobrien 972170589Syongari for (ntries = 0; ntries < NFE_TIMEOUT; ntries++) { 973159952Sobrien DELAY(100); 974159952Sobrien if (!(NFE_READ(sc, NFE_PHY_CTL) & NFE_PHY_BUSY)) 975159952Sobrien break; 976159952Sobrien } 977159952Sobrien#ifdef NFE_DEBUG 978170589Syongari if (nfedebug >= 2 && ntries == NFE_TIMEOUT) 979170589Syongari device_printf(sc->nfe_dev, "could not write to PHY\n"); 980159952Sobrien#endif 981170589Syongari return (0); 982159952Sobrien} 983159952Sobrien 984170589Syongari/* 985170589Syongari * Allocate a jumbo buffer. 986170589Syongari */ 987170589Syongaristatic void * 988170589Syongarinfe_jalloc(struct nfe_softc *sc) 989170589Syongari{ 990170589Syongari struct nfe_jpool_entry *entry; 991163503Sobrien 992170589Syongari NFE_JLIST_LOCK(sc); 993170589Syongari 994170589Syongari entry = SLIST_FIRST(&sc->nfe_jfree_listhead); 995170589Syongari 996170589Syongari if (entry == NULL) { 997170589Syongari NFE_JLIST_UNLOCK(sc); 998170589Syongari return (NULL); 999170589Syongari } 1000170589Syongari 1001170589Syongari SLIST_REMOVE_HEAD(&sc->nfe_jfree_listhead, jpool_entries); 1002170589Syongari SLIST_INSERT_HEAD(&sc->nfe_jinuse_listhead, entry, jpool_entries); 1003170589Syongari 1004170589Syongari NFE_JLIST_UNLOCK(sc); 1005170589Syongari 1006170589Syongari return (sc->jrxq.jslots[entry->slot]); 1007170589Syongari} 1008170589Syongari 1009170589Syongari/* 1010170589Syongari * Release a jumbo buffer. 1011170589Syongari */ 1012170589Syongaristatic void 1013170589Syongarinfe_jfree(void *buf, void *args) 1014170589Syongari{ 1015170589Syongari struct nfe_softc *sc; 1016170589Syongari struct nfe_jpool_entry *entry; 1017170589Syongari int i; 1018170589Syongari 1019170589Syongari /* Extract the softc struct pointer. */ 1020170589Syongari sc = (struct nfe_softc *)args; 1021170589Syongari KASSERT(sc != NULL, ("%s: can't find softc pointer!", __func__)); 1022170589Syongari 1023170589Syongari NFE_JLIST_LOCK(sc); 1024170589Syongari /* Calculate the slot this buffer belongs to. */ 1025170589Syongari i = ((vm_offset_t)buf 1026170589Syongari - (vm_offset_t)sc->jrxq.jpool) / NFE_JLEN; 1027170589Syongari KASSERT(i >= 0 && i < NFE_JSLOTS, 1028170589Syongari ("%s: asked to free buffer that we don't manage!", __func__)); 1029170589Syongari 1030170589Syongari entry = SLIST_FIRST(&sc->nfe_jinuse_listhead); 1031170589Syongari KASSERT(entry != NULL, ("%s: buffer not in use!", __func__)); 1032170589Syongari entry->slot = i; 1033170589Syongari SLIST_REMOVE_HEAD(&sc->nfe_jinuse_listhead, jpool_entries); 1034170589Syongari SLIST_INSERT_HEAD(&sc->nfe_jfree_listhead, entry, jpool_entries); 1035170589Syongari if (SLIST_EMPTY(&sc->nfe_jinuse_listhead)) 1036170589Syongari wakeup(sc); 1037170589Syongari 1038170589Syongari NFE_JLIST_UNLOCK(sc); 1039170589Syongari} 1040170589Syongari 1041170589Syongaristruct nfe_dmamap_arg { 1042170589Syongari bus_addr_t nfe_busaddr; 1043170589Syongari}; 1044170589Syongari 1045159967Sobrienstatic int 1046159967Sobriennfe_alloc_rx_ring(struct nfe_softc *sc, struct nfe_rx_ring *ring) 1047159952Sobrien{ 1048170589Syongari struct nfe_dmamap_arg ctx; 1049159967Sobrien struct nfe_rx_data *data; 1050170589Syongari void *desc; 1051159967Sobrien int i, error, descsize; 1052159967Sobrien 1053159967Sobrien if (sc->nfe_flags & NFE_40BIT_ADDR) { 1054170589Syongari desc = ring->desc64; 1055159967Sobrien descsize = sizeof (struct nfe_desc64); 1056159967Sobrien } else { 1057170589Syongari desc = ring->desc32; 1058159967Sobrien descsize = sizeof (struct nfe_desc32); 1059159967Sobrien } 1060159967Sobrien 1061159967Sobrien ring->cur = ring->next = 0; 1062159967Sobrien 1063163503Sobrien error = bus_dma_tag_create(sc->nfe_parent_tag, 1064170589Syongari NFE_RING_ALIGN, 0, /* alignment, boundary */ 1065170589Syongari BUS_SPACE_MAXADDR, /* lowaddr */ 1066170589Syongari BUS_SPACE_MAXADDR, /* highaddr */ 1067170589Syongari NULL, NULL, /* filter, filterarg */ 1068170589Syongari NFE_RX_RING_COUNT * descsize, 1, /* maxsize, nsegments */ 1069170589Syongari NFE_RX_RING_COUNT * descsize, /* maxsegsize */ 1070170589Syongari 0, /* flags */ 1071170589Syongari NULL, NULL, /* lockfunc, lockarg */ 1072170589Syongari &ring->rx_desc_tag); 1073159967Sobrien if (error != 0) { 1074170589Syongari device_printf(sc->nfe_dev, "could not create desc DMA tag\n"); 1075159967Sobrien goto fail; 1076159967Sobrien } 1077159967Sobrien 1078159967Sobrien /* allocate memory to desc */ 1079170589Syongari error = bus_dmamem_alloc(ring->rx_desc_tag, &desc, BUS_DMA_WAITOK | 1080170589Syongari BUS_DMA_COHERENT | BUS_DMA_ZERO, &ring->rx_desc_map); 1081159967Sobrien if (error != 0) { 1082170589Syongari device_printf(sc->nfe_dev, "could not create desc DMA map\n"); 1083159967Sobrien goto fail; 1084159967Sobrien } 1085170589Syongari if (sc->nfe_flags & NFE_40BIT_ADDR) 1086170589Syongari ring->desc64 = desc; 1087170589Syongari else 1088170589Syongari ring->desc32 = desc; 1089159967Sobrien 1090159967Sobrien /* map desc to device visible address space */ 1091170589Syongari ctx.nfe_busaddr = 0; 1092170589Syongari error = bus_dmamap_load(ring->rx_desc_tag, ring->rx_desc_map, desc, 1093170589Syongari NFE_RX_RING_COUNT * descsize, nfe_dma_map_segs, &ctx, 0); 1094159967Sobrien if (error != 0) { 1095170589Syongari device_printf(sc->nfe_dev, "could not load desc DMA map\n"); 1096159967Sobrien goto fail; 1097159967Sobrien } 1098170589Syongari ring->physaddr = ctx.nfe_busaddr; 1099159967Sobrien 1100170589Syongari error = bus_dma_tag_create(sc->nfe_parent_tag, 1101170589Syongari 1, 0, /* alignment, boundary */ 1102170589Syongari BUS_SPACE_MAXADDR, /* lowaddr */ 1103170589Syongari BUS_SPACE_MAXADDR, /* highaddr */ 1104170589Syongari NULL, NULL, /* filter, filterarg */ 1105170589Syongari MCLBYTES, 1, /* maxsize, nsegments */ 1106170589Syongari MCLBYTES, /* maxsegsize */ 1107170589Syongari 0, /* flags */ 1108170589Syongari NULL, NULL, /* lockfunc, lockarg */ 1109170589Syongari &ring->rx_data_tag); 1110170589Syongari if (error != 0) { 1111170589Syongari device_printf(sc->nfe_dev, "could not create Rx DMA tag\n"); 1112170589Syongari goto fail; 1113170589Syongari } 1114159967Sobrien 1115170589Syongari error = bus_dmamap_create(ring->rx_data_tag, 0, &ring->rx_spare_map); 1116170589Syongari if (error != 0) { 1117170589Syongari device_printf(sc->nfe_dev, 1118170589Syongari "could not create Rx DMA spare map\n"); 1119170589Syongari goto fail; 1120170589Syongari } 1121170589Syongari 1122159967Sobrien /* 1123159967Sobrien * Pre-allocate Rx buffers and populate Rx ring. 1124159967Sobrien */ 1125159967Sobrien for (i = 0; i < NFE_RX_RING_COUNT; i++) { 1126159967Sobrien data = &sc->rxq.data[i]; 1127170589Syongari data->rx_data_map = NULL; 1128170589Syongari data->m = NULL; 1129170589Syongari error = bus_dmamap_create(ring->rx_data_tag, 0, 1130170589Syongari &data->rx_data_map); 1131164651Sobrien if (error != 0) { 1132170589Syongari device_printf(sc->nfe_dev, 1133170589Syongari "could not create Rx DMA map\n"); 1134164651Sobrien goto fail; 1135164651Sobrien } 1136170589Syongari } 1137159967Sobrien 1138170589Syongarifail: 1139170589Syongari return (error); 1140170589Syongari} 1141170589Syongari 1142170589Syongari 1143171559Syongaristatic void 1144170589Syongarinfe_alloc_jrx_ring(struct nfe_softc *sc, struct nfe_jrx_ring *ring) 1145170589Syongari{ 1146170589Syongari struct nfe_dmamap_arg ctx; 1147170589Syongari struct nfe_rx_data *data; 1148170589Syongari void *desc; 1149170589Syongari struct nfe_jpool_entry *entry; 1150170589Syongari uint8_t *ptr; 1151170589Syongari int i, error, descsize; 1152170589Syongari 1153170589Syongari if ((sc->nfe_flags & NFE_JUMBO_SUP) == 0) 1154171559Syongari return; 1155171559Syongari if (jumbo_disable != 0) { 1156171559Syongari device_printf(sc->nfe_dev, "disabling jumbo frame support\n"); 1157171559Syongari sc->nfe_jumbo_disable = 1; 1158171559Syongari return; 1159171559Syongari } 1160170589Syongari 1161170589Syongari if (sc->nfe_flags & NFE_40BIT_ADDR) { 1162170589Syongari desc = ring->jdesc64; 1163170589Syongari descsize = sizeof (struct nfe_desc64); 1164170589Syongari } else { 1165170589Syongari desc = ring->jdesc32; 1166170589Syongari descsize = sizeof (struct nfe_desc32); 1167170589Syongari } 1168170589Syongari 1169170589Syongari ring->jcur = ring->jnext = 0; 1170170589Syongari 1171170589Syongari /* Create DMA tag for jumbo Rx ring. */ 1172170589Syongari error = bus_dma_tag_create(sc->nfe_parent_tag, 1173170589Syongari NFE_RING_ALIGN, 0, /* alignment, boundary */ 1174170589Syongari BUS_SPACE_MAXADDR, /* lowaddr */ 1175170589Syongari BUS_SPACE_MAXADDR, /* highaddr */ 1176170589Syongari NULL, NULL, /* filter, filterarg */ 1177170589Syongari NFE_JUMBO_RX_RING_COUNT * descsize, /* maxsize */ 1178170589Syongari 1, /* nsegments */ 1179170589Syongari NFE_JUMBO_RX_RING_COUNT * descsize, /* maxsegsize */ 1180170589Syongari 0, /* flags */ 1181170589Syongari NULL, NULL, /* lockfunc, lockarg */ 1182170589Syongari &ring->jrx_desc_tag); 1183170589Syongari if (error != 0) { 1184170589Syongari device_printf(sc->nfe_dev, 1185170589Syongari "could not create jumbo ring DMA tag\n"); 1186170589Syongari goto fail; 1187170589Syongari } 1188170589Syongari 1189170589Syongari /* Create DMA tag for jumbo buffer blocks. */ 1190170589Syongari error = bus_dma_tag_create(sc->nfe_parent_tag, 1191170589Syongari PAGE_SIZE, 0, /* alignment, boundary */ 1192170589Syongari BUS_SPACE_MAXADDR, /* lowaddr */ 1193170589Syongari BUS_SPACE_MAXADDR, /* highaddr */ 1194170589Syongari NULL, NULL, /* filter, filterarg */ 1195170589Syongari NFE_JMEM, /* maxsize */ 1196170589Syongari 1, /* nsegments */ 1197170589Syongari NFE_JMEM, /* maxsegsize */ 1198170589Syongari 0, /* flags */ 1199170589Syongari NULL, NULL, /* lockfunc, lockarg */ 1200170589Syongari &ring->jrx_jumbo_tag); 1201170589Syongari if (error != 0) { 1202170589Syongari device_printf(sc->nfe_dev, 1203170589Syongari "could not create jumbo Rx buffer block DMA tag\n"); 1204170589Syongari goto fail; 1205170589Syongari } 1206170589Syongari 1207170589Syongari /* Create DMA tag for jumbo Rx buffers. */ 1208170589Syongari error = bus_dma_tag_create(sc->nfe_parent_tag, 1209170589Syongari PAGE_SIZE, 0, /* alignment, boundary */ 1210170589Syongari BUS_SPACE_MAXADDR, /* lowaddr */ 1211170589Syongari BUS_SPACE_MAXADDR, /* highaddr */ 1212170589Syongari NULL, NULL, /* filter, filterarg */ 1213170589Syongari NFE_JLEN, /* maxsize */ 1214170589Syongari 1, /* nsegments */ 1215170589Syongari NFE_JLEN, /* maxsegsize */ 1216170589Syongari 0, /* flags */ 1217170589Syongari NULL, NULL, /* lockfunc, lockarg */ 1218170589Syongari &ring->jrx_data_tag); 1219170589Syongari if (error != 0) { 1220170589Syongari device_printf(sc->nfe_dev, 1221170589Syongari "could not create jumbo Rx buffer DMA tag\n"); 1222170589Syongari goto fail; 1223170589Syongari } 1224170589Syongari 1225170589Syongari /* Allocate DMA'able memory and load the DMA map for jumbo Rx ring. */ 1226170589Syongari error = bus_dmamem_alloc(ring->jrx_desc_tag, &desc, BUS_DMA_WAITOK | 1227170589Syongari BUS_DMA_COHERENT | BUS_DMA_ZERO, &ring->jrx_desc_map); 1228170589Syongari if (error != 0) { 1229170589Syongari device_printf(sc->nfe_dev, 1230170589Syongari "could not allocate DMA'able memory for jumbo Rx ring\n"); 1231170589Syongari goto fail; 1232170589Syongari } 1233170589Syongari if (sc->nfe_flags & NFE_40BIT_ADDR) 1234170589Syongari ring->jdesc64 = desc; 1235170589Syongari else 1236170589Syongari ring->jdesc32 = desc; 1237170589Syongari 1238170589Syongari ctx.nfe_busaddr = 0; 1239170589Syongari error = bus_dmamap_load(ring->jrx_desc_tag, ring->jrx_desc_map, desc, 1240170589Syongari NFE_JUMBO_RX_RING_COUNT * descsize, nfe_dma_map_segs, &ctx, 0); 1241170589Syongari if (error != 0) { 1242170589Syongari device_printf(sc->nfe_dev, 1243170589Syongari "could not load DMA'able memory for jumbo Rx ring\n"); 1244170589Syongari goto fail; 1245170589Syongari } 1246170589Syongari ring->jphysaddr = ctx.nfe_busaddr; 1247170589Syongari 1248170589Syongari /* Create DMA maps for jumbo Rx buffers. */ 1249170589Syongari error = bus_dmamap_create(ring->jrx_data_tag, 0, &ring->jrx_spare_map); 1250170589Syongari if (error != 0) { 1251170589Syongari device_printf(sc->nfe_dev, 1252170589Syongari "could not create jumbo Rx DMA spare map\n"); 1253170589Syongari goto fail; 1254170589Syongari } 1255170589Syongari 1256170589Syongari for (i = 0; i < NFE_JUMBO_RX_RING_COUNT; i++) { 1257170589Syongari data = &sc->jrxq.jdata[i]; 1258170589Syongari data->rx_data_map = NULL; 1259170589Syongari data->m = NULL; 1260170589Syongari error = bus_dmamap_create(ring->jrx_data_tag, 0, 1261164651Sobrien &data->rx_data_map); 1262164651Sobrien if (error != 0) { 1263170589Syongari device_printf(sc->nfe_dev, 1264170589Syongari "could not create jumbo Rx DMA map\n"); 1265164651Sobrien goto fail; 1266164651Sobrien } 1267170589Syongari } 1268159967Sobrien 1269170589Syongari /* Allocate DMA'able memory and load the DMA map for jumbo buf. */ 1270170589Syongari error = bus_dmamem_alloc(ring->jrx_jumbo_tag, (void **)&ring->jpool, 1271170589Syongari BUS_DMA_WAITOK | BUS_DMA_COHERENT | BUS_DMA_ZERO, 1272170589Syongari &ring->jrx_jumbo_map); 1273170589Syongari if (error != 0) { 1274170589Syongari device_printf(sc->nfe_dev, 1275170589Syongari "could not allocate DMA'able memory for jumbo pool\n"); 1276170589Syongari goto fail; 1277170589Syongari } 1278170589Syongari 1279170589Syongari ctx.nfe_busaddr = 0; 1280170589Syongari error = bus_dmamap_load(ring->jrx_jumbo_tag, ring->jrx_jumbo_map, 1281170589Syongari ring->jpool, NFE_JMEM, nfe_dma_map_segs, &ctx, 0); 1282170589Syongari if (error != 0) { 1283170589Syongari device_printf(sc->nfe_dev, 1284170589Syongari "could not load DMA'able memory for jumbo pool\n"); 1285170589Syongari goto fail; 1286170589Syongari } 1287170589Syongari 1288170589Syongari /* 1289170589Syongari * Now divide it up into 9K pieces and save the addresses 1290170589Syongari * in an array. 1291170589Syongari */ 1292170589Syongari ptr = ring->jpool; 1293170589Syongari for (i = 0; i < NFE_JSLOTS; i++) { 1294170589Syongari ring->jslots[i] = ptr; 1295170589Syongari ptr += NFE_JLEN; 1296170589Syongari entry = malloc(sizeof(struct nfe_jpool_entry), M_DEVBUF, 1297170589Syongari M_WAITOK); 1298170589Syongari if (entry == NULL) { 1299170589Syongari device_printf(sc->nfe_dev, 1300170589Syongari "no memory for jumbo buffers!\n"); 1301164651Sobrien error = ENOMEM; 1302164651Sobrien goto fail; 1303164651Sobrien } 1304170589Syongari entry->slot = i; 1305170589Syongari SLIST_INSERT_HEAD(&sc->nfe_jfree_listhead, entry, 1306170589Syongari jpool_entries); 1307170589Syongari } 1308159967Sobrien 1309171559Syongari return; 1310159967Sobrien 1311170589Syongarifail: 1312171559Syongari /* 1313171559Syongari * Running without jumbo frame support is ok for most cases 1314171559Syongari * so don't fail on creating dma tag/map for jumbo frame. 1315171559Syongari */ 1316170589Syongari nfe_free_jrx_ring(sc, ring); 1317171559Syongari device_printf(sc->nfe_dev, "disabling jumbo frame support due to " 1318171559Syongari "resource shortage\n"); 1319171559Syongari sc->nfe_jumbo_disable = 1; 1320170589Syongari} 1321159967Sobrien 1322159967Sobrien 1323170589Syongaristatic int 1324170589Syongarinfe_init_rx_ring(struct nfe_softc *sc, struct nfe_rx_ring *ring) 1325170589Syongari{ 1326170589Syongari void *desc; 1327170589Syongari size_t descsize; 1328170589Syongari int i; 1329159967Sobrien 1330170589Syongari ring->cur = ring->next = 0; 1331170589Syongari if (sc->nfe_flags & NFE_40BIT_ADDR) { 1332170589Syongari desc = ring->desc64; 1333170589Syongari descsize = sizeof (struct nfe_desc64); 1334170589Syongari } else { 1335170589Syongari desc = ring->desc32; 1336170589Syongari descsize = sizeof (struct nfe_desc32); 1337159967Sobrien } 1338170589Syongari bzero(desc, descsize * NFE_RX_RING_COUNT); 1339170589Syongari for (i = 0; i < NFE_RX_RING_COUNT; i++) { 1340170589Syongari if (nfe_newbuf(sc, i) != 0) 1341170589Syongari return (ENOBUFS); 1342170589Syongari } 1343159967Sobrien 1344163503Sobrien bus_dmamap_sync(ring->rx_desc_tag, ring->rx_desc_map, 1345170589Syongari BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 1346159967Sobrien 1347170589Syongari return (0); 1348159967Sobrien} 1349159967Sobrien 1350163503Sobrien 1351170589Syongaristatic int 1352170589Syongarinfe_init_jrx_ring(struct nfe_softc *sc, struct nfe_jrx_ring *ring) 1353159967Sobrien{ 1354170589Syongari void *desc; 1355170589Syongari size_t descsize; 1356159967Sobrien int i; 1357159967Sobrien 1358170589Syongari ring->jcur = ring->jnext = 0; 1359170589Syongari if (sc->nfe_flags & NFE_40BIT_ADDR) { 1360170589Syongari desc = ring->jdesc64; 1361170589Syongari descsize = sizeof (struct nfe_desc64); 1362170589Syongari } else { 1363170589Syongari desc = ring->jdesc32; 1364170589Syongari descsize = sizeof (struct nfe_desc32); 1365159952Sobrien } 1366170589Syongari bzero(desc, descsize * NFE_RX_RING_COUNT); 1367170589Syongari for (i = 0; i < NFE_JUMBO_RX_RING_COUNT; i++) { 1368170589Syongari if (nfe_jnewbuf(sc, i) != 0) 1369170589Syongari return (ENOBUFS); 1370170589Syongari } 1371159952Sobrien 1372170589Syongari bus_dmamap_sync(ring->jrx_desc_tag, ring->jrx_desc_map, 1373170589Syongari BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 1374159952Sobrien 1375170589Syongari return (0); 1376159967Sobrien} 1377159967Sobrien 1378159967Sobrien 1379159967Sobrienstatic void 1380159967Sobriennfe_free_rx_ring(struct nfe_softc *sc, struct nfe_rx_ring *ring) 1381159967Sobrien{ 1382159967Sobrien struct nfe_rx_data *data; 1383159967Sobrien void *desc; 1384159967Sobrien int i, descsize; 1385159967Sobrien 1386159967Sobrien if (sc->nfe_flags & NFE_40BIT_ADDR) { 1387159967Sobrien desc = ring->desc64; 1388159967Sobrien descsize = sizeof (struct nfe_desc64); 1389159967Sobrien } else { 1390159967Sobrien desc = ring->desc32; 1391159967Sobrien descsize = sizeof (struct nfe_desc32); 1392159952Sobrien } 1393159952Sobrien 1394170589Syongari for (i = 0; i < NFE_RX_RING_COUNT; i++) { 1395170589Syongari data = &ring->data[i]; 1396170589Syongari if (data->rx_data_map != NULL) { 1397170589Syongari bus_dmamap_destroy(ring->rx_data_tag, 1398170589Syongari data->rx_data_map); 1399170589Syongari data->rx_data_map = NULL; 1400170589Syongari } 1401170589Syongari if (data->m != NULL) { 1402170589Syongari m_freem(data->m); 1403170589Syongari data->m = NULL; 1404170589Syongari } 1405170589Syongari } 1406170589Syongari if (ring->rx_data_tag != NULL) { 1407170589Syongari if (ring->rx_spare_map != NULL) { 1408170589Syongari bus_dmamap_destroy(ring->rx_data_tag, 1409170589Syongari ring->rx_spare_map); 1410170589Syongari ring->rx_spare_map = NULL; 1411170589Syongari } 1412170589Syongari bus_dma_tag_destroy(ring->rx_data_tag); 1413170589Syongari ring->rx_data_tag = NULL; 1414170589Syongari } 1415170589Syongari 1416159967Sobrien if (desc != NULL) { 1417159967Sobrien bus_dmamap_unload(ring->rx_desc_tag, ring->rx_desc_map); 1418159967Sobrien bus_dmamem_free(ring->rx_desc_tag, desc, ring->rx_desc_map); 1419170589Syongari ring->desc64 = NULL; 1420170589Syongari ring->desc32 = NULL; 1421170589Syongari ring->rx_desc_map = NULL; 1422170589Syongari } 1423170589Syongari if (ring->rx_desc_tag != NULL) { 1424159967Sobrien bus_dma_tag_destroy(ring->rx_desc_tag); 1425170589Syongari ring->rx_desc_tag = NULL; 1426159967Sobrien } 1427170589Syongari} 1428159967Sobrien 1429164650Sobrien 1430170589Syongaristatic void 1431170589Syongarinfe_free_jrx_ring(struct nfe_softc *sc, struct nfe_jrx_ring *ring) 1432170589Syongari{ 1433170589Syongari struct nfe_jpool_entry *entry; 1434170589Syongari struct nfe_rx_data *data; 1435170589Syongari void *desc; 1436170589Syongari int i, descsize; 1437170589Syongari 1438170589Syongari if ((sc->nfe_flags & NFE_JUMBO_SUP) == 0) 1439170589Syongari return; 1440170589Syongari 1441170589Syongari NFE_JLIST_LOCK(sc); 1442170589Syongari while ((entry = SLIST_FIRST(&sc->nfe_jinuse_listhead))) { 1443170589Syongari device_printf(sc->nfe_dev, 1444170589Syongari "asked to free buffer that is in use!\n"); 1445170589Syongari SLIST_REMOVE_HEAD(&sc->nfe_jinuse_listhead, jpool_entries); 1446170589Syongari SLIST_INSERT_HEAD(&sc->nfe_jfree_listhead, entry, 1447170589Syongari jpool_entries); 1448170589Syongari } 1449170589Syongari 1450170589Syongari while (!SLIST_EMPTY(&sc->nfe_jfree_listhead)) { 1451170589Syongari entry = SLIST_FIRST(&sc->nfe_jfree_listhead); 1452170589Syongari SLIST_REMOVE_HEAD(&sc->nfe_jfree_listhead, jpool_entries); 1453170589Syongari free(entry, M_DEVBUF); 1454170589Syongari } 1455170589Syongari NFE_JLIST_UNLOCK(sc); 1456170589Syongari 1457170589Syongari if (sc->nfe_flags & NFE_40BIT_ADDR) { 1458170589Syongari desc = ring->jdesc64; 1459170589Syongari descsize = sizeof (struct nfe_desc64); 1460170589Syongari } else { 1461170589Syongari desc = ring->jdesc32; 1462170589Syongari descsize = sizeof (struct nfe_desc32); 1463170589Syongari } 1464170589Syongari 1465170589Syongari for (i = 0; i < NFE_JUMBO_RX_RING_COUNT; i++) { 1466170589Syongari data = &ring->jdata[i]; 1467164651Sobrien if (data->rx_data_map != NULL) { 1468170589Syongari bus_dmamap_destroy(ring->jrx_data_tag, 1469164651Sobrien data->rx_data_map); 1470170589Syongari data->rx_data_map = NULL; 1471164651Sobrien } 1472170589Syongari if (data->m != NULL) { 1473164651Sobrien m_freem(data->m); 1474170589Syongari data->m = NULL; 1475170589Syongari } 1476164651Sobrien } 1477170589Syongari if (ring->jrx_data_tag != NULL) { 1478170589Syongari if (ring->jrx_spare_map != NULL) { 1479170589Syongari bus_dmamap_destroy(ring->jrx_data_tag, 1480170589Syongari ring->jrx_spare_map); 1481170589Syongari ring->jrx_spare_map = NULL; 1482170589Syongari } 1483170589Syongari bus_dma_tag_destroy(ring->jrx_data_tag); 1484170589Syongari ring->jrx_data_tag = NULL; 1485170589Syongari } 1486170589Syongari 1487170589Syongari if (desc != NULL) { 1488170589Syongari bus_dmamap_unload(ring->jrx_desc_tag, ring->jrx_desc_map); 1489170589Syongari bus_dmamem_free(ring->jrx_desc_tag, desc, ring->jrx_desc_map); 1490170589Syongari ring->jdesc64 = NULL; 1491170589Syongari ring->jdesc32 = NULL; 1492170589Syongari ring->jrx_desc_map = NULL; 1493170589Syongari } 1494170589Syongari /* Destroy jumbo buffer block. */ 1495170589Syongari if (ring->jrx_jumbo_map != NULL) 1496170589Syongari bus_dmamap_unload(ring->jrx_jumbo_tag, ring->jrx_jumbo_map); 1497170589Syongari if (ring->jrx_jumbo_map != NULL) { 1498170589Syongari bus_dmamem_free(ring->jrx_jumbo_tag, ring->jpool, 1499170589Syongari ring->jrx_jumbo_map); 1500170589Syongari ring->jpool = NULL; 1501170589Syongari ring->jrx_jumbo_map = NULL; 1502170589Syongari } 1503170589Syongari if (ring->jrx_desc_tag != NULL) { 1504170589Syongari bus_dma_tag_destroy(ring->jrx_desc_tag); 1505170589Syongari ring->jrx_desc_tag = NULL; 1506170589Syongari } 1507159952Sobrien} 1508159952Sobrien 1509163503Sobrien 1510159967Sobrienstatic int 1511159967Sobriennfe_alloc_tx_ring(struct nfe_softc *sc, struct nfe_tx_ring *ring) 1512159952Sobrien{ 1513170589Syongari struct nfe_dmamap_arg ctx; 1514159967Sobrien int i, error; 1515170589Syongari void *desc; 1516159967Sobrien int descsize; 1517159952Sobrien 1518159967Sobrien if (sc->nfe_flags & NFE_40BIT_ADDR) { 1519170589Syongari desc = ring->desc64; 1520159967Sobrien descsize = sizeof (struct nfe_desc64); 1521159967Sobrien } else { 1522170589Syongari desc = ring->desc32; 1523159967Sobrien descsize = sizeof (struct nfe_desc32); 1524159967Sobrien } 1525159952Sobrien 1526159967Sobrien ring->queued = 0; 1527159967Sobrien ring->cur = ring->next = 0; 1528159967Sobrien 1529163503Sobrien error = bus_dma_tag_create(sc->nfe_parent_tag, 1530170589Syongari NFE_RING_ALIGN, 0, /* alignment, boundary */ 1531170589Syongari BUS_SPACE_MAXADDR, /* lowaddr */ 1532170589Syongari BUS_SPACE_MAXADDR, /* highaddr */ 1533170589Syongari NULL, NULL, /* filter, filterarg */ 1534170589Syongari NFE_TX_RING_COUNT * descsize, 1, /* maxsize, nsegments */ 1535170589Syongari NFE_TX_RING_COUNT * descsize, /* maxsegsize */ 1536170589Syongari 0, /* flags */ 1537170589Syongari NULL, NULL, /* lockfunc, lockarg */ 1538170589Syongari &ring->tx_desc_tag); 1539159967Sobrien if (error != 0) { 1540170589Syongari device_printf(sc->nfe_dev, "could not create desc DMA tag\n"); 1541159967Sobrien goto fail; 1542159952Sobrien } 1543159952Sobrien 1544170589Syongari error = bus_dmamem_alloc(ring->tx_desc_tag, &desc, BUS_DMA_WAITOK | 1545170589Syongari BUS_DMA_COHERENT | BUS_DMA_ZERO, &ring->tx_desc_map); 1546159967Sobrien if (error != 0) { 1547170589Syongari device_printf(sc->nfe_dev, "could not create desc DMA map\n"); 1548159967Sobrien goto fail; 1549159967Sobrien } 1550170589Syongari if (sc->nfe_flags & NFE_40BIT_ADDR) 1551170589Syongari ring->desc64 = desc; 1552170589Syongari else 1553170589Syongari ring->desc32 = desc; 1554159967Sobrien 1555170589Syongari ctx.nfe_busaddr = 0; 1556170589Syongari error = bus_dmamap_load(ring->tx_desc_tag, ring->tx_desc_map, desc, 1557170589Syongari NFE_TX_RING_COUNT * descsize, nfe_dma_map_segs, &ctx, 0); 1558159967Sobrien if (error != 0) { 1559170589Syongari device_printf(sc->nfe_dev, "could not load desc DMA map\n"); 1560159967Sobrien goto fail; 1561159967Sobrien } 1562170589Syongari ring->physaddr = ctx.nfe_busaddr; 1563159967Sobrien 1564163503Sobrien error = bus_dma_tag_create(sc->nfe_parent_tag, 1565170589Syongari 1, 0, 1566170589Syongari BUS_SPACE_MAXADDR, 1567170589Syongari BUS_SPACE_MAXADDR, 1568170589Syongari NULL, NULL, 1569170595Syongari NFE_TSO_MAXSIZE, 1570170589Syongari NFE_MAX_SCATTER, 1571170595Syongari NFE_TSO_MAXSGSIZE, 1572170589Syongari 0, 1573170589Syongari NULL, NULL, 1574170589Syongari &ring->tx_data_tag); 1575159967Sobrien if (error != 0) { 1576170589Syongari device_printf(sc->nfe_dev, "could not create Tx DMA tag\n"); 1577170589Syongari goto fail; 1578159967Sobrien } 1579159967Sobrien 1580159967Sobrien for (i = 0; i < NFE_TX_RING_COUNT; i++) { 1581163503Sobrien error = bus_dmamap_create(ring->tx_data_tag, 0, 1582163503Sobrien &ring->data[i].tx_data_map); 1583159967Sobrien if (error != 0) { 1584170589Syongari device_printf(sc->nfe_dev, 1585170589Syongari "could not create Tx DMA map\n"); 1586159967Sobrien goto fail; 1587159967Sobrien } 1588159967Sobrien } 1589159967Sobrien 1590170589Syongarifail: 1591170589Syongari return (error); 1592159967Sobrien} 1593159967Sobrien 1594159967Sobrien 1595159967Sobrienstatic void 1596170589Syongarinfe_init_tx_ring(struct nfe_softc *sc, struct nfe_tx_ring *ring) 1597159967Sobrien{ 1598170589Syongari void *desc; 1599170589Syongari size_t descsize; 1600159967Sobrien 1601170589Syongari sc->nfe_force_tx = 0; 1602170589Syongari ring->queued = 0; 1603170589Syongari ring->cur = ring->next = 0; 1604170589Syongari if (sc->nfe_flags & NFE_40BIT_ADDR) { 1605170589Syongari desc = ring->desc64; 1606170589Syongari descsize = sizeof (struct nfe_desc64); 1607170589Syongari } else { 1608170589Syongari desc = ring->desc32; 1609170589Syongari descsize = sizeof (struct nfe_desc32); 1610159967Sobrien } 1611170589Syongari bzero(desc, descsize * NFE_TX_RING_COUNT); 1612159967Sobrien 1613163503Sobrien bus_dmamap_sync(ring->tx_desc_tag, ring->tx_desc_map, 1614170589Syongari BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 1615159967Sobrien} 1616159967Sobrien 1617163503Sobrien 1618159967Sobrienstatic void 1619159967Sobriennfe_free_tx_ring(struct nfe_softc *sc, struct nfe_tx_ring *ring) 1620159967Sobrien{ 1621159967Sobrien struct nfe_tx_data *data; 1622159967Sobrien void *desc; 1623159967Sobrien int i, descsize; 1624159967Sobrien 1625159967Sobrien if (sc->nfe_flags & NFE_40BIT_ADDR) { 1626159967Sobrien desc = ring->desc64; 1627159967Sobrien descsize = sizeof (struct nfe_desc64); 1628159967Sobrien } else { 1629159967Sobrien desc = ring->desc32; 1630159967Sobrien descsize = sizeof (struct nfe_desc32); 1631159967Sobrien } 1632159967Sobrien 1633159967Sobrien for (i = 0; i < NFE_TX_RING_COUNT; i++) { 1634159967Sobrien data = &ring->data[i]; 1635159967Sobrien 1636159967Sobrien if (data->m != NULL) { 1637170589Syongari bus_dmamap_sync(ring->tx_data_tag, data->tx_data_map, 1638163503Sobrien BUS_DMASYNC_POSTWRITE); 1639170589Syongari bus_dmamap_unload(ring->tx_data_tag, data->tx_data_map); 1640159967Sobrien m_freem(data->m); 1641170589Syongari data->m = NULL; 1642159967Sobrien } 1643170589Syongari if (data->tx_data_map != NULL) { 1644170589Syongari bus_dmamap_destroy(ring->tx_data_tag, 1645170589Syongari data->tx_data_map); 1646170589Syongari data->tx_data_map = NULL; 1647170589Syongari } 1648159967Sobrien } 1649159967Sobrien 1650170589Syongari if (ring->tx_data_tag != NULL) { 1651170589Syongari bus_dma_tag_destroy(ring->tx_data_tag); 1652170589Syongari ring->tx_data_tag = NULL; 1653159967Sobrien } 1654159967Sobrien 1655170589Syongari if (desc != NULL) { 1656170589Syongari bus_dmamap_sync(ring->tx_desc_tag, ring->tx_desc_map, 1657170589Syongari BUS_DMASYNC_POSTWRITE); 1658170589Syongari bus_dmamap_unload(ring->tx_desc_tag, ring->tx_desc_map); 1659170589Syongari bus_dmamem_free(ring->tx_desc_tag, desc, ring->tx_desc_map); 1660170589Syongari ring->desc64 = NULL; 1661170589Syongari ring->desc32 = NULL; 1662170589Syongari ring->tx_desc_map = NULL; 1663170589Syongari bus_dma_tag_destroy(ring->tx_desc_tag); 1664170589Syongari ring->tx_desc_tag = NULL; 1665170589Syongari } 1666159967Sobrien} 1667159967Sobrien 1668159967Sobrien#ifdef DEVICE_POLLING 1669159967Sobrienstatic poll_handler_t nfe_poll; 1670159967Sobrien 1671163503Sobrien 1672159967Sobrienstatic void 1673159967Sobriennfe_poll(struct ifnet *ifp, enum poll_cmd cmd, int count) 1674159967Sobrien{ 1675164360Sobrien struct nfe_softc *sc = ifp->if_softc; 1676170589Syongari uint32_t r; 1677159967Sobrien 1678159967Sobrien NFE_LOCK(sc); 1679159967Sobrien 1680159967Sobrien if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) { 1681170589Syongari NFE_UNLOCK(sc); 1682159967Sobrien return; 1683159967Sobrien } 1684159967Sobrien 1685171559Syongari if (sc->nfe_framesize > MCLBYTES - ETHER_HDR_LEN) 1686171559Syongari nfe_jrxeof(sc, count); 1687171559Syongari else 1688171559Syongari nfe_rxeof(sc, count); 1689159967Sobrien nfe_txeof(sc); 1690159967Sobrien if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) 1691173674Ssam taskqueue_enqueue_fast(sc->nfe_tq, &sc->nfe_tx_task); 1692159967Sobrien 1693159967Sobrien if (cmd == POLL_AND_CHECK_STATUS) { 1694170589Syongari if ((r = NFE_READ(sc, sc->nfe_irq_status)) == 0) { 1695170589Syongari NFE_UNLOCK(sc); 1696163503Sobrien return; 1697163503Sobrien } 1698170589Syongari NFE_WRITE(sc, sc->nfe_irq_status, r); 1699159967Sobrien 1700163503Sobrien if (r & NFE_IRQ_LINK) { 1701163503Sobrien NFE_READ(sc, NFE_PHY_STATUS); 1702163503Sobrien NFE_WRITE(sc, NFE_PHY_STATUS, 0xf); 1703170589Syongari DPRINTF(sc, "link state changed\n"); 1704163503Sobrien } 1705159967Sobrien } 1706170589Syongari NFE_UNLOCK(sc); 1707159967Sobrien} 1708159967Sobrien#endif /* DEVICE_POLLING */ 1709159967Sobrien 1710170589Syongaristatic void 1711170589Syongarinfe_set_intr(struct nfe_softc *sc) 1712170589Syongari{ 1713159967Sobrien 1714170589Syongari if (sc->nfe_msi != 0) 1715170589Syongari NFE_WRITE(sc, NFE_IRQ_MASK, NFE_IRQ_WANTED); 1716170589Syongari} 1717170589Syongari 1718170589Syongari 1719170589Syongari/* In MSIX, a write to mask reegisters behaves as XOR. */ 1720170589Syongaristatic __inline void 1721170589Syongarinfe_enable_intr(struct nfe_softc *sc) 1722170589Syongari{ 1723170589Syongari 1724170589Syongari if (sc->nfe_msix != 0) { 1725170589Syongari /* XXX Should have a better way to enable interrupts! */ 1726170589Syongari if (NFE_READ(sc, sc->nfe_irq_mask) == 0) 1727170589Syongari NFE_WRITE(sc, sc->nfe_irq_mask, sc->nfe_intrs); 1728170589Syongari } else 1729170589Syongari NFE_WRITE(sc, sc->nfe_irq_mask, sc->nfe_intrs); 1730170589Syongari} 1731170589Syongari 1732170589Syongari 1733170589Syongaristatic __inline void 1734170589Syongarinfe_disable_intr(struct nfe_softc *sc) 1735170589Syongari{ 1736170589Syongari 1737170589Syongari if (sc->nfe_msix != 0) { 1738170589Syongari /* XXX Should have a better way to disable interrupts! */ 1739170589Syongari if (NFE_READ(sc, sc->nfe_irq_mask) != 0) 1740170589Syongari NFE_WRITE(sc, sc->nfe_irq_mask, sc->nfe_nointrs); 1741170589Syongari } else 1742170589Syongari NFE_WRITE(sc, sc->nfe_irq_mask, sc->nfe_nointrs); 1743170589Syongari} 1744170589Syongari 1745170589Syongari 1746159967Sobrienstatic int 1747159967Sobriennfe_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 1748159967Sobrien{ 1749170589Syongari struct nfe_softc *sc; 1750170589Syongari struct ifreq *ifr; 1751163503Sobrien struct mii_data *mii; 1752170589Syongari int error, init, mask; 1753159967Sobrien 1754170589Syongari sc = ifp->if_softc; 1755170589Syongari ifr = (struct ifreq *) data; 1756170589Syongari error = 0; 1757170589Syongari init = 0; 1758159952Sobrien switch (cmd) { 1759159952Sobrien case SIOCSIFMTU: 1760170589Syongari if (ifr->ifr_mtu < ETHERMIN || ifr->ifr_mtu > NFE_JUMBO_MTU) 1761159952Sobrien error = EINVAL; 1762170589Syongari else if (ifp->if_mtu != ifr->ifr_mtu) { 1763171559Syongari if ((((sc->nfe_flags & NFE_JUMBO_SUP) == 0) || 1764171559Syongari (sc->nfe_jumbo_disable != 0)) && 1765170589Syongari ifr->ifr_mtu > ETHERMTU) 1766170589Syongari error = EINVAL; 1767170589Syongari else { 1768170589Syongari NFE_LOCK(sc); 1769170589Syongari ifp->if_mtu = ifr->ifr_mtu; 1770170589Syongari if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) 1771170589Syongari nfe_init_locked(sc); 1772170589Syongari NFE_UNLOCK(sc); 1773164650Sobrien } 1774164650Sobrien } 1775159952Sobrien break; 1776159952Sobrien case SIOCSIFFLAGS: 1777159967Sobrien NFE_LOCK(sc); 1778159952Sobrien if (ifp->if_flags & IFF_UP) { 1779159952Sobrien /* 1780159952Sobrien * If only the PROMISC or ALLMULTI flag changes, then 1781159952Sobrien * don't do a full re-init of the chip, just update 1782159952Sobrien * the Rx filter. 1783159952Sobrien */ 1784159967Sobrien if ((ifp->if_drv_flags & IFF_DRV_RUNNING) && 1785159967Sobrien ((ifp->if_flags ^ sc->nfe_if_flags) & 1786159967Sobrien (IFF_ALLMULTI | IFF_PROMISC)) != 0) 1787159952Sobrien nfe_setmulti(sc); 1788159967Sobrien else 1789159967Sobrien nfe_init_locked(sc); 1790159952Sobrien } else { 1791159967Sobrien if (ifp->if_drv_flags & IFF_DRV_RUNNING) 1792170589Syongari nfe_stop(ifp); 1793159952Sobrien } 1794159967Sobrien sc->nfe_if_flags = ifp->if_flags; 1795159967Sobrien NFE_UNLOCK(sc); 1796159967Sobrien error = 0; 1797159952Sobrien break; 1798159952Sobrien case SIOCADDMULTI: 1799159952Sobrien case SIOCDELMULTI: 1800170589Syongari if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) { 1801159967Sobrien NFE_LOCK(sc); 1802159967Sobrien nfe_setmulti(sc); 1803159967Sobrien NFE_UNLOCK(sc); 1804159952Sobrien error = 0; 1805159952Sobrien } 1806159952Sobrien break; 1807159952Sobrien case SIOCSIFMEDIA: 1808159952Sobrien case SIOCGIFMEDIA: 1809159967Sobrien mii = device_get_softc(sc->nfe_miibus); 1810159967Sobrien error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, cmd); 1811159952Sobrien break; 1812159967Sobrien case SIOCSIFCAP: 1813170589Syongari mask = ifr->ifr_reqcap ^ ifp->if_capenable; 1814159967Sobrien#ifdef DEVICE_POLLING 1815170589Syongari if ((mask & IFCAP_POLLING) != 0) { 1816170589Syongari if ((ifr->ifr_reqcap & IFCAP_POLLING) != 0) { 1817159967Sobrien error = ether_poll_register(nfe_poll, ifp); 1818159967Sobrien if (error) 1819170589Syongari break; 1820159967Sobrien NFE_LOCK(sc); 1821170589Syongari nfe_disable_intr(sc); 1822163503Sobrien ifp->if_capenable |= IFCAP_POLLING; 1823159967Sobrien NFE_UNLOCK(sc); 1824159967Sobrien } else { 1825159967Sobrien error = ether_poll_deregister(ifp); 1826159967Sobrien /* Enable interrupt even in error case */ 1827159967Sobrien NFE_LOCK(sc); 1828170589Syongari nfe_enable_intr(sc); 1829159967Sobrien ifp->if_capenable &= ~IFCAP_POLLING; 1830159967Sobrien NFE_UNLOCK(sc); 1831159967Sobrien } 1832159967Sobrien } 1833163503Sobrien#endif /* DEVICE_POLLING */ 1834170589Syongari if ((sc->nfe_flags & NFE_HW_CSUM) != 0 && 1835170589Syongari (mask & IFCAP_HWCSUM) != 0) { 1836159967Sobrien ifp->if_capenable ^= IFCAP_HWCSUM; 1837170589Syongari if ((IFCAP_TXCSUM & ifp->if_capenable) != 0 && 1838170589Syongari (IFCAP_TXCSUM & ifp->if_capabilities) != 0) 1839170589Syongari ifp->if_hwassist |= NFE_CSUM_FEATURES; 1840159967Sobrien else 1841170589Syongari ifp->if_hwassist &= ~NFE_CSUM_FEATURES; 1842170589Syongari init++; 1843159967Sobrien } 1844170589Syongari if ((sc->nfe_flags & NFE_HW_VLAN) != 0 && 1845170589Syongari (mask & IFCAP_VLAN_HWTAGGING) != 0) { 1846170589Syongari ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING; 1847170589Syongari init++; 1848170589Syongari } 1849170589Syongari /* 1850170589Syongari * XXX 1851170589Syongari * It seems that VLAN stripping requires Rx checksum offload. 1852170589Syongari * Unfortunately FreeBSD has no way to disable only Rx side 1853170589Syongari * VLAN stripping. So when we know Rx checksum offload is 1854170589Syongari * disabled turn entire hardware VLAN assist off. 1855170589Syongari */ 1856170589Syongari if ((sc->nfe_flags & (NFE_HW_CSUM | NFE_HW_VLAN)) == 1857170589Syongari (NFE_HW_CSUM | NFE_HW_VLAN)) { 1858170589Syongari if ((ifp->if_capenable & IFCAP_RXCSUM) == 0) 1859170589Syongari ifp->if_capenable &= ~IFCAP_VLAN_HWTAGGING; 1860170589Syongari } 1861170589Syongari 1862170589Syongari if ((sc->nfe_flags & NFE_HW_CSUM) != 0 && 1863170589Syongari (mask & IFCAP_TSO4) != 0) { 1864170589Syongari ifp->if_capenable ^= IFCAP_TSO4; 1865170589Syongari if ((IFCAP_TSO4 & ifp->if_capenable) != 0 && 1866170589Syongari (IFCAP_TSO4 & ifp->if_capabilities) != 0) 1867170589Syongari ifp->if_hwassist |= CSUM_TSO; 1868170589Syongari else 1869170589Syongari ifp->if_hwassist &= ~CSUM_TSO; 1870170589Syongari } 1871170589Syongari 1872170589Syongari if (init > 0 && (ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) { 1873170589Syongari ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 1874164656Sobrien nfe_init(sc); 1875170589Syongari } 1876170589Syongari if ((sc->nfe_flags & NFE_HW_VLAN) != 0) 1877170589Syongari VLAN_CAPABILITIES(ifp); 1878159967Sobrien break; 1879159952Sobrien default: 1880159967Sobrien error = ether_ioctl(ifp, cmd, data); 1881159967Sobrien break; 1882159952Sobrien } 1883159952Sobrien 1884170589Syongari return (error); 1885159952Sobrien} 1886159952Sobrien 1887159967Sobrien 1888170589Syongaristatic int 1889163503Sobriennfe_intr(void *arg) 1890159967Sobrien{ 1891170589Syongari struct nfe_softc *sc; 1892170589Syongari uint32_t status; 1893170589Syongari 1894170589Syongari sc = (struct nfe_softc *)arg; 1895170589Syongari 1896170589Syongari status = NFE_READ(sc, sc->nfe_irq_status); 1897170589Syongari if (status == 0 || status == 0xffffffff) 1898170589Syongari return (FILTER_STRAY); 1899170589Syongari nfe_disable_intr(sc); 1900173674Ssam taskqueue_enqueue_fast(sc->nfe_tq, &sc->nfe_int_task); 1901170589Syongari 1902170589Syongari return (FILTER_HANDLED); 1903170589Syongari} 1904170589Syongari 1905170589Syongari 1906170589Syongaristatic void 1907170589Syongarinfe_int_task(void *arg, int pending) 1908170589Syongari{ 1909159967Sobrien struct nfe_softc *sc = arg; 1910159967Sobrien struct ifnet *ifp = sc->nfe_ifp; 1911170589Syongari uint32_t r; 1912170589Syongari int domore; 1913159967Sobrien 1914163503Sobrien NFE_LOCK(sc); 1915159967Sobrien 1916170589Syongari if ((r = NFE_READ(sc, sc->nfe_irq_status)) == 0) { 1917170589Syongari nfe_enable_intr(sc); 1918170589Syongari NFE_UNLOCK(sc); 1919170589Syongari return; /* not for us */ 1920170589Syongari } 1921170589Syongari NFE_WRITE(sc, sc->nfe_irq_status, r); 1922170589Syongari 1923170589Syongari DPRINTFN(sc, 5, "nfe_intr: interrupt register %x\n", r); 1924170589Syongari 1925159967Sobrien#ifdef DEVICE_POLLING 1926159967Sobrien if (ifp->if_capenable & IFCAP_POLLING) { 1927159967Sobrien NFE_UNLOCK(sc); 1928159967Sobrien return; 1929159967Sobrien } 1930159967Sobrien#endif 1931159967Sobrien 1932172169Syongari if (r & NFE_IRQ_LINK) { 1933172169Syongari NFE_READ(sc, NFE_PHY_STATUS); 1934172169Syongari NFE_WRITE(sc, NFE_PHY_STATUS, 0xf); 1935172169Syongari DPRINTF(sc, "link state changed\n"); 1936172169Syongari } 1937172169Syongari 1938170589Syongari if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) { 1939163503Sobrien NFE_UNLOCK(sc); 1940170589Syongari nfe_enable_intr(sc); 1941170589Syongari return; 1942159967Sobrien } 1943159967Sobrien 1944170589Syongari domore = 0; 1945170589Syongari /* check Rx ring */ 1946170589Syongari if (sc->nfe_framesize > MCLBYTES - ETHER_HDR_LEN) 1947170589Syongari domore = nfe_jrxeof(sc, sc->nfe_process_limit); 1948170589Syongari else 1949170589Syongari domore = nfe_rxeof(sc, sc->nfe_process_limit); 1950170589Syongari /* check Tx ring */ 1951170589Syongari nfe_txeof(sc); 1952159967Sobrien 1953170589Syongari if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) 1954173674Ssam taskqueue_enqueue_fast(sc->nfe_tq, &sc->nfe_tx_task); 1955159967Sobrien 1956159967Sobrien NFE_UNLOCK(sc); 1957159967Sobrien 1958170589Syongari if (domore || (NFE_READ(sc, sc->nfe_irq_status) != 0)) { 1959173674Ssam taskqueue_enqueue_fast(sc->nfe_tq, &sc->nfe_int_task); 1960170589Syongari return; 1961170589Syongari } 1962170589Syongari 1963170589Syongari /* Reenable interrupts. */ 1964170589Syongari nfe_enable_intr(sc); 1965159967Sobrien} 1966159967Sobrien 1967163503Sobrien 1968170589Syongaristatic __inline void 1969170589Syongarinfe_discard_rxbuf(struct nfe_softc *sc, int idx) 1970159952Sobrien{ 1971170589Syongari struct nfe_desc32 *desc32; 1972170589Syongari struct nfe_desc64 *desc64; 1973170589Syongari struct nfe_rx_data *data; 1974170589Syongari struct mbuf *m; 1975163503Sobrien 1976170589Syongari data = &sc->rxq.data[idx]; 1977170589Syongari m = data->m; 1978170589Syongari 1979170589Syongari if (sc->nfe_flags & NFE_40BIT_ADDR) { 1980170589Syongari desc64 = &sc->rxq.desc64[idx]; 1981170589Syongari /* VLAN packet may have overwritten it. */ 1982170589Syongari desc64->physaddr[0] = htole32(NFE_ADDR_HI(data->paddr)); 1983170589Syongari desc64->physaddr[1] = htole32(NFE_ADDR_LO(data->paddr)); 1984170589Syongari desc64->length = htole16(m->m_len); 1985170589Syongari desc64->flags = htole16(NFE_RX_READY); 1986170589Syongari } else { 1987170589Syongari desc32 = &sc->rxq.desc32[idx]; 1988170589Syongari desc32->length = htole16(m->m_len); 1989170589Syongari desc32->flags = htole16(NFE_RX_READY); 1990170589Syongari } 1991159952Sobrien} 1992159952Sobrien 1993163503Sobrien 1994170589Syongaristatic __inline void 1995170589Syongarinfe_discard_jrxbuf(struct nfe_softc *sc, int idx) 1996159952Sobrien{ 1997170589Syongari struct nfe_desc32 *desc32; 1998170589Syongari struct nfe_desc64 *desc64; 1999170589Syongari struct nfe_rx_data *data; 2000170589Syongari struct mbuf *m; 2001163503Sobrien 2002170589Syongari data = &sc->jrxq.jdata[idx]; 2003170589Syongari m = data->m; 2004170589Syongari 2005170589Syongari if (sc->nfe_flags & NFE_40BIT_ADDR) { 2006170589Syongari desc64 = &sc->jrxq.jdesc64[idx]; 2007170589Syongari /* VLAN packet may have overwritten it. */ 2008170589Syongari desc64->physaddr[0] = htole32(NFE_ADDR_HI(data->paddr)); 2009170589Syongari desc64->physaddr[1] = htole32(NFE_ADDR_LO(data->paddr)); 2010170589Syongari desc64->length = htole16(m->m_len); 2011170589Syongari desc64->flags = htole16(NFE_RX_READY); 2012170589Syongari } else { 2013170589Syongari desc32 = &sc->jrxq.jdesc32[idx]; 2014170589Syongari desc32->length = htole16(m->m_len); 2015170589Syongari desc32->flags = htole16(NFE_RX_READY); 2016170589Syongari } 2017159952Sobrien} 2018159952Sobrien 2019163503Sobrien 2020170589Syongaristatic int 2021170589Syongarinfe_newbuf(struct nfe_softc *sc, int idx) 2022159952Sobrien{ 2023170589Syongari struct nfe_rx_data *data; 2024170589Syongari struct nfe_desc32 *desc32; 2025170589Syongari struct nfe_desc64 *desc64; 2026170589Syongari struct mbuf *m; 2027170589Syongari bus_dma_segment_t segs[1]; 2028170589Syongari bus_dmamap_t map; 2029170589Syongari int nsegs; 2030163503Sobrien 2031170589Syongari m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); 2032170589Syongari if (m == NULL) 2033170589Syongari return (ENOBUFS); 2034159952Sobrien 2035170589Syongari m->m_len = m->m_pkthdr.len = MCLBYTES; 2036170589Syongari m_adj(m, ETHER_ALIGN); 2037163503Sobrien 2038170589Syongari if (bus_dmamap_load_mbuf_sg(sc->rxq.rx_data_tag, sc->rxq.rx_spare_map, 2039170589Syongari m, segs, &nsegs, BUS_DMA_NOWAIT) != 0) { 2040170589Syongari m_freem(m); 2041170589Syongari return (ENOBUFS); 2042170589Syongari } 2043170589Syongari KASSERT(nsegs == 1, ("%s: %d segments returned!", __func__, nsegs)); 2044163503Sobrien 2045170589Syongari data = &sc->rxq.data[idx]; 2046170589Syongari if (data->m != NULL) { 2047170589Syongari bus_dmamap_sync(sc->rxq.rx_data_tag, data->rx_data_map, 2048170589Syongari BUS_DMASYNC_POSTREAD); 2049170589Syongari bus_dmamap_unload(sc->rxq.rx_data_tag, data->rx_data_map); 2050170589Syongari } 2051170589Syongari map = data->rx_data_map; 2052170589Syongari data->rx_data_map = sc->rxq.rx_spare_map; 2053170589Syongari sc->rxq.rx_spare_map = map; 2054170589Syongari bus_dmamap_sync(sc->rxq.rx_data_tag, data->rx_data_map, 2055170589Syongari BUS_DMASYNC_PREREAD); 2056170589Syongari data->paddr = segs[0].ds_addr; 2057170589Syongari data->m = m; 2058170589Syongari /* update mapping address in h/w descriptor */ 2059170589Syongari if (sc->nfe_flags & NFE_40BIT_ADDR) { 2060170589Syongari desc64 = &sc->rxq.desc64[idx]; 2061170589Syongari desc64->physaddr[0] = htole32(NFE_ADDR_HI(segs[0].ds_addr)); 2062170589Syongari desc64->physaddr[1] = htole32(NFE_ADDR_LO(segs[0].ds_addr)); 2063170589Syongari desc64->length = htole16(segs[0].ds_len); 2064170589Syongari desc64->flags = htole16(NFE_RX_READY); 2065170589Syongari } else { 2066170589Syongari desc32 = &sc->rxq.desc32[idx]; 2067170589Syongari desc32->physaddr = htole32(NFE_ADDR_LO(segs[0].ds_addr)); 2068170589Syongari desc32->length = htole16(segs[0].ds_len); 2069170589Syongari desc32->flags = htole16(NFE_RX_READY); 2070170589Syongari } 2071170589Syongari 2072170589Syongari return (0); 2073159952Sobrien} 2074159952Sobrien 2075163503Sobrien 2076170589Syongaristatic int 2077170589Syongarinfe_jnewbuf(struct nfe_softc *sc, int idx) 2078159952Sobrien{ 2079170589Syongari struct nfe_rx_data *data; 2080170589Syongari struct nfe_desc32 *desc32; 2081170589Syongari struct nfe_desc64 *desc64; 2082170589Syongari struct mbuf *m; 2083170589Syongari bus_dma_segment_t segs[1]; 2084170589Syongari bus_dmamap_t map; 2085170589Syongari int nsegs; 2086170589Syongari void *buf; 2087163503Sobrien 2088170589Syongari MGETHDR(m, M_DONTWAIT, MT_DATA); 2089170589Syongari if (m == NULL) 2090170589Syongari return (ENOBUFS); 2091170589Syongari buf = nfe_jalloc(sc); 2092170589Syongari if (buf == NULL) { 2093170589Syongari m_freem(m); 2094170589Syongari return (ENOBUFS); 2095170589Syongari } 2096170589Syongari /* Attach the buffer to the mbuf. */ 2097170589Syongari MEXTADD(m, buf, NFE_JLEN, nfe_jfree, (struct nfe_softc *)sc, 0, 2098170589Syongari EXT_NET_DRV); 2099170589Syongari if ((m->m_flags & M_EXT) == 0) { 2100170589Syongari m_freem(m); 2101170589Syongari return (ENOBUFS); 2102170589Syongari } 2103170589Syongari m->m_pkthdr.len = m->m_len = NFE_JLEN; 2104170589Syongari m_adj(m, ETHER_ALIGN); 2105159952Sobrien 2106170589Syongari if (bus_dmamap_load_mbuf_sg(sc->jrxq.jrx_data_tag, 2107170589Syongari sc->jrxq.jrx_spare_map, m, segs, &nsegs, BUS_DMA_NOWAIT) != 0) { 2108170589Syongari m_freem(m); 2109170589Syongari return (ENOBUFS); 2110170589Syongari } 2111170589Syongari KASSERT(nsegs == 1, ("%s: %d segments returned!", __func__, nsegs)); 2112163503Sobrien 2113170589Syongari data = &sc->jrxq.jdata[idx]; 2114170589Syongari if (data->m != NULL) { 2115170589Syongari bus_dmamap_sync(sc->jrxq.jrx_data_tag, data->rx_data_map, 2116170589Syongari BUS_DMASYNC_POSTREAD); 2117170589Syongari bus_dmamap_unload(sc->jrxq.jrx_data_tag, data->rx_data_map); 2118170589Syongari } 2119170589Syongari map = data->rx_data_map; 2120170589Syongari data->rx_data_map = sc->jrxq.jrx_spare_map; 2121170589Syongari sc->jrxq.jrx_spare_map = map; 2122170589Syongari bus_dmamap_sync(sc->jrxq.jrx_data_tag, data->rx_data_map, 2123170589Syongari BUS_DMASYNC_PREREAD); 2124170589Syongari data->paddr = segs[0].ds_addr; 2125170589Syongari data->m = m; 2126170589Syongari /* update mapping address in h/w descriptor */ 2127170589Syongari if (sc->nfe_flags & NFE_40BIT_ADDR) { 2128170589Syongari desc64 = &sc->jrxq.jdesc64[idx]; 2129170589Syongari desc64->physaddr[0] = htole32(NFE_ADDR_HI(segs[0].ds_addr)); 2130170589Syongari desc64->physaddr[1] = htole32(NFE_ADDR_LO(segs[0].ds_addr)); 2131170589Syongari desc64->length = htole16(segs[0].ds_len); 2132170589Syongari desc64->flags = htole16(NFE_RX_READY); 2133170589Syongari } else { 2134170589Syongari desc32 = &sc->jrxq.jdesc32[idx]; 2135170589Syongari desc32->physaddr = htole32(NFE_ADDR_LO(segs[0].ds_addr)); 2136170589Syongari desc32->length = htole16(segs[0].ds_len); 2137170589Syongari desc32->flags = htole16(NFE_RX_READY); 2138170589Syongari } 2139159967Sobrien 2140170589Syongari return (0); 2141159952Sobrien} 2142159952Sobrien 2143163503Sobrien 2144170589Syongaristatic int 2145170589Syongarinfe_rxeof(struct nfe_softc *sc, int count) 2146159952Sobrien{ 2147159967Sobrien struct ifnet *ifp = sc->nfe_ifp; 2148170589Syongari struct nfe_desc32 *desc32; 2149170589Syongari struct nfe_desc64 *desc64; 2150159952Sobrien struct nfe_rx_data *data; 2151170589Syongari struct mbuf *m; 2152170589Syongari uint16_t flags; 2153170589Syongari int len, prog; 2154170589Syongari uint32_t vtag = 0; 2155159952Sobrien 2156159967Sobrien NFE_LOCK_ASSERT(sc); 2157159967Sobrien 2158170589Syongari bus_dmamap_sync(sc->rxq.rx_desc_tag, sc->rxq.rx_desc_map, 2159170589Syongari BUS_DMASYNC_POSTREAD); 2160159967Sobrien 2161170589Syongari for (prog = 0;;NFE_INC(sc->rxq.cur, NFE_RX_RING_COUNT), vtag = 0) { 2162170589Syongari if (count <= 0) 2163170589Syongari break; 2164170589Syongari count--; 2165159967Sobrien 2166159952Sobrien data = &sc->rxq.data[sc->rxq.cur]; 2167159952Sobrien 2168159967Sobrien if (sc->nfe_flags & NFE_40BIT_ADDR) { 2169159952Sobrien desc64 = &sc->rxq.desc64[sc->rxq.cur]; 2170170589Syongari vtag = le32toh(desc64->physaddr[1]); 2171170589Syongari flags = le16toh(desc64->flags); 2172170589Syongari len = le16toh(desc64->length) & NFE_RX_LEN_MASK; 2173159952Sobrien } else { 2174159952Sobrien desc32 = &sc->rxq.desc32[sc->rxq.cur]; 2175170589Syongari flags = le16toh(desc32->flags); 2176170589Syongari len = le16toh(desc32->length) & NFE_RX_LEN_MASK; 2177159952Sobrien } 2178159952Sobrien 2179159952Sobrien if (flags & NFE_RX_READY) 2180159952Sobrien break; 2181170589Syongari prog++; 2182159967Sobrien if ((sc->nfe_flags & (NFE_JUMBO_SUP | NFE_40BIT_ADDR)) == 0) { 2183170589Syongari if (!(flags & NFE_RX_VALID_V1)) { 2184170589Syongari ifp->if_ierrors++; 2185170589Syongari nfe_discard_rxbuf(sc, sc->rxq.cur); 2186170589Syongari continue; 2187170589Syongari } 2188159952Sobrien if ((flags & NFE_RX_FIXME_V1) == NFE_RX_FIXME_V1) { 2189159952Sobrien flags &= ~NFE_RX_ERROR; 2190159952Sobrien len--; /* fix buffer length */ 2191159952Sobrien } 2192159952Sobrien } else { 2193170589Syongari if (!(flags & NFE_RX_VALID_V2)) { 2194170589Syongari ifp->if_ierrors++; 2195170589Syongari nfe_discard_rxbuf(sc, sc->rxq.cur); 2196170589Syongari continue; 2197170589Syongari } 2198159952Sobrien 2199159952Sobrien if ((flags & NFE_RX_FIXME_V2) == NFE_RX_FIXME_V2) { 2200159952Sobrien flags &= ~NFE_RX_ERROR; 2201159952Sobrien len--; /* fix buffer length */ 2202159952Sobrien } 2203159952Sobrien } 2204159952Sobrien 2205159952Sobrien if (flags & NFE_RX_ERROR) { 2206159952Sobrien ifp->if_ierrors++; 2207170589Syongari nfe_discard_rxbuf(sc, sc->rxq.cur); 2208170589Syongari continue; 2209159952Sobrien } 2210159952Sobrien 2211170589Syongari m = data->m; 2212170589Syongari if (nfe_newbuf(sc, sc->rxq.cur) != 0) { 2213170589Syongari ifp->if_iqdrops++; 2214170589Syongari nfe_discard_rxbuf(sc, sc->rxq.cur); 2215170589Syongari continue; 2216159952Sobrien } 2217159952Sobrien 2218170589Syongari if ((vtag & NFE_RX_VTAG) != 0 && 2219170589Syongari (ifp->if_capenable & IFCAP_VLAN_HWTAGGING) != 0) { 2220170589Syongari m->m_pkthdr.ether_vtag = vtag & 0xffff; 2221170589Syongari m->m_flags |= M_VLANTAG; 2222164651Sobrien } 2223159952Sobrien 2224170589Syongari m->m_pkthdr.len = m->m_len = len; 2225170589Syongari m->m_pkthdr.rcvif = ifp; 2226164651Sobrien 2227170589Syongari if ((ifp->if_capenable & IFCAP_RXCSUM) != 0) { 2228170589Syongari if ((flags & NFE_RX_IP_CSUMOK) != 0) { 2229170589Syongari m->m_pkthdr.csum_flags |= CSUM_IP_CHECKED; 2230170589Syongari m->m_pkthdr.csum_flags |= CSUM_IP_VALID; 2231170589Syongari if ((flags & NFE_RX_TCP_CSUMOK) != 0 || 2232170589Syongari (flags & NFE_RX_UDP_CSUMOK) != 0) { 2233170589Syongari m->m_pkthdr.csum_flags |= 2234170589Syongari CSUM_DATA_VALID | CSUM_PSEUDO_HDR; 2235170589Syongari m->m_pkthdr.csum_data = 0xffff; 2236170589Syongari } 2237159952Sobrien } 2238170589Syongari } 2239170589Syongari 2240170589Syongari ifp->if_ipackets++; 2241170589Syongari 2242170589Syongari NFE_UNLOCK(sc); 2243170589Syongari (*ifp->if_input)(ifp, m); 2244170589Syongari NFE_LOCK(sc); 2245170589Syongari } 2246170589Syongari 2247170589Syongari if (prog > 0) 2248170589Syongari bus_dmamap_sync(sc->rxq.rx_desc_tag, sc->rxq.rx_desc_map, 2249170589Syongari BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 2250170589Syongari 2251170589Syongari return (count > 0 ? 0 : EAGAIN); 2252170589Syongari} 2253170589Syongari 2254170589Syongari 2255170589Syongaristatic int 2256170589Syongarinfe_jrxeof(struct nfe_softc *sc, int count) 2257170589Syongari{ 2258170589Syongari struct ifnet *ifp = sc->nfe_ifp; 2259170589Syongari struct nfe_desc32 *desc32; 2260170589Syongari struct nfe_desc64 *desc64; 2261170589Syongari struct nfe_rx_data *data; 2262170589Syongari struct mbuf *m; 2263170589Syongari uint16_t flags; 2264170589Syongari int len, prog; 2265170589Syongari uint32_t vtag = 0; 2266170589Syongari 2267170589Syongari NFE_LOCK_ASSERT(sc); 2268170589Syongari 2269170589Syongari bus_dmamap_sync(sc->jrxq.jrx_desc_tag, sc->jrxq.jrx_desc_map, 2270170589Syongari BUS_DMASYNC_POSTREAD); 2271170589Syongari 2272170589Syongari for (prog = 0;;NFE_INC(sc->jrxq.jcur, NFE_JUMBO_RX_RING_COUNT), 2273170589Syongari vtag = 0) { 2274170589Syongari if (count <= 0) 2275170589Syongari break; 2276170589Syongari count--; 2277170589Syongari 2278170589Syongari data = &sc->jrxq.jdata[sc->jrxq.jcur]; 2279170589Syongari 2280170589Syongari if (sc->nfe_flags & NFE_40BIT_ADDR) { 2281170589Syongari desc64 = &sc->jrxq.jdesc64[sc->jrxq.jcur]; 2282170589Syongari vtag = le32toh(desc64->physaddr[1]); 2283170589Syongari flags = le16toh(desc64->flags); 2284170589Syongari len = le16toh(desc64->length) & NFE_RX_LEN_MASK; 2285170589Syongari } else { 2286170589Syongari desc32 = &sc->jrxq.jdesc32[sc->jrxq.jcur]; 2287170589Syongari flags = le16toh(desc32->flags); 2288170589Syongari len = le16toh(desc32->length) & NFE_RX_LEN_MASK; 2289170589Syongari } 2290170589Syongari 2291170589Syongari if (flags & NFE_RX_READY) 2292170589Syongari break; 2293170589Syongari prog++; 2294170589Syongari if ((sc->nfe_flags & (NFE_JUMBO_SUP | NFE_40BIT_ADDR)) == 0) { 2295170589Syongari if (!(flags & NFE_RX_VALID_V1)) { 2296170589Syongari ifp->if_ierrors++; 2297170589Syongari nfe_discard_jrxbuf(sc, sc->jrxq.jcur); 2298170589Syongari continue; 2299170589Syongari } 2300170589Syongari if ((flags & NFE_RX_FIXME_V1) == NFE_RX_FIXME_V1) { 2301170589Syongari flags &= ~NFE_RX_ERROR; 2302170589Syongari len--; /* fix buffer length */ 2303170589Syongari } 2304170589Syongari } else { 2305170589Syongari if (!(flags & NFE_RX_VALID_V2)) { 2306170589Syongari ifp->if_ierrors++; 2307170589Syongari nfe_discard_jrxbuf(sc, sc->jrxq.jcur); 2308170589Syongari continue; 2309170589Syongari } 2310170589Syongari 2311170589Syongari if ((flags & NFE_RX_FIXME_V2) == NFE_RX_FIXME_V2) { 2312170589Syongari flags &= ~NFE_RX_ERROR; 2313170589Syongari len--; /* fix buffer length */ 2314170589Syongari } 2315170589Syongari } 2316170589Syongari 2317170589Syongari if (flags & NFE_RX_ERROR) { 2318164651Sobrien ifp->if_ierrors++; 2319170589Syongari nfe_discard_jrxbuf(sc, sc->jrxq.jcur); 2320170589Syongari continue; 2321164651Sobrien } 2322159952Sobrien 2323159952Sobrien m = data->m; 2324170589Syongari if (nfe_jnewbuf(sc, sc->jrxq.jcur) != 0) { 2325170589Syongari ifp->if_iqdrops++; 2326170589Syongari nfe_discard_jrxbuf(sc, sc->jrxq.jcur); 2327170589Syongari continue; 2328170589Syongari } 2329159952Sobrien 2330170589Syongari if ((vtag & NFE_RX_VTAG) != 0 && 2331170589Syongari (ifp->if_capenable & IFCAP_VLAN_HWTAGGING) != 0) { 2332170589Syongari m->m_pkthdr.ether_vtag = vtag & 0xffff; 2333170589Syongari m->m_flags |= M_VLANTAG; 2334170589Syongari } 2335170589Syongari 2336159952Sobrien m->m_pkthdr.len = m->m_len = len; 2337159952Sobrien m->m_pkthdr.rcvif = ifp; 2338159952Sobrien 2339170589Syongari if ((ifp->if_capenable & IFCAP_RXCSUM) != 0) { 2340170589Syongari if ((flags & NFE_RX_IP_CSUMOK) != 0) { 2341170589Syongari m->m_pkthdr.csum_flags |= CSUM_IP_CHECKED; 2342159967Sobrien m->m_pkthdr.csum_flags |= CSUM_IP_VALID; 2343170589Syongari if ((flags & NFE_RX_TCP_CSUMOK) != 0 || 2344170589Syongari (flags & NFE_RX_UDP_CSUMOK) != 0) { 2345170589Syongari m->m_pkthdr.csum_flags |= 2346170589Syongari CSUM_DATA_VALID | CSUM_PSEUDO_HDR; 2347170589Syongari m->m_pkthdr.csum_data = 0xffff; 2348170589Syongari } 2349159967Sobrien } 2350159952Sobrien } 2351159952Sobrien 2352159952Sobrien ifp->if_ipackets++; 2353159952Sobrien 2354159967Sobrien NFE_UNLOCK(sc); 2355159967Sobrien (*ifp->if_input)(ifp, m); 2356159967Sobrien NFE_LOCK(sc); 2357170589Syongari } 2358159967Sobrien 2359170589Syongari if (prog > 0) 2360170589Syongari bus_dmamap_sync(sc->jrxq.jrx_desc_tag, sc->jrxq.jrx_desc_map, 2361170589Syongari BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 2362159952Sobrien 2363170589Syongari return (count > 0 ? 0 : EAGAIN); 2364159952Sobrien} 2365159952Sobrien 2366163503Sobrien 2367163503Sobrienstatic void 2368163503Sobriennfe_txeof(struct nfe_softc *sc) 2369159952Sobrien{ 2370159967Sobrien struct ifnet *ifp = sc->nfe_ifp; 2371159952Sobrien struct nfe_desc32 *desc32; 2372159952Sobrien struct nfe_desc64 *desc64; 2373159952Sobrien struct nfe_tx_data *data = NULL; 2374170589Syongari uint16_t flags; 2375170589Syongari int cons, prog; 2376159952Sobrien 2377159967Sobrien NFE_LOCK_ASSERT(sc); 2378159967Sobrien 2379170589Syongari bus_dmamap_sync(sc->txq.tx_desc_tag, sc->txq.tx_desc_map, 2380170589Syongari BUS_DMASYNC_POSTREAD); 2381170589Syongari 2382170589Syongari prog = 0; 2383170589Syongari for (cons = sc->txq.next; cons != sc->txq.cur; 2384170589Syongari NFE_INC(cons, NFE_TX_RING_COUNT)) { 2385159967Sobrien if (sc->nfe_flags & NFE_40BIT_ADDR) { 2386170589Syongari desc64 = &sc->txq.desc64[cons]; 2387170589Syongari flags = le16toh(desc64->flags); 2388159952Sobrien } else { 2389170589Syongari desc32 = &sc->txq.desc32[cons]; 2390170589Syongari flags = le16toh(desc32->flags); 2391159952Sobrien } 2392159952Sobrien 2393159952Sobrien if (flags & NFE_TX_VALID) 2394159952Sobrien break; 2395159952Sobrien 2396170589Syongari prog++; 2397170589Syongari sc->txq.queued--; 2398170589Syongari data = &sc->txq.data[cons]; 2399159952Sobrien 2400159967Sobrien if ((sc->nfe_flags & (NFE_JUMBO_SUP | NFE_40BIT_ADDR)) == 0) { 2401170589Syongari if ((flags & NFE_TX_LASTFRAG_V1) == 0) 2402170589Syongari continue; 2403159952Sobrien if ((flags & NFE_TX_ERROR_V1) != 0) { 2404170589Syongari device_printf(sc->nfe_dev, 2405170589Syongari "tx v1 error 0x%4b\n", flags, NFE_V1_TXERR); 2406159967Sobrien 2407159952Sobrien ifp->if_oerrors++; 2408159952Sobrien } else 2409159952Sobrien ifp->if_opackets++; 2410159952Sobrien } else { 2411170589Syongari if ((flags & NFE_TX_LASTFRAG_V2) == 0) 2412170589Syongari continue; 2413159952Sobrien if ((flags & NFE_TX_ERROR_V2) != 0) { 2414170589Syongari device_printf(sc->nfe_dev, 2415170589Syongari "tx v2 error 0x%4b\n", flags, NFE_V2_TXERR); 2416159952Sobrien ifp->if_oerrors++; 2417159952Sobrien } else 2418159952Sobrien ifp->if_opackets++; 2419159952Sobrien } 2420159952Sobrien 2421159952Sobrien /* last fragment of the mbuf chain transmitted */ 2422170589Syongari KASSERT(data->m != NULL, ("%s: freeing NULL mbuf!", __func__)); 2423170589Syongari bus_dmamap_sync(sc->txq.tx_data_tag, data->tx_data_map, 2424159967Sobrien BUS_DMASYNC_POSTWRITE); 2425170589Syongari bus_dmamap_unload(sc->txq.tx_data_tag, data->tx_data_map); 2426159952Sobrien m_freem(data->m); 2427159952Sobrien data->m = NULL; 2428159952Sobrien } 2429159952Sobrien 2430170589Syongari if (prog > 0) { 2431170589Syongari sc->nfe_force_tx = 0; 2432170589Syongari sc->txq.next = cons; 2433159967Sobrien ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 2434170589Syongari if (sc->txq.queued == 0) 2435170589Syongari sc->nfe_watchdog_timer = 0; 2436159952Sobrien } 2437159952Sobrien} 2438159952Sobrien 2439163503Sobrienstatic int 2440170589Syongarinfe_encap(struct nfe_softc *sc, struct mbuf **m_head) 2441159952Sobrien{ 2442170589Syongari struct nfe_desc32 *desc32 = NULL; 2443170589Syongari struct nfe_desc64 *desc64 = NULL; 2444159952Sobrien bus_dmamap_t map; 2445163503Sobrien bus_dma_segment_t segs[NFE_MAX_SCATTER]; 2446170589Syongari int error, i, nsegs, prod, si; 2447170589Syongari uint32_t tso_segsz; 2448170589Syongari uint16_t cflags, flags; 2449170589Syongari struct mbuf *m; 2450159952Sobrien 2451170589Syongari prod = si = sc->txq.cur; 2452170589Syongari map = sc->txq.data[prod].tx_data_map; 2453159952Sobrien 2454170589Syongari error = bus_dmamap_load_mbuf_sg(sc->txq.tx_data_tag, map, *m_head, segs, 2455159967Sobrien &nsegs, BUS_DMA_NOWAIT); 2456170589Syongari if (error == EFBIG) { 2457175418Sjhb m = m_collapse(*m_head, M_DONTWAIT, NFE_MAX_SCATTER); 2458170589Syongari if (m == NULL) { 2459170589Syongari m_freem(*m_head); 2460170589Syongari *m_head = NULL; 2461170589Syongari return (ENOBUFS); 2462170589Syongari } 2463170589Syongari *m_head = m; 2464170589Syongari error = bus_dmamap_load_mbuf_sg(sc->txq.tx_data_tag, map, 2465170589Syongari *m_head, segs, &nsegs, BUS_DMA_NOWAIT); 2466170589Syongari if (error != 0) { 2467170589Syongari m_freem(*m_head); 2468170589Syongari *m_head = NULL; 2469170589Syongari return (ENOBUFS); 2470170589Syongari } 2471170589Syongari } else if (error != 0) 2472170589Syongari return (error); 2473170589Syongari if (nsegs == 0) { 2474170589Syongari m_freem(*m_head); 2475170589Syongari *m_head = NULL; 2476170589Syongari return (EIO); 2477159952Sobrien } 2478159952Sobrien 2479170589Syongari if (sc->txq.queued + nsegs >= NFE_TX_RING_COUNT - 2) { 2480159967Sobrien bus_dmamap_unload(sc->txq.tx_data_tag, map); 2481170589Syongari return (ENOBUFS); 2482159952Sobrien } 2483159952Sobrien 2484170589Syongari m = *m_head; 2485170589Syongari cflags = flags = 0; 2486170589Syongari tso_segsz = 0; 2487170589Syongari if ((m->m_pkthdr.csum_flags & NFE_CSUM_FEATURES) != 0) { 2488170589Syongari if ((m->m_pkthdr.csum_flags & CSUM_IP) != 0) 2489170589Syongari cflags |= NFE_TX_IP_CSUM; 2490170589Syongari if ((m->m_pkthdr.csum_flags & CSUM_TCP) != 0) 2491170589Syongari cflags |= NFE_TX_TCP_UDP_CSUM; 2492170589Syongari if ((m->m_pkthdr.csum_flags & CSUM_UDP) != 0) 2493170589Syongari cflags |= NFE_TX_TCP_UDP_CSUM; 2494164656Sobrien } 2495170589Syongari if ((m->m_pkthdr.csum_flags & CSUM_TSO) != 0) { 2496170589Syongari tso_segsz = (uint32_t)m->m_pkthdr.tso_segsz << 2497170589Syongari NFE_TX_TSO_SHIFT; 2498170589Syongari cflags &= ~(NFE_TX_IP_CSUM | NFE_TX_TCP_UDP_CSUM); 2499170589Syongari cflags |= NFE_TX_TSO; 2500170589Syongari } 2501159967Sobrien 2502159967Sobrien for (i = 0; i < nsegs; i++) { 2503159967Sobrien if (sc->nfe_flags & NFE_40BIT_ADDR) { 2504170589Syongari desc64 = &sc->txq.desc64[prod]; 2505170589Syongari desc64->physaddr[0] = 2506170589Syongari htole32(NFE_ADDR_HI(segs[i].ds_addr)); 2507170589Syongari desc64->physaddr[1] = 2508170589Syongari htole32(NFE_ADDR_LO(segs[i].ds_addr)); 2509170589Syongari desc64->vtag = 0; 2510159967Sobrien desc64->length = htole16(segs[i].ds_len - 1); 2511159952Sobrien desc64->flags = htole16(flags); 2512159952Sobrien } else { 2513170589Syongari desc32 = &sc->txq.desc32[prod]; 2514170589Syongari desc32->physaddr = 2515170589Syongari htole32(NFE_ADDR_LO(segs[i].ds_addr)); 2516159967Sobrien desc32->length = htole16(segs[i].ds_len - 1); 2517159952Sobrien desc32->flags = htole16(flags); 2518159952Sobrien } 2519159952Sobrien 2520170589Syongari /* 2521170589Syongari * Setting of the valid bit in the first descriptor is 2522170589Syongari * deferred until the whole chain is fully setup. 2523170589Syongari */ 2524170589Syongari flags |= NFE_TX_VALID; 2525163503Sobrien 2526159952Sobrien sc->txq.queued++; 2527170589Syongari NFE_INC(prod, NFE_TX_RING_COUNT); 2528159952Sobrien } 2529159952Sobrien 2530170589Syongari /* 2531170589Syongari * the whole mbuf chain has been DMA mapped, fix last/first descriptor. 2532170589Syongari * csum flags, vtag and TSO belong to the first fragment only. 2533170589Syongari */ 2534159967Sobrien if (sc->nfe_flags & NFE_40BIT_ADDR) { 2535170589Syongari desc64->flags |= htole16(NFE_TX_LASTFRAG_V2); 2536170589Syongari desc64 = &sc->txq.desc64[si]; 2537170589Syongari if ((m->m_flags & M_VLANTAG) != 0) 2538170589Syongari desc64->vtag = htole32(NFE_TX_VTAG | 2539170589Syongari m->m_pkthdr.ether_vtag); 2540170589Syongari if (tso_segsz != 0) { 2541170589Syongari /* 2542170589Syongari * XXX 2543170589Syongari * The following indicates the descriptor element 2544170589Syongari * is a 32bit quantity. 2545170589Syongari */ 2546170589Syongari desc64->length |= htole16((uint16_t)tso_segsz); 2547170589Syongari desc64->flags |= htole16(tso_segsz >> 16); 2548170589Syongari } 2549170589Syongari /* 2550170589Syongari * finally, set the valid/checksum/TSO bit in the first 2551170589Syongari * descriptor. 2552170589Syongari */ 2553170589Syongari desc64->flags |= htole16(NFE_TX_VALID | cflags); 2554159952Sobrien } else { 2555159967Sobrien if (sc->nfe_flags & NFE_JUMBO_SUP) 2556170589Syongari desc32->flags |= htole16(NFE_TX_LASTFRAG_V2); 2557159952Sobrien else 2558170589Syongari desc32->flags |= htole16(NFE_TX_LASTFRAG_V1); 2559170589Syongari desc32 = &sc->txq.desc32[si]; 2560170589Syongari if (tso_segsz != 0) { 2561170589Syongari /* 2562170589Syongari * XXX 2563170589Syongari * The following indicates the descriptor element 2564170589Syongari * is a 32bit quantity. 2565170589Syongari */ 2566170589Syongari desc32->length |= htole16((uint16_t)tso_segsz); 2567170589Syongari desc32->flags |= htole16(tso_segsz >> 16); 2568170589Syongari } 2569170589Syongari /* 2570170589Syongari * finally, set the valid/checksum/TSO bit in the first 2571170589Syongari * descriptor. 2572170589Syongari */ 2573170589Syongari desc32->flags |= htole16(NFE_TX_VALID | cflags); 2574159952Sobrien } 2575159952Sobrien 2576170589Syongari sc->txq.cur = prod; 2577170589Syongari prod = (prod + NFE_TX_RING_COUNT - 1) % NFE_TX_RING_COUNT; 2578170589Syongari sc->txq.data[si].tx_data_map = sc->txq.data[prod].tx_data_map; 2579170589Syongari sc->txq.data[prod].tx_data_map = map; 2580170589Syongari sc->txq.data[prod].m = m; 2581159952Sobrien 2582159967Sobrien bus_dmamap_sync(sc->txq.tx_data_tag, map, BUS_DMASYNC_PREWRITE); 2583159952Sobrien 2584170589Syongari return (0); 2585159952Sobrien} 2586159952Sobrien 2587159967Sobrien 2588163503Sobrienstatic void 2589163503Sobriennfe_setmulti(struct nfe_softc *sc) 2590159952Sobrien{ 2591159967Sobrien struct ifnet *ifp = sc->nfe_ifp; 2592163503Sobrien struct ifmultiaddr *ifma; 2593163503Sobrien int i; 2594170589Syongari uint32_t filter; 2595170589Syongari uint8_t addr[ETHER_ADDR_LEN], mask[ETHER_ADDR_LEN]; 2596170589Syongari uint8_t etherbroadcastaddr[ETHER_ADDR_LEN] = { 2597163503Sobrien 0xff, 0xff, 0xff, 0xff, 0xff, 0xff 2598163503Sobrien }; 2599159967Sobrien 2600159967Sobrien NFE_LOCK_ASSERT(sc); 2601159967Sobrien 2602159967Sobrien if ((ifp->if_flags & (IFF_ALLMULTI | IFF_PROMISC)) != 0) { 2603159967Sobrien bzero(addr, ETHER_ADDR_LEN); 2604159967Sobrien bzero(mask, ETHER_ADDR_LEN); 2605159967Sobrien goto done; 2606159967Sobrien } 2607159967Sobrien 2608159967Sobrien bcopy(etherbroadcastaddr, addr, ETHER_ADDR_LEN); 2609159967Sobrien bcopy(etherbroadcastaddr, mask, ETHER_ADDR_LEN); 2610159967Sobrien 2611159967Sobrien IF_ADDR_LOCK(ifp); 2612159967Sobrien TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { 2613159967Sobrien u_char *addrp; 2614159967Sobrien 2615159967Sobrien if (ifma->ifma_addr->sa_family != AF_LINK) 2616159967Sobrien continue; 2617159967Sobrien 2618159967Sobrien addrp = LLADDR((struct sockaddr_dl *) ifma->ifma_addr); 2619159967Sobrien for (i = 0; i < ETHER_ADDR_LEN; i++) { 2620159967Sobrien u_int8_t mcaddr = addrp[i]; 2621159967Sobrien addr[i] &= mcaddr; 2622159967Sobrien mask[i] &= ~mcaddr; 2623159967Sobrien } 2624159967Sobrien } 2625159967Sobrien IF_ADDR_UNLOCK(ifp); 2626159967Sobrien 2627159967Sobrien for (i = 0; i < ETHER_ADDR_LEN; i++) { 2628159967Sobrien mask[i] |= addr[i]; 2629159967Sobrien } 2630159967Sobrien 2631159967Sobriendone: 2632159967Sobrien addr[0] |= 0x01; /* make sure multicast bit is set */ 2633159967Sobrien 2634159967Sobrien NFE_WRITE(sc, NFE_MULTIADDR_HI, 2635159967Sobrien addr[3] << 24 | addr[2] << 16 | addr[1] << 8 | addr[0]); 2636159967Sobrien NFE_WRITE(sc, NFE_MULTIADDR_LO, 2637159967Sobrien addr[5] << 8 | addr[4]); 2638159967Sobrien NFE_WRITE(sc, NFE_MULTIMASK_HI, 2639159967Sobrien mask[3] << 24 | mask[2] << 16 | mask[1] << 8 | mask[0]); 2640159967Sobrien NFE_WRITE(sc, NFE_MULTIMASK_LO, 2641159967Sobrien mask[5] << 8 | mask[4]); 2642159967Sobrien 2643170589Syongari filter = NFE_READ(sc, NFE_RXFILTER); 2644170589Syongari filter &= NFE_PFF_RX_PAUSE; 2645170589Syongari filter |= NFE_RXFILTER_MAGIC; 2646170589Syongari filter |= (ifp->if_flags & IFF_PROMISC) ? NFE_PFF_PROMISC : NFE_PFF_U2M; 2647159967Sobrien NFE_WRITE(sc, NFE_RXFILTER, filter); 2648159967Sobrien} 2649159967Sobrien 2650163503Sobrien 2651163503Sobrienstatic void 2652170589Syongarinfe_tx_task(void *arg, int pending) 2653159967Sobrien{ 2654170589Syongari struct ifnet *ifp; 2655159967Sobrien 2656170589Syongari ifp = (struct ifnet *)arg; 2657170589Syongari nfe_start(ifp); 2658159967Sobrien} 2659159967Sobrien 2660163503Sobrien 2661163503Sobrienstatic void 2662170589Syongarinfe_start(struct ifnet *ifp) 2663159967Sobrien{ 2664159952Sobrien struct nfe_softc *sc = ifp->if_softc; 2665163503Sobrien struct mbuf *m0; 2666170589Syongari int enq; 2667159952Sobrien 2668170589Syongari NFE_LOCK(sc); 2669170589Syongari 2670170589Syongari if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) != 2671170589Syongari IFF_DRV_RUNNING || sc->nfe_link == 0) { 2672170589Syongari NFE_UNLOCK(sc); 2673159967Sobrien return; 2674159967Sobrien } 2675159967Sobrien 2676170589Syongari for (enq = 0; !IFQ_DRV_IS_EMPTY(&ifp->if_snd);) { 2677170589Syongari IFQ_DRV_DEQUEUE(&ifp->if_snd, m0); 2678159952Sobrien if (m0 == NULL) 2679159952Sobrien break; 2680159952Sobrien 2681170589Syongari if (nfe_encap(sc, &m0) != 0) { 2682170589Syongari if (m0 == NULL) 2683170589Syongari break; 2684170589Syongari IFQ_DRV_PREPEND(&ifp->if_snd, m0); 2685159967Sobrien ifp->if_drv_flags |= IFF_DRV_OACTIVE; 2686159952Sobrien break; 2687159952Sobrien } 2688170589Syongari enq++; 2689167190Scsjp ETHER_BPF_MTAP(ifp, m0); 2690159952Sobrien } 2691159952Sobrien 2692170589Syongari if (enq > 0) { 2693170589Syongari bus_dmamap_sync(sc->txq.tx_desc_tag, sc->txq.tx_desc_map, 2694170589Syongari BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 2695159952Sobrien 2696170589Syongari /* kick Tx */ 2697170589Syongari NFE_WRITE(sc, NFE_RXTX_CTL, NFE_RXTX_KICKTX | sc->rxtxctl); 2698159952Sobrien 2699170589Syongari /* 2700170589Syongari * Set a timeout in case the chip goes out to lunch. 2701170589Syongari */ 2702170589Syongari sc->nfe_watchdog_timer = 5; 2703170589Syongari } 2704159967Sobrien 2705170589Syongari NFE_UNLOCK(sc); 2706159952Sobrien} 2707159952Sobrien 2708163503Sobrien 2709163503Sobrienstatic void 2710163503Sobriennfe_watchdog(struct ifnet *ifp) 2711159952Sobrien{ 2712159952Sobrien struct nfe_softc *sc = ifp->if_softc; 2713159952Sobrien 2714170589Syongari if (sc->nfe_watchdog_timer == 0 || --sc->nfe_watchdog_timer) 2715170589Syongari return; 2716159952Sobrien 2717170589Syongari /* Check if we've lost Tx completion interrupt. */ 2718170589Syongari nfe_txeof(sc); 2719170589Syongari if (sc->txq.queued == 0) { 2720170589Syongari if_printf(ifp, "watchdog timeout (missed Tx interrupts) " 2721170589Syongari "-- recovering\n"); 2722170589Syongari if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) 2723173674Ssam taskqueue_enqueue_fast(sc->nfe_tq, &sc->nfe_tx_task); 2724170589Syongari return; 2725170589Syongari } 2726170589Syongari /* Check if we've lost start Tx command. */ 2727170589Syongari sc->nfe_force_tx++; 2728170589Syongari if (sc->nfe_force_tx <= 3) { 2729170589Syongari /* 2730170589Syongari * If this is the case for watchdog timeout, the following 2731170589Syongari * code should go to nfe_txeof(). 2732170589Syongari */ 2733170589Syongari NFE_WRITE(sc, NFE_RXTX_CTL, NFE_RXTX_KICKTX | sc->rxtxctl); 2734170589Syongari return; 2735170589Syongari } 2736170589Syongari sc->nfe_force_tx = 0; 2737170589Syongari 2738170589Syongari if_printf(ifp, "watchdog timeout\n"); 2739170589Syongari 2740159967Sobrien ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 2741159952Sobrien ifp->if_oerrors++; 2742170589Syongari nfe_init_locked(sc); 2743159952Sobrien} 2744159952Sobrien 2745163503Sobrien 2746163503Sobrienstatic void 2747163503Sobriennfe_init(void *xsc) 2748159952Sobrien{ 2749159967Sobrien struct nfe_softc *sc = xsc; 2750159952Sobrien 2751159967Sobrien NFE_LOCK(sc); 2752159967Sobrien nfe_init_locked(sc); 2753159967Sobrien NFE_UNLOCK(sc); 2754159967Sobrien} 2755159967Sobrien 2756163503Sobrien 2757163503Sobrienstatic void 2758163503Sobriennfe_init_locked(void *xsc) 2759159967Sobrien{ 2760159967Sobrien struct nfe_softc *sc = xsc; 2761159967Sobrien struct ifnet *ifp = sc->nfe_ifp; 2762159967Sobrien struct mii_data *mii; 2763170589Syongari uint32_t val; 2764170589Syongari int error; 2765159967Sobrien 2766159967Sobrien NFE_LOCK_ASSERT(sc); 2767159967Sobrien 2768159967Sobrien mii = device_get_softc(sc->nfe_miibus); 2769159967Sobrien 2770170589Syongari if (ifp->if_drv_flags & IFF_DRV_RUNNING) 2771159967Sobrien return; 2772170589Syongari 2773170589Syongari nfe_stop(ifp); 2774170589Syongari 2775170589Syongari sc->nfe_framesize = ifp->if_mtu + NFE_RX_HEADERS; 2776170589Syongari 2777170589Syongari nfe_init_tx_ring(sc, &sc->txq); 2778170589Syongari if (sc->nfe_framesize > (MCLBYTES - ETHER_HDR_LEN)) 2779170589Syongari error = nfe_init_jrx_ring(sc, &sc->jrxq); 2780170589Syongari else 2781170589Syongari error = nfe_init_rx_ring(sc, &sc->rxq); 2782170589Syongari if (error != 0) { 2783170589Syongari device_printf(sc->nfe_dev, 2784170589Syongari "initialization failed: no memory for rx buffers\n"); 2785170589Syongari nfe_stop(ifp); 2786170589Syongari return; 2787159967Sobrien } 2788159967Sobrien 2789170589Syongari val = 0; 2790170589Syongari if ((sc->nfe_flags & NFE_CORRECT_MACADDR) != 0) 2791170589Syongari val |= NFE_MAC_ADDR_INORDER; 2792170589Syongari NFE_WRITE(sc, NFE_TX_UNK, val); 2793159952Sobrien NFE_WRITE(sc, NFE_STATUS, 0); 2794159952Sobrien 2795170589Syongari if ((sc->nfe_flags & NFE_TX_FLOW_CTRL) != 0) 2796170589Syongari NFE_WRITE(sc, NFE_TX_PAUSE_FRAME, NFE_TX_PAUSE_FRAME_DISABLE); 2797170589Syongari 2798159952Sobrien sc->rxtxctl = NFE_RXTX_BIT2; 2799159967Sobrien if (sc->nfe_flags & NFE_40BIT_ADDR) 2800159952Sobrien sc->rxtxctl |= NFE_RXTX_V3MAGIC; 2801159967Sobrien else if (sc->nfe_flags & NFE_JUMBO_SUP) 2802159952Sobrien sc->rxtxctl |= NFE_RXTX_V2MAGIC; 2803164656Sobrien 2804170589Syongari if ((ifp->if_capenable & IFCAP_RXCSUM) != 0) 2805159952Sobrien sc->rxtxctl |= NFE_RXTX_RXCSUM; 2806170589Syongari if ((ifp->if_capenable & IFCAP_VLAN_HWTAGGING) != 0) 2807170589Syongari sc->rxtxctl |= NFE_RXTX_VTAG_INSERT | NFE_RXTX_VTAG_STRIP; 2808159967Sobrien 2809159952Sobrien NFE_WRITE(sc, NFE_RXTX_CTL, NFE_RXTX_RESET | sc->rxtxctl); 2810159952Sobrien DELAY(10); 2811159952Sobrien NFE_WRITE(sc, NFE_RXTX_CTL, sc->rxtxctl); 2812159952Sobrien 2813170589Syongari if ((ifp->if_capenable & IFCAP_VLAN_HWTAGGING) != 0) 2814159952Sobrien NFE_WRITE(sc, NFE_VTAG_CTL, NFE_VTAG_ENABLE); 2815170589Syongari else 2816170589Syongari NFE_WRITE(sc, NFE_VTAG_CTL, 0); 2817159952Sobrien 2818159952Sobrien NFE_WRITE(sc, NFE_SETUP_R6, 0); 2819159952Sobrien 2820159952Sobrien /* set MAC address */ 2821170589Syongari nfe_set_macaddr(sc, IF_LLADDR(ifp)); 2822159952Sobrien 2823159952Sobrien /* tell MAC where rings are in memory */ 2824170589Syongari if (sc->nfe_framesize > MCLBYTES - ETHER_HDR_LEN) { 2825170589Syongari NFE_WRITE(sc, NFE_RX_RING_ADDR_HI, 2826170589Syongari NFE_ADDR_HI(sc->jrxq.jphysaddr)); 2827170589Syongari NFE_WRITE(sc, NFE_RX_RING_ADDR_LO, 2828170589Syongari NFE_ADDR_LO(sc->jrxq.jphysaddr)); 2829170589Syongari } else { 2830170589Syongari NFE_WRITE(sc, NFE_RX_RING_ADDR_HI, 2831170589Syongari NFE_ADDR_HI(sc->rxq.physaddr)); 2832170589Syongari NFE_WRITE(sc, NFE_RX_RING_ADDR_LO, 2833170589Syongari NFE_ADDR_LO(sc->rxq.physaddr)); 2834170589Syongari } 2835170589Syongari NFE_WRITE(sc, NFE_TX_RING_ADDR_HI, NFE_ADDR_HI(sc->txq.physaddr)); 2836170589Syongari NFE_WRITE(sc, NFE_TX_RING_ADDR_LO, NFE_ADDR_LO(sc->txq.physaddr)); 2837159952Sobrien 2838159952Sobrien NFE_WRITE(sc, NFE_RING_SIZE, 2839159952Sobrien (NFE_RX_RING_COUNT - 1) << 16 | 2840159952Sobrien (NFE_TX_RING_COUNT - 1)); 2841159952Sobrien 2842170589Syongari NFE_WRITE(sc, NFE_RXBUFSZ, sc->nfe_framesize); 2843159952Sobrien 2844159952Sobrien /* force MAC to wakeup */ 2845170589Syongari val = NFE_READ(sc, NFE_PWR_STATE); 2846170589Syongari if ((val & NFE_PWR_WAKEUP) == 0) 2847170589Syongari NFE_WRITE(sc, NFE_PWR_STATE, val | NFE_PWR_WAKEUP); 2848159952Sobrien DELAY(10); 2849170589Syongari val = NFE_READ(sc, NFE_PWR_STATE); 2850170589Syongari NFE_WRITE(sc, NFE_PWR_STATE, val | NFE_PWR_VALID); 2851159952Sobrien 2852159952Sobrien#if 1 2853159952Sobrien /* configure interrupts coalescing/mitigation */ 2854159952Sobrien NFE_WRITE(sc, NFE_IMTIMER, NFE_IM_DEFAULT); 2855159952Sobrien#else 2856159952Sobrien /* no interrupt mitigation: one interrupt per packet */ 2857159952Sobrien NFE_WRITE(sc, NFE_IMTIMER, 970); 2858159952Sobrien#endif 2859159952Sobrien 2860170589Syongari NFE_WRITE(sc, NFE_SETUP_R1, NFE_R1_MAGIC_10_100); 2861159952Sobrien NFE_WRITE(sc, NFE_SETUP_R2, NFE_R2_MAGIC); 2862159952Sobrien NFE_WRITE(sc, NFE_SETUP_R6, NFE_R6_MAGIC); 2863159952Sobrien 2864159952Sobrien /* update MAC knowledge of PHY; generates a NFE_IRQ_LINK interrupt */ 2865159952Sobrien NFE_WRITE(sc, NFE_STATUS, sc->mii_phyaddr << 24 | NFE_STATUS_MAGIC); 2866159952Sobrien 2867159952Sobrien NFE_WRITE(sc, NFE_SETUP_R4, NFE_R4_MAGIC); 2868159952Sobrien NFE_WRITE(sc, NFE_WOL_CTL, NFE_WOL_MAGIC); 2869159952Sobrien 2870159952Sobrien sc->rxtxctl &= ~NFE_RXTX_BIT2; 2871159952Sobrien NFE_WRITE(sc, NFE_RXTX_CTL, sc->rxtxctl); 2872159952Sobrien DELAY(10); 2873159952Sobrien NFE_WRITE(sc, NFE_RXTX_CTL, NFE_RXTX_BIT1 | sc->rxtxctl); 2874159952Sobrien 2875159952Sobrien /* set Rx filter */ 2876159952Sobrien nfe_setmulti(sc); 2877159952Sobrien 2878159952Sobrien /* enable Rx */ 2879159952Sobrien NFE_WRITE(sc, NFE_RX_CTL, NFE_RX_START); 2880159952Sobrien 2881159952Sobrien /* enable Tx */ 2882159952Sobrien NFE_WRITE(sc, NFE_TX_CTL, NFE_TX_START); 2883159952Sobrien 2884159952Sobrien NFE_WRITE(sc, NFE_PHY_STATUS, 0xf); 2885159952Sobrien 2886159967Sobrien#ifdef DEVICE_POLLING 2887159967Sobrien if (ifp->if_capenable & IFCAP_POLLING) 2888170589Syongari nfe_disable_intr(sc); 2889159967Sobrien else 2890159967Sobrien#endif 2891170589Syongari nfe_set_intr(sc); 2892170589Syongari nfe_enable_intr(sc); /* enable interrupts */ 2893159952Sobrien 2894159967Sobrien ifp->if_drv_flags |= IFF_DRV_RUNNING; 2895159967Sobrien ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 2896159952Sobrien 2897159967Sobrien sc->nfe_link = 0; 2898170589Syongari mii_mediachg(mii); 2899159952Sobrien 2900170589Syongari callout_reset(&sc->nfe_stat_ch, hz, nfe_tick, sc); 2901159952Sobrien} 2902159952Sobrien 2903163503Sobrien 2904163503Sobrienstatic void 2905170589Syongarinfe_stop(struct ifnet *ifp) 2906159952Sobrien{ 2907159952Sobrien struct nfe_softc *sc = ifp->if_softc; 2908170589Syongari struct nfe_rx_ring *rx_ring; 2909170589Syongari struct nfe_jrx_ring *jrx_ring; 2910170589Syongari struct nfe_tx_ring *tx_ring; 2911170589Syongari struct nfe_rx_data *rdata; 2912170589Syongari struct nfe_tx_data *tdata; 2913170589Syongari int i; 2914159952Sobrien 2915159967Sobrien NFE_LOCK_ASSERT(sc); 2916159952Sobrien 2917170589Syongari sc->nfe_watchdog_timer = 0; 2918159967Sobrien ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); 2919159952Sobrien 2920159967Sobrien callout_stop(&sc->nfe_stat_ch); 2921159967Sobrien 2922159952Sobrien /* abort Tx */ 2923159952Sobrien NFE_WRITE(sc, NFE_TX_CTL, 0); 2924159952Sobrien 2925159952Sobrien /* disable Rx */ 2926159952Sobrien NFE_WRITE(sc, NFE_RX_CTL, 0); 2927159952Sobrien 2928159952Sobrien /* disable interrupts */ 2929170589Syongari nfe_disable_intr(sc); 2930159952Sobrien 2931159967Sobrien sc->nfe_link = 0; 2932159967Sobrien 2933170589Syongari /* free Rx and Tx mbufs still in the queues. */ 2934170589Syongari rx_ring = &sc->rxq; 2935170589Syongari for (i = 0; i < NFE_RX_RING_COUNT; i++) { 2936170589Syongari rdata = &rx_ring->data[i]; 2937170589Syongari if (rdata->m != NULL) { 2938170589Syongari bus_dmamap_sync(rx_ring->rx_data_tag, 2939170589Syongari rdata->rx_data_map, BUS_DMASYNC_POSTREAD); 2940170589Syongari bus_dmamap_unload(rx_ring->rx_data_tag, 2941170589Syongari rdata->rx_data_map); 2942170589Syongari m_freem(rdata->m); 2943170589Syongari rdata->m = NULL; 2944170589Syongari } 2945170589Syongari } 2946159952Sobrien 2947170589Syongari if ((sc->nfe_flags & NFE_JUMBO_SUP) != 0) { 2948170589Syongari jrx_ring = &sc->jrxq; 2949170589Syongari for (i = 0; i < NFE_JUMBO_RX_RING_COUNT; i++) { 2950170589Syongari rdata = &jrx_ring->jdata[i]; 2951170589Syongari if (rdata->m != NULL) { 2952170589Syongari bus_dmamap_sync(jrx_ring->jrx_data_tag, 2953170589Syongari rdata->rx_data_map, BUS_DMASYNC_POSTREAD); 2954170589Syongari bus_dmamap_unload(jrx_ring->jrx_data_tag, 2955170589Syongari rdata->rx_data_map); 2956170589Syongari m_freem(rdata->m); 2957170589Syongari rdata->m = NULL; 2958170589Syongari } 2959170589Syongari } 2960170589Syongari } 2961170589Syongari 2962170589Syongari tx_ring = &sc->txq; 2963170589Syongari for (i = 0; i < NFE_RX_RING_COUNT; i++) { 2964170589Syongari tdata = &tx_ring->data[i]; 2965170589Syongari if (tdata->m != NULL) { 2966170589Syongari bus_dmamap_sync(tx_ring->tx_data_tag, 2967170589Syongari tdata->tx_data_map, BUS_DMASYNC_POSTWRITE); 2968170589Syongari bus_dmamap_unload(tx_ring->tx_data_tag, 2969170589Syongari tdata->tx_data_map); 2970170589Syongari m_freem(tdata->m); 2971170589Syongari tdata->m = NULL; 2972170589Syongari } 2973170589Syongari } 2974159952Sobrien} 2975159952Sobrien 2976163503Sobrien 2977163503Sobrienstatic int 2978163503Sobriennfe_ifmedia_upd(struct ifnet *ifp) 2979159952Sobrien{ 2980159967Sobrien struct nfe_softc *sc = ifp->if_softc; 2981170589Syongari struct mii_data *mii; 2982159952Sobrien 2983159967Sobrien NFE_LOCK(sc); 2984159967Sobrien mii = device_get_softc(sc->nfe_miibus); 2985159967Sobrien mii_mediachg(mii); 2986170589Syongari NFE_UNLOCK(sc); 2987159967Sobrien 2988159967Sobrien return (0); 2989159952Sobrien} 2990159952Sobrien 2991163503Sobrien 2992163503Sobrienstatic void 2993163503Sobriennfe_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr) 2994159952Sobrien{ 2995163503Sobrien struct nfe_softc *sc; 2996163503Sobrien struct mii_data *mii; 2997159952Sobrien 2998159967Sobrien sc = ifp->if_softc; 2999159952Sobrien 3000159967Sobrien NFE_LOCK(sc); 3001159967Sobrien mii = device_get_softc(sc->nfe_miibus); 3002159967Sobrien mii_pollstat(mii); 3003159967Sobrien NFE_UNLOCK(sc); 3004159952Sobrien 3005159967Sobrien ifmr->ifm_active = mii->mii_media_active; 3006159967Sobrien ifmr->ifm_status = mii->mii_media_status; 3007159952Sobrien} 3008159952Sobrien 3009163503Sobrien 3010170589Syongarivoid 3011159967Sobriennfe_tick(void *xsc) 3012159952Sobrien{ 3013159967Sobrien struct nfe_softc *sc; 3014163503Sobrien struct mii_data *mii; 3015163503Sobrien struct ifnet *ifp; 3016159952Sobrien 3017170589Syongari sc = (struct nfe_softc *)xsc; 3018159952Sobrien 3019163503Sobrien NFE_LOCK_ASSERT(sc); 3020159952Sobrien 3021159967Sobrien ifp = sc->nfe_ifp; 3022159952Sobrien 3023159967Sobrien mii = device_get_softc(sc->nfe_miibus); 3024159967Sobrien mii_tick(mii); 3025170589Syongari nfe_watchdog(ifp); 3026159967Sobrien callout_reset(&sc->nfe_stat_ch, hz, nfe_tick, sc); 3027159952Sobrien} 3028159952Sobrien 3029159952Sobrien 3030173839Syongaristatic int 3031163503Sobriennfe_shutdown(device_t dev) 3032159952Sobrien{ 3033159967Sobrien struct nfe_softc *sc; 3034159967Sobrien struct ifnet *ifp; 3035159952Sobrien 3036159967Sobrien sc = device_get_softc(dev); 3037159952Sobrien 3038159967Sobrien NFE_LOCK(sc); 3039159967Sobrien ifp = sc->nfe_ifp; 3040170589Syongari nfe_stop(ifp); 3041159967Sobrien /* nfe_reset(sc); */ 3042159967Sobrien NFE_UNLOCK(sc); 3043173839Syongari 3044173839Syongari return (0); 3045159952Sobrien} 3046159952Sobrien 3047159952Sobrien 3048163503Sobrienstatic void 3049170589Syongarinfe_get_macaddr(struct nfe_softc *sc, uint8_t *addr) 3050159952Sobrien{ 3051170589Syongari uint32_t val; 3052159952Sobrien 3053170589Syongari if ((sc->nfe_flags & NFE_CORRECT_MACADDR) == 0) { 3054170589Syongari val = NFE_READ(sc, NFE_MACADDR_LO); 3055170589Syongari addr[0] = (val >> 8) & 0xff; 3056170589Syongari addr[1] = (val & 0xff); 3057159952Sobrien 3058170589Syongari val = NFE_READ(sc, NFE_MACADDR_HI); 3059170589Syongari addr[2] = (val >> 24) & 0xff; 3060170589Syongari addr[3] = (val >> 16) & 0xff; 3061170589Syongari addr[4] = (val >> 8) & 0xff; 3062170589Syongari addr[5] = (val & 0xff); 3063170589Syongari } else { 3064170589Syongari val = NFE_READ(sc, NFE_MACADDR_LO); 3065170589Syongari addr[5] = (val >> 8) & 0xff; 3066170589Syongari addr[4] = (val & 0xff); 3067170589Syongari 3068170589Syongari val = NFE_READ(sc, NFE_MACADDR_HI); 3069170589Syongari addr[3] = (val >> 24) & 0xff; 3070170589Syongari addr[2] = (val >> 16) & 0xff; 3071170589Syongari addr[1] = (val >> 8) & 0xff; 3072170589Syongari addr[0] = (val & 0xff); 3073170589Syongari } 3074159952Sobrien} 3075159952Sobrien 3076163503Sobrien 3077163503Sobrienstatic void 3078170589Syongarinfe_set_macaddr(struct nfe_softc *sc, uint8_t *addr) 3079159952Sobrien{ 3080159967Sobrien 3081159967Sobrien NFE_WRITE(sc, NFE_MACADDR_LO, addr[5] << 8 | addr[4]); 3082159967Sobrien NFE_WRITE(sc, NFE_MACADDR_HI, addr[3] << 24 | addr[2] << 16 | 3083159967Sobrien addr[1] << 8 | addr[0]); 3084159952Sobrien} 3085159952Sobrien 3086163503Sobrien 3087159967Sobrien/* 3088159967Sobrien * Map a single buffer address. 3089159967Sobrien */ 3090159967Sobrien 3091159967Sobrienstatic void 3092170589Syongarinfe_dma_map_segs(void *arg, bus_dma_segment_t *segs, int nseg, int error) 3093159952Sobrien{ 3094170589Syongari struct nfe_dmamap_arg *ctx; 3095159952Sobrien 3096170589Syongari if (error != 0) 3097159967Sobrien return; 3098159952Sobrien 3099159967Sobrien KASSERT(nseg == 1, ("too many DMA segments, %d should be 1", nseg)); 3100159967Sobrien 3101170589Syongari ctx = (struct nfe_dmamap_arg *)arg; 3102170589Syongari ctx->nfe_busaddr = segs[0].ds_addr; 3103170589Syongari} 3104159967Sobrien 3105170589Syongari 3106170589Syongaristatic int 3107170589Syongarisysctl_int_range(SYSCTL_HANDLER_ARGS, int low, int high) 3108170589Syongari{ 3109170589Syongari int error, value; 3110170589Syongari 3111170589Syongari if (!arg1) 3112170589Syongari return (EINVAL); 3113170589Syongari value = *(int *)arg1; 3114170589Syongari error = sysctl_handle_int(oidp, &value, 0, req); 3115170589Syongari if (error || !req->newptr) 3116170589Syongari return (error); 3117170589Syongari if (value < low || value > high) 3118170589Syongari return (EINVAL); 3119170589Syongari *(int *)arg1 = value; 3120170589Syongari 3121170589Syongari return (0); 3122159952Sobrien} 3123170589Syongari 3124170589Syongari 3125170589Syongaristatic int 3126170589Syongarisysctl_hw_nfe_proc_limit(SYSCTL_HANDLER_ARGS) 3127170589Syongari{ 3128170589Syongari 3129170589Syongari return (sysctl_int_range(oidp, arg1, arg2, req, NFE_PROC_MIN, 3130170589Syongari NFE_PROC_MAX)); 3131170589Syongari} 3132