if_nfe.c revision 164649
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 164649 2006-11-27 00:10:00Z obrien $"); 25159952Sobrien 26159967Sobrien/* Uncomment the following line to enable polling. */ 27163503Sobrien/* #define DEVICE_POLLING */ 28159967Sobrien 29163503Sobrien#define NFE_NO_JUMBO 30163503Sobrien#define NFE_CSUM 31163503Sobrien#define NFE_CSUM_FEATURES (CSUM_IP | CSUM_TCP | CSUM_UDP) 32163503Sobrien#define NVLAN 0 33159967Sobrien 34159967Sobrien#ifdef HAVE_KERNEL_OPTION_HEADERS 35159967Sobrien#include "opt_device_polling.h" 36159967Sobrien#endif 37159967Sobrien 38159952Sobrien#include <sys/param.h> 39159952Sobrien#include <sys/endian.h> 40159952Sobrien#include <sys/systm.h> 41159952Sobrien#include <sys/sockio.h> 42159952Sobrien#include <sys/mbuf.h> 43159952Sobrien#include <sys/malloc.h> 44159967Sobrien#include <sys/module.h> 45159952Sobrien#include <sys/kernel.h> 46159952Sobrien#include <sys/socket.h> 47159967Sobrien#include <sys/taskqueue.h> 48159952Sobrien 49159952Sobrien#include <net/if.h> 50159967Sobrien#include <net/if_arp.h> 51159967Sobrien#include <net/ethernet.h> 52159952Sobrien#include <net/if_dl.h> 53159952Sobrien#include <net/if_media.h> 54159952Sobrien#include <net/if_types.h> 55159952Sobrien#include <net/if_vlan_var.h> 56159952Sobrien 57159952Sobrien#include <net/bpf.h> 58159952Sobrien 59159967Sobrien#include <machine/bus.h> 60159967Sobrien#include <machine/resource.h> 61159967Sobrien#include <sys/bus.h> 62159967Sobrien#include <sys/rman.h> 63159967Sobrien 64159952Sobrien#include <dev/mii/mii.h> 65159952Sobrien#include <dev/mii/miivar.h> 66159952Sobrien 67159952Sobrien#include <dev/pci/pcireg.h> 68159952Sobrien#include <dev/pci/pcivar.h> 69159952Sobrien 70159967Sobrien#include <dev/nfe/if_nfereg.h> 71159967Sobrien#include <dev/nfe/if_nfevar.h> 72159952Sobrien 73159967SobrienMODULE_DEPEND(nfe, pci, 1, 1, 1); 74159967SobrienMODULE_DEPEND(nfe, ether, 1, 1, 1); 75159967SobrienMODULE_DEPEND(nfe, miibus, 1, 1, 1); 76159967Sobrien#include "miibus_if.h" 77159952Sobrien 78163503Sobrienstatic int nfe_probe(device_t); 79163503Sobrienstatic int nfe_attach(device_t); 80163503Sobrienstatic int nfe_detach(device_t); 81163503Sobrienstatic void nfe_shutdown(device_t); 82163503Sobrienstatic int nfe_miibus_readreg(device_t, int, int); 83163503Sobrienstatic int nfe_miibus_writereg(device_t, int, int, int); 84163503Sobrienstatic void nfe_miibus_statchg(device_t); 85163503Sobrienstatic int nfe_ioctl(struct ifnet *, u_long, caddr_t); 86163503Sobrienstatic void nfe_intr(void *); 87159967Sobrienstatic void nfe_txdesc32_sync(struct nfe_softc *, struct nfe_desc32 *, int); 88159967Sobrienstatic void nfe_txdesc64_sync(struct nfe_softc *, struct nfe_desc64 *, int); 89159967Sobrienstatic void nfe_txdesc32_rsync(struct nfe_softc *, int, int, int); 90159967Sobrienstatic void nfe_txdesc64_rsync(struct nfe_softc *, int, int, int); 91159967Sobrienstatic void nfe_rxdesc32_sync(struct nfe_softc *, struct nfe_desc32 *, int); 92159967Sobrienstatic void nfe_rxdesc64_sync(struct nfe_softc *, struct nfe_desc64 *, int); 93159967Sobrienstatic void nfe_rxeof(struct nfe_softc *); 94159967Sobrienstatic void nfe_txeof(struct nfe_softc *); 95159967Sobrienstatic int nfe_encap(struct nfe_softc *, struct mbuf *); 96159967Sobrienstatic struct nfe_jbuf *nfe_jalloc(struct nfe_softc *); 97159967Sobrienstatic void nfe_jfree(void *, void *); 98159967Sobrienstatic int nfe_jpool_alloc(struct nfe_softc *); 99159967Sobrienstatic void nfe_jpool_free(struct nfe_softc *); 100159967Sobrienstatic void nfe_setmulti(struct nfe_softc *); 101159967Sobrienstatic void nfe_start(struct ifnet *); 102159967Sobrienstatic void nfe_start_locked(struct ifnet *); 103159967Sobrienstatic void nfe_watchdog(struct ifnet *); 104159967Sobrienstatic void nfe_init(void *); 105159967Sobrienstatic void nfe_init_locked(void *); 106159967Sobrienstatic void nfe_stop(struct ifnet *, int); 107159967Sobrienstatic int nfe_alloc_rx_ring(struct nfe_softc *, struct nfe_rx_ring *); 108159967Sobrienstatic void nfe_reset_rx_ring(struct nfe_softc *, struct nfe_rx_ring *); 109159967Sobrienstatic void nfe_free_rx_ring(struct nfe_softc *, struct nfe_rx_ring *); 110159967Sobrienstatic int nfe_alloc_tx_ring(struct nfe_softc *, struct nfe_tx_ring *); 111159967Sobrienstatic void nfe_reset_tx_ring(struct nfe_softc *, struct nfe_tx_ring *); 112159967Sobrienstatic void nfe_free_tx_ring(struct nfe_softc *, struct nfe_tx_ring *); 113159967Sobrienstatic int nfe_ifmedia_upd(struct ifnet *); 114159967Sobrienstatic int nfe_ifmedia_upd_locked(struct ifnet *); 115159967Sobrienstatic void nfe_ifmedia_sts(struct ifnet *, struct ifmediareq *); 116159967Sobrienstatic void nfe_tick(void *); 117159967Sobrienstatic void nfe_tick_locked(struct nfe_softc *); 118159967Sobrienstatic void nfe_get_macaddr(struct nfe_softc *, u_char *); 119159967Sobrienstatic void nfe_set_macaddr(struct nfe_softc *, u_char *); 120159967Sobrienstatic void nfe_dma_map_segs (void *, bus_dma_segment_t *, int, int); 121159967Sobrien#ifdef DEVICE_POLLING 122159967Sobrienstatic void nfe_poll_locked(struct ifnet *, enum poll_cmd, int); 123159967Sobrien#endif 124159952Sobrien 125159952Sobrien#ifdef NFE_DEBUG 126159952Sobrienint nfedebug = 0; 127163503Sobrien#define DPRINTF(x) do { if (nfedebug) printf x; } while (0) 128163503Sobrien#define DPRINTFN(n,x) do { if (nfedebug >= (n)) printf x; } while (0) 129159952Sobrien#else 130163503Sobrien#define DPRINTF(x) 131163503Sobrien#define DPRINTFN(n,x) 132159952Sobrien#endif 133159952Sobrien 134159967Sobrien#define NFE_LOCK(_sc) mtx_lock(&(_sc)->nfe_mtx) 135159967Sobrien#define NFE_UNLOCK(_sc) mtx_unlock(&(_sc)->nfe_mtx) 136159967Sobrien#define NFE_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->nfe_mtx, MA_OWNED) 137159967Sobrien 138163503Sobrien#define letoh16(x) le16toh(x) 139159967Sobrien 140159967Sobrien#define NV_RID 0x10 141159967Sobrien 142159967Sobrienstatic device_method_t nfe_methods[] = { 143159967Sobrien /* Device interface */ 144159967Sobrien DEVMETHOD(device_probe, nfe_probe), 145159967Sobrien DEVMETHOD(device_attach, nfe_attach), 146159967Sobrien DEVMETHOD(device_detach, nfe_detach), 147159967Sobrien DEVMETHOD(device_shutdown, nfe_shutdown), 148159967Sobrien 149159967Sobrien /* bus interface */ 150159967Sobrien DEVMETHOD(bus_print_child, bus_generic_print_child), 151159967Sobrien DEVMETHOD(bus_driver_added, bus_generic_driver_added), 152159967Sobrien 153159967Sobrien /* MII interface */ 154159967Sobrien DEVMETHOD(miibus_readreg, nfe_miibus_readreg), 155159967Sobrien DEVMETHOD(miibus_writereg, nfe_miibus_writereg), 156163503Sobrien DEVMETHOD(miibus_statchg, nfe_miibus_statchg), 157159967Sobrien 158159967Sobrien { 0, 0 } 159159952Sobrien}; 160159952Sobrien 161159967Sobrienstatic driver_t nfe_driver = { 162159967Sobrien "nfe", 163159967Sobrien nfe_methods, 164159967Sobrien sizeof(struct nfe_softc) 165159967Sobrien}; 166159967Sobrien 167159967Sobrienstatic devclass_t nfe_devclass; 168159967Sobrien 169159967SobrienDRIVER_MODULE(nfe, pci, nfe_driver, nfe_devclass, 0, 0); 170159967SobrienDRIVER_MODULE(miibus, nfe, miibus_driver, miibus_devclass, 0, 0); 171159967Sobrien 172159967Sobrienstatic struct nfe_type nfe_devs[] = { 173159967Sobrien {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE_LAN, 174163503Sobrien "NVIDIA nForce MCP Networking Adapter"}, 175159967Sobrien {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE2_LAN, 176163503Sobrien "NVIDIA nForce2 MCP2 Networking Adapter"}, 177159967Sobrien {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE2_400_LAN1, 178163503Sobrien "NVIDIA nForce2 400 MCP4 Networking Adapter"}, 179159967Sobrien {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE2_400_LAN2, 180163503Sobrien "NVIDIA nForce2 400 MCP5 Networking Adapter"}, 181163437Sobrien {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE3_LAN1, 182163503Sobrien "NVIDIA nForce3 MCP3 Networking Adapter"}, 183159967Sobrien {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE3_250_LAN, 184163503Sobrien "NVIDIA nForce3 250 MCP6 Networking Adapter"}, 185159967Sobrien {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE3_LAN4, 186163503Sobrien "NVIDIA nForce3 MCP7 Networking Adapter"}, 187159967Sobrien {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE4_LAN1, 188163503Sobrien "NVIDIA nForce4 CK804 MCP8 Networking Adapter"}, 189159967Sobrien {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE4_LAN2, 190163503Sobrien "NVIDIA nForce4 CK804 MCP9 Networking Adapter"}, 191159967Sobrien {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP04_LAN1, 192163503Sobrien "NVIDIA nForce MCP04 Networking Adapter"}, // MCP10 193159967Sobrien {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP04_LAN2, 194163503Sobrien "NVIDIA nForce MCP04 Networking Adapter"}, // MCP11 195159967Sobrien {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE430_LAN1, 196163503Sobrien "NVIDIA nForce 430 MCP12 Networking Adapter"}, 197159967Sobrien {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE430_LAN2, 198163503Sobrien "NVIDIA nForce 430 MCP13 Networking Adapter"}, 199159967Sobrien {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP55_LAN1, 200163503Sobrien "NVIDIA nForce MCP55 Networking Adapter"}, 201159967Sobrien {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP55_LAN2, 202163503Sobrien "NVIDIA nForce MCP55 Networking Adapter"}, 203162212Sobrien {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP61_LAN1, 204163503Sobrien "NVIDIA nForce MCP61 Networking Adapter"}, 205162212Sobrien {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP61_LAN2, 206163503Sobrien "NVIDIA nForce MCP61 Networking Adapter"}, 207162212Sobrien {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP61_LAN3, 208163503Sobrien "NVIDIA nForce MCP61 Networking Adapter"}, 209162212Sobrien {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP61_LAN2, 210163503Sobrien "NVIDIA nForce MCP61 Networking Adapter"}, 211162212Sobrien {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP65_LAN1, 212163503Sobrien "NVIDIA nForce MCP65 Networking Adapter"}, 213162212Sobrien {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP65_LAN2, 214163503Sobrien "NVIDIA nForce MCP65 Networking Adapter"}, 215162212Sobrien {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP65_LAN3, 216163503Sobrien "NVIDIA nForce MCP65 Networking Adapter"}, 217162212Sobrien {PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP65_LAN2, 218163503Sobrien "NVIDIA nForce MCP65 Networking Adapter"}, 219159967Sobrien {0, 0, NULL} 220159967Sobrien}; 221159967Sobrien 222159967Sobrien 223159967Sobrien/* Probe for supported hardware ID's */ 224159967Sobrienstatic int 225159967Sobriennfe_probe(device_t dev) 226159952Sobrien{ 227159967Sobrien struct nfe_type *t; 228159967Sobrien 229159967Sobrien t = nfe_devs; 230159967Sobrien /* Check for matching PCI DEVICE ID's */ 231159967Sobrien while (t->name != NULL) { 232159967Sobrien if ((pci_get_vendor(dev) == t->vid_id) && 233159967Sobrien (pci_get_device(dev) == t->dev_id)) { 234159967Sobrien device_set_desc(dev, t->name); 235159967Sobrien return (0); 236159967Sobrien } 237159967Sobrien t++; 238159967Sobrien } 239159967Sobrien 240159967Sobrien return (ENXIO); 241159952Sobrien} 242159952Sobrien 243163503Sobrien 244159967Sobrienstatic int 245159967Sobriennfe_attach(device_t dev) 246159952Sobrien{ 247159967Sobrien struct nfe_softc *sc; 248159952Sobrien struct ifnet *ifp; 249159967Sobrien int unit, error = 0, rid; 250159952Sobrien 251159967Sobrien sc = device_get_softc(dev); 252159967Sobrien unit = device_get_unit(dev); 253159967Sobrien sc->nfe_dev = dev; 254159967Sobrien sc->nfe_unit = unit; 255159952Sobrien 256159967Sobrien mtx_init(&sc->nfe_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK, 257159967Sobrien MTX_DEF | MTX_RECURSE); 258159967Sobrien callout_init_mtx(&sc->nfe_stat_ch, &sc->nfe_mtx, 0); 259159967Sobrien 260163503Sobrien pci_enable_busmaster(dev); 261159967Sobrien 262159967Sobrien rid = NV_RID; 263159967Sobrien sc->nfe_res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, 264159967Sobrien 0, ~0, 1, RF_ACTIVE); 265159967Sobrien 266159967Sobrien if (sc->nfe_res == NULL) { 267159967Sobrien printf ("nfe%d: couldn't map ports/memory\n", unit); 268159967Sobrien error = ENXIO; 269159967Sobrien goto fail; 270159952Sobrien } 271159952Sobrien 272159967Sobrien sc->nfe_memt = rman_get_bustag(sc->nfe_res); 273159967Sobrien sc->nfe_memh = rman_get_bushandle(sc->nfe_res); 274159967Sobrien 275159967Sobrien /* Allocate interrupt */ 276159967Sobrien rid = 0; 277159967Sobrien sc->nfe_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 278159967Sobrien 0, ~0, 1, RF_SHAREABLE | RF_ACTIVE); 279159967Sobrien 280159967Sobrien if (sc->nfe_irq == NULL) { 281159967Sobrien printf("nfe%d: couldn't map interrupt\n", unit); 282159967Sobrien error = ENXIO; 283159967Sobrien goto fail; 284159952Sobrien } 285159952Sobrien 286159967Sobrien nfe_get_macaddr(sc, sc->eaddr); 287159952Sobrien 288159967Sobrien sc->nfe_flags = 0; 289159952Sobrien 290159967Sobrien switch (pci_get_device(dev)) { 291159952Sobrien case PCI_PRODUCT_NVIDIA_NFORCE3_LAN2: 292159952Sobrien case PCI_PRODUCT_NVIDIA_NFORCE3_LAN3: 293159952Sobrien case PCI_PRODUCT_NVIDIA_NFORCE3_LAN4: 294159952Sobrien case PCI_PRODUCT_NVIDIA_NFORCE3_LAN5: 295159967Sobrien sc->nfe_flags |= NFE_JUMBO_SUP | NFE_HW_CSUM; 296159952Sobrien break; 297159952Sobrien case PCI_PRODUCT_NVIDIA_MCP51_LAN1: 298159952Sobrien case PCI_PRODUCT_NVIDIA_MCP51_LAN2: 299159967Sobrien sc->nfe_flags |= NFE_40BIT_ADDR; 300159952Sobrien break; 301159952Sobrien case PCI_PRODUCT_NVIDIA_CK804_LAN1: 302159952Sobrien case PCI_PRODUCT_NVIDIA_CK804_LAN2: 303159952Sobrien case PCI_PRODUCT_NVIDIA_MCP04_LAN1: 304159952Sobrien case PCI_PRODUCT_NVIDIA_MCP04_LAN2: 305159967Sobrien sc->nfe_flags |= NFE_JUMBO_SUP | NFE_40BIT_ADDR | NFE_HW_CSUM; 306159952Sobrien break; 307159952Sobrien case PCI_PRODUCT_NVIDIA_MCP55_LAN1: 308159952Sobrien case PCI_PRODUCT_NVIDIA_MCP55_LAN2: 309163503Sobrien sc->nfe_flags |= NFE_JUMBO_SUP | NFE_40BIT_ADDR | NFE_HW_CSUM | 310163503Sobrien NFE_HW_VLAN; 311159952Sobrien break; 312162212Sobrien case PCI_PRODUCT_NVIDIA_MCP61_LAN1: 313162212Sobrien case PCI_PRODUCT_NVIDIA_MCP61_LAN2: 314162212Sobrien case PCI_PRODUCT_NVIDIA_MCP61_LAN3: 315162212Sobrien case PCI_PRODUCT_NVIDIA_MCP61_LAN4: 316162212Sobrien sc->nfe_flags |= NFE_40BIT_ADDR; 317162212Sobrien break; 318162212Sobrien case PCI_PRODUCT_NVIDIA_MCP65_LAN1: 319162212Sobrien case PCI_PRODUCT_NVIDIA_MCP65_LAN2: 320162212Sobrien case PCI_PRODUCT_NVIDIA_MCP65_LAN3: 321162212Sobrien case PCI_PRODUCT_NVIDIA_MCP65_LAN4: 322162212Sobrien sc->nfe_flags |= NFE_JUMBO_SUP | NFE_40BIT_ADDR | NFE_HW_CSUM; 323163503Sobrien break; 324159952Sobrien } 325159952Sobrien 326159952Sobrien#ifndef NFE_NO_JUMBO 327159952Sobrien /* enable jumbo frames for adapters that support it */ 328159967Sobrien if (sc->nfe_flags & NFE_JUMBO_SUP) 329159967Sobrien sc->nfe_flags |= NFE_USE_JUMBO; 330159952Sobrien#endif 331159952Sobrien 332159952Sobrien /* 333159967Sobrien * Allocate the parent bus DMA tag appropriate for PCI. 334159967Sobrien */ 335163503Sobrien#define NFE_NSEG_NEW 32 336159967Sobrien error = bus_dma_tag_create(NULL, /* parent */ 337163503Sobrien 1, 0, /* alignment, boundary */ 338163503Sobrien BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 339163503Sobrien BUS_SPACE_MAXADDR, /* highaddr */ 340163503Sobrien NULL, NULL, /* filter, filterarg */ 341163503Sobrien MAXBSIZE, NFE_NSEG_NEW, /* maxsize, nsegments */ 342163503Sobrien BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ 343163503Sobrien BUS_DMA_ALLOCNOW, /* flags */ 344163503Sobrien NULL, NULL, /* lockfunc, lockarg */ 345163503Sobrien &sc->nfe_parent_tag); 346159967Sobrien if (error) 347159967Sobrien goto fail; 348159967Sobrien 349159967Sobrien /* 350159952Sobrien * Allocate Tx and Rx rings. 351159952Sobrien */ 352159952Sobrien if (nfe_alloc_tx_ring(sc, &sc->txq) != 0) { 353159967Sobrien printf("nfe%d: could not allocate Tx ring\n", unit); 354159967Sobrien error = ENXIO; 355159967Sobrien goto fail; 356159952Sobrien } 357159952Sobrien 358159952Sobrien if (nfe_alloc_rx_ring(sc, &sc->rxq) != 0) { 359159967Sobrien printf("nfe%d: could not allocate Rx ring\n", unit); 360159952Sobrien nfe_free_tx_ring(sc, &sc->txq); 361159967Sobrien error = ENXIO; 362159967Sobrien goto fail; 363159952Sobrien } 364159952Sobrien 365159967Sobrien ifp = sc->nfe_ifp = if_alloc(IFT_ETHER); 366159967Sobrien if (ifp == NULL) { 367159967Sobrien printf("nfe%d: can not if_alloc()\n", unit); 368159967Sobrien error = ENOSPC; 369159967Sobrien goto fail; 370159967Sobrien } 371159967Sobrien 372159952Sobrien ifp->if_softc = sc; 373159967Sobrien if_initname(ifp, device_get_name(dev), device_get_unit(dev)); 374159967Sobrien ifp->if_mtu = ETHERMTU; 375159952Sobrien ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 376159952Sobrien ifp->if_ioctl = nfe_ioctl; 377159952Sobrien ifp->if_start = nfe_start; 378159967Sobrien /* ifp->if_hwassist = NFE_CSUM_FEATURES; */ 379159952Sobrien ifp->if_watchdog = nfe_watchdog; 380159952Sobrien ifp->if_init = nfe_init; 381159952Sobrien ifp->if_baudrate = IF_Gbps(1); 382159967Sobrien ifp->if_snd.ifq_maxlen = NFE_IFQ_MAXLEN; 383159952Sobrien 384159952Sobrien ifp->if_capabilities = IFCAP_VLAN_MTU; 385159952Sobrien#if NVLAN > 0 386159967Sobrien if (sc->nfe_flags & NFE_HW_VLAN) 387159952Sobrien ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING; 388159952Sobrien#endif 389159952Sobrien#ifdef NFE_CSUM 390159967Sobrien if (sc->nfe_flags & NFE_HW_CSUM) { 391159967Sobrien ifp->if_capabilities |= IFCAP_HWCSUM; 392159952Sobrien } 393159952Sobrien#endif 394159967Sobrien ifp->if_capenable = ifp->if_capabilities; 395159952Sobrien 396159967Sobrien#ifdef DEVICE_POLLING 397159967Sobrien ifp->if_capabilities |= IFCAP_POLLING; 398159967Sobrien#endif 399159952Sobrien 400159967Sobrien /* Do MII setup */ 401163503Sobrien if (mii_phy_probe(dev, &sc->nfe_miibus, nfe_ifmedia_upd, 402163503Sobrien nfe_ifmedia_sts)) { 403159967Sobrien printf("nfe%d: MII without any phy!\n", unit); 404159967Sobrien error = ENXIO; 405159967Sobrien goto fail; 406159967Sobrien } 407159952Sobrien 408159967Sobrien ether_ifattach(ifp, sc->eaddr); 409159952Sobrien 410163503Sobrien error = bus_setup_intr(dev, sc->nfe_irq, INTR_TYPE_NET | INTR_MPSAFE, 411159967Sobrien nfe_intr, sc, &sc->nfe_intrhand); 412159952Sobrien 413159967Sobrien if (error) { 414159967Sobrien printf("nfe%d: couldn't set up irq\n", unit); 415159967Sobrien ether_ifdetach(ifp); 416159967Sobrien goto fail; 417159967Sobrien } 418159967Sobrien 419159967Sobrienfail: 420159967Sobrien if (error) 421159967Sobrien nfe_detach(dev); 422159967Sobrien 423159967Sobrien return (error); 424159952Sobrien} 425159952Sobrien 426159967Sobrien 427159967Sobrienstatic int 428159967Sobriennfe_detach(device_t dev) 429159952Sobrien{ 430163503Sobrien struct nfe_softc *sc; 431163503Sobrien struct ifnet *ifp; 432163503Sobrien u_char eaddr[ETHER_ADDR_LEN]; 433163503Sobrien int i; 434159952Sobrien 435159967Sobrien sc = device_get_softc(dev); 436159967Sobrien KASSERT(mtx_initialized(&sc->nfe_mtx), ("nfe mutex not initialized")); 437159967Sobrien ifp = sc->nfe_ifp; 438159967Sobrien 439159967Sobrien#ifdef DEVICE_POLLING 440159967Sobrien if (ifp->if_capenable & IFCAP_POLLING) 441159967Sobrien ether_poll_deregister(ifp); 442159967Sobrien#endif 443159967Sobrien 444159967Sobrien for (i = 0; i < ETHER_ADDR_LEN; i++) { 445159967Sobrien eaddr[i] = sc->eaddr[5 - i]; 446159952Sobrien } 447159967Sobrien nfe_set_macaddr(sc, eaddr); 448159967Sobrien 449159967Sobrien if (device_is_attached(dev)) { 450164649Sobrien NFE_LOCK(sc); 451159967Sobrien nfe_stop(ifp, 1); 452159967Sobrien ifp->if_flags &= ~IFF_UP; 453164649Sobrien NFE_UNLOCK(sc); 454159967Sobrien callout_drain(&sc->nfe_stat_ch); 455159967Sobrien ether_ifdetach(ifp); 456159967Sobrien } 457159967Sobrien 458159967Sobrien if (ifp) 459159967Sobrien if_free(ifp); 460159967Sobrien if (sc->nfe_miibus) 461159967Sobrien device_delete_child(dev, sc->nfe_miibus); 462159967Sobrien bus_generic_detach(dev); 463159967Sobrien 464159967Sobrien if (sc->nfe_intrhand) 465159967Sobrien bus_teardown_intr(dev, sc->nfe_irq, sc->nfe_intrhand); 466159967Sobrien if (sc->nfe_irq) 467159967Sobrien bus_release_resource(dev, SYS_RES_IRQ, 0, sc->nfe_irq); 468159967Sobrien if (sc->nfe_res) 469159967Sobrien bus_release_resource(dev, SYS_RES_MEMORY, NV_RID, sc->nfe_res); 470159967Sobrien 471159967Sobrien nfe_free_tx_ring(sc, &sc->txq); 472159967Sobrien nfe_free_rx_ring(sc, &sc->rxq); 473159967Sobrien 474159967Sobrien if (sc->nfe_parent_tag) 475159967Sobrien bus_dma_tag_destroy(sc->nfe_parent_tag); 476159967Sobrien 477159967Sobrien mtx_destroy(&sc->nfe_mtx); 478159967Sobrien 479159967Sobrien return (0); 480159952Sobrien} 481159952Sobrien 482159967Sobrien 483159967Sobrienstatic void 484159967Sobriennfe_miibus_statchg(device_t dev) 485159952Sobrien{ 486159967Sobrien struct nfe_softc *sc; 487159967Sobrien struct mii_data *mii; 488159967Sobrien u_int32_t phy, seed, misc = NFE_MISC1_MAGIC, link = NFE_MEDIA_SET; 489159952Sobrien 490159967Sobrien sc = device_get_softc(dev); 491159967Sobrien mii = device_get_softc(sc->nfe_miibus); 492159967Sobrien 493159952Sobrien phy = NFE_READ(sc, NFE_PHY_IFACE); 494159952Sobrien phy &= ~(NFE_PHY_HDX | NFE_PHY_100TX | NFE_PHY_1000T); 495159952Sobrien 496159952Sobrien seed = NFE_READ(sc, NFE_RNDSEED); 497159952Sobrien seed &= ~NFE_SEED_MASK; 498159952Sobrien 499159952Sobrien if ((mii->mii_media_active & IFM_GMASK) == IFM_HDX) { 500159952Sobrien phy |= NFE_PHY_HDX; /* half-duplex */ 501159952Sobrien misc |= NFE_MISC1_HDX; 502159952Sobrien } 503159952Sobrien 504159952Sobrien switch (IFM_SUBTYPE(mii->mii_media_active)) { 505159952Sobrien case IFM_1000_T: /* full-duplex only */ 506159952Sobrien link |= NFE_MEDIA_1000T; 507159952Sobrien seed |= NFE_SEED_1000T; 508159952Sobrien phy |= NFE_PHY_1000T; 509159952Sobrien break; 510159952Sobrien case IFM_100_TX: 511159952Sobrien link |= NFE_MEDIA_100TX; 512159952Sobrien seed |= NFE_SEED_100TX; 513159952Sobrien phy |= NFE_PHY_100TX; 514159952Sobrien break; 515159952Sobrien case IFM_10_T: 516159952Sobrien link |= NFE_MEDIA_10T; 517159952Sobrien seed |= NFE_SEED_10T; 518159952Sobrien break; 519159952Sobrien } 520159952Sobrien 521159952Sobrien NFE_WRITE(sc, NFE_RNDSEED, seed); /* XXX: gigabit NICs only? */ 522159952Sobrien 523159952Sobrien NFE_WRITE(sc, NFE_PHY_IFACE, phy); 524159952Sobrien NFE_WRITE(sc, NFE_MISC1, misc); 525159952Sobrien NFE_WRITE(sc, NFE_LINKSPEED, link); 526159952Sobrien} 527159952Sobrien 528163503Sobrien 529159967Sobrienstatic int 530159967Sobriennfe_miibus_readreg(device_t dev, int phy, int reg) 531159952Sobrien{ 532159967Sobrien struct nfe_softc *sc = device_get_softc(dev); 533159967Sobrien u_int32_t val; 534159952Sobrien int ntries; 535159952Sobrien 536159952Sobrien NFE_WRITE(sc, NFE_PHY_STATUS, 0xf); 537159952Sobrien 538159952Sobrien if (NFE_READ(sc, NFE_PHY_CTL) & NFE_PHY_BUSY) { 539159952Sobrien NFE_WRITE(sc, NFE_PHY_CTL, NFE_PHY_BUSY); 540159952Sobrien DELAY(100); 541159952Sobrien } 542159952Sobrien 543159952Sobrien NFE_WRITE(sc, NFE_PHY_CTL, (phy << NFE_PHYADD_SHIFT) | reg); 544159952Sobrien 545159952Sobrien for (ntries = 0; ntries < 1000; ntries++) { 546159952Sobrien DELAY(100); 547159952Sobrien if (!(NFE_READ(sc, NFE_PHY_CTL) & NFE_PHY_BUSY)) 548159952Sobrien break; 549159952Sobrien } 550159952Sobrien if (ntries == 1000) { 551159967Sobrien DPRINTFN(2, ("nfe%d: timeout waiting for PHY\n", sc->nfe_unit)); 552159952Sobrien return 0; 553159952Sobrien } 554159952Sobrien 555159952Sobrien if (NFE_READ(sc, NFE_PHY_STATUS) & NFE_PHY_ERROR) { 556159967Sobrien DPRINTFN(2, ("nfe%d: could not read PHY\n", sc->nfe_unit)); 557159952Sobrien return 0; 558159952Sobrien } 559159952Sobrien 560159952Sobrien val = NFE_READ(sc, NFE_PHY_DATA); 561159952Sobrien if (val != 0xffffffff && val != 0) 562159952Sobrien sc->mii_phyaddr = phy; 563159952Sobrien 564163503Sobrien DPRINTFN(2, ("nfe%d: mii read phy %d reg 0x%x ret 0x%x\n", 565163503Sobrien sc->nfe_unit, phy, reg, val)); 566159952Sobrien 567159952Sobrien return val; 568159952Sobrien} 569159952Sobrien 570163503Sobrien 571159967Sobrienstatic int 572159967Sobriennfe_miibus_writereg(device_t dev, int phy, int reg, int val) 573159952Sobrien{ 574159967Sobrien struct nfe_softc *sc = device_get_softc(dev); 575159967Sobrien u_int32_t ctl; 576163503Sobrien int ntries; 577159952Sobrien 578159952Sobrien NFE_WRITE(sc, NFE_PHY_STATUS, 0xf); 579159952Sobrien 580159952Sobrien if (NFE_READ(sc, NFE_PHY_CTL) & NFE_PHY_BUSY) { 581159952Sobrien NFE_WRITE(sc, NFE_PHY_CTL, NFE_PHY_BUSY); 582159952Sobrien DELAY(100); 583159952Sobrien } 584159952Sobrien 585159952Sobrien NFE_WRITE(sc, NFE_PHY_DATA, val); 586159952Sobrien ctl = NFE_PHY_WRITE | (phy << NFE_PHYADD_SHIFT) | reg; 587159952Sobrien NFE_WRITE(sc, NFE_PHY_CTL, ctl); 588159952Sobrien 589159952Sobrien for (ntries = 0; ntries < 1000; ntries++) { 590159952Sobrien DELAY(100); 591159952Sobrien if (!(NFE_READ(sc, NFE_PHY_CTL) & NFE_PHY_BUSY)) 592159952Sobrien break; 593159952Sobrien } 594159952Sobrien#ifdef NFE_DEBUG 595159952Sobrien if (nfedebug >= 2 && ntries == 1000) 596159952Sobrien printf("could not write to PHY\n"); 597159952Sobrien#endif 598159967Sobrien return 0; 599159952Sobrien} 600159952Sobrien 601163503Sobrien 602159967Sobrienstatic int 603159967Sobriennfe_alloc_rx_ring(struct nfe_softc *sc, struct nfe_rx_ring *ring) 604159952Sobrien{ 605159967Sobrien struct nfe_desc32 *desc32; 606159967Sobrien struct nfe_desc64 *desc64; 607159967Sobrien struct nfe_rx_data *data; 608159967Sobrien struct nfe_jbuf *jbuf; 609159967Sobrien void **desc; 610159967Sobrien bus_addr_t physaddr; 611159967Sobrien int i, error, descsize; 612159967Sobrien 613159967Sobrien if (sc->nfe_flags & NFE_40BIT_ADDR) { 614159967Sobrien desc = (void **)&ring->desc64; 615159967Sobrien descsize = sizeof (struct nfe_desc64); 616159967Sobrien } else { 617159967Sobrien desc = (void **)&ring->desc32; 618159967Sobrien descsize = sizeof (struct nfe_desc32); 619159967Sobrien } 620159967Sobrien 621159967Sobrien ring->cur = ring->next = 0; 622159967Sobrien ring->bufsz = MCLBYTES; 623159967Sobrien 624163503Sobrien error = bus_dma_tag_create(sc->nfe_parent_tag, 625163503Sobrien PAGE_SIZE, 0, /* alignment, boundary */ 626163503Sobrien BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 627163503Sobrien BUS_SPACE_MAXADDR, /* highaddr */ 628163503Sobrien NULL, NULL, /* filter, filterarg */ 629163503Sobrien NFE_RX_RING_COUNT * descsize, 1, /* maxsize, nsegments */ 630163503Sobrien NFE_RX_RING_COUNT * descsize, /* maxsegsize */ 631163503Sobrien BUS_DMA_ALLOCNOW, /* flags */ 632163503Sobrien NULL, NULL, /* lockfunc, lockarg */ 633163503Sobrien &ring->rx_desc_tag); 634159967Sobrien if (error != 0) { 635159967Sobrien printf("nfe%d: could not create desc DMA tag\n", sc->nfe_unit); 636159967Sobrien goto fail; 637159967Sobrien } 638159967Sobrien 639159967Sobrien /* allocate memory to desc */ 640163503Sobrien error = bus_dmamem_alloc(ring->rx_desc_tag, (void **)desc, 641163503Sobrien BUS_DMA_NOWAIT, &ring->rx_desc_map); 642159967Sobrien if (error != 0) { 643159967Sobrien printf("nfe%d: could not create desc DMA map\n", sc->nfe_unit); 644159967Sobrien goto fail; 645159967Sobrien } 646159967Sobrien 647159967Sobrien /* map desc to device visible address space */ 648159967Sobrien error = bus_dmamap_load(ring->rx_desc_tag, ring->rx_desc_map, *desc, 649163503Sobrien NFE_RX_RING_COUNT * descsize, nfe_dma_map_segs, 650163503Sobrien &ring->rx_desc_segs, BUS_DMA_NOWAIT); 651159967Sobrien if (error != 0) { 652159967Sobrien printf("nfe%d: could not load desc DMA map\n", sc->nfe_unit); 653159967Sobrien goto fail; 654159967Sobrien } 655159967Sobrien 656159967Sobrien bzero(*desc, NFE_RX_RING_COUNT * descsize); 657159967Sobrien ring->rx_desc_addr = ring->rx_desc_segs.ds_addr; 658159967Sobrien ring->physaddr = ring->rx_desc_addr; 659159967Sobrien 660159967Sobrien if (sc->nfe_flags & NFE_USE_JUMBO) { 661159967Sobrien ring->bufsz = NFE_JBYTES; 662159967Sobrien if ((error = nfe_jpool_alloc(sc)) != 0) { 663163503Sobrien printf("nfe%d: could not allocate jumbo frames\n", 664163503Sobrien sc->nfe_unit); 665159967Sobrien goto fail; 666159967Sobrien } 667159967Sobrien } 668159967Sobrien 669159967Sobrien /* 670159967Sobrien * Pre-allocate Rx buffers and populate Rx ring. 671159967Sobrien */ 672159967Sobrien for (i = 0; i < NFE_RX_RING_COUNT; i++) { 673159967Sobrien data = &sc->rxq.data[i]; 674159967Sobrien 675159967Sobrien MGETHDR(data->m, M_DONTWAIT, MT_DATA); 676159967Sobrien if (data->m == NULL) { 677163503Sobrien printf("nfe%d: could not allocate rx mbuf\n", 678163503Sobrien sc->nfe_unit); 679159967Sobrien error = ENOMEM; 680159967Sobrien goto fail; 681159967Sobrien } 682159967Sobrien 683159967Sobrien if (sc->nfe_flags & NFE_USE_JUMBO) { 684159967Sobrien if ((jbuf = nfe_jalloc(sc)) == NULL) { 685163503Sobrien printf("nfe%d: could not allocate jumbo buffer\n", 686163503Sobrien sc->nfe_unit); 687159967Sobrien goto fail; 688159967Sobrien } 689159967Sobrien data->m->m_data = (void *)jbuf->buf; 690159967Sobrien data->m->m_len = data->m->m_pkthdr.len = NFE_JBYTES; 691163503Sobrien MEXTADD(data->m, jbuf->buf, NFE_JBYTES, nfe_jfree, 692163503Sobrien (struct nfe_softc *)sc, 0, EXT_NET_DRV); 693159967Sobrien /* m_adj(data->m, ETHER_ALIGN); */ 694159967Sobrien physaddr = jbuf->physaddr; 695159967Sobrien } else { 696163503Sobrien error = bus_dma_tag_create(sc->nfe_parent_tag, 697163503Sobrien ETHER_ALIGN, 0, /* alignment, boundary */ 698163503Sobrien BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 699163503Sobrien BUS_SPACE_MAXADDR, /* highaddr */ 700163503Sobrien NULL, NULL, /* filter, filterarg */ 701163503Sobrien MCLBYTES, 1, /* maxsize, nsegments */ 702163503Sobrien MCLBYTES, /* maxsegsize */ 703163503Sobrien BUS_DMA_ALLOCNOW, /* flags */ 704163503Sobrien NULL, NULL, /* lockfunc, lockarg */ 705163503Sobrien &data->rx_data_tag); 706163503Sobrien if (error != 0) { 707163503Sobrien printf("nfe%d: could not create DMA map\n", 708163503Sobrien sc->nfe_unit); 709163503Sobrien goto fail; 710163503Sobrien } 711159967Sobrien 712163503Sobrien error = bus_dmamap_create(data->rx_data_tag, 0, 713163503Sobrien &data->rx_data_map); 714163503Sobrien if (error != 0) { 715163503Sobrien printf("nfe%d: could not allocate mbuf cluster\n", 716163503Sobrien sc->nfe_unit); 717163503Sobrien goto fail; 718163503Sobrien } 719159967Sobrien 720163503Sobrien MCLGET(data->m, M_DONTWAIT); 721163503Sobrien if (!(data->m->m_flags & M_EXT)) { 722163503Sobrien error = ENOMEM; 723163503Sobrien goto fail; 724163503Sobrien } 725159967Sobrien 726163503Sobrien error = bus_dmamap_load(data->rx_data_tag, 727163503Sobrien data->rx_data_map, mtod(data->m, void *), MCLBYTES, 728163503Sobrien nfe_dma_map_segs, &data->rx_data_segs, 729163503Sobrien BUS_DMA_NOWAIT); 730163503Sobrien if (error != 0) { 731163503Sobrien printf("nfe%d: could not load rx buf DMA map\n", 732163503Sobrien sc->nfe_unit); 733163503Sobrien goto fail; 734163503Sobrien } 735159967Sobrien 736163503Sobrien data->rx_data_addr = data->rx_data_segs.ds_addr; 737163503Sobrien physaddr = data->rx_data_addr; 738159967Sobrien 739159967Sobrien } 740159967Sobrien 741159967Sobrien if (sc->nfe_flags & NFE_40BIT_ADDR) { 742159967Sobrien desc64 = &sc->rxq.desc64[i]; 743159967Sobrien#if defined(__LP64__) 744159967Sobrien desc64->physaddr[0] = htole32(physaddr >> 32); 745159967Sobrien#endif 746159967Sobrien desc64->physaddr[1] = htole32(physaddr & 0xffffffff); 747159967Sobrien desc64->length = htole16(sc->rxq.bufsz); 748159967Sobrien desc64->flags = htole16(NFE_RX_READY); 749159967Sobrien } else { 750159967Sobrien desc32 = &sc->rxq.desc32[i]; 751159967Sobrien desc32->physaddr = htole32(physaddr); 752159967Sobrien desc32->length = htole16(sc->rxq.bufsz); 753159967Sobrien desc32->flags = htole16(NFE_RX_READY); 754159967Sobrien } 755159967Sobrien 756159967Sobrien } 757159967Sobrien 758163503Sobrien bus_dmamap_sync(ring->rx_desc_tag, ring->rx_desc_map, 759163503Sobrien BUS_DMASYNC_PREWRITE); 760159967Sobrien 761159967Sobrien return 0; 762159967Sobrien 763159967Sobrienfail: nfe_free_rx_ring(sc, ring); 764159967Sobrien 765159967Sobrien return error; 766159967Sobrien} 767159967Sobrien 768163503Sobrien 769159967Sobrienstatic int 770159967Sobriennfe_jpool_alloc(struct nfe_softc *sc) 771159967Sobrien{ 772159967Sobrien struct nfe_rx_ring *ring = &sc->rxq; 773159967Sobrien struct nfe_jbuf *jbuf; 774159967Sobrien bus_addr_t physaddr; 775159967Sobrien caddr_t buf; 776159967Sobrien int i, error; 777159967Sobrien 778159967Sobrien /* 779159967Sobrien * Allocate a big chunk of DMA'able memory. 780159967Sobrien */ 781163503Sobrien error = bus_dma_tag_create(sc->nfe_parent_tag, 782163503Sobrien PAGE_SIZE, 0, /* alignment, boundary */ 783163503Sobrien BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 784163503Sobrien BUS_SPACE_MAXADDR, /* highaddr */ 785163503Sobrien NULL, NULL, /* filter, filterarg */ 786163503Sobrien NFE_JPOOL_SIZE, 1, /* maxsize, nsegments */ 787163503Sobrien NFE_JPOOL_SIZE, /* maxsegsize */ 788163503Sobrien BUS_DMA_ALLOCNOW, /* flags */ 789163503Sobrien NULL, NULL, /* lockfunc, lockarg */ 790163503Sobrien &ring->rx_jumbo_tag); 791159967Sobrien if (error != 0) { 792159967Sobrien printf("nfe%d: could not create jumbo DMA tag\n", sc->nfe_unit); 793159967Sobrien goto fail; 794159967Sobrien } 795163503Sobrien 796163503Sobrien error = bus_dmamem_alloc(ring->rx_jumbo_tag, (void **)&ring->jpool, 797163503Sobrien BUS_DMA_NOWAIT, &ring->rx_jumbo_map); 798159967Sobrien if (error != 0) { 799163503Sobrien printf("nfe%d: could not create jumbo DMA memory\n", 800163503Sobrien sc->nfe_unit); 801159967Sobrien goto fail; 802159967Sobrien } 803159967Sobrien 804163503Sobrien error = bus_dmamap_load(ring->rx_jumbo_tag, ring->rx_jumbo_map, 805163503Sobrien ring->jpool, NFE_JPOOL_SIZE, nfe_dma_map_segs, &ring->rx_jumbo_segs, 806163503Sobrien BUS_DMA_NOWAIT); 807159967Sobrien if (error != 0) { 808159967Sobrien printf("nfe%d: could not load jumbo DMA map\n", sc->nfe_unit); 809159967Sobrien goto fail; 810159967Sobrien } 811159967Sobrien 812159967Sobrien /* ..and split it into 9KB chunks */ 813159967Sobrien SLIST_INIT(&ring->jfreelist); 814159967Sobrien 815159967Sobrien buf = ring->jpool; 816159967Sobrien ring->rx_jumbo_addr = ring->rx_jumbo_segs.ds_addr; 817159967Sobrien physaddr = ring->rx_jumbo_addr; 818159967Sobrien 819159967Sobrien for (i = 0; i < NFE_JPOOL_COUNT; i++) { 820159967Sobrien jbuf = &ring->jbuf[i]; 821159967Sobrien 822159967Sobrien jbuf->buf = buf; 823159967Sobrien jbuf->physaddr = physaddr; 824159967Sobrien 825159967Sobrien SLIST_INSERT_HEAD(&ring->jfreelist, jbuf, jnext); 826159967Sobrien 827159967Sobrien buf += NFE_JBYTES; 828159967Sobrien physaddr += NFE_JBYTES; 829159967Sobrien } 830159967Sobrien 831159967Sobrien return 0; 832159967Sobrien 833159967Sobrienfail: nfe_jpool_free(sc); 834159967Sobrien return error; 835159967Sobrien} 836159967Sobrien 837159967Sobrien 838159967Sobrienstatic void 839159967Sobriennfe_jpool_free(struct nfe_softc *sc) 840159967Sobrien{ 841159967Sobrien struct nfe_rx_ring *ring = &sc->rxq; 842159967Sobrien 843159967Sobrien if (ring->jpool != NULL) { 844159967Sobrien#if 0 845163503Sobrien bus_dmamem_unmap(ring->rx_jumbo_tag, ring->jpool, 846163503Sobrien NFE_JPOOL_SIZE); 847159967Sobrien#endif 848163503Sobrien bus_dmamem_free(ring->rx_jumbo_tag, &ring->rx_jumbo_segs, 849163503Sobrien ring->rx_jumbo_map); 850159967Sobrien } 851159967Sobrien if (ring->rx_jumbo_map != NULL) { 852163503Sobrien bus_dmamap_sync(ring->rx_jumbo_tag, ring->rx_jumbo_map, 853163503Sobrien BUS_DMASYNC_POSTWRITE); 854159967Sobrien bus_dmamap_unload(ring->rx_jumbo_tag, ring->rx_jumbo_map); 855159967Sobrien bus_dmamap_destroy(ring->rx_jumbo_tag, ring->rx_jumbo_map); 856159967Sobrien } 857159967Sobrien} 858159967Sobrien 859163503Sobrien 860159967Sobrienstatic struct nfe_jbuf * 861159967Sobriennfe_jalloc(struct nfe_softc *sc) 862159967Sobrien{ 863159967Sobrien struct nfe_jbuf *jbuf; 864159967Sobrien 865159967Sobrien jbuf = SLIST_FIRST(&sc->rxq.jfreelist); 866159967Sobrien if (jbuf == NULL) 867159967Sobrien return NULL; 868159967Sobrien SLIST_REMOVE_HEAD(&sc->rxq.jfreelist, jnext); 869159967Sobrien return jbuf; 870159967Sobrien} 871159967Sobrien 872163503Sobrien 873159967Sobrien/* 874159967Sobrien * This is called automatically by the network stack when the mbuf is freed. 875159967Sobrien * Caution must be taken that the NIC might be reset by the time the mbuf is 876159967Sobrien * freed. 877159967Sobrien */ 878159967Sobrienstatic void 879159967Sobriennfe_jfree(void *buf, void *arg) 880159967Sobrien{ 881159952Sobrien struct nfe_softc *sc = arg; 882159967Sobrien struct nfe_jbuf *jbuf; 883159967Sobrien int i; 884159952Sobrien 885159967Sobrien /* find the jbuf from the base pointer */ 886159967Sobrien i = ((vm_offset_t)buf - (vm_offset_t)sc->rxq.jpool) / NFE_JBYTES; 887159967Sobrien if (i < 0 || i >= NFE_JPOOL_COUNT) { 888163503Sobrien printf("nfe%d: request to free a buffer (%p) not managed by us\n", 889163503Sobrien sc->nfe_unit, buf); 890159967Sobrien return; 891159967Sobrien } 892159967Sobrien jbuf = &sc->rxq.jbuf[i]; 893159952Sobrien 894159967Sobrien /* ..and put it back in the free list */ 895159967Sobrien SLIST_INSERT_HEAD(&sc->rxq.jfreelist, jbuf, jnext); 896159967Sobrien} 897159952Sobrien 898159967Sobrien 899159967Sobrienstatic void 900159967Sobriennfe_reset_rx_ring(struct nfe_softc *sc, struct nfe_rx_ring *ring) 901159967Sobrien{ 902159967Sobrien int i; 903159967Sobrien 904159967Sobrien for (i = 0; i < NFE_RX_RING_COUNT; i++) { 905159967Sobrien if (sc->nfe_flags & NFE_40BIT_ADDR) { 906159967Sobrien ring->desc64[i].length = htole16(ring->bufsz); 907159967Sobrien ring->desc64[i].flags = htole16(NFE_RX_READY); 908159967Sobrien } else { 909159967Sobrien ring->desc32[i].length = htole16(ring->bufsz); 910159967Sobrien ring->desc32[i].flags = htole16(NFE_RX_READY); 911159967Sobrien } 912159952Sobrien } 913159952Sobrien 914163503Sobrien bus_dmamap_sync(ring->rx_desc_tag, ring->rx_desc_map, 915163503Sobrien BUS_DMASYNC_PREWRITE); 916159952Sobrien 917159967Sobrien ring->cur = ring->next = 0; 918159967Sobrien} 919159967Sobrien 920159967Sobrien 921159967Sobrienstatic void 922159967Sobriennfe_free_rx_ring(struct nfe_softc *sc, struct nfe_rx_ring *ring) 923159967Sobrien{ 924159967Sobrien struct nfe_rx_data *data; 925159967Sobrien void *desc; 926159967Sobrien int i, descsize; 927159967Sobrien 928159967Sobrien if (sc->nfe_flags & NFE_40BIT_ADDR) { 929159967Sobrien desc = ring->desc64; 930159967Sobrien descsize = sizeof (struct nfe_desc64); 931159967Sobrien } else { 932159967Sobrien desc = ring->desc32; 933159967Sobrien descsize = sizeof (struct nfe_desc32); 934159952Sobrien } 935159952Sobrien 936159967Sobrien if (desc != NULL) { 937163503Sobrien bus_dmamap_sync(ring->rx_desc_tag, ring->rx_desc_map, 938163503Sobrien BUS_DMASYNC_POSTWRITE); 939159967Sobrien bus_dmamap_unload(ring->rx_desc_tag, ring->rx_desc_map); 940159967Sobrien bus_dmamem_free(ring->rx_desc_tag, desc, ring->rx_desc_map); 941159967Sobrien bus_dma_tag_destroy(ring->rx_desc_tag); 942159967Sobrien } 943159967Sobrien 944159967Sobrien if (sc->nfe_flags & NFE_USE_JUMBO) { 945163503Sobrien nfe_jpool_free(sc); 946159967Sobrien } else { 947163503Sobrien for (i = 0; i < NFE_RX_RING_COUNT; i++) { 948163503Sobrien data = &ring->data[i]; 949159967Sobrien 950163503Sobrien if (data->rx_data_map != NULL) { 951163503Sobrien bus_dmamap_sync(data->rx_data_tag, 952163503Sobrien data->rx_data_map, BUS_DMASYNC_POSTREAD); 953163503Sobrien bus_dmamap_unload(data->rx_data_tag, 954163503Sobrien data->rx_data_map); 955163503Sobrien bus_dmamap_destroy(data->rx_data_tag, 956163503Sobrien data->rx_data_map); 957163503Sobrien bus_dma_tag_destroy(data->rx_data_tag); 958163503Sobrien } 959163503Sobrien 960163503Sobrien if (data->m != NULL) 961163503Sobrien m_freem(data->m); 962163503Sobrien } 963159967Sobrien } 964159952Sobrien} 965159952Sobrien 966163503Sobrien 967159967Sobrienstatic int 968159967Sobriennfe_alloc_tx_ring(struct nfe_softc *sc, struct nfe_tx_ring *ring) 969159952Sobrien{ 970159967Sobrien int i, error; 971159967Sobrien void **desc; 972159967Sobrien int descsize; 973159952Sobrien 974159967Sobrien if (sc->nfe_flags & NFE_40BIT_ADDR) { 975159967Sobrien desc = (void **)&ring->desc64; 976159967Sobrien descsize = sizeof (struct nfe_desc64); 977159967Sobrien } else { 978159967Sobrien desc = (void **)&ring->desc32; 979159967Sobrien descsize = sizeof (struct nfe_desc32); 980159967Sobrien } 981159952Sobrien 982159967Sobrien ring->queued = 0; 983159967Sobrien ring->cur = ring->next = 0; 984159967Sobrien 985163503Sobrien error = bus_dma_tag_create(sc->nfe_parent_tag, 986163503Sobrien PAGE_SIZE, 0, /* alignment, boundary */ 987163503Sobrien BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ 988163503Sobrien BUS_SPACE_MAXADDR, /* highaddr */ 989163503Sobrien NULL, NULL, /* filter, filterarg */ 990163503Sobrien NFE_TX_RING_COUNT * descsize, 1, /* maxsize, nsegments */ 991163503Sobrien NFE_TX_RING_COUNT * descsize, /* maxsegsize */ 992163503Sobrien BUS_DMA_ALLOCNOW, /* flags */ 993163503Sobrien NULL, NULL, /* lockfunc, lockarg */ 994163503Sobrien &ring->tx_desc_tag); 995159967Sobrien if (error != 0) { 996159967Sobrien printf("nfe%d: could not create desc DMA tag\n", sc->nfe_unit); 997159967Sobrien goto fail; 998159952Sobrien } 999159952Sobrien 1000163503Sobrien error = bus_dmamem_alloc(ring->tx_desc_tag, (void **)desc, 1001163503Sobrien BUS_DMA_NOWAIT, &ring->tx_desc_map); 1002159967Sobrien if (error != 0) { 1003159967Sobrien printf("nfe%d: could not create desc DMA map\n", sc->nfe_unit); 1004159967Sobrien goto fail; 1005159967Sobrien } 1006159967Sobrien 1007159967Sobrien error = bus_dmamap_load(ring->tx_desc_tag, ring->tx_desc_map, *desc, 1008163503Sobrien NFE_TX_RING_COUNT * descsize, nfe_dma_map_segs, &ring->tx_desc_segs, 1009163503Sobrien BUS_DMA_NOWAIT); 1010159967Sobrien if (error != 0) { 1011159967Sobrien printf("nfe%d: could not load desc DMA map\n", sc->nfe_unit); 1012159967Sobrien goto fail; 1013159967Sobrien } 1014159967Sobrien 1015159967Sobrien bzero(*desc, NFE_TX_RING_COUNT * descsize); 1016159967Sobrien 1017159967Sobrien ring->tx_desc_addr = ring->tx_desc_segs.ds_addr; 1018159967Sobrien ring->physaddr = ring->tx_desc_addr; 1019159967Sobrien 1020163503Sobrien error = bus_dma_tag_create(sc->nfe_parent_tag, 1021163503Sobrien ETHER_ALIGN, 0, 1022163503Sobrien BUS_SPACE_MAXADDR_32BIT, 1023163503Sobrien BUS_SPACE_MAXADDR, 1024163503Sobrien NULL, NULL, 1025163503Sobrien NFE_JBYTES, NFE_MAX_SCATTER, 1026163503Sobrien NFE_JBYTES, 1027163503Sobrien BUS_DMA_ALLOCNOW, 1028163503Sobrien NULL, NULL, 1029163503Sobrien &ring->tx_data_tag); 1030159967Sobrien if (error != 0) { 1031159967Sobrien printf("nfe%d: could not create DMA tag\n", sc->nfe_unit); 1032159967Sobrien goto fail; 1033159967Sobrien } 1034159967Sobrien 1035159967Sobrien for (i = 0; i < NFE_TX_RING_COUNT; i++) { 1036163503Sobrien error = bus_dmamap_create(ring->tx_data_tag, 0, 1037163503Sobrien &ring->data[i].tx_data_map); 1038159967Sobrien if (error != 0) { 1039163503Sobrien printf("nfe%d: could not create DMA map\n", 1040163503Sobrien sc->nfe_unit); 1041159967Sobrien goto fail; 1042159967Sobrien } 1043159967Sobrien } 1044159967Sobrien 1045159967Sobrien return 0; 1046159967Sobrien 1047159967Sobrienfail: nfe_free_tx_ring(sc, ring); 1048159967Sobrien return error; 1049159967Sobrien} 1050159967Sobrien 1051159967Sobrien 1052159967Sobrienstatic void 1053159967Sobriennfe_reset_tx_ring(struct nfe_softc *sc, struct nfe_tx_ring *ring) 1054159967Sobrien{ 1055159967Sobrien struct nfe_tx_data *data; 1056159967Sobrien int i; 1057159967Sobrien 1058159967Sobrien for (i = 0; i < NFE_TX_RING_COUNT; i++) { 1059159967Sobrien if (sc->nfe_flags & NFE_40BIT_ADDR) 1060159967Sobrien ring->desc64[i].flags = 0; 1061159967Sobrien else 1062159967Sobrien ring->desc32[i].flags = 0; 1063159967Sobrien 1064159967Sobrien data = &ring->data[i]; 1065159967Sobrien 1066159967Sobrien if (data->m != NULL) { 1067163503Sobrien bus_dmamap_sync(ring->tx_data_tag, data->active, 1068163503Sobrien BUS_DMASYNC_POSTWRITE); 1069159967Sobrien bus_dmamap_unload(ring->tx_data_tag, data->active); 1070159967Sobrien m_freem(data->m); 1071159967Sobrien data->m = NULL; 1072159967Sobrien } 1073159967Sobrien } 1074159967Sobrien 1075163503Sobrien bus_dmamap_sync(ring->tx_desc_tag, ring->tx_desc_map, 1076163503Sobrien BUS_DMASYNC_PREWRITE); 1077159967Sobrien 1078159967Sobrien ring->queued = 0; 1079159967Sobrien ring->cur = ring->next = 0; 1080159967Sobrien} 1081159967Sobrien 1082163503Sobrien 1083159967Sobrienstatic void 1084159967Sobriennfe_free_tx_ring(struct nfe_softc *sc, struct nfe_tx_ring *ring) 1085159967Sobrien{ 1086159967Sobrien struct nfe_tx_data *data; 1087159967Sobrien void *desc; 1088159967Sobrien int i, descsize; 1089159967Sobrien 1090159967Sobrien if (sc->nfe_flags & NFE_40BIT_ADDR) { 1091159967Sobrien desc = ring->desc64; 1092159967Sobrien descsize = sizeof (struct nfe_desc64); 1093159967Sobrien } else { 1094159967Sobrien desc = ring->desc32; 1095159967Sobrien descsize = sizeof (struct nfe_desc32); 1096159967Sobrien } 1097159967Sobrien 1098159967Sobrien if (desc != NULL) { 1099163503Sobrien bus_dmamap_sync(ring->tx_desc_tag, ring->tx_desc_map, 1100163503Sobrien BUS_DMASYNC_POSTWRITE); 1101159967Sobrien bus_dmamap_unload(ring->tx_desc_tag, ring->tx_desc_map); 1102159967Sobrien bus_dmamem_free(ring->tx_desc_tag, desc, ring->tx_desc_map); 1103159967Sobrien bus_dma_tag_destroy(ring->tx_desc_tag); 1104159967Sobrien } 1105159967Sobrien 1106159967Sobrien for (i = 0; i < NFE_TX_RING_COUNT; i++) { 1107159967Sobrien data = &ring->data[i]; 1108159967Sobrien 1109159967Sobrien if (data->m != NULL) { 1110163503Sobrien bus_dmamap_sync(ring->tx_data_tag, data->active, 1111163503Sobrien BUS_DMASYNC_POSTWRITE); 1112159967Sobrien bus_dmamap_unload(ring->tx_data_tag, data->active); 1113159967Sobrien m_freem(data->m); 1114159967Sobrien } 1115159967Sobrien } 1116159967Sobrien 1117159967Sobrien /* ..and now actually destroy the DMA mappings */ 1118159967Sobrien for (i = 0; i < NFE_TX_RING_COUNT; i++) { 1119159967Sobrien data = &ring->data[i]; 1120159967Sobrien if (data->tx_data_map == NULL) 1121159967Sobrien continue; 1122159967Sobrien bus_dmamap_destroy(ring->tx_data_tag, data->tx_data_map); 1123159967Sobrien } 1124159967Sobrien 1125159967Sobrien bus_dma_tag_destroy(ring->tx_data_tag); 1126159967Sobrien} 1127159967Sobrien 1128159967Sobrien#ifdef DEVICE_POLLING 1129159967Sobrienstatic poll_handler_t nfe_poll; 1130159967Sobrien 1131163503Sobrien 1132159967Sobrienstatic void 1133159967Sobriennfe_poll(struct ifnet *ifp, enum poll_cmd cmd, int count) 1134159967Sobrien{ 1135164360Sobrien struct nfe_softc *sc = ifp->if_softc; 1136159967Sobrien 1137159967Sobrien NFE_LOCK(sc); 1138159967Sobrien if (ifp->if_drv_flags & IFF_DRV_RUNNING) 1139159967Sobrien nfe_poll_locked(ifp, cmd, count); 1140159967Sobrien NFE_UNLOCK(sc); 1141159967Sobrien} 1142159967Sobrien 1143159967Sobrien 1144159967Sobrienstatic void 1145159967Sobriennfe_poll_locked(struct ifnet *ifp, enum poll_cmd cmd, int count) 1146159967Sobrien{ 1147164360Sobrien struct nfe_softc *sc = ifp->if_softc; 1148159967Sobrien u_int32_t r; 1149159967Sobrien 1150159967Sobrien NFE_LOCK_ASSERT(sc); 1151159967Sobrien 1152159967Sobrien if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) { 1153159967Sobrien return; 1154159967Sobrien } 1155159967Sobrien 1156159967Sobrien sc->rxcycles = count; 1157159967Sobrien nfe_rxeof(sc); 1158159967Sobrien nfe_txeof(sc); 1159159967Sobrien if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) 1160159967Sobrien nfe_start_locked(ifp); 1161159967Sobrien 1162159967Sobrien if (cmd == POLL_AND_CHECK_STATUS) { 1163163503Sobrien if ((r = NFE_READ(sc, NFE_IRQ_STATUS)) == 0) { 1164163503Sobrien return; 1165163503Sobrien } 1166163503Sobrien NFE_WRITE(sc, NFE_IRQ_STATUS, r); 1167159967Sobrien 1168163503Sobrien if (r & NFE_IRQ_LINK) { 1169163503Sobrien NFE_READ(sc, NFE_PHY_STATUS); 1170163503Sobrien NFE_WRITE(sc, NFE_PHY_STATUS, 0xf); 1171163503Sobrien DPRINTF(("nfe%d: link state changed\n", sc->nfe_unit)); 1172163503Sobrien } 1173159967Sobrien } 1174159967Sobrien} 1175159967Sobrien#endif /* DEVICE_POLLING */ 1176159967Sobrien 1177159967Sobrien 1178159967Sobrienstatic int 1179159967Sobriennfe_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 1180159967Sobrien{ 1181163503Sobrien struct nfe_softc *sc = ifp->if_softc; 1182163503Sobrien struct ifreq *ifr = (struct ifreq *) data; 1183163503Sobrien struct mii_data *mii; 1184163503Sobrien int error = 0; 1185159967Sobrien 1186159952Sobrien switch (cmd) { 1187159952Sobrien case SIOCSIFMTU: 1188159952Sobrien if (ifr->ifr_mtu < ETHERMIN || 1189159967Sobrien ((sc->nfe_flags & NFE_USE_JUMBO) && 1190159952Sobrien ifr->ifr_mtu > ETHERMTU_JUMBO) || 1191159967Sobrien (!(sc->nfe_flags & NFE_USE_JUMBO) && 1192163503Sobrien ifr->ifr_mtu > ETHERMTU)) { 1193159952Sobrien error = EINVAL; 1194163503Sobrien } else if (ifp->if_mtu != ifr->ifr_mtu) { 1195159952Sobrien ifp->if_mtu = ifr->ifr_mtu; 1196159967Sobrien ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 1197159967Sobrien nfe_init(sc); 1198159967Sobrien } 1199159952Sobrien break; 1200159952Sobrien case SIOCSIFFLAGS: 1201159967Sobrien NFE_LOCK(sc); 1202159952Sobrien if (ifp->if_flags & IFF_UP) { 1203159952Sobrien /* 1204159952Sobrien * If only the PROMISC or ALLMULTI flag changes, then 1205159952Sobrien * don't do a full re-init of the chip, just update 1206159952Sobrien * the Rx filter. 1207159952Sobrien */ 1208159967Sobrien if ((ifp->if_drv_flags & IFF_DRV_RUNNING) && 1209159967Sobrien ((ifp->if_flags ^ sc->nfe_if_flags) & 1210159967Sobrien (IFF_ALLMULTI | IFF_PROMISC)) != 0) 1211159952Sobrien nfe_setmulti(sc); 1212159967Sobrien else 1213159967Sobrien nfe_init_locked(sc); 1214159952Sobrien } else { 1215159967Sobrien if (ifp->if_drv_flags & IFF_DRV_RUNNING) 1216159952Sobrien nfe_stop(ifp, 1); 1217159952Sobrien } 1218159967Sobrien sc->nfe_if_flags = ifp->if_flags; 1219159967Sobrien NFE_UNLOCK(sc); 1220159967Sobrien error = 0; 1221159952Sobrien break; 1222159952Sobrien case SIOCADDMULTI: 1223159952Sobrien case SIOCDELMULTI: 1224159967Sobrien if (ifp->if_drv_flags & IFF_DRV_RUNNING) { 1225159967Sobrien NFE_LOCK(sc); 1226159967Sobrien nfe_setmulti(sc); 1227159967Sobrien NFE_UNLOCK(sc); 1228159952Sobrien error = 0; 1229159952Sobrien } 1230159952Sobrien break; 1231159952Sobrien case SIOCSIFMEDIA: 1232159952Sobrien case SIOCGIFMEDIA: 1233159967Sobrien mii = device_get_softc(sc->nfe_miibus); 1234159967Sobrien error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, cmd); 1235159952Sobrien break; 1236159967Sobrien case SIOCSIFCAP: 1237163503Sobrien { 1238159967Sobrien int mask = ifr->ifr_reqcap ^ ifp->if_capenable; 1239159967Sobrien#ifdef DEVICE_POLLING 1240159967Sobrien if (mask & IFCAP_POLLING) { 1241159967Sobrien if (ifr->ifr_reqcap & IFCAP_POLLING) { 1242159967Sobrien error = ether_poll_register(nfe_poll, ifp); 1243159967Sobrien if (error) 1244159967Sobrien return(error); 1245159967Sobrien NFE_LOCK(sc); 1246159967Sobrien NFE_WRITE(sc, NFE_IRQ_MASK, 0); 1247163503Sobrien ifp->if_capenable |= IFCAP_POLLING; 1248159967Sobrien NFE_UNLOCK(sc); 1249159967Sobrien } else { 1250159967Sobrien error = ether_poll_deregister(ifp); 1251159967Sobrien /* Enable interrupt even in error case */ 1252159967Sobrien NFE_LOCK(sc); 1253159967Sobrien NFE_WRITE(sc, NFE_IRQ_MASK, NFE_IRQ_WANTED); 1254159967Sobrien ifp->if_capenable &= ~IFCAP_POLLING; 1255159967Sobrien NFE_UNLOCK(sc); 1256159967Sobrien } 1257159967Sobrien } 1258163503Sobrien#endif /* DEVICE_POLLING */ 1259159967Sobrien if (mask & IFCAP_HWCSUM) { 1260159967Sobrien ifp->if_capenable ^= IFCAP_HWCSUM; 1261159967Sobrien if (IFCAP_HWCSUM & ifp->if_capenable && 1262159967Sobrien IFCAP_HWCSUM & ifp->if_capabilities) 1263159967Sobrien ifp->if_hwassist = NFE_CSUM_FEATURES; 1264159967Sobrien else 1265159967Sobrien ifp->if_hwassist = 0; 1266159967Sobrien } 1267163503Sobrien } 1268159967Sobrien break; 1269159967Sobrien 1270159952Sobrien default: 1271159967Sobrien error = ether_ioctl(ifp, cmd, data); 1272159967Sobrien break; 1273159952Sobrien } 1274159952Sobrien 1275159952Sobrien return error; 1276159952Sobrien} 1277159952Sobrien 1278159967Sobrien 1279163503Sobrienstatic void 1280163503Sobriennfe_intr(void *arg) 1281159967Sobrien{ 1282159967Sobrien struct nfe_softc *sc = arg; 1283159967Sobrien struct ifnet *ifp = sc->nfe_ifp; 1284159967Sobrien u_int32_t r; 1285159967Sobrien 1286163503Sobrien NFE_LOCK(sc); 1287159967Sobrien 1288159967Sobrien#ifdef DEVICE_POLLING 1289159967Sobrien if (ifp->if_capenable & IFCAP_POLLING) { 1290159967Sobrien NFE_UNLOCK(sc); 1291159967Sobrien return; 1292159967Sobrien } 1293159967Sobrien#endif 1294159967Sobrien 1295159967Sobrien if ((r = NFE_READ(sc, NFE_IRQ_STATUS)) == 0) { 1296163503Sobrien NFE_UNLOCK(sc); 1297159967Sobrien return; /* not for us */ 1298159967Sobrien } 1299159967Sobrien NFE_WRITE(sc, NFE_IRQ_STATUS, r); 1300159967Sobrien 1301159967Sobrien DPRINTFN(5, ("nfe_intr: interrupt register %x\n", r)); 1302159967Sobrien 1303159967Sobrien NFE_WRITE(sc, NFE_IRQ_MASK, 0); 1304159967Sobrien 1305159967Sobrien if (r & NFE_IRQ_LINK) { 1306159967Sobrien NFE_READ(sc, NFE_PHY_STATUS); 1307159967Sobrien NFE_WRITE(sc, NFE_PHY_STATUS, 0xf); 1308159967Sobrien DPRINTF(("nfe%d: link state changed\n", sc->nfe_unit)); 1309159967Sobrien } 1310159967Sobrien 1311159967Sobrien if (ifp->if_drv_flags & IFF_DRV_RUNNING) { 1312159967Sobrien /* check Rx ring */ 1313159967Sobrien nfe_rxeof(sc); 1314159967Sobrien /* check Tx ring */ 1315159967Sobrien nfe_txeof(sc); 1316159967Sobrien } 1317159967Sobrien 1318163503Sobrien NFE_WRITE(sc, NFE_IRQ_MASK, NFE_IRQ_WANTED); 1319159967Sobrien 1320159967Sobrien if (ifp->if_drv_flags & IFF_DRV_RUNNING && 1321159967Sobrien !IFQ_DRV_IS_EMPTY(&ifp->if_snd)) 1322159967Sobrien nfe_start_locked(ifp); 1323159967Sobrien 1324159967Sobrien NFE_UNLOCK(sc); 1325159967Sobrien 1326159967Sobrien return; 1327159967Sobrien} 1328159967Sobrien 1329163503Sobrien 1330159967Sobrienstatic void 1331159952Sobriennfe_txdesc32_sync(struct nfe_softc *sc, struct nfe_desc32 *desc32, int ops) 1332159952Sobrien{ 1333163503Sobrien 1334159967Sobrien bus_dmamap_sync(sc->txq.tx_desc_tag, sc->txq.tx_desc_map, ops); 1335159952Sobrien} 1336159952Sobrien 1337163503Sobrien 1338159967Sobrienstatic void 1339159952Sobriennfe_txdesc64_sync(struct nfe_softc *sc, struct nfe_desc64 *desc64, int ops) 1340159952Sobrien{ 1341163503Sobrien 1342159967Sobrien bus_dmamap_sync(sc->txq.tx_desc_tag, sc->txq.tx_desc_map, ops); 1343159952Sobrien} 1344159952Sobrien 1345163503Sobrien 1346159967Sobrienstatic void 1347159952Sobriennfe_txdesc32_rsync(struct nfe_softc *sc, int start, int end, int ops) 1348159952Sobrien{ 1349163503Sobrien 1350159967Sobrien bus_dmamap_sync(sc->txq.tx_desc_tag, sc->txq.tx_desc_map, ops); 1351159952Sobrien} 1352159952Sobrien 1353163503Sobrien 1354159967Sobrienstatic void 1355159952Sobriennfe_txdesc64_rsync(struct nfe_softc *sc, int start, int end, int ops) 1356159952Sobrien{ 1357163503Sobrien 1358159967Sobrien bus_dmamap_sync(sc->txq.tx_desc_tag, sc->txq.tx_desc_map, ops); 1359159952Sobrien} 1360159952Sobrien 1361163503Sobrien 1362159967Sobrienstatic void 1363159952Sobriennfe_rxdesc32_sync(struct nfe_softc *sc, struct nfe_desc32 *desc32, int ops) 1364159952Sobrien{ 1365163503Sobrien 1366159967Sobrien bus_dmamap_sync(sc->rxq.rx_desc_tag, sc->rxq.rx_desc_map, ops); 1367159952Sobrien} 1368159952Sobrien 1369163503Sobrien 1370159967Sobrienstatic void 1371159952Sobriennfe_rxdesc64_sync(struct nfe_softc *sc, struct nfe_desc64 *desc64, int ops) 1372159952Sobrien{ 1373159967Sobrien 1374159967Sobrien bus_dmamap_sync(sc->rxq.rx_desc_tag, sc->rxq.rx_desc_map, ops); 1375159952Sobrien} 1376159952Sobrien 1377163503Sobrien 1378163503Sobrienstatic void 1379163503Sobriennfe_rxeof(struct nfe_softc *sc) 1380159952Sobrien{ 1381159967Sobrien struct ifnet *ifp = sc->nfe_ifp; 1382159967Sobrien struct nfe_desc32 *desc32=NULL; 1383159967Sobrien struct nfe_desc64 *desc64=NULL; 1384159952Sobrien struct nfe_rx_data *data; 1385159952Sobrien struct nfe_jbuf *jbuf; 1386159952Sobrien struct mbuf *m, *mnew; 1387159952Sobrien bus_addr_t physaddr; 1388159967Sobrien u_int16_t flags; 1389159952Sobrien int error, len; 1390159967Sobrien#if NVLAN > 1 1391159967Sobrien u_int16_t vlan_tag = 0; 1392159967Sobrien int have_tag = 0; 1393159967Sobrien#endif 1394159952Sobrien 1395159967Sobrien NFE_LOCK_ASSERT(sc); 1396159967Sobrien 1397159952Sobrien for (;;) { 1398159967Sobrien 1399159967Sobrien#ifdef DEVICE_POLLING 1400159967Sobrien if (ifp->if_capenable & IFCAP_POLLING) { 1401159967Sobrien if (sc->rxcycles <= 0) 1402159967Sobrien break; 1403159967Sobrien sc->rxcycles--; 1404159967Sobrien } 1405159967Sobrien#endif 1406159967Sobrien 1407159952Sobrien data = &sc->rxq.data[sc->rxq.cur]; 1408159952Sobrien 1409159967Sobrien if (sc->nfe_flags & NFE_40BIT_ADDR) { 1410159952Sobrien desc64 = &sc->rxq.desc64[sc->rxq.cur]; 1411159952Sobrien nfe_rxdesc64_sync(sc, desc64, BUS_DMASYNC_POSTREAD); 1412159952Sobrien 1413159952Sobrien flags = letoh16(desc64->flags); 1414159952Sobrien len = letoh16(desc64->length) & 0x3fff; 1415159967Sobrien 1416159967Sobrien#if NVLAN > 1 1417159967Sobrien if (flags & NFE_TX_VLAN_TAG) { 1418159967Sobrien have_tag = 1; 1419159967Sobrien vlan_tag = desc64->vtag; 1420159967Sobrien } 1421159967Sobrien#endif 1422159967Sobrien 1423159952Sobrien } else { 1424159952Sobrien desc32 = &sc->rxq.desc32[sc->rxq.cur]; 1425159952Sobrien nfe_rxdesc32_sync(sc, desc32, BUS_DMASYNC_POSTREAD); 1426159952Sobrien 1427159952Sobrien flags = letoh16(desc32->flags); 1428159952Sobrien len = letoh16(desc32->length) & 0x3fff; 1429159952Sobrien } 1430159952Sobrien 1431159952Sobrien if (flags & NFE_RX_READY) 1432159952Sobrien break; 1433159952Sobrien 1434159967Sobrien if ((sc->nfe_flags & (NFE_JUMBO_SUP | NFE_40BIT_ADDR)) == 0) { 1435159952Sobrien if (!(flags & NFE_RX_VALID_V1)) 1436159952Sobrien goto skip; 1437159952Sobrien if ((flags & NFE_RX_FIXME_V1) == NFE_RX_FIXME_V1) { 1438159952Sobrien flags &= ~NFE_RX_ERROR; 1439159952Sobrien len--; /* fix buffer length */ 1440159952Sobrien } 1441159952Sobrien } else { 1442159952Sobrien if (!(flags & NFE_RX_VALID_V2)) 1443159952Sobrien goto skip; 1444159952Sobrien 1445159952Sobrien if ((flags & NFE_RX_FIXME_V2) == NFE_RX_FIXME_V2) { 1446159952Sobrien flags &= ~NFE_RX_ERROR; 1447159952Sobrien len--; /* fix buffer length */ 1448159952Sobrien } 1449159952Sobrien } 1450159952Sobrien 1451159952Sobrien if (flags & NFE_RX_ERROR) { 1452159952Sobrien ifp->if_ierrors++; 1453159952Sobrien goto skip; 1454159952Sobrien } 1455159952Sobrien 1456159952Sobrien /* 1457159952Sobrien * Try to allocate a new mbuf for this ring element and load 1458159952Sobrien * it before processing the current mbuf. If the ring element 1459159952Sobrien * cannot be loaded, drop the received packet and reuse the 1460159952Sobrien * old mbuf. In the unlikely case that the old mbuf can't be 1461159952Sobrien * reloaded either, explicitly panic. 1462159952Sobrien */ 1463159952Sobrien MGETHDR(mnew, M_DONTWAIT, MT_DATA); 1464159952Sobrien if (mnew == NULL) { 1465159952Sobrien ifp->if_ierrors++; 1466159952Sobrien goto skip; 1467159952Sobrien } 1468159952Sobrien 1469159967Sobrien if (sc->nfe_flags & NFE_USE_JUMBO) { 1470159952Sobrien if ((jbuf = nfe_jalloc(sc)) == NULL) { 1471159952Sobrien m_freem(mnew); 1472159952Sobrien ifp->if_ierrors++; 1473159952Sobrien goto skip; 1474159952Sobrien } 1475159967Sobrien mnew->m_data = (void *)jbuf->buf; 1476159967Sobrien mnew->m_len = mnew->m_pkthdr.len = NFE_JBYTES; 1477159967Sobrien MEXTADD(mnew, jbuf->buf, NFE_JBYTES, nfe_jfree, 1478159967Sobrien (struct nfe_softc *)sc, 0 , EXT_NET_DRV); 1479159952Sobrien 1480159967Sobrien bus_dmamap_sync(sc->rxq.rx_jumbo_tag, 1481159967Sobrien sc->rxq.rx_jumbo_map, BUS_DMASYNC_POSTREAD); 1482159952Sobrien physaddr = jbuf->physaddr; 1483159952Sobrien } else { 1484159952Sobrien MCLGET(mnew, M_DONTWAIT); 1485159952Sobrien if (!(mnew->m_flags & M_EXT)) { 1486159952Sobrien m_freem(mnew); 1487159952Sobrien ifp->if_ierrors++; 1488159952Sobrien goto skip; 1489159952Sobrien } 1490159952Sobrien 1491159967Sobrien bus_dmamap_sync(data->rx_data_tag, data->rx_data_map, 1492159967Sobrien BUS_DMASYNC_POSTREAD); 1493159967Sobrien bus_dmamap_unload(data->rx_data_tag, data->rx_data_map); 1494159967Sobrien error = bus_dmamap_load(data->rx_data_tag, 1495159967Sobrien data->rx_data_map, mtod(mnew, void *), MCLBYTES, 1496159967Sobrien nfe_dma_map_segs, &data->rx_data_segs, 1497159967Sobrien BUS_DMA_NOWAIT); 1498159952Sobrien if (error != 0) { 1499159952Sobrien m_freem(mnew); 1500159952Sobrien 1501159952Sobrien /* try to reload the old mbuf */ 1502159967Sobrien error = bus_dmamap_load(data->rx_data_tag, 1503159967Sobrien data->rx_data_map, mtod(data->m, void *), 1504159967Sobrien MCLBYTES, nfe_dma_map_segs, 1505159967Sobrien &data->rx_data_segs, BUS_DMA_NOWAIT); 1506159952Sobrien if (error != 0) { 1507159952Sobrien /* very unlikely that it will fail.. */ 1508159967Sobrien panic("nfe%d: could not load old rx mbuf", 1509159967Sobrien sc->nfe_unit); 1510159952Sobrien } 1511159952Sobrien ifp->if_ierrors++; 1512159952Sobrien goto skip; 1513159952Sobrien } 1514159967Sobrien data->rx_data_addr = data->rx_data_segs.ds_addr; 1515159967Sobrien physaddr = data->rx_data_addr; 1516159952Sobrien } 1517159952Sobrien 1518159952Sobrien /* 1519159952Sobrien * New mbuf successfully loaded, update Rx ring and continue 1520159952Sobrien * processing. 1521159952Sobrien */ 1522159952Sobrien m = data->m; 1523159952Sobrien data->m = mnew; 1524159952Sobrien 1525159952Sobrien /* finalize mbuf */ 1526159952Sobrien m->m_pkthdr.len = m->m_len = len; 1527159952Sobrien m->m_pkthdr.rcvif = ifp; 1528159952Sobrien 1529159967Sobrien 1530159967Sobrien#if defined(NFE_CSUM) 1531159967Sobrien if ((sc->nfe_flags & NFE_HW_CSUM) && (flags & NFE_RX_CSUMOK)) { 1532159967Sobrien m->m_pkthdr.csum_flags |= CSUM_IP_CHECKED; 1533159967Sobrien if (flags & NFE_RX_IP_CSUMOK_V2) { 1534159967Sobrien m->m_pkthdr.csum_flags |= CSUM_IP_VALID; 1535159967Sobrien } 1536159967Sobrien if (flags & NFE_RX_UDP_CSUMOK_V2 || 1537159967Sobrien flags & NFE_RX_TCP_CSUMOK_V2) { 1538159967Sobrien m->m_pkthdr.csum_flags |= 1539163503Sobrien CSUM_DATA_VALID | CSUM_PSEUDO_HDR; 1540159967Sobrien m->m_pkthdr.csum_data = 0xffff; 1541159967Sobrien } 1542159952Sobrien } 1543159952Sobrien#endif 1544159952Sobrien 1545159967Sobrien#if NVLAN > 1 1546159967Sobrien if (have_tag) { 1547162375Sandre m->m_pkthdr.ether_vtag = vlan_tag; 1548162375Sandre m->m_flags |= M_VLANTAG; 1549159967Sobrien } 1550159952Sobrien#endif 1551159967Sobrien 1552159952Sobrien ifp->if_ipackets++; 1553159952Sobrien 1554159967Sobrien NFE_UNLOCK(sc); 1555159967Sobrien (*ifp->if_input)(ifp, m); 1556159967Sobrien NFE_LOCK(sc); 1557159967Sobrien 1558159952Sobrien /* update mapping address in h/w descriptor */ 1559159967Sobrien if (sc->nfe_flags & NFE_40BIT_ADDR) { 1560159952Sobrien#if defined(__LP64__) 1561159952Sobrien desc64->physaddr[0] = htole32(physaddr >> 32); 1562159952Sobrien#endif 1563159952Sobrien desc64->physaddr[1] = htole32(physaddr & 0xffffffff); 1564159952Sobrien } else { 1565159952Sobrien desc32->physaddr = htole32(physaddr); 1566159952Sobrien } 1567159952Sobrien 1568159967Sobrienskip: if (sc->nfe_flags & NFE_40BIT_ADDR) { 1569159952Sobrien desc64->length = htole16(sc->rxq.bufsz); 1570159952Sobrien desc64->flags = htole16(NFE_RX_READY); 1571159952Sobrien 1572159952Sobrien nfe_rxdesc64_sync(sc, desc64, BUS_DMASYNC_PREWRITE); 1573159952Sobrien } else { 1574159952Sobrien desc32->length = htole16(sc->rxq.bufsz); 1575159952Sobrien desc32->flags = htole16(NFE_RX_READY); 1576159952Sobrien 1577159952Sobrien nfe_rxdesc32_sync(sc, desc32, BUS_DMASYNC_PREWRITE); 1578159952Sobrien } 1579159952Sobrien 1580159952Sobrien sc->rxq.cur = (sc->rxq.cur + 1) % NFE_RX_RING_COUNT; 1581159952Sobrien } 1582159952Sobrien} 1583159952Sobrien 1584163503Sobrien 1585163503Sobrienstatic void 1586163503Sobriennfe_txeof(struct nfe_softc *sc) 1587159952Sobrien{ 1588159967Sobrien struct ifnet *ifp = sc->nfe_ifp; 1589159952Sobrien struct nfe_desc32 *desc32; 1590159952Sobrien struct nfe_desc64 *desc64; 1591159952Sobrien struct nfe_tx_data *data = NULL; 1592159967Sobrien u_int16_t flags; 1593159952Sobrien 1594159967Sobrien NFE_LOCK_ASSERT(sc); 1595159967Sobrien 1596159952Sobrien while (sc->txq.next != sc->txq.cur) { 1597159967Sobrien if (sc->nfe_flags & NFE_40BIT_ADDR) { 1598159952Sobrien desc64 = &sc->txq.desc64[sc->txq.next]; 1599159952Sobrien nfe_txdesc64_sync(sc, desc64, BUS_DMASYNC_POSTREAD); 1600159952Sobrien 1601159952Sobrien flags = letoh16(desc64->flags); 1602159952Sobrien } else { 1603159952Sobrien desc32 = &sc->txq.desc32[sc->txq.next]; 1604159952Sobrien nfe_txdesc32_sync(sc, desc32, BUS_DMASYNC_POSTREAD); 1605159952Sobrien 1606159952Sobrien flags = letoh16(desc32->flags); 1607159952Sobrien } 1608159952Sobrien 1609159952Sobrien if (flags & NFE_TX_VALID) 1610159952Sobrien break; 1611159952Sobrien 1612159952Sobrien data = &sc->txq.data[sc->txq.next]; 1613159952Sobrien 1614159967Sobrien if ((sc->nfe_flags & (NFE_JUMBO_SUP | NFE_40BIT_ADDR)) == 0) { 1615159952Sobrien if (!(flags & NFE_TX_LASTFRAG_V1) && data->m == NULL) 1616159952Sobrien goto skip; 1617159952Sobrien 1618159952Sobrien if ((flags & NFE_TX_ERROR_V1) != 0) { 1619159967Sobrien printf("nfe%d: tx v1 error 0x%4b\n", 1620163503Sobrien sc->nfe_unit, flags, NFE_V1_TXERR); 1621159967Sobrien 1622159952Sobrien ifp->if_oerrors++; 1623159952Sobrien } else 1624159952Sobrien ifp->if_opackets++; 1625159952Sobrien } else { 1626159952Sobrien if (!(flags & NFE_TX_LASTFRAG_V2) && data->m == NULL) 1627159952Sobrien goto skip; 1628159952Sobrien 1629159952Sobrien if ((flags & NFE_TX_ERROR_V2) != 0) { 1630159967Sobrien printf("nfe%d: tx v1 error 0x%4b\n", 1631163503Sobrien sc->nfe_unit, flags, NFE_V2_TXERR); 1632159967Sobrien 1633159952Sobrien ifp->if_oerrors++; 1634159952Sobrien } else 1635159952Sobrien ifp->if_opackets++; 1636159952Sobrien } 1637159952Sobrien 1638159952Sobrien if (data->m == NULL) { /* should not get there */ 1639163503Sobrien printf("nfe%d: last fragment bit w/o associated mbuf!\n", 1640159967Sobrien sc->nfe_unit); 1641159952Sobrien goto skip; 1642159952Sobrien } 1643159952Sobrien 1644159952Sobrien /* last fragment of the mbuf chain transmitted */ 1645159967Sobrien bus_dmamap_sync(sc->txq.tx_data_tag, data->active, 1646159967Sobrien BUS_DMASYNC_POSTWRITE); 1647159967Sobrien bus_dmamap_unload(sc->txq.tx_data_tag, data->active); 1648159952Sobrien m_freem(data->m); 1649159952Sobrien data->m = NULL; 1650159952Sobrien 1651159952Sobrien ifp->if_timer = 0; 1652159952Sobrien 1653159952Sobrienskip: sc->txq.queued--; 1654159952Sobrien sc->txq.next = (sc->txq.next + 1) % NFE_TX_RING_COUNT; 1655159952Sobrien } 1656159952Sobrien 1657159952Sobrien if (data != NULL) { /* at least one slot freed */ 1658159967Sobrien ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 1659159967Sobrien nfe_start_locked(ifp); 1660159952Sobrien } 1661159952Sobrien} 1662159952Sobrien 1663163503Sobrien 1664163503Sobrienstatic int 1665163503Sobriennfe_encap(struct nfe_softc *sc, struct mbuf *m0) 1666159952Sobrien{ 1667159967Sobrien struct nfe_desc32 *desc32=NULL; 1668159967Sobrien struct nfe_desc64 *desc64=NULL; 1669159967Sobrien struct nfe_tx_data *data=NULL; 1670159952Sobrien bus_dmamap_t map; 1671163503Sobrien bus_dma_segment_t segs[NFE_MAX_SCATTER]; 1672163503Sobrien int error, i, nsegs; 1673159967Sobrien u_int16_t flags = NFE_TX_VALID; 1674159952Sobrien 1675159967Sobrien map = sc->txq.data[sc->txq.cur].tx_data_map; 1676159952Sobrien 1677159967Sobrien error = bus_dmamap_load_mbuf_sg(sc->txq.tx_data_tag, map, m0, segs, 1678159967Sobrien &nsegs, BUS_DMA_NOWAIT); 1679159967Sobrien 1680159952Sobrien if (error != 0) { 1681159967Sobrien printf("nfe%d: could not map mbuf (error %d)\n", sc->nfe_unit, 1682159967Sobrien error); 1683159952Sobrien return error; 1684159952Sobrien } 1685159952Sobrien 1686159967Sobrien if (sc->txq.queued + nsegs >= NFE_TX_RING_COUNT - 1) { 1687159967Sobrien bus_dmamap_unload(sc->txq.tx_data_tag, map); 1688159952Sobrien return ENOBUFS; 1689159952Sobrien } 1690159952Sobrien 1691159967Sobrien 1692159952Sobrien#ifdef NFE_CSUM 1693159967Sobrien if (m0->m_pkthdr.csum_flags & CSUM_IP) 1694159952Sobrien flags |= NFE_TX_IP_CSUM; 1695159967Sobrien if (m0->m_pkthdr.csum_flags & CSUM_TCP) 1696159952Sobrien flags |= NFE_TX_TCP_CSUM; 1697159967Sobrien if (m0->m_pkthdr.csum_flags & CSUM_UDP) 1698159967Sobrien flags |= NFE_TX_TCP_CSUM; 1699159952Sobrien#endif 1700159952Sobrien 1701159967Sobrien for (i = 0; i < nsegs; i++) { 1702159952Sobrien data = &sc->txq.data[sc->txq.cur]; 1703159952Sobrien 1704159967Sobrien if (sc->nfe_flags & NFE_40BIT_ADDR) { 1705159952Sobrien desc64 = &sc->txq.desc64[sc->txq.cur]; 1706159952Sobrien#if defined(__LP64__) 1707159967Sobrien desc64->physaddr[0] = htole32(segs[i].ds_addr >> 32); 1708159952Sobrien#endif 1709159967Sobrien desc64->physaddr[1] = htole32(segs[i].ds_addr & 1710159967Sobrien 0xffffffff); 1711159967Sobrien desc64->length = htole16(segs[i].ds_len - 1); 1712159952Sobrien desc64->flags = htole16(flags); 1713159952Sobrien#if NVLAN > 0 1714162375Sandre if (m0->m_flags & M_VLANTAG) 1715162375Sandre desc64->vtag = htole32(NFE_TX_VTAG | 1716162375Sandre m0->m_pkthdr.ether_vtag); 1717159952Sobrien#endif 1718159952Sobrien } else { 1719159952Sobrien desc32 = &sc->txq.desc32[sc->txq.cur]; 1720159952Sobrien 1721159967Sobrien desc32->physaddr = htole32(segs[i].ds_addr); 1722159967Sobrien desc32->length = htole16(segs[i].ds_len - 1); 1723159952Sobrien desc32->flags = htole16(flags); 1724159952Sobrien } 1725159952Sobrien 1726159952Sobrien /* csum flags and vtag belong to the first fragment only */ 1727159967Sobrien if (nsegs > 1) { 1728159952Sobrien flags &= ~(NFE_TX_IP_CSUM | NFE_TX_TCP_CSUM); 1729159952Sobrien } 1730163503Sobrien 1731159952Sobrien sc->txq.queued++; 1732159952Sobrien sc->txq.cur = (sc->txq.cur + 1) % NFE_TX_RING_COUNT; 1733159952Sobrien } 1734159952Sobrien 1735159952Sobrien /* the whole mbuf chain has been DMA mapped, fix last descriptor */ 1736159967Sobrien if (sc->nfe_flags & NFE_40BIT_ADDR) { 1737159952Sobrien flags |= NFE_TX_LASTFRAG_V2; 1738159952Sobrien desc64->flags = htole16(flags); 1739159952Sobrien } else { 1740159967Sobrien if (sc->nfe_flags & NFE_JUMBO_SUP) 1741159952Sobrien flags |= NFE_TX_LASTFRAG_V2; 1742159952Sobrien else 1743159952Sobrien flags |= NFE_TX_LASTFRAG_V1; 1744159952Sobrien desc32->flags = htole16(flags); 1745159952Sobrien } 1746159952Sobrien 1747159952Sobrien data->m = m0; 1748159952Sobrien data->active = map; 1749159967Sobrien data->nsegs = nsegs; 1750159952Sobrien 1751159967Sobrien bus_dmamap_sync(sc->txq.tx_data_tag, map, BUS_DMASYNC_PREWRITE); 1752159952Sobrien 1753159952Sobrien return 0; 1754159952Sobrien} 1755159952Sobrien 1756159967Sobrien 1757163503Sobrienstatic void 1758163503Sobriennfe_setmulti(struct nfe_softc *sc) 1759159952Sobrien{ 1760159967Sobrien struct ifnet *ifp = sc->nfe_ifp; 1761163503Sobrien struct ifmultiaddr *ifma; 1762163503Sobrien int i; 1763163503Sobrien u_int32_t filter = NFE_RXFILTER_MAGIC; 1764159967Sobrien u_int8_t addr[ETHER_ADDR_LEN], mask[ETHER_ADDR_LEN]; 1765163503Sobrien u_int8_t etherbroadcastaddr[ETHER_ADDR_LEN] = { 1766163503Sobrien 0xff, 0xff, 0xff, 0xff, 0xff, 0xff 1767163503Sobrien }; 1768159967Sobrien 1769159967Sobrien NFE_LOCK_ASSERT(sc); 1770159967Sobrien 1771159967Sobrien if ((ifp->if_flags & (IFF_ALLMULTI | IFF_PROMISC)) != 0) { 1772159967Sobrien bzero(addr, ETHER_ADDR_LEN); 1773159967Sobrien bzero(mask, ETHER_ADDR_LEN); 1774159967Sobrien goto done; 1775159967Sobrien } 1776159967Sobrien 1777159967Sobrien bcopy(etherbroadcastaddr, addr, ETHER_ADDR_LEN); 1778159967Sobrien bcopy(etherbroadcastaddr, mask, ETHER_ADDR_LEN); 1779159967Sobrien 1780159967Sobrien IF_ADDR_LOCK(ifp); 1781159967Sobrien TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { 1782159967Sobrien u_char *addrp; 1783159967Sobrien 1784159967Sobrien if (ifma->ifma_addr->sa_family != AF_LINK) 1785159967Sobrien continue; 1786159967Sobrien 1787159967Sobrien addrp = LLADDR((struct sockaddr_dl *) ifma->ifma_addr); 1788159967Sobrien for (i = 0; i < ETHER_ADDR_LEN; i++) { 1789159967Sobrien u_int8_t mcaddr = addrp[i]; 1790159967Sobrien addr[i] &= mcaddr; 1791159967Sobrien mask[i] &= ~mcaddr; 1792159967Sobrien } 1793159967Sobrien } 1794159967Sobrien IF_ADDR_UNLOCK(ifp); 1795159967Sobrien 1796159967Sobrien for (i = 0; i < ETHER_ADDR_LEN; i++) { 1797159967Sobrien mask[i] |= addr[i]; 1798159967Sobrien } 1799159967Sobrien 1800159967Sobriendone: 1801159967Sobrien addr[0] |= 0x01; /* make sure multicast bit is set */ 1802159967Sobrien 1803159967Sobrien NFE_WRITE(sc, NFE_MULTIADDR_HI, 1804159967Sobrien addr[3] << 24 | addr[2] << 16 | addr[1] << 8 | addr[0]); 1805159967Sobrien NFE_WRITE(sc, NFE_MULTIADDR_LO, 1806159967Sobrien addr[5] << 8 | addr[4]); 1807159967Sobrien NFE_WRITE(sc, NFE_MULTIMASK_HI, 1808159967Sobrien mask[3] << 24 | mask[2] << 16 | mask[1] << 8 | mask[0]); 1809159967Sobrien NFE_WRITE(sc, NFE_MULTIMASK_LO, 1810159967Sobrien mask[5] << 8 | mask[4]); 1811159967Sobrien 1812159967Sobrien filter |= (ifp->if_flags & IFF_PROMISC) ? NFE_PROMISC : NFE_U2M; 1813159967Sobrien NFE_WRITE(sc, NFE_RXFILTER, filter); 1814159967Sobrien} 1815159967Sobrien 1816163503Sobrien 1817163503Sobrienstatic void 1818163503Sobriennfe_start(struct ifnet *ifp) 1819159967Sobrien{ 1820159967Sobrien struct nfe_softc *sc; 1821159967Sobrien 1822159967Sobrien sc = ifp->if_softc; 1823159967Sobrien NFE_LOCK(sc); 1824159967Sobrien nfe_start_locked(ifp); 1825159967Sobrien NFE_UNLOCK(sc); 1826159967Sobrien} 1827159967Sobrien 1828163503Sobrien 1829163503Sobrienstatic void 1830163503Sobriennfe_start_locked(struct ifnet *ifp) 1831159967Sobrien{ 1832159952Sobrien struct nfe_softc *sc = ifp->if_softc; 1833163503Sobrien struct mbuf *m0; 1834159952Sobrien int old = sc->txq.cur; 1835159952Sobrien 1836159967Sobrien if (!sc->nfe_link || ifp->if_drv_flags & IFF_DRV_OACTIVE) { 1837159967Sobrien return; 1838159967Sobrien } 1839159967Sobrien 1840159952Sobrien for (;;) { 1841159952Sobrien IFQ_POLL(&ifp->if_snd, m0); 1842159952Sobrien if (m0 == NULL) 1843159952Sobrien break; 1844159952Sobrien 1845159952Sobrien if (nfe_encap(sc, m0) != 0) { 1846159967Sobrien ifp->if_drv_flags |= IFF_DRV_OACTIVE; 1847159952Sobrien break; 1848159952Sobrien } 1849159952Sobrien 1850159952Sobrien /* packet put in h/w queue, remove from s/w queue */ 1851159952Sobrien IFQ_DEQUEUE(&ifp->if_snd, m0); 1852159952Sobrien 1853159967Sobrien BPF_MTAP(ifp, m0); 1854159952Sobrien } 1855159967Sobrien if (sc->txq.cur == old) { /* nothing sent */ 1856159952Sobrien return; 1857159967Sobrien } 1858159952Sobrien 1859159967Sobrien if (sc->nfe_flags & NFE_40BIT_ADDR) 1860159952Sobrien nfe_txdesc64_rsync(sc, old, sc->txq.cur, BUS_DMASYNC_PREWRITE); 1861159952Sobrien else 1862159952Sobrien nfe_txdesc32_rsync(sc, old, sc->txq.cur, BUS_DMASYNC_PREWRITE); 1863159952Sobrien 1864159952Sobrien /* kick Tx */ 1865159952Sobrien NFE_WRITE(sc, NFE_RXTX_CTL, NFE_RXTX_KICKTX | sc->rxtxctl); 1866159952Sobrien 1867159952Sobrien /* 1868159952Sobrien * Set a timeout in case the chip goes out to lunch. 1869159952Sobrien */ 1870159952Sobrien ifp->if_timer = 5; 1871159967Sobrien 1872159967Sobrien return; 1873159952Sobrien} 1874159952Sobrien 1875163503Sobrien 1876163503Sobrienstatic void 1877163503Sobriennfe_watchdog(struct ifnet *ifp) 1878159952Sobrien{ 1879159952Sobrien struct nfe_softc *sc = ifp->if_softc; 1880159952Sobrien 1881159967Sobrien printf("nfe%d: watchdog timeout\n", sc->nfe_unit); 1882159952Sobrien 1883159967Sobrien ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 1884159967Sobrien nfe_init(sc); 1885159952Sobrien ifp->if_oerrors++; 1886159967Sobrien 1887159967Sobrien return; 1888159952Sobrien} 1889159952Sobrien 1890163503Sobrien 1891163503Sobrienstatic void 1892163503Sobriennfe_init(void *xsc) 1893159952Sobrien{ 1894159967Sobrien struct nfe_softc *sc = xsc; 1895159952Sobrien 1896159967Sobrien NFE_LOCK(sc); 1897159967Sobrien nfe_init_locked(sc); 1898159967Sobrien NFE_UNLOCK(sc); 1899159967Sobrien 1900159967Sobrien return; 1901159967Sobrien} 1902159967Sobrien 1903163503Sobrien 1904163503Sobrienstatic void 1905163503Sobriennfe_init_locked(void *xsc) 1906159967Sobrien{ 1907159967Sobrien struct nfe_softc *sc = xsc; 1908159967Sobrien struct ifnet *ifp = sc->nfe_ifp; 1909159967Sobrien struct mii_data *mii; 1910159967Sobrien u_int32_t tmp; 1911159967Sobrien 1912159967Sobrien NFE_LOCK_ASSERT(sc); 1913159967Sobrien 1914159967Sobrien mii = device_get_softc(sc->nfe_miibus); 1915159967Sobrien 1916159967Sobrien if (ifp->if_drv_flags & IFF_DRV_RUNNING) { 1917159967Sobrien return; 1918159967Sobrien } 1919159967Sobrien 1920159952Sobrien nfe_stop(ifp, 0); 1921159952Sobrien 1922159952Sobrien NFE_WRITE(sc, NFE_TX_UNK, 0); 1923159952Sobrien NFE_WRITE(sc, NFE_STATUS, 0); 1924159952Sobrien 1925159952Sobrien sc->rxtxctl = NFE_RXTX_BIT2; 1926159967Sobrien if (sc->nfe_flags & NFE_40BIT_ADDR) 1927159952Sobrien sc->rxtxctl |= NFE_RXTX_V3MAGIC; 1928159967Sobrien else if (sc->nfe_flags & NFE_JUMBO_SUP) 1929159952Sobrien sc->rxtxctl |= NFE_RXTX_V2MAGIC; 1930159952Sobrien#ifdef NFE_CSUM 1931159967Sobrien if (sc->nfe_flags & NFE_HW_CSUM) 1932159952Sobrien sc->rxtxctl |= NFE_RXTX_RXCSUM; 1933159952Sobrien#endif 1934159967Sobrien 1935159952Sobrien#if NVLAN > 0 1936159952Sobrien /* 1937159952Sobrien * Although the adapter is capable of stripping VLAN tags from received 1938159952Sobrien * frames (NFE_RXTX_VTAG_STRIP), we do not enable this functionality on 1939159952Sobrien * purpose. This will be done in software by our network stack. 1940159952Sobrien */ 1941159967Sobrien if (sc->nfe_flags & NFE_HW_VLAN) 1942159952Sobrien sc->rxtxctl |= NFE_RXTX_VTAG_INSERT; 1943159952Sobrien#endif 1944159967Sobrien 1945159952Sobrien NFE_WRITE(sc, NFE_RXTX_CTL, NFE_RXTX_RESET | sc->rxtxctl); 1946159952Sobrien DELAY(10); 1947159952Sobrien NFE_WRITE(sc, NFE_RXTX_CTL, sc->rxtxctl); 1948159952Sobrien 1949159952Sobrien#if NVLAN 1950159967Sobrien if (sc->nfe_flags & NFE_HW_VLAN) 1951159952Sobrien NFE_WRITE(sc, NFE_VTAG_CTL, NFE_VTAG_ENABLE); 1952159952Sobrien#endif 1953159952Sobrien 1954159952Sobrien NFE_WRITE(sc, NFE_SETUP_R6, 0); 1955159952Sobrien 1956159952Sobrien /* set MAC address */ 1957159967Sobrien nfe_set_macaddr(sc, sc->eaddr); 1958159952Sobrien 1959159952Sobrien /* tell MAC where rings are in memory */ 1960159952Sobrien#ifdef __LP64__ 1961159952Sobrien NFE_WRITE(sc, NFE_RX_RING_ADDR_HI, sc->rxq.physaddr >> 32); 1962159952Sobrien#endif 1963159952Sobrien NFE_WRITE(sc, NFE_RX_RING_ADDR_LO, sc->rxq.physaddr & 0xffffffff); 1964159952Sobrien#ifdef __LP64__ 1965159952Sobrien NFE_WRITE(sc, NFE_TX_RING_ADDR_HI, sc->txq.physaddr >> 32); 1966159952Sobrien#endif 1967159952Sobrien NFE_WRITE(sc, NFE_TX_RING_ADDR_LO, sc->txq.physaddr & 0xffffffff); 1968159952Sobrien 1969159952Sobrien NFE_WRITE(sc, NFE_RING_SIZE, 1970159952Sobrien (NFE_RX_RING_COUNT - 1) << 16 | 1971159952Sobrien (NFE_TX_RING_COUNT - 1)); 1972159952Sobrien 1973159952Sobrien NFE_WRITE(sc, NFE_RXBUFSZ, sc->rxq.bufsz); 1974159952Sobrien 1975159952Sobrien /* force MAC to wakeup */ 1976159952Sobrien tmp = NFE_READ(sc, NFE_PWR_STATE); 1977159952Sobrien NFE_WRITE(sc, NFE_PWR_STATE, tmp | NFE_PWR_WAKEUP); 1978159952Sobrien DELAY(10); 1979159952Sobrien tmp = NFE_READ(sc, NFE_PWR_STATE); 1980159952Sobrien NFE_WRITE(sc, NFE_PWR_STATE, tmp | NFE_PWR_VALID); 1981159952Sobrien 1982159952Sobrien#if 1 1983159952Sobrien /* configure interrupts coalescing/mitigation */ 1984159952Sobrien NFE_WRITE(sc, NFE_IMTIMER, NFE_IM_DEFAULT); 1985159952Sobrien#else 1986159952Sobrien /* no interrupt mitigation: one interrupt per packet */ 1987159952Sobrien NFE_WRITE(sc, NFE_IMTIMER, 970); 1988159952Sobrien#endif 1989159952Sobrien 1990159952Sobrien NFE_WRITE(sc, NFE_SETUP_R1, NFE_R1_MAGIC); 1991159952Sobrien NFE_WRITE(sc, NFE_SETUP_R2, NFE_R2_MAGIC); 1992159952Sobrien NFE_WRITE(sc, NFE_SETUP_R6, NFE_R6_MAGIC); 1993159952Sobrien 1994159952Sobrien /* update MAC knowledge of PHY; generates a NFE_IRQ_LINK interrupt */ 1995159952Sobrien NFE_WRITE(sc, NFE_STATUS, sc->mii_phyaddr << 24 | NFE_STATUS_MAGIC); 1996159952Sobrien 1997159952Sobrien NFE_WRITE(sc, NFE_SETUP_R4, NFE_R4_MAGIC); 1998159952Sobrien NFE_WRITE(sc, NFE_WOL_CTL, NFE_WOL_MAGIC); 1999159952Sobrien 2000159952Sobrien sc->rxtxctl &= ~NFE_RXTX_BIT2; 2001159952Sobrien NFE_WRITE(sc, NFE_RXTX_CTL, sc->rxtxctl); 2002159952Sobrien DELAY(10); 2003159952Sobrien NFE_WRITE(sc, NFE_RXTX_CTL, NFE_RXTX_BIT1 | sc->rxtxctl); 2004159952Sobrien 2005159952Sobrien /* set Rx filter */ 2006159952Sobrien nfe_setmulti(sc); 2007159952Sobrien 2008159952Sobrien nfe_ifmedia_upd(ifp); 2009159952Sobrien 2010159967Sobrien nfe_tick_locked(sc); 2011159967Sobrien 2012159952Sobrien /* enable Rx */ 2013159952Sobrien NFE_WRITE(sc, NFE_RX_CTL, NFE_RX_START); 2014159952Sobrien 2015159952Sobrien /* enable Tx */ 2016159952Sobrien NFE_WRITE(sc, NFE_TX_CTL, NFE_TX_START); 2017159952Sobrien 2018159952Sobrien NFE_WRITE(sc, NFE_PHY_STATUS, 0xf); 2019159952Sobrien 2020159967Sobrien#ifdef DEVICE_POLLING 2021159967Sobrien if (ifp->if_capenable & IFCAP_POLLING) 2022159967Sobrien NFE_WRITE(sc, NFE_IRQ_MASK, 0); 2023159967Sobrien else 2024159967Sobrien#endif 2025159967Sobrien NFE_WRITE(sc, NFE_IRQ_MASK, NFE_IRQ_WANTED); /* enable interrupts */ 2026159952Sobrien 2027159967Sobrien ifp->if_drv_flags |= IFF_DRV_RUNNING; 2028159967Sobrien ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 2029159952Sobrien 2030159967Sobrien sc->nfe_link = 0; 2031159952Sobrien 2032159967Sobrien return; 2033159952Sobrien} 2034159952Sobrien 2035163503Sobrien 2036163503Sobrienstatic void 2037163503Sobriennfe_stop(struct ifnet *ifp, int disable) 2038159952Sobrien{ 2039159952Sobrien struct nfe_softc *sc = ifp->if_softc; 2040159967Sobrien struct mii_data *mii; 2041159952Sobrien 2042159967Sobrien NFE_LOCK_ASSERT(sc); 2043159952Sobrien 2044159952Sobrien ifp->if_timer = 0; 2045159967Sobrien ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); 2046159952Sobrien 2047159967Sobrien mii = device_get_softc(sc->nfe_miibus); 2048159952Sobrien 2049159967Sobrien callout_stop(&sc->nfe_stat_ch); 2050159967Sobrien 2051159952Sobrien /* abort Tx */ 2052159952Sobrien NFE_WRITE(sc, NFE_TX_CTL, 0); 2053159952Sobrien 2054159952Sobrien /* disable Rx */ 2055159952Sobrien NFE_WRITE(sc, NFE_RX_CTL, 0); 2056159952Sobrien 2057159952Sobrien /* disable interrupts */ 2058159952Sobrien NFE_WRITE(sc, NFE_IRQ_MASK, 0); 2059159952Sobrien 2060159967Sobrien sc->nfe_link = 0; 2061159967Sobrien 2062159952Sobrien /* reset Tx and Rx rings */ 2063159952Sobrien nfe_reset_tx_ring(sc, &sc->txq); 2064159952Sobrien nfe_reset_rx_ring(sc, &sc->rxq); 2065159952Sobrien 2066159967Sobrien return; 2067159952Sobrien} 2068159952Sobrien 2069163503Sobrien 2070163503Sobrienstatic int 2071163503Sobriennfe_ifmedia_upd(struct ifnet *ifp) 2072159952Sobrien{ 2073159967Sobrien struct nfe_softc *sc = ifp->if_softc; 2074159952Sobrien 2075159967Sobrien NFE_LOCK(sc); 2076159967Sobrien nfe_ifmedia_upd_locked(ifp); 2077159967Sobrien NFE_UNLOCK(sc); 2078159967Sobrien return (0); 2079159952Sobrien} 2080159952Sobrien 2081163503Sobrien 2082163503Sobrienstatic int 2083163503Sobriennfe_ifmedia_upd_locked(struct ifnet *ifp) 2084159952Sobrien{ 2085163503Sobrien struct nfe_softc *sc = ifp->if_softc; 2086163503Sobrien struct mii_data *mii; 2087159952Sobrien 2088159967Sobrien NFE_LOCK_ASSERT(sc); 2089159952Sobrien 2090159967Sobrien mii = device_get_softc(sc->nfe_miibus); 2091159952Sobrien 2092159967Sobrien if (mii->mii_instance) { 2093159967Sobrien struct mii_softc *miisc; 2094159967Sobrien for (miisc = LIST_FIRST(&mii->mii_phys); miisc != NULL; 2095159967Sobrien miisc = LIST_NEXT(miisc, mii_list)) { 2096159967Sobrien mii_phy_reset(miisc); 2097159952Sobrien } 2098159952Sobrien } 2099159967Sobrien mii_mediachg(mii); 2100159967Sobrien 2101159967Sobrien return (0); 2102159952Sobrien} 2103159952Sobrien 2104163503Sobrien 2105163503Sobrienstatic void 2106163503Sobriennfe_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr) 2107159952Sobrien{ 2108163503Sobrien struct nfe_softc *sc; 2109163503Sobrien struct mii_data *mii; 2110159952Sobrien 2111159967Sobrien sc = ifp->if_softc; 2112159952Sobrien 2113159967Sobrien NFE_LOCK(sc); 2114159967Sobrien mii = device_get_softc(sc->nfe_miibus); 2115159967Sobrien mii_pollstat(mii); 2116159967Sobrien NFE_UNLOCK(sc); 2117159952Sobrien 2118159967Sobrien ifmr->ifm_active = mii->mii_media_active; 2119159967Sobrien ifmr->ifm_status = mii->mii_media_status; 2120159952Sobrien 2121159967Sobrien return; 2122159952Sobrien} 2123159952Sobrien 2124163503Sobrien 2125159967Sobrienstatic void 2126159967Sobriennfe_tick(void *xsc) 2127159952Sobrien{ 2128159967Sobrien struct nfe_softc *sc; 2129159952Sobrien 2130159967Sobrien sc = xsc; 2131159952Sobrien 2132159967Sobrien NFE_LOCK(sc); 2133159967Sobrien nfe_tick_locked(sc); 2134159967Sobrien NFE_UNLOCK(sc); 2135159952Sobrien} 2136159952Sobrien 2137159952Sobrien 2138163503Sobrienvoid 2139163503Sobriennfe_tick_locked(struct nfe_softc *arg) 2140159952Sobrien{ 2141163503Sobrien struct nfe_softc *sc; 2142163503Sobrien struct mii_data *mii; 2143163503Sobrien struct ifnet *ifp; 2144159952Sobrien 2145159967Sobrien sc = arg; 2146159952Sobrien 2147163503Sobrien NFE_LOCK_ASSERT(sc); 2148159952Sobrien 2149159967Sobrien ifp = sc->nfe_ifp; 2150159952Sobrien 2151159967Sobrien mii = device_get_softc(sc->nfe_miibus); 2152159967Sobrien mii_tick(mii); 2153159952Sobrien 2154159967Sobrien if (!sc->nfe_link) { 2155159967Sobrien if (mii->mii_media_status & IFM_ACTIVE && 2156159967Sobrien IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) { 2157159967Sobrien sc->nfe_link++; 2158159967Sobrien if (IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_T 2159159967Sobrien && bootverbose) 2160159967Sobrien if_printf(sc->nfe_ifp, "gigabit link up\n"); 2161159967Sobrien if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) 2162159967Sobrien nfe_start_locked(ifp); 2163159952Sobrien } 2164159952Sobrien } 2165159967Sobrien callout_reset(&sc->nfe_stat_ch, hz, nfe_tick, sc); 2166159952Sobrien 2167159967Sobrien return; 2168159952Sobrien} 2169159952Sobrien 2170159952Sobrien 2171163503Sobrienstatic void 2172163503Sobriennfe_shutdown(device_t dev) 2173159952Sobrien{ 2174159967Sobrien struct nfe_softc *sc; 2175159967Sobrien struct ifnet *ifp; 2176159952Sobrien 2177159967Sobrien sc = device_get_softc(dev); 2178159952Sobrien 2179159967Sobrien NFE_LOCK(sc); 2180159967Sobrien ifp = sc->nfe_ifp; 2181159967Sobrien nfe_stop(ifp,0); 2182159967Sobrien /* nfe_reset(sc); */ 2183159967Sobrien NFE_UNLOCK(sc); 2184159952Sobrien 2185159967Sobrien return; 2186159952Sobrien} 2187159952Sobrien 2188159952Sobrien 2189163503Sobrienstatic void 2190163503Sobriennfe_get_macaddr(struct nfe_softc *sc, u_char *addr) 2191159952Sobrien{ 2192159952Sobrien uint32_t tmp; 2193159952Sobrien 2194159952Sobrien tmp = NFE_READ(sc, NFE_MACADDR_LO); 2195159952Sobrien addr[0] = (tmp >> 8) & 0xff; 2196159952Sobrien addr[1] = (tmp & 0xff); 2197159952Sobrien 2198159952Sobrien tmp = NFE_READ(sc, NFE_MACADDR_HI); 2199159952Sobrien addr[2] = (tmp >> 24) & 0xff; 2200159952Sobrien addr[3] = (tmp >> 16) & 0xff; 2201159952Sobrien addr[4] = (tmp >> 8) & 0xff; 2202159952Sobrien addr[5] = (tmp & 0xff); 2203159952Sobrien} 2204159952Sobrien 2205163503Sobrien 2206163503Sobrienstatic void 2207163503Sobriennfe_set_macaddr(struct nfe_softc *sc, u_char *addr) 2208159952Sobrien{ 2209159967Sobrien 2210159967Sobrien NFE_WRITE(sc, NFE_MACADDR_LO, addr[5] << 8 | addr[4]); 2211159967Sobrien NFE_WRITE(sc, NFE_MACADDR_HI, addr[3] << 24 | addr[2] << 16 | 2212159967Sobrien addr[1] << 8 | addr[0]); 2213159952Sobrien} 2214159952Sobrien 2215163503Sobrien 2216159967Sobrien/* 2217159967Sobrien * Map a single buffer address. 2218159967Sobrien */ 2219159967Sobrien 2220159967Sobrienstatic void 2221159967Sobriennfe_dma_map_segs(arg, segs, nseg, error) 2222159967Sobrien void *arg; 2223159967Sobrien bus_dma_segment_t *segs; 2224159967Sobrien int error, nseg; 2225159952Sobrien{ 2226159952Sobrien 2227159967Sobrien if (error) 2228159967Sobrien return; 2229159952Sobrien 2230159967Sobrien KASSERT(nseg == 1, ("too many DMA segments, %d should be 1", nseg)); 2231159967Sobrien 2232159967Sobrien *(bus_dma_segment_t *)arg = *segs; 2233159967Sobrien 2234159967Sobrien return; 2235159952Sobrien} 2236