1d217d4d9SSepherosa Ziehau /* 2d217d4d9SSepherosa Ziehau * Copyright (c) 2007 The DragonFly Project. All rights reserved. 3d217d4d9SSepherosa Ziehau * 4d217d4d9SSepherosa Ziehau * This code is derived from software contributed to The DragonFly Project 5d217d4d9SSepherosa Ziehau * by Sepherosa Ziehau <sepherosa@gmail.com> 6d217d4d9SSepherosa Ziehau * 7d217d4d9SSepherosa Ziehau * Redistribution and use in source and binary forms, with or without 8d217d4d9SSepherosa Ziehau * modification, are permitted provided that the following conditions 9d217d4d9SSepherosa Ziehau * are met: 10d217d4d9SSepherosa Ziehau * 11d217d4d9SSepherosa Ziehau * 1. Redistributions of source code must retain the above copyright 12d217d4d9SSepherosa Ziehau * notice, this list of conditions and the following disclaimer. 13d217d4d9SSepherosa Ziehau * 2. Redistributions in binary form must reproduce the above copyright 14d217d4d9SSepherosa Ziehau * notice, this list of conditions and the following disclaimer in 15d217d4d9SSepherosa Ziehau * the documentation and/or other materials provided with the 16d217d4d9SSepherosa Ziehau * distribution. 17d217d4d9SSepherosa Ziehau * 3. Neither the name of The DragonFly Project nor the names of its 18d217d4d9SSepherosa Ziehau * contributors may be used to endorse or promote products derived 19d217d4d9SSepherosa Ziehau * from this software without specific, prior written permission. 20d217d4d9SSepherosa Ziehau * 21d217d4d9SSepherosa Ziehau * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22d217d4d9SSepherosa Ziehau * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23d217d4d9SSepherosa Ziehau * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24d217d4d9SSepherosa Ziehau * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25d217d4d9SSepherosa Ziehau * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26d217d4d9SSepherosa Ziehau * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 27d217d4d9SSepherosa Ziehau * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28d217d4d9SSepherosa Ziehau * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 29d217d4d9SSepherosa Ziehau * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30d217d4d9SSepherosa Ziehau * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 31d217d4d9SSepherosa Ziehau * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32d217d4d9SSepherosa Ziehau * SUCH DAMAGE. 33d217d4d9SSepherosa Ziehau * 34*5a5f28f3SSepherosa Ziehau * $DragonFly: src/sys/dev/netif/et/if_et.c,v 1.11 2008/07/07 13:14:23 sephe Exp $ 35d217d4d9SSepherosa Ziehau */ 36d217d4d9SSepherosa Ziehau 37d217d4d9SSepherosa Ziehau #include <sys/param.h> 38b5b6e4f4SSepherosa Ziehau #include <sys/bitops.h> 39d217d4d9SSepherosa Ziehau #include <sys/endian.h> 40d217d4d9SSepherosa Ziehau #include <sys/kernel.h> 41d217d4d9SSepherosa Ziehau #include <sys/bus.h> 429db4b353SSepherosa Ziehau #include <sys/interrupt.h> 43d217d4d9SSepherosa Ziehau #include <sys/malloc.h> 44d217d4d9SSepherosa Ziehau #include <sys/proc.h> 45d217d4d9SSepherosa Ziehau #include <sys/rman.h> 46d217d4d9SSepherosa Ziehau #include <sys/serialize.h> 47d217d4d9SSepherosa Ziehau #include <sys/socket.h> 48d217d4d9SSepherosa Ziehau #include <sys/sockio.h> 49d217d4d9SSepherosa Ziehau #include <sys/sysctl.h> 50d217d4d9SSepherosa Ziehau 51d217d4d9SSepherosa Ziehau #include <net/ethernet.h> 52d217d4d9SSepherosa Ziehau #include <net/if.h> 53d217d4d9SSepherosa Ziehau #include <net/bpf.h> 54d217d4d9SSepherosa Ziehau #include <net/if_arp.h> 55d217d4d9SSepherosa Ziehau #include <net/if_dl.h> 56d217d4d9SSepherosa Ziehau #include <net/if_media.h> 57d217d4d9SSepherosa Ziehau #include <net/ifq_var.h> 58d217d4d9SSepherosa Ziehau #include <net/vlan/if_vlan_var.h> 59d217d4d9SSepherosa Ziehau 60d217d4d9SSepherosa Ziehau #include <dev/netif/mii_layer/miivar.h> 61d217d4d9SSepherosa Ziehau 62d217d4d9SSepherosa Ziehau #include <bus/pci/pcireg.h> 63d217d4d9SSepherosa Ziehau #include <bus/pci/pcivar.h> 64d217d4d9SSepherosa Ziehau #include <bus/pci/pcidevs.h> 65d217d4d9SSepherosa Ziehau 66b5b6e4f4SSepherosa Ziehau #include <dev/netif/et/if_etreg.h> 67b5b6e4f4SSepherosa Ziehau #include <dev/netif/et/if_etvar.h> 68d217d4d9SSepherosa Ziehau 69b5b6e4f4SSepherosa Ziehau #include "miibus_if.h" 70d217d4d9SSepherosa Ziehau 71d217d4d9SSepherosa Ziehau static int et_probe(device_t); 72d217d4d9SSepherosa Ziehau static int et_attach(device_t); 73d217d4d9SSepherosa Ziehau static int et_detach(device_t); 74d217d4d9SSepherosa Ziehau static int et_shutdown(device_t); 75d217d4d9SSepherosa Ziehau 76d217d4d9SSepherosa Ziehau static int et_miibus_readreg(device_t, int, int); 77d217d4d9SSepherosa Ziehau static int et_miibus_writereg(device_t, int, int, int); 78d217d4d9SSepherosa Ziehau static void et_miibus_statchg(device_t); 79d217d4d9SSepherosa Ziehau 80d217d4d9SSepherosa Ziehau static void et_init(void *); 81d217d4d9SSepherosa Ziehau static int et_ioctl(struct ifnet *, u_long, caddr_t, struct ucred *); 82d217d4d9SSepherosa Ziehau static void et_start(struct ifnet *); 83d217d4d9SSepherosa Ziehau static void et_watchdog(struct ifnet *); 84d217d4d9SSepherosa Ziehau static int et_ifmedia_upd(struct ifnet *); 85d217d4d9SSepherosa Ziehau static void et_ifmedia_sts(struct ifnet *, struct ifmediareq *); 86d217d4d9SSepherosa Ziehau 87d217d4d9SSepherosa Ziehau static int et_sysctl_rx_intr_npkts(SYSCTL_HANDLER_ARGS); 88d217d4d9SSepherosa Ziehau static int et_sysctl_rx_intr_delay(SYSCTL_HANDLER_ARGS); 89d217d4d9SSepherosa Ziehau 90d217d4d9SSepherosa Ziehau static void et_intr(void *); 91d217d4d9SSepherosa Ziehau static void et_enable_intrs(struct et_softc *, uint32_t); 92d217d4d9SSepherosa Ziehau static void et_disable_intrs(struct et_softc *); 93d217d4d9SSepherosa Ziehau static void et_rxeof(struct et_softc *); 94d217d4d9SSepherosa Ziehau static void et_txeof(struct et_softc *); 95d217d4d9SSepherosa Ziehau 96d217d4d9SSepherosa Ziehau static int et_dma_alloc(device_t); 97d217d4d9SSepherosa Ziehau static void et_dma_free(device_t); 98d217d4d9SSepherosa Ziehau static int et_dma_mem_create(device_t, bus_size_t, bus_dma_tag_t *, 99d217d4d9SSepherosa Ziehau void **, bus_addr_t *, bus_dmamap_t *); 100d217d4d9SSepherosa Ziehau static void et_dma_mem_destroy(bus_dma_tag_t, void *, bus_dmamap_t); 101d217d4d9SSepherosa Ziehau static int et_dma_mbuf_create(device_t); 102d217d4d9SSepherosa Ziehau static void et_dma_mbuf_destroy(device_t, int, const int[]); 1033effc1bfSSepherosa Ziehau static int et_jumbo_mem_alloc(device_t); 1043effc1bfSSepherosa Ziehau static void et_jumbo_mem_free(device_t); 105d217d4d9SSepherosa Ziehau static void et_dma_ring_addr(void *, bus_dma_segment_t *, int, int); 106d217d4d9SSepherosa Ziehau static void et_dma_buf_addr(void *, bus_dma_segment_t *, int, 107d217d4d9SSepherosa Ziehau bus_size_t, int); 108d217d4d9SSepherosa Ziehau static int et_init_tx_ring(struct et_softc *); 109d217d4d9SSepherosa Ziehau static int et_init_rx_ring(struct et_softc *); 110d217d4d9SSepherosa Ziehau static void et_free_tx_ring(struct et_softc *); 111d217d4d9SSepherosa Ziehau static void et_free_rx_ring(struct et_softc *); 112d217d4d9SSepherosa Ziehau static int et_encap(struct et_softc *, struct mbuf **); 1133effc1bfSSepherosa Ziehau static struct et_jslot * 1143effc1bfSSepherosa Ziehau et_jalloc(struct et_jumbo_data *); 1153effc1bfSSepherosa Ziehau static void et_jfree(void *); 1163effc1bfSSepherosa Ziehau static void et_jref(void *); 117d217d4d9SSepherosa Ziehau static int et_newbuf(struct et_rxbuf_data *, int, int, int); 118d217d4d9SSepherosa Ziehau static int et_newbuf_cluster(struct et_rxbuf_data *, int, int); 119d217d4d9SSepherosa Ziehau static int et_newbuf_hdr(struct et_rxbuf_data *, int, int); 1203effc1bfSSepherosa Ziehau static int et_newbuf_jumbo(struct et_rxbuf_data *, int, int); 121d217d4d9SSepherosa Ziehau 122d217d4d9SSepherosa Ziehau static void et_stop(struct et_softc *); 123d217d4d9SSepherosa Ziehau static int et_chip_init(struct et_softc *); 124d217d4d9SSepherosa Ziehau static void et_chip_attach(struct et_softc *); 125d217d4d9SSepherosa Ziehau static void et_init_mac(struct et_softc *); 126d217d4d9SSepherosa Ziehau static void et_init_rxmac(struct et_softc *); 127d217d4d9SSepherosa Ziehau static void et_init_txmac(struct et_softc *); 128d217d4d9SSepherosa Ziehau static int et_init_rxdma(struct et_softc *); 129d217d4d9SSepherosa Ziehau static int et_init_txdma(struct et_softc *); 130d217d4d9SSepherosa Ziehau static int et_start_rxdma(struct et_softc *); 131d217d4d9SSepherosa Ziehau static int et_start_txdma(struct et_softc *); 132d217d4d9SSepherosa Ziehau static int et_stop_rxdma(struct et_softc *); 133d217d4d9SSepherosa Ziehau static int et_stop_txdma(struct et_softc *); 13460d2de1fSSepherosa Ziehau static int et_enable_txrx(struct et_softc *, int); 135d217d4d9SSepherosa Ziehau static void et_reset(struct et_softc *); 136d217d4d9SSepherosa Ziehau static int et_bus_config(device_t); 137d217d4d9SSepherosa Ziehau static void et_get_eaddr(device_t, uint8_t[]); 138d217d4d9SSepherosa Ziehau static void et_setmulti(struct et_softc *); 139d217d4d9SSepherosa Ziehau static void et_tick(void *); 14060d2de1fSSepherosa Ziehau static void et_setmedia(struct et_softc *); 1413effc1bfSSepherosa Ziehau static void et_setup_rxdesc(struct et_rxbuf_data *, int, bus_addr_t); 142d217d4d9SSepherosa Ziehau 143d217d4d9SSepherosa Ziehau static const struct et_dev { 144d217d4d9SSepherosa Ziehau uint16_t vid; 145d217d4d9SSepherosa Ziehau uint16_t did; 146d217d4d9SSepherosa Ziehau const char *desc; 147d217d4d9SSepherosa Ziehau } et_devices[] = { 148d217d4d9SSepherosa Ziehau { PCI_VENDOR_LUCENT, PCI_PRODUCT_LUCENT_ET1310, 149d217d4d9SSepherosa Ziehau "Agere ET1310 Gigabit Ethernet" }, 150d217d4d9SSepherosa Ziehau { PCI_VENDOR_LUCENT, PCI_PRODUCT_LUCENT_ET1310_FAST, 151d217d4d9SSepherosa Ziehau "Agere ET1310 Fast Ethernet" }, 152d217d4d9SSepherosa Ziehau { 0, 0, NULL } 153d217d4d9SSepherosa Ziehau }; 154d217d4d9SSepherosa Ziehau 155d217d4d9SSepherosa Ziehau static device_method_t et_methods[] = { 156d217d4d9SSepherosa Ziehau DEVMETHOD(device_probe, et_probe), 157d217d4d9SSepherosa Ziehau DEVMETHOD(device_attach, et_attach), 158d217d4d9SSepherosa Ziehau DEVMETHOD(device_detach, et_detach), 159d217d4d9SSepherosa Ziehau DEVMETHOD(device_shutdown, et_shutdown), 160d217d4d9SSepherosa Ziehau #if 0 161d217d4d9SSepherosa Ziehau DEVMETHOD(device_suspend, et_suspend), 162d217d4d9SSepherosa Ziehau DEVMETHOD(device_resume, et_resume), 163d217d4d9SSepherosa Ziehau #endif 164d217d4d9SSepherosa Ziehau 165d217d4d9SSepherosa Ziehau DEVMETHOD(bus_print_child, bus_generic_print_child), 166d217d4d9SSepherosa Ziehau DEVMETHOD(bus_driver_added, bus_generic_driver_added), 167d217d4d9SSepherosa Ziehau 168d217d4d9SSepherosa Ziehau DEVMETHOD(miibus_readreg, et_miibus_readreg), 169d217d4d9SSepherosa Ziehau DEVMETHOD(miibus_writereg, et_miibus_writereg), 170d217d4d9SSepherosa Ziehau DEVMETHOD(miibus_statchg, et_miibus_statchg), 171d217d4d9SSepherosa Ziehau 172d217d4d9SSepherosa Ziehau { 0, 0 } 173d217d4d9SSepherosa Ziehau }; 174d217d4d9SSepherosa Ziehau 175d217d4d9SSepherosa Ziehau static driver_t et_driver = { 176d217d4d9SSepherosa Ziehau "et", 177d217d4d9SSepherosa Ziehau et_methods, 178d217d4d9SSepherosa Ziehau sizeof(struct et_softc) 179d217d4d9SSepherosa Ziehau }; 180d217d4d9SSepherosa Ziehau 181d217d4d9SSepherosa Ziehau static devclass_t et_devclass; 182d217d4d9SSepherosa Ziehau 183d217d4d9SSepherosa Ziehau DECLARE_DUMMY_MODULE(if_et); 184d217d4d9SSepherosa Ziehau MODULE_DEPEND(if_et, miibus, 1, 1, 1); 185d217d4d9SSepherosa Ziehau DRIVER_MODULE(if_et, pci, et_driver, et_devclass, 0, 0); 186d217d4d9SSepherosa Ziehau DRIVER_MODULE(miibus, et, miibus_driver, miibus_devclass, 0, 0); 187d217d4d9SSepherosa Ziehau 188d217d4d9SSepherosa Ziehau static int et_rx_intr_npkts = 32; 189d217d4d9SSepherosa Ziehau static int et_rx_intr_delay = 20; /* x10 usec */ 190d217d4d9SSepherosa Ziehau static int et_tx_intr_nsegs = 126; 191d217d4d9SSepherosa Ziehau static uint32_t et_timer = 1000 * 1000 * 1000; /* nanosec */ 192d217d4d9SSepherosa Ziehau 193d217d4d9SSepherosa Ziehau TUNABLE_INT("hw.et.timer", &et_timer); 194d217d4d9SSepherosa Ziehau TUNABLE_INT("hw.et.rx_intr_npkts", &et_rx_intr_npkts); 195f285c685SSascha Wildner TUNABLE_INT("hw.et.rx_intr_delay", &et_rx_intr_delay); 196af6a2c2aSSascha Wildner TUNABLE_INT("hw.et.tx_intr_nsegs", &et_tx_intr_nsegs); 197d217d4d9SSepherosa Ziehau 198d217d4d9SSepherosa Ziehau struct et_bsize { 199d217d4d9SSepherosa Ziehau int bufsize; 2003effc1bfSSepherosa Ziehau int jumbo; 201d217d4d9SSepherosa Ziehau et_newbuf_t newbuf; 202d217d4d9SSepherosa Ziehau }; 203d217d4d9SSepherosa Ziehau 2043effc1bfSSepherosa Ziehau static const struct et_bsize et_bufsize_std[ET_RX_NRING] = { 2053effc1bfSSepherosa Ziehau { .bufsize = ET_RXDMA_CTRL_RING0_128, .jumbo = 0, 2063effc1bfSSepherosa Ziehau .newbuf = et_newbuf_hdr }, 2073effc1bfSSepherosa Ziehau { .bufsize = ET_RXDMA_CTRL_RING1_2048, .jumbo = 0, 2083effc1bfSSepherosa Ziehau .newbuf = et_newbuf_cluster }, 2093effc1bfSSepherosa Ziehau }; 2103effc1bfSSepherosa Ziehau 2113effc1bfSSepherosa Ziehau static const struct et_bsize et_bufsize_jumbo[ET_RX_NRING] = { 2123effc1bfSSepherosa Ziehau { .bufsize = ET_RXDMA_CTRL_RING0_128, .jumbo = 0, 2133effc1bfSSepherosa Ziehau .newbuf = et_newbuf_hdr }, 2143effc1bfSSepherosa Ziehau { .bufsize = ET_RXDMA_CTRL_RING1_16384, .jumbo = 1, 2153effc1bfSSepherosa Ziehau .newbuf = et_newbuf_jumbo }, 216d217d4d9SSepherosa Ziehau }; 217d217d4d9SSepherosa Ziehau 218d217d4d9SSepherosa Ziehau static int 219d217d4d9SSepherosa Ziehau et_probe(device_t dev) 220d217d4d9SSepherosa Ziehau { 221d217d4d9SSepherosa Ziehau const struct et_dev *d; 222d217d4d9SSepherosa Ziehau uint16_t did, vid; 223d217d4d9SSepherosa Ziehau 224d217d4d9SSepherosa Ziehau vid = pci_get_vendor(dev); 225d217d4d9SSepherosa Ziehau did = pci_get_device(dev); 226d217d4d9SSepherosa Ziehau 227d217d4d9SSepherosa Ziehau for (d = et_devices; d->desc != NULL; ++d) { 228d217d4d9SSepherosa Ziehau if (vid == d->vid && did == d->did) { 229d217d4d9SSepherosa Ziehau device_set_desc(dev, d->desc); 230d217d4d9SSepherosa Ziehau return 0; 231d217d4d9SSepherosa Ziehau } 232d217d4d9SSepherosa Ziehau } 233d217d4d9SSepherosa Ziehau return ENXIO; 234d217d4d9SSepherosa Ziehau } 235d217d4d9SSepherosa Ziehau 236d217d4d9SSepherosa Ziehau static int 237d217d4d9SSepherosa Ziehau et_attach(device_t dev) 238d217d4d9SSepherosa Ziehau { 239d217d4d9SSepherosa Ziehau struct et_softc *sc = device_get_softc(dev); 240d217d4d9SSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 241d217d4d9SSepherosa Ziehau uint8_t eaddr[ETHER_ADDR_LEN]; 242d217d4d9SSepherosa Ziehau int error; 243d217d4d9SSepherosa Ziehau 244d217d4d9SSepherosa Ziehau if_initname(ifp, device_get_name(dev), device_get_unit(dev)); 245d217d4d9SSepherosa Ziehau callout_init(&sc->sc_tick); 246d217d4d9SSepherosa Ziehau 247d217d4d9SSepherosa Ziehau /* 248d217d4d9SSepherosa Ziehau * Initialize tunables 249d217d4d9SSepherosa Ziehau */ 250d217d4d9SSepherosa Ziehau sc->sc_rx_intr_npkts = et_rx_intr_npkts; 251d217d4d9SSepherosa Ziehau sc->sc_rx_intr_delay = et_rx_intr_delay; 252d217d4d9SSepherosa Ziehau sc->sc_tx_intr_nsegs = et_tx_intr_nsegs; 253d217d4d9SSepherosa Ziehau sc->sc_timer = et_timer; 254d217d4d9SSepherosa Ziehau 255d217d4d9SSepherosa Ziehau #ifndef BURN_BRIDGES 256d217d4d9SSepherosa Ziehau if (pci_get_powerstate(dev) != PCI_POWERSTATE_D0) { 257d217d4d9SSepherosa Ziehau uint32_t irq, mem; 258d217d4d9SSepherosa Ziehau 259d217d4d9SSepherosa Ziehau irq = pci_read_config(dev, PCIR_INTLINE, 4); 260d217d4d9SSepherosa Ziehau mem = pci_read_config(dev, ET_PCIR_BAR, 4); 261d217d4d9SSepherosa Ziehau 262d217d4d9SSepherosa Ziehau device_printf(dev, "chip is in D%d power mode " 263d217d4d9SSepherosa Ziehau "-- setting to D0\n", pci_get_powerstate(dev)); 264d217d4d9SSepherosa Ziehau 265d217d4d9SSepherosa Ziehau pci_set_powerstate(dev, PCI_POWERSTATE_D0); 266d217d4d9SSepherosa Ziehau 267d217d4d9SSepherosa Ziehau pci_write_config(dev, PCIR_INTLINE, irq, 4); 268d217d4d9SSepherosa Ziehau pci_write_config(dev, ET_PCIR_BAR, mem, 4); 269d217d4d9SSepherosa Ziehau } 270d217d4d9SSepherosa Ziehau #endif /* !BURN_BRIDGE */ 271d217d4d9SSepherosa Ziehau 272d217d4d9SSepherosa Ziehau /* Enable bus mastering */ 273d217d4d9SSepherosa Ziehau pci_enable_busmaster(dev); 274d217d4d9SSepherosa Ziehau 275d217d4d9SSepherosa Ziehau /* 276d217d4d9SSepherosa Ziehau * Allocate IO memory 277d217d4d9SSepherosa Ziehau */ 278d217d4d9SSepherosa Ziehau sc->sc_mem_rid = ET_PCIR_BAR; 279d217d4d9SSepherosa Ziehau sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 280d217d4d9SSepherosa Ziehau &sc->sc_mem_rid, RF_ACTIVE); 281d217d4d9SSepherosa Ziehau if (sc->sc_mem_res == NULL) { 282d217d4d9SSepherosa Ziehau device_printf(dev, "can't allocate IO memory\n"); 283d217d4d9SSepherosa Ziehau return ENXIO; 284d217d4d9SSepherosa Ziehau } 285d217d4d9SSepherosa Ziehau sc->sc_mem_bt = rman_get_bustag(sc->sc_mem_res); 286d217d4d9SSepherosa Ziehau sc->sc_mem_bh = rman_get_bushandle(sc->sc_mem_res); 287d217d4d9SSepherosa Ziehau 288d217d4d9SSepherosa Ziehau /* 289d217d4d9SSepherosa Ziehau * Allocate IRQ 290d217d4d9SSepherosa Ziehau */ 291d217d4d9SSepherosa Ziehau sc->sc_irq_rid = 0; 292d217d4d9SSepherosa Ziehau sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, 293d217d4d9SSepherosa Ziehau &sc->sc_irq_rid, 294d217d4d9SSepherosa Ziehau RF_SHAREABLE | RF_ACTIVE); 295d217d4d9SSepherosa Ziehau if (sc->sc_irq_res == NULL) { 296d217d4d9SSepherosa Ziehau device_printf(dev, "can't allocate irq\n"); 297d217d4d9SSepherosa Ziehau error = ENXIO; 298d217d4d9SSepherosa Ziehau goto fail; 299d217d4d9SSepherosa Ziehau } 300d217d4d9SSepherosa Ziehau 301d217d4d9SSepherosa Ziehau /* 302d217d4d9SSepherosa Ziehau * Create sysctl tree 303d217d4d9SSepherosa Ziehau */ 304d217d4d9SSepherosa Ziehau sysctl_ctx_init(&sc->sc_sysctl_ctx); 305d217d4d9SSepherosa Ziehau sc->sc_sysctl_tree = SYSCTL_ADD_NODE(&sc->sc_sysctl_ctx, 306d217d4d9SSepherosa Ziehau SYSCTL_STATIC_CHILDREN(_hw), 307d217d4d9SSepherosa Ziehau OID_AUTO, 308d217d4d9SSepherosa Ziehau device_get_nameunit(dev), 309d217d4d9SSepherosa Ziehau CTLFLAG_RD, 0, ""); 310d217d4d9SSepherosa Ziehau if (sc->sc_sysctl_tree == NULL) { 311d217d4d9SSepherosa Ziehau device_printf(dev, "can't add sysctl node\n"); 312d217d4d9SSepherosa Ziehau error = ENXIO; 313d217d4d9SSepherosa Ziehau goto fail; 314d217d4d9SSepherosa Ziehau } 315d217d4d9SSepherosa Ziehau 316d217d4d9SSepherosa Ziehau SYSCTL_ADD_PROC(&sc->sc_sysctl_ctx, 317d217d4d9SSepherosa Ziehau SYSCTL_CHILDREN(sc->sc_sysctl_tree), 318d217d4d9SSepherosa Ziehau OID_AUTO, "rx_intr_npkts", CTLTYPE_INT | CTLFLAG_RW, 319d217d4d9SSepherosa Ziehau sc, 0, et_sysctl_rx_intr_npkts, "I", 320d217d4d9SSepherosa Ziehau "RX IM, # packets per RX interrupt"); 321d217d4d9SSepherosa Ziehau SYSCTL_ADD_PROC(&sc->sc_sysctl_ctx, 322d217d4d9SSepherosa Ziehau SYSCTL_CHILDREN(sc->sc_sysctl_tree), 323d217d4d9SSepherosa Ziehau OID_AUTO, "rx_intr_delay", CTLTYPE_INT | CTLFLAG_RW, 324d217d4d9SSepherosa Ziehau sc, 0, et_sysctl_rx_intr_delay, "I", 325d217d4d9SSepherosa Ziehau "RX IM, RX interrupt delay (x10 usec)"); 326d217d4d9SSepherosa Ziehau SYSCTL_ADD_INT(&sc->sc_sysctl_ctx, 327d217d4d9SSepherosa Ziehau SYSCTL_CHILDREN(sc->sc_sysctl_tree), OID_AUTO, 328d217d4d9SSepherosa Ziehau "tx_intr_nsegs", CTLFLAG_RW, &sc->sc_tx_intr_nsegs, 0, 329d217d4d9SSepherosa Ziehau "TX IM, # segments per TX interrupt"); 330d217d4d9SSepherosa Ziehau SYSCTL_ADD_UINT(&sc->sc_sysctl_ctx, 331d217d4d9SSepherosa Ziehau SYSCTL_CHILDREN(sc->sc_sysctl_tree), OID_AUTO, 332d217d4d9SSepherosa Ziehau "timer", CTLFLAG_RW, &sc->sc_timer, 0, 333d217d4d9SSepherosa Ziehau "TX timer"); 334d217d4d9SSepherosa Ziehau 335d217d4d9SSepherosa Ziehau error = et_bus_config(dev); 336d217d4d9SSepherosa Ziehau if (error) 337d217d4d9SSepherosa Ziehau goto fail; 338d217d4d9SSepherosa Ziehau 339d217d4d9SSepherosa Ziehau et_get_eaddr(dev, eaddr); 340d217d4d9SSepherosa Ziehau 341d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_PM, 342d217d4d9SSepherosa Ziehau ET_PM_SYSCLK_GATE | ET_PM_TXCLK_GATE | ET_PM_RXCLK_GATE); 343d217d4d9SSepherosa Ziehau 344d217d4d9SSepherosa Ziehau et_reset(sc); 345d217d4d9SSepherosa Ziehau 346d217d4d9SSepherosa Ziehau et_disable_intrs(sc); 347d217d4d9SSepherosa Ziehau 348d217d4d9SSepherosa Ziehau error = et_dma_alloc(dev); 349d217d4d9SSepherosa Ziehau if (error) 350d217d4d9SSepherosa Ziehau goto fail; 351d217d4d9SSepherosa Ziehau 352d217d4d9SSepherosa Ziehau ifp->if_softc = sc; 353d217d4d9SSepherosa Ziehau ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 354d217d4d9SSepherosa Ziehau ifp->if_init = et_init; 355d217d4d9SSepherosa Ziehau ifp->if_ioctl = et_ioctl; 356d217d4d9SSepherosa Ziehau ifp->if_start = et_start; 357d217d4d9SSepherosa Ziehau ifp->if_watchdog = et_watchdog; 358d217d4d9SSepherosa Ziehau ifp->if_mtu = ETHERMTU; 35939fdb7b3SSepherosa Ziehau ifp->if_capabilities = IFCAP_VLAN_MTU; 36039fdb7b3SSepherosa Ziehau ifp->if_capenable = ifp->if_capabilities; 361d217d4d9SSepherosa Ziehau ifq_set_maxlen(&ifp->if_snd, ET_TX_NDESC); 362d217d4d9SSepherosa Ziehau ifq_set_ready(&ifp->if_snd); 363d217d4d9SSepherosa Ziehau 364d217d4d9SSepherosa Ziehau et_chip_attach(sc); 365d217d4d9SSepherosa Ziehau 366d217d4d9SSepherosa Ziehau error = mii_phy_probe(dev, &sc->sc_miibus, 367d217d4d9SSepherosa Ziehau et_ifmedia_upd, et_ifmedia_sts); 368d217d4d9SSepherosa Ziehau if (error) { 369d217d4d9SSepherosa Ziehau device_printf(dev, "can't probe any PHY\n"); 370d217d4d9SSepherosa Ziehau goto fail; 371d217d4d9SSepherosa Ziehau } 372d217d4d9SSepherosa Ziehau 373d217d4d9SSepherosa Ziehau ether_ifattach(ifp, eaddr, NULL); 374d217d4d9SSepherosa Ziehau 375d217d4d9SSepherosa Ziehau error = bus_setup_intr(dev, sc->sc_irq_res, INTR_MPSAFE, et_intr, sc, 376d217d4d9SSepherosa Ziehau &sc->sc_irq_handle, ifp->if_serializer); 377d217d4d9SSepherosa Ziehau if (error) { 378d217d4d9SSepherosa Ziehau ether_ifdetach(ifp); 379d217d4d9SSepherosa Ziehau device_printf(dev, "can't setup intr\n"); 380d217d4d9SSepherosa Ziehau goto fail; 381d217d4d9SSepherosa Ziehau } 3829db4b353SSepherosa Ziehau 3839db4b353SSepherosa Ziehau ifp->if_cpuid = ithread_cpuid(rman_get_start(sc->sc_irq_res)); 3849db4b353SSepherosa Ziehau KKASSERT(ifp->if_cpuid >= 0 && ifp->if_cpuid < ncpus); 3859db4b353SSepherosa Ziehau 386d217d4d9SSepherosa Ziehau return 0; 387d217d4d9SSepherosa Ziehau fail: 388d217d4d9SSepherosa Ziehau et_detach(dev); 389d217d4d9SSepherosa Ziehau return error; 390d217d4d9SSepherosa Ziehau } 391d217d4d9SSepherosa Ziehau 392d217d4d9SSepherosa Ziehau static int 393d217d4d9SSepherosa Ziehau et_detach(device_t dev) 394d217d4d9SSepherosa Ziehau { 395d217d4d9SSepherosa Ziehau struct et_softc *sc = device_get_softc(dev); 396d217d4d9SSepherosa Ziehau 397d217d4d9SSepherosa Ziehau if (device_is_attached(dev)) { 398d217d4d9SSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 399d217d4d9SSepherosa Ziehau 400d217d4d9SSepherosa Ziehau lwkt_serialize_enter(ifp->if_serializer); 401d217d4d9SSepherosa Ziehau et_stop(sc); 402d217d4d9SSepherosa Ziehau bus_teardown_intr(dev, sc->sc_irq_res, sc->sc_irq_handle); 403d217d4d9SSepherosa Ziehau lwkt_serialize_exit(ifp->if_serializer); 404d217d4d9SSepherosa Ziehau 405d217d4d9SSepherosa Ziehau ether_ifdetach(ifp); 406d217d4d9SSepherosa Ziehau } 407d217d4d9SSepherosa Ziehau 408d217d4d9SSepherosa Ziehau if (sc->sc_sysctl_tree != NULL) 409d217d4d9SSepherosa Ziehau sysctl_ctx_free(&sc->sc_sysctl_ctx); 410d217d4d9SSepherosa Ziehau 411d217d4d9SSepherosa Ziehau if (sc->sc_miibus != NULL) 412d217d4d9SSepherosa Ziehau device_delete_child(dev, sc->sc_miibus); 413d217d4d9SSepherosa Ziehau bus_generic_detach(dev); 414d217d4d9SSepherosa Ziehau 415d217d4d9SSepherosa Ziehau if (sc->sc_irq_res != NULL) { 416d217d4d9SSepherosa Ziehau bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irq_rid, 417d217d4d9SSepherosa Ziehau sc->sc_irq_res); 418d217d4d9SSepherosa Ziehau } 419d217d4d9SSepherosa Ziehau 420d217d4d9SSepherosa Ziehau if (sc->sc_mem_res != NULL) { 421d217d4d9SSepherosa Ziehau bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_mem_rid, 422d217d4d9SSepherosa Ziehau sc->sc_mem_res); 423d217d4d9SSepherosa Ziehau } 424d217d4d9SSepherosa Ziehau 425d217d4d9SSepherosa Ziehau et_dma_free(dev); 426d217d4d9SSepherosa Ziehau 427d217d4d9SSepherosa Ziehau return 0; 428d217d4d9SSepherosa Ziehau } 429d217d4d9SSepherosa Ziehau 430d217d4d9SSepherosa Ziehau static int 431d217d4d9SSepherosa Ziehau et_shutdown(device_t dev) 432d217d4d9SSepherosa Ziehau { 433d217d4d9SSepherosa Ziehau struct et_softc *sc = device_get_softc(dev); 434d217d4d9SSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 435d217d4d9SSepherosa Ziehau 436d217d4d9SSepherosa Ziehau lwkt_serialize_enter(ifp->if_serializer); 437d217d4d9SSepherosa Ziehau et_stop(sc); 438d217d4d9SSepherosa Ziehau lwkt_serialize_exit(ifp->if_serializer); 439d217d4d9SSepherosa Ziehau return 0; 440d217d4d9SSepherosa Ziehau } 441d217d4d9SSepherosa Ziehau 442d217d4d9SSepherosa Ziehau static int 443d217d4d9SSepherosa Ziehau et_miibus_readreg(device_t dev, int phy, int reg) 444d217d4d9SSepherosa Ziehau { 445d217d4d9SSepherosa Ziehau struct et_softc *sc = device_get_softc(dev); 446d217d4d9SSepherosa Ziehau uint32_t val; 447d217d4d9SSepherosa Ziehau int i, ret; 448d217d4d9SSepherosa Ziehau 449d217d4d9SSepherosa Ziehau /* Stop any pending operations */ 450d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_MII_CMD, 0); 451d217d4d9SSepherosa Ziehau 452d217d4d9SSepherosa Ziehau val = __SHIFTIN(phy, ET_MII_ADDR_PHY) | 453d217d4d9SSepherosa Ziehau __SHIFTIN(reg, ET_MII_ADDR_REG); 454d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_MII_ADDR, val); 455d217d4d9SSepherosa Ziehau 456d217d4d9SSepherosa Ziehau /* Start reading */ 457d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_MII_CMD, ET_MII_CMD_READ); 458d217d4d9SSepherosa Ziehau 459d217d4d9SSepherosa Ziehau #define NRETRY 50 460d217d4d9SSepherosa Ziehau 461d217d4d9SSepherosa Ziehau for (i = 0; i < NRETRY; ++i) { 462d217d4d9SSepherosa Ziehau val = CSR_READ_4(sc, ET_MII_IND); 463d217d4d9SSepherosa Ziehau if ((val & (ET_MII_IND_BUSY | ET_MII_IND_INVALID)) == 0) 464d217d4d9SSepherosa Ziehau break; 465d217d4d9SSepherosa Ziehau DELAY(50); 466d217d4d9SSepherosa Ziehau } 467d217d4d9SSepherosa Ziehau if (i == NRETRY) { 468d217d4d9SSepherosa Ziehau if_printf(&sc->arpcom.ac_if, 469d217d4d9SSepherosa Ziehau "read phy %d, reg %d timed out\n", phy, reg); 470d217d4d9SSepherosa Ziehau ret = 0; 471d217d4d9SSepherosa Ziehau goto back; 472d217d4d9SSepherosa Ziehau } 473d217d4d9SSepherosa Ziehau 474d217d4d9SSepherosa Ziehau #undef NRETRY 475d217d4d9SSepherosa Ziehau 476d217d4d9SSepherosa Ziehau val = CSR_READ_4(sc, ET_MII_STAT); 477d217d4d9SSepherosa Ziehau ret = __SHIFTOUT(val, ET_MII_STAT_VALUE); 478d217d4d9SSepherosa Ziehau 479d217d4d9SSepherosa Ziehau back: 480d217d4d9SSepherosa Ziehau /* Make sure that the current operation is stopped */ 481d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_MII_CMD, 0); 482d217d4d9SSepherosa Ziehau return ret; 483d217d4d9SSepherosa Ziehau } 484d217d4d9SSepherosa Ziehau 485d217d4d9SSepherosa Ziehau static int 486d217d4d9SSepherosa Ziehau et_miibus_writereg(device_t dev, int phy, int reg, int val0) 487d217d4d9SSepherosa Ziehau { 488d217d4d9SSepherosa Ziehau struct et_softc *sc = device_get_softc(dev); 489d217d4d9SSepherosa Ziehau uint32_t val; 490d217d4d9SSepherosa Ziehau int i; 491d217d4d9SSepherosa Ziehau 492d217d4d9SSepherosa Ziehau /* Stop any pending operations */ 493d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_MII_CMD, 0); 494d217d4d9SSepherosa Ziehau 495d217d4d9SSepherosa Ziehau val = __SHIFTIN(phy, ET_MII_ADDR_PHY) | 496d217d4d9SSepherosa Ziehau __SHIFTIN(reg, ET_MII_ADDR_REG); 497d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_MII_ADDR, val); 498d217d4d9SSepherosa Ziehau 499d217d4d9SSepherosa Ziehau /* Start writing */ 500d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_MII_CTRL, __SHIFTIN(val0, ET_MII_CTRL_VALUE)); 501d217d4d9SSepherosa Ziehau 502d217d4d9SSepherosa Ziehau #define NRETRY 100 503d217d4d9SSepherosa Ziehau 504d217d4d9SSepherosa Ziehau for (i = 0; i < NRETRY; ++i) { 505d217d4d9SSepherosa Ziehau val = CSR_READ_4(sc, ET_MII_IND); 506d217d4d9SSepherosa Ziehau if ((val & ET_MII_IND_BUSY) == 0) 507d217d4d9SSepherosa Ziehau break; 508d217d4d9SSepherosa Ziehau DELAY(50); 509d217d4d9SSepherosa Ziehau } 510d217d4d9SSepherosa Ziehau if (i == NRETRY) { 511d217d4d9SSepherosa Ziehau if_printf(&sc->arpcom.ac_if, 512d217d4d9SSepherosa Ziehau "write phy %d, reg %d timed out\n", phy, reg); 513d217d4d9SSepherosa Ziehau et_miibus_readreg(dev, phy, reg); 514d217d4d9SSepherosa Ziehau } 515d217d4d9SSepherosa Ziehau 516d217d4d9SSepherosa Ziehau #undef NRETRY 517d217d4d9SSepherosa Ziehau 518d217d4d9SSepherosa Ziehau /* Make sure that the current operation is stopped */ 519d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_MII_CMD, 0); 520d217d4d9SSepherosa Ziehau return 0; 521d217d4d9SSepherosa Ziehau } 522d217d4d9SSepherosa Ziehau 523d217d4d9SSepherosa Ziehau static void 524d217d4d9SSepherosa Ziehau et_miibus_statchg(device_t dev) 525d217d4d9SSepherosa Ziehau { 52660d2de1fSSepherosa Ziehau et_setmedia(device_get_softc(dev)); 527d217d4d9SSepherosa Ziehau } 528d217d4d9SSepherosa Ziehau 529d217d4d9SSepherosa Ziehau static int 530d217d4d9SSepherosa Ziehau et_ifmedia_upd(struct ifnet *ifp) 531d217d4d9SSepherosa Ziehau { 532d217d4d9SSepherosa Ziehau struct et_softc *sc = ifp->if_softc; 533d217d4d9SSepherosa Ziehau struct mii_data *mii = device_get_softc(sc->sc_miibus); 534d217d4d9SSepherosa Ziehau 535d217d4d9SSepherosa Ziehau if (mii->mii_instance != 0) { 536d217d4d9SSepherosa Ziehau struct mii_softc *miisc; 537d217d4d9SSepherosa Ziehau 538d217d4d9SSepherosa Ziehau LIST_FOREACH(miisc, &mii->mii_phys, mii_list) 539d217d4d9SSepherosa Ziehau mii_phy_reset(miisc); 540d217d4d9SSepherosa Ziehau } 541d217d4d9SSepherosa Ziehau mii_mediachg(mii); 542d217d4d9SSepherosa Ziehau 543d217d4d9SSepherosa Ziehau return 0; 544d217d4d9SSepherosa Ziehau } 545d217d4d9SSepherosa Ziehau 546d217d4d9SSepherosa Ziehau static void 547d217d4d9SSepherosa Ziehau et_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr) 548d217d4d9SSepherosa Ziehau { 549d217d4d9SSepherosa Ziehau struct et_softc *sc = ifp->if_softc; 550d217d4d9SSepherosa Ziehau struct mii_data *mii = device_get_softc(sc->sc_miibus); 551d217d4d9SSepherosa Ziehau 552d217d4d9SSepherosa Ziehau mii_pollstat(mii); 553d217d4d9SSepherosa Ziehau ifmr->ifm_active = mii->mii_media_active; 554d217d4d9SSepherosa Ziehau ifmr->ifm_status = mii->mii_media_status; 555d217d4d9SSepherosa Ziehau } 556d217d4d9SSepherosa Ziehau 557d217d4d9SSepherosa Ziehau static void 558d217d4d9SSepherosa Ziehau et_stop(struct et_softc *sc) 559d217d4d9SSepherosa Ziehau { 560d217d4d9SSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 561d217d4d9SSepherosa Ziehau 562d217d4d9SSepherosa Ziehau ASSERT_SERIALIZED(ifp->if_serializer); 563d217d4d9SSepherosa Ziehau 564d217d4d9SSepherosa Ziehau callout_stop(&sc->sc_tick); 565d217d4d9SSepherosa Ziehau 566d217d4d9SSepherosa Ziehau et_stop_rxdma(sc); 567d217d4d9SSepherosa Ziehau et_stop_txdma(sc); 568d217d4d9SSepherosa Ziehau 569d217d4d9SSepherosa Ziehau et_disable_intrs(sc); 570d217d4d9SSepherosa Ziehau 571d217d4d9SSepherosa Ziehau et_free_tx_ring(sc); 572d217d4d9SSepherosa Ziehau et_free_rx_ring(sc); 573d217d4d9SSepherosa Ziehau 574d217d4d9SSepherosa Ziehau et_reset(sc); 575d217d4d9SSepherosa Ziehau 576d217d4d9SSepherosa Ziehau sc->sc_tx = 0; 577d217d4d9SSepherosa Ziehau sc->sc_tx_intr = 0; 5783effc1bfSSepherosa Ziehau sc->sc_flags &= ~ET_FLAG_TXRX_ENABLED; 579d217d4d9SSepherosa Ziehau 580d217d4d9SSepherosa Ziehau ifp->if_timer = 0; 581d217d4d9SSepherosa Ziehau ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); 582d217d4d9SSepherosa Ziehau } 583d217d4d9SSepherosa Ziehau 584d217d4d9SSepherosa Ziehau static int 585d217d4d9SSepherosa Ziehau et_bus_config(device_t dev) 586d217d4d9SSepherosa Ziehau { 587d217d4d9SSepherosa Ziehau uint32_t val, max_plsz; 588d217d4d9SSepherosa Ziehau uint16_t ack_latency, replay_timer; 589d217d4d9SSepherosa Ziehau 590d217d4d9SSepherosa Ziehau /* 591d217d4d9SSepherosa Ziehau * Test whether EEPROM is valid 592d217d4d9SSepherosa Ziehau * NOTE: Read twice to get the correct value 593d217d4d9SSepherosa Ziehau */ 594d217d4d9SSepherosa Ziehau pci_read_config(dev, ET_PCIR_EEPROM_STATUS, 1); 595d217d4d9SSepherosa Ziehau val = pci_read_config(dev, ET_PCIR_EEPROM_STATUS, 1); 596d217d4d9SSepherosa Ziehau if (val & ET_PCIM_EEPROM_STATUS_ERROR) { 597d217d4d9SSepherosa Ziehau device_printf(dev, "EEPROM status error 0x%02x\n", val); 598d217d4d9SSepherosa Ziehau return ENXIO; 599d217d4d9SSepherosa Ziehau } 600d217d4d9SSepherosa Ziehau 601d217d4d9SSepherosa Ziehau /* TODO: LED */ 602d217d4d9SSepherosa Ziehau 603d217d4d9SSepherosa Ziehau /* 604d217d4d9SSepherosa Ziehau * Configure ACK latency and replay timer according to 605d217d4d9SSepherosa Ziehau * max playload size 606d217d4d9SSepherosa Ziehau */ 607d217d4d9SSepherosa Ziehau val = pci_read_config(dev, ET_PCIR_DEVICE_CAPS, 4); 608d217d4d9SSepherosa Ziehau max_plsz = val & ET_PCIM_DEVICE_CAPS_MAX_PLSZ; 609d217d4d9SSepherosa Ziehau 610d217d4d9SSepherosa Ziehau switch (max_plsz) { 611d217d4d9SSepherosa Ziehau case ET_PCIV_DEVICE_CAPS_PLSZ_128: 612d217d4d9SSepherosa Ziehau ack_latency = ET_PCIV_ACK_LATENCY_128; 613d217d4d9SSepherosa Ziehau replay_timer = ET_PCIV_REPLAY_TIMER_128; 614d217d4d9SSepherosa Ziehau break; 615d217d4d9SSepherosa Ziehau 616d217d4d9SSepherosa Ziehau case ET_PCIV_DEVICE_CAPS_PLSZ_256: 617d217d4d9SSepherosa Ziehau ack_latency = ET_PCIV_ACK_LATENCY_256; 618d217d4d9SSepherosa Ziehau replay_timer = ET_PCIV_REPLAY_TIMER_256; 619d217d4d9SSepherosa Ziehau break; 620d217d4d9SSepherosa Ziehau 621d217d4d9SSepherosa Ziehau default: 622d217d4d9SSepherosa Ziehau ack_latency = pci_read_config(dev, ET_PCIR_ACK_LATENCY, 2); 623d217d4d9SSepherosa Ziehau replay_timer = pci_read_config(dev, ET_PCIR_REPLAY_TIMER, 2); 624d217d4d9SSepherosa Ziehau device_printf(dev, "ack latency %u, replay timer %u\n", 625d217d4d9SSepherosa Ziehau ack_latency, replay_timer); 626d217d4d9SSepherosa Ziehau break; 627d217d4d9SSepherosa Ziehau } 628d217d4d9SSepherosa Ziehau if (ack_latency != 0) { 629d217d4d9SSepherosa Ziehau pci_write_config(dev, ET_PCIR_ACK_LATENCY, ack_latency, 2); 630d217d4d9SSepherosa Ziehau pci_write_config(dev, ET_PCIR_REPLAY_TIMER, replay_timer, 2); 631d217d4d9SSepherosa Ziehau } 632d217d4d9SSepherosa Ziehau 633d217d4d9SSepherosa Ziehau /* 634d217d4d9SSepherosa Ziehau * Set L0s and L1 latency timer to 2us 635d217d4d9SSepherosa Ziehau */ 636d217d4d9SSepherosa Ziehau val = ET_PCIV_L0S_LATENCY(2) | ET_PCIV_L1_LATENCY(2); 637d217d4d9SSepherosa Ziehau pci_write_config(dev, ET_PCIR_L0S_L1_LATENCY, val, 1); 638d217d4d9SSepherosa Ziehau 639d217d4d9SSepherosa Ziehau /* 640d217d4d9SSepherosa Ziehau * Set max read request size to 2048 bytes 641d217d4d9SSepherosa Ziehau */ 642d217d4d9SSepherosa Ziehau val = pci_read_config(dev, ET_PCIR_DEVICE_CTRL, 2); 643d217d4d9SSepherosa Ziehau val &= ~ET_PCIM_DEVICE_CTRL_MAX_RRSZ; 644d217d4d9SSepherosa Ziehau val |= ET_PCIV_DEVICE_CTRL_RRSZ_2K; 645d217d4d9SSepherosa Ziehau pci_write_config(dev, ET_PCIR_DEVICE_CTRL, val, 2); 646d217d4d9SSepherosa Ziehau 647d217d4d9SSepherosa Ziehau return 0; 648d217d4d9SSepherosa Ziehau } 649d217d4d9SSepherosa Ziehau 650d217d4d9SSepherosa Ziehau static void 651d217d4d9SSepherosa Ziehau et_get_eaddr(device_t dev, uint8_t eaddr[]) 652d217d4d9SSepherosa Ziehau { 653d217d4d9SSepherosa Ziehau uint32_t val; 654d217d4d9SSepherosa Ziehau int i; 655d217d4d9SSepherosa Ziehau 656d217d4d9SSepherosa Ziehau val = pci_read_config(dev, ET_PCIR_MAC_ADDR0, 4); 657d217d4d9SSepherosa Ziehau for (i = 0; i < 4; ++i) 658d217d4d9SSepherosa Ziehau eaddr[i] = (val >> (8 * i)) & 0xff; 659d217d4d9SSepherosa Ziehau 660d217d4d9SSepherosa Ziehau val = pci_read_config(dev, ET_PCIR_MAC_ADDR1, 2); 661d217d4d9SSepherosa Ziehau for (; i < ETHER_ADDR_LEN; ++i) 662d217d4d9SSepherosa Ziehau eaddr[i] = (val >> (8 * (i - 4))) & 0xff; 663d217d4d9SSepherosa Ziehau } 664d217d4d9SSepherosa Ziehau 665d217d4d9SSepherosa Ziehau static void 666d217d4d9SSepherosa Ziehau et_reset(struct et_softc *sc) 667d217d4d9SSepherosa Ziehau { 668d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_MAC_CFG1, 669d217d4d9SSepherosa Ziehau ET_MAC_CFG1_RST_TXFUNC | ET_MAC_CFG1_RST_RXFUNC | 670d217d4d9SSepherosa Ziehau ET_MAC_CFG1_RST_TXMC | ET_MAC_CFG1_RST_RXMC | 671d217d4d9SSepherosa Ziehau ET_MAC_CFG1_SIM_RST | ET_MAC_CFG1_SOFT_RST); 672d217d4d9SSepherosa Ziehau 673d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_SWRST, 674d217d4d9SSepherosa Ziehau ET_SWRST_TXDMA | ET_SWRST_RXDMA | 675d217d4d9SSepherosa Ziehau ET_SWRST_TXMAC | ET_SWRST_RXMAC | 676d217d4d9SSepherosa Ziehau ET_SWRST_MAC | ET_SWRST_MAC_STAT | ET_SWRST_MMC); 677d217d4d9SSepherosa Ziehau 678d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_MAC_CFG1, 679d217d4d9SSepherosa Ziehau ET_MAC_CFG1_RST_TXFUNC | ET_MAC_CFG1_RST_RXFUNC | 680d217d4d9SSepherosa Ziehau ET_MAC_CFG1_RST_TXMC | ET_MAC_CFG1_RST_RXMC); 681d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_MAC_CFG1, 0); 682d217d4d9SSepherosa Ziehau } 683d217d4d9SSepherosa Ziehau 684d217d4d9SSepherosa Ziehau static void 685d217d4d9SSepherosa Ziehau et_disable_intrs(struct et_softc *sc) 686d217d4d9SSepherosa Ziehau { 687d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_INTR_MASK, 0xffffffff); 688d217d4d9SSepherosa Ziehau } 689d217d4d9SSepherosa Ziehau 690d217d4d9SSepherosa Ziehau static void 691d217d4d9SSepherosa Ziehau et_enable_intrs(struct et_softc *sc, uint32_t intrs) 692d217d4d9SSepherosa Ziehau { 693d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_INTR_MASK, ~intrs); 694d217d4d9SSepherosa Ziehau } 695d217d4d9SSepherosa Ziehau 696d217d4d9SSepherosa Ziehau static int 697d217d4d9SSepherosa Ziehau et_dma_alloc(device_t dev) 698d217d4d9SSepherosa Ziehau { 699d217d4d9SSepherosa Ziehau struct et_softc *sc = device_get_softc(dev); 700d217d4d9SSepherosa Ziehau struct et_txdesc_ring *tx_ring = &sc->sc_tx_ring; 701d217d4d9SSepherosa Ziehau struct et_txstatus_data *txsd = &sc->sc_tx_status; 702d217d4d9SSepherosa Ziehau struct et_rxstat_ring *rxst_ring = &sc->sc_rxstat_ring; 703d217d4d9SSepherosa Ziehau struct et_rxstatus_data *rxsd = &sc->sc_rx_status; 704d217d4d9SSepherosa Ziehau int i, error; 705d217d4d9SSepherosa Ziehau 706d217d4d9SSepherosa Ziehau /* 707d217d4d9SSepherosa Ziehau * Create top level DMA tag 708d217d4d9SSepherosa Ziehau */ 709d217d4d9SSepherosa Ziehau error = bus_dma_tag_create(NULL, 1, 0, 710d217d4d9SSepherosa Ziehau BUS_SPACE_MAXADDR_32BIT, 711d217d4d9SSepherosa Ziehau BUS_SPACE_MAXADDR, 712d217d4d9SSepherosa Ziehau NULL, NULL, 713d217d4d9SSepherosa Ziehau MAXBSIZE, 714d217d4d9SSepherosa Ziehau BUS_SPACE_UNRESTRICTED, 715d217d4d9SSepherosa Ziehau BUS_SPACE_MAXSIZE_32BIT, 716d217d4d9SSepherosa Ziehau 0, &sc->sc_dtag); 717d217d4d9SSepherosa Ziehau if (error) { 718d217d4d9SSepherosa Ziehau device_printf(dev, "can't create DMA tag\n"); 719d217d4d9SSepherosa Ziehau return error; 720d217d4d9SSepherosa Ziehau } 721d217d4d9SSepherosa Ziehau 722d217d4d9SSepherosa Ziehau /* 723d217d4d9SSepherosa Ziehau * Create TX ring DMA stuffs 724d217d4d9SSepherosa Ziehau */ 725d217d4d9SSepherosa Ziehau error = et_dma_mem_create(dev, ET_TX_RING_SIZE, &tx_ring->tr_dtag, 726d217d4d9SSepherosa Ziehau (void **)&tx_ring->tr_desc, 727d217d4d9SSepherosa Ziehau &tx_ring->tr_paddr, &tx_ring->tr_dmap); 728d217d4d9SSepherosa Ziehau if (error) { 729d217d4d9SSepherosa Ziehau device_printf(dev, "can't create TX ring DMA stuffs\n"); 730d217d4d9SSepherosa Ziehau return error; 731d217d4d9SSepherosa Ziehau } 732d217d4d9SSepherosa Ziehau 733d217d4d9SSepherosa Ziehau /* 734d217d4d9SSepherosa Ziehau * Create TX status DMA stuffs 735d217d4d9SSepherosa Ziehau */ 736d217d4d9SSepherosa Ziehau error = et_dma_mem_create(dev, sizeof(uint32_t), &txsd->txsd_dtag, 737d217d4d9SSepherosa Ziehau (void **)&txsd->txsd_status, 738d217d4d9SSepherosa Ziehau &txsd->txsd_paddr, &txsd->txsd_dmap); 739d217d4d9SSepherosa Ziehau if (error) { 740d217d4d9SSepherosa Ziehau device_printf(dev, "can't create TX status DMA stuffs\n"); 741d217d4d9SSepherosa Ziehau return error; 742d217d4d9SSepherosa Ziehau } 743d217d4d9SSepherosa Ziehau 744d217d4d9SSepherosa Ziehau /* 745d217d4d9SSepherosa Ziehau * Create DMA stuffs for RX rings 746d217d4d9SSepherosa Ziehau */ 747d217d4d9SSepherosa Ziehau for (i = 0; i < ET_RX_NRING; ++i) { 748d217d4d9SSepherosa Ziehau static const uint32_t rx_ring_posreg[ET_RX_NRING] = 749d217d4d9SSepherosa Ziehau { ET_RX_RING0_POS, ET_RX_RING1_POS }; 750d217d4d9SSepherosa Ziehau 751d217d4d9SSepherosa Ziehau struct et_rxdesc_ring *rx_ring = &sc->sc_rx_ring[i]; 752d217d4d9SSepherosa Ziehau 753d217d4d9SSepherosa Ziehau error = et_dma_mem_create(dev, ET_RX_RING_SIZE, 754d217d4d9SSepherosa Ziehau &rx_ring->rr_dtag, 755d217d4d9SSepherosa Ziehau (void **)&rx_ring->rr_desc, 756d217d4d9SSepherosa Ziehau &rx_ring->rr_paddr, 757d217d4d9SSepherosa Ziehau &rx_ring->rr_dmap); 758d217d4d9SSepherosa Ziehau if (error) { 759d217d4d9SSepherosa Ziehau device_printf(dev, "can't create DMA stuffs for " 760d217d4d9SSepherosa Ziehau "the %d RX ring\n", i); 761d217d4d9SSepherosa Ziehau return error; 762d217d4d9SSepherosa Ziehau } 763d217d4d9SSepherosa Ziehau rx_ring->rr_posreg = rx_ring_posreg[i]; 764d217d4d9SSepherosa Ziehau } 765d217d4d9SSepherosa Ziehau 766d217d4d9SSepherosa Ziehau /* 767d217d4d9SSepherosa Ziehau * Create RX stat ring DMA stuffs 768d217d4d9SSepherosa Ziehau */ 769d217d4d9SSepherosa Ziehau error = et_dma_mem_create(dev, ET_RXSTAT_RING_SIZE, 770d217d4d9SSepherosa Ziehau &rxst_ring->rsr_dtag, 771d217d4d9SSepherosa Ziehau (void **)&rxst_ring->rsr_stat, 772d217d4d9SSepherosa Ziehau &rxst_ring->rsr_paddr, &rxst_ring->rsr_dmap); 773d217d4d9SSepherosa Ziehau if (error) { 774d217d4d9SSepherosa Ziehau device_printf(dev, "can't create RX stat ring DMA stuffs\n"); 775d217d4d9SSepherosa Ziehau return error; 776d217d4d9SSepherosa Ziehau } 777d217d4d9SSepherosa Ziehau 778d217d4d9SSepherosa Ziehau /* 779d217d4d9SSepherosa Ziehau * Create RX status DMA stuffs 780d217d4d9SSepherosa Ziehau */ 781d217d4d9SSepherosa Ziehau error = et_dma_mem_create(dev, sizeof(struct et_rxstatus), 782d217d4d9SSepherosa Ziehau &rxsd->rxsd_dtag, 783d217d4d9SSepherosa Ziehau (void **)&rxsd->rxsd_status, 784d217d4d9SSepherosa Ziehau &rxsd->rxsd_paddr, &rxsd->rxsd_dmap); 785d217d4d9SSepherosa Ziehau if (error) { 786d217d4d9SSepherosa Ziehau device_printf(dev, "can't create RX status DMA stuffs\n"); 787d217d4d9SSepherosa Ziehau return error; 788d217d4d9SSepherosa Ziehau } 789d217d4d9SSepherosa Ziehau 790d217d4d9SSepherosa Ziehau /* 791d217d4d9SSepherosa Ziehau * Create mbuf DMA stuffs 792d217d4d9SSepherosa Ziehau */ 793d217d4d9SSepherosa Ziehau error = et_dma_mbuf_create(dev); 794d217d4d9SSepherosa Ziehau if (error) 795d217d4d9SSepherosa Ziehau return error; 796d217d4d9SSepherosa Ziehau 7973effc1bfSSepherosa Ziehau /* 7983effc1bfSSepherosa Ziehau * Create jumbo buffer DMA stuffs 7993effc1bfSSepherosa Ziehau * NOTE: Allow it to fail 8003effc1bfSSepherosa Ziehau */ 8013effc1bfSSepherosa Ziehau if (et_jumbo_mem_alloc(dev) == 0) 8023effc1bfSSepherosa Ziehau sc->sc_flags |= ET_FLAG_JUMBO; 8033effc1bfSSepherosa Ziehau 804d217d4d9SSepherosa Ziehau return 0; 805d217d4d9SSepherosa Ziehau } 806d217d4d9SSepherosa Ziehau 807d217d4d9SSepherosa Ziehau static void 808d217d4d9SSepherosa Ziehau et_dma_free(device_t dev) 809d217d4d9SSepherosa Ziehau { 810d217d4d9SSepherosa Ziehau struct et_softc *sc = device_get_softc(dev); 811d217d4d9SSepherosa Ziehau struct et_txdesc_ring *tx_ring = &sc->sc_tx_ring; 812d217d4d9SSepherosa Ziehau struct et_txstatus_data *txsd = &sc->sc_tx_status; 813d217d4d9SSepherosa Ziehau struct et_rxstat_ring *rxst_ring = &sc->sc_rxstat_ring; 814d217d4d9SSepherosa Ziehau struct et_rxstatus_data *rxsd = &sc->sc_rx_status; 815d217d4d9SSepherosa Ziehau int i, rx_done[ET_RX_NRING]; 816d217d4d9SSepherosa Ziehau 817d217d4d9SSepherosa Ziehau /* 818d217d4d9SSepherosa Ziehau * Destroy TX ring DMA stuffs 819d217d4d9SSepherosa Ziehau */ 820d217d4d9SSepherosa Ziehau et_dma_mem_destroy(tx_ring->tr_dtag, tx_ring->tr_desc, 821d217d4d9SSepherosa Ziehau tx_ring->tr_dmap); 822d217d4d9SSepherosa Ziehau 823d217d4d9SSepherosa Ziehau /* 824d217d4d9SSepherosa Ziehau * Destroy TX status DMA stuffs 825d217d4d9SSepherosa Ziehau */ 826d217d4d9SSepherosa Ziehau et_dma_mem_destroy(txsd->txsd_dtag, txsd->txsd_status, 827d217d4d9SSepherosa Ziehau txsd->txsd_dmap); 828d217d4d9SSepherosa Ziehau 829d217d4d9SSepherosa Ziehau /* 830d217d4d9SSepherosa Ziehau * Destroy DMA stuffs for RX rings 831d217d4d9SSepherosa Ziehau */ 832d217d4d9SSepherosa Ziehau for (i = 0; i < ET_RX_NRING; ++i) { 833d217d4d9SSepherosa Ziehau struct et_rxdesc_ring *rx_ring = &sc->sc_rx_ring[i]; 834d217d4d9SSepherosa Ziehau 835d217d4d9SSepherosa Ziehau et_dma_mem_destroy(rx_ring->rr_dtag, rx_ring->rr_desc, 836d217d4d9SSepherosa Ziehau rx_ring->rr_dmap); 837d217d4d9SSepherosa Ziehau } 838d217d4d9SSepherosa Ziehau 839d217d4d9SSepherosa Ziehau /* 840d217d4d9SSepherosa Ziehau * Destroy RX stat ring DMA stuffs 841d217d4d9SSepherosa Ziehau */ 842d217d4d9SSepherosa Ziehau et_dma_mem_destroy(rxst_ring->rsr_dtag, rxst_ring->rsr_stat, 843d217d4d9SSepherosa Ziehau rxst_ring->rsr_dmap); 844d217d4d9SSepherosa Ziehau 845d217d4d9SSepherosa Ziehau /* 846d217d4d9SSepherosa Ziehau * Destroy RX status DMA stuffs 847d217d4d9SSepherosa Ziehau */ 848d217d4d9SSepherosa Ziehau et_dma_mem_destroy(rxsd->rxsd_dtag, rxsd->rxsd_status, 849d217d4d9SSepherosa Ziehau rxsd->rxsd_dmap); 850d217d4d9SSepherosa Ziehau 851d217d4d9SSepherosa Ziehau /* 852d217d4d9SSepherosa Ziehau * Destroy mbuf DMA stuffs 853d217d4d9SSepherosa Ziehau */ 854d217d4d9SSepherosa Ziehau for (i = 0; i < ET_RX_NRING; ++i) 855d217d4d9SSepherosa Ziehau rx_done[i] = ET_RX_NDESC; 856d217d4d9SSepherosa Ziehau et_dma_mbuf_destroy(dev, ET_TX_NDESC, rx_done); 857d217d4d9SSepherosa Ziehau 858d217d4d9SSepherosa Ziehau /* 8593effc1bfSSepherosa Ziehau * Destroy jumbo buffer DMA stuffs 8603effc1bfSSepherosa Ziehau */ 8613effc1bfSSepherosa Ziehau if (sc->sc_flags & ET_FLAG_JUMBO) 8623effc1bfSSepherosa Ziehau et_jumbo_mem_free(dev); 8633effc1bfSSepherosa Ziehau 8643effc1bfSSepherosa Ziehau /* 865d217d4d9SSepherosa Ziehau * Destroy top level DMA tag 866d217d4d9SSepherosa Ziehau */ 867d217d4d9SSepherosa Ziehau if (sc->sc_dtag != NULL) 868d217d4d9SSepherosa Ziehau bus_dma_tag_destroy(sc->sc_dtag); 869d217d4d9SSepherosa Ziehau } 870d217d4d9SSepherosa Ziehau 871d217d4d9SSepherosa Ziehau static int 872d217d4d9SSepherosa Ziehau et_dma_mbuf_create(device_t dev) 873d217d4d9SSepherosa Ziehau { 874d217d4d9SSepherosa Ziehau struct et_softc *sc = device_get_softc(dev); 875d217d4d9SSepherosa Ziehau struct et_txbuf_data *tbd = &sc->sc_tx_data; 876d217d4d9SSepherosa Ziehau int i, error, rx_done[ET_RX_NRING]; 877d217d4d9SSepherosa Ziehau 878d217d4d9SSepherosa Ziehau /* 879d217d4d9SSepherosa Ziehau * Create mbuf DMA tag 880d217d4d9SSepherosa Ziehau */ 881d217d4d9SSepherosa Ziehau error = bus_dma_tag_create(sc->sc_dtag, 1, 0, 882d217d4d9SSepherosa Ziehau BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, 883d217d4d9SSepherosa Ziehau NULL, NULL, 8843effc1bfSSepherosa Ziehau ET_JUMBO_FRAMELEN, ET_NSEG_MAX, 885d217d4d9SSepherosa Ziehau BUS_SPACE_MAXSIZE_32BIT, 886d217d4d9SSepherosa Ziehau BUS_DMA_ALLOCNOW, &sc->sc_mbuf_dtag); 887d217d4d9SSepherosa Ziehau if (error) { 888d217d4d9SSepherosa Ziehau device_printf(dev, "can't create mbuf DMA tag\n"); 889d217d4d9SSepherosa Ziehau return error; 890d217d4d9SSepherosa Ziehau } 891d217d4d9SSepherosa Ziehau 892d217d4d9SSepherosa Ziehau /* 893d217d4d9SSepherosa Ziehau * Create spare DMA map for RX mbufs 894d217d4d9SSepherosa Ziehau */ 895d217d4d9SSepherosa Ziehau error = bus_dmamap_create(sc->sc_mbuf_dtag, 0, &sc->sc_mbuf_tmp_dmap); 896d217d4d9SSepherosa Ziehau if (error) { 897d217d4d9SSepherosa Ziehau device_printf(dev, "can't create spare mbuf DMA map\n"); 898d217d4d9SSepherosa Ziehau bus_dma_tag_destroy(sc->sc_mbuf_dtag); 899d217d4d9SSepherosa Ziehau sc->sc_mbuf_dtag = NULL; 900d217d4d9SSepherosa Ziehau return error; 901d217d4d9SSepherosa Ziehau } 902d217d4d9SSepherosa Ziehau 903d217d4d9SSepherosa Ziehau /* 904d217d4d9SSepherosa Ziehau * Create DMA maps for RX mbufs 905d217d4d9SSepherosa Ziehau */ 906d217d4d9SSepherosa Ziehau bzero(rx_done, sizeof(rx_done)); 907d217d4d9SSepherosa Ziehau for (i = 0; i < ET_RX_NRING; ++i) { 908d217d4d9SSepherosa Ziehau struct et_rxbuf_data *rbd = &sc->sc_rx_data[i]; 909d217d4d9SSepherosa Ziehau int j; 910d217d4d9SSepherosa Ziehau 911d217d4d9SSepherosa Ziehau for (j = 0; j < ET_RX_NDESC; ++j) { 912d217d4d9SSepherosa Ziehau error = bus_dmamap_create(sc->sc_mbuf_dtag, 0, 913d217d4d9SSepherosa Ziehau &rbd->rbd_buf[j].rb_dmap); 914d217d4d9SSepherosa Ziehau if (error) { 915d217d4d9SSepherosa Ziehau device_printf(dev, "can't create %d RX mbuf " 916d217d4d9SSepherosa Ziehau "for %d RX ring\n", j, i); 917d217d4d9SSepherosa Ziehau rx_done[i] = j; 918d217d4d9SSepherosa Ziehau et_dma_mbuf_destroy(dev, 0, rx_done); 919d217d4d9SSepherosa Ziehau return error; 920d217d4d9SSepherosa Ziehau } 921d217d4d9SSepherosa Ziehau } 922d217d4d9SSepherosa Ziehau rx_done[i] = ET_RX_NDESC; 923d217d4d9SSepherosa Ziehau 924d217d4d9SSepherosa Ziehau rbd->rbd_softc = sc; 925d217d4d9SSepherosa Ziehau rbd->rbd_ring = &sc->sc_rx_ring[i]; 926d217d4d9SSepherosa Ziehau } 927d217d4d9SSepherosa Ziehau 928d217d4d9SSepherosa Ziehau /* 929d217d4d9SSepherosa Ziehau * Create DMA maps for TX mbufs 930d217d4d9SSepherosa Ziehau */ 931d217d4d9SSepherosa Ziehau for (i = 0; i < ET_TX_NDESC; ++i) { 932d217d4d9SSepherosa Ziehau error = bus_dmamap_create(sc->sc_mbuf_dtag, 0, 933d217d4d9SSepherosa Ziehau &tbd->tbd_buf[i].tb_dmap); 934d217d4d9SSepherosa Ziehau if (error) { 935d217d4d9SSepherosa Ziehau device_printf(dev, "can't create %d TX mbuf " 936d217d4d9SSepherosa Ziehau "DMA map\n", i); 937d217d4d9SSepherosa Ziehau et_dma_mbuf_destroy(dev, i, rx_done); 938d217d4d9SSepherosa Ziehau return error; 939d217d4d9SSepherosa Ziehau } 940d217d4d9SSepherosa Ziehau } 941d217d4d9SSepherosa Ziehau 942d217d4d9SSepherosa Ziehau return 0; 943d217d4d9SSepherosa Ziehau } 944d217d4d9SSepherosa Ziehau 945d217d4d9SSepherosa Ziehau static void 946d217d4d9SSepherosa Ziehau et_dma_mbuf_destroy(device_t dev, int tx_done, const int rx_done[]) 947d217d4d9SSepherosa Ziehau { 948d217d4d9SSepherosa Ziehau struct et_softc *sc = device_get_softc(dev); 949d217d4d9SSepherosa Ziehau struct et_txbuf_data *tbd = &sc->sc_tx_data; 950d217d4d9SSepherosa Ziehau int i; 951d217d4d9SSepherosa Ziehau 952d217d4d9SSepherosa Ziehau if (sc->sc_mbuf_dtag == NULL) 953d217d4d9SSepherosa Ziehau return; 954d217d4d9SSepherosa Ziehau 955d217d4d9SSepherosa Ziehau /* 956d217d4d9SSepherosa Ziehau * Destroy DMA maps for RX mbufs 957d217d4d9SSepherosa Ziehau */ 958d217d4d9SSepherosa Ziehau for (i = 0; i < ET_RX_NRING; ++i) { 959d217d4d9SSepherosa Ziehau struct et_rxbuf_data *rbd = &sc->sc_rx_data[i]; 960d217d4d9SSepherosa Ziehau int j; 961d217d4d9SSepherosa Ziehau 962d217d4d9SSepherosa Ziehau for (j = 0; j < rx_done[i]; ++j) { 963d217d4d9SSepherosa Ziehau struct et_rxbuf *rb = &rbd->rbd_buf[j]; 964d217d4d9SSepherosa Ziehau 965d217d4d9SSepherosa Ziehau KASSERT(rb->rb_mbuf == NULL, 966d217d4d9SSepherosa Ziehau ("RX mbuf in %d RX ring is not freed yet\n", i)); 967d217d4d9SSepherosa Ziehau bus_dmamap_destroy(sc->sc_mbuf_dtag, rb->rb_dmap); 968d217d4d9SSepherosa Ziehau } 969d217d4d9SSepherosa Ziehau } 970d217d4d9SSepherosa Ziehau 971d217d4d9SSepherosa Ziehau /* 972d217d4d9SSepherosa Ziehau * Destroy DMA maps for TX mbufs 973d217d4d9SSepherosa Ziehau */ 974d217d4d9SSepherosa Ziehau for (i = 0; i < tx_done; ++i) { 975d217d4d9SSepherosa Ziehau struct et_txbuf *tb = &tbd->tbd_buf[i]; 976d217d4d9SSepherosa Ziehau 977d217d4d9SSepherosa Ziehau KASSERT(tb->tb_mbuf == NULL, ("TX mbuf is not freed yet\n")); 978d217d4d9SSepherosa Ziehau bus_dmamap_destroy(sc->sc_mbuf_dtag, tb->tb_dmap); 979d217d4d9SSepherosa Ziehau } 980d217d4d9SSepherosa Ziehau 981d217d4d9SSepherosa Ziehau /* 982d217d4d9SSepherosa Ziehau * Destroy spare mbuf DMA map 983d217d4d9SSepherosa Ziehau */ 984d217d4d9SSepherosa Ziehau bus_dmamap_destroy(sc->sc_mbuf_dtag, sc->sc_mbuf_tmp_dmap); 985d217d4d9SSepherosa Ziehau 986d217d4d9SSepherosa Ziehau /* 987d217d4d9SSepherosa Ziehau * Destroy mbuf DMA tag 988d217d4d9SSepherosa Ziehau */ 989d217d4d9SSepherosa Ziehau bus_dma_tag_destroy(sc->sc_mbuf_dtag); 990d217d4d9SSepherosa Ziehau sc->sc_mbuf_dtag = NULL; 991d217d4d9SSepherosa Ziehau } 992d217d4d9SSepherosa Ziehau 993d217d4d9SSepherosa Ziehau static int 994d217d4d9SSepherosa Ziehau et_dma_mem_create(device_t dev, bus_size_t size, bus_dma_tag_t *dtag, 995d217d4d9SSepherosa Ziehau void **addr, bus_addr_t *paddr, bus_dmamap_t *dmap) 996d217d4d9SSepherosa Ziehau { 997d217d4d9SSepherosa Ziehau struct et_softc *sc = device_get_softc(dev); 998d217d4d9SSepherosa Ziehau int error; 999d217d4d9SSepherosa Ziehau 1000d217d4d9SSepherosa Ziehau error = bus_dma_tag_create(sc->sc_dtag, ET_ALIGN, 0, 1001d217d4d9SSepherosa Ziehau BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, 1002d217d4d9SSepherosa Ziehau NULL, NULL, 1003d217d4d9SSepherosa Ziehau size, 1, BUS_SPACE_MAXSIZE_32BIT, 1004d217d4d9SSepherosa Ziehau 0, dtag); 1005d217d4d9SSepherosa Ziehau if (error) { 1006d217d4d9SSepherosa Ziehau device_printf(dev, "can't create DMA tag\n"); 1007d217d4d9SSepherosa Ziehau return error; 1008d217d4d9SSepherosa Ziehau } 1009d217d4d9SSepherosa Ziehau 1010d217d4d9SSepherosa Ziehau error = bus_dmamem_alloc(*dtag, addr, BUS_DMA_WAITOK | BUS_DMA_ZERO, 1011d217d4d9SSepherosa Ziehau dmap); 1012d217d4d9SSepherosa Ziehau if (error) { 1013d217d4d9SSepherosa Ziehau device_printf(dev, "can't allocate DMA mem\n"); 1014d217d4d9SSepherosa Ziehau bus_dma_tag_destroy(*dtag); 1015d217d4d9SSepherosa Ziehau *dtag = NULL; 1016d217d4d9SSepherosa Ziehau return error; 1017d217d4d9SSepherosa Ziehau } 1018d217d4d9SSepherosa Ziehau 1019d217d4d9SSepherosa Ziehau error = bus_dmamap_load(*dtag, *dmap, *addr, size, 1020d217d4d9SSepherosa Ziehau et_dma_ring_addr, paddr, BUS_DMA_WAITOK); 1021d217d4d9SSepherosa Ziehau if (error) { 1022d217d4d9SSepherosa Ziehau device_printf(dev, "can't load DMA mem\n"); 1023d217d4d9SSepherosa Ziehau bus_dmamem_free(*dtag, *addr, *dmap); 1024d217d4d9SSepherosa Ziehau bus_dma_tag_destroy(*dtag); 1025d217d4d9SSepherosa Ziehau *dtag = NULL; 1026d217d4d9SSepherosa Ziehau return error; 1027d217d4d9SSepherosa Ziehau } 1028d217d4d9SSepherosa Ziehau return 0; 1029d217d4d9SSepherosa Ziehau } 1030d217d4d9SSepherosa Ziehau 1031d217d4d9SSepherosa Ziehau static void 1032d217d4d9SSepherosa Ziehau et_dma_mem_destroy(bus_dma_tag_t dtag, void *addr, bus_dmamap_t dmap) 1033d217d4d9SSepherosa Ziehau { 1034d217d4d9SSepherosa Ziehau if (dtag != NULL) { 1035d217d4d9SSepherosa Ziehau bus_dmamap_unload(dtag, dmap); 1036d217d4d9SSepherosa Ziehau bus_dmamem_free(dtag, addr, dmap); 1037d217d4d9SSepherosa Ziehau bus_dma_tag_destroy(dtag); 1038d217d4d9SSepherosa Ziehau } 1039d217d4d9SSepherosa Ziehau } 1040d217d4d9SSepherosa Ziehau 1041d217d4d9SSepherosa Ziehau static void 1042d217d4d9SSepherosa Ziehau et_dma_ring_addr(void *arg, bus_dma_segment_t *seg, int nseg, int error) 1043d217d4d9SSepherosa Ziehau { 1044d217d4d9SSepherosa Ziehau KASSERT(nseg == 1, ("too many segments\n")); 1045d217d4d9SSepherosa Ziehau *((bus_addr_t *)arg) = seg->ds_addr; 1046d217d4d9SSepherosa Ziehau } 1047d217d4d9SSepherosa Ziehau 1048d217d4d9SSepherosa Ziehau static void 1049d217d4d9SSepherosa Ziehau et_chip_attach(struct et_softc *sc) 1050d217d4d9SSepherosa Ziehau { 1051d217d4d9SSepherosa Ziehau uint32_t val; 1052d217d4d9SSepherosa Ziehau 1053d217d4d9SSepherosa Ziehau /* 1054d217d4d9SSepherosa Ziehau * Perform minimal initialization 1055d217d4d9SSepherosa Ziehau */ 1056d217d4d9SSepherosa Ziehau 1057d217d4d9SSepherosa Ziehau /* Disable loopback */ 1058d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_LOOPBACK, 0); 1059d217d4d9SSepherosa Ziehau 1060d217d4d9SSepherosa Ziehau /* Reset MAC */ 1061d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_MAC_CFG1, 1062d217d4d9SSepherosa Ziehau ET_MAC_CFG1_RST_TXFUNC | ET_MAC_CFG1_RST_RXFUNC | 1063d217d4d9SSepherosa Ziehau ET_MAC_CFG1_RST_TXMC | ET_MAC_CFG1_RST_RXMC | 1064d217d4d9SSepherosa Ziehau ET_MAC_CFG1_SIM_RST | ET_MAC_CFG1_SOFT_RST); 1065d217d4d9SSepherosa Ziehau 1066d217d4d9SSepherosa Ziehau /* 1067d217d4d9SSepherosa Ziehau * Setup half duplex mode 1068d217d4d9SSepherosa Ziehau */ 1069d217d4d9SSepherosa Ziehau val = __SHIFTIN(10, ET_MAC_HDX_ALT_BEB_TRUNC) | 1070d217d4d9SSepherosa Ziehau __SHIFTIN(15, ET_MAC_HDX_REXMIT_MAX) | 1071d217d4d9SSepherosa Ziehau __SHIFTIN(55, ET_MAC_HDX_COLLWIN) | 1072d217d4d9SSepherosa Ziehau ET_MAC_HDX_EXC_DEFER; 1073d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_MAC_HDX, val); 1074d217d4d9SSepherosa Ziehau 1075d217d4d9SSepherosa Ziehau /* Clear MAC control */ 1076d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_MAC_CTRL, 0); 1077d217d4d9SSepherosa Ziehau 1078d217d4d9SSepherosa Ziehau /* Reset MII */ 1079d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_MII_CFG, ET_MII_CFG_CLKRST); 1080d217d4d9SSepherosa Ziehau 1081d217d4d9SSepherosa Ziehau /* Bring MAC out of reset state */ 1082d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_MAC_CFG1, 0); 1083d217d4d9SSepherosa Ziehau 1084d217d4d9SSepherosa Ziehau /* Enable memory controllers */ 1085d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_MMC_CTRL, ET_MMC_CTRL_ENABLE); 1086d217d4d9SSepherosa Ziehau } 1087d217d4d9SSepherosa Ziehau 1088d217d4d9SSepherosa Ziehau static void 1089d217d4d9SSepherosa Ziehau et_intr(void *xsc) 1090d217d4d9SSepherosa Ziehau { 1091d217d4d9SSepherosa Ziehau struct et_softc *sc = xsc; 1092d217d4d9SSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 1093d217d4d9SSepherosa Ziehau uint32_t intrs; 1094d217d4d9SSepherosa Ziehau 1095d217d4d9SSepherosa Ziehau ASSERT_SERIALIZED(ifp->if_serializer); 1096d217d4d9SSepherosa Ziehau 1097d217d4d9SSepherosa Ziehau if ((ifp->if_flags & IFF_RUNNING) == 0) 1098d217d4d9SSepherosa Ziehau return; 1099d217d4d9SSepherosa Ziehau 1100d217d4d9SSepherosa Ziehau et_disable_intrs(sc); 1101d217d4d9SSepherosa Ziehau 1102d217d4d9SSepherosa Ziehau intrs = CSR_READ_4(sc, ET_INTR_STATUS); 1103d217d4d9SSepherosa Ziehau intrs &= ET_INTRS; 1104d217d4d9SSepherosa Ziehau if (intrs == 0) /* Not interested */ 1105d217d4d9SSepherosa Ziehau goto back; 1106d217d4d9SSepherosa Ziehau 1107d217d4d9SSepherosa Ziehau if (intrs & ET_INTR_RXEOF) 1108d217d4d9SSepherosa Ziehau et_rxeof(sc); 1109d217d4d9SSepherosa Ziehau if (intrs & (ET_INTR_TXEOF | ET_INTR_TIMER)) 1110d217d4d9SSepherosa Ziehau et_txeof(sc); 1111d217d4d9SSepherosa Ziehau if (intrs & ET_INTR_TIMER) 1112d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_TIMER, sc->sc_timer); 1113d217d4d9SSepherosa Ziehau back: 1114d217d4d9SSepherosa Ziehau et_enable_intrs(sc, ET_INTRS); 1115d217d4d9SSepherosa Ziehau } 1116d217d4d9SSepherosa Ziehau 1117d217d4d9SSepherosa Ziehau static void 1118d217d4d9SSepherosa Ziehau et_init(void *xsc) 1119d217d4d9SSepherosa Ziehau { 1120d217d4d9SSepherosa Ziehau struct et_softc *sc = xsc; 1121d217d4d9SSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 1122d217d4d9SSepherosa Ziehau const struct et_bsize *arr; 1123d217d4d9SSepherosa Ziehau int error, i; 1124d217d4d9SSepherosa Ziehau 1125d217d4d9SSepherosa Ziehau ASSERT_SERIALIZED(ifp->if_serializer); 1126d217d4d9SSepherosa Ziehau 1127d217d4d9SSepherosa Ziehau et_stop(sc); 1128d217d4d9SSepherosa Ziehau 11293effc1bfSSepherosa Ziehau arr = ET_FRAMELEN(ifp->if_mtu) < MCLBYTES ? 11303effc1bfSSepherosa Ziehau et_bufsize_std : et_bufsize_jumbo; 1131d217d4d9SSepherosa Ziehau for (i = 0; i < ET_RX_NRING; ++i) { 1132d217d4d9SSepherosa Ziehau sc->sc_rx_data[i].rbd_bufsize = arr[i].bufsize; 1133d217d4d9SSepherosa Ziehau sc->sc_rx_data[i].rbd_newbuf = arr[i].newbuf; 11343effc1bfSSepherosa Ziehau sc->sc_rx_data[i].rbd_jumbo = arr[i].jumbo; 1135d217d4d9SSepherosa Ziehau } 1136d217d4d9SSepherosa Ziehau 1137d217d4d9SSepherosa Ziehau error = et_init_tx_ring(sc); 1138d217d4d9SSepherosa Ziehau if (error) 1139d217d4d9SSepherosa Ziehau goto back; 1140d217d4d9SSepherosa Ziehau 1141d217d4d9SSepherosa Ziehau error = et_init_rx_ring(sc); 1142d217d4d9SSepherosa Ziehau if (error) 1143d217d4d9SSepherosa Ziehau goto back; 1144d217d4d9SSepherosa Ziehau 1145d217d4d9SSepherosa Ziehau error = et_chip_init(sc); 1146d217d4d9SSepherosa Ziehau if (error) 1147d217d4d9SSepherosa Ziehau goto back; 1148d217d4d9SSepherosa Ziehau 114960d2de1fSSepherosa Ziehau error = et_enable_txrx(sc, 1); 1150d217d4d9SSepherosa Ziehau if (error) 1151d217d4d9SSepherosa Ziehau goto back; 1152d217d4d9SSepherosa Ziehau 1153d217d4d9SSepherosa Ziehau et_enable_intrs(sc, ET_INTRS); 1154d217d4d9SSepherosa Ziehau 1155d217d4d9SSepherosa Ziehau callout_reset(&sc->sc_tick, hz, et_tick, sc); 1156d217d4d9SSepherosa Ziehau 1157d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_TIMER, sc->sc_timer); 1158d217d4d9SSepherosa Ziehau 1159d217d4d9SSepherosa Ziehau ifp->if_flags |= IFF_RUNNING; 1160d217d4d9SSepherosa Ziehau ifp->if_flags &= ~IFF_OACTIVE; 1161d217d4d9SSepherosa Ziehau back: 1162d217d4d9SSepherosa Ziehau if (error) 1163d217d4d9SSepherosa Ziehau et_stop(sc); 1164d217d4d9SSepherosa Ziehau } 1165d217d4d9SSepherosa Ziehau 1166d217d4d9SSepherosa Ziehau static int 1167d217d4d9SSepherosa Ziehau et_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data, struct ucred *cr) 1168d217d4d9SSepherosa Ziehau { 1169d217d4d9SSepherosa Ziehau struct et_softc *sc = ifp->if_softc; 1170d217d4d9SSepherosa Ziehau struct mii_data *mii = device_get_softc(sc->sc_miibus); 1171d217d4d9SSepherosa Ziehau struct ifreq *ifr = (struct ifreq *)data; 11723effc1bfSSepherosa Ziehau int error = 0, max_framelen; 1173d217d4d9SSepherosa Ziehau 1174d217d4d9SSepherosa Ziehau ASSERT_SERIALIZED(ifp->if_serializer); 1175d217d4d9SSepherosa Ziehau 1176d217d4d9SSepherosa Ziehau switch (cmd) { 1177d217d4d9SSepherosa Ziehau case SIOCSIFFLAGS: 1178d217d4d9SSepherosa Ziehau if (ifp->if_flags & IFF_UP) { 1179d217d4d9SSepherosa Ziehau if (ifp->if_flags & IFF_RUNNING) { 1180d217d4d9SSepherosa Ziehau if ((ifp->if_flags ^ sc->sc_if_flags) & 1181*5a5f28f3SSepherosa Ziehau (IFF_ALLMULTI | IFF_PROMISC)) 1182d217d4d9SSepherosa Ziehau et_setmulti(sc); 1183d217d4d9SSepherosa Ziehau } else { 1184d217d4d9SSepherosa Ziehau et_init(sc); 1185d217d4d9SSepherosa Ziehau } 1186d217d4d9SSepherosa Ziehau } else { 1187d217d4d9SSepherosa Ziehau if (ifp->if_flags & IFF_RUNNING) 1188d217d4d9SSepherosa Ziehau et_stop(sc); 1189d217d4d9SSepherosa Ziehau } 1190d217d4d9SSepherosa Ziehau sc->sc_if_flags = ifp->if_flags; 1191d217d4d9SSepherosa Ziehau break; 1192d217d4d9SSepherosa Ziehau 1193d217d4d9SSepherosa Ziehau case SIOCSIFMEDIA: 1194d217d4d9SSepherosa Ziehau case SIOCGIFMEDIA: 1195d217d4d9SSepherosa Ziehau error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, cmd); 1196d217d4d9SSepherosa Ziehau break; 1197d217d4d9SSepherosa Ziehau 1198d217d4d9SSepherosa Ziehau case SIOCADDMULTI: 1199d217d4d9SSepherosa Ziehau case SIOCDELMULTI: 1200d217d4d9SSepherosa Ziehau if (ifp->if_flags & IFF_RUNNING) 1201d217d4d9SSepherosa Ziehau et_setmulti(sc); 1202d217d4d9SSepherosa Ziehau break; 1203d217d4d9SSepherosa Ziehau 1204d217d4d9SSepherosa Ziehau case SIOCSIFMTU: 12053effc1bfSSepherosa Ziehau if (sc->sc_flags & ET_FLAG_JUMBO) 12063effc1bfSSepherosa Ziehau max_framelen = ET_JUMBO_FRAMELEN; 12073effc1bfSSepherosa Ziehau else 12083effc1bfSSepherosa Ziehau max_framelen = MCLBYTES - 1; 12093effc1bfSSepherosa Ziehau 12103effc1bfSSepherosa Ziehau if (ET_FRAMELEN(ifr->ifr_mtu) > max_framelen) { 1211d217d4d9SSepherosa Ziehau error = EOPNOTSUPP; 1212d217d4d9SSepherosa Ziehau break; 12130fd7469eSSepherosa Ziehau } 12140fd7469eSSepherosa Ziehau 12150fd7469eSSepherosa Ziehau ifp->if_mtu = ifr->ifr_mtu; 12160fd7469eSSepherosa Ziehau if (ifp->if_flags & IFF_RUNNING) 12170fd7469eSSepherosa Ziehau et_init(sc); 12180fd7469eSSepherosa Ziehau break; 1219d217d4d9SSepherosa Ziehau 1220d217d4d9SSepherosa Ziehau default: 1221d217d4d9SSepherosa Ziehau error = ether_ioctl(ifp, cmd, data); 1222d217d4d9SSepherosa Ziehau break; 1223d217d4d9SSepherosa Ziehau } 1224d217d4d9SSepherosa Ziehau return error; 1225d217d4d9SSepherosa Ziehau } 1226d217d4d9SSepherosa Ziehau 1227d217d4d9SSepherosa Ziehau static void 1228d217d4d9SSepherosa Ziehau et_start(struct ifnet *ifp) 1229d217d4d9SSepherosa Ziehau { 1230d217d4d9SSepherosa Ziehau struct et_softc *sc = ifp->if_softc; 1231d217d4d9SSepherosa Ziehau struct et_txbuf_data *tbd = &sc->sc_tx_data; 1232d217d4d9SSepherosa Ziehau int trans; 1233d217d4d9SSepherosa Ziehau 1234d217d4d9SSepherosa Ziehau ASSERT_SERIALIZED(ifp->if_serializer); 1235d217d4d9SSepherosa Ziehau 12369db4b353SSepherosa Ziehau if ((sc->sc_flags & ET_FLAG_TXRX_ENABLED) == 0) { 12379db4b353SSepherosa Ziehau ifq_purge(&ifp->if_snd); 123860d2de1fSSepherosa Ziehau return; 12399db4b353SSepherosa Ziehau } 124060d2de1fSSepherosa Ziehau 1241d217d4d9SSepherosa Ziehau if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING) 1242d217d4d9SSepherosa Ziehau return; 1243d217d4d9SSepherosa Ziehau 1244d217d4d9SSepherosa Ziehau trans = 0; 1245d217d4d9SSepherosa Ziehau for (;;) { 1246d217d4d9SSepherosa Ziehau struct mbuf *m; 1247d217d4d9SSepherosa Ziehau 1248d217d4d9SSepherosa Ziehau if ((tbd->tbd_used + ET_NSEG_SPARE) > ET_TX_NDESC) { 1249d217d4d9SSepherosa Ziehau ifp->if_flags |= IFF_OACTIVE; 1250d217d4d9SSepherosa Ziehau break; 1251d217d4d9SSepherosa Ziehau } 1252d217d4d9SSepherosa Ziehau 1253d217d4d9SSepherosa Ziehau m = ifq_dequeue(&ifp->if_snd, NULL); 1254d217d4d9SSepherosa Ziehau if (m == NULL) 1255d217d4d9SSepherosa Ziehau break; 1256d217d4d9SSepherosa Ziehau 1257d217d4d9SSepherosa Ziehau if (et_encap(sc, &m)) { 1258d217d4d9SSepherosa Ziehau ifp->if_oerrors++; 1259d217d4d9SSepherosa Ziehau ifp->if_flags |= IFF_OACTIVE; 1260d217d4d9SSepherosa Ziehau break; 1261d217d4d9SSepherosa Ziehau } 1262d217d4d9SSepherosa Ziehau trans = 1; 1263d217d4d9SSepherosa Ziehau 1264d217d4d9SSepherosa Ziehau BPF_MTAP(ifp, m); 1265d217d4d9SSepherosa Ziehau } 1266d217d4d9SSepherosa Ziehau 1267d217d4d9SSepherosa Ziehau if (trans) 1268d217d4d9SSepherosa Ziehau ifp->if_timer = 5; 1269d217d4d9SSepherosa Ziehau } 1270d217d4d9SSepherosa Ziehau 1271d217d4d9SSepherosa Ziehau static void 1272d217d4d9SSepherosa Ziehau et_watchdog(struct ifnet *ifp) 1273d217d4d9SSepherosa Ziehau { 1274d217d4d9SSepherosa Ziehau ASSERT_SERIALIZED(ifp->if_serializer); 1275d217d4d9SSepherosa Ziehau 1276d217d4d9SSepherosa Ziehau if_printf(ifp, "watchdog timed out\n"); 1277d217d4d9SSepherosa Ziehau 1278d217d4d9SSepherosa Ziehau ifp->if_init(ifp->if_softc); 12799db4b353SSepherosa Ziehau if_devstart(ifp); 1280d217d4d9SSepherosa Ziehau } 1281d217d4d9SSepherosa Ziehau 1282d217d4d9SSepherosa Ziehau static int 1283d217d4d9SSepherosa Ziehau et_stop_rxdma(struct et_softc *sc) 1284d217d4d9SSepherosa Ziehau { 1285d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_RXDMA_CTRL, 1286d217d4d9SSepherosa Ziehau ET_RXDMA_CTRL_HALT | ET_RXDMA_CTRL_RING1_ENABLE); 1287d217d4d9SSepherosa Ziehau 1288d217d4d9SSepherosa Ziehau DELAY(5); 1289d217d4d9SSepherosa Ziehau if ((CSR_READ_4(sc, ET_RXDMA_CTRL) & ET_RXDMA_CTRL_HALTED) == 0) { 1290d217d4d9SSepherosa Ziehau if_printf(&sc->arpcom.ac_if, "can't stop RX DMA engine\n"); 1291d217d4d9SSepherosa Ziehau return ETIMEDOUT; 1292d217d4d9SSepherosa Ziehau } 1293d217d4d9SSepherosa Ziehau return 0; 1294d217d4d9SSepherosa Ziehau } 1295d217d4d9SSepherosa Ziehau 1296d217d4d9SSepherosa Ziehau static int 1297d217d4d9SSepherosa Ziehau et_stop_txdma(struct et_softc *sc) 1298d217d4d9SSepherosa Ziehau { 1299d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_TXDMA_CTRL, 1300d217d4d9SSepherosa Ziehau ET_TXDMA_CTRL_HALT | ET_TXDMA_CTRL_SINGLE_EPKT); 1301d217d4d9SSepherosa Ziehau return 0; 1302d217d4d9SSepherosa Ziehau } 1303d217d4d9SSepherosa Ziehau 1304d217d4d9SSepherosa Ziehau static void 1305d217d4d9SSepherosa Ziehau et_free_tx_ring(struct et_softc *sc) 1306d217d4d9SSepherosa Ziehau { 1307d217d4d9SSepherosa Ziehau struct et_txbuf_data *tbd = &sc->sc_tx_data; 1308d217d4d9SSepherosa Ziehau struct et_txdesc_ring *tx_ring = &sc->sc_tx_ring; 1309d217d4d9SSepherosa Ziehau int i; 1310d217d4d9SSepherosa Ziehau 1311d217d4d9SSepherosa Ziehau for (i = 0; i < ET_TX_NDESC; ++i) { 1312d217d4d9SSepherosa Ziehau struct et_txbuf *tb = &tbd->tbd_buf[i]; 1313d217d4d9SSepherosa Ziehau 1314d217d4d9SSepherosa Ziehau if (tb->tb_mbuf != NULL) { 1315d217d4d9SSepherosa Ziehau bus_dmamap_unload(sc->sc_mbuf_dtag, tb->tb_dmap); 1316d217d4d9SSepherosa Ziehau m_freem(tb->tb_mbuf); 1317d217d4d9SSepherosa Ziehau tb->tb_mbuf = NULL; 1318d217d4d9SSepherosa Ziehau } 1319d217d4d9SSepherosa Ziehau } 1320d217d4d9SSepherosa Ziehau 1321d217d4d9SSepherosa Ziehau bzero(tx_ring->tr_desc, ET_TX_RING_SIZE); 1322d217d4d9SSepherosa Ziehau bus_dmamap_sync(tx_ring->tr_dtag, tx_ring->tr_dmap, 1323d217d4d9SSepherosa Ziehau BUS_DMASYNC_PREWRITE); 1324d217d4d9SSepherosa Ziehau } 1325d217d4d9SSepherosa Ziehau 1326d217d4d9SSepherosa Ziehau static void 1327d217d4d9SSepherosa Ziehau et_free_rx_ring(struct et_softc *sc) 1328d217d4d9SSepherosa Ziehau { 1329d217d4d9SSepherosa Ziehau int n; 1330d217d4d9SSepherosa Ziehau 1331d217d4d9SSepherosa Ziehau for (n = 0; n < ET_RX_NRING; ++n) { 1332d217d4d9SSepherosa Ziehau struct et_rxbuf_data *rbd = &sc->sc_rx_data[n]; 1333d217d4d9SSepherosa Ziehau struct et_rxdesc_ring *rx_ring = &sc->sc_rx_ring[n]; 1334d217d4d9SSepherosa Ziehau int i; 1335d217d4d9SSepherosa Ziehau 1336d217d4d9SSepherosa Ziehau for (i = 0; i < ET_RX_NDESC; ++i) { 1337d217d4d9SSepherosa Ziehau struct et_rxbuf *rb = &rbd->rbd_buf[i]; 1338d217d4d9SSepherosa Ziehau 1339d217d4d9SSepherosa Ziehau if (rb->rb_mbuf != NULL) { 13403effc1bfSSepherosa Ziehau if (!rbd->rbd_jumbo) { 1341d217d4d9SSepherosa Ziehau bus_dmamap_unload(sc->sc_mbuf_dtag, 1342d217d4d9SSepherosa Ziehau rb->rb_dmap); 13433effc1bfSSepherosa Ziehau } 1344d217d4d9SSepherosa Ziehau m_freem(rb->rb_mbuf); 1345d217d4d9SSepherosa Ziehau rb->rb_mbuf = NULL; 1346d217d4d9SSepherosa Ziehau } 1347d217d4d9SSepherosa Ziehau } 1348d217d4d9SSepherosa Ziehau 1349d217d4d9SSepherosa Ziehau bzero(rx_ring->rr_desc, ET_RX_RING_SIZE); 1350d217d4d9SSepherosa Ziehau bus_dmamap_sync(rx_ring->rr_dtag, rx_ring->rr_dmap, 1351d217d4d9SSepherosa Ziehau BUS_DMASYNC_PREWRITE); 1352d217d4d9SSepherosa Ziehau } 1353d217d4d9SSepherosa Ziehau } 1354d217d4d9SSepherosa Ziehau 1355d217d4d9SSepherosa Ziehau static void 1356d217d4d9SSepherosa Ziehau et_setmulti(struct et_softc *sc) 1357d217d4d9SSepherosa Ziehau { 1358d217d4d9SSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 1359d217d4d9SSepherosa Ziehau uint32_t hash[4] = { 0, 0, 0, 0 }; 1360d217d4d9SSepherosa Ziehau uint32_t rxmac_ctrl, pktfilt; 1361d217d4d9SSepherosa Ziehau struct ifmultiaddr *ifma; 1362d217d4d9SSepherosa Ziehau int i, count; 1363d217d4d9SSepherosa Ziehau 1364d217d4d9SSepherosa Ziehau pktfilt = CSR_READ_4(sc, ET_PKTFILT); 1365d217d4d9SSepherosa Ziehau rxmac_ctrl = CSR_READ_4(sc, ET_RXMAC_CTRL); 1366d217d4d9SSepherosa Ziehau 1367d217d4d9SSepherosa Ziehau pktfilt &= ~(ET_PKTFILT_BCAST | ET_PKTFILT_MCAST | ET_PKTFILT_UCAST); 1368d217d4d9SSepherosa Ziehau if (ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI)) { 1369d217d4d9SSepherosa Ziehau rxmac_ctrl |= ET_RXMAC_CTRL_NO_PKTFILT; 1370d217d4d9SSepherosa Ziehau goto back; 1371d217d4d9SSepherosa Ziehau } 1372d217d4d9SSepherosa Ziehau 1373d217d4d9SSepherosa Ziehau count = 0; 1374d217d4d9SSepherosa Ziehau LIST_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { 1375d217d4d9SSepherosa Ziehau uint32_t *hp, h; 1376d217d4d9SSepherosa Ziehau 1377d217d4d9SSepherosa Ziehau if (ifma->ifma_addr->sa_family != AF_LINK) 1378d217d4d9SSepherosa Ziehau continue; 1379d217d4d9SSepherosa Ziehau 1380d217d4d9SSepherosa Ziehau h = ether_crc32_be(LLADDR((struct sockaddr_dl *) 1381d217d4d9SSepherosa Ziehau ifma->ifma_addr), ETHER_ADDR_LEN); 1382d217d4d9SSepherosa Ziehau h = (h & 0x3f800000) >> 23; 1383d217d4d9SSepherosa Ziehau 1384d217d4d9SSepherosa Ziehau hp = &hash[0]; 1385d217d4d9SSepherosa Ziehau if (h >= 32 && h < 64) { 1386d217d4d9SSepherosa Ziehau h -= 32; 1387d217d4d9SSepherosa Ziehau hp = &hash[1]; 1388d217d4d9SSepherosa Ziehau } else if (h >= 64 && h < 96) { 1389d217d4d9SSepherosa Ziehau h -= 64; 1390d217d4d9SSepherosa Ziehau hp = &hash[2]; 1391d217d4d9SSepherosa Ziehau } else if (h >= 96) { 1392d217d4d9SSepherosa Ziehau h -= 96; 1393d217d4d9SSepherosa Ziehau hp = &hash[3]; 1394d217d4d9SSepherosa Ziehau } 1395d217d4d9SSepherosa Ziehau *hp |= (1 << h); 1396d217d4d9SSepherosa Ziehau 1397d217d4d9SSepherosa Ziehau ++count; 1398d217d4d9SSepherosa Ziehau } 1399d217d4d9SSepherosa Ziehau 1400d217d4d9SSepherosa Ziehau for (i = 0; i < 4; ++i) 1401d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_MULTI_HASH + (i * 4), hash[i]); 1402d217d4d9SSepherosa Ziehau 1403d217d4d9SSepherosa Ziehau if (count > 0) 1404d217d4d9SSepherosa Ziehau pktfilt |= ET_PKTFILT_MCAST; 1405d217d4d9SSepherosa Ziehau rxmac_ctrl &= ~ET_RXMAC_CTRL_NO_PKTFILT; 1406d217d4d9SSepherosa Ziehau back: 1407d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_PKTFILT, pktfilt); 1408d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_RXMAC_CTRL, rxmac_ctrl); 1409d217d4d9SSepherosa Ziehau } 1410d217d4d9SSepherosa Ziehau 1411d217d4d9SSepherosa Ziehau static int 1412d217d4d9SSepherosa Ziehau et_chip_init(struct et_softc *sc) 1413d217d4d9SSepherosa Ziehau { 1414d217d4d9SSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 1415d217d4d9SSepherosa Ziehau uint32_t rxq_end; 14163effc1bfSSepherosa Ziehau int error, frame_len, rxmem_size; 1417d217d4d9SSepherosa Ziehau 1418d217d4d9SSepherosa Ziehau /* 14193effc1bfSSepherosa Ziehau * Split 16Kbytes internal memory between TX and RX 14203effc1bfSSepherosa Ziehau * according to frame length. 1421d217d4d9SSepherosa Ziehau */ 14223effc1bfSSepherosa Ziehau frame_len = ET_FRAMELEN(ifp->if_mtu); 14233effc1bfSSepherosa Ziehau if (frame_len < 2048) { 14243effc1bfSSepherosa Ziehau rxmem_size = ET_MEM_RXSIZE_DEFAULT; 14253effc1bfSSepherosa Ziehau } else if (frame_len <= ET_RXMAC_CUT_THRU_FRMLEN) { 14263effc1bfSSepherosa Ziehau rxmem_size = ET_MEM_SIZE / 2; 14273effc1bfSSepherosa Ziehau } else { 14283effc1bfSSepherosa Ziehau rxmem_size = ET_MEM_SIZE - 14293effc1bfSSepherosa Ziehau roundup(frame_len + ET_MEM_TXSIZE_EX, ET_MEM_UNIT); 14303effc1bfSSepherosa Ziehau } 14313effc1bfSSepherosa Ziehau rxq_end = ET_QUEUE_ADDR(rxmem_size); 14323effc1bfSSepherosa Ziehau 14333effc1bfSSepherosa Ziehau CSR_WRITE_4(sc, ET_RXQUEUE_START, ET_QUEUE_ADDR_START); 14343effc1bfSSepherosa Ziehau CSR_WRITE_4(sc, ET_RXQUEUE_END, rxq_end); 14353effc1bfSSepherosa Ziehau CSR_WRITE_4(sc, ET_TXQUEUE_START, rxq_end + 1); 14363effc1bfSSepherosa Ziehau CSR_WRITE_4(sc, ET_TXQUEUE_END, ET_QUEUE_ADDR_END); 1437d217d4d9SSepherosa Ziehau 1438d217d4d9SSepherosa Ziehau /* No loopback */ 1439d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_LOOPBACK, 0); 1440d217d4d9SSepherosa Ziehau 1441d217d4d9SSepherosa Ziehau /* Clear MSI configure */ 1442d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_MSI_CFG, 0); 1443d217d4d9SSepherosa Ziehau 1444d217d4d9SSepherosa Ziehau /* Disable timer */ 1445d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_TIMER, 0); 1446d217d4d9SSepherosa Ziehau 1447d217d4d9SSepherosa Ziehau /* Initialize MAC */ 1448d217d4d9SSepherosa Ziehau et_init_mac(sc); 1449d217d4d9SSepherosa Ziehau 1450d217d4d9SSepherosa Ziehau /* Enable memory controllers */ 1451d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_MMC_CTRL, ET_MMC_CTRL_ENABLE); 1452d217d4d9SSepherosa Ziehau 1453d217d4d9SSepherosa Ziehau /* Initialize RX MAC */ 1454d217d4d9SSepherosa Ziehau et_init_rxmac(sc); 1455d217d4d9SSepherosa Ziehau 1456d217d4d9SSepherosa Ziehau /* Initialize TX MAC */ 1457d217d4d9SSepherosa Ziehau et_init_txmac(sc); 1458d217d4d9SSepherosa Ziehau 1459d217d4d9SSepherosa Ziehau /* Initialize RX DMA engine */ 1460d217d4d9SSepherosa Ziehau error = et_init_rxdma(sc); 1461d217d4d9SSepherosa Ziehau if (error) 1462d217d4d9SSepherosa Ziehau return error; 1463d217d4d9SSepherosa Ziehau 1464d217d4d9SSepherosa Ziehau /* Initialize TX DMA engine */ 1465d217d4d9SSepherosa Ziehau error = et_init_txdma(sc); 1466d217d4d9SSepherosa Ziehau if (error) 1467d217d4d9SSepherosa Ziehau return error; 1468d217d4d9SSepherosa Ziehau 1469d217d4d9SSepherosa Ziehau return 0; 1470d217d4d9SSepherosa Ziehau } 1471d217d4d9SSepherosa Ziehau 1472d217d4d9SSepherosa Ziehau static int 1473d217d4d9SSepherosa Ziehau et_init_tx_ring(struct et_softc *sc) 1474d217d4d9SSepherosa Ziehau { 1475d217d4d9SSepherosa Ziehau struct et_txdesc_ring *tx_ring = &sc->sc_tx_ring; 1476d217d4d9SSepherosa Ziehau struct et_txstatus_data *txsd = &sc->sc_tx_status; 1477d217d4d9SSepherosa Ziehau struct et_txbuf_data *tbd = &sc->sc_tx_data; 1478d217d4d9SSepherosa Ziehau 1479d217d4d9SSepherosa Ziehau bzero(tx_ring->tr_desc, ET_TX_RING_SIZE); 1480d217d4d9SSepherosa Ziehau bus_dmamap_sync(tx_ring->tr_dtag, tx_ring->tr_dmap, 1481d217d4d9SSepherosa Ziehau BUS_DMASYNC_PREWRITE); 1482d217d4d9SSepherosa Ziehau 1483d217d4d9SSepherosa Ziehau tbd->tbd_start_index = 0; 1484d217d4d9SSepherosa Ziehau tbd->tbd_start_wrap = 0; 1485d217d4d9SSepherosa Ziehau tbd->tbd_used = 0; 1486d217d4d9SSepherosa Ziehau 1487d217d4d9SSepherosa Ziehau bzero(txsd->txsd_status, sizeof(uint32_t)); 1488d217d4d9SSepherosa Ziehau bus_dmamap_sync(txsd->txsd_dtag, txsd->txsd_dmap, 1489d217d4d9SSepherosa Ziehau BUS_DMASYNC_PREWRITE); 1490d217d4d9SSepherosa Ziehau return 0; 1491d217d4d9SSepherosa Ziehau } 1492d217d4d9SSepherosa Ziehau 1493d217d4d9SSepherosa Ziehau static int 1494d217d4d9SSepherosa Ziehau et_init_rx_ring(struct et_softc *sc) 1495d217d4d9SSepherosa Ziehau { 1496d217d4d9SSepherosa Ziehau struct et_rxstatus_data *rxsd = &sc->sc_rx_status; 1497d217d4d9SSepherosa Ziehau struct et_rxstat_ring *rxst_ring = &sc->sc_rxstat_ring; 1498d217d4d9SSepherosa Ziehau int n; 1499d217d4d9SSepherosa Ziehau 1500d217d4d9SSepherosa Ziehau for (n = 0; n < ET_RX_NRING; ++n) { 1501d217d4d9SSepherosa Ziehau struct et_rxbuf_data *rbd = &sc->sc_rx_data[n]; 1502d217d4d9SSepherosa Ziehau int i, error; 1503d217d4d9SSepherosa Ziehau 1504d217d4d9SSepherosa Ziehau for (i = 0; i < ET_RX_NDESC; ++i) { 1505d217d4d9SSepherosa Ziehau error = rbd->rbd_newbuf(rbd, i, 1); 1506d217d4d9SSepherosa Ziehau if (error) { 1507d217d4d9SSepherosa Ziehau if_printf(&sc->arpcom.ac_if, "%d ring %d buf, " 1508d217d4d9SSepherosa Ziehau "newbuf failed: %d\n", n, i, error); 1509d217d4d9SSepherosa Ziehau return error; 1510d217d4d9SSepherosa Ziehau } 1511d217d4d9SSepherosa Ziehau } 1512d217d4d9SSepherosa Ziehau } 1513d217d4d9SSepherosa Ziehau 1514d217d4d9SSepherosa Ziehau bzero(rxsd->rxsd_status, sizeof(struct et_rxstatus)); 1515d217d4d9SSepherosa Ziehau bus_dmamap_sync(rxsd->rxsd_dtag, rxsd->rxsd_dmap, 1516d217d4d9SSepherosa Ziehau BUS_DMASYNC_PREWRITE); 1517d217d4d9SSepherosa Ziehau 1518d217d4d9SSepherosa Ziehau bzero(rxst_ring->rsr_stat, ET_RXSTAT_RING_SIZE); 1519d217d4d9SSepherosa Ziehau bus_dmamap_sync(rxst_ring->rsr_dtag, rxst_ring->rsr_dmap, 1520d217d4d9SSepherosa Ziehau BUS_DMASYNC_PREWRITE); 1521d217d4d9SSepherosa Ziehau 1522d217d4d9SSepherosa Ziehau return 0; 1523d217d4d9SSepherosa Ziehau } 1524d217d4d9SSepherosa Ziehau 1525d217d4d9SSepherosa Ziehau static void 1526d217d4d9SSepherosa Ziehau et_dma_buf_addr(void *xctx, bus_dma_segment_t *segs, int nsegs, 1527d217d4d9SSepherosa Ziehau bus_size_t mapsz __unused, int error) 1528d217d4d9SSepherosa Ziehau { 1529d217d4d9SSepherosa Ziehau struct et_dmamap_ctx *ctx = xctx; 1530d217d4d9SSepherosa Ziehau int i; 1531d217d4d9SSepherosa Ziehau 1532d217d4d9SSepherosa Ziehau if (error) 1533d217d4d9SSepherosa Ziehau return; 1534d217d4d9SSepherosa Ziehau 1535d217d4d9SSepherosa Ziehau if (nsegs > ctx->nsegs) { 1536d217d4d9SSepherosa Ziehau ctx->nsegs = 0; 1537d217d4d9SSepherosa Ziehau return; 1538d217d4d9SSepherosa Ziehau } 1539d217d4d9SSepherosa Ziehau 1540d217d4d9SSepherosa Ziehau ctx->nsegs = nsegs; 1541d217d4d9SSepherosa Ziehau for (i = 0; i < nsegs; ++i) 1542d217d4d9SSepherosa Ziehau ctx->segs[i] = segs[i]; 1543d217d4d9SSepherosa Ziehau } 1544d217d4d9SSepherosa Ziehau 1545d217d4d9SSepherosa Ziehau static int 1546d217d4d9SSepherosa Ziehau et_init_rxdma(struct et_softc *sc) 1547d217d4d9SSepherosa Ziehau { 1548d217d4d9SSepherosa Ziehau struct et_rxstatus_data *rxsd = &sc->sc_rx_status; 1549d217d4d9SSepherosa Ziehau struct et_rxstat_ring *rxst_ring = &sc->sc_rxstat_ring; 1550d217d4d9SSepherosa Ziehau struct et_rxdesc_ring *rx_ring; 1551d217d4d9SSepherosa Ziehau int error; 1552d217d4d9SSepherosa Ziehau 1553d217d4d9SSepherosa Ziehau error = et_stop_rxdma(sc); 1554d217d4d9SSepherosa Ziehau if (error) { 1555d217d4d9SSepherosa Ziehau if_printf(&sc->arpcom.ac_if, "can't init RX DMA engine\n"); 1556d217d4d9SSepherosa Ziehau return error; 1557d217d4d9SSepherosa Ziehau } 1558d217d4d9SSepherosa Ziehau 1559d217d4d9SSepherosa Ziehau /* 1560d217d4d9SSepherosa Ziehau * Install RX status 1561d217d4d9SSepherosa Ziehau */ 1562d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_RX_STATUS_HI, ET_ADDR_HI(rxsd->rxsd_paddr)); 1563d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_RX_STATUS_LO, ET_ADDR_LO(rxsd->rxsd_paddr)); 1564d217d4d9SSepherosa Ziehau 1565d217d4d9SSepherosa Ziehau /* 1566d217d4d9SSepherosa Ziehau * Install RX stat ring 1567d217d4d9SSepherosa Ziehau */ 1568d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_RXSTAT_HI, ET_ADDR_HI(rxst_ring->rsr_paddr)); 1569d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_RXSTAT_LO, ET_ADDR_LO(rxst_ring->rsr_paddr)); 1570d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_RXSTAT_CNT, ET_RX_NSTAT - 1); 1571d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_RXSTAT_POS, 0); 1572d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_RXSTAT_MINCNT, ((ET_RX_NSTAT * 15) / 100) - 1); 1573d217d4d9SSepherosa Ziehau 1574d217d4d9SSepherosa Ziehau /* Match ET_RXSTAT_POS */ 1575d217d4d9SSepherosa Ziehau rxst_ring->rsr_index = 0; 1576d217d4d9SSepherosa Ziehau rxst_ring->rsr_wrap = 0; 1577d217d4d9SSepherosa Ziehau 1578d217d4d9SSepherosa Ziehau /* 1579d217d4d9SSepherosa Ziehau * Install the 2nd RX descriptor ring 1580d217d4d9SSepherosa Ziehau */ 1581d217d4d9SSepherosa Ziehau rx_ring = &sc->sc_rx_ring[1]; 1582d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_RX_RING1_HI, ET_ADDR_HI(rx_ring->rr_paddr)); 1583d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_RX_RING1_LO, ET_ADDR_LO(rx_ring->rr_paddr)); 1584d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_RX_RING1_CNT, ET_RX_NDESC - 1); 1585d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_RX_RING1_POS, ET_RX_RING1_POS_WRAP); 1586d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_RX_RING1_MINCNT, ((ET_RX_NDESC * 15) / 100) - 1); 1587d217d4d9SSepherosa Ziehau 1588d217d4d9SSepherosa Ziehau /* Match ET_RX_RING1_POS */ 1589d217d4d9SSepherosa Ziehau rx_ring->rr_index = 0; 1590d217d4d9SSepherosa Ziehau rx_ring->rr_wrap = 1; 1591d217d4d9SSepherosa Ziehau 1592d217d4d9SSepherosa Ziehau /* 1593d217d4d9SSepherosa Ziehau * Install the 1st RX descriptor ring 1594d217d4d9SSepherosa Ziehau */ 1595d217d4d9SSepherosa Ziehau rx_ring = &sc->sc_rx_ring[0]; 1596d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_RX_RING0_HI, ET_ADDR_HI(rx_ring->rr_paddr)); 1597d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_RX_RING0_LO, ET_ADDR_LO(rx_ring->rr_paddr)); 1598d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_RX_RING0_CNT, ET_RX_NDESC - 1); 1599d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_RX_RING0_POS, ET_RX_RING0_POS_WRAP); 1600d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_RX_RING0_MINCNT, ((ET_RX_NDESC * 15) / 100) - 1); 1601d217d4d9SSepherosa Ziehau 1602d217d4d9SSepherosa Ziehau /* Match ET_RX_RING0_POS */ 1603d217d4d9SSepherosa Ziehau rx_ring->rr_index = 0; 1604d217d4d9SSepherosa Ziehau rx_ring->rr_wrap = 1; 1605d217d4d9SSepherosa Ziehau 1606d217d4d9SSepherosa Ziehau /* 1607d217d4d9SSepherosa Ziehau * RX intr moderation 1608d217d4d9SSepherosa Ziehau */ 1609d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_RX_INTR_NPKTS, sc->sc_rx_intr_npkts); 1610d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_RX_INTR_DELAY, sc->sc_rx_intr_delay); 1611d217d4d9SSepherosa Ziehau 1612d217d4d9SSepherosa Ziehau return 0; 1613d217d4d9SSepherosa Ziehau } 1614d217d4d9SSepherosa Ziehau 1615d217d4d9SSepherosa Ziehau static int 1616d217d4d9SSepherosa Ziehau et_init_txdma(struct et_softc *sc) 1617d217d4d9SSepherosa Ziehau { 1618d217d4d9SSepherosa Ziehau struct et_txdesc_ring *tx_ring = &sc->sc_tx_ring; 1619d217d4d9SSepherosa Ziehau struct et_txstatus_data *txsd = &sc->sc_tx_status; 1620d217d4d9SSepherosa Ziehau int error; 1621d217d4d9SSepherosa Ziehau 1622d217d4d9SSepherosa Ziehau error = et_stop_txdma(sc); 1623d217d4d9SSepherosa Ziehau if (error) { 1624d217d4d9SSepherosa Ziehau if_printf(&sc->arpcom.ac_if, "can't init TX DMA engine\n"); 1625d217d4d9SSepherosa Ziehau return error; 1626d217d4d9SSepherosa Ziehau } 1627d217d4d9SSepherosa Ziehau 1628d217d4d9SSepherosa Ziehau /* 1629d217d4d9SSepherosa Ziehau * Install TX descriptor ring 1630d217d4d9SSepherosa Ziehau */ 1631d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_TX_RING_HI, ET_ADDR_HI(tx_ring->tr_paddr)); 1632d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_TX_RING_LO, ET_ADDR_LO(tx_ring->tr_paddr)); 1633d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_TX_RING_CNT, ET_TX_NDESC - 1); 1634d217d4d9SSepherosa Ziehau 1635d217d4d9SSepherosa Ziehau /* 1636d217d4d9SSepherosa Ziehau * Install TX status 1637d217d4d9SSepherosa Ziehau */ 1638d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_TX_STATUS_HI, ET_ADDR_HI(txsd->txsd_paddr)); 1639d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_TX_STATUS_LO, ET_ADDR_LO(txsd->txsd_paddr)); 1640d217d4d9SSepherosa Ziehau 1641d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_TX_READY_POS, 0); 1642d217d4d9SSepherosa Ziehau 1643d217d4d9SSepherosa Ziehau /* Match ET_TX_READY_POS */ 1644d217d4d9SSepherosa Ziehau tx_ring->tr_ready_index = 0; 1645d217d4d9SSepherosa Ziehau tx_ring->tr_ready_wrap = 0; 1646d217d4d9SSepherosa Ziehau 1647d217d4d9SSepherosa Ziehau return 0; 1648d217d4d9SSepherosa Ziehau } 1649d217d4d9SSepherosa Ziehau 1650d217d4d9SSepherosa Ziehau static void 1651d217d4d9SSepherosa Ziehau et_init_mac(struct et_softc *sc) 1652d217d4d9SSepherosa Ziehau { 1653d217d4d9SSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 1654d217d4d9SSepherosa Ziehau const uint8_t *eaddr = IF_LLADDR(ifp); 1655d217d4d9SSepherosa Ziehau uint32_t val; 1656d217d4d9SSepherosa Ziehau 1657d217d4d9SSepherosa Ziehau /* Reset MAC */ 1658d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_MAC_CFG1, 1659d217d4d9SSepherosa Ziehau ET_MAC_CFG1_RST_TXFUNC | ET_MAC_CFG1_RST_RXFUNC | 1660d217d4d9SSepherosa Ziehau ET_MAC_CFG1_RST_TXMC | ET_MAC_CFG1_RST_RXMC | 1661d217d4d9SSepherosa Ziehau ET_MAC_CFG1_SIM_RST | ET_MAC_CFG1_SOFT_RST); 1662d217d4d9SSepherosa Ziehau 1663d217d4d9SSepherosa Ziehau /* 1664d217d4d9SSepherosa Ziehau * Setup inter packet gap 1665d217d4d9SSepherosa Ziehau */ 1666d217d4d9SSepherosa Ziehau val = __SHIFTIN(56, ET_IPG_NONB2B_1) | 1667d217d4d9SSepherosa Ziehau __SHIFTIN(88, ET_IPG_NONB2B_2) | 1668d217d4d9SSepherosa Ziehau __SHIFTIN(80, ET_IPG_MINIFG) | 1669d217d4d9SSepherosa Ziehau __SHIFTIN(96, ET_IPG_B2B); 1670d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_IPG, val); 1671d217d4d9SSepherosa Ziehau 1672d217d4d9SSepherosa Ziehau /* 1673d217d4d9SSepherosa Ziehau * Setup half duplex mode 1674d217d4d9SSepherosa Ziehau */ 1675d217d4d9SSepherosa Ziehau val = __SHIFTIN(10, ET_MAC_HDX_ALT_BEB_TRUNC) | 1676d217d4d9SSepherosa Ziehau __SHIFTIN(15, ET_MAC_HDX_REXMIT_MAX) | 1677d217d4d9SSepherosa Ziehau __SHIFTIN(55, ET_MAC_HDX_COLLWIN) | 1678d217d4d9SSepherosa Ziehau ET_MAC_HDX_EXC_DEFER; 1679d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_MAC_HDX, val); 1680d217d4d9SSepherosa Ziehau 1681d217d4d9SSepherosa Ziehau /* Clear MAC control */ 1682d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_MAC_CTRL, 0); 1683d217d4d9SSepherosa Ziehau 1684d217d4d9SSepherosa Ziehau /* Reset MII */ 1685d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_MII_CFG, ET_MII_CFG_CLKRST); 1686d217d4d9SSepherosa Ziehau 1687d217d4d9SSepherosa Ziehau /* 1688d217d4d9SSepherosa Ziehau * Set MAC address 1689d217d4d9SSepherosa Ziehau */ 1690d217d4d9SSepherosa Ziehau val = eaddr[2] | (eaddr[3] << 8) | (eaddr[4] << 16) | (eaddr[5] << 24); 1691d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_MAC_ADDR1, val); 1692d217d4d9SSepherosa Ziehau val = (eaddr[0] << 16) | (eaddr[1] << 24); 1693d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_MAC_ADDR2, val); 1694d217d4d9SSepherosa Ziehau 1695d217d4d9SSepherosa Ziehau /* Set max frame length */ 16960fd7469eSSepherosa Ziehau CSR_WRITE_4(sc, ET_MAX_FRMLEN, ET_FRAMELEN(ifp->if_mtu)); 1697d217d4d9SSepherosa Ziehau 1698d217d4d9SSepherosa Ziehau /* Bring MAC out of reset state */ 1699d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_MAC_CFG1, 0); 1700d217d4d9SSepherosa Ziehau } 1701d217d4d9SSepherosa Ziehau 1702d217d4d9SSepherosa Ziehau static void 1703d217d4d9SSepherosa Ziehau et_init_rxmac(struct et_softc *sc) 1704d217d4d9SSepherosa Ziehau { 1705d217d4d9SSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 1706d217d4d9SSepherosa Ziehau const uint8_t *eaddr = IF_LLADDR(ifp); 1707d217d4d9SSepherosa Ziehau uint32_t val; 1708d217d4d9SSepherosa Ziehau int i; 1709d217d4d9SSepherosa Ziehau 1710d217d4d9SSepherosa Ziehau /* Disable RX MAC and WOL */ 1711d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_RXMAC_CTRL, ET_RXMAC_CTRL_WOL_DISABLE); 1712d217d4d9SSepherosa Ziehau 1713d217d4d9SSepherosa Ziehau /* 1714d217d4d9SSepherosa Ziehau * Clear all WOL related registers 1715d217d4d9SSepherosa Ziehau */ 1716d217d4d9SSepherosa Ziehau for (i = 0; i < 3; ++i) 1717d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_WOL_CRC + (i * 4), 0); 1718d217d4d9SSepherosa Ziehau for (i = 0; i < 20; ++i) 1719d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_WOL_MASK + (i * 4), 0); 1720d217d4d9SSepherosa Ziehau 1721d217d4d9SSepherosa Ziehau /* 1722d217d4d9SSepherosa Ziehau * Set WOL source address. XXX is this necessary? 1723d217d4d9SSepherosa Ziehau */ 1724d217d4d9SSepherosa Ziehau val = (eaddr[2] << 24) | (eaddr[3] << 16) | (eaddr[4] << 8) | eaddr[5]; 1725d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_WOL_SA_LO, val); 1726d217d4d9SSepherosa Ziehau val = (eaddr[0] << 8) | eaddr[1]; 1727d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_WOL_SA_HI, val); 1728d217d4d9SSepherosa Ziehau 1729d217d4d9SSepherosa Ziehau /* Clear packet filters */ 1730d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_PKTFILT, 0); 1731d217d4d9SSepherosa Ziehau 1732d217d4d9SSepherosa Ziehau /* No ucast filtering */ 1733d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_UCAST_FILTADDR1, 0); 1734d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_UCAST_FILTADDR2, 0); 1735d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_UCAST_FILTADDR3, 0); 1736d217d4d9SSepherosa Ziehau 17373effc1bfSSepherosa Ziehau if (ET_FRAMELEN(ifp->if_mtu) > ET_RXMAC_CUT_THRU_FRMLEN) { 1738d217d4d9SSepherosa Ziehau /* 17393effc1bfSSepherosa Ziehau * In order to transmit jumbo packets greater than 17403effc1bfSSepherosa Ziehau * ET_RXMAC_CUT_THRU_FRMLEN bytes, the FIFO between 17413effc1bfSSepherosa Ziehau * RX MAC and RX DMA needs to be reduced in size to 17423effc1bfSSepherosa Ziehau * (ET_MEM_SIZE - ET_MEM_TXSIZE_EX - framelen). In 17433effc1bfSSepherosa Ziehau * order to implement this, we must use "cut through" 17443effc1bfSSepherosa Ziehau * mode in the RX MAC, which chops packets down into 17453effc1bfSSepherosa Ziehau * segments. In this case we selected 256 bytes, 17463effc1bfSSepherosa Ziehau * since this is the size of the PCI-Express TLP's 17473effc1bfSSepherosa Ziehau * that the ET1310 uses. 1748d217d4d9SSepherosa Ziehau */ 17493effc1bfSSepherosa Ziehau val = __SHIFTIN(ET_RXMAC_SEGSZ(256), ET_RXMAC_MC_SEGSZ_MAX) | 1750d217d4d9SSepherosa Ziehau ET_RXMAC_MC_SEGSZ_ENABLE; 1751d217d4d9SSepherosa Ziehau } else { 1752d217d4d9SSepherosa Ziehau val = 0; 1753d217d4d9SSepherosa Ziehau } 1754d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_RXMAC_MC_SEGSZ, val); 1755d217d4d9SSepherosa Ziehau 1756d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_RXMAC_MC_WATERMARK, 0); 1757d217d4d9SSepherosa Ziehau 1758d217d4d9SSepherosa Ziehau /* Initialize RX MAC management register */ 1759d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_RXMAC_MGT, 0); 1760d217d4d9SSepherosa Ziehau 1761d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_RXMAC_SPACE_AVL, 0); 1762d217d4d9SSepherosa Ziehau 1763d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_RXMAC_MGT, 1764d217d4d9SSepherosa Ziehau ET_RXMAC_MGT_PASS_ECRC | 1765d217d4d9SSepherosa Ziehau ET_RXMAC_MGT_PASS_ELEN | 1766d217d4d9SSepherosa Ziehau ET_RXMAC_MGT_PASS_ETRUNC | 1767d217d4d9SSepherosa Ziehau ET_RXMAC_MGT_CHECK_PKT); 1768d217d4d9SSepherosa Ziehau 1769d217d4d9SSepherosa Ziehau /* 1770d217d4d9SSepherosa Ziehau * Configure runt filtering (may not work on certain chip generation) 1771d217d4d9SSepherosa Ziehau */ 1772d217d4d9SSepherosa Ziehau val = __SHIFTIN(ETHER_MIN_LEN, ET_PKTFILT_MINLEN) | ET_PKTFILT_FRAG; 1773d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_PKTFILT, val); 1774d217d4d9SSepherosa Ziehau 1775d217d4d9SSepherosa Ziehau /* Enable RX MAC but leave WOL disabled */ 1776d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_RXMAC_CTRL, 1777d217d4d9SSepherosa Ziehau ET_RXMAC_CTRL_WOL_DISABLE | ET_RXMAC_CTRL_ENABLE); 1778d217d4d9SSepherosa Ziehau 1779d217d4d9SSepherosa Ziehau /* 1780d217d4d9SSepherosa Ziehau * Setup multicast hash and allmulti/promisc mode 1781d217d4d9SSepherosa Ziehau */ 1782d217d4d9SSepherosa Ziehau et_setmulti(sc); 1783d217d4d9SSepherosa Ziehau } 1784d217d4d9SSepherosa Ziehau 1785d217d4d9SSepherosa Ziehau static void 1786d217d4d9SSepherosa Ziehau et_init_txmac(struct et_softc *sc) 1787d217d4d9SSepherosa Ziehau { 1788d217d4d9SSepherosa Ziehau /* Disable TX MAC and FC(?) */ 1789d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_TXMAC_CTRL, ET_TXMAC_CTRL_FC_DISABLE); 1790d217d4d9SSepherosa Ziehau 1791d217d4d9SSepherosa Ziehau /* No flow control yet */ 1792d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_TXMAC_FLOWCTRL, 0); 1793d217d4d9SSepherosa Ziehau 1794d217d4d9SSepherosa Ziehau /* Enable TX MAC but leave FC(?) diabled */ 1795d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_TXMAC_CTRL, 1796d217d4d9SSepherosa Ziehau ET_TXMAC_CTRL_ENABLE | ET_TXMAC_CTRL_FC_DISABLE); 1797d217d4d9SSepherosa Ziehau } 1798d217d4d9SSepherosa Ziehau 1799d217d4d9SSepherosa Ziehau static int 1800d217d4d9SSepherosa Ziehau et_start_rxdma(struct et_softc *sc) 1801d217d4d9SSepherosa Ziehau { 1802d217d4d9SSepherosa Ziehau uint32_t val = 0; 1803d217d4d9SSepherosa Ziehau 1804d217d4d9SSepherosa Ziehau val |= __SHIFTIN(sc->sc_rx_data[0].rbd_bufsize, 1805d217d4d9SSepherosa Ziehau ET_RXDMA_CTRL_RING0_SIZE) | 1806d217d4d9SSepherosa Ziehau ET_RXDMA_CTRL_RING0_ENABLE; 1807d217d4d9SSepherosa Ziehau val |= __SHIFTIN(sc->sc_rx_data[1].rbd_bufsize, 1808d217d4d9SSepherosa Ziehau ET_RXDMA_CTRL_RING1_SIZE) | 1809d217d4d9SSepherosa Ziehau ET_RXDMA_CTRL_RING1_ENABLE; 1810d217d4d9SSepherosa Ziehau 1811d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_RXDMA_CTRL, val); 1812d217d4d9SSepherosa Ziehau 1813d217d4d9SSepherosa Ziehau DELAY(5); 1814d217d4d9SSepherosa Ziehau 1815d217d4d9SSepherosa Ziehau if (CSR_READ_4(sc, ET_RXDMA_CTRL) & ET_RXDMA_CTRL_HALTED) { 1816d217d4d9SSepherosa Ziehau if_printf(&sc->arpcom.ac_if, "can't start RX DMA engine\n"); 1817d217d4d9SSepherosa Ziehau return ETIMEDOUT; 1818d217d4d9SSepherosa Ziehau } 1819d217d4d9SSepherosa Ziehau return 0; 1820d217d4d9SSepherosa Ziehau } 1821d217d4d9SSepherosa Ziehau 1822d217d4d9SSepherosa Ziehau static int 1823d217d4d9SSepherosa Ziehau et_start_txdma(struct et_softc *sc) 1824d217d4d9SSepherosa Ziehau { 1825d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_TXDMA_CTRL, ET_TXDMA_CTRL_SINGLE_EPKT); 1826d217d4d9SSepherosa Ziehau return 0; 1827d217d4d9SSepherosa Ziehau } 1828d217d4d9SSepherosa Ziehau 1829d217d4d9SSepherosa Ziehau static int 183060d2de1fSSepherosa Ziehau et_enable_txrx(struct et_softc *sc, int media_upd) 1831d217d4d9SSepherosa Ziehau { 1832d217d4d9SSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 1833d217d4d9SSepherosa Ziehau uint32_t val; 183460d2de1fSSepherosa Ziehau int i, error; 1835d217d4d9SSepherosa Ziehau 1836d217d4d9SSepherosa Ziehau val = CSR_READ_4(sc, ET_MAC_CFG1); 1837d217d4d9SSepherosa Ziehau val |= ET_MAC_CFG1_TXEN | ET_MAC_CFG1_RXEN; 1838d217d4d9SSepherosa Ziehau val &= ~(ET_MAC_CFG1_TXFLOW | ET_MAC_CFG1_RXFLOW | 1839d217d4d9SSepherosa Ziehau ET_MAC_CFG1_LOOPBACK); 1840d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_MAC_CFG1, val); 1841d217d4d9SSepherosa Ziehau 184260d2de1fSSepherosa Ziehau if (media_upd) 1843d217d4d9SSepherosa Ziehau et_ifmedia_upd(ifp); 184460d2de1fSSepherosa Ziehau else 184560d2de1fSSepherosa Ziehau et_setmedia(sc); 1846d217d4d9SSepherosa Ziehau 1847d217d4d9SSepherosa Ziehau #define NRETRY 100 1848d217d4d9SSepherosa Ziehau 1849d217d4d9SSepherosa Ziehau for (i = 0; i < NRETRY; ++i) { 1850d217d4d9SSepherosa Ziehau val = CSR_READ_4(sc, ET_MAC_CFG1); 1851d217d4d9SSepherosa Ziehau if ((val & (ET_MAC_CFG1_SYNC_TXEN | ET_MAC_CFG1_SYNC_RXEN)) == 1852d217d4d9SSepherosa Ziehau (ET_MAC_CFG1_SYNC_TXEN | ET_MAC_CFG1_SYNC_RXEN)) 1853d217d4d9SSepherosa Ziehau break; 1854d217d4d9SSepherosa Ziehau 1855d217d4d9SSepherosa Ziehau DELAY(10); 1856d217d4d9SSepherosa Ziehau } 1857d217d4d9SSepherosa Ziehau if (i == NRETRY) { 1858d217d4d9SSepherosa Ziehau if_printf(ifp, "can't enable RX/TX\n"); 185960d2de1fSSepherosa Ziehau return 0; 1860d217d4d9SSepherosa Ziehau } 18613effc1bfSSepherosa Ziehau sc->sc_flags |= ET_FLAG_TXRX_ENABLED; 1862d217d4d9SSepherosa Ziehau 1863d217d4d9SSepherosa Ziehau #undef NRETRY 186460d2de1fSSepherosa Ziehau 186560d2de1fSSepherosa Ziehau /* 186660d2de1fSSepherosa Ziehau * Start TX/RX DMA engine 186760d2de1fSSepherosa Ziehau */ 186860d2de1fSSepherosa Ziehau error = et_start_rxdma(sc); 186960d2de1fSSepherosa Ziehau if (error) 187060d2de1fSSepherosa Ziehau return error; 187160d2de1fSSepherosa Ziehau 187260d2de1fSSepherosa Ziehau error = et_start_txdma(sc); 187360d2de1fSSepherosa Ziehau if (error) 187460d2de1fSSepherosa Ziehau return error; 187560d2de1fSSepherosa Ziehau 1876d217d4d9SSepherosa Ziehau return 0; 1877d217d4d9SSepherosa Ziehau } 1878d217d4d9SSepherosa Ziehau 1879d217d4d9SSepherosa Ziehau static void 1880d217d4d9SSepherosa Ziehau et_rxeof(struct et_softc *sc) 1881d217d4d9SSepherosa Ziehau { 1882d217d4d9SSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 1883d217d4d9SSepherosa Ziehau struct et_rxstatus_data *rxsd = &sc->sc_rx_status; 1884d217d4d9SSepherosa Ziehau struct et_rxstat_ring *rxst_ring = &sc->sc_rxstat_ring; 1885d217d4d9SSepherosa Ziehau uint32_t rxs_stat_ring; 1886d217d4d9SSepherosa Ziehau int rxst_wrap, rxst_index; 1887d217d4d9SSepherosa Ziehau 18883effc1bfSSepherosa Ziehau if ((sc->sc_flags & ET_FLAG_TXRX_ENABLED) == 0) 188960d2de1fSSepherosa Ziehau return; 189060d2de1fSSepherosa Ziehau 1891d217d4d9SSepherosa Ziehau bus_dmamap_sync(rxsd->rxsd_dtag, rxsd->rxsd_dmap, 1892d217d4d9SSepherosa Ziehau BUS_DMASYNC_POSTREAD); 1893d217d4d9SSepherosa Ziehau bus_dmamap_sync(rxst_ring->rsr_dtag, rxst_ring->rsr_dmap, 1894d217d4d9SSepherosa Ziehau BUS_DMASYNC_POSTREAD); 1895d217d4d9SSepherosa Ziehau 1896d217d4d9SSepherosa Ziehau rxs_stat_ring = rxsd->rxsd_status->rxs_stat_ring; 1897d217d4d9SSepherosa Ziehau rxst_wrap = (rxs_stat_ring & ET_RXS_STATRING_WRAP) ? 1 : 0; 1898d217d4d9SSepherosa Ziehau rxst_index = __SHIFTOUT(rxs_stat_ring, ET_RXS_STATRING_INDEX); 1899d217d4d9SSepherosa Ziehau 1900d217d4d9SSepherosa Ziehau while (rxst_index != rxst_ring->rsr_index || 1901d217d4d9SSepherosa Ziehau rxst_wrap != rxst_ring->rsr_wrap) { 1902d217d4d9SSepherosa Ziehau struct et_rxbuf_data *rbd; 1903d217d4d9SSepherosa Ziehau struct et_rxdesc_ring *rx_ring; 1904d217d4d9SSepherosa Ziehau struct et_rxstat *st; 1905d217d4d9SSepherosa Ziehau struct mbuf *m; 1906d217d4d9SSepherosa Ziehau int buflen, buf_idx, ring_idx; 1907d217d4d9SSepherosa Ziehau uint32_t rxstat_pos, rxring_pos; 1908d217d4d9SSepherosa Ziehau 1909d217d4d9SSepherosa Ziehau KKASSERT(rxst_ring->rsr_index < ET_RX_NSTAT); 1910d217d4d9SSepherosa Ziehau st = &rxst_ring->rsr_stat[rxst_ring->rsr_index]; 1911d217d4d9SSepherosa Ziehau 1912d217d4d9SSepherosa Ziehau buflen = __SHIFTOUT(st->rxst_info2, ET_RXST_INFO2_LEN); 1913d217d4d9SSepherosa Ziehau buf_idx = __SHIFTOUT(st->rxst_info2, ET_RXST_INFO2_BUFIDX); 1914d217d4d9SSepherosa Ziehau ring_idx = __SHIFTOUT(st->rxst_info2, ET_RXST_INFO2_RINGIDX); 1915d217d4d9SSepherosa Ziehau 1916d217d4d9SSepherosa Ziehau if (++rxst_ring->rsr_index == ET_RX_NSTAT) { 1917d217d4d9SSepherosa Ziehau rxst_ring->rsr_index = 0; 1918d217d4d9SSepherosa Ziehau rxst_ring->rsr_wrap ^= 1; 1919d217d4d9SSepherosa Ziehau } 1920d217d4d9SSepherosa Ziehau rxstat_pos = __SHIFTIN(rxst_ring->rsr_index, 1921d217d4d9SSepherosa Ziehau ET_RXSTAT_POS_INDEX); 1922d217d4d9SSepherosa Ziehau if (rxst_ring->rsr_wrap) 1923d217d4d9SSepherosa Ziehau rxstat_pos |= ET_RXSTAT_POS_WRAP; 1924d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_RXSTAT_POS, rxstat_pos); 1925d217d4d9SSepherosa Ziehau 1926d217d4d9SSepherosa Ziehau if (ring_idx >= ET_RX_NRING) { 1927d217d4d9SSepherosa Ziehau ifp->if_ierrors++; 1928d217d4d9SSepherosa Ziehau if_printf(ifp, "invalid ring index %d\n", ring_idx); 1929d217d4d9SSepherosa Ziehau continue; 1930d217d4d9SSepherosa Ziehau } 1931d217d4d9SSepherosa Ziehau if (buf_idx >= ET_RX_NDESC) { 1932d217d4d9SSepherosa Ziehau ifp->if_ierrors++; 1933d217d4d9SSepherosa Ziehau if_printf(ifp, "invalid buf index %d\n", buf_idx); 1934d217d4d9SSepherosa Ziehau continue; 1935d217d4d9SSepherosa Ziehau } 1936d217d4d9SSepherosa Ziehau 1937d217d4d9SSepherosa Ziehau rbd = &sc->sc_rx_data[ring_idx]; 19383effc1bfSSepherosa Ziehau m = rbd->rbd_buf[buf_idx].rb_mbuf; 1939d217d4d9SSepherosa Ziehau 1940d217d4d9SSepherosa Ziehau if (rbd->rbd_newbuf(rbd, buf_idx, 0) == 0) { 19410fd7469eSSepherosa Ziehau if (buflen < ETHER_CRC_LEN) { 19420fd7469eSSepherosa Ziehau m_freem(m); 19430fd7469eSSepherosa Ziehau ifp->if_ierrors++; 19440fd7469eSSepherosa Ziehau } else { 1945d217d4d9SSepherosa Ziehau m->m_pkthdr.len = m->m_len = buflen; 1946d217d4d9SSepherosa Ziehau m->m_pkthdr.rcvif = ifp; 1947d217d4d9SSepherosa Ziehau 19480fd7469eSSepherosa Ziehau m_adj(m, -ETHER_CRC_LEN); 19490fd7469eSSepherosa Ziehau 1950d217d4d9SSepherosa Ziehau ifp->if_ipackets++; 1951d217d4d9SSepherosa Ziehau ifp->if_input(ifp, m); 19520fd7469eSSepherosa Ziehau } 1953d217d4d9SSepherosa Ziehau } else { 1954d217d4d9SSepherosa Ziehau ifp->if_ierrors++; 1955d217d4d9SSepherosa Ziehau } 19560fd7469eSSepherosa Ziehau m = NULL; /* Catch invalid reference */ 1957d217d4d9SSepherosa Ziehau 1958d217d4d9SSepherosa Ziehau rx_ring = &sc->sc_rx_ring[ring_idx]; 1959d217d4d9SSepherosa Ziehau 1960d217d4d9SSepherosa Ziehau if (buf_idx != rx_ring->rr_index) { 1961d217d4d9SSepherosa Ziehau if_printf(ifp, "WARNING!! ring %d, " 1962d217d4d9SSepherosa Ziehau "buf_idx %d, rr_idx %d\n", 1963d217d4d9SSepherosa Ziehau ring_idx, buf_idx, rx_ring->rr_index); 1964d217d4d9SSepherosa Ziehau } 1965d217d4d9SSepherosa Ziehau 1966d217d4d9SSepherosa Ziehau KKASSERT(rx_ring->rr_index < ET_RX_NDESC); 1967d217d4d9SSepherosa Ziehau if (++rx_ring->rr_index == ET_RX_NDESC) { 1968d217d4d9SSepherosa Ziehau rx_ring->rr_index = 0; 1969d217d4d9SSepherosa Ziehau rx_ring->rr_wrap ^= 1; 1970d217d4d9SSepherosa Ziehau } 1971d217d4d9SSepherosa Ziehau rxring_pos = __SHIFTIN(rx_ring->rr_index, ET_RX_RING_POS_INDEX); 1972d217d4d9SSepherosa Ziehau if (rx_ring->rr_wrap) 1973d217d4d9SSepherosa Ziehau rxring_pos |= ET_RX_RING_POS_WRAP; 1974d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, rx_ring->rr_posreg, rxring_pos); 1975d217d4d9SSepherosa Ziehau } 1976d217d4d9SSepherosa Ziehau } 1977d217d4d9SSepherosa Ziehau 1978d217d4d9SSepherosa Ziehau static int 1979d217d4d9SSepherosa Ziehau et_encap(struct et_softc *sc, struct mbuf **m0) 1980d217d4d9SSepherosa Ziehau { 1981d217d4d9SSepherosa Ziehau struct mbuf *m = *m0; 1982d217d4d9SSepherosa Ziehau bus_dma_segment_t segs[ET_NSEG_MAX]; 1983d217d4d9SSepherosa Ziehau struct et_dmamap_ctx ctx; 1984d217d4d9SSepherosa Ziehau struct et_txdesc_ring *tx_ring = &sc->sc_tx_ring; 1985d217d4d9SSepherosa Ziehau struct et_txbuf_data *tbd = &sc->sc_tx_data; 1986d217d4d9SSepherosa Ziehau struct et_txdesc *td; 1987d217d4d9SSepherosa Ziehau bus_dmamap_t map; 1988d217d4d9SSepherosa Ziehau int error, maxsegs, first_idx, last_idx, i; 1989d217d4d9SSepherosa Ziehau uint32_t tx_ready_pos, last_td_ctrl2; 1990d217d4d9SSepherosa Ziehau 1991d217d4d9SSepherosa Ziehau maxsegs = ET_TX_NDESC - tbd->tbd_used; 1992d217d4d9SSepherosa Ziehau if (maxsegs > ET_NSEG_MAX) 1993d217d4d9SSepherosa Ziehau maxsegs = ET_NSEG_MAX; 1994d217d4d9SSepherosa Ziehau KASSERT(maxsegs >= ET_NSEG_SPARE, 1995d217d4d9SSepherosa Ziehau ("not enough spare TX desc (%d)\n", maxsegs)); 1996d217d4d9SSepherosa Ziehau 1997d217d4d9SSepherosa Ziehau KKASSERT(tx_ring->tr_ready_index < ET_TX_NDESC); 1998d217d4d9SSepherosa Ziehau first_idx = tx_ring->tr_ready_index; 1999d217d4d9SSepherosa Ziehau map = tbd->tbd_buf[first_idx].tb_dmap; 2000d217d4d9SSepherosa Ziehau 2001d217d4d9SSepherosa Ziehau ctx.nsegs = maxsegs; 2002d217d4d9SSepherosa Ziehau ctx.segs = segs; 2003d217d4d9SSepherosa Ziehau error = bus_dmamap_load_mbuf(sc->sc_mbuf_dtag, map, m, 2004d217d4d9SSepherosa Ziehau et_dma_buf_addr, &ctx, BUS_DMA_NOWAIT); 2005d217d4d9SSepherosa Ziehau if (!error && ctx.nsegs == 0) { 2006d217d4d9SSepherosa Ziehau bus_dmamap_unload(sc->sc_mbuf_dtag, map); 2007d217d4d9SSepherosa Ziehau error = EFBIG; 2008d217d4d9SSepherosa Ziehau } 2009d217d4d9SSepherosa Ziehau if (error && error != EFBIG) { 20103effc1bfSSepherosa Ziehau if_printf(&sc->arpcom.ac_if, "can't load TX mbuf, error %d\n", 20113effc1bfSSepherosa Ziehau error); 2012d217d4d9SSepherosa Ziehau goto back; 2013d217d4d9SSepherosa Ziehau } 2014d217d4d9SSepherosa Ziehau if (error) { /* error == EFBIG */ 2015d217d4d9SSepherosa Ziehau struct mbuf *m_new; 2016d217d4d9SSepherosa Ziehau 2017d217d4d9SSepherosa Ziehau m_new = m_defrag(m, MB_DONTWAIT); 2018d217d4d9SSepherosa Ziehau if (m_new == NULL) { 2019d217d4d9SSepherosa Ziehau if_printf(&sc->arpcom.ac_if, "can't defrag TX mbuf\n"); 2020d217d4d9SSepherosa Ziehau error = ENOBUFS; 2021d217d4d9SSepherosa Ziehau goto back; 2022d217d4d9SSepherosa Ziehau } else { 2023d217d4d9SSepherosa Ziehau *m0 = m = m_new; 2024d217d4d9SSepherosa Ziehau } 2025d217d4d9SSepherosa Ziehau 2026d217d4d9SSepherosa Ziehau ctx.nsegs = maxsegs; 2027d217d4d9SSepherosa Ziehau ctx.segs = segs; 2028d217d4d9SSepherosa Ziehau error = bus_dmamap_load_mbuf(sc->sc_mbuf_dtag, map, m, 2029d217d4d9SSepherosa Ziehau et_dma_buf_addr, &ctx, 2030d217d4d9SSepherosa Ziehau BUS_DMA_NOWAIT); 2031d217d4d9SSepherosa Ziehau if (error || ctx.nsegs == 0) { 2032d217d4d9SSepherosa Ziehau if (ctx.nsegs == 0) { 2033d217d4d9SSepherosa Ziehau bus_dmamap_unload(sc->sc_mbuf_dtag, map); 2034d217d4d9SSepherosa Ziehau error = EFBIG; 2035d217d4d9SSepherosa Ziehau } 2036d217d4d9SSepherosa Ziehau if_printf(&sc->arpcom.ac_if, 2037d217d4d9SSepherosa Ziehau "can't load defraged TX mbuf\n"); 2038d217d4d9SSepherosa Ziehau goto back; 2039d217d4d9SSepherosa Ziehau } 2040d217d4d9SSepherosa Ziehau } 2041d217d4d9SSepherosa Ziehau 2042d217d4d9SSepherosa Ziehau bus_dmamap_sync(sc->sc_mbuf_dtag, map, BUS_DMASYNC_PREWRITE); 2043d217d4d9SSepherosa Ziehau 2044d217d4d9SSepherosa Ziehau last_td_ctrl2 = ET_TDCTRL2_LAST_FRAG; 2045d217d4d9SSepherosa Ziehau sc->sc_tx += ctx.nsegs; 2046d217d4d9SSepherosa Ziehau if (sc->sc_tx / sc->sc_tx_intr_nsegs != sc->sc_tx_intr) { 2047d217d4d9SSepherosa Ziehau sc->sc_tx_intr = sc->sc_tx / sc->sc_tx_intr_nsegs; 2048d217d4d9SSepherosa Ziehau last_td_ctrl2 |= ET_TDCTRL2_INTR; 2049d217d4d9SSepherosa Ziehau } 2050d217d4d9SSepherosa Ziehau 2051d217d4d9SSepherosa Ziehau last_idx = -1; 2052d217d4d9SSepherosa Ziehau for (i = 0; i < ctx.nsegs; ++i) { 2053d217d4d9SSepherosa Ziehau int idx; 2054d217d4d9SSepherosa Ziehau 2055d217d4d9SSepherosa Ziehau idx = (first_idx + i) % ET_TX_NDESC; 2056d217d4d9SSepherosa Ziehau td = &tx_ring->tr_desc[idx]; 2057d217d4d9SSepherosa Ziehau td->td_addr_hi = ET_ADDR_HI(segs[i].ds_addr); 2058d217d4d9SSepherosa Ziehau td->td_addr_lo = ET_ADDR_LO(segs[i].ds_addr); 2059d217d4d9SSepherosa Ziehau td->td_ctrl1 = __SHIFTIN(segs[i].ds_len, ET_TDCTRL1_LEN); 2060d217d4d9SSepherosa Ziehau 2061d217d4d9SSepherosa Ziehau if (i == ctx.nsegs - 1) { /* Last frag */ 2062d217d4d9SSepherosa Ziehau td->td_ctrl2 = last_td_ctrl2; 2063d217d4d9SSepherosa Ziehau last_idx = idx; 2064d217d4d9SSepherosa Ziehau } 2065d217d4d9SSepherosa Ziehau 2066d217d4d9SSepherosa Ziehau KKASSERT(tx_ring->tr_ready_index < ET_TX_NDESC); 2067d217d4d9SSepherosa Ziehau if (++tx_ring->tr_ready_index == ET_TX_NDESC) { 2068d217d4d9SSepherosa Ziehau tx_ring->tr_ready_index = 0; 2069d217d4d9SSepherosa Ziehau tx_ring->tr_ready_wrap ^= 1; 2070d217d4d9SSepherosa Ziehau } 2071d217d4d9SSepherosa Ziehau } 2072d217d4d9SSepherosa Ziehau td = &tx_ring->tr_desc[first_idx]; 2073d217d4d9SSepherosa Ziehau td->td_ctrl2 |= ET_TDCTRL2_FIRST_FRAG; /* First frag */ 2074d217d4d9SSepherosa Ziehau 2075d217d4d9SSepherosa Ziehau KKASSERT(last_idx >= 0); 2076d217d4d9SSepherosa Ziehau tbd->tbd_buf[first_idx].tb_dmap = tbd->tbd_buf[last_idx].tb_dmap; 2077d217d4d9SSepherosa Ziehau tbd->tbd_buf[last_idx].tb_dmap = map; 2078d217d4d9SSepherosa Ziehau tbd->tbd_buf[last_idx].tb_mbuf = m; 2079d217d4d9SSepherosa Ziehau 2080d217d4d9SSepherosa Ziehau tbd->tbd_used += ctx.nsegs; 2081d217d4d9SSepherosa Ziehau KKASSERT(tbd->tbd_used <= ET_TX_NDESC); 2082d217d4d9SSepherosa Ziehau 2083d217d4d9SSepherosa Ziehau bus_dmamap_sync(tx_ring->tr_dtag, tx_ring->tr_dmap, 2084d217d4d9SSepherosa Ziehau BUS_DMASYNC_PREWRITE); 2085d217d4d9SSepherosa Ziehau 2086d217d4d9SSepherosa Ziehau tx_ready_pos = __SHIFTIN(tx_ring->tr_ready_index, 2087d217d4d9SSepherosa Ziehau ET_TX_READY_POS_INDEX); 2088d217d4d9SSepherosa Ziehau if (tx_ring->tr_ready_wrap) 2089d217d4d9SSepherosa Ziehau tx_ready_pos |= ET_TX_READY_POS_WRAP; 2090d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_TX_READY_POS, tx_ready_pos); 2091d217d4d9SSepherosa Ziehau 2092d217d4d9SSepherosa Ziehau error = 0; 2093d217d4d9SSepherosa Ziehau back: 2094d217d4d9SSepherosa Ziehau if (error) { 2095d217d4d9SSepherosa Ziehau m_freem(m); 2096d217d4d9SSepherosa Ziehau *m0 = NULL; 2097d217d4d9SSepherosa Ziehau } 2098d217d4d9SSepherosa Ziehau return error; 2099d217d4d9SSepherosa Ziehau } 2100d217d4d9SSepherosa Ziehau 2101d217d4d9SSepherosa Ziehau static void 2102d217d4d9SSepherosa Ziehau et_txeof(struct et_softc *sc) 2103d217d4d9SSepherosa Ziehau { 2104d217d4d9SSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 2105d217d4d9SSepherosa Ziehau struct et_txdesc_ring *tx_ring = &sc->sc_tx_ring; 2106d217d4d9SSepherosa Ziehau struct et_txbuf_data *tbd = &sc->sc_tx_data; 2107d217d4d9SSepherosa Ziehau uint32_t tx_done; 2108d217d4d9SSepherosa Ziehau int end, wrap; 2109d217d4d9SSepherosa Ziehau 21103effc1bfSSepherosa Ziehau if ((sc->sc_flags & ET_FLAG_TXRX_ENABLED) == 0) 211160d2de1fSSepherosa Ziehau return; 211260d2de1fSSepherosa Ziehau 2113d217d4d9SSepherosa Ziehau if (tbd->tbd_used == 0) 2114d217d4d9SSepherosa Ziehau return; 2115d217d4d9SSepherosa Ziehau 2116d217d4d9SSepherosa Ziehau tx_done = CSR_READ_4(sc, ET_TX_DONE_POS); 2117d217d4d9SSepherosa Ziehau end = __SHIFTOUT(tx_done, ET_TX_DONE_POS_INDEX); 2118d217d4d9SSepherosa Ziehau wrap = (tx_done & ET_TX_DONE_POS_WRAP) ? 1 : 0; 2119d217d4d9SSepherosa Ziehau 2120d217d4d9SSepherosa Ziehau while (tbd->tbd_start_index != end || tbd->tbd_start_wrap != wrap) { 2121d217d4d9SSepherosa Ziehau struct et_txbuf *tb; 2122d217d4d9SSepherosa Ziehau 2123d217d4d9SSepherosa Ziehau KKASSERT(tbd->tbd_start_index < ET_TX_NDESC); 2124d217d4d9SSepherosa Ziehau tb = &tbd->tbd_buf[tbd->tbd_start_index]; 2125d217d4d9SSepherosa Ziehau 2126d217d4d9SSepherosa Ziehau bzero(&tx_ring->tr_desc[tbd->tbd_start_index], 2127d217d4d9SSepherosa Ziehau sizeof(struct et_txdesc)); 2128d217d4d9SSepherosa Ziehau bus_dmamap_sync(tx_ring->tr_dtag, tx_ring->tr_dmap, 2129d217d4d9SSepherosa Ziehau BUS_DMASYNC_PREWRITE); 2130d217d4d9SSepherosa Ziehau 2131d217d4d9SSepherosa Ziehau if (tb->tb_mbuf != NULL) { 2132d217d4d9SSepherosa Ziehau bus_dmamap_unload(sc->sc_mbuf_dtag, tb->tb_dmap); 2133d217d4d9SSepherosa Ziehau m_freem(tb->tb_mbuf); 2134d217d4d9SSepherosa Ziehau tb->tb_mbuf = NULL; 21353d60df79SSepherosa Ziehau ifp->if_opackets++; 2136d217d4d9SSepherosa Ziehau } 2137d217d4d9SSepherosa Ziehau 2138d217d4d9SSepherosa Ziehau if (++tbd->tbd_start_index == ET_TX_NDESC) { 2139d217d4d9SSepherosa Ziehau tbd->tbd_start_index = 0; 2140d217d4d9SSepherosa Ziehau tbd->tbd_start_wrap ^= 1; 2141d217d4d9SSepherosa Ziehau } 2142d217d4d9SSepherosa Ziehau 2143d217d4d9SSepherosa Ziehau KKASSERT(tbd->tbd_used > 0); 2144d217d4d9SSepherosa Ziehau tbd->tbd_used--; 2145d217d4d9SSepherosa Ziehau } 2146d217d4d9SSepherosa Ziehau 2147d217d4d9SSepherosa Ziehau if (tbd->tbd_used == 0) 2148d217d4d9SSepherosa Ziehau ifp->if_timer = 0; 2149d217d4d9SSepherosa Ziehau if (tbd->tbd_used + ET_NSEG_SPARE <= ET_TX_NDESC) 2150d217d4d9SSepherosa Ziehau ifp->if_flags &= ~IFF_OACTIVE; 2151d217d4d9SSepherosa Ziehau 21529db4b353SSepherosa Ziehau if_devstart(ifp); 2153d217d4d9SSepherosa Ziehau } 2154d217d4d9SSepherosa Ziehau 2155d217d4d9SSepherosa Ziehau static void 2156d217d4d9SSepherosa Ziehau et_tick(void *xsc) 2157d217d4d9SSepherosa Ziehau { 2158d217d4d9SSepherosa Ziehau struct et_softc *sc = xsc; 2159d217d4d9SSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 216060d2de1fSSepherosa Ziehau struct mii_data *mii = device_get_softc(sc->sc_miibus); 2161d217d4d9SSepherosa Ziehau 2162d217d4d9SSepherosa Ziehau lwkt_serialize_enter(ifp->if_serializer); 2163d217d4d9SSepherosa Ziehau 216460d2de1fSSepherosa Ziehau mii_tick(mii); 21653effc1bfSSepherosa Ziehau if ((sc->sc_flags & ET_FLAG_TXRX_ENABLED) == 0 && 21663effc1bfSSepherosa Ziehau (mii->mii_media_status & IFM_ACTIVE) && 216760d2de1fSSepherosa Ziehau IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) { 216860d2de1fSSepherosa Ziehau if_printf(ifp, "Link up, enable TX/RX\n"); 216960d2de1fSSepherosa Ziehau if (et_enable_txrx(sc, 0) == 0) 21709db4b353SSepherosa Ziehau if_devstart(ifp); 217160d2de1fSSepherosa Ziehau } 2172d217d4d9SSepherosa Ziehau callout_reset(&sc->sc_tick, hz, et_tick, sc); 2173d217d4d9SSepherosa Ziehau 2174d217d4d9SSepherosa Ziehau lwkt_serialize_exit(ifp->if_serializer); 2175d217d4d9SSepherosa Ziehau } 2176d217d4d9SSepherosa Ziehau 2177d217d4d9SSepherosa Ziehau static int 2178d217d4d9SSepherosa Ziehau et_newbuf_cluster(struct et_rxbuf_data *rbd, int buf_idx, int init) 2179d217d4d9SSepherosa Ziehau { 2180d217d4d9SSepherosa Ziehau return et_newbuf(rbd, buf_idx, init, MCLBYTES); 2181d217d4d9SSepherosa Ziehau } 2182d217d4d9SSepherosa Ziehau 2183d217d4d9SSepherosa Ziehau static int 2184d217d4d9SSepherosa Ziehau et_newbuf_hdr(struct et_rxbuf_data *rbd, int buf_idx, int init) 2185d217d4d9SSepherosa Ziehau { 2186d217d4d9SSepherosa Ziehau return et_newbuf(rbd, buf_idx, init, MHLEN); 2187d217d4d9SSepherosa Ziehau } 2188d217d4d9SSepherosa Ziehau 2189d217d4d9SSepherosa Ziehau static int 2190d217d4d9SSepherosa Ziehau et_newbuf(struct et_rxbuf_data *rbd, int buf_idx, int init, int len0) 2191d217d4d9SSepherosa Ziehau { 2192d217d4d9SSepherosa Ziehau struct et_softc *sc = rbd->rbd_softc; 2193d217d4d9SSepherosa Ziehau struct et_rxbuf *rb; 2194d217d4d9SSepherosa Ziehau struct mbuf *m; 2195d217d4d9SSepherosa Ziehau struct et_dmamap_ctx ctx; 2196d217d4d9SSepherosa Ziehau bus_dma_segment_t seg; 2197d217d4d9SSepherosa Ziehau bus_dmamap_t dmap; 2198d217d4d9SSepherosa Ziehau int error, len; 2199d217d4d9SSepherosa Ziehau 22003effc1bfSSepherosa Ziehau KASSERT(!rbd->rbd_jumbo, ("calling %s with jumbo ring\n", __func__)); 22013effc1bfSSepherosa Ziehau 2202d217d4d9SSepherosa Ziehau KKASSERT(buf_idx < ET_RX_NDESC); 2203d217d4d9SSepherosa Ziehau rb = &rbd->rbd_buf[buf_idx]; 2204d217d4d9SSepherosa Ziehau 2205d217d4d9SSepherosa Ziehau m = m_getl(len0, init ? MB_WAIT : MB_DONTWAIT, MT_DATA, M_PKTHDR, &len); 2206d217d4d9SSepherosa Ziehau if (m == NULL) { 2207d217d4d9SSepherosa Ziehau error = ENOBUFS; 2208d217d4d9SSepherosa Ziehau 22090fd7469eSSepherosa Ziehau if (init) { 2210d217d4d9SSepherosa Ziehau if_printf(&sc->arpcom.ac_if, 2211d217d4d9SSepherosa Ziehau "m_getl failed, size %d\n", len0); 2212d217d4d9SSepherosa Ziehau return error; 2213d217d4d9SSepherosa Ziehau } else { 2214d217d4d9SSepherosa Ziehau goto back; 2215d217d4d9SSepherosa Ziehau } 2216d217d4d9SSepherosa Ziehau } 2217d217d4d9SSepherosa Ziehau m->m_len = m->m_pkthdr.len = len; 2218d217d4d9SSepherosa Ziehau 2219d217d4d9SSepherosa Ziehau /* 2220d217d4d9SSepherosa Ziehau * Try load RX mbuf into temporary DMA tag 2221d217d4d9SSepherosa Ziehau */ 2222d217d4d9SSepherosa Ziehau ctx.nsegs = 1; 2223d217d4d9SSepherosa Ziehau ctx.segs = &seg; 2224d217d4d9SSepherosa Ziehau error = bus_dmamap_load_mbuf(sc->sc_mbuf_dtag, sc->sc_mbuf_tmp_dmap, m, 2225d217d4d9SSepherosa Ziehau et_dma_buf_addr, &ctx, 2226d217d4d9SSepherosa Ziehau init ? BUS_DMA_WAITOK : BUS_DMA_NOWAIT); 2227d217d4d9SSepherosa Ziehau if (error || ctx.nsegs == 0) { 2228d217d4d9SSepherosa Ziehau if (!error) { 2229d217d4d9SSepherosa Ziehau bus_dmamap_unload(sc->sc_mbuf_dtag, 2230d217d4d9SSepherosa Ziehau sc->sc_mbuf_tmp_dmap); 2231d217d4d9SSepherosa Ziehau error = EFBIG; 2232d217d4d9SSepherosa Ziehau if_printf(&sc->arpcom.ac_if, "too many segments?!\n"); 2233d217d4d9SSepherosa Ziehau } 2234d217d4d9SSepherosa Ziehau m_freem(m); 2235d217d4d9SSepherosa Ziehau 2236d217d4d9SSepherosa Ziehau if (init) { 22370fd7469eSSepherosa Ziehau if_printf(&sc->arpcom.ac_if, "can't load RX mbuf\n"); 2238d217d4d9SSepherosa Ziehau return error; 2239d217d4d9SSepherosa Ziehau } else { 2240d217d4d9SSepherosa Ziehau goto back; 2241d217d4d9SSepherosa Ziehau } 2242d217d4d9SSepherosa Ziehau } 2243d217d4d9SSepherosa Ziehau 22443effc1bfSSepherosa Ziehau if (!init) { 22453effc1bfSSepherosa Ziehau bus_dmamap_sync(sc->sc_mbuf_dtag, rb->rb_dmap, 22463effc1bfSSepherosa Ziehau BUS_DMASYNC_POSTREAD); 2247d217d4d9SSepherosa Ziehau bus_dmamap_unload(sc->sc_mbuf_dtag, rb->rb_dmap); 22483effc1bfSSepherosa Ziehau } 2249d217d4d9SSepherosa Ziehau rb->rb_mbuf = m; 2250d217d4d9SSepherosa Ziehau rb->rb_paddr = seg.ds_addr; 2251d217d4d9SSepherosa Ziehau 2252d217d4d9SSepherosa Ziehau /* 2253d217d4d9SSepherosa Ziehau * Swap RX buf's DMA map with the loaded temporary one 2254d217d4d9SSepherosa Ziehau */ 2255d217d4d9SSepherosa Ziehau dmap = rb->rb_dmap; 2256d217d4d9SSepherosa Ziehau rb->rb_dmap = sc->sc_mbuf_tmp_dmap; 2257d217d4d9SSepherosa Ziehau sc->sc_mbuf_tmp_dmap = dmap; 2258d217d4d9SSepherosa Ziehau 2259d217d4d9SSepherosa Ziehau error = 0; 2260d217d4d9SSepherosa Ziehau back: 22613effc1bfSSepherosa Ziehau et_setup_rxdesc(rbd, buf_idx, rb->rb_paddr); 2262d217d4d9SSepherosa Ziehau return error; 2263d217d4d9SSepherosa Ziehau } 2264d217d4d9SSepherosa Ziehau 2265d217d4d9SSepherosa Ziehau static int 2266d217d4d9SSepherosa Ziehau et_sysctl_rx_intr_npkts(SYSCTL_HANDLER_ARGS) 2267d217d4d9SSepherosa Ziehau { 2268d217d4d9SSepherosa Ziehau struct et_softc *sc = arg1; 2269d217d4d9SSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 2270d217d4d9SSepherosa Ziehau int error = 0, v; 2271d217d4d9SSepherosa Ziehau 2272d217d4d9SSepherosa Ziehau lwkt_serialize_enter(ifp->if_serializer); 2273d217d4d9SSepherosa Ziehau 2274d217d4d9SSepherosa Ziehau v = sc->sc_rx_intr_npkts; 2275d217d4d9SSepherosa Ziehau error = sysctl_handle_int(oidp, &v, 0, req); 2276d217d4d9SSepherosa Ziehau if (error || req->newptr == NULL) 2277d217d4d9SSepherosa Ziehau goto back; 2278d217d4d9SSepherosa Ziehau if (v <= 0) { 2279d217d4d9SSepherosa Ziehau error = EINVAL; 2280d217d4d9SSepherosa Ziehau goto back; 2281d217d4d9SSepherosa Ziehau } 2282d217d4d9SSepherosa Ziehau 2283d217d4d9SSepherosa Ziehau if (sc->sc_rx_intr_npkts != v) { 2284d217d4d9SSepherosa Ziehau if (ifp->if_flags & IFF_RUNNING) 2285d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_RX_INTR_NPKTS, v); 2286d217d4d9SSepherosa Ziehau sc->sc_rx_intr_npkts = v; 2287d217d4d9SSepherosa Ziehau } 2288d217d4d9SSepherosa Ziehau back: 2289d217d4d9SSepherosa Ziehau lwkt_serialize_exit(ifp->if_serializer); 2290d217d4d9SSepherosa Ziehau return error; 2291d217d4d9SSepherosa Ziehau } 2292d217d4d9SSepherosa Ziehau 2293d217d4d9SSepherosa Ziehau static int 2294d217d4d9SSepherosa Ziehau et_sysctl_rx_intr_delay(SYSCTL_HANDLER_ARGS) 2295d217d4d9SSepherosa Ziehau { 2296d217d4d9SSepherosa Ziehau struct et_softc *sc = arg1; 2297d217d4d9SSepherosa Ziehau struct ifnet *ifp = &sc->arpcom.ac_if; 2298d217d4d9SSepherosa Ziehau int error = 0, v; 2299d217d4d9SSepherosa Ziehau 2300d217d4d9SSepherosa Ziehau lwkt_serialize_enter(ifp->if_serializer); 2301d217d4d9SSepherosa Ziehau 2302d217d4d9SSepherosa Ziehau v = sc->sc_rx_intr_delay; 2303d217d4d9SSepherosa Ziehau error = sysctl_handle_int(oidp, &v, 0, req); 2304d217d4d9SSepherosa Ziehau if (error || req->newptr == NULL) 2305d217d4d9SSepherosa Ziehau goto back; 2306d217d4d9SSepherosa Ziehau if (v <= 0) { 2307d217d4d9SSepherosa Ziehau error = EINVAL; 2308d217d4d9SSepherosa Ziehau goto back; 2309d217d4d9SSepherosa Ziehau } 2310d217d4d9SSepherosa Ziehau 2311d217d4d9SSepherosa Ziehau if (sc->sc_rx_intr_delay != v) { 2312d217d4d9SSepherosa Ziehau if (ifp->if_flags & IFF_RUNNING) 2313d217d4d9SSepherosa Ziehau CSR_WRITE_4(sc, ET_RX_INTR_DELAY, v); 2314d217d4d9SSepherosa Ziehau sc->sc_rx_intr_delay = v; 2315d217d4d9SSepherosa Ziehau } 2316d217d4d9SSepherosa Ziehau back: 2317d217d4d9SSepherosa Ziehau lwkt_serialize_exit(ifp->if_serializer); 2318d217d4d9SSepherosa Ziehau return error; 2319d217d4d9SSepherosa Ziehau } 232060d2de1fSSepherosa Ziehau 232160d2de1fSSepherosa Ziehau static void 232260d2de1fSSepherosa Ziehau et_setmedia(struct et_softc *sc) 232360d2de1fSSepherosa Ziehau { 232460d2de1fSSepherosa Ziehau struct mii_data *mii = device_get_softc(sc->sc_miibus); 232560d2de1fSSepherosa Ziehau uint32_t cfg2, ctrl; 232660d2de1fSSepherosa Ziehau 232760d2de1fSSepherosa Ziehau cfg2 = CSR_READ_4(sc, ET_MAC_CFG2); 232860d2de1fSSepherosa Ziehau cfg2 &= ~(ET_MAC_CFG2_MODE_MII | ET_MAC_CFG2_MODE_GMII | 232960d2de1fSSepherosa Ziehau ET_MAC_CFG2_FDX | ET_MAC_CFG2_BIGFRM); 233060d2de1fSSepherosa Ziehau cfg2 |= ET_MAC_CFG2_LENCHK | ET_MAC_CFG2_CRC | ET_MAC_CFG2_PADCRC | 233160d2de1fSSepherosa Ziehau __SHIFTIN(7, ET_MAC_CFG2_PREAMBLE_LEN); 233260d2de1fSSepherosa Ziehau 233360d2de1fSSepherosa Ziehau ctrl = CSR_READ_4(sc, ET_MAC_CTRL); 233460d2de1fSSepherosa Ziehau ctrl &= ~(ET_MAC_CTRL_GHDX | ET_MAC_CTRL_MODE_MII); 233560d2de1fSSepherosa Ziehau 233660d2de1fSSepherosa Ziehau if (IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_T) { 233760d2de1fSSepherosa Ziehau cfg2 |= ET_MAC_CFG2_MODE_GMII; 233860d2de1fSSepherosa Ziehau } else { 233960d2de1fSSepherosa Ziehau cfg2 |= ET_MAC_CFG2_MODE_MII; 234060d2de1fSSepherosa Ziehau ctrl |= ET_MAC_CTRL_MODE_MII; 234160d2de1fSSepherosa Ziehau } 234260d2de1fSSepherosa Ziehau 234360d2de1fSSepherosa Ziehau if ((mii->mii_media_active & IFM_GMASK) == IFM_FDX) 234460d2de1fSSepherosa Ziehau cfg2 |= ET_MAC_CFG2_FDX; 234560d2de1fSSepherosa Ziehau else 234660d2de1fSSepherosa Ziehau ctrl |= ET_MAC_CTRL_GHDX; 234760d2de1fSSepherosa Ziehau 234860d2de1fSSepherosa Ziehau CSR_WRITE_4(sc, ET_MAC_CTRL, ctrl); 234960d2de1fSSepherosa Ziehau CSR_WRITE_4(sc, ET_MAC_CFG2, cfg2); 235060d2de1fSSepherosa Ziehau } 23513effc1bfSSepherosa Ziehau 23523effc1bfSSepherosa Ziehau static int 23533effc1bfSSepherosa Ziehau et_jumbo_mem_alloc(device_t dev) 23543effc1bfSSepherosa Ziehau { 23553effc1bfSSepherosa Ziehau struct et_softc *sc = device_get_softc(dev); 23563effc1bfSSepherosa Ziehau struct et_jumbo_data *jd = &sc->sc_jumbo_data; 23573effc1bfSSepherosa Ziehau bus_addr_t paddr; 23583effc1bfSSepherosa Ziehau uint8_t *buf; 23593effc1bfSSepherosa Ziehau int error, i; 23603effc1bfSSepherosa Ziehau 23613effc1bfSSepherosa Ziehau error = et_dma_mem_create(dev, ET_JUMBO_MEM_SIZE, &jd->jd_dtag, 23623effc1bfSSepherosa Ziehau &jd->jd_buf, &paddr, &jd->jd_dmap); 23633effc1bfSSepherosa Ziehau if (error) { 23643effc1bfSSepherosa Ziehau device_printf(dev, "can't create jumbo DMA stuffs\n"); 23653effc1bfSSepherosa Ziehau return error; 23663effc1bfSSepherosa Ziehau } 23673effc1bfSSepherosa Ziehau 23683effc1bfSSepherosa Ziehau jd->jd_slots = kmalloc(sizeof(*jd->jd_slots) * ET_JSLOTS, M_DEVBUF, 23693effc1bfSSepherosa Ziehau M_WAITOK | M_ZERO); 23703effc1bfSSepherosa Ziehau lwkt_serialize_init(&jd->jd_serializer); 23713effc1bfSSepherosa Ziehau SLIST_INIT(&jd->jd_free_slots); 23723effc1bfSSepherosa Ziehau 23733effc1bfSSepherosa Ziehau buf = jd->jd_buf; 23743effc1bfSSepherosa Ziehau for (i = 0; i < ET_JSLOTS; ++i) { 23753effc1bfSSepherosa Ziehau struct et_jslot *jslot = &jd->jd_slots[i]; 23763effc1bfSSepherosa Ziehau 23773effc1bfSSepherosa Ziehau jslot->jslot_data = jd; 23783effc1bfSSepherosa Ziehau jslot->jslot_buf = buf; 23793effc1bfSSepherosa Ziehau jslot->jslot_paddr = paddr; 23803effc1bfSSepherosa Ziehau jslot->jslot_inuse = 0; 23813effc1bfSSepherosa Ziehau jslot->jslot_index = i; 23823effc1bfSSepherosa Ziehau SLIST_INSERT_HEAD(&jd->jd_free_slots, jslot, jslot_link); 23833effc1bfSSepherosa Ziehau 23843effc1bfSSepherosa Ziehau buf += ET_JLEN; 23853effc1bfSSepherosa Ziehau paddr += ET_JLEN; 23863effc1bfSSepherosa Ziehau } 23873effc1bfSSepherosa Ziehau return 0; 23883effc1bfSSepherosa Ziehau } 23893effc1bfSSepherosa Ziehau 23903effc1bfSSepherosa Ziehau static void 23913effc1bfSSepherosa Ziehau et_jumbo_mem_free(device_t dev) 23923effc1bfSSepherosa Ziehau { 23933effc1bfSSepherosa Ziehau struct et_softc *sc = device_get_softc(dev); 23943effc1bfSSepherosa Ziehau struct et_jumbo_data *jd = &sc->sc_jumbo_data; 23953effc1bfSSepherosa Ziehau 23963effc1bfSSepherosa Ziehau KKASSERT(sc->sc_flags & ET_FLAG_JUMBO); 23973effc1bfSSepherosa Ziehau 23983effc1bfSSepherosa Ziehau kfree(jd->jd_slots, M_DEVBUF); 23993effc1bfSSepherosa Ziehau et_dma_mem_destroy(jd->jd_dtag, jd->jd_buf, jd->jd_dmap); 24003effc1bfSSepherosa Ziehau } 24013effc1bfSSepherosa Ziehau 24023effc1bfSSepherosa Ziehau static struct et_jslot * 24033effc1bfSSepherosa Ziehau et_jalloc(struct et_jumbo_data *jd) 24043effc1bfSSepherosa Ziehau { 24053effc1bfSSepherosa Ziehau struct et_jslot *jslot; 24063effc1bfSSepherosa Ziehau 24073effc1bfSSepherosa Ziehau lwkt_serialize_enter(&jd->jd_serializer); 24083effc1bfSSepherosa Ziehau 24093effc1bfSSepherosa Ziehau jslot = SLIST_FIRST(&jd->jd_free_slots); 24103effc1bfSSepherosa Ziehau if (jslot) { 24113effc1bfSSepherosa Ziehau SLIST_REMOVE_HEAD(&jd->jd_free_slots, jslot_link); 24123effc1bfSSepherosa Ziehau jslot->jslot_inuse = 1; 24133effc1bfSSepherosa Ziehau } 24143effc1bfSSepherosa Ziehau 24153effc1bfSSepherosa Ziehau lwkt_serialize_exit(&jd->jd_serializer); 24163effc1bfSSepherosa Ziehau return jslot; 24173effc1bfSSepherosa Ziehau } 24183effc1bfSSepherosa Ziehau 24193effc1bfSSepherosa Ziehau static void 24203effc1bfSSepherosa Ziehau et_jfree(void *xjslot) 24213effc1bfSSepherosa Ziehau { 24223effc1bfSSepherosa Ziehau struct et_jslot *jslot = xjslot; 24233effc1bfSSepherosa Ziehau struct et_jumbo_data *jd = jslot->jslot_data; 24243effc1bfSSepherosa Ziehau 24253effc1bfSSepherosa Ziehau if (&jd->jd_slots[jslot->jslot_index] != jslot) { 24263effc1bfSSepherosa Ziehau panic("%s wrong jslot!?\n", __func__); 24273effc1bfSSepherosa Ziehau } else if (jslot->jslot_inuse == 0) { 24283effc1bfSSepherosa Ziehau panic("%s jslot already freed\n", __func__); 24293effc1bfSSepherosa Ziehau } else { 24303effc1bfSSepherosa Ziehau lwkt_serialize_enter(&jd->jd_serializer); 24313effc1bfSSepherosa Ziehau 24323effc1bfSSepherosa Ziehau atomic_subtract_int(&jslot->jslot_inuse, 1); 24333effc1bfSSepherosa Ziehau if (jslot->jslot_inuse == 0) { 24343effc1bfSSepherosa Ziehau SLIST_INSERT_HEAD(&jd->jd_free_slots, jslot, 24353effc1bfSSepherosa Ziehau jslot_link); 24363effc1bfSSepherosa Ziehau } 24373effc1bfSSepherosa Ziehau 24383effc1bfSSepherosa Ziehau lwkt_serialize_exit(&jd->jd_serializer); 24393effc1bfSSepherosa Ziehau } 24403effc1bfSSepherosa Ziehau } 24413effc1bfSSepherosa Ziehau 24423effc1bfSSepherosa Ziehau static void 24433effc1bfSSepherosa Ziehau et_jref(void *xjslot) 24443effc1bfSSepherosa Ziehau { 24453effc1bfSSepherosa Ziehau struct et_jslot *jslot = xjslot; 24463effc1bfSSepherosa Ziehau struct et_jumbo_data *jd = jslot->jslot_data; 24473effc1bfSSepherosa Ziehau 24483effc1bfSSepherosa Ziehau if (&jd->jd_slots[jslot->jslot_index] != jslot) 24493effc1bfSSepherosa Ziehau panic("%s wrong jslot!?\n", __func__); 24503effc1bfSSepherosa Ziehau else if (jslot->jslot_inuse == 0) 24513effc1bfSSepherosa Ziehau panic("%s jslot already freed\n", __func__); 24523effc1bfSSepherosa Ziehau else 24533effc1bfSSepherosa Ziehau atomic_add_int(&jslot->jslot_inuse, 1); 24543effc1bfSSepherosa Ziehau } 24553effc1bfSSepherosa Ziehau 24563effc1bfSSepherosa Ziehau static int 24573effc1bfSSepherosa Ziehau et_newbuf_jumbo(struct et_rxbuf_data *rbd, int buf_idx, int init) 24583effc1bfSSepherosa Ziehau { 24593effc1bfSSepherosa Ziehau struct et_softc *sc = rbd->rbd_softc; 24603effc1bfSSepherosa Ziehau struct et_rxbuf *rb; 24613effc1bfSSepherosa Ziehau struct mbuf *m; 24623effc1bfSSepherosa Ziehau struct et_jslot *jslot; 24633effc1bfSSepherosa Ziehau int error; 24643effc1bfSSepherosa Ziehau 24653effc1bfSSepherosa Ziehau KASSERT(rbd->rbd_jumbo, ("calling %s with non-jumbo ring\n", __func__)); 24663effc1bfSSepherosa Ziehau 24673effc1bfSSepherosa Ziehau KKASSERT(buf_idx < ET_RX_NDESC); 24683effc1bfSSepherosa Ziehau rb = &rbd->rbd_buf[buf_idx]; 24693effc1bfSSepherosa Ziehau 24703effc1bfSSepherosa Ziehau error = ENOBUFS; 24713effc1bfSSepherosa Ziehau 24723effc1bfSSepherosa Ziehau MGETHDR(m, init ? MB_WAIT : MB_DONTWAIT, MT_DATA); 24733effc1bfSSepherosa Ziehau if (m == NULL) { 24743effc1bfSSepherosa Ziehau if (init) { 24753effc1bfSSepherosa Ziehau if_printf(&sc->arpcom.ac_if, "MGETHDR failed\n"); 24763effc1bfSSepherosa Ziehau return error; 24773effc1bfSSepherosa Ziehau } else { 24783effc1bfSSepherosa Ziehau goto back; 24793effc1bfSSepherosa Ziehau } 24803effc1bfSSepherosa Ziehau } 24813effc1bfSSepherosa Ziehau 24823effc1bfSSepherosa Ziehau jslot = et_jalloc(&sc->sc_jumbo_data); 24833effc1bfSSepherosa Ziehau if (jslot == NULL) { 24843effc1bfSSepherosa Ziehau m_freem(m); 24853effc1bfSSepherosa Ziehau 24863effc1bfSSepherosa Ziehau if (init) { 24873effc1bfSSepherosa Ziehau if_printf(&sc->arpcom.ac_if, 24883effc1bfSSepherosa Ziehau "jslot allocation failed\n"); 24893effc1bfSSepherosa Ziehau return error; 24903effc1bfSSepherosa Ziehau } else { 24913effc1bfSSepherosa Ziehau goto back; 24923effc1bfSSepherosa Ziehau } 24933effc1bfSSepherosa Ziehau } 24943effc1bfSSepherosa Ziehau 24953effc1bfSSepherosa Ziehau m->m_ext.ext_arg = jslot; 24963effc1bfSSepherosa Ziehau m->m_ext.ext_buf = jslot->jslot_buf; 24973effc1bfSSepherosa Ziehau m->m_ext.ext_free = et_jfree; 24983effc1bfSSepherosa Ziehau m->m_ext.ext_ref = et_jref; 24993effc1bfSSepherosa Ziehau m->m_ext.ext_size = ET_JUMBO_FRAMELEN; 25003effc1bfSSepherosa Ziehau m->m_flags |= M_EXT; 25013effc1bfSSepherosa Ziehau m->m_data = m->m_ext.ext_buf; 25023effc1bfSSepherosa Ziehau m->m_len = m->m_pkthdr.len = m->m_ext.ext_size; 25033effc1bfSSepherosa Ziehau 25043effc1bfSSepherosa Ziehau rb->rb_mbuf = m; 25053effc1bfSSepherosa Ziehau rb->rb_paddr = jslot->jslot_paddr; 25063effc1bfSSepherosa Ziehau 25073effc1bfSSepherosa Ziehau error = 0; 25083effc1bfSSepherosa Ziehau back: 25093effc1bfSSepherosa Ziehau et_setup_rxdesc(rbd, buf_idx, rb->rb_paddr); 25103effc1bfSSepherosa Ziehau return error; 25113effc1bfSSepherosa Ziehau } 25123effc1bfSSepherosa Ziehau 25133effc1bfSSepherosa Ziehau static void 25143effc1bfSSepherosa Ziehau et_setup_rxdesc(struct et_rxbuf_data *rbd, int buf_idx, bus_addr_t paddr) 25153effc1bfSSepherosa Ziehau { 25163effc1bfSSepherosa Ziehau struct et_rxdesc_ring *rx_ring = rbd->rbd_ring; 25173effc1bfSSepherosa Ziehau struct et_rxdesc *desc; 25183effc1bfSSepherosa Ziehau 25193effc1bfSSepherosa Ziehau KKASSERT(buf_idx < ET_RX_NDESC); 25203effc1bfSSepherosa Ziehau desc = &rx_ring->rr_desc[buf_idx]; 25213effc1bfSSepherosa Ziehau 25223effc1bfSSepherosa Ziehau desc->rd_addr_hi = ET_ADDR_HI(paddr); 25233effc1bfSSepherosa Ziehau desc->rd_addr_lo = ET_ADDR_LO(paddr); 25243effc1bfSSepherosa Ziehau desc->rd_ctrl = __SHIFTIN(buf_idx, ET_RDCTRL_BUFIDX); 25253effc1bfSSepherosa Ziehau 25263effc1bfSSepherosa Ziehau bus_dmamap_sync(rx_ring->rr_dtag, rx_ring->rr_dmap, 25273effc1bfSSepherosa Ziehau BUS_DMASYNC_PREWRITE); 25283effc1bfSSepherosa Ziehau } 2529