1ae813fd8SSepherosa Ziehau /* $OpenBSD: if_nfe.c,v 1.63 2006/06/17 18:00:43 brad Exp $ */ 246d50f4bSSepherosa Ziehau /* $DragonFly: src/sys/dev/netif/nfe/if_nfe.c,v 1.46 2008/10/28 07:30:49 sephe Exp $ */ 3ae813fd8SSepherosa Ziehau 4ae813fd8SSepherosa Ziehau /* 5ae813fd8SSepherosa Ziehau * Copyright (c) 2006 The DragonFly Project. All rights reserved. 6ae813fd8SSepherosa Ziehau * 7ae813fd8SSepherosa Ziehau * This code is derived from software contributed to The DragonFly Project 8ae813fd8SSepherosa Ziehau * by Sepherosa Ziehau <sepherosa@gmail.com> and 9ae813fd8SSepherosa Ziehau * Matthew Dillon <dillon@apollo.backplane.com> 10ae813fd8SSepherosa Ziehau * 11ae813fd8SSepherosa Ziehau * Redistribution and use in source and binary forms, with or without 12ae813fd8SSepherosa Ziehau * modification, are permitted provided that the following conditions 13ae813fd8SSepherosa Ziehau * are met: 14ae813fd8SSepherosa Ziehau * 15ae813fd8SSepherosa Ziehau * 1. Redistributions of source code must retain the above copyright 16ae813fd8SSepherosa Ziehau * notice, this list of conditions and the following disclaimer. 17ae813fd8SSepherosa Ziehau * 2. Redistributions in binary form must reproduce the above copyright 18ae813fd8SSepherosa Ziehau * notice, this list of conditions and the following disclaimer in 19ae813fd8SSepherosa Ziehau * the documentation and/or other materials provided with the 20ae813fd8SSepherosa Ziehau * distribution. 21ae813fd8SSepherosa Ziehau * 3. Neither the name of The DragonFly Project nor the names of its 22ae813fd8SSepherosa Ziehau * contributors may be used to endorse or promote products derived 23ae813fd8SSepherosa Ziehau * from this software without specific, prior written permission. 24ae813fd8SSepherosa Ziehau * 25ae813fd8SSepherosa Ziehau * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26ae813fd8SSepherosa Ziehau * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27ae813fd8SSepherosa Ziehau * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 28ae813fd8SSepherosa Ziehau * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 29ae813fd8SSepherosa Ziehau * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 30ae813fd8SSepherosa Ziehau * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 31ae813fd8SSepherosa Ziehau * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 32ae813fd8SSepherosa Ziehau * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 33ae813fd8SSepherosa Ziehau * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 34ae813fd8SSepherosa Ziehau * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 35ae813fd8SSepherosa Ziehau * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36ae813fd8SSepherosa Ziehau * SUCH DAMAGE. 37ae813fd8SSepherosa Ziehau */ 38ae813fd8SSepherosa Ziehau 39ae813fd8SSepherosa Ziehau /* 40ae813fd8SSepherosa Ziehau * Copyright (c) 2006 Damien Bergamini <damien.bergamini@free.fr> 41ae813fd8SSepherosa Ziehau * Copyright (c) 2005, 2006 Jonathan Gray <jsg@openbsd.org> 42ae813fd8SSepherosa Ziehau * 43ae813fd8SSepherosa Ziehau * Permission to use, copy, modify, and distribute this software for any 44ae813fd8SSepherosa Ziehau * purpose with or without fee is hereby granted, provided that the above 45ae813fd8SSepherosa Ziehau * copyright notice and this permission notice appear in all copies. 46ae813fd8SSepherosa Ziehau * 47ae813fd8SSepherosa Ziehau * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 48ae813fd8SSepherosa Ziehau * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 49ae813fd8SSepherosa Ziehau * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 50ae813fd8SSepherosa Ziehau * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 51ae813fd8SSepherosa Ziehau * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 52ae813fd8SSepherosa Ziehau * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 53ae813fd8SSepherosa Ziehau * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 54ae813fd8SSepherosa Ziehau */ 55ae813fd8SSepherosa Ziehau 56ae813fd8SSepherosa Ziehau /* Driver for NVIDIA nForce MCP Fast Ethernet and Gigabit Ethernet */ 57ae813fd8SSepherosa Ziehau 58ae813fd8SSepherosa Ziehau #include "opt_polling.h" 59ae813fd8SSepherosa Ziehau 60ae813fd8SSepherosa Ziehau #include <sys/param.h> 61ae813fd8SSepherosa Ziehau #include <sys/endian.h> 62ae813fd8SSepherosa Ziehau #include <sys/kernel.h> 63ae813fd8SSepherosa Ziehau #include <sys/bus.h> 649db4b353SSepherosa Ziehau #include <sys/interrupt.h> 65ae813fd8SSepherosa Ziehau #include <sys/proc.h> 66ae813fd8SSepherosa Ziehau #include <sys/rman.h> 67ae813fd8SSepherosa Ziehau #include <sys/serialize.h> 68ae813fd8SSepherosa Ziehau #include <sys/socket.h> 69ae813fd8SSepherosa Ziehau #include <sys/sockio.h> 70ae813fd8SSepherosa Ziehau #include <sys/sysctl.h> 71ae813fd8SSepherosa Ziehau 72ae813fd8SSepherosa Ziehau #include <net/ethernet.h> 73ae813fd8SSepherosa Ziehau #include <net/if.h> 74ae813fd8SSepherosa Ziehau #include <net/bpf.h> 75ae813fd8SSepherosa Ziehau #include <net/if_arp.h> 76ae813fd8SSepherosa Ziehau #include <net/if_dl.h> 77ae813fd8SSepherosa Ziehau #include <net/if_media.h> 78ae813fd8SSepherosa Ziehau #include <net/ifq_var.h> 79ae813fd8SSepherosa Ziehau #include <net/if_types.h> 80ae813fd8SSepherosa Ziehau #include <net/if_var.h> 81ae813fd8SSepherosa Ziehau #include <net/vlan/if_vlan_var.h> 82b637f170SSepherosa Ziehau #include <net/vlan/if_vlan_ether.h> 83ae813fd8SSepherosa Ziehau 84ae813fd8SSepherosa Ziehau #include <bus/pci/pcireg.h> 85ae813fd8SSepherosa Ziehau #include <bus/pci/pcivar.h> 86ae813fd8SSepherosa Ziehau #include <bus/pci/pcidevs.h> 87ae813fd8SSepherosa Ziehau 88ae813fd8SSepherosa Ziehau #include <dev/netif/mii_layer/mii.h> 89ae813fd8SSepherosa Ziehau #include <dev/netif/mii_layer/miivar.h> 90ae813fd8SSepherosa Ziehau 91ae813fd8SSepherosa Ziehau #include "miibus_if.h" 92ae813fd8SSepherosa Ziehau 9311db6c57SSepherosa Ziehau #include <dev/netif/nfe/if_nfereg.h> 9411db6c57SSepherosa Ziehau #include <dev/netif/nfe/if_nfevar.h> 9511db6c57SSepherosa Ziehau 9611db6c57SSepherosa Ziehau #define NFE_CSUM 9711db6c57SSepherosa Ziehau #define NFE_CSUM_FEATURES (CSUM_IP | CSUM_TCP | CSUM_UDP) 98ae813fd8SSepherosa Ziehau 99ae813fd8SSepherosa Ziehau static int nfe_probe(device_t); 100ae813fd8SSepherosa Ziehau static int nfe_attach(device_t); 101ae813fd8SSepherosa Ziehau static int nfe_detach(device_t); 102ae813fd8SSepherosa Ziehau static void nfe_shutdown(device_t); 103ae813fd8SSepherosa Ziehau static int nfe_resume(device_t); 104ae813fd8SSepherosa Ziehau static int nfe_suspend(device_t); 105ae813fd8SSepherosa Ziehau 106ae813fd8SSepherosa Ziehau static int nfe_miibus_readreg(device_t, int, int); 107ae813fd8SSepherosa Ziehau static void nfe_miibus_writereg(device_t, int, int, int); 108ae813fd8SSepherosa Ziehau static void nfe_miibus_statchg(device_t); 109ae813fd8SSepherosa Ziehau 110ae813fd8SSepherosa Ziehau #ifdef DEVICE_POLLING 111ae813fd8SSepherosa Ziehau static void nfe_poll(struct ifnet *, enum poll_cmd, int); 112ae813fd8SSepherosa Ziehau #endif 113ae813fd8SSepherosa Ziehau static void nfe_intr(void *); 114ae813fd8SSepherosa Ziehau static int nfe_ioctl(struct ifnet *, u_long, caddr_t, struct ucred *); 11504b9ef8dSSepherosa Ziehau static int nfe_rxeof(struct nfe_softc *); 116d378110eSSepherosa Ziehau static int nfe_txeof(struct nfe_softc *, int); 117ae813fd8SSepherosa Ziehau static int nfe_encap(struct nfe_softc *, struct nfe_tx_ring *, 118ae813fd8SSepherosa Ziehau struct mbuf *); 119ae813fd8SSepherosa Ziehau static void nfe_start(struct ifnet *); 120ae813fd8SSepherosa Ziehau static void nfe_watchdog(struct ifnet *); 121ae813fd8SSepherosa Ziehau static void nfe_init(void *); 122ae813fd8SSepherosa Ziehau static void nfe_stop(struct nfe_softc *); 123ae813fd8SSepherosa Ziehau static struct nfe_jbuf *nfe_jalloc(struct nfe_softc *); 124ae813fd8SSepherosa Ziehau static void nfe_jfree(void *); 125ae813fd8SSepherosa Ziehau static void nfe_jref(void *); 126ae813fd8SSepherosa Ziehau static int nfe_jpool_alloc(struct nfe_softc *, struct nfe_rx_ring *); 127ae813fd8SSepherosa Ziehau static void nfe_jpool_free(struct nfe_softc *, struct nfe_rx_ring *); 128ae813fd8SSepherosa Ziehau static int nfe_alloc_rx_ring(struct nfe_softc *, struct nfe_rx_ring *); 129ae813fd8SSepherosa Ziehau static void nfe_reset_rx_ring(struct nfe_softc *, struct nfe_rx_ring *); 130ae813fd8SSepherosa Ziehau static int nfe_init_rx_ring(struct nfe_softc *, struct nfe_rx_ring *); 131ae813fd8SSepherosa Ziehau static void nfe_free_rx_ring(struct nfe_softc *, struct nfe_rx_ring *); 132ae813fd8SSepherosa Ziehau static int nfe_alloc_tx_ring(struct nfe_softc *, struct nfe_tx_ring *); 133ae813fd8SSepherosa Ziehau static void nfe_reset_tx_ring(struct nfe_softc *, struct nfe_tx_ring *); 134ae813fd8SSepherosa Ziehau static int nfe_init_tx_ring(struct nfe_softc *, struct nfe_tx_ring *); 135ae813fd8SSepherosa Ziehau static void nfe_free_tx_ring(struct nfe_softc *, struct nfe_tx_ring *); 136ae813fd8SSepherosa Ziehau static int nfe_ifmedia_upd(struct ifnet *); 137ae813fd8SSepherosa Ziehau static void nfe_ifmedia_sts(struct ifnet *, struct ifmediareq *); 138ae813fd8SSepherosa Ziehau static void nfe_setmulti(struct nfe_softc *); 139ae813fd8SSepherosa Ziehau static void nfe_get_macaddr(struct nfe_softc *, uint8_t *); 140ae813fd8SSepherosa Ziehau static void nfe_set_macaddr(struct nfe_softc *, const uint8_t *); 141faaea42eSSepherosa Ziehau static void nfe_powerup(device_t); 142faaea42eSSepherosa Ziehau static void nfe_mac_reset(struct nfe_softc *); 143ae813fd8SSepherosa Ziehau static void nfe_tick(void *); 144ae813fd8SSepherosa Ziehau static void nfe_buf_dma_addr(void *, bus_dma_segment_t *, int, bus_size_t, 145ae813fd8SSepherosa Ziehau int); 146ae813fd8SSepherosa Ziehau static void nfe_set_paddr_rxdesc(struct nfe_softc *, struct nfe_rx_ring *, 147ae813fd8SSepherosa Ziehau int, bus_addr_t); 148ae813fd8SSepherosa Ziehau static void nfe_set_ready_rxdesc(struct nfe_softc *, struct nfe_rx_ring *, 149ae813fd8SSepherosa Ziehau int); 150ae813fd8SSepherosa Ziehau static int nfe_newbuf_std(struct nfe_softc *, struct nfe_rx_ring *, int, 151ae813fd8SSepherosa Ziehau int); 152ae813fd8SSepherosa Ziehau static int nfe_newbuf_jumbo(struct nfe_softc *, struct nfe_rx_ring *, int, 153ae813fd8SSepherosa Ziehau int); 15404b9ef8dSSepherosa Ziehau static void nfe_enable_intrs(struct nfe_softc *); 15504b9ef8dSSepherosa Ziehau static void nfe_disable_intrs(struct nfe_softc *); 156ae813fd8SSepherosa Ziehau 157ec9403d0SSepherosa Ziehau static int nfe_sysctl_imtime(SYSCTL_HANDLER_ARGS); 158ec9403d0SSepherosa Ziehau 159ae813fd8SSepherosa Ziehau #define NFE_DEBUG 160ae813fd8SSepherosa Ziehau #ifdef NFE_DEBUG 161ae813fd8SSepherosa Ziehau 162ae813fd8SSepherosa Ziehau static int nfe_debug = 0; 163a455c52eSSepherosa Ziehau static int nfe_rx_ring_count = NFE_RX_RING_DEF_COUNT; 164b4633098SSepherosa Ziehau static int nfe_tx_ring_count = NFE_TX_RING_DEF_COUNT; 165517ed06dSSepherosa Ziehau /* hw timer simulated interrupt moderation @8000Hz */ 166517ed06dSSepherosa Ziehau static int nfe_imtime = -125; 167a455c52eSSepherosa Ziehau 168a455c52eSSepherosa Ziehau TUNABLE_INT("hw.nfe.rx_ring_count", &nfe_rx_ring_count); 169b4633098SSepherosa Ziehau TUNABLE_INT("hw.nfe.tx_ring_count", &nfe_tx_ring_count); 170c4eebf3aSThomas Nikolajsen TUNABLE_INT("hw.nfe.imtimer", &nfe_imtime); 171ec9403d0SSepherosa Ziehau TUNABLE_INT("hw.nfe.debug", &nfe_debug); 172ae813fd8SSepherosa Ziehau 173ae813fd8SSepherosa Ziehau #define DPRINTF(sc, fmt, ...) do { \ 174ec9403d0SSepherosa Ziehau if ((sc)->sc_debug) { \ 175ae813fd8SSepherosa Ziehau if_printf(&(sc)->arpcom.ac_if, \ 176ae813fd8SSepherosa Ziehau fmt, __VA_ARGS__); \ 177ae813fd8SSepherosa Ziehau } \ 178ae813fd8SSepherosa Ziehau } while (0) 179ae813fd8SSepherosa Ziehau 180ae813fd8SSepherosa Ziehau #define DPRINTFN(sc, lv, fmt, ...) do { \ 181ec9403d0SSepherosa Ziehau if ((sc)->sc_debug >= (lv)) { \ 182ae813fd8SSepherosa Ziehau if_printf(&(sc)->arpcom.ac_if, \ 183ae813fd8SSepherosa Ziehau fmt, __VA_ARGS__); \ 184ae813fd8SSepherosa Ziehau } \ 185ae813fd8SSepherosa Ziehau } while (0) 186ae813fd8SSepherosa Ziehau 187ae813fd8SSepherosa Ziehau #else /* !NFE_DEBUG */ 188ae813fd8SSepherosa Ziehau 189ae813fd8SSepherosa Ziehau #define DPRINTF(sc, fmt, ...) 190ae813fd8SSepherosa Ziehau #define DPRINTFN(sc, lv, fmt, ...) 191ae813fd8SSepherosa Ziehau 192ae813fd8SSepherosa Ziehau #endif /* NFE_DEBUG */ 193ae813fd8SSepherosa Ziehau 194ae813fd8SSepherosa Ziehau struct nfe_dma_ctx { 195ae813fd8SSepherosa Ziehau int nsegs; 196ae813fd8SSepherosa Ziehau bus_dma_segment_t *segs; 197ae813fd8SSepherosa Ziehau }; 198ae813fd8SSepherosa Ziehau 199ae813fd8SSepherosa Ziehau static const struct nfe_dev { 200ae813fd8SSepherosa Ziehau uint16_t vid; 201ae813fd8SSepherosa Ziehau uint16_t did; 202ae813fd8SSepherosa Ziehau const char *desc; 203ae813fd8SSepherosa Ziehau } nfe_devices[] = { 204ae813fd8SSepherosa Ziehau { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE_LAN, 20587e3db44SThomas E. Spanjaard "NVIDIA nForce Fast Ethernet" }, 206ae813fd8SSepherosa Ziehau 207ae813fd8SSepherosa Ziehau { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE2_LAN, 20887e3db44SThomas E. Spanjaard "NVIDIA nForce2 Fast Ethernet" }, 209ae813fd8SSepherosa Ziehau 210ae813fd8SSepherosa Ziehau { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE3_LAN1, 211ae813fd8SSepherosa Ziehau "NVIDIA nForce3 Gigabit Ethernet" }, 212ae813fd8SSepherosa Ziehau 21387e3db44SThomas E. Spanjaard /* XXX TGEN the next chip can also be found in the nForce2 Ultra 400Gb 21487e3db44SThomas E. Spanjaard chipset, and possibly also the 400R; it might be both nForce2- and 21587e3db44SThomas E. Spanjaard nForce3-based boards can use the same MCPs (= southbridges) */ 216ae813fd8SSepherosa Ziehau { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE3_LAN2, 217ae813fd8SSepherosa Ziehau "NVIDIA nForce3 Gigabit Ethernet" }, 218ae813fd8SSepherosa Ziehau 219ae813fd8SSepherosa Ziehau { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE3_LAN3, 220ae813fd8SSepherosa Ziehau "NVIDIA nForce3 Gigabit Ethernet" }, 221ae813fd8SSepherosa Ziehau 222ae813fd8SSepherosa Ziehau { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE3_LAN4, 223ae813fd8SSepherosa Ziehau "NVIDIA nForce3 Gigabit Ethernet" }, 224ae813fd8SSepherosa Ziehau 225ae813fd8SSepherosa Ziehau { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_NFORCE3_LAN5, 226ae813fd8SSepherosa Ziehau "NVIDIA nForce3 Gigabit Ethernet" }, 227ae813fd8SSepherosa Ziehau 228ae813fd8SSepherosa Ziehau { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_CK804_LAN1, 229ae813fd8SSepherosa Ziehau "NVIDIA CK804 Gigabit Ethernet" }, 230ae813fd8SSepherosa Ziehau 231ae813fd8SSepherosa Ziehau { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_CK804_LAN2, 232ae813fd8SSepherosa Ziehau "NVIDIA CK804 Gigabit Ethernet" }, 233ae813fd8SSepherosa Ziehau 234ae813fd8SSepherosa Ziehau { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP04_LAN1, 235ae813fd8SSepherosa Ziehau "NVIDIA MCP04 Gigabit Ethernet" }, 236ae813fd8SSepherosa Ziehau 237ae813fd8SSepherosa Ziehau { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP04_LAN2, 238ae813fd8SSepherosa Ziehau "NVIDIA MCP04 Gigabit Ethernet" }, 239ae813fd8SSepherosa Ziehau 240ae813fd8SSepherosa Ziehau { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP51_LAN1, 241ae813fd8SSepherosa Ziehau "NVIDIA MCP51 Gigabit Ethernet" }, 242ae813fd8SSepherosa Ziehau 243ae813fd8SSepherosa Ziehau { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP51_LAN2, 244ae813fd8SSepherosa Ziehau "NVIDIA MCP51 Gigabit Ethernet" }, 245ae813fd8SSepherosa Ziehau 246ae813fd8SSepherosa Ziehau { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP55_LAN1, 247ae813fd8SSepherosa Ziehau "NVIDIA MCP55 Gigabit Ethernet" }, 248ae813fd8SSepherosa Ziehau 249ae813fd8SSepherosa Ziehau { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP55_LAN2, 2509d1ecb21SSepherosa Ziehau "NVIDIA MCP55 Gigabit Ethernet" }, 2519d1ecb21SSepherosa Ziehau 2529d1ecb21SSepherosa Ziehau { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP61_LAN1, 2539d1ecb21SSepherosa Ziehau "NVIDIA MCP61 Gigabit Ethernet" }, 2549d1ecb21SSepherosa Ziehau 2559d1ecb21SSepherosa Ziehau { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP61_LAN2, 2569d1ecb21SSepherosa Ziehau "NVIDIA MCP61 Gigabit Ethernet" }, 2579d1ecb21SSepherosa Ziehau 2589d1ecb21SSepherosa Ziehau { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP61_LAN3, 2599d1ecb21SSepherosa Ziehau "NVIDIA MCP61 Gigabit Ethernet" }, 2609d1ecb21SSepherosa Ziehau 2619d1ecb21SSepherosa Ziehau { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP61_LAN4, 2629d1ecb21SSepherosa Ziehau "NVIDIA MCP61 Gigabit Ethernet" }, 2639d1ecb21SSepherosa Ziehau 2649d1ecb21SSepherosa Ziehau { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP65_LAN1, 2659d1ecb21SSepherosa Ziehau "NVIDIA MCP65 Gigabit Ethernet" }, 2669d1ecb21SSepherosa Ziehau 2679d1ecb21SSepherosa Ziehau { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP65_LAN2, 2689d1ecb21SSepherosa Ziehau "NVIDIA MCP65 Gigabit Ethernet" }, 2699d1ecb21SSepherosa Ziehau 2709d1ecb21SSepherosa Ziehau { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP65_LAN3, 2719d1ecb21SSepherosa Ziehau "NVIDIA MCP65 Gigabit Ethernet" }, 2729d1ecb21SSepherosa Ziehau 2739d1ecb21SSepherosa Ziehau { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP65_LAN4, 274df290cacSSepherosa Ziehau "NVIDIA MCP65 Gigabit Ethernet" }, 275df290cacSSepherosa Ziehau 276df290cacSSepherosa Ziehau { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP67_LAN1, 277df290cacSSepherosa Ziehau "NVIDIA MCP67 Gigabit Ethernet" }, 278df290cacSSepherosa Ziehau 279df290cacSSepherosa Ziehau { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP67_LAN2, 280df290cacSSepherosa Ziehau "NVIDIA MCP67 Gigabit Ethernet" }, 281df290cacSSepherosa Ziehau 282df290cacSSepherosa Ziehau { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP67_LAN3, 283df290cacSSepherosa Ziehau "NVIDIA MCP67 Gigabit Ethernet" }, 284df290cacSSepherosa Ziehau 285df290cacSSepherosa Ziehau { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP67_LAN4, 2861d67eefeSSepherosa Ziehau "NVIDIA MCP67 Gigabit Ethernet" }, 2871d67eefeSSepherosa Ziehau 2881d67eefeSSepherosa Ziehau { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP73_LAN1, 2891d67eefeSSepherosa Ziehau "NVIDIA MCP73 Gigabit Ethernet" }, 2901d67eefeSSepherosa Ziehau 2911d67eefeSSepherosa Ziehau { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP73_LAN2, 2921d67eefeSSepherosa Ziehau "NVIDIA MCP73 Gigabit Ethernet" }, 2931d67eefeSSepherosa Ziehau 2941d67eefeSSepherosa Ziehau { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP73_LAN3, 2951d67eefeSSepherosa Ziehau "NVIDIA MCP73 Gigabit Ethernet" }, 2961d67eefeSSepherosa Ziehau 2971d67eefeSSepherosa Ziehau { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP73_LAN4, 2981d67eefeSSepherosa Ziehau "NVIDIA MCP73 Gigabit Ethernet" }, 2991d67eefeSSepherosa Ziehau 3001d67eefeSSepherosa Ziehau { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP77_LAN1, 3011d67eefeSSepherosa Ziehau "NVIDIA MCP77 Gigabit Ethernet" }, 3021d67eefeSSepherosa Ziehau 3031d67eefeSSepherosa Ziehau { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP77_LAN2, 3041d67eefeSSepherosa Ziehau "NVIDIA MCP77 Gigabit Ethernet" }, 3051d67eefeSSepherosa Ziehau 3061d67eefeSSepherosa Ziehau { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP77_LAN3, 3071d67eefeSSepherosa Ziehau "NVIDIA MCP77 Gigabit Ethernet" }, 3081d67eefeSSepherosa Ziehau 3091d67eefeSSepherosa Ziehau { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP77_LAN4, 3101d67eefeSSepherosa Ziehau "NVIDIA MCP77 Gigabit Ethernet" }, 3111d67eefeSSepherosa Ziehau 3121d67eefeSSepherosa Ziehau { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP79_LAN1, 3131d67eefeSSepherosa Ziehau "NVIDIA MCP79 Gigabit Ethernet" }, 3141d67eefeSSepherosa Ziehau 3151d67eefeSSepherosa Ziehau { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP79_LAN2, 3161d67eefeSSepherosa Ziehau "NVIDIA MCP79 Gigabit Ethernet" }, 3171d67eefeSSepherosa Ziehau 3181d67eefeSSepherosa Ziehau { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP79_LAN3, 3191d67eefeSSepherosa Ziehau "NVIDIA MCP79 Gigabit Ethernet" }, 3201d67eefeSSepherosa Ziehau 3211d67eefeSSepherosa Ziehau { PCI_VENDOR_NVIDIA, PCI_PRODUCT_NVIDIA_MCP79_LAN4, 3221d67eefeSSepherosa Ziehau "NVIDIA MCP79 Gigabit Ethernet" }, 3231d67eefeSSepherosa Ziehau 3241d67eefeSSepherosa Ziehau { 0, 0, NULL } 325ae813fd8SSepherosa Ziehau }; 326ae813fd8SSepherosa Ziehau 327ae813fd8SSepherosa Ziehau static device_method_t nfe_methods[] = { 328ae813fd8SSepherosa Ziehau /* Device interface */ 329ae813fd8SSepherosa Ziehau DEVMETHOD(device_probe, nfe_probe), 330ae813fd8SSepherosa Ziehau DEVMETHOD(device_attach, nfe_attach), 331ae813fd8SSepherosa Ziehau DEVMETHOD(device_detach, nfe_detach), 332ae813fd8SSepherosa Ziehau DEVMETHOD(device_suspend, nfe_suspend), 333ae813fd8SSepherosa Ziehau DEVMETHOD(device_resume, nfe_resume), 334ae813fd8SSepherosa Ziehau DEVMETHOD(device_shutdown, nfe_shutdown), 335ae813fd8SSepherosa Ziehau 336ae813fd8SSepherosa Ziehau /* Bus interface */ 337ae813fd8SSepherosa Ziehau DEVMETHOD(bus_print_child, bus_generic_print_child), 338ae813fd8SSepherosa Ziehau DEVMETHOD(bus_driver_added, bus_generic_driver_added), 339ae813fd8SSepherosa Ziehau 340ae813fd8SSepherosa Ziehau /* MII interface */ 341ae813fd8SSepherosa Ziehau DEVMETHOD(miibus_readreg, nfe_miibus_readreg), 342ae813fd8SSepherosa Ziehau DEVMETHOD(miibus_writereg, nfe_miibus_writereg), 343ae813fd8SSepherosa Ziehau DEVMETHOD(miibus_statchg, nfe_miibus_statchg), 344ae813fd8SSepherosa Ziehau 345ae813fd8SSepherosa Ziehau { 0, 0 } 346ae813fd8SSepherosa Ziehau }; 347ae813fd8SSepherosa Ziehau 348ae813fd8SSepherosa Ziehau static driver_t nfe_driver = { 349ae813fd8SSepherosa Ziehau "nfe", 350ae813fd8SSepherosa Ziehau nfe_methods, 351ae813fd8SSepherosa Ziehau sizeof(struct nfe_softc) 352ae813fd8SSepherosa Ziehau }; 353ae813fd8SSepherosa Ziehau 354ae813fd8SSepherosa Ziehau static devclass_t nfe_devclass; 355ae813fd8SSepherosa Ziehau 356ae813fd8SSepherosa Ziehau DECLARE_DUMMY_MODULE(if_nfe); 357ae813fd8SSepherosa Ziehau MODULE_DEPEND(if_nfe, miibus, 1, 1, 1); 358ae813fd8SSepherosa Ziehau DRIVER_MODULE(if_nfe, pci, nfe_driver, nfe_devclass, 0, 0); 359ae813fd8SSepherosa Ziehau DRIVER_MODULE(miibus, nfe, miibus_driver, miibus_devclass, 0, 0); 360ae813fd8SSepherosa Ziehau 361ae813fd8SSepherosa Ziehau static int 362ae813fd8SSepherosa Ziehau nfe_probe(device_t dev) 363ae813fd8SSepherosa Ziehau { 364ae813fd8SSepherosa Ziehau const struct nfe_dev *n; 365ae813fd8SSepherosa Ziehau uint16_t vid, did; 366ae813fd8SSepherosa Ziehau 367ae813fd8SSepherosa Ziehau vid = pci_get_vendor(dev); 368ae813fd8SSepherosa Ziehau did = pci_get_device(dev); 369ae813fd8SSepherosa Ziehau for (n = nfe_devices; n->desc != NULL; ++n) { 370ae813fd8SSepherosa Ziehau if (vid == n->vid && did == n->did) { 371ae813fd8SSepherosa Ziehau struct nfe_softc *sc = device_get_softc(dev); 372ae813fd8SSepherosa Ziehau 373ae813fd8SSepherosa Ziehau switch (did) { 374f678f57eSSepherosa Ziehau case PCI_PRODUCT_NVIDIA_NFORCE_LAN: 375f678f57eSSepherosa Ziehau case PCI_PRODUCT_NVIDIA_NFORCE2_LAN: 376f678f57eSSepherosa Ziehau case PCI_PRODUCT_NVIDIA_NFORCE3_LAN1: 377ece56005SSepherosa Ziehau sc->sc_caps = NFE_NO_PWRCTL | 378ece56005SSepherosa Ziehau NFE_FIX_EADDR; 379f678f57eSSepherosa Ziehau break; 380ae813fd8SSepherosa Ziehau case PCI_PRODUCT_NVIDIA_NFORCE3_LAN2: 381ae813fd8SSepherosa Ziehau case PCI_PRODUCT_NVIDIA_NFORCE3_LAN3: 382ae813fd8SSepherosa Ziehau case PCI_PRODUCT_NVIDIA_NFORCE3_LAN4: 383ae813fd8SSepherosa Ziehau case PCI_PRODUCT_NVIDIA_NFORCE3_LAN5: 38488d487c3SSepherosa Ziehau sc->sc_caps = NFE_JUMBO_SUP | 385f678f57eSSepherosa Ziehau NFE_HW_CSUM | 386ece56005SSepherosa Ziehau NFE_NO_PWRCTL | 387ece56005SSepherosa Ziehau NFE_FIX_EADDR; 388ae813fd8SSepherosa Ziehau break; 389ae813fd8SSepherosa Ziehau case PCI_PRODUCT_NVIDIA_MCP51_LAN1: 390ae813fd8SSepherosa Ziehau case PCI_PRODUCT_NVIDIA_MCP51_LAN2: 391ece56005SSepherosa Ziehau sc->sc_caps = NFE_FIX_EADDR; 392ece56005SSepherosa Ziehau /* FALL THROUGH */ 3939d1ecb21SSepherosa Ziehau case PCI_PRODUCT_NVIDIA_MCP61_LAN1: 3949d1ecb21SSepherosa Ziehau case PCI_PRODUCT_NVIDIA_MCP61_LAN2: 3959d1ecb21SSepherosa Ziehau case PCI_PRODUCT_NVIDIA_MCP61_LAN3: 3969d1ecb21SSepherosa Ziehau case PCI_PRODUCT_NVIDIA_MCP61_LAN4: 397df290cacSSepherosa Ziehau case PCI_PRODUCT_NVIDIA_MCP67_LAN1: 398df290cacSSepherosa Ziehau case PCI_PRODUCT_NVIDIA_MCP67_LAN2: 399df290cacSSepherosa Ziehau case PCI_PRODUCT_NVIDIA_MCP67_LAN3: 400df290cacSSepherosa Ziehau case PCI_PRODUCT_NVIDIA_MCP67_LAN4: 4011d67eefeSSepherosa Ziehau case PCI_PRODUCT_NVIDIA_MCP73_LAN1: 4021d67eefeSSepherosa Ziehau case PCI_PRODUCT_NVIDIA_MCP73_LAN2: 4031d67eefeSSepherosa Ziehau case PCI_PRODUCT_NVIDIA_MCP73_LAN3: 4041d67eefeSSepherosa Ziehau case PCI_PRODUCT_NVIDIA_MCP73_LAN4: 405ece56005SSepherosa Ziehau sc->sc_caps |= NFE_40BIT_ADDR; 406ae813fd8SSepherosa Ziehau break; 407ae813fd8SSepherosa Ziehau case PCI_PRODUCT_NVIDIA_CK804_LAN1: 408ae813fd8SSepherosa Ziehau case PCI_PRODUCT_NVIDIA_CK804_LAN2: 409ae813fd8SSepherosa Ziehau case PCI_PRODUCT_NVIDIA_MCP04_LAN1: 410ae813fd8SSepherosa Ziehau case PCI_PRODUCT_NVIDIA_MCP04_LAN2: 41188d487c3SSepherosa Ziehau sc->sc_caps = NFE_JUMBO_SUP | 412972538a5SSepherosa Ziehau NFE_40BIT_ADDR | 413f678f57eSSepherosa Ziehau NFE_HW_CSUM | 414ece56005SSepherosa Ziehau NFE_NO_PWRCTL | 415ece56005SSepherosa Ziehau NFE_FIX_EADDR; 416972538a5SSepherosa Ziehau break; 4179d1ecb21SSepherosa Ziehau case PCI_PRODUCT_NVIDIA_MCP65_LAN1: 4189d1ecb21SSepherosa Ziehau case PCI_PRODUCT_NVIDIA_MCP65_LAN2: 4199d1ecb21SSepherosa Ziehau case PCI_PRODUCT_NVIDIA_MCP65_LAN3: 4209d1ecb21SSepherosa Ziehau case PCI_PRODUCT_NVIDIA_MCP65_LAN4: 42188d487c3SSepherosa Ziehau sc->sc_caps = NFE_JUMBO_SUP | 422972538a5SSepherosa Ziehau NFE_40BIT_ADDR; 423ae813fd8SSepherosa Ziehau break; 424ae813fd8SSepherosa Ziehau case PCI_PRODUCT_NVIDIA_MCP55_LAN1: 425ae813fd8SSepherosa Ziehau case PCI_PRODUCT_NVIDIA_MCP55_LAN2: 42688d487c3SSepherosa Ziehau sc->sc_caps = NFE_JUMBO_SUP | 427ae813fd8SSepherosa Ziehau NFE_40BIT_ADDR | 428ae813fd8SSepherosa Ziehau NFE_HW_CSUM | 429ece56005SSepherosa Ziehau NFE_HW_VLAN | 430ece56005SSepherosa Ziehau NFE_FIX_EADDR; 431ae813fd8SSepherosa Ziehau break; 4321d67eefeSSepherosa Ziehau case PCI_PRODUCT_NVIDIA_MCP77_LAN1: 4331d67eefeSSepherosa Ziehau case PCI_PRODUCT_NVIDIA_MCP77_LAN2: 4341d67eefeSSepherosa Ziehau case PCI_PRODUCT_NVIDIA_MCP77_LAN3: 4351d67eefeSSepherosa Ziehau case PCI_PRODUCT_NVIDIA_MCP77_LAN4: 4361d67eefeSSepherosa Ziehau case PCI_PRODUCT_NVIDIA_MCP79_LAN1: 4371d67eefeSSepherosa Ziehau case PCI_PRODUCT_NVIDIA_MCP79_LAN2: 4381d67eefeSSepherosa Ziehau case PCI_PRODUCT_NVIDIA_MCP79_LAN3: 4391d67eefeSSepherosa Ziehau case PCI_PRODUCT_NVIDIA_MCP79_LAN4: 44088d487c3SSepherosa Ziehau sc->sc_caps = NFE_40BIT_ADDR | 4411d67eefeSSepherosa Ziehau NFE_HW_CSUM; 4421d67eefeSSepherosa Ziehau break; 443ae813fd8SSepherosa Ziehau } 444ae813fd8SSepherosa Ziehau 445ae813fd8SSepherosa Ziehau device_set_desc(dev, n->desc); 446dbcd0c9bSMatthew Dillon device_set_async_attach(dev, TRUE); 447ae813fd8SSepherosa Ziehau return 0; 448ae813fd8SSepherosa Ziehau } 449ae813fd8SSepherosa Ziehau } 450ae813fd8SSepherosa Ziehau return ENXIO; 451ae813fd8SSepherosa Ziehau } 452ae813fd8SSepherosa Ziehau 453ae813fd8SSepherosa Ziehau static int 454ae813fd8SSepherosa Ziehau nfe_attach(device_t dev) 455ae813fd8SSepherosa Ziehau { 456ae813fd8SSepherosa Ziehau struct nfe_softc *sc = device_get_softc(dev); 457ae813fd8SSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 458ae813fd8SSepherosa Ziehau uint8_t eaddr[ETHER_ADDR_LEN]; 459244a9aa3SSepherosa Ziehau bus_addr_t lowaddr; 460ae813fd8SSepherosa Ziehau int error; 461ae813fd8SSepherosa Ziehau 462ae813fd8SSepherosa Ziehau if_initname(ifp, device_get_name(dev), device_get_unit(dev)); 463ae813fd8SSepherosa Ziehau lwkt_serialize_init(&sc->sc_jbuf_serializer); 464ae813fd8SSepherosa Ziehau 465ec9403d0SSepherosa Ziehau /* 466ec9403d0SSepherosa Ziehau * Initialize sysctl variables 467ec9403d0SSepherosa Ziehau */ 468ec9403d0SSepherosa Ziehau sc->sc_rx_ring_count = nfe_rx_ring_count; 469b4633098SSepherosa Ziehau sc->sc_tx_ring_count = nfe_tx_ring_count; 470ec9403d0SSepherosa Ziehau sc->sc_debug = nfe_debug; 47104b9ef8dSSepherosa Ziehau if (nfe_imtime < 0) { 47204b9ef8dSSepherosa Ziehau sc->sc_flags |= NFE_F_DYN_IM; 47304b9ef8dSSepherosa Ziehau sc->sc_imtime = -nfe_imtime; 47404b9ef8dSSepherosa Ziehau } else { 47504b9ef8dSSepherosa Ziehau sc->sc_imtime = nfe_imtime; 47604b9ef8dSSepherosa Ziehau } 47704b9ef8dSSepherosa Ziehau sc->sc_irq_enable = NFE_IRQ_ENABLE(sc); 478ec9403d0SSepherosa Ziehau 479ae813fd8SSepherosa Ziehau sc->sc_mem_rid = PCIR_BAR(0); 480ae813fd8SSepherosa Ziehau 48188d487c3SSepherosa Ziehau if (sc->sc_caps & NFE_40BIT_ADDR) 482faaea42eSSepherosa Ziehau sc->rxtxctl_desc = NFE_RXTX_DESC_V3; 48388d487c3SSepherosa Ziehau else if (sc->sc_caps & NFE_JUMBO_SUP) 484faaea42eSSepherosa Ziehau sc->rxtxctl_desc = NFE_RXTX_DESC_V2; 485faaea42eSSepherosa Ziehau 486ae813fd8SSepherosa Ziehau #ifndef BURN_BRIDGES 487ae813fd8SSepherosa Ziehau if (pci_get_powerstate(dev) != PCI_POWERSTATE_D0) { 488ae813fd8SSepherosa Ziehau uint32_t mem, irq; 489ae813fd8SSepherosa Ziehau 490ae813fd8SSepherosa Ziehau mem = pci_read_config(dev, sc->sc_mem_rid, 4); 491ae813fd8SSepherosa Ziehau irq = pci_read_config(dev, PCIR_INTLINE, 4); 492ae813fd8SSepherosa Ziehau 493ae813fd8SSepherosa Ziehau device_printf(dev, "chip is in D%d power mode " 494ae813fd8SSepherosa Ziehau "-- setting to D0\n", pci_get_powerstate(dev)); 495ae813fd8SSepherosa Ziehau 496ae813fd8SSepherosa Ziehau pci_set_powerstate(dev, PCI_POWERSTATE_D0); 497ae813fd8SSepherosa Ziehau 498ae813fd8SSepherosa Ziehau pci_write_config(dev, sc->sc_mem_rid, mem, 4); 499ae813fd8SSepherosa Ziehau pci_write_config(dev, PCIR_INTLINE, irq, 4); 500ae813fd8SSepherosa Ziehau } 501ae813fd8SSepherosa Ziehau #endif /* !BURN_BRIDGE */ 502ae813fd8SSepherosa Ziehau 503ae813fd8SSepherosa Ziehau /* Enable bus mastering */ 504ae813fd8SSepherosa Ziehau pci_enable_busmaster(dev); 505ae813fd8SSepherosa Ziehau 506ae813fd8SSepherosa Ziehau /* Allocate IO memory */ 507ae813fd8SSepherosa Ziehau sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 508ae813fd8SSepherosa Ziehau &sc->sc_mem_rid, RF_ACTIVE); 509ae813fd8SSepherosa Ziehau if (sc->sc_mem_res == NULL) { 510ae813fd8SSepherosa Ziehau device_printf(dev, "cound not allocate io memory\n"); 511ae813fd8SSepherosa Ziehau return ENXIO; 512ae813fd8SSepherosa Ziehau } 513ae813fd8SSepherosa Ziehau sc->sc_memh = rman_get_bushandle(sc->sc_mem_res); 514ae813fd8SSepherosa Ziehau sc->sc_memt = rman_get_bustag(sc->sc_mem_res); 515ae813fd8SSepherosa Ziehau 516ae813fd8SSepherosa Ziehau /* Allocate IRQ */ 517ae813fd8SSepherosa Ziehau sc->sc_irq_rid = 0; 518ae813fd8SSepherosa Ziehau sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, 519ae813fd8SSepherosa Ziehau &sc->sc_irq_rid, 520ae813fd8SSepherosa Ziehau RF_SHAREABLE | RF_ACTIVE); 521ae813fd8SSepherosa Ziehau if (sc->sc_irq_res == NULL) { 522ae813fd8SSepherosa Ziehau device_printf(dev, "could not allocate irq\n"); 523ae813fd8SSepherosa Ziehau error = ENXIO; 524ae813fd8SSepherosa Ziehau goto fail; 525ae813fd8SSepherosa Ziehau } 526ae813fd8SSepherosa Ziehau 527755f8683SSepherosa Ziehau /* Disable WOL */ 528755f8683SSepherosa Ziehau NFE_WRITE(sc, NFE_WOL_CTL, 0); 529755f8683SSepherosa Ziehau 53088d487c3SSepherosa Ziehau if ((sc->sc_caps & NFE_NO_PWRCTL) == 0) 531faaea42eSSepherosa Ziehau nfe_powerup(dev); 532faaea42eSSepherosa Ziehau 533ae813fd8SSepherosa Ziehau nfe_get_macaddr(sc, eaddr); 534ae813fd8SSepherosa Ziehau 535ae813fd8SSepherosa Ziehau /* 536244a9aa3SSepherosa Ziehau * Allocate top level DMA tag 537244a9aa3SSepherosa Ziehau */ 538244a9aa3SSepherosa Ziehau if (sc->sc_caps & NFE_40BIT_ADDR) 539244a9aa3SSepherosa Ziehau lowaddr = NFE_BUS_SPACE_MAXADDR; 540244a9aa3SSepherosa Ziehau else 541244a9aa3SSepherosa Ziehau lowaddr = BUS_SPACE_MAXADDR_32BIT; 542244a9aa3SSepherosa Ziehau error = bus_dma_tag_create(NULL, /* parent */ 543244a9aa3SSepherosa Ziehau 1, 0, /* alignment, boundary */ 544244a9aa3SSepherosa Ziehau lowaddr, /* lowaddr */ 545244a9aa3SSepherosa Ziehau BUS_SPACE_MAXADDR, /* highaddr */ 546244a9aa3SSepherosa Ziehau NULL, NULL, /* filter, filterarg */ 547244a9aa3SSepherosa Ziehau BUS_SPACE_MAXSIZE_32BIT,/* maxsize */ 548244a9aa3SSepherosa Ziehau 0, /* nsegments */ 549244a9aa3SSepherosa Ziehau BUS_SPACE_MAXSIZE_32BIT,/* maxsegsize */ 550244a9aa3SSepherosa Ziehau 0, /* flags */ 551244a9aa3SSepherosa Ziehau &sc->sc_dtag); 552244a9aa3SSepherosa Ziehau if (error) { 553244a9aa3SSepherosa Ziehau device_printf(dev, "could not allocate parent dma tag\n"); 554244a9aa3SSepherosa Ziehau goto fail; 555244a9aa3SSepherosa Ziehau } 556244a9aa3SSepherosa Ziehau 557244a9aa3SSepherosa Ziehau /* 558ae813fd8SSepherosa Ziehau * Allocate Tx and Rx rings. 559ae813fd8SSepherosa Ziehau */ 560ae813fd8SSepherosa Ziehau error = nfe_alloc_tx_ring(sc, &sc->txq); 561ae813fd8SSepherosa Ziehau if (error) { 562ae813fd8SSepherosa Ziehau device_printf(dev, "could not allocate Tx ring\n"); 563ae813fd8SSepherosa Ziehau goto fail; 564ae813fd8SSepherosa Ziehau } 565ae813fd8SSepherosa Ziehau 566ae813fd8SSepherosa Ziehau error = nfe_alloc_rx_ring(sc, &sc->rxq); 567ae813fd8SSepherosa Ziehau if (error) { 568ae813fd8SSepherosa Ziehau device_printf(dev, "could not allocate Rx ring\n"); 569ae813fd8SSepherosa Ziehau goto fail; 570ae813fd8SSepherosa Ziehau } 571ae813fd8SSepherosa Ziehau 572ec9403d0SSepherosa Ziehau /* 573ec9403d0SSepherosa Ziehau * Create sysctl tree 574ec9403d0SSepherosa Ziehau */ 575ec9403d0SSepherosa Ziehau sysctl_ctx_init(&sc->sc_sysctl_ctx); 576ec9403d0SSepherosa Ziehau sc->sc_sysctl_tree = SYSCTL_ADD_NODE(&sc->sc_sysctl_ctx, 577ec9403d0SSepherosa Ziehau SYSCTL_STATIC_CHILDREN(_hw), 578ec9403d0SSepherosa Ziehau OID_AUTO, 579ec9403d0SSepherosa Ziehau device_get_nameunit(dev), 580ec9403d0SSepherosa Ziehau CTLFLAG_RD, 0, ""); 581ec9403d0SSepherosa Ziehau if (sc->sc_sysctl_tree == NULL) { 582ec9403d0SSepherosa Ziehau device_printf(dev, "can't add sysctl node\n"); 583ec9403d0SSepherosa Ziehau error = ENXIO; 584ec9403d0SSepherosa Ziehau goto fail; 585ec9403d0SSepherosa Ziehau } 586ec9403d0SSepherosa Ziehau SYSCTL_ADD_PROC(&sc->sc_sysctl_ctx, 587ec9403d0SSepherosa Ziehau SYSCTL_CHILDREN(sc->sc_sysctl_tree), 588ec9403d0SSepherosa Ziehau OID_AUTO, "imtimer", CTLTYPE_INT | CTLFLAG_RW, 589ec9403d0SSepherosa Ziehau sc, 0, nfe_sysctl_imtime, "I", 590ec9403d0SSepherosa Ziehau "Interrupt moderation time (usec). " 59104b9ef8dSSepherosa Ziehau "0 to disable interrupt moderation."); 59256fa71a9SSepherosa Ziehau SYSCTL_ADD_INT(&sc->sc_sysctl_ctx, 59356fa71a9SSepherosa Ziehau SYSCTL_CHILDREN(sc->sc_sysctl_tree), OID_AUTO, 594ec9403d0SSepherosa Ziehau "rx_ring_count", CTLFLAG_RD, &sc->sc_rx_ring_count, 595ec9403d0SSepherosa Ziehau 0, "RX ring count"); 59656fa71a9SSepherosa Ziehau SYSCTL_ADD_INT(&sc->sc_sysctl_ctx, 59756fa71a9SSepherosa Ziehau SYSCTL_CHILDREN(sc->sc_sysctl_tree), OID_AUTO, 598b4633098SSepherosa Ziehau "tx_ring_count", CTLFLAG_RD, &sc->sc_tx_ring_count, 599b4633098SSepherosa Ziehau 0, "TX ring count"); 600b4633098SSepherosa Ziehau SYSCTL_ADD_INT(&sc->sc_sysctl_ctx, 601b4633098SSepherosa Ziehau SYSCTL_CHILDREN(sc->sc_sysctl_tree), OID_AUTO, 602ec9403d0SSepherosa Ziehau "debug", CTLFLAG_RW, &sc->sc_debug, 603ec9403d0SSepherosa Ziehau 0, "control debugging printfs"); 604ec9403d0SSepherosa Ziehau 605ae813fd8SSepherosa Ziehau error = mii_phy_probe(dev, &sc->sc_miibus, nfe_ifmedia_upd, 606ae813fd8SSepherosa Ziehau nfe_ifmedia_sts); 607ae813fd8SSepherosa Ziehau if (error) { 608ae813fd8SSepherosa Ziehau device_printf(dev, "MII without any phy\n"); 609ae813fd8SSepherosa Ziehau goto fail; 610ae813fd8SSepherosa Ziehau } 611ae813fd8SSepherosa Ziehau 612ae813fd8SSepherosa Ziehau ifp->if_softc = sc; 613ae813fd8SSepherosa Ziehau ifp->if_mtu = ETHERMTU; 614ae813fd8SSepherosa Ziehau ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 615ae813fd8SSepherosa Ziehau ifp->if_ioctl = nfe_ioctl; 616ae813fd8SSepherosa Ziehau ifp->if_start = nfe_start; 617ae813fd8SSepherosa Ziehau #ifdef DEVICE_POLLING 618ae813fd8SSepherosa Ziehau ifp->if_poll = nfe_poll; 619ae813fd8SSepherosa Ziehau #endif 620ae813fd8SSepherosa Ziehau ifp->if_watchdog = nfe_watchdog; 621ae813fd8SSepherosa Ziehau ifp->if_init = nfe_init; 622d378110eSSepherosa Ziehau ifq_set_maxlen(&ifp->if_snd, sc->sc_tx_ring_count); 623ae813fd8SSepherosa Ziehau ifq_set_ready(&ifp->if_snd); 624ae813fd8SSepherosa Ziehau 625ae813fd8SSepherosa Ziehau ifp->if_capabilities = IFCAP_VLAN_MTU; 626ae813fd8SSepherosa Ziehau 62788d487c3SSepherosa Ziehau if (sc->sc_caps & NFE_HW_VLAN) 628ae813fd8SSepherosa Ziehau ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING; 629ae813fd8SSepherosa Ziehau 630ae813fd8SSepherosa Ziehau #ifdef NFE_CSUM 63188d487c3SSepherosa Ziehau if (sc->sc_caps & NFE_HW_CSUM) { 63211db6c57SSepherosa Ziehau ifp->if_capabilities |= IFCAP_HWCSUM; 63311db6c57SSepherosa Ziehau ifp->if_hwassist = NFE_CSUM_FEATURES; 634ae813fd8SSepherosa Ziehau } 63511db6c57SSepherosa Ziehau #else 63688d487c3SSepherosa Ziehau sc->sc_caps &= ~NFE_HW_CSUM; 637ae813fd8SSepherosa Ziehau #endif 638ae813fd8SSepherosa Ziehau ifp->if_capenable = ifp->if_capabilities; 639ae813fd8SSepherosa Ziehau 640ae813fd8SSepherosa Ziehau callout_init(&sc->sc_tick_ch); 641ae813fd8SSepherosa Ziehau 642ae813fd8SSepherosa Ziehau ether_ifattach(ifp, eaddr, NULL); 643ae813fd8SSepherosa Ziehau 644ae813fd8SSepherosa Ziehau error = bus_setup_intr(dev, sc->sc_irq_res, INTR_MPSAFE, nfe_intr, sc, 645ae813fd8SSepherosa Ziehau &sc->sc_ih, ifp->if_serializer); 646ae813fd8SSepherosa Ziehau if (error) { 647ae813fd8SSepherosa Ziehau device_printf(dev, "could not setup intr\n"); 648ae813fd8SSepherosa Ziehau ether_ifdetach(ifp); 649ae813fd8SSepherosa Ziehau goto fail; 650ae813fd8SSepherosa Ziehau } 651ae813fd8SSepherosa Ziehau 6529db4b353SSepherosa Ziehau ifp->if_cpuid = ithread_cpuid(rman_get_start(sc->sc_irq_res)); 6539db4b353SSepherosa Ziehau KKASSERT(ifp->if_cpuid >= 0 && ifp->if_cpuid < ncpus); 6549db4b353SSepherosa Ziehau 655ae813fd8SSepherosa Ziehau return 0; 656ae813fd8SSepherosa Ziehau fail: 657ae813fd8SSepherosa Ziehau nfe_detach(dev); 658ae813fd8SSepherosa Ziehau return error; 659ae813fd8SSepherosa Ziehau } 660ae813fd8SSepherosa Ziehau 661ae813fd8SSepherosa Ziehau static int 662ae813fd8SSepherosa Ziehau nfe_detach(device_t dev) 663ae813fd8SSepherosa Ziehau { 664ae813fd8SSepherosa Ziehau struct nfe_softc *sc = device_get_softc(dev); 665ae813fd8SSepherosa Ziehau 666ae813fd8SSepherosa Ziehau if (device_is_attached(dev)) { 667ae813fd8SSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 668ae813fd8SSepherosa Ziehau 669ae813fd8SSepherosa Ziehau lwkt_serialize_enter(ifp->if_serializer); 670ae813fd8SSepherosa Ziehau nfe_stop(sc); 671ae813fd8SSepherosa Ziehau bus_teardown_intr(dev, sc->sc_irq_res, sc->sc_ih); 672ae813fd8SSepherosa Ziehau lwkt_serialize_exit(ifp->if_serializer); 673ae813fd8SSepherosa Ziehau 674ae813fd8SSepherosa Ziehau ether_ifdetach(ifp); 675ae813fd8SSepherosa Ziehau } 676ae813fd8SSepherosa Ziehau 677ae813fd8SSepherosa Ziehau if (sc->sc_miibus != NULL) 678ae813fd8SSepherosa Ziehau device_delete_child(dev, sc->sc_miibus); 679ae813fd8SSepherosa Ziehau bus_generic_detach(dev); 680ae813fd8SSepherosa Ziehau 681ec9403d0SSepherosa Ziehau if (sc->sc_sysctl_tree != NULL) 682ec9403d0SSepherosa Ziehau sysctl_ctx_free(&sc->sc_sysctl_ctx); 683ec9403d0SSepherosa Ziehau 684ae813fd8SSepherosa Ziehau if (sc->sc_irq_res != NULL) { 685ae813fd8SSepherosa Ziehau bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irq_rid, 686ae813fd8SSepherosa Ziehau sc->sc_irq_res); 687ae813fd8SSepherosa Ziehau } 688ae813fd8SSepherosa Ziehau 689ae813fd8SSepherosa Ziehau if (sc->sc_mem_res != NULL) { 690ae813fd8SSepherosa Ziehau bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_mem_rid, 691ae813fd8SSepherosa Ziehau sc->sc_mem_res); 692ae813fd8SSepherosa Ziehau } 693ae813fd8SSepherosa Ziehau 694ae813fd8SSepherosa Ziehau nfe_free_tx_ring(sc, &sc->txq); 695ae813fd8SSepherosa Ziehau nfe_free_rx_ring(sc, &sc->rxq); 696244a9aa3SSepherosa Ziehau if (sc->sc_dtag != NULL) 697244a9aa3SSepherosa Ziehau bus_dma_tag_destroy(sc->sc_dtag); 698ae813fd8SSepherosa Ziehau 699ae813fd8SSepherosa Ziehau return 0; 700ae813fd8SSepherosa Ziehau } 701ae813fd8SSepherosa Ziehau 702ae813fd8SSepherosa Ziehau static void 703ae813fd8SSepherosa Ziehau nfe_shutdown(device_t dev) 704ae813fd8SSepherosa Ziehau { 705ae813fd8SSepherosa Ziehau struct nfe_softc *sc = device_get_softc(dev); 706ae813fd8SSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 707ae813fd8SSepherosa Ziehau 708ae813fd8SSepherosa Ziehau lwkt_serialize_enter(ifp->if_serializer); 709ae813fd8SSepherosa Ziehau nfe_stop(sc); 710ae813fd8SSepherosa Ziehau lwkt_serialize_exit(ifp->if_serializer); 711ae813fd8SSepherosa Ziehau } 712ae813fd8SSepherosa Ziehau 713ae813fd8SSepherosa Ziehau static int 714ae813fd8SSepherosa Ziehau nfe_suspend(device_t dev) 715ae813fd8SSepherosa Ziehau { 716ae813fd8SSepherosa Ziehau struct nfe_softc *sc = device_get_softc(dev); 717ae813fd8SSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 718ae813fd8SSepherosa Ziehau 719ae813fd8SSepherosa Ziehau lwkt_serialize_enter(ifp->if_serializer); 720ae813fd8SSepherosa Ziehau nfe_stop(sc); 721ae813fd8SSepherosa Ziehau lwkt_serialize_exit(ifp->if_serializer); 722ae813fd8SSepherosa Ziehau 723ae813fd8SSepherosa Ziehau return 0; 724ae813fd8SSepherosa Ziehau } 725ae813fd8SSepherosa Ziehau 726ae813fd8SSepherosa Ziehau static int 727ae813fd8SSepherosa Ziehau nfe_resume(device_t dev) 728ae813fd8SSepherosa Ziehau { 729ae813fd8SSepherosa Ziehau struct nfe_softc *sc = device_get_softc(dev); 730ae813fd8SSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 731ae813fd8SSepherosa Ziehau 732ae813fd8SSepherosa Ziehau lwkt_serialize_enter(ifp->if_serializer); 733751890abSMatthew Dillon if (ifp->if_flags & IFF_UP) 7343ffca68aSSepherosa Ziehau nfe_init(sc); 735ae813fd8SSepherosa Ziehau lwkt_serialize_exit(ifp->if_serializer); 736ae813fd8SSepherosa Ziehau 737ae813fd8SSepherosa Ziehau return 0; 738ae813fd8SSepherosa Ziehau } 739ae813fd8SSepherosa Ziehau 740ae813fd8SSepherosa Ziehau static void 741ae813fd8SSepherosa Ziehau nfe_miibus_statchg(device_t dev) 742ae813fd8SSepherosa Ziehau { 743ae813fd8SSepherosa Ziehau struct nfe_softc *sc = device_get_softc(dev); 744ae813fd8SSepherosa Ziehau struct mii_data *mii = device_get_softc(sc->sc_miibus); 745ae813fd8SSepherosa Ziehau uint32_t phy, seed, misc = NFE_MISC1_MAGIC, link = NFE_MEDIA_SET; 746ae813fd8SSepherosa Ziehau 747c0dcc88eSSepherosa Ziehau ASSERT_SERIALIZED(sc->arpcom.ac_if.if_serializer); 748c0dcc88eSSepherosa Ziehau 749ae813fd8SSepherosa Ziehau phy = NFE_READ(sc, NFE_PHY_IFACE); 750ae813fd8SSepherosa Ziehau phy &= ~(NFE_PHY_HDX | NFE_PHY_100TX | NFE_PHY_1000T); 751ae813fd8SSepherosa Ziehau 752ae813fd8SSepherosa Ziehau seed = NFE_READ(sc, NFE_RNDSEED); 753ae813fd8SSepherosa Ziehau seed &= ~NFE_SEED_MASK; 754ae813fd8SSepherosa Ziehau 755ae813fd8SSepherosa Ziehau if ((mii->mii_media_active & IFM_GMASK) == IFM_HDX) { 756ae813fd8SSepherosa Ziehau phy |= NFE_PHY_HDX; /* half-duplex */ 757ae813fd8SSepherosa Ziehau misc |= NFE_MISC1_HDX; 758ae813fd8SSepherosa Ziehau } 759ae813fd8SSepherosa Ziehau 760ae813fd8SSepherosa Ziehau switch (IFM_SUBTYPE(mii->mii_media_active)) { 761ae813fd8SSepherosa Ziehau case IFM_1000_T: /* full-duplex only */ 762ae813fd8SSepherosa Ziehau link |= NFE_MEDIA_1000T; 763ae813fd8SSepherosa Ziehau seed |= NFE_SEED_1000T; 764ae813fd8SSepherosa Ziehau phy |= NFE_PHY_1000T; 765ae813fd8SSepherosa Ziehau break; 766ae813fd8SSepherosa Ziehau case IFM_100_TX: 767ae813fd8SSepherosa Ziehau link |= NFE_MEDIA_100TX; 768ae813fd8SSepherosa Ziehau seed |= NFE_SEED_100TX; 769ae813fd8SSepherosa Ziehau phy |= NFE_PHY_100TX; 770ae813fd8SSepherosa Ziehau break; 771ae813fd8SSepherosa Ziehau case IFM_10_T: 772ae813fd8SSepherosa Ziehau link |= NFE_MEDIA_10T; 773ae813fd8SSepherosa Ziehau seed |= NFE_SEED_10T; 774ae813fd8SSepherosa Ziehau break; 775ae813fd8SSepherosa Ziehau } 776ae813fd8SSepherosa Ziehau 777ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_RNDSEED, seed); /* XXX: gigabit NICs only? */ 778ae813fd8SSepherosa Ziehau 779ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_PHY_IFACE, phy); 780ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_MISC1, misc); 781ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_LINKSPEED, link); 782ae813fd8SSepherosa Ziehau } 783ae813fd8SSepherosa Ziehau 784ae813fd8SSepherosa Ziehau static int 785ae813fd8SSepherosa Ziehau nfe_miibus_readreg(device_t dev, int phy, int reg) 786ae813fd8SSepherosa Ziehau { 787ae813fd8SSepherosa Ziehau struct nfe_softc *sc = device_get_softc(dev); 788ae813fd8SSepherosa Ziehau uint32_t val; 789ae813fd8SSepherosa Ziehau int ntries; 790ae813fd8SSepherosa Ziehau 791ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_PHY_STATUS, 0xf); 792ae813fd8SSepherosa Ziehau 793ae813fd8SSepherosa Ziehau if (NFE_READ(sc, NFE_PHY_CTL) & NFE_PHY_BUSY) { 794ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_PHY_CTL, NFE_PHY_BUSY); 795ae813fd8SSepherosa Ziehau DELAY(100); 796ae813fd8SSepherosa Ziehau } 797ae813fd8SSepherosa Ziehau 798ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_PHY_CTL, (phy << NFE_PHYADD_SHIFT) | reg); 799ae813fd8SSepherosa Ziehau 800ae813fd8SSepherosa Ziehau for (ntries = 0; ntries < 1000; ntries++) { 801ae813fd8SSepherosa Ziehau DELAY(100); 802ae813fd8SSepherosa Ziehau if (!(NFE_READ(sc, NFE_PHY_CTL) & NFE_PHY_BUSY)) 803ae813fd8SSepherosa Ziehau break; 804ae813fd8SSepherosa Ziehau } 805ae813fd8SSepherosa Ziehau if (ntries == 1000) { 806ae813fd8SSepherosa Ziehau DPRINTFN(sc, 2, "timeout waiting for PHY %s\n", ""); 807ae813fd8SSepherosa Ziehau return 0; 808ae813fd8SSepherosa Ziehau } 809ae813fd8SSepherosa Ziehau 810ae813fd8SSepherosa Ziehau if (NFE_READ(sc, NFE_PHY_STATUS) & NFE_PHY_ERROR) { 811ae813fd8SSepherosa Ziehau DPRINTFN(sc, 2, "could not read PHY %s\n", ""); 812ae813fd8SSepherosa Ziehau return 0; 813ae813fd8SSepherosa Ziehau } 814ae813fd8SSepherosa Ziehau 815ae813fd8SSepherosa Ziehau val = NFE_READ(sc, NFE_PHY_DATA); 816ae813fd8SSepherosa Ziehau if (val != 0xffffffff && val != 0) 817ae813fd8SSepherosa Ziehau sc->mii_phyaddr = phy; 818ae813fd8SSepherosa Ziehau 819ae813fd8SSepherosa Ziehau DPRINTFN(sc, 2, "mii read phy %d reg 0x%x ret 0x%x\n", phy, reg, val); 820ae813fd8SSepherosa Ziehau 821ae813fd8SSepherosa Ziehau return val; 822ae813fd8SSepherosa Ziehau } 823ae813fd8SSepherosa Ziehau 824ae813fd8SSepherosa Ziehau static void 825ae813fd8SSepherosa Ziehau nfe_miibus_writereg(device_t dev, int phy, int reg, int val) 826ae813fd8SSepherosa Ziehau { 827ae813fd8SSepherosa Ziehau struct nfe_softc *sc = device_get_softc(dev); 828ae813fd8SSepherosa Ziehau uint32_t ctl; 829ae813fd8SSepherosa Ziehau int ntries; 830ae813fd8SSepherosa Ziehau 831ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_PHY_STATUS, 0xf); 832ae813fd8SSepherosa Ziehau 833ae813fd8SSepherosa Ziehau if (NFE_READ(sc, NFE_PHY_CTL) & NFE_PHY_BUSY) { 834ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_PHY_CTL, NFE_PHY_BUSY); 835ae813fd8SSepherosa Ziehau DELAY(100); 836ae813fd8SSepherosa Ziehau } 837ae813fd8SSepherosa Ziehau 838ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_PHY_DATA, val); 839ae813fd8SSepherosa Ziehau ctl = NFE_PHY_WRITE | (phy << NFE_PHYADD_SHIFT) | reg; 840ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_PHY_CTL, ctl); 841ae813fd8SSepherosa Ziehau 842ae813fd8SSepherosa Ziehau for (ntries = 0; ntries < 1000; ntries++) { 843ae813fd8SSepherosa Ziehau DELAY(100); 844ae813fd8SSepherosa Ziehau if (!(NFE_READ(sc, NFE_PHY_CTL) & NFE_PHY_BUSY)) 845ae813fd8SSepherosa Ziehau break; 846ae813fd8SSepherosa Ziehau } 847ae813fd8SSepherosa Ziehau 848ae813fd8SSepherosa Ziehau #ifdef NFE_DEBUG 849ae813fd8SSepherosa Ziehau if (ntries == 1000) 850ae813fd8SSepherosa Ziehau DPRINTFN(sc, 2, "could not write to PHY %s\n", ""); 851ae813fd8SSepherosa Ziehau #endif 852ae813fd8SSepherosa Ziehau } 853ae813fd8SSepherosa Ziehau 854ae813fd8SSepherosa Ziehau #ifdef DEVICE_POLLING 855ae813fd8SSepherosa Ziehau 856ae813fd8SSepherosa Ziehau static void 857ae813fd8SSepherosa Ziehau nfe_poll(struct ifnet *ifp, enum poll_cmd cmd, int count) 858ae813fd8SSepherosa Ziehau { 859ae813fd8SSepherosa Ziehau struct nfe_softc *sc = ifp->if_softc; 860ae813fd8SSepherosa Ziehau 861ec9403d0SSepherosa Ziehau ASSERT_SERIALIZED(ifp->if_serializer); 862ec9403d0SSepherosa Ziehau 863ae813fd8SSepherosa Ziehau switch(cmd) { 864ae813fd8SSepherosa Ziehau case POLL_REGISTER: 86504b9ef8dSSepherosa Ziehau nfe_disable_intrs(sc); 866ae813fd8SSepherosa Ziehau break; 86704b9ef8dSSepherosa Ziehau 868ae813fd8SSepherosa Ziehau case POLL_DEREGISTER: 86904b9ef8dSSepherosa Ziehau nfe_enable_intrs(sc); 870ae813fd8SSepherosa Ziehau break; 87104b9ef8dSSepherosa Ziehau 872ae813fd8SSepherosa Ziehau case POLL_AND_CHECK_STATUS: 873ae813fd8SSepherosa Ziehau /* fall through */ 874ae813fd8SSepherosa Ziehau case POLL_ONLY: 875ae813fd8SSepherosa Ziehau if (ifp->if_flags & IFF_RUNNING) { 876ae813fd8SSepherosa Ziehau nfe_rxeof(sc); 877d378110eSSepherosa Ziehau nfe_txeof(sc, 1); 878ae813fd8SSepherosa Ziehau } 879ae813fd8SSepherosa Ziehau break; 880ae813fd8SSepherosa Ziehau } 881ae813fd8SSepherosa Ziehau } 882ae813fd8SSepherosa Ziehau 883ae813fd8SSepherosa Ziehau #endif 884ae813fd8SSepherosa Ziehau 885ae813fd8SSepherosa Ziehau static void 886ae813fd8SSepherosa Ziehau nfe_intr(void *arg) 887ae813fd8SSepherosa Ziehau { 888ae813fd8SSepherosa Ziehau struct nfe_softc *sc = arg; 889ae813fd8SSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 890ae813fd8SSepherosa Ziehau uint32_t r; 891ae813fd8SSepherosa Ziehau 892ae813fd8SSepherosa Ziehau r = NFE_READ(sc, NFE_IRQ_STATUS); 893ae813fd8SSepherosa Ziehau if (r == 0) 894ae813fd8SSepherosa Ziehau return; /* not for us */ 895ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_IRQ_STATUS, r); 896ae813fd8SSepherosa Ziehau 897ae813fd8SSepherosa Ziehau DPRINTFN(sc, 5, "%s: interrupt register %x\n", __func__, r); 898ae813fd8SSepherosa Ziehau 899ae813fd8SSepherosa Ziehau if (r & NFE_IRQ_LINK) { 900ae813fd8SSepherosa Ziehau NFE_READ(sc, NFE_PHY_STATUS); 901ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_PHY_STATUS, 0xf); 902ae813fd8SSepherosa Ziehau DPRINTF(sc, "link state changed %s\n", ""); 903ae813fd8SSepherosa Ziehau } 904ae813fd8SSepherosa Ziehau 905ae813fd8SSepherosa Ziehau if (ifp->if_flags & IFF_RUNNING) { 90604b9ef8dSSepherosa Ziehau int ret; 90704b9ef8dSSepherosa Ziehau 908ae813fd8SSepherosa Ziehau /* check Rx ring */ 90904b9ef8dSSepherosa Ziehau ret = nfe_rxeof(sc); 910ae813fd8SSepherosa Ziehau 911ae813fd8SSepherosa Ziehau /* check Tx ring */ 912d378110eSSepherosa Ziehau ret |= nfe_txeof(sc, 1); 91304b9ef8dSSepherosa Ziehau 91404b9ef8dSSepherosa Ziehau if (sc->sc_flags & NFE_F_DYN_IM) { 91504b9ef8dSSepherosa Ziehau if (ret && (sc->sc_flags & NFE_F_IRQ_TIMER) == 0) { 91604b9ef8dSSepherosa Ziehau /* 91704b9ef8dSSepherosa Ziehau * Assume that using hardware timer could reduce 91804b9ef8dSSepherosa Ziehau * the interrupt rate. 91904b9ef8dSSepherosa Ziehau */ 92004b9ef8dSSepherosa Ziehau NFE_WRITE(sc, NFE_IRQ_MASK, NFE_IRQ_IMTIMER); 92104b9ef8dSSepherosa Ziehau sc->sc_flags |= NFE_F_IRQ_TIMER; 92204b9ef8dSSepherosa Ziehau } else if (!ret && (sc->sc_flags & NFE_F_IRQ_TIMER)) { 92304b9ef8dSSepherosa Ziehau /* 92404b9ef8dSSepherosa Ziehau * Nothing needs to be processed, fall back to 92504b9ef8dSSepherosa Ziehau * use TX/RX interrupts. 92604b9ef8dSSepherosa Ziehau */ 92704b9ef8dSSepherosa Ziehau NFE_WRITE(sc, NFE_IRQ_MASK, NFE_IRQ_NOIMTIMER); 92804b9ef8dSSepherosa Ziehau sc->sc_flags &= ~NFE_F_IRQ_TIMER; 92946d50f4bSSepherosa Ziehau 93046d50f4bSSepherosa Ziehau /* 93146d50f4bSSepherosa Ziehau * Recollect, mainly to avoid the possible race 93246d50f4bSSepherosa Ziehau * introduced by changing interrupt masks. 93346d50f4bSSepherosa Ziehau */ 93446d50f4bSSepherosa Ziehau nfe_rxeof(sc); 93546d50f4bSSepherosa Ziehau nfe_txeof(sc, 1); 93604b9ef8dSSepherosa Ziehau } 93704b9ef8dSSepherosa Ziehau } 938ae813fd8SSepherosa Ziehau } 939ae813fd8SSepherosa Ziehau } 940ae813fd8SSepherosa Ziehau 941ae813fd8SSepherosa Ziehau static int 942ae813fd8SSepherosa Ziehau nfe_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data, struct ucred *cr) 943ae813fd8SSepherosa Ziehau { 944ae813fd8SSepherosa Ziehau struct nfe_softc *sc = ifp->if_softc; 945ae813fd8SSepherosa Ziehau struct ifreq *ifr = (struct ifreq *)data; 946ae813fd8SSepherosa Ziehau struct mii_data *mii; 94756fa71a9SSepherosa Ziehau int error = 0, mask, jumbo_cap; 948ae813fd8SSepherosa Ziehau 949c0dcc88eSSepherosa Ziehau ASSERT_SERIALIZED(ifp->if_serializer); 950c0dcc88eSSepherosa Ziehau 951ae813fd8SSepherosa Ziehau switch (cmd) { 952ae813fd8SSepherosa Ziehau case SIOCSIFMTU: 95356fa71a9SSepherosa Ziehau if ((sc->sc_caps & NFE_JUMBO_SUP) && sc->rxq.jbuf != NULL) 95456fa71a9SSepherosa Ziehau jumbo_cap = 1; 95556fa71a9SSepherosa Ziehau else 95656fa71a9SSepherosa Ziehau jumbo_cap = 0; 95756fa71a9SSepherosa Ziehau 95856fa71a9SSepherosa Ziehau if ((jumbo_cap && ifr->ifr_mtu > NFE_JUMBO_MTU) || 95956fa71a9SSepherosa Ziehau (!jumbo_cap && ifr->ifr_mtu > ETHERMTU)) { 960a455c52eSSepherosa Ziehau return EINVAL; 961a455c52eSSepherosa Ziehau } else if (ifp->if_mtu != ifr->ifr_mtu) { 962a455c52eSSepherosa Ziehau ifp->if_mtu = ifr->ifr_mtu; 96356fa71a9SSepherosa Ziehau if (ifp->if_flags & IFF_RUNNING) 964a455c52eSSepherosa Ziehau nfe_init(sc); 965a455c52eSSepherosa Ziehau } 966ae813fd8SSepherosa Ziehau break; 967ae813fd8SSepherosa Ziehau case SIOCSIFFLAGS: 968ae813fd8SSepherosa Ziehau if (ifp->if_flags & IFF_UP) { 969ae813fd8SSepherosa Ziehau /* 970ae813fd8SSepherosa Ziehau * If only the PROMISC or ALLMULTI flag changes, then 971ae813fd8SSepherosa Ziehau * don't do a full re-init of the chip, just update 972ae813fd8SSepherosa Ziehau * the Rx filter. 973ae813fd8SSepherosa Ziehau */ 974ae813fd8SSepherosa Ziehau if ((ifp->if_flags & IFF_RUNNING) && 975ae813fd8SSepherosa Ziehau ((ifp->if_flags ^ sc->sc_if_flags) & 976ae813fd8SSepherosa Ziehau (IFF_ALLMULTI | IFF_PROMISC)) != 0) { 977ae813fd8SSepherosa Ziehau nfe_setmulti(sc); 978ae813fd8SSepherosa Ziehau } else { 979ae813fd8SSepherosa Ziehau if (!(ifp->if_flags & IFF_RUNNING)) 980ae813fd8SSepherosa Ziehau nfe_init(sc); 981ae813fd8SSepherosa Ziehau } 982ae813fd8SSepherosa Ziehau } else { 983ae813fd8SSepherosa Ziehau if (ifp->if_flags & IFF_RUNNING) 984ae813fd8SSepherosa Ziehau nfe_stop(sc); 985ae813fd8SSepherosa Ziehau } 986ae813fd8SSepherosa Ziehau sc->sc_if_flags = ifp->if_flags; 987ae813fd8SSepherosa Ziehau break; 988ae813fd8SSepherosa Ziehau case SIOCADDMULTI: 989ae813fd8SSepherosa Ziehau case SIOCDELMULTI: 990ae813fd8SSepherosa Ziehau if (ifp->if_flags & IFF_RUNNING) 991ae813fd8SSepherosa Ziehau nfe_setmulti(sc); 992ae813fd8SSepherosa Ziehau break; 993ae813fd8SSepherosa Ziehau case SIOCSIFMEDIA: 994ae813fd8SSepherosa Ziehau case SIOCGIFMEDIA: 995ae813fd8SSepherosa Ziehau mii = device_get_softc(sc->sc_miibus); 996ae813fd8SSepherosa Ziehau error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, cmd); 997ae813fd8SSepherosa Ziehau break; 998ae813fd8SSepherosa Ziehau case SIOCSIFCAP: 999bf2a5992SSepherosa Ziehau mask = (ifr->ifr_reqcap ^ ifp->if_capenable) & IFCAP_HWCSUM; 1000bf2a5992SSepherosa Ziehau if (mask && (ifp->if_capabilities & IFCAP_HWCSUM)) { 1001bf2a5992SSepherosa Ziehau ifp->if_capenable ^= mask; 1002bf2a5992SSepherosa Ziehau if (IFCAP_TXCSUM & ifp->if_capenable) 100311db6c57SSepherosa Ziehau ifp->if_hwassist = NFE_CSUM_FEATURES; 1004bf2a5992SSepherosa Ziehau else 1005bf2a5992SSepherosa Ziehau ifp->if_hwassist = 0; 100611db6c57SSepherosa Ziehau 100711db6c57SSepherosa Ziehau if (ifp->if_flags & IFF_RUNNING) 100811db6c57SSepherosa Ziehau nfe_init(sc); 1009ae813fd8SSepherosa Ziehau } 1010ae813fd8SSepherosa Ziehau break; 1011ae813fd8SSepherosa Ziehau default: 1012ae813fd8SSepherosa Ziehau error = ether_ioctl(ifp, cmd, data); 1013ae813fd8SSepherosa Ziehau break; 1014ae813fd8SSepherosa Ziehau } 1015ae813fd8SSepherosa Ziehau return error; 1016ae813fd8SSepherosa Ziehau } 1017ae813fd8SSepherosa Ziehau 101804b9ef8dSSepherosa Ziehau static int 1019ae813fd8SSepherosa Ziehau nfe_rxeof(struct nfe_softc *sc) 1020ae813fd8SSepherosa Ziehau { 1021ae813fd8SSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 1022ae813fd8SSepherosa Ziehau struct nfe_rx_ring *ring = &sc->rxq; 1023ae813fd8SSepherosa Ziehau int reap; 10241bf7e051SSepherosa Ziehau struct mbuf_chain chain[MAXCPU]; 1025ae813fd8SSepherosa Ziehau 1026ae813fd8SSepherosa Ziehau reap = 0; 1027ae813fd8SSepherosa Ziehau bus_dmamap_sync(ring->tag, ring->map, BUS_DMASYNC_POSTREAD); 1028ae813fd8SSepherosa Ziehau 10291bf7e051SSepherosa Ziehau ether_input_chain_init(chain); 10301bf7e051SSepherosa Ziehau 1031ae813fd8SSepherosa Ziehau for (;;) { 1032ae813fd8SSepherosa Ziehau struct nfe_rx_data *data = &ring->data[ring->cur]; 1033ae813fd8SSepherosa Ziehau struct mbuf *m; 1034ae813fd8SSepherosa Ziehau uint16_t flags; 1035ae813fd8SSepherosa Ziehau int len, error; 1036ae813fd8SSepherosa Ziehau 103788d487c3SSepherosa Ziehau if (sc->sc_caps & NFE_40BIT_ADDR) { 1038ae813fd8SSepherosa Ziehau struct nfe_desc64 *desc64 = &ring->desc64[ring->cur]; 1039ae813fd8SSepherosa Ziehau 1040ae813fd8SSepherosa Ziehau flags = le16toh(desc64->flags); 1041ae813fd8SSepherosa Ziehau len = le16toh(desc64->length) & 0x3fff; 1042ae813fd8SSepherosa Ziehau } else { 1043ae813fd8SSepherosa Ziehau struct nfe_desc32 *desc32 = &ring->desc32[ring->cur]; 1044ae813fd8SSepherosa Ziehau 1045ae813fd8SSepherosa Ziehau flags = le16toh(desc32->flags); 1046ae813fd8SSepherosa Ziehau len = le16toh(desc32->length) & 0x3fff; 1047ae813fd8SSepherosa Ziehau } 1048ae813fd8SSepherosa Ziehau 1049ae813fd8SSepherosa Ziehau if (flags & NFE_RX_READY) 1050ae813fd8SSepherosa Ziehau break; 1051ae813fd8SSepherosa Ziehau 1052ae813fd8SSepherosa Ziehau reap = 1; 1053ae813fd8SSepherosa Ziehau 105488d487c3SSepherosa Ziehau if ((sc->sc_caps & (NFE_JUMBO_SUP | NFE_40BIT_ADDR)) == 0) { 1055ae813fd8SSepherosa Ziehau if (!(flags & NFE_RX_VALID_V1)) 1056ae813fd8SSepherosa Ziehau goto skip; 1057ae813fd8SSepherosa Ziehau 1058ae813fd8SSepherosa Ziehau if ((flags & NFE_RX_FIXME_V1) == NFE_RX_FIXME_V1) { 1059ae813fd8SSepherosa Ziehau flags &= ~NFE_RX_ERROR; 1060ae813fd8SSepherosa Ziehau len--; /* fix buffer length */ 1061ae813fd8SSepherosa Ziehau } 1062ae813fd8SSepherosa Ziehau } else { 1063ae813fd8SSepherosa Ziehau if (!(flags & NFE_RX_VALID_V2)) 1064ae813fd8SSepherosa Ziehau goto skip; 1065ae813fd8SSepherosa Ziehau 1066ae813fd8SSepherosa Ziehau if ((flags & NFE_RX_FIXME_V2) == NFE_RX_FIXME_V2) { 1067ae813fd8SSepherosa Ziehau flags &= ~NFE_RX_ERROR; 1068ae813fd8SSepherosa Ziehau len--; /* fix buffer length */ 1069ae813fd8SSepherosa Ziehau } 1070ae813fd8SSepherosa Ziehau } 1071ae813fd8SSepherosa Ziehau 1072ae813fd8SSepherosa Ziehau if (flags & NFE_RX_ERROR) { 1073ae813fd8SSepherosa Ziehau ifp->if_ierrors++; 1074ae813fd8SSepherosa Ziehau goto skip; 1075ae813fd8SSepherosa Ziehau } 1076ae813fd8SSepherosa Ziehau 1077ae813fd8SSepherosa Ziehau m = data->m; 1078ae813fd8SSepherosa Ziehau 10795dc1e30eSSepherosa Ziehau if (sc->sc_flags & NFE_F_USE_JUMBO) 1080ae813fd8SSepherosa Ziehau error = nfe_newbuf_jumbo(sc, ring, ring->cur, 0); 1081ae813fd8SSepherosa Ziehau else 1082ae813fd8SSepherosa Ziehau error = nfe_newbuf_std(sc, ring, ring->cur, 0); 1083ae813fd8SSepherosa Ziehau if (error) { 1084ae813fd8SSepherosa Ziehau ifp->if_ierrors++; 1085ae813fd8SSepherosa Ziehau goto skip; 1086ae813fd8SSepherosa Ziehau } 1087ae813fd8SSepherosa Ziehau 1088ae813fd8SSepherosa Ziehau /* finalize mbuf */ 1089ae813fd8SSepherosa Ziehau m->m_pkthdr.len = m->m_len = len; 1090ae813fd8SSepherosa Ziehau m->m_pkthdr.rcvif = ifp; 1091ae813fd8SSepherosa Ziehau 1092bf2a5992SSepherosa Ziehau if ((ifp->if_capenable & IFCAP_RXCSUM) && 109311db6c57SSepherosa Ziehau (flags & NFE_RX_CSUMOK)) { 10948b712a27SSepherosa Ziehau if (flags & NFE_RX_IP_CSUMOK_V2) { 10958b712a27SSepherosa Ziehau m->m_pkthdr.csum_flags |= CSUM_IP_CHECKED | 10968b712a27SSepherosa Ziehau CSUM_IP_VALID; 10978b712a27SSepherosa Ziehau } 109811db6c57SSepherosa Ziehau 109911db6c57SSepherosa Ziehau if (flags & 110011db6c57SSepherosa Ziehau (NFE_RX_UDP_CSUMOK_V2 | NFE_RX_TCP_CSUMOK_V2)) { 110111db6c57SSepherosa Ziehau m->m_pkthdr.csum_flags |= CSUM_DATA_VALID | 1102fbb35ef0SSepherosa Ziehau CSUM_PSEUDO_HDR | 1103fbb35ef0SSepherosa Ziehau CSUM_FRAG_NOT_CHECKED; 110411db6c57SSepherosa Ziehau m->m_pkthdr.csum_data = 0xffff; 1105ae813fd8SSepherosa Ziehau } 110611db6c57SSepherosa Ziehau } 1107ae813fd8SSepherosa Ziehau 1108ae813fd8SSepherosa Ziehau ifp->if_ipackets++; 110950098e2eSSepherosa Ziehau ether_input_chain(ifp, m, chain); 1110ae813fd8SSepherosa Ziehau skip: 1111ae813fd8SSepherosa Ziehau nfe_set_ready_rxdesc(sc, ring, ring->cur); 1112ec9403d0SSepherosa Ziehau sc->rxq.cur = (sc->rxq.cur + 1) % sc->sc_rx_ring_count; 1113ae813fd8SSepherosa Ziehau } 1114ae813fd8SSepherosa Ziehau 11151bf7e051SSepherosa Ziehau if (reap) { 1116ae813fd8SSepherosa Ziehau bus_dmamap_sync(ring->tag, ring->map, BUS_DMASYNC_PREWRITE); 11171bf7e051SSepherosa Ziehau ether_input_dispatch(chain); 11181bf7e051SSepherosa Ziehau } 111904b9ef8dSSepherosa Ziehau return reap; 1120ae813fd8SSepherosa Ziehau } 1121ae813fd8SSepherosa Ziehau 112204b9ef8dSSepherosa Ziehau static int 1123d378110eSSepherosa Ziehau nfe_txeof(struct nfe_softc *sc, int start) 1124ae813fd8SSepherosa Ziehau { 1125ae813fd8SSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 1126ae813fd8SSepherosa Ziehau struct nfe_tx_ring *ring = &sc->txq; 1127ae813fd8SSepherosa Ziehau struct nfe_tx_data *data = NULL; 1128ae813fd8SSepherosa Ziehau 1129ae813fd8SSepherosa Ziehau bus_dmamap_sync(ring->tag, ring->map, BUS_DMASYNC_POSTREAD); 1130ae813fd8SSepherosa Ziehau while (ring->next != ring->cur) { 1131ae813fd8SSepherosa Ziehau uint16_t flags; 1132ae813fd8SSepherosa Ziehau 113388d487c3SSepherosa Ziehau if (sc->sc_caps & NFE_40BIT_ADDR) 1134ae813fd8SSepherosa Ziehau flags = le16toh(ring->desc64[ring->next].flags); 1135ae813fd8SSepherosa Ziehau else 1136ae813fd8SSepherosa Ziehau flags = le16toh(ring->desc32[ring->next].flags); 1137ae813fd8SSepherosa Ziehau 1138ae813fd8SSepherosa Ziehau if (flags & NFE_TX_VALID) 1139ae813fd8SSepherosa Ziehau break; 1140ae813fd8SSepherosa Ziehau 1141ae813fd8SSepherosa Ziehau data = &ring->data[ring->next]; 1142ae813fd8SSepherosa Ziehau 114388d487c3SSepherosa Ziehau if ((sc->sc_caps & (NFE_JUMBO_SUP | NFE_40BIT_ADDR)) == 0) { 1144ae813fd8SSepherosa Ziehau if (!(flags & NFE_TX_LASTFRAG_V1) && data->m == NULL) 1145ae813fd8SSepherosa Ziehau goto skip; 1146ae813fd8SSepherosa Ziehau 1147ae813fd8SSepherosa Ziehau if ((flags & NFE_TX_ERROR_V1) != 0) { 1148ae813fd8SSepherosa Ziehau if_printf(ifp, "tx v1 error 0x%4b\n", flags, 1149ae813fd8SSepherosa Ziehau NFE_V1_TXERR); 1150ae813fd8SSepherosa Ziehau ifp->if_oerrors++; 1151ae813fd8SSepherosa Ziehau } else { 1152ae813fd8SSepherosa Ziehau ifp->if_opackets++; 1153ae813fd8SSepherosa Ziehau } 1154ae813fd8SSepherosa Ziehau } else { 1155ae813fd8SSepherosa Ziehau if (!(flags & NFE_TX_LASTFRAG_V2) && data->m == NULL) 1156ae813fd8SSepherosa Ziehau goto skip; 1157ae813fd8SSepherosa Ziehau 1158ae813fd8SSepherosa Ziehau if ((flags & NFE_TX_ERROR_V2) != 0) { 1159ae813fd8SSepherosa Ziehau if_printf(ifp, "tx v2 error 0x%4b\n", flags, 1160ae813fd8SSepherosa Ziehau NFE_V2_TXERR); 1161ae813fd8SSepherosa Ziehau ifp->if_oerrors++; 1162ae813fd8SSepherosa Ziehau } else { 1163ae813fd8SSepherosa Ziehau ifp->if_opackets++; 1164ae813fd8SSepherosa Ziehau } 1165ae813fd8SSepherosa Ziehau } 1166ae813fd8SSepherosa Ziehau 1167ae813fd8SSepherosa Ziehau if (data->m == NULL) { /* should not get there */ 1168ae813fd8SSepherosa Ziehau if_printf(ifp, 1169ae813fd8SSepherosa Ziehau "last fragment bit w/o associated mbuf!\n"); 1170ae813fd8SSepherosa Ziehau goto skip; 1171ae813fd8SSepherosa Ziehau } 1172ae813fd8SSepherosa Ziehau 1173ae813fd8SSepherosa Ziehau /* last fragment of the mbuf chain transmitted */ 1174ae813fd8SSepherosa Ziehau bus_dmamap_unload(ring->data_tag, data->map); 1175ae813fd8SSepherosa Ziehau m_freem(data->m); 1176ae813fd8SSepherosa Ziehau data->m = NULL; 1177ae813fd8SSepherosa Ziehau skip: 1178ae813fd8SSepherosa Ziehau ring->queued--; 1179ae813fd8SSepherosa Ziehau KKASSERT(ring->queued >= 0); 1180b4633098SSepherosa Ziehau ring->next = (ring->next + 1) % sc->sc_tx_ring_count; 1181ae813fd8SSepherosa Ziehau } 1182ae813fd8SSepherosa Ziehau 1183d378110eSSepherosa Ziehau if (sc->sc_tx_ring_count - ring->queued >= 1184d378110eSSepherosa Ziehau sc->sc_tx_spare + NFE_NSEG_RSVD) 1185ae813fd8SSepherosa Ziehau ifp->if_flags &= ~IFF_OACTIVE; 1186d378110eSSepherosa Ziehau 1187d378110eSSepherosa Ziehau if (ring->queued == 0) 1188d378110eSSepherosa Ziehau ifp->if_timer = 0; 1189d378110eSSepherosa Ziehau 1190d378110eSSepherosa Ziehau if (start && !ifq_is_empty(&ifp->if_snd)) 11919db4b353SSepherosa Ziehau if_devstart(ifp); 1192d378110eSSepherosa Ziehau 1193d378110eSSepherosa Ziehau if (data != NULL) 119404b9ef8dSSepherosa Ziehau return 1; 1195d378110eSSepherosa Ziehau else 119604b9ef8dSSepherosa Ziehau return 0; 1197ae813fd8SSepherosa Ziehau } 1198ae813fd8SSepherosa Ziehau 1199ae813fd8SSepherosa Ziehau static int 1200ae813fd8SSepherosa Ziehau nfe_encap(struct nfe_softc *sc, struct nfe_tx_ring *ring, struct mbuf *m0) 1201ae813fd8SSepherosa Ziehau { 1202ae813fd8SSepherosa Ziehau struct nfe_dma_ctx ctx; 1203ae813fd8SSepherosa Ziehau bus_dma_segment_t segs[NFE_MAX_SCATTER]; 1204ae813fd8SSepherosa Ziehau struct nfe_tx_data *data, *data_map; 1205ae813fd8SSepherosa Ziehau bus_dmamap_t map; 1206ae813fd8SSepherosa Ziehau struct nfe_desc64 *desc64 = NULL; 1207ae813fd8SSepherosa Ziehau struct nfe_desc32 *desc32 = NULL; 1208ae813fd8SSepherosa Ziehau uint16_t flags = 0; 1209ae813fd8SSepherosa Ziehau uint32_t vtag = 0; 1210d378110eSSepherosa Ziehau int error, i, j, maxsegs; 1211ae813fd8SSepherosa Ziehau 1212ae813fd8SSepherosa Ziehau data = &ring->data[ring->cur]; 1213ae813fd8SSepherosa Ziehau map = data->map; 1214ae813fd8SSepherosa Ziehau data_map = data; /* Remember who owns the DMA map */ 1215ae813fd8SSepherosa Ziehau 1216d378110eSSepherosa Ziehau maxsegs = (sc->sc_tx_ring_count - ring->queued) - NFE_NSEG_RSVD; 1217d378110eSSepherosa Ziehau if (maxsegs > NFE_MAX_SCATTER) 1218d378110eSSepherosa Ziehau maxsegs = NFE_MAX_SCATTER; 1219d378110eSSepherosa Ziehau KASSERT(maxsegs >= sc->sc_tx_spare, 1220d378110eSSepherosa Ziehau ("no enough segments %d,%d\n", maxsegs, sc->sc_tx_spare)); 1221d378110eSSepherosa Ziehau 1222d378110eSSepherosa Ziehau ctx.nsegs = maxsegs; 1223ae813fd8SSepherosa Ziehau ctx.segs = segs; 1224ae813fd8SSepherosa Ziehau error = bus_dmamap_load_mbuf(ring->data_tag, map, m0, 1225ae813fd8SSepherosa Ziehau nfe_buf_dma_addr, &ctx, BUS_DMA_NOWAIT); 122677cdd7f0SSepherosa Ziehau if (!error && ctx.nsegs == 0) { 122777cdd7f0SSepherosa Ziehau bus_dmamap_unload(ring->data_tag, map); 122877cdd7f0SSepherosa Ziehau error = EFBIG; 122977cdd7f0SSepherosa Ziehau } 1230e679c149SSepherosa Ziehau if (error && error != EFBIG) 1231ae813fd8SSepherosa Ziehau goto back; 1232ae813fd8SSepherosa Ziehau if (error) { /* error == EFBIG */ 1233ae813fd8SSepherosa Ziehau struct mbuf *m_new; 1234ae813fd8SSepherosa Ziehau 1235ae813fd8SSepherosa Ziehau m_new = m_defrag(m0, MB_DONTWAIT); 1236ae813fd8SSepherosa Ziehau if (m_new == NULL) { 1237ae813fd8SSepherosa Ziehau error = ENOBUFS; 1238ae813fd8SSepherosa Ziehau goto back; 1239ae813fd8SSepherosa Ziehau } else { 1240ae813fd8SSepherosa Ziehau m0 = m_new; 1241ae813fd8SSepherosa Ziehau } 1242ae813fd8SSepherosa Ziehau 1243d378110eSSepherosa Ziehau ctx.nsegs = maxsegs; 1244ae813fd8SSepherosa Ziehau ctx.segs = segs; 1245ae813fd8SSepherosa Ziehau error = bus_dmamap_load_mbuf(ring->data_tag, map, m0, 1246ae813fd8SSepherosa Ziehau nfe_buf_dma_addr, &ctx, 1247ae813fd8SSepherosa Ziehau BUS_DMA_NOWAIT); 124877cdd7f0SSepherosa Ziehau if (error || ctx.nsegs == 0) { 124977cdd7f0SSepherosa Ziehau if (!error) { 125077cdd7f0SSepherosa Ziehau bus_dmamap_unload(ring->data_tag, map); 125177cdd7f0SSepherosa Ziehau error = EFBIG; 125277cdd7f0SSepherosa Ziehau } 1253ae813fd8SSepherosa Ziehau goto back; 1254ae813fd8SSepherosa Ziehau } 1255ae813fd8SSepherosa Ziehau } 1256e679c149SSepherosa Ziehau bus_dmamap_sync(ring->data_tag, map, BUS_DMASYNC_PREWRITE); 1257ae813fd8SSepherosa Ziehau 1258ae813fd8SSepherosa Ziehau error = 0; 1259ae813fd8SSepherosa Ziehau 1260ae813fd8SSepherosa Ziehau /* setup h/w VLAN tagging */ 126183790f85SSepherosa Ziehau if (m0->m_flags & M_VLANTAG) 126283790f85SSepherosa Ziehau vtag = m0->m_pkthdr.ether_vlantag; 1263ae813fd8SSepherosa Ziehau 1264bf2a5992SSepherosa Ziehau if (sc->arpcom.ac_if.if_capenable & IFCAP_TXCSUM) { 126511db6c57SSepherosa Ziehau if (m0->m_pkthdr.csum_flags & CSUM_IP) 1266ae813fd8SSepherosa Ziehau flags |= NFE_TX_IP_CSUM; 126711db6c57SSepherosa Ziehau if (m0->m_pkthdr.csum_flags & (CSUM_TCP | CSUM_UDP)) 1268ae813fd8SSepherosa Ziehau flags |= NFE_TX_TCP_CSUM; 126911db6c57SSepherosa Ziehau } 1270ae813fd8SSepherosa Ziehau 1271ae813fd8SSepherosa Ziehau /* 1272ae813fd8SSepherosa Ziehau * XXX urm. somebody is unaware of how hardware works. You 1273ae813fd8SSepherosa Ziehau * absolutely CANNOT set NFE_TX_VALID on the next descriptor in 1274ae813fd8SSepherosa Ziehau * the ring until the entire chain is actually *VALID*. Otherwise 1275ae813fd8SSepherosa Ziehau * the hardware may encounter a partially initialized chain that 1276ae813fd8SSepherosa Ziehau * is marked as being ready to go when it in fact is not ready to 1277ae813fd8SSepherosa Ziehau * go. 1278ae813fd8SSepherosa Ziehau */ 1279ae813fd8SSepherosa Ziehau 1280ae813fd8SSepherosa Ziehau for (i = 0; i < ctx.nsegs; i++) { 1281b4633098SSepherosa Ziehau j = (ring->cur + i) % sc->sc_tx_ring_count; 1282ae813fd8SSepherosa Ziehau data = &ring->data[j]; 1283ae813fd8SSepherosa Ziehau 128488d487c3SSepherosa Ziehau if (sc->sc_caps & NFE_40BIT_ADDR) { 1285ae813fd8SSepherosa Ziehau desc64 = &ring->desc64[j]; 1286ae813fd8SSepherosa Ziehau desc64->physaddr[0] = 12877752918dSSepherosa Ziehau htole32(NFE_ADDR_HI(segs[i].ds_addr)); 1288ae813fd8SSepherosa Ziehau desc64->physaddr[1] = 12897752918dSSepherosa Ziehau htole32(NFE_ADDR_LO(segs[i].ds_addr)); 1290ae813fd8SSepherosa Ziehau desc64->length = htole16(segs[i].ds_len - 1); 1291ae813fd8SSepherosa Ziehau desc64->vtag = htole32(vtag); 1292ae813fd8SSepherosa Ziehau desc64->flags = htole16(flags); 1293ae813fd8SSepherosa Ziehau } else { 1294ae813fd8SSepherosa Ziehau desc32 = &ring->desc32[j]; 1295ae813fd8SSepherosa Ziehau desc32->physaddr = htole32(segs[i].ds_addr); 1296ae813fd8SSepherosa Ziehau desc32->length = htole16(segs[i].ds_len - 1); 1297ae813fd8SSepherosa Ziehau desc32->flags = htole16(flags); 1298ae813fd8SSepherosa Ziehau } 1299ae813fd8SSepherosa Ziehau 1300ae813fd8SSepherosa Ziehau /* csum flags and vtag belong to the first fragment only */ 1301ae813fd8SSepherosa Ziehau flags &= ~(NFE_TX_IP_CSUM | NFE_TX_TCP_CSUM); 1302ae813fd8SSepherosa Ziehau vtag = 0; 1303ae813fd8SSepherosa Ziehau 1304ae813fd8SSepherosa Ziehau ring->queued++; 1305b4633098SSepherosa Ziehau KKASSERT(ring->queued <= sc->sc_tx_ring_count); 1306ae813fd8SSepherosa Ziehau } 1307ae813fd8SSepherosa Ziehau 1308ae813fd8SSepherosa Ziehau /* the whole mbuf chain has been DMA mapped, fix last descriptor */ 130988d487c3SSepherosa Ziehau if (sc->sc_caps & NFE_40BIT_ADDR) { 1310ae813fd8SSepherosa Ziehau desc64->flags |= htole16(NFE_TX_LASTFRAG_V2); 1311ae813fd8SSepherosa Ziehau } else { 131288d487c3SSepherosa Ziehau if (sc->sc_caps & NFE_JUMBO_SUP) 1313ae813fd8SSepherosa Ziehau flags = NFE_TX_LASTFRAG_V2; 1314ae813fd8SSepherosa Ziehau else 1315ae813fd8SSepherosa Ziehau flags = NFE_TX_LASTFRAG_V1; 1316ae813fd8SSepherosa Ziehau desc32->flags |= htole16(flags); 1317ae813fd8SSepherosa Ziehau } 1318ae813fd8SSepherosa Ziehau 1319ae813fd8SSepherosa Ziehau /* 1320ae813fd8SSepherosa Ziehau * Set NFE_TX_VALID backwards so the hardware doesn't see the 1321ae813fd8SSepherosa Ziehau * whole mess until the first descriptor in the map is flagged. 1322ae813fd8SSepherosa Ziehau */ 1323ae813fd8SSepherosa Ziehau for (i = ctx.nsegs - 1; i >= 0; --i) { 1324b4633098SSepherosa Ziehau j = (ring->cur + i) % sc->sc_tx_ring_count; 132588d487c3SSepherosa Ziehau if (sc->sc_caps & NFE_40BIT_ADDR) { 1326ae813fd8SSepherosa Ziehau desc64 = &ring->desc64[j]; 1327ae813fd8SSepherosa Ziehau desc64->flags |= htole16(NFE_TX_VALID); 1328ae813fd8SSepherosa Ziehau } else { 1329ae813fd8SSepherosa Ziehau desc32 = &ring->desc32[j]; 1330ae813fd8SSepherosa Ziehau desc32->flags |= htole16(NFE_TX_VALID); 1331ae813fd8SSepherosa Ziehau } 1332ae813fd8SSepherosa Ziehau } 1333b4633098SSepherosa Ziehau ring->cur = (ring->cur + ctx.nsegs) % sc->sc_tx_ring_count; 1334ae813fd8SSepherosa Ziehau 1335ae813fd8SSepherosa Ziehau /* Exchange DMA map */ 1336ae813fd8SSepherosa Ziehau data_map->map = data->map; 1337ae813fd8SSepherosa Ziehau data->map = map; 1338ae813fd8SSepherosa Ziehau data->m = m0; 1339ae813fd8SSepherosa Ziehau back: 1340ae813fd8SSepherosa Ziehau if (error) 1341ae813fd8SSepherosa Ziehau m_freem(m0); 1342ae813fd8SSepherosa Ziehau return error; 1343ae813fd8SSepherosa Ziehau } 1344ae813fd8SSepherosa Ziehau 1345ae813fd8SSepherosa Ziehau static void 1346ae813fd8SSepherosa Ziehau nfe_start(struct ifnet *ifp) 1347ae813fd8SSepherosa Ziehau { 1348ae813fd8SSepherosa Ziehau struct nfe_softc *sc = ifp->if_softc; 1349ae813fd8SSepherosa Ziehau struct nfe_tx_ring *ring = &sc->txq; 1350d378110eSSepherosa Ziehau int count = 0, oactive = 0; 1351ae813fd8SSepherosa Ziehau struct mbuf *m0; 1352ae813fd8SSepherosa Ziehau 1353c0dcc88eSSepherosa Ziehau ASSERT_SERIALIZED(ifp->if_serializer); 1354c0dcc88eSSepherosa Ziehau 13559db4b353SSepherosa Ziehau if ((ifp->if_flags & (IFF_OACTIVE | IFF_RUNNING)) != IFF_RUNNING) 1356ae813fd8SSepherosa Ziehau return; 1357ae813fd8SSepherosa Ziehau 1358ae813fd8SSepherosa Ziehau for (;;) { 1359d378110eSSepherosa Ziehau int error; 1360d378110eSSepherosa Ziehau 1361d378110eSSepherosa Ziehau if (sc->sc_tx_ring_count - ring->queued < 1362d378110eSSepherosa Ziehau sc->sc_tx_spare + NFE_NSEG_RSVD) { 1363d378110eSSepherosa Ziehau if (oactive) { 1364d378110eSSepherosa Ziehau ifp->if_flags |= IFF_OACTIVE; 1365d378110eSSepherosa Ziehau break; 1366d378110eSSepherosa Ziehau } 1367d378110eSSepherosa Ziehau 1368d378110eSSepherosa Ziehau nfe_txeof(sc, 0); 1369d378110eSSepherosa Ziehau oactive = 1; 1370d378110eSSepherosa Ziehau continue; 1371d378110eSSepherosa Ziehau } 1372d378110eSSepherosa Ziehau 1373ae813fd8SSepherosa Ziehau m0 = ifq_dequeue(&ifp->if_snd, NULL); 1374ae813fd8SSepherosa Ziehau if (m0 == NULL) 1375ae813fd8SSepherosa Ziehau break; 1376ae813fd8SSepherosa Ziehau 1377b637f170SSepherosa Ziehau ETHER_BPF_MTAP(ifp, m0); 1378ae813fd8SSepherosa Ziehau 1379d378110eSSepherosa Ziehau error = nfe_encap(sc, ring, m0); 1380d378110eSSepherosa Ziehau if (error) { 1381d378110eSSepherosa Ziehau ifp->if_oerrors++; 1382d378110eSSepherosa Ziehau if (error == EFBIG) { 1383d378110eSSepherosa Ziehau if (oactive) { 1384ae813fd8SSepherosa Ziehau ifp->if_flags |= IFF_OACTIVE; 1385ae813fd8SSepherosa Ziehau break; 1386ae813fd8SSepherosa Ziehau } 1387d378110eSSepherosa Ziehau nfe_txeof(sc, 0); 1388d378110eSSepherosa Ziehau oactive = 1; 1389d378110eSSepherosa Ziehau } 1390d378110eSSepherosa Ziehau continue; 1391d378110eSSepherosa Ziehau } else { 1392d378110eSSepherosa Ziehau oactive = 0; 1393d378110eSSepherosa Ziehau } 1394ae813fd8SSepherosa Ziehau ++count; 1395ae813fd8SSepherosa Ziehau 1396ae813fd8SSepherosa Ziehau /* 1397ae813fd8SSepherosa Ziehau * NOTE: 1398ae813fd8SSepherosa Ziehau * `m0' may be freed in nfe_encap(), so 1399ae813fd8SSepherosa Ziehau * it should not be touched any more. 1400ae813fd8SSepherosa Ziehau */ 1401ae813fd8SSepherosa Ziehau } 1402ae813fd8SSepherosa Ziehau if (count == 0) /* nothing sent */ 1403ae813fd8SSepherosa Ziehau return; 1404ae813fd8SSepherosa Ziehau 1405ae813fd8SSepherosa Ziehau /* Sync TX descriptor ring */ 1406ae813fd8SSepherosa Ziehau bus_dmamap_sync(ring->tag, ring->map, BUS_DMASYNC_PREWRITE); 1407ae813fd8SSepherosa Ziehau 1408ae813fd8SSepherosa Ziehau /* Kick Tx */ 1409ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_RXTX_CTL, NFE_RXTX_KICKTX | sc->rxtxctl); 1410ae813fd8SSepherosa Ziehau 1411ae813fd8SSepherosa Ziehau /* 1412ae813fd8SSepherosa Ziehau * Set a timeout in case the chip goes out to lunch. 1413ae813fd8SSepherosa Ziehau */ 1414ae813fd8SSepherosa Ziehau ifp->if_timer = 5; 1415ae813fd8SSepherosa Ziehau } 1416ae813fd8SSepherosa Ziehau 1417ae813fd8SSepherosa Ziehau static void 1418ae813fd8SSepherosa Ziehau nfe_watchdog(struct ifnet *ifp) 1419ae813fd8SSepherosa Ziehau { 1420ae813fd8SSepherosa Ziehau struct nfe_softc *sc = ifp->if_softc; 1421ae813fd8SSepherosa Ziehau 1422c0dcc88eSSepherosa Ziehau ASSERT_SERIALIZED(ifp->if_serializer); 1423c0dcc88eSSepherosa Ziehau 1424ae813fd8SSepherosa Ziehau if (ifp->if_flags & IFF_RUNNING) { 1425ae813fd8SSepherosa Ziehau if_printf(ifp, "watchdog timeout - lost interrupt recovered\n"); 1426d378110eSSepherosa Ziehau nfe_txeof(sc, 1); 1427ae813fd8SSepherosa Ziehau return; 1428ae813fd8SSepherosa Ziehau } 1429ae813fd8SSepherosa Ziehau 1430ae813fd8SSepherosa Ziehau if_printf(ifp, "watchdog timeout\n"); 1431ae813fd8SSepherosa Ziehau 1432ae813fd8SSepherosa Ziehau nfe_init(ifp->if_softc); 1433ae813fd8SSepherosa Ziehau 1434ae813fd8SSepherosa Ziehau ifp->if_oerrors++; 1435ae813fd8SSepherosa Ziehau } 1436ae813fd8SSepherosa Ziehau 1437ae813fd8SSepherosa Ziehau static void 1438ae813fd8SSepherosa Ziehau nfe_init(void *xsc) 1439ae813fd8SSepherosa Ziehau { 1440ae813fd8SSepherosa Ziehau struct nfe_softc *sc = xsc; 1441ae813fd8SSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 1442ae813fd8SSepherosa Ziehau uint32_t tmp; 1443ae813fd8SSepherosa Ziehau int error; 1444ae813fd8SSepherosa Ziehau 1445c0dcc88eSSepherosa Ziehau ASSERT_SERIALIZED(ifp->if_serializer); 1446c0dcc88eSSepherosa Ziehau 1447ae813fd8SSepherosa Ziehau nfe_stop(sc); 1448ae813fd8SSepherosa Ziehau 144988d487c3SSepherosa Ziehau if ((sc->sc_caps & NFE_NO_PWRCTL) == 0) 1450faaea42eSSepherosa Ziehau nfe_mac_reset(sc); 1451faaea42eSSepherosa Ziehau 1452a455c52eSSepherosa Ziehau /* 1453a455c52eSSepherosa Ziehau * NOTE: 1454a455c52eSSepherosa Ziehau * Switching between jumbo frames and normal frames should 1455a455c52eSSepherosa Ziehau * be done _after_ nfe_stop() but _before_ nfe_init_rx_ring(). 1456a455c52eSSepherosa Ziehau */ 1457a455c52eSSepherosa Ziehau if (ifp->if_mtu > ETHERMTU) { 14585dc1e30eSSepherosa Ziehau sc->sc_flags |= NFE_F_USE_JUMBO; 1459a455c52eSSepherosa Ziehau sc->rxq.bufsz = NFE_JBYTES; 1460d378110eSSepherosa Ziehau sc->sc_tx_spare = NFE_NSEG_SPARE_JUMBO; 1461a455c52eSSepherosa Ziehau if (bootverbose) 1462a455c52eSSepherosa Ziehau if_printf(ifp, "use jumbo frames\n"); 1463a455c52eSSepherosa Ziehau } else { 14645dc1e30eSSepherosa Ziehau sc->sc_flags &= ~NFE_F_USE_JUMBO; 1465a455c52eSSepherosa Ziehau sc->rxq.bufsz = MCLBYTES; 1466d378110eSSepherosa Ziehau sc->sc_tx_spare = NFE_NSEG_SPARE; 1467a455c52eSSepherosa Ziehau if (bootverbose) 1468a455c52eSSepherosa Ziehau if_printf(ifp, "use non-jumbo frames\n"); 1469a455c52eSSepherosa Ziehau } 1470a455c52eSSepherosa Ziehau 1471ae813fd8SSepherosa Ziehau error = nfe_init_tx_ring(sc, &sc->txq); 1472ae813fd8SSepherosa Ziehau if (error) { 1473ae813fd8SSepherosa Ziehau nfe_stop(sc); 1474ae813fd8SSepherosa Ziehau return; 1475ae813fd8SSepherosa Ziehau } 1476ae813fd8SSepherosa Ziehau 1477ae813fd8SSepherosa Ziehau error = nfe_init_rx_ring(sc, &sc->rxq); 1478ae813fd8SSepherosa Ziehau if (error) { 1479ae813fd8SSepherosa Ziehau nfe_stop(sc); 1480ae813fd8SSepherosa Ziehau return; 1481ae813fd8SSepherosa Ziehau } 1482ae813fd8SSepherosa Ziehau 1483fd9c8397SSepherosa Ziehau NFE_WRITE(sc, NFE_TX_POLL, 0); 1484ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_STATUS, 0); 1485ae813fd8SSepherosa Ziehau 1486faaea42eSSepherosa Ziehau sc->rxtxctl = NFE_RXTX_BIT2 | sc->rxtxctl_desc; 148711db6c57SSepherosa Ziehau 1488bf2a5992SSepherosa Ziehau if (ifp->if_capenable & IFCAP_RXCSUM) 1489ae813fd8SSepherosa Ziehau sc->rxtxctl |= NFE_RXTX_RXCSUM; 1490ae813fd8SSepherosa Ziehau 1491ae813fd8SSepherosa Ziehau /* 1492ae813fd8SSepherosa Ziehau * Although the adapter is capable of stripping VLAN tags from received 1493ae813fd8SSepherosa Ziehau * frames (NFE_RXTX_VTAG_STRIP), we do not enable this functionality on 1494ae813fd8SSepherosa Ziehau * purpose. This will be done in software by our network stack. 1495ae813fd8SSepherosa Ziehau */ 149688d487c3SSepherosa Ziehau if (sc->sc_caps & NFE_HW_VLAN) 1497ae813fd8SSepherosa Ziehau sc->rxtxctl |= NFE_RXTX_VTAG_INSERT; 1498ae813fd8SSepherosa Ziehau 1499ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_RXTX_CTL, NFE_RXTX_RESET | sc->rxtxctl); 1500ae813fd8SSepherosa Ziehau DELAY(10); 1501ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_RXTX_CTL, sc->rxtxctl); 1502ae813fd8SSepherosa Ziehau 150388d487c3SSepherosa Ziehau if (sc->sc_caps & NFE_HW_VLAN) 1504ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_VTAG_CTL, NFE_VTAG_ENABLE); 1505ae813fd8SSepherosa Ziehau 1506ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_SETUP_R6, 0); 1507ae813fd8SSepherosa Ziehau 1508ae813fd8SSepherosa Ziehau /* set MAC address */ 1509ae813fd8SSepherosa Ziehau nfe_set_macaddr(sc, sc->arpcom.ac_enaddr); 1510ae813fd8SSepherosa Ziehau 1511ae813fd8SSepherosa Ziehau /* tell MAC where rings are in memory */ 15127752918dSSepherosa Ziehau if (sc->sc_caps & NFE_40BIT_ADDR) { 15137752918dSSepherosa Ziehau NFE_WRITE(sc, NFE_RX_RING_ADDR_HI, 15147752918dSSepherosa Ziehau NFE_ADDR_HI(sc->rxq.physaddr)); 15157752918dSSepherosa Ziehau } 15167752918dSSepherosa Ziehau NFE_WRITE(sc, NFE_RX_RING_ADDR_LO, NFE_ADDR_LO(sc->rxq.physaddr)); 15177752918dSSepherosa Ziehau 15187752918dSSepherosa Ziehau if (sc->sc_caps & NFE_40BIT_ADDR) { 15197752918dSSepherosa Ziehau NFE_WRITE(sc, NFE_TX_RING_ADDR_HI, 15207752918dSSepherosa Ziehau NFE_ADDR_HI(sc->txq.physaddr)); 15217752918dSSepherosa Ziehau } 15227752918dSSepherosa Ziehau NFE_WRITE(sc, NFE_TX_RING_ADDR_LO, NFE_ADDR_LO(sc->txq.physaddr)); 1523ae813fd8SSepherosa Ziehau 1524ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_RING_SIZE, 1525ec9403d0SSepherosa Ziehau (sc->sc_rx_ring_count - 1) << 16 | 1526b4633098SSepherosa Ziehau (sc->sc_tx_ring_count - 1)); 1527ae813fd8SSepherosa Ziehau 1528ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_RXBUFSZ, sc->rxq.bufsz); 1529ae813fd8SSepherosa Ziehau 1530ae813fd8SSepherosa Ziehau /* force MAC to wakeup */ 1531ae813fd8SSepherosa Ziehau tmp = NFE_READ(sc, NFE_PWR_STATE); 1532ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_PWR_STATE, tmp | NFE_PWR_WAKEUP); 1533ae813fd8SSepherosa Ziehau DELAY(10); 1534ae813fd8SSepherosa Ziehau tmp = NFE_READ(sc, NFE_PWR_STATE); 1535ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_PWR_STATE, tmp | NFE_PWR_VALID); 1536ae813fd8SSepherosa Ziehau 1537ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_SETUP_R1, NFE_R1_MAGIC); 1538ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_SETUP_R2, NFE_R2_MAGIC); 1539ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_SETUP_R6, NFE_R6_MAGIC); 1540ae813fd8SSepherosa Ziehau 1541ae813fd8SSepherosa Ziehau /* update MAC knowledge of PHY; generates a NFE_IRQ_LINK interrupt */ 1542ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_STATUS, sc->mii_phyaddr << 24 | NFE_STATUS_MAGIC); 1543ae813fd8SSepherosa Ziehau 1544ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_SETUP_R4, NFE_R4_MAGIC); 1545ae813fd8SSepherosa Ziehau 1546ae813fd8SSepherosa Ziehau sc->rxtxctl &= ~NFE_RXTX_BIT2; 1547ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_RXTX_CTL, sc->rxtxctl); 1548ae813fd8SSepherosa Ziehau DELAY(10); 1549ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_RXTX_CTL, NFE_RXTX_BIT1 | sc->rxtxctl); 1550ae813fd8SSepherosa Ziehau 1551ae813fd8SSepherosa Ziehau /* set Rx filter */ 1552ae813fd8SSepherosa Ziehau nfe_setmulti(sc); 1553ae813fd8SSepherosa Ziehau 1554ae813fd8SSepherosa Ziehau nfe_ifmedia_upd(ifp); 1555ae813fd8SSepherosa Ziehau 1556ae813fd8SSepherosa Ziehau /* enable Rx */ 1557ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_RX_CTL, NFE_RX_START); 1558ae813fd8SSepherosa Ziehau 1559ae813fd8SSepherosa Ziehau /* enable Tx */ 1560ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_TX_CTL, NFE_TX_START); 1561ae813fd8SSepherosa Ziehau 1562ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_PHY_STATUS, 0xf); 1563ae813fd8SSepherosa Ziehau 1564ae813fd8SSepherosa Ziehau #ifdef DEVICE_POLLING 156504b9ef8dSSepherosa Ziehau if ((ifp->if_flags & IFF_POLLING)) 156604b9ef8dSSepherosa Ziehau nfe_disable_intrs(sc); 156704b9ef8dSSepherosa Ziehau else 1568ae813fd8SSepherosa Ziehau #endif 156904b9ef8dSSepherosa Ziehau nfe_enable_intrs(sc); 1570ae813fd8SSepherosa Ziehau 1571ae813fd8SSepherosa Ziehau callout_reset(&sc->sc_tick_ch, hz, nfe_tick, sc); 1572ae813fd8SSepherosa Ziehau 1573ae813fd8SSepherosa Ziehau ifp->if_flags |= IFF_RUNNING; 1574ae813fd8SSepherosa Ziehau ifp->if_flags &= ~IFF_OACTIVE; 1575751890abSMatthew Dillon 1576751890abSMatthew Dillon /* 1577751890abSMatthew Dillon * If we had stuff in the tx ring before its all cleaned out now 1578751890abSMatthew Dillon * so we are not going to get an interrupt, jump-start any pending 1579751890abSMatthew Dillon * output. 1580751890abSMatthew Dillon */ 1581d378110eSSepherosa Ziehau if (!ifq_is_empty(&ifp->if_snd)) 15829db4b353SSepherosa Ziehau if_devstart(ifp); 1583ae813fd8SSepherosa Ziehau } 1584ae813fd8SSepherosa Ziehau 1585ae813fd8SSepherosa Ziehau static void 1586ae813fd8SSepherosa Ziehau nfe_stop(struct nfe_softc *sc) 1587ae813fd8SSepherosa Ziehau { 1588ae813fd8SSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 158953f1d017SSepherosa Ziehau uint32_t rxtxctl = sc->rxtxctl_desc | NFE_RXTX_BIT2; 159053f1d017SSepherosa Ziehau int i; 1591ae813fd8SSepherosa Ziehau 1592c0dcc88eSSepherosa Ziehau ASSERT_SERIALIZED(ifp->if_serializer); 1593c0dcc88eSSepherosa Ziehau 1594ae813fd8SSepherosa Ziehau callout_stop(&sc->sc_tick_ch); 1595ae813fd8SSepherosa Ziehau 1596ae813fd8SSepherosa Ziehau ifp->if_timer = 0; 1597ae813fd8SSepherosa Ziehau ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); 159804b9ef8dSSepherosa Ziehau sc->sc_flags &= ~NFE_F_IRQ_TIMER; 1599ae813fd8SSepherosa Ziehau 160053f1d017SSepherosa Ziehau #define WAITMAX 50000 160153f1d017SSepherosa Ziehau 1602d1daf8afSMatthew Dillon /* 160353f1d017SSepherosa Ziehau * Abort Tx 1604d1daf8afSMatthew Dillon */ 1605ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_TX_CTL, 0); 160653f1d017SSepherosa Ziehau for (i = 0; i < WAITMAX; ++i) { 160753f1d017SSepherosa Ziehau DELAY(100); 160853f1d017SSepherosa Ziehau if ((NFE_READ(sc, NFE_TX_STATUS) & NFE_TX_STATUS_BUSY) == 0) 160953f1d017SSepherosa Ziehau break; 161053f1d017SSepherosa Ziehau } 161153f1d017SSepherosa Ziehau if (i == WAITMAX) 161253f1d017SSepherosa Ziehau if_printf(ifp, "can't stop TX\n"); 161353f1d017SSepherosa Ziehau DELAY(100); 1614ae813fd8SSepherosa Ziehau 161553f1d017SSepherosa Ziehau /* 161653f1d017SSepherosa Ziehau * Disable Rx 161753f1d017SSepherosa Ziehau */ 1618ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_RX_CTL, 0); 161953f1d017SSepherosa Ziehau for (i = 0; i < WAITMAX; ++i) { 162053f1d017SSepherosa Ziehau DELAY(100); 162153f1d017SSepherosa Ziehau if ((NFE_READ(sc, NFE_RX_STATUS) & NFE_RX_STATUS_BUSY) == 0) 162253f1d017SSepherosa Ziehau break; 162353f1d017SSepherosa Ziehau } 162453f1d017SSepherosa Ziehau if (i == WAITMAX) 162553f1d017SSepherosa Ziehau if_printf(ifp, "can't stop RX\n"); 162653f1d017SSepherosa Ziehau DELAY(100); 162753f1d017SSepherosa Ziehau 162853f1d017SSepherosa Ziehau #undef WAITMAX 162953f1d017SSepherosa Ziehau 163053f1d017SSepherosa Ziehau NFE_WRITE(sc, NFE_RXTX_CTL, NFE_RXTX_RESET | rxtxctl); 163153f1d017SSepherosa Ziehau DELAY(10); 163253f1d017SSepherosa Ziehau NFE_WRITE(sc, NFE_RXTX_CTL, rxtxctl); 1633ae813fd8SSepherosa Ziehau 1634ae813fd8SSepherosa Ziehau /* Disable interrupts */ 1635ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_IRQ_MASK, 0); 1636ae813fd8SSepherosa Ziehau 1637ae813fd8SSepherosa Ziehau /* Reset Tx and Rx rings */ 1638ae813fd8SSepherosa Ziehau nfe_reset_tx_ring(sc, &sc->txq); 1639ae813fd8SSepherosa Ziehau nfe_reset_rx_ring(sc, &sc->rxq); 1640ae813fd8SSepherosa Ziehau } 1641ae813fd8SSepherosa Ziehau 1642ae813fd8SSepherosa Ziehau static int 1643ae813fd8SSepherosa Ziehau nfe_alloc_rx_ring(struct nfe_softc *sc, struct nfe_rx_ring *ring) 1644ae813fd8SSepherosa Ziehau { 1645ae813fd8SSepherosa Ziehau int i, j, error, descsize; 1646244a9aa3SSepherosa Ziehau bus_dmamem_t dmem; 1647ae813fd8SSepherosa Ziehau void **desc; 1648ae813fd8SSepherosa Ziehau 164988d487c3SSepherosa Ziehau if (sc->sc_caps & NFE_40BIT_ADDR) { 1650ae813fd8SSepherosa Ziehau desc = (void **)&ring->desc64; 1651ae813fd8SSepherosa Ziehau descsize = sizeof(struct nfe_desc64); 1652ae813fd8SSepherosa Ziehau } else { 1653ae813fd8SSepherosa Ziehau desc = (void **)&ring->desc32; 1654ae813fd8SSepherosa Ziehau descsize = sizeof(struct nfe_desc32); 1655ae813fd8SSepherosa Ziehau } 1656ae813fd8SSepherosa Ziehau 1657ae813fd8SSepherosa Ziehau ring->bufsz = MCLBYTES; 1658ae813fd8SSepherosa Ziehau ring->cur = ring->next = 0; 1659ae813fd8SSepherosa Ziehau 1660244a9aa3SSepherosa Ziehau error = bus_dmamem_coherent(sc->sc_dtag, PAGE_SIZE, 0, 1661244a9aa3SSepherosa Ziehau BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, 1662ec9403d0SSepherosa Ziehau sc->sc_rx_ring_count * descsize, 1663244a9aa3SSepherosa Ziehau BUS_DMA_WAITOK | BUS_DMA_ZERO, &dmem); 1664ae813fd8SSepherosa Ziehau if (error) { 1665ae813fd8SSepherosa Ziehau if_printf(&sc->arpcom.ac_if, 1666244a9aa3SSepherosa Ziehau "could not create RX desc ring\n"); 1667ae813fd8SSepherosa Ziehau return error; 1668ae813fd8SSepherosa Ziehau } 1669244a9aa3SSepherosa Ziehau ring->tag = dmem.dmem_tag; 1670244a9aa3SSepherosa Ziehau ring->map = dmem.dmem_map; 1671244a9aa3SSepherosa Ziehau *desc = dmem.dmem_addr; 1672244a9aa3SSepherosa Ziehau ring->physaddr = dmem.dmem_busaddr; 1673ae813fd8SSepherosa Ziehau 167488d487c3SSepherosa Ziehau if (sc->sc_caps & NFE_JUMBO_SUP) { 1675c58816edSSepherosa Ziehau ring->jbuf = 1676c58816edSSepherosa Ziehau kmalloc(sizeof(struct nfe_jbuf) * NFE_JPOOL_COUNT(sc), 167756fa71a9SSepherosa Ziehau M_DEVBUF, M_WAITOK | M_ZERO); 167856fa71a9SSepherosa Ziehau 1679ae813fd8SSepherosa Ziehau error = nfe_jpool_alloc(sc, ring); 1680ae813fd8SSepherosa Ziehau if (error) { 1681ae813fd8SSepherosa Ziehau if_printf(&sc->arpcom.ac_if, 1682ae813fd8SSepherosa Ziehau "could not allocate jumbo frames\n"); 168356fa71a9SSepherosa Ziehau kfree(ring->jbuf, M_DEVBUF); 168456fa71a9SSepherosa Ziehau ring->jbuf = NULL; 168556fa71a9SSepherosa Ziehau /* Allow jumbo frame allocation to fail */ 1686ae813fd8SSepherosa Ziehau } 1687ae813fd8SSepherosa Ziehau } 1688ae813fd8SSepherosa Ziehau 168956fa71a9SSepherosa Ziehau ring->data = kmalloc(sizeof(struct nfe_rx_data) * sc->sc_rx_ring_count, 169056fa71a9SSepherosa Ziehau M_DEVBUF, M_WAITOK | M_ZERO); 169156fa71a9SSepherosa Ziehau 1692244a9aa3SSepherosa Ziehau error = bus_dma_tag_create(sc->sc_dtag, 1, 0, 1693244a9aa3SSepherosa Ziehau BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, 1694ae813fd8SSepherosa Ziehau NULL, NULL, 1695244a9aa3SSepherosa Ziehau MCLBYTES, 1, MCLBYTES, 1696244a9aa3SSepherosa Ziehau BUS_DMA_ALLOCNOW | BUS_DMA_WAITOK, 1697244a9aa3SSepherosa Ziehau &ring->data_tag); 1698ae813fd8SSepherosa Ziehau if (error) { 1699ae813fd8SSepherosa Ziehau if_printf(&sc->arpcom.ac_if, 1700ae813fd8SSepherosa Ziehau "could not create RX mbuf DMA tag\n"); 1701ae813fd8SSepherosa Ziehau return error; 1702ae813fd8SSepherosa Ziehau } 1703ae813fd8SSepherosa Ziehau 1704ae813fd8SSepherosa Ziehau /* Create a spare RX mbuf DMA map */ 1705244a9aa3SSepherosa Ziehau error = bus_dmamap_create(ring->data_tag, BUS_DMA_WAITOK, 1706244a9aa3SSepherosa Ziehau &ring->data_tmpmap); 1707ae813fd8SSepherosa Ziehau if (error) { 1708ae813fd8SSepherosa Ziehau if_printf(&sc->arpcom.ac_if, 1709ae813fd8SSepherosa Ziehau "could not create spare RX mbuf DMA map\n"); 1710ae813fd8SSepherosa Ziehau bus_dma_tag_destroy(ring->data_tag); 1711ae813fd8SSepherosa Ziehau ring->data_tag = NULL; 1712ae813fd8SSepherosa Ziehau return error; 1713ae813fd8SSepherosa Ziehau } 1714ae813fd8SSepherosa Ziehau 1715ec9403d0SSepherosa Ziehau for (i = 0; i < sc->sc_rx_ring_count; i++) { 1716244a9aa3SSepherosa Ziehau error = bus_dmamap_create(ring->data_tag, BUS_DMA_WAITOK, 1717ae813fd8SSepherosa Ziehau &ring->data[i].map); 1718ae813fd8SSepherosa Ziehau if (error) { 1719ae813fd8SSepherosa Ziehau if_printf(&sc->arpcom.ac_if, 1720ae813fd8SSepherosa Ziehau "could not create %dth RX mbuf DMA mapn", i); 1721ae813fd8SSepherosa Ziehau goto fail; 1722ae813fd8SSepherosa Ziehau } 1723ae813fd8SSepherosa Ziehau } 1724ae813fd8SSepherosa Ziehau return 0; 1725ae813fd8SSepherosa Ziehau fail: 1726ae813fd8SSepherosa Ziehau for (j = 0; j < i; ++j) 1727ae813fd8SSepherosa Ziehau bus_dmamap_destroy(ring->data_tag, ring->data[i].map); 1728ae813fd8SSepherosa Ziehau bus_dmamap_destroy(ring->data_tag, ring->data_tmpmap); 1729ae813fd8SSepherosa Ziehau bus_dma_tag_destroy(ring->data_tag); 1730ae813fd8SSepherosa Ziehau ring->data_tag = NULL; 1731ae813fd8SSepherosa Ziehau return error; 1732ae813fd8SSepherosa Ziehau } 1733ae813fd8SSepherosa Ziehau 1734ae813fd8SSepherosa Ziehau static void 1735ae813fd8SSepherosa Ziehau nfe_reset_rx_ring(struct nfe_softc *sc, struct nfe_rx_ring *ring) 1736ae813fd8SSepherosa Ziehau { 1737ae813fd8SSepherosa Ziehau int i; 1738ae813fd8SSepherosa Ziehau 1739ec9403d0SSepherosa Ziehau for (i = 0; i < sc->sc_rx_ring_count; i++) { 1740ae813fd8SSepherosa Ziehau struct nfe_rx_data *data = &ring->data[i]; 1741ae813fd8SSepherosa Ziehau 1742ae813fd8SSepherosa Ziehau if (data->m != NULL) { 17435dc1e30eSSepherosa Ziehau if ((sc->sc_flags & NFE_F_USE_JUMBO) == 0) 1744ae813fd8SSepherosa Ziehau bus_dmamap_unload(ring->data_tag, data->map); 1745ae813fd8SSepherosa Ziehau m_freem(data->m); 1746ae813fd8SSepherosa Ziehau data->m = NULL; 1747ae813fd8SSepherosa Ziehau } 1748ae813fd8SSepherosa Ziehau } 1749ae813fd8SSepherosa Ziehau 1750ae813fd8SSepherosa Ziehau ring->cur = ring->next = 0; 1751ae813fd8SSepherosa Ziehau } 1752ae813fd8SSepherosa Ziehau 1753ae813fd8SSepherosa Ziehau static int 1754ae813fd8SSepherosa Ziehau nfe_init_rx_ring(struct nfe_softc *sc, struct nfe_rx_ring *ring) 1755ae813fd8SSepherosa Ziehau { 1756ae813fd8SSepherosa Ziehau int i; 1757ae813fd8SSepherosa Ziehau 1758ec9403d0SSepherosa Ziehau for (i = 0; i < sc->sc_rx_ring_count; ++i) { 1759ae813fd8SSepherosa Ziehau int error; 1760ae813fd8SSepherosa Ziehau 1761ae813fd8SSepherosa Ziehau /* XXX should use a function pointer */ 17625dc1e30eSSepherosa Ziehau if (sc->sc_flags & NFE_F_USE_JUMBO) 1763ae813fd8SSepherosa Ziehau error = nfe_newbuf_jumbo(sc, ring, i, 1); 1764ae813fd8SSepherosa Ziehau else 1765ae813fd8SSepherosa Ziehau error = nfe_newbuf_std(sc, ring, i, 1); 1766ae813fd8SSepherosa Ziehau if (error) { 1767ae813fd8SSepherosa Ziehau if_printf(&sc->arpcom.ac_if, 1768ae813fd8SSepherosa Ziehau "could not allocate RX buffer\n"); 1769ae813fd8SSepherosa Ziehau return error; 1770ae813fd8SSepherosa Ziehau } 1771ae813fd8SSepherosa Ziehau nfe_set_ready_rxdesc(sc, ring, i); 1772ae813fd8SSepherosa Ziehau } 1773ae813fd8SSepherosa Ziehau bus_dmamap_sync(ring->tag, ring->map, BUS_DMASYNC_PREWRITE); 1774ae813fd8SSepherosa Ziehau 1775ae813fd8SSepherosa Ziehau return 0; 1776ae813fd8SSepherosa Ziehau } 1777ae813fd8SSepherosa Ziehau 1778ae813fd8SSepherosa Ziehau static void 1779ae813fd8SSepherosa Ziehau nfe_free_rx_ring(struct nfe_softc *sc, struct nfe_rx_ring *ring) 1780ae813fd8SSepherosa Ziehau { 1781ae813fd8SSepherosa Ziehau if (ring->data_tag != NULL) { 1782ae813fd8SSepherosa Ziehau struct nfe_rx_data *data; 1783ae813fd8SSepherosa Ziehau int i; 1784ae813fd8SSepherosa Ziehau 1785ec9403d0SSepherosa Ziehau for (i = 0; i < sc->sc_rx_ring_count; i++) { 1786ae813fd8SSepherosa Ziehau data = &ring->data[i]; 1787ae813fd8SSepherosa Ziehau 1788ae813fd8SSepherosa Ziehau if (data->m != NULL) { 1789ae813fd8SSepherosa Ziehau bus_dmamap_unload(ring->data_tag, data->map); 1790ae813fd8SSepherosa Ziehau m_freem(data->m); 1791ae813fd8SSepherosa Ziehau } 1792ae813fd8SSepherosa Ziehau bus_dmamap_destroy(ring->data_tag, data->map); 1793ae813fd8SSepherosa Ziehau } 1794ae813fd8SSepherosa Ziehau bus_dmamap_destroy(ring->data_tag, ring->data_tmpmap); 1795ae813fd8SSepherosa Ziehau bus_dma_tag_destroy(ring->data_tag); 1796ae813fd8SSepherosa Ziehau } 1797ae813fd8SSepherosa Ziehau 1798ae813fd8SSepherosa Ziehau nfe_jpool_free(sc, ring); 1799ae813fd8SSepherosa Ziehau 1800a455c52eSSepherosa Ziehau if (ring->jbuf != NULL) 1801a455c52eSSepherosa Ziehau kfree(ring->jbuf, M_DEVBUF); 1802a455c52eSSepherosa Ziehau if (ring->data != NULL) 1803a455c52eSSepherosa Ziehau kfree(ring->data, M_DEVBUF); 1804a455c52eSSepherosa Ziehau 1805ae813fd8SSepherosa Ziehau if (ring->tag != NULL) { 1806ae813fd8SSepherosa Ziehau void *desc; 1807ae813fd8SSepherosa Ziehau 180888d487c3SSepherosa Ziehau if (sc->sc_caps & NFE_40BIT_ADDR) 1809ae813fd8SSepherosa Ziehau desc = ring->desc64; 1810ae813fd8SSepherosa Ziehau else 1811ae813fd8SSepherosa Ziehau desc = ring->desc32; 1812ae813fd8SSepherosa Ziehau 1813ae813fd8SSepherosa Ziehau bus_dmamap_unload(ring->tag, ring->map); 1814ae813fd8SSepherosa Ziehau bus_dmamem_free(ring->tag, desc, ring->map); 1815ae813fd8SSepherosa Ziehau bus_dma_tag_destroy(ring->tag); 1816ae813fd8SSepherosa Ziehau } 1817ae813fd8SSepherosa Ziehau } 1818ae813fd8SSepherosa Ziehau 1819ae813fd8SSepherosa Ziehau static struct nfe_jbuf * 1820ae813fd8SSepherosa Ziehau nfe_jalloc(struct nfe_softc *sc) 1821ae813fd8SSepherosa Ziehau { 1822ae813fd8SSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 1823ae813fd8SSepherosa Ziehau struct nfe_jbuf *jbuf; 1824ae813fd8SSepherosa Ziehau 1825ae813fd8SSepherosa Ziehau lwkt_serialize_enter(&sc->sc_jbuf_serializer); 1826ae813fd8SSepherosa Ziehau 1827ae813fd8SSepherosa Ziehau jbuf = SLIST_FIRST(&sc->rxq.jfreelist); 1828ae813fd8SSepherosa Ziehau if (jbuf != NULL) { 1829ae813fd8SSepherosa Ziehau SLIST_REMOVE_HEAD(&sc->rxq.jfreelist, jnext); 1830ae813fd8SSepherosa Ziehau jbuf->inuse = 1; 1831ae813fd8SSepherosa Ziehau } else { 1832ae813fd8SSepherosa Ziehau if_printf(ifp, "no free jumbo buffer\n"); 1833ae813fd8SSepherosa Ziehau } 1834ae813fd8SSepherosa Ziehau 1835ae813fd8SSepherosa Ziehau lwkt_serialize_exit(&sc->sc_jbuf_serializer); 1836ae813fd8SSepherosa Ziehau 1837ae813fd8SSepherosa Ziehau return jbuf; 1838ae813fd8SSepherosa Ziehau } 1839ae813fd8SSepherosa Ziehau 1840ae813fd8SSepherosa Ziehau static void 1841ae813fd8SSepherosa Ziehau nfe_jfree(void *arg) 1842ae813fd8SSepherosa Ziehau { 1843ae813fd8SSepherosa Ziehau struct nfe_jbuf *jbuf = arg; 1844ae813fd8SSepherosa Ziehau struct nfe_softc *sc = jbuf->sc; 1845ae813fd8SSepherosa Ziehau struct nfe_rx_ring *ring = jbuf->ring; 1846ae813fd8SSepherosa Ziehau 1847ae813fd8SSepherosa Ziehau if (&ring->jbuf[jbuf->slot] != jbuf) 1848ae813fd8SSepherosa Ziehau panic("%s: free wrong jumbo buffer\n", __func__); 1849ae813fd8SSepherosa Ziehau else if (jbuf->inuse == 0) 1850ae813fd8SSepherosa Ziehau panic("%s: jumbo buffer already freed\n", __func__); 1851ae813fd8SSepherosa Ziehau 1852ae813fd8SSepherosa Ziehau lwkt_serialize_enter(&sc->sc_jbuf_serializer); 1853ae813fd8SSepherosa Ziehau atomic_subtract_int(&jbuf->inuse, 1); 1854ae813fd8SSepherosa Ziehau if (jbuf->inuse == 0) 1855ae813fd8SSepherosa Ziehau SLIST_INSERT_HEAD(&ring->jfreelist, jbuf, jnext); 1856ae813fd8SSepherosa Ziehau lwkt_serialize_exit(&sc->sc_jbuf_serializer); 1857ae813fd8SSepherosa Ziehau } 1858ae813fd8SSepherosa Ziehau 1859ae813fd8SSepherosa Ziehau static void 1860ae813fd8SSepherosa Ziehau nfe_jref(void *arg) 1861ae813fd8SSepherosa Ziehau { 1862ae813fd8SSepherosa Ziehau struct nfe_jbuf *jbuf = arg; 1863ae813fd8SSepherosa Ziehau struct nfe_rx_ring *ring = jbuf->ring; 1864ae813fd8SSepherosa Ziehau 1865ae813fd8SSepherosa Ziehau if (&ring->jbuf[jbuf->slot] != jbuf) 1866ae813fd8SSepherosa Ziehau panic("%s: ref wrong jumbo buffer\n", __func__); 1867ae813fd8SSepherosa Ziehau else if (jbuf->inuse == 0) 1868ae813fd8SSepherosa Ziehau panic("%s: jumbo buffer already freed\n", __func__); 1869ae813fd8SSepherosa Ziehau 187006406609SSepherosa Ziehau atomic_add_int(&jbuf->inuse, 1); 1871ae813fd8SSepherosa Ziehau } 1872ae813fd8SSepherosa Ziehau 1873ae813fd8SSepherosa Ziehau static int 1874ae813fd8SSepherosa Ziehau nfe_jpool_alloc(struct nfe_softc *sc, struct nfe_rx_ring *ring) 1875ae813fd8SSepherosa Ziehau { 1876ae813fd8SSepherosa Ziehau struct nfe_jbuf *jbuf; 1877244a9aa3SSepherosa Ziehau bus_dmamem_t dmem; 1878ae813fd8SSepherosa Ziehau bus_addr_t physaddr; 1879ae813fd8SSepherosa Ziehau caddr_t buf; 1880ae813fd8SSepherosa Ziehau int i, error; 1881ae813fd8SSepherosa Ziehau 1882ae813fd8SSepherosa Ziehau /* 1883ae813fd8SSepherosa Ziehau * Allocate a big chunk of DMA'able memory. 1884ae813fd8SSepherosa Ziehau */ 1885244a9aa3SSepherosa Ziehau error = bus_dmamem_coherent(sc->sc_dtag, PAGE_SIZE, 0, 1886244a9aa3SSepherosa Ziehau BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, 1887c58816edSSepherosa Ziehau NFE_JPOOL_SIZE(sc), 1888244a9aa3SSepherosa Ziehau BUS_DMA_WAITOK, &dmem); 1889ae813fd8SSepherosa Ziehau if (error) { 1890ae813fd8SSepherosa Ziehau if_printf(&sc->arpcom.ac_if, 1891244a9aa3SSepherosa Ziehau "could not create jumbo buffer\n"); 1892ae813fd8SSepherosa Ziehau return error; 1893ae813fd8SSepherosa Ziehau } 1894244a9aa3SSepherosa Ziehau ring->jtag = dmem.dmem_tag; 1895244a9aa3SSepherosa Ziehau ring->jmap = dmem.dmem_map; 1896244a9aa3SSepherosa Ziehau ring->jpool = dmem.dmem_addr; 1897244a9aa3SSepherosa Ziehau physaddr = dmem.dmem_busaddr; 1898ae813fd8SSepherosa Ziehau 1899ae813fd8SSepherosa Ziehau /* ..and split it into 9KB chunks */ 1900ae813fd8SSepherosa Ziehau SLIST_INIT(&ring->jfreelist); 1901ae813fd8SSepherosa Ziehau 1902ae813fd8SSepherosa Ziehau buf = ring->jpool; 1903c58816edSSepherosa Ziehau for (i = 0; i < NFE_JPOOL_COUNT(sc); i++) { 1904ae813fd8SSepherosa Ziehau jbuf = &ring->jbuf[i]; 1905ae813fd8SSepherosa Ziehau 1906ae813fd8SSepherosa Ziehau jbuf->sc = sc; 1907ae813fd8SSepherosa Ziehau jbuf->ring = ring; 1908ae813fd8SSepherosa Ziehau jbuf->inuse = 0; 1909ae813fd8SSepherosa Ziehau jbuf->slot = i; 1910ae813fd8SSepherosa Ziehau jbuf->buf = buf; 1911ae813fd8SSepherosa Ziehau jbuf->physaddr = physaddr; 1912ae813fd8SSepherosa Ziehau 1913ae813fd8SSepherosa Ziehau SLIST_INSERT_HEAD(&ring->jfreelist, jbuf, jnext); 1914ae813fd8SSepherosa Ziehau 1915ae813fd8SSepherosa Ziehau buf += NFE_JBYTES; 1916ae813fd8SSepherosa Ziehau physaddr += NFE_JBYTES; 1917ae813fd8SSepherosa Ziehau } 1918ae813fd8SSepherosa Ziehau 1919ae813fd8SSepherosa Ziehau return 0; 1920ae813fd8SSepherosa Ziehau } 1921ae813fd8SSepherosa Ziehau 1922ae813fd8SSepherosa Ziehau static void 1923ae813fd8SSepherosa Ziehau nfe_jpool_free(struct nfe_softc *sc, struct nfe_rx_ring *ring) 1924ae813fd8SSepherosa Ziehau { 1925ae813fd8SSepherosa Ziehau if (ring->jtag != NULL) { 1926ae813fd8SSepherosa Ziehau bus_dmamap_unload(ring->jtag, ring->jmap); 1927ae813fd8SSepherosa Ziehau bus_dmamem_free(ring->jtag, ring->jpool, ring->jmap); 1928ae813fd8SSepherosa Ziehau bus_dma_tag_destroy(ring->jtag); 1929ae813fd8SSepherosa Ziehau } 1930ae813fd8SSepherosa Ziehau } 1931ae813fd8SSepherosa Ziehau 1932ae813fd8SSepherosa Ziehau static int 1933ae813fd8SSepherosa Ziehau nfe_alloc_tx_ring(struct nfe_softc *sc, struct nfe_tx_ring *ring) 1934ae813fd8SSepherosa Ziehau { 1935ae813fd8SSepherosa Ziehau int i, j, error, descsize; 1936244a9aa3SSepherosa Ziehau bus_dmamem_t dmem; 1937ae813fd8SSepherosa Ziehau void **desc; 1938ae813fd8SSepherosa Ziehau 193988d487c3SSepherosa Ziehau if (sc->sc_caps & NFE_40BIT_ADDR) { 1940ae813fd8SSepherosa Ziehau desc = (void **)&ring->desc64; 1941ae813fd8SSepherosa Ziehau descsize = sizeof(struct nfe_desc64); 1942ae813fd8SSepherosa Ziehau } else { 1943ae813fd8SSepherosa Ziehau desc = (void **)&ring->desc32; 1944ae813fd8SSepherosa Ziehau descsize = sizeof(struct nfe_desc32); 1945ae813fd8SSepherosa Ziehau } 1946ae813fd8SSepherosa Ziehau 1947ae813fd8SSepherosa Ziehau ring->queued = 0; 1948ae813fd8SSepherosa Ziehau ring->cur = ring->next = 0; 1949ae813fd8SSepherosa Ziehau 1950244a9aa3SSepherosa Ziehau error = bus_dmamem_coherent(sc->sc_dtag, PAGE_SIZE, 0, 1951244a9aa3SSepherosa Ziehau BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, 1952b4633098SSepherosa Ziehau sc->sc_tx_ring_count * descsize, 1953244a9aa3SSepherosa Ziehau BUS_DMA_WAITOK | BUS_DMA_ZERO, &dmem); 1954ae813fd8SSepherosa Ziehau if (error) { 1955ae813fd8SSepherosa Ziehau if_printf(&sc->arpcom.ac_if, 1956244a9aa3SSepherosa Ziehau "could not create TX desc ring\n"); 1957ae813fd8SSepherosa Ziehau return error; 1958ae813fd8SSepherosa Ziehau } 1959244a9aa3SSepherosa Ziehau ring->tag = dmem.dmem_tag; 1960244a9aa3SSepherosa Ziehau ring->map = dmem.dmem_map; 1961244a9aa3SSepherosa Ziehau *desc = dmem.dmem_addr; 1962244a9aa3SSepherosa Ziehau ring->physaddr = dmem.dmem_busaddr; 1963ae813fd8SSepherosa Ziehau 1964b4633098SSepherosa Ziehau ring->data = kmalloc(sizeof(struct nfe_tx_data) * sc->sc_tx_ring_count, 1965b4633098SSepherosa Ziehau M_DEVBUF, M_WAITOK | M_ZERO); 1966b4633098SSepherosa Ziehau 1967244a9aa3SSepherosa Ziehau error = bus_dma_tag_create(sc->sc_dtag, 1, 0, 1968244a9aa3SSepherosa Ziehau BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, 1969ae813fd8SSepherosa Ziehau NULL, NULL, 1970244a9aa3SSepherosa Ziehau NFE_JBYTES, NFE_MAX_SCATTER, MCLBYTES, 1971*90a9e482SSepherosa Ziehau BUS_DMA_ALLOCNOW | BUS_DMA_WAITOK | BUS_DMA_ONEBPAGE, 1972244a9aa3SSepherosa Ziehau &ring->data_tag); 1973ae813fd8SSepherosa Ziehau if (error) { 1974ae813fd8SSepherosa Ziehau if_printf(&sc->arpcom.ac_if, 1975ae813fd8SSepherosa Ziehau "could not create TX buf DMA tag\n"); 1976ae813fd8SSepherosa Ziehau return error; 1977ae813fd8SSepherosa Ziehau } 1978ae813fd8SSepherosa Ziehau 1979b4633098SSepherosa Ziehau for (i = 0; i < sc->sc_tx_ring_count; i++) { 1980244a9aa3SSepherosa Ziehau error = bus_dmamap_create(ring->data_tag, 1981*90a9e482SSepherosa Ziehau BUS_DMA_WAITOK | BUS_DMA_ONEBPAGE, 1982ae813fd8SSepherosa Ziehau &ring->data[i].map); 1983ae813fd8SSepherosa Ziehau if (error) { 1984ae813fd8SSepherosa Ziehau if_printf(&sc->arpcom.ac_if, 1985ae813fd8SSepherosa Ziehau "could not create %dth TX buf DMA map\n", i); 1986ae813fd8SSepherosa Ziehau goto fail; 1987ae813fd8SSepherosa Ziehau } 1988ae813fd8SSepherosa Ziehau } 1989ae813fd8SSepherosa Ziehau 1990ae813fd8SSepherosa Ziehau return 0; 1991ae813fd8SSepherosa Ziehau fail: 1992ae813fd8SSepherosa Ziehau for (j = 0; j < i; ++j) 1993ae813fd8SSepherosa Ziehau bus_dmamap_destroy(ring->data_tag, ring->data[i].map); 1994ae813fd8SSepherosa Ziehau bus_dma_tag_destroy(ring->data_tag); 1995ae813fd8SSepherosa Ziehau ring->data_tag = NULL; 1996ae813fd8SSepherosa Ziehau return error; 1997ae813fd8SSepherosa Ziehau } 1998ae813fd8SSepherosa Ziehau 1999ae813fd8SSepherosa Ziehau static void 2000ae813fd8SSepherosa Ziehau nfe_reset_tx_ring(struct nfe_softc *sc, struct nfe_tx_ring *ring) 2001ae813fd8SSepherosa Ziehau { 2002ae813fd8SSepherosa Ziehau int i; 2003ae813fd8SSepherosa Ziehau 2004b4633098SSepherosa Ziehau for (i = 0; i < sc->sc_tx_ring_count; i++) { 2005ae813fd8SSepherosa Ziehau struct nfe_tx_data *data = &ring->data[i]; 2006ae813fd8SSepherosa Ziehau 200788d487c3SSepherosa Ziehau if (sc->sc_caps & NFE_40BIT_ADDR) 2008ae813fd8SSepherosa Ziehau ring->desc64[i].flags = 0; 2009ae813fd8SSepherosa Ziehau else 2010ae813fd8SSepherosa Ziehau ring->desc32[i].flags = 0; 2011ae813fd8SSepherosa Ziehau 2012ae813fd8SSepherosa Ziehau if (data->m != NULL) { 2013ae813fd8SSepherosa Ziehau bus_dmamap_unload(ring->data_tag, data->map); 2014ae813fd8SSepherosa Ziehau m_freem(data->m); 2015ae813fd8SSepherosa Ziehau data->m = NULL; 2016ae813fd8SSepherosa Ziehau } 2017ae813fd8SSepherosa Ziehau } 2018ae813fd8SSepherosa Ziehau bus_dmamap_sync(ring->tag, ring->map, BUS_DMASYNC_PREWRITE); 2019ae813fd8SSepherosa Ziehau 2020ae813fd8SSepherosa Ziehau ring->queued = 0; 2021ae813fd8SSepherosa Ziehau ring->cur = ring->next = 0; 2022ae813fd8SSepherosa Ziehau } 2023ae813fd8SSepherosa Ziehau 2024ae813fd8SSepherosa Ziehau static int 2025ae813fd8SSepherosa Ziehau nfe_init_tx_ring(struct nfe_softc *sc __unused, 2026ae813fd8SSepherosa Ziehau struct nfe_tx_ring *ring __unused) 2027ae813fd8SSepherosa Ziehau { 2028ae813fd8SSepherosa Ziehau return 0; 2029ae813fd8SSepherosa Ziehau } 2030ae813fd8SSepherosa Ziehau 2031ae813fd8SSepherosa Ziehau static void 2032ae813fd8SSepherosa Ziehau nfe_free_tx_ring(struct nfe_softc *sc, struct nfe_tx_ring *ring) 2033ae813fd8SSepherosa Ziehau { 2034ae813fd8SSepherosa Ziehau if (ring->data_tag != NULL) { 2035ae813fd8SSepherosa Ziehau struct nfe_tx_data *data; 2036ae813fd8SSepherosa Ziehau int i; 2037ae813fd8SSepherosa Ziehau 2038b4633098SSepherosa Ziehau for (i = 0; i < sc->sc_tx_ring_count; ++i) { 2039ae813fd8SSepherosa Ziehau data = &ring->data[i]; 2040ae813fd8SSepherosa Ziehau 2041ae813fd8SSepherosa Ziehau if (data->m != NULL) { 2042ae813fd8SSepherosa Ziehau bus_dmamap_unload(ring->data_tag, data->map); 2043ae813fd8SSepherosa Ziehau m_freem(data->m); 2044ae813fd8SSepherosa Ziehau } 2045ae813fd8SSepherosa Ziehau bus_dmamap_destroy(ring->data_tag, data->map); 2046ae813fd8SSepherosa Ziehau } 2047ae813fd8SSepherosa Ziehau 2048ae813fd8SSepherosa Ziehau bus_dma_tag_destroy(ring->data_tag); 2049ae813fd8SSepherosa Ziehau } 2050ae813fd8SSepherosa Ziehau 2051b4633098SSepherosa Ziehau if (ring->data != NULL) 2052b4633098SSepherosa Ziehau kfree(ring->data, M_DEVBUF); 2053b4633098SSepherosa Ziehau 2054ae813fd8SSepherosa Ziehau if (ring->tag != NULL) { 2055ae813fd8SSepherosa Ziehau void *desc; 2056ae813fd8SSepherosa Ziehau 205788d487c3SSepherosa Ziehau if (sc->sc_caps & NFE_40BIT_ADDR) 2058ae813fd8SSepherosa Ziehau desc = ring->desc64; 2059ae813fd8SSepherosa Ziehau else 2060ae813fd8SSepherosa Ziehau desc = ring->desc32; 2061ae813fd8SSepherosa Ziehau 2062ae813fd8SSepherosa Ziehau bus_dmamap_unload(ring->tag, ring->map); 2063ae813fd8SSepherosa Ziehau bus_dmamem_free(ring->tag, desc, ring->map); 2064ae813fd8SSepherosa Ziehau bus_dma_tag_destroy(ring->tag); 2065ae813fd8SSepherosa Ziehau } 2066ae813fd8SSepherosa Ziehau } 2067ae813fd8SSepherosa Ziehau 2068ae813fd8SSepherosa Ziehau static int 2069ae813fd8SSepherosa Ziehau nfe_ifmedia_upd(struct ifnet *ifp) 2070ae813fd8SSepherosa Ziehau { 2071ae813fd8SSepherosa Ziehau struct nfe_softc *sc = ifp->if_softc; 2072ae813fd8SSepherosa Ziehau struct mii_data *mii = device_get_softc(sc->sc_miibus); 2073ae813fd8SSepherosa Ziehau 2074c0dcc88eSSepherosa Ziehau ASSERT_SERIALIZED(ifp->if_serializer); 2075c0dcc88eSSepherosa Ziehau 2076ae813fd8SSepherosa Ziehau if (mii->mii_instance != 0) { 2077ae813fd8SSepherosa Ziehau struct mii_softc *miisc; 2078ae813fd8SSepherosa Ziehau 2079ae813fd8SSepherosa Ziehau LIST_FOREACH(miisc, &mii->mii_phys, mii_list) 2080ae813fd8SSepherosa Ziehau mii_phy_reset(miisc); 2081ae813fd8SSepherosa Ziehau } 2082ae813fd8SSepherosa Ziehau mii_mediachg(mii); 2083ae813fd8SSepherosa Ziehau 2084ae813fd8SSepherosa Ziehau return 0; 2085ae813fd8SSepherosa Ziehau } 2086ae813fd8SSepherosa Ziehau 2087ae813fd8SSepherosa Ziehau static void 2088ae813fd8SSepherosa Ziehau nfe_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr) 2089ae813fd8SSepherosa Ziehau { 2090ae813fd8SSepherosa Ziehau struct nfe_softc *sc = ifp->if_softc; 2091ae813fd8SSepherosa Ziehau struct mii_data *mii = device_get_softc(sc->sc_miibus); 2092ae813fd8SSepherosa Ziehau 2093c0dcc88eSSepherosa Ziehau ASSERT_SERIALIZED(ifp->if_serializer); 2094c0dcc88eSSepherosa Ziehau 2095ae813fd8SSepherosa Ziehau mii_pollstat(mii); 2096ae813fd8SSepherosa Ziehau ifmr->ifm_status = mii->mii_media_status; 2097ae813fd8SSepherosa Ziehau ifmr->ifm_active = mii->mii_media_active; 2098ae813fd8SSepherosa Ziehau } 2099ae813fd8SSepherosa Ziehau 2100ae813fd8SSepherosa Ziehau static void 2101ae813fd8SSepherosa Ziehau nfe_setmulti(struct nfe_softc *sc) 2102ae813fd8SSepherosa Ziehau { 2103ae813fd8SSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 2104ae813fd8SSepherosa Ziehau struct ifmultiaddr *ifma; 2105ae813fd8SSepherosa Ziehau uint8_t addr[ETHER_ADDR_LEN], mask[ETHER_ADDR_LEN]; 2106ae813fd8SSepherosa Ziehau uint32_t filter = NFE_RXFILTER_MAGIC; 2107ae813fd8SSepherosa Ziehau int i; 2108ae813fd8SSepherosa Ziehau 2109ae813fd8SSepherosa Ziehau if ((ifp->if_flags & (IFF_ALLMULTI | IFF_PROMISC)) != 0) { 2110ae813fd8SSepherosa Ziehau bzero(addr, ETHER_ADDR_LEN); 2111ae813fd8SSepherosa Ziehau bzero(mask, ETHER_ADDR_LEN); 2112ae813fd8SSepherosa Ziehau goto done; 2113ae813fd8SSepherosa Ziehau } 2114ae813fd8SSepherosa Ziehau 2115ae813fd8SSepherosa Ziehau bcopy(etherbroadcastaddr, addr, ETHER_ADDR_LEN); 2116ae813fd8SSepherosa Ziehau bcopy(etherbroadcastaddr, mask, ETHER_ADDR_LEN); 2117ae813fd8SSepherosa Ziehau 2118ae813fd8SSepherosa Ziehau LIST_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { 2119ae813fd8SSepherosa Ziehau caddr_t maddr; 2120ae813fd8SSepherosa Ziehau 2121ae813fd8SSepherosa Ziehau if (ifma->ifma_addr->sa_family != AF_LINK) 2122ae813fd8SSepherosa Ziehau continue; 2123ae813fd8SSepherosa Ziehau 2124ae813fd8SSepherosa Ziehau maddr = LLADDR((struct sockaddr_dl *)ifma->ifma_addr); 2125ae813fd8SSepherosa Ziehau for (i = 0; i < ETHER_ADDR_LEN; i++) { 2126ae813fd8SSepherosa Ziehau addr[i] &= maddr[i]; 2127ae813fd8SSepherosa Ziehau mask[i] &= ~maddr[i]; 2128ae813fd8SSepherosa Ziehau } 2129ae813fd8SSepherosa Ziehau } 2130ae813fd8SSepherosa Ziehau 2131ae813fd8SSepherosa Ziehau for (i = 0; i < ETHER_ADDR_LEN; i++) 2132ae813fd8SSepherosa Ziehau mask[i] |= addr[i]; 2133ae813fd8SSepherosa Ziehau 2134ae813fd8SSepherosa Ziehau done: 2135ae813fd8SSepherosa Ziehau addr[0] |= 0x01; /* make sure multicast bit is set */ 2136ae813fd8SSepherosa Ziehau 2137ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_MULTIADDR_HI, 2138ae813fd8SSepherosa Ziehau addr[3] << 24 | addr[2] << 16 | addr[1] << 8 | addr[0]); 2139ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_MULTIADDR_LO, 2140ae813fd8SSepherosa Ziehau addr[5] << 8 | addr[4]); 2141ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_MULTIMASK_HI, 2142ae813fd8SSepherosa Ziehau mask[3] << 24 | mask[2] << 16 | mask[1] << 8 | mask[0]); 2143ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_MULTIMASK_LO, 2144ae813fd8SSepherosa Ziehau mask[5] << 8 | mask[4]); 2145ae813fd8SSepherosa Ziehau 2146ae813fd8SSepherosa Ziehau filter |= (ifp->if_flags & IFF_PROMISC) ? NFE_PROMISC : NFE_U2M; 2147ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_RXFILTER, filter); 2148ae813fd8SSepherosa Ziehau } 2149ae813fd8SSepherosa Ziehau 2150ae813fd8SSepherosa Ziehau static void 2151ae813fd8SSepherosa Ziehau nfe_get_macaddr(struct nfe_softc *sc, uint8_t *addr) 2152ae813fd8SSepherosa Ziehau { 2153ece56005SSepherosa Ziehau uint32_t lo, hi; 2154ae813fd8SSepherosa Ziehau 2155ece56005SSepherosa Ziehau lo = NFE_READ(sc, NFE_MACADDR_LO); 2156ece56005SSepherosa Ziehau hi = NFE_READ(sc, NFE_MACADDR_HI); 2157ece56005SSepherosa Ziehau if (sc->sc_caps & NFE_FIX_EADDR) { 2158ece56005SSepherosa Ziehau addr[0] = (lo >> 8) & 0xff; 2159ece56005SSepherosa Ziehau addr[1] = (lo & 0xff); 2160ae813fd8SSepherosa Ziehau 2161ece56005SSepherosa Ziehau addr[2] = (hi >> 24) & 0xff; 2162ece56005SSepherosa Ziehau addr[3] = (hi >> 16) & 0xff; 2163ece56005SSepherosa Ziehau addr[4] = (hi >> 8) & 0xff; 2164ece56005SSepherosa Ziehau addr[5] = (hi & 0xff); 2165ece56005SSepherosa Ziehau } else { 2166ece56005SSepherosa Ziehau addr[0] = (hi & 0xff); 2167ece56005SSepherosa Ziehau addr[1] = (hi >> 8) & 0xff; 2168ece56005SSepherosa Ziehau addr[2] = (hi >> 16) & 0xff; 2169ece56005SSepherosa Ziehau addr[3] = (hi >> 24) & 0xff; 2170ece56005SSepherosa Ziehau 2171ece56005SSepherosa Ziehau addr[4] = (lo & 0xff); 2172ece56005SSepherosa Ziehau addr[5] = (lo >> 8) & 0xff; 2173ece56005SSepherosa Ziehau } 2174ae813fd8SSepherosa Ziehau } 2175ae813fd8SSepherosa Ziehau 2176ae813fd8SSepherosa Ziehau static void 2177ae813fd8SSepherosa Ziehau nfe_set_macaddr(struct nfe_softc *sc, const uint8_t *addr) 2178ae813fd8SSepherosa Ziehau { 2179ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_MACADDR_LO, 2180ae813fd8SSepherosa Ziehau addr[5] << 8 | addr[4]); 2181ae813fd8SSepherosa Ziehau NFE_WRITE(sc, NFE_MACADDR_HI, 2182ae813fd8SSepherosa Ziehau addr[3] << 24 | addr[2] << 16 | addr[1] << 8 | addr[0]); 2183ae813fd8SSepherosa Ziehau } 2184ae813fd8SSepherosa Ziehau 2185ae813fd8SSepherosa Ziehau static void 2186ae813fd8SSepherosa Ziehau nfe_tick(void *arg) 2187ae813fd8SSepherosa Ziehau { 2188ae813fd8SSepherosa Ziehau struct nfe_softc *sc = arg; 2189ae813fd8SSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 2190ae813fd8SSepherosa Ziehau struct mii_data *mii = device_get_softc(sc->sc_miibus); 2191ae813fd8SSepherosa Ziehau 2192ae813fd8SSepherosa Ziehau lwkt_serialize_enter(ifp->if_serializer); 2193ae813fd8SSepherosa Ziehau 2194ae813fd8SSepherosa Ziehau mii_tick(mii); 2195ae813fd8SSepherosa Ziehau callout_reset(&sc->sc_tick_ch, hz, nfe_tick, sc); 2196ae813fd8SSepherosa Ziehau 2197ae813fd8SSepherosa Ziehau lwkt_serialize_exit(ifp->if_serializer); 2198ae813fd8SSepherosa Ziehau } 2199ae813fd8SSepherosa Ziehau 2200ae813fd8SSepherosa Ziehau static void 2201ae813fd8SSepherosa Ziehau nfe_buf_dma_addr(void *arg, bus_dma_segment_t *segs, int nsegs, 2202ae813fd8SSepherosa Ziehau bus_size_t mapsz __unused, int error) 2203ae813fd8SSepherosa Ziehau { 2204ae813fd8SSepherosa Ziehau struct nfe_dma_ctx *ctx = arg; 2205ae813fd8SSepherosa Ziehau int i; 2206ae813fd8SSepherosa Ziehau 2207ae813fd8SSepherosa Ziehau if (error) 2208ae813fd8SSepherosa Ziehau return; 2209ae813fd8SSepherosa Ziehau 221077cdd7f0SSepherosa Ziehau if (nsegs > ctx->nsegs) { 221177cdd7f0SSepherosa Ziehau ctx->nsegs = 0; 221277cdd7f0SSepherosa Ziehau return; 221377cdd7f0SSepherosa Ziehau } 2214ae813fd8SSepherosa Ziehau 2215ae813fd8SSepherosa Ziehau ctx->nsegs = nsegs; 2216ae813fd8SSepherosa Ziehau for (i = 0; i < nsegs; ++i) 2217ae813fd8SSepherosa Ziehau ctx->segs[i] = segs[i]; 2218ae813fd8SSepherosa Ziehau } 2219ae813fd8SSepherosa Ziehau 2220ae813fd8SSepherosa Ziehau static int 2221ae813fd8SSepherosa Ziehau nfe_newbuf_std(struct nfe_softc *sc, struct nfe_rx_ring *ring, int idx, 2222ae813fd8SSepherosa Ziehau int wait) 2223ae813fd8SSepherosa Ziehau { 2224ae813fd8SSepherosa Ziehau struct nfe_rx_data *data = &ring->data[idx]; 2225ae813fd8SSepherosa Ziehau struct nfe_dma_ctx ctx; 2226ae813fd8SSepherosa Ziehau bus_dma_segment_t seg; 2227ae813fd8SSepherosa Ziehau bus_dmamap_t map; 2228ae813fd8SSepherosa Ziehau struct mbuf *m; 2229ae813fd8SSepherosa Ziehau int error; 2230ae813fd8SSepherosa Ziehau 2231ae813fd8SSepherosa Ziehau m = m_getcl(wait ? MB_WAIT : MB_DONTWAIT, MT_DATA, M_PKTHDR); 2232ae813fd8SSepherosa Ziehau if (m == NULL) 2233ae813fd8SSepherosa Ziehau return ENOBUFS; 2234ae813fd8SSepherosa Ziehau m->m_len = m->m_pkthdr.len = MCLBYTES; 2235ae813fd8SSepherosa Ziehau 2236ae813fd8SSepherosa Ziehau ctx.nsegs = 1; 2237ae813fd8SSepherosa Ziehau ctx.segs = &seg; 2238ae813fd8SSepherosa Ziehau error = bus_dmamap_load_mbuf(ring->data_tag, ring->data_tmpmap, 2239ae813fd8SSepherosa Ziehau m, nfe_buf_dma_addr, &ctx, 2240e679c149SSepherosa Ziehau BUS_DMA_NOWAIT); 224177cdd7f0SSepherosa Ziehau if (error || ctx.nsegs == 0) { 224277cdd7f0SSepherosa Ziehau if (!error) { 224377cdd7f0SSepherosa Ziehau bus_dmamap_unload(ring->data_tag, ring->data_tmpmap); 224477cdd7f0SSepherosa Ziehau error = EFBIG; 2245e679c149SSepherosa Ziehau if (wait) { 2246e679c149SSepherosa Ziehau if_printf(&sc->arpcom.ac_if, 2247e679c149SSepherosa Ziehau "too many segments?!\n"); 2248e679c149SSepherosa Ziehau } 224977cdd7f0SSepherosa Ziehau } 2250ae813fd8SSepherosa Ziehau m_freem(m); 225177cdd7f0SSepherosa Ziehau 225277cdd7f0SSepherosa Ziehau if (wait) { 225377cdd7f0SSepherosa Ziehau if_printf(&sc->arpcom.ac_if, 225477cdd7f0SSepherosa Ziehau "could map RX mbuf %d\n", error); 225577cdd7f0SSepherosa Ziehau } 2256ae813fd8SSepherosa Ziehau return error; 2257ae813fd8SSepherosa Ziehau } 2258ae813fd8SSepherosa Ziehau 2259e679c149SSepherosa Ziehau if (data->m != NULL) { 2260e679c149SSepherosa Ziehau /* Sync and unload originally mapped mbuf */ 2261e679c149SSepherosa Ziehau bus_dmamap_sync(ring->data_tag, data->map, 2262e679c149SSepherosa Ziehau BUS_DMASYNC_POSTREAD); 2263ae813fd8SSepherosa Ziehau bus_dmamap_unload(ring->data_tag, data->map); 2264e679c149SSepherosa Ziehau } 2265ae813fd8SSepherosa Ziehau 2266ae813fd8SSepherosa Ziehau /* Swap this DMA map with tmp DMA map */ 2267ae813fd8SSepherosa Ziehau map = data->map; 2268ae813fd8SSepherosa Ziehau data->map = ring->data_tmpmap; 2269ae813fd8SSepherosa Ziehau ring->data_tmpmap = map; 2270ae813fd8SSepherosa Ziehau 2271ae813fd8SSepherosa Ziehau /* Caller is assumed to have collected the old mbuf */ 2272ae813fd8SSepherosa Ziehau data->m = m; 2273ae813fd8SSepherosa Ziehau 2274ae813fd8SSepherosa Ziehau nfe_set_paddr_rxdesc(sc, ring, idx, seg.ds_addr); 2275ae813fd8SSepherosa Ziehau return 0; 2276ae813fd8SSepherosa Ziehau } 2277ae813fd8SSepherosa Ziehau 2278ae813fd8SSepherosa Ziehau static int 2279ae813fd8SSepherosa Ziehau nfe_newbuf_jumbo(struct nfe_softc *sc, struct nfe_rx_ring *ring, int idx, 2280ae813fd8SSepherosa Ziehau int wait) 2281ae813fd8SSepherosa Ziehau { 2282ae813fd8SSepherosa Ziehau struct nfe_rx_data *data = &ring->data[idx]; 2283ae813fd8SSepherosa Ziehau struct nfe_jbuf *jbuf; 2284ae813fd8SSepherosa Ziehau struct mbuf *m; 2285ae813fd8SSepherosa Ziehau 2286ae813fd8SSepherosa Ziehau MGETHDR(m, wait ? MB_WAIT : MB_DONTWAIT, MT_DATA); 2287ae813fd8SSepherosa Ziehau if (m == NULL) 2288ae813fd8SSepherosa Ziehau return ENOBUFS; 2289ae813fd8SSepherosa Ziehau 2290ae813fd8SSepherosa Ziehau jbuf = nfe_jalloc(sc); 2291ae813fd8SSepherosa Ziehau if (jbuf == NULL) { 2292ae813fd8SSepherosa Ziehau m_freem(m); 2293ae813fd8SSepherosa Ziehau if_printf(&sc->arpcom.ac_if, "jumbo allocation failed " 2294ae813fd8SSepherosa Ziehau "-- packet dropped!\n"); 2295ae813fd8SSepherosa Ziehau return ENOBUFS; 2296ae813fd8SSepherosa Ziehau } 2297ae813fd8SSepherosa Ziehau 2298ae813fd8SSepherosa Ziehau m->m_ext.ext_arg = jbuf; 2299ae813fd8SSepherosa Ziehau m->m_ext.ext_buf = jbuf->buf; 2300ae813fd8SSepherosa Ziehau m->m_ext.ext_free = nfe_jfree; 2301ae813fd8SSepherosa Ziehau m->m_ext.ext_ref = nfe_jref; 2302ae813fd8SSepherosa Ziehau m->m_ext.ext_size = NFE_JBYTES; 2303ae813fd8SSepherosa Ziehau 2304ae813fd8SSepherosa Ziehau m->m_data = m->m_ext.ext_buf; 2305ae813fd8SSepherosa Ziehau m->m_flags |= M_EXT; 2306ae813fd8SSepherosa Ziehau m->m_len = m->m_pkthdr.len = m->m_ext.ext_size; 2307ae813fd8SSepherosa Ziehau 2308ae813fd8SSepherosa Ziehau /* Caller is assumed to have collected the old mbuf */ 2309ae813fd8SSepherosa Ziehau data->m = m; 2310ae813fd8SSepherosa Ziehau 2311ae813fd8SSepherosa Ziehau nfe_set_paddr_rxdesc(sc, ring, idx, jbuf->physaddr); 2312ae813fd8SSepherosa Ziehau return 0; 2313ae813fd8SSepherosa Ziehau } 2314ae813fd8SSepherosa Ziehau 2315ae813fd8SSepherosa Ziehau static void 2316ae813fd8SSepherosa Ziehau nfe_set_paddr_rxdesc(struct nfe_softc *sc, struct nfe_rx_ring *ring, int idx, 2317ae813fd8SSepherosa Ziehau bus_addr_t physaddr) 2318ae813fd8SSepherosa Ziehau { 231988d487c3SSepherosa Ziehau if (sc->sc_caps & NFE_40BIT_ADDR) { 2320ae813fd8SSepherosa Ziehau struct nfe_desc64 *desc64 = &ring->desc64[idx]; 2321ae813fd8SSepherosa Ziehau 23227752918dSSepherosa Ziehau desc64->physaddr[0] = htole32(NFE_ADDR_HI(physaddr)); 23237752918dSSepherosa Ziehau desc64->physaddr[1] = htole32(NFE_ADDR_LO(physaddr)); 2324ae813fd8SSepherosa Ziehau } else { 2325ae813fd8SSepherosa Ziehau struct nfe_desc32 *desc32 = &ring->desc32[idx]; 2326ae813fd8SSepherosa Ziehau 2327ae813fd8SSepherosa Ziehau desc32->physaddr = htole32(physaddr); 2328ae813fd8SSepherosa Ziehau } 2329ae813fd8SSepherosa Ziehau } 2330ae813fd8SSepherosa Ziehau 2331ae813fd8SSepherosa Ziehau static void 2332ae813fd8SSepherosa Ziehau nfe_set_ready_rxdesc(struct nfe_softc *sc, struct nfe_rx_ring *ring, int idx) 2333ae813fd8SSepherosa Ziehau { 233488d487c3SSepherosa Ziehau if (sc->sc_caps & NFE_40BIT_ADDR) { 2335ae813fd8SSepherosa Ziehau struct nfe_desc64 *desc64 = &ring->desc64[idx]; 2336ae813fd8SSepherosa Ziehau 2337ae813fd8SSepherosa Ziehau desc64->length = htole16(ring->bufsz); 2338ae813fd8SSepherosa Ziehau desc64->flags = htole16(NFE_RX_READY); 2339ae813fd8SSepherosa Ziehau } else { 2340ae813fd8SSepherosa Ziehau struct nfe_desc32 *desc32 = &ring->desc32[idx]; 2341ae813fd8SSepherosa Ziehau 2342ae813fd8SSepherosa Ziehau desc32->length = htole16(ring->bufsz); 2343ae813fd8SSepherosa Ziehau desc32->flags = htole16(NFE_RX_READY); 2344ae813fd8SSepherosa Ziehau } 2345ae813fd8SSepherosa Ziehau } 2346ec9403d0SSepherosa Ziehau 2347ec9403d0SSepherosa Ziehau static int 2348ec9403d0SSepherosa Ziehau nfe_sysctl_imtime(SYSCTL_HANDLER_ARGS) 2349ec9403d0SSepherosa Ziehau { 2350ec9403d0SSepherosa Ziehau struct nfe_softc *sc = arg1; 2351ec9403d0SSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 235204b9ef8dSSepherosa Ziehau uint32_t flags; 2353ec9403d0SSepherosa Ziehau int error, v; 2354ec9403d0SSepherosa Ziehau 2355ec9403d0SSepherosa Ziehau lwkt_serialize_enter(ifp->if_serializer); 2356ec9403d0SSepherosa Ziehau 235704b9ef8dSSepherosa Ziehau flags = sc->sc_flags & ~NFE_F_DYN_IM; 2358ec9403d0SSepherosa Ziehau v = sc->sc_imtime; 235904b9ef8dSSepherosa Ziehau if (sc->sc_flags & NFE_F_DYN_IM) 236004b9ef8dSSepherosa Ziehau v = -v; 236104b9ef8dSSepherosa Ziehau 2362ec9403d0SSepherosa Ziehau error = sysctl_handle_int(oidp, &v, 0, req); 2363ec9403d0SSepherosa Ziehau if (error || req->newptr == NULL) 2364ec9403d0SSepherosa Ziehau goto back; 236504b9ef8dSSepherosa Ziehau 236604b9ef8dSSepherosa Ziehau if (v < 0) { 236704b9ef8dSSepherosa Ziehau flags |= NFE_F_DYN_IM; 236804b9ef8dSSepherosa Ziehau v = -v; 2369ec9403d0SSepherosa Ziehau } 2370ec9403d0SSepherosa Ziehau 237104b9ef8dSSepherosa Ziehau if (v != sc->sc_imtime || (flags ^ sc->sc_flags)) { 2372ec9403d0SSepherosa Ziehau int old_imtime = sc->sc_imtime; 237304b9ef8dSSepherosa Ziehau uint32_t old_flags = sc->sc_flags; 2374ec9403d0SSepherosa Ziehau 2375ec9403d0SSepherosa Ziehau sc->sc_imtime = v; 237604b9ef8dSSepherosa Ziehau sc->sc_flags = flags; 2377ec9403d0SSepherosa Ziehau sc->sc_irq_enable = NFE_IRQ_ENABLE(sc); 2378ec9403d0SSepherosa Ziehau 2379ec9403d0SSepherosa Ziehau if ((ifp->if_flags & (IFF_POLLING | IFF_RUNNING)) 2380ec9403d0SSepherosa Ziehau == IFF_RUNNING) { 238104b9ef8dSSepherosa Ziehau if (old_imtime * sc->sc_imtime == 0 || 238204b9ef8dSSepherosa Ziehau (old_flags ^ sc->sc_flags)) { 238304b9ef8dSSepherosa Ziehau ifp->if_init(sc); 238404b9ef8dSSepherosa Ziehau } else { 2385ec9403d0SSepherosa Ziehau NFE_WRITE(sc, NFE_IMTIMER, 2386ec9403d0SSepherosa Ziehau NFE_IMTIME(sc->sc_imtime)); 2387ec9403d0SSepherosa Ziehau } 2388ec9403d0SSepherosa Ziehau } 2389ec9403d0SSepherosa Ziehau } 2390ec9403d0SSepherosa Ziehau back: 2391ec9403d0SSepherosa Ziehau lwkt_serialize_exit(ifp->if_serializer); 2392ec9403d0SSepherosa Ziehau return error; 2393ec9403d0SSepherosa Ziehau } 2394faaea42eSSepherosa Ziehau 2395faaea42eSSepherosa Ziehau static void 2396faaea42eSSepherosa Ziehau nfe_powerup(device_t dev) 2397faaea42eSSepherosa Ziehau { 2398faaea42eSSepherosa Ziehau struct nfe_softc *sc = device_get_softc(dev); 2399faaea42eSSepherosa Ziehau uint32_t pwr_state; 2400faaea42eSSepherosa Ziehau uint16_t did; 2401faaea42eSSepherosa Ziehau 2402faaea42eSSepherosa Ziehau /* 2403faaea42eSSepherosa Ziehau * Bring MAC and PHY out of low power state 2404faaea42eSSepherosa Ziehau */ 2405faaea42eSSepherosa Ziehau 2406faaea42eSSepherosa Ziehau pwr_state = NFE_READ(sc, NFE_PWR_STATE2) & ~NFE_PWRUP_MASK; 2407faaea42eSSepherosa Ziehau 2408faaea42eSSepherosa Ziehau did = pci_get_device(dev); 2409faaea42eSSepherosa Ziehau if ((did == PCI_PRODUCT_NVIDIA_MCP51_LAN1 || 2410faaea42eSSepherosa Ziehau did == PCI_PRODUCT_NVIDIA_MCP51_LAN2) && 2411faaea42eSSepherosa Ziehau pci_get_revid(dev) >= 0xa3) 2412faaea42eSSepherosa Ziehau pwr_state |= NFE_PWRUP_REV_A3; 2413faaea42eSSepherosa Ziehau 2414faaea42eSSepherosa Ziehau NFE_WRITE(sc, NFE_PWR_STATE2, pwr_state); 2415faaea42eSSepherosa Ziehau } 2416faaea42eSSepherosa Ziehau 2417faaea42eSSepherosa Ziehau static void 2418faaea42eSSepherosa Ziehau nfe_mac_reset(struct nfe_softc *sc) 2419faaea42eSSepherosa Ziehau { 2420faaea42eSSepherosa Ziehau uint32_t rxtxctl = sc->rxtxctl_desc | NFE_RXTX_BIT2; 2421faaea42eSSepherosa Ziehau uint32_t macaddr_hi, macaddr_lo, tx_poll; 2422faaea42eSSepherosa Ziehau 2423faaea42eSSepherosa Ziehau NFE_WRITE(sc, NFE_RXTX_CTL, NFE_RXTX_RESET | rxtxctl); 2424faaea42eSSepherosa Ziehau 2425faaea42eSSepherosa Ziehau /* Save several registers for later restoration */ 2426faaea42eSSepherosa Ziehau macaddr_hi = NFE_READ(sc, NFE_MACADDR_HI); 2427faaea42eSSepherosa Ziehau macaddr_lo = NFE_READ(sc, NFE_MACADDR_LO); 2428faaea42eSSepherosa Ziehau tx_poll = NFE_READ(sc, NFE_TX_POLL); 2429faaea42eSSepherosa Ziehau 2430faaea42eSSepherosa Ziehau NFE_WRITE(sc, NFE_MAC_RESET, NFE_RESET_ASSERT); 2431faaea42eSSepherosa Ziehau DELAY(100); 2432faaea42eSSepherosa Ziehau 2433faaea42eSSepherosa Ziehau NFE_WRITE(sc, NFE_MAC_RESET, 0); 2434faaea42eSSepherosa Ziehau DELAY(100); 2435faaea42eSSepherosa Ziehau 2436faaea42eSSepherosa Ziehau /* Restore saved registers */ 2437faaea42eSSepherosa Ziehau NFE_WRITE(sc, NFE_MACADDR_HI, macaddr_hi); 2438faaea42eSSepherosa Ziehau NFE_WRITE(sc, NFE_MACADDR_LO, macaddr_lo); 2439faaea42eSSepherosa Ziehau NFE_WRITE(sc, NFE_TX_POLL, tx_poll); 2440faaea42eSSepherosa Ziehau 2441faaea42eSSepherosa Ziehau NFE_WRITE(sc, NFE_RXTX_CTL, rxtxctl); 2442faaea42eSSepherosa Ziehau } 244304b9ef8dSSepherosa Ziehau 244404b9ef8dSSepherosa Ziehau static void 244504b9ef8dSSepherosa Ziehau nfe_enable_intrs(struct nfe_softc *sc) 244604b9ef8dSSepherosa Ziehau { 244704b9ef8dSSepherosa Ziehau /* 244804b9ef8dSSepherosa Ziehau * NFE_IMTIMER generates a periodic interrupt via NFE_IRQ_TIMER. 244904b9ef8dSSepherosa Ziehau * It is unclear how wide the timer is. Base programming does 245004b9ef8dSSepherosa Ziehau * not seem to effect NFE_IRQ_TX_DONE or NFE_IRQ_RX_DONE so 245104b9ef8dSSepherosa Ziehau * we don't get any interrupt moderation. TX moderation is 245204b9ef8dSSepherosa Ziehau * possible by using the timer interrupt instead of TX_DONE. 245304b9ef8dSSepherosa Ziehau * 245404b9ef8dSSepherosa Ziehau * It is unclear whether there are other bits that can be 245504b9ef8dSSepherosa Ziehau * set to make the NFE device actually do interrupt moderation 245604b9ef8dSSepherosa Ziehau * on the RX side. 245704b9ef8dSSepherosa Ziehau * 245804b9ef8dSSepherosa Ziehau * For now set a 128uS interval as a placemark, but don't use 245904b9ef8dSSepherosa Ziehau * the timer. 246004b9ef8dSSepherosa Ziehau */ 246104b9ef8dSSepherosa Ziehau if (sc->sc_imtime == 0) 246204b9ef8dSSepherosa Ziehau NFE_WRITE(sc, NFE_IMTIMER, NFE_IMTIME_DEFAULT); 246304b9ef8dSSepherosa Ziehau else 246404b9ef8dSSepherosa Ziehau NFE_WRITE(sc, NFE_IMTIMER, NFE_IMTIME(sc->sc_imtime)); 246504b9ef8dSSepherosa Ziehau 246604b9ef8dSSepherosa Ziehau /* Enable interrupts */ 246704b9ef8dSSepherosa Ziehau NFE_WRITE(sc, NFE_IRQ_MASK, sc->sc_irq_enable); 246804b9ef8dSSepherosa Ziehau 246904b9ef8dSSepherosa Ziehau if (sc->sc_irq_enable & NFE_IRQ_TIMER) 247004b9ef8dSSepherosa Ziehau sc->sc_flags |= NFE_F_IRQ_TIMER; 247104b9ef8dSSepherosa Ziehau else 247204b9ef8dSSepherosa Ziehau sc->sc_flags &= ~NFE_F_IRQ_TIMER; 247304b9ef8dSSepherosa Ziehau } 247404b9ef8dSSepherosa Ziehau 247504b9ef8dSSepherosa Ziehau static void 247604b9ef8dSSepherosa Ziehau nfe_disable_intrs(struct nfe_softc *sc) 247704b9ef8dSSepherosa Ziehau { 247804b9ef8dSSepherosa Ziehau /* Disable interrupts */ 247904b9ef8dSSepherosa Ziehau NFE_WRITE(sc, NFE_IRQ_MASK, 0); 248004b9ef8dSSepherosa Ziehau sc->sc_flags &= ~NFE_F_IRQ_TIMER; 248104b9ef8dSSepherosa Ziehau } 2482