if_et.c revision 219902
1179895Sdelphij/*- 2210661Sdelphij * Copyright (c) 2007 Sepherosa Ziehau. All rights reserved. 3179895Sdelphij * 4179895Sdelphij * This code is derived from software contributed to The DragonFly Project 5179895Sdelphij * by Sepherosa Ziehau <sepherosa@gmail.com> 6179895Sdelphij * 7179895Sdelphij * Redistribution and use in source and binary forms, with or without 8179895Sdelphij * modification, are permitted provided that the following conditions 9179895Sdelphij * are met: 10179895Sdelphij * 11179895Sdelphij * 1. Redistributions of source code must retain the above copyright 12179895Sdelphij * notice, this list of conditions and the following disclaimer. 13179895Sdelphij * 2. Redistributions in binary form must reproduce the above copyright 14179895Sdelphij * notice, this list of conditions and the following disclaimer in 15179895Sdelphij * the documentation and/or other materials provided with the 16179895Sdelphij * distribution. 17179895Sdelphij * 3. Neither the name of The DragonFly Project nor the names of its 18179895Sdelphij * contributors may be used to endorse or promote products derived 19179895Sdelphij * from this software without specific, prior written permission. 20179895Sdelphij * 21179895Sdelphij * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22179895Sdelphij * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23179895Sdelphij * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24179895Sdelphij * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25179895Sdelphij * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26179895Sdelphij * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 27179895Sdelphij * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28179895Sdelphij * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 29179895Sdelphij * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30179895Sdelphij * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 31179895Sdelphij * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32179895Sdelphij * SUCH DAMAGE. 33179895Sdelphij * 34179895Sdelphij * $DragonFly: src/sys/dev/netif/et/if_et.c,v 1.10 2008/05/18 07:47:14 sephe Exp $ 35179895Sdelphij */ 36179895Sdelphij 37199612Syongari#include <sys/cdefs.h> 38199612Syongari__FBSDID("$FreeBSD: head/sys/dev/et/if_et.c 219902 2011-03-23 13:10:15Z jhb $"); 39199612Syongari 40179895Sdelphij#include <sys/param.h> 41179895Sdelphij#include <sys/systm.h> 42179895Sdelphij#include <sys/endian.h> 43179895Sdelphij#include <sys/kernel.h> 44179895Sdelphij#include <sys/bus.h> 45179895Sdelphij#include <sys/malloc.h> 46179895Sdelphij#include <sys/mbuf.h> 47179895Sdelphij#include <sys/proc.h> 48179895Sdelphij#include <sys/rman.h> 49179895Sdelphij#include <sys/module.h> 50179895Sdelphij#include <sys/socket.h> 51179895Sdelphij#include <sys/sockio.h> 52179895Sdelphij#include <sys/sysctl.h> 53179895Sdelphij 54179895Sdelphij#include <net/ethernet.h> 55179895Sdelphij#include <net/if.h> 56179895Sdelphij#include <net/if_dl.h> 57179895Sdelphij#include <net/if_types.h> 58179895Sdelphij#include <net/bpf.h> 59179895Sdelphij#include <net/if_arp.h> 60179895Sdelphij#include <net/if_dl.h> 61179895Sdelphij#include <net/if_media.h> 62179895Sdelphij#include <net/if_vlan_var.h> 63179895Sdelphij 64179895Sdelphij#include <machine/bus.h> 65179895Sdelphij 66213894Smarius#include <dev/mii/mii.h> 67179895Sdelphij#include <dev/mii/miivar.h> 68179895Sdelphij 69179895Sdelphij#include <dev/pci/pcireg.h> 70179895Sdelphij#include <dev/pci/pcivar.h> 71179895Sdelphij 72179895Sdelphij#include <dev/et/if_etreg.h> 73179895Sdelphij#include <dev/et/if_etvar.h> 74179895Sdelphij 75179895Sdelphij#include "miibus_if.h" 76179895Sdelphij 77179895SdelphijMODULE_DEPEND(et, pci, 1, 1, 1); 78179895SdelphijMODULE_DEPEND(et, ether, 1, 1, 1); 79179895SdelphijMODULE_DEPEND(et, miibus, 1, 1, 1); 80179895Sdelphij 81199552Syongari/* Tunables. */ 82199552Syongaristatic int msi_disable = 0; 83199563SyongariTUNABLE_INT("hw.et.msi_disable", &msi_disable); 84199552Syongari 85199611Syongari#define ET_CSUM_FEATURES (CSUM_IP | CSUM_TCP | CSUM_UDP) 86199611Syongari 87179895Sdelphijstatic int et_probe(device_t); 88179895Sdelphijstatic int et_attach(device_t); 89179895Sdelphijstatic int et_detach(device_t); 90179895Sdelphijstatic int et_shutdown(device_t); 91179895Sdelphij 92179895Sdelphijstatic int et_miibus_readreg(device_t, int, int); 93179895Sdelphijstatic int et_miibus_writereg(device_t, int, int, int); 94179895Sdelphijstatic void et_miibus_statchg(device_t); 95179895Sdelphij 96179895Sdelphijstatic void et_init_locked(struct et_softc *); 97179895Sdelphijstatic void et_init(void *); 98179895Sdelphijstatic int et_ioctl(struct ifnet *, u_long, caddr_t); 99179895Sdelphijstatic void et_start_locked(struct ifnet *); 100179895Sdelphijstatic void et_start(struct ifnet *); 101179895Sdelphijstatic void et_watchdog(struct et_softc *); 102179895Sdelphijstatic int et_ifmedia_upd_locked(struct ifnet *); 103179895Sdelphijstatic int et_ifmedia_upd(struct ifnet *); 104179895Sdelphijstatic void et_ifmedia_sts(struct ifnet *, struct ifmediareq *); 105179895Sdelphij 106179895Sdelphijstatic void et_add_sysctls(struct et_softc *); 107179895Sdelphijstatic int et_sysctl_rx_intr_npkts(SYSCTL_HANDLER_ARGS); 108179895Sdelphijstatic int et_sysctl_rx_intr_delay(SYSCTL_HANDLER_ARGS); 109179895Sdelphij 110179895Sdelphijstatic void et_intr(void *); 111179895Sdelphijstatic void et_enable_intrs(struct et_softc *, uint32_t); 112179895Sdelphijstatic void et_disable_intrs(struct et_softc *); 113179895Sdelphijstatic void et_rxeof(struct et_softc *); 114179895Sdelphijstatic void et_txeof(struct et_softc *); 115179895Sdelphij 116179895Sdelphijstatic int et_dma_alloc(device_t); 117179895Sdelphijstatic void et_dma_free(device_t); 118179895Sdelphijstatic int et_dma_mem_create(device_t, bus_size_t, bus_dma_tag_t *, 119179895Sdelphij void **, bus_addr_t *, bus_dmamap_t *); 120179895Sdelphijstatic void et_dma_mem_destroy(bus_dma_tag_t, void *, bus_dmamap_t); 121179895Sdelphijstatic int et_dma_mbuf_create(device_t); 122179895Sdelphijstatic void et_dma_mbuf_destroy(device_t, int, const int[]); 123179895Sdelphijstatic void et_dma_ring_addr(void *, bus_dma_segment_t *, int, int); 124179895Sdelphijstatic void et_dma_buf_addr(void *, bus_dma_segment_t *, int, 125179895Sdelphij bus_size_t, int); 126179895Sdelphijstatic int et_init_tx_ring(struct et_softc *); 127179895Sdelphijstatic int et_init_rx_ring(struct et_softc *); 128179895Sdelphijstatic void et_free_tx_ring(struct et_softc *); 129179895Sdelphijstatic void et_free_rx_ring(struct et_softc *); 130179895Sdelphijstatic int et_encap(struct et_softc *, struct mbuf **); 131179895Sdelphijstatic int et_newbuf(struct et_rxbuf_data *, int, int, int); 132179895Sdelphijstatic int et_newbuf_cluster(struct et_rxbuf_data *, int, int); 133179895Sdelphijstatic int et_newbuf_hdr(struct et_rxbuf_data *, int, int); 134179895Sdelphij 135179895Sdelphijstatic void et_stop(struct et_softc *); 136179895Sdelphijstatic int et_chip_init(struct et_softc *); 137179895Sdelphijstatic void et_chip_attach(struct et_softc *); 138179895Sdelphijstatic void et_init_mac(struct et_softc *); 139179895Sdelphijstatic void et_init_rxmac(struct et_softc *); 140179895Sdelphijstatic void et_init_txmac(struct et_softc *); 141179895Sdelphijstatic int et_init_rxdma(struct et_softc *); 142179895Sdelphijstatic int et_init_txdma(struct et_softc *); 143179895Sdelphijstatic int et_start_rxdma(struct et_softc *); 144179895Sdelphijstatic int et_start_txdma(struct et_softc *); 145179895Sdelphijstatic int et_stop_rxdma(struct et_softc *); 146179895Sdelphijstatic int et_stop_txdma(struct et_softc *); 147179895Sdelphijstatic int et_enable_txrx(struct et_softc *, int); 148179895Sdelphijstatic void et_reset(struct et_softc *); 149199561Syongaristatic int et_bus_config(struct et_softc *); 150179895Sdelphijstatic void et_get_eaddr(device_t, uint8_t[]); 151179895Sdelphijstatic void et_setmulti(struct et_softc *); 152179895Sdelphijstatic void et_tick(void *); 153179895Sdelphijstatic void et_setmedia(struct et_softc *); 154179895Sdelphijstatic void et_setup_rxdesc(struct et_rxbuf_data *, int, bus_addr_t); 155179895Sdelphij 156179895Sdelphijstatic const struct et_dev { 157179895Sdelphij uint16_t vid; 158179895Sdelphij uint16_t did; 159179895Sdelphij const char *desc; 160179895Sdelphij} et_devices[] = { 161179895Sdelphij { PCI_VENDOR_LUCENT, PCI_PRODUCT_LUCENT_ET1310, 162179895Sdelphij "Agere ET1310 Gigabit Ethernet" }, 163179895Sdelphij { PCI_VENDOR_LUCENT, PCI_PRODUCT_LUCENT_ET1310_FAST, 164179895Sdelphij "Agere ET1310 Fast Ethernet" }, 165179895Sdelphij { 0, 0, NULL } 166179895Sdelphij}; 167179895Sdelphij 168179895Sdelphijstatic device_method_t et_methods[] = { 169179895Sdelphij DEVMETHOD(device_probe, et_probe), 170179895Sdelphij DEVMETHOD(device_attach, et_attach), 171179895Sdelphij DEVMETHOD(device_detach, et_detach), 172179895Sdelphij DEVMETHOD(device_shutdown, et_shutdown), 173179895Sdelphij 174179895Sdelphij DEVMETHOD(bus_print_child, bus_generic_print_child), 175179895Sdelphij DEVMETHOD(bus_driver_added, bus_generic_driver_added), 176179895Sdelphij 177179895Sdelphij DEVMETHOD(miibus_readreg, et_miibus_readreg), 178179895Sdelphij DEVMETHOD(miibus_writereg, et_miibus_writereg), 179179895Sdelphij DEVMETHOD(miibus_statchg, et_miibus_statchg), 180179895Sdelphij 181179895Sdelphij { 0, 0 } 182179895Sdelphij}; 183179895Sdelphij 184179895Sdelphijstatic driver_t et_driver = { 185179895Sdelphij "et", 186179895Sdelphij et_methods, 187179895Sdelphij sizeof(struct et_softc) 188179895Sdelphij}; 189179895Sdelphij 190179895Sdelphijstatic devclass_t et_devclass; 191179895Sdelphij 192179895SdelphijDRIVER_MODULE(et, pci, et_driver, et_devclass, 0, 0); 193179895SdelphijDRIVER_MODULE(miibus, et, miibus_driver, miibus_devclass, 0, 0); 194179895Sdelphij 195179895Sdelphijstatic int et_rx_intr_npkts = 32; 196179895Sdelphijstatic int et_rx_intr_delay = 20; /* x10 usec */ 197179895Sdelphijstatic int et_tx_intr_nsegs = 126; 198179895Sdelphijstatic uint32_t et_timer = 1000 * 1000 * 1000; /* nanosec */ 199179895Sdelphij 200179895SdelphijTUNABLE_INT("hw.et.timer", &et_timer); 201179895SdelphijTUNABLE_INT("hw.et.rx_intr_npkts", &et_rx_intr_npkts); 202179895SdelphijTUNABLE_INT("hw.et.rx_intr_delay", &et_rx_intr_delay); 203179895SdelphijTUNABLE_INT("hw.et.tx_intr_nsegs", &et_tx_intr_nsegs); 204179895Sdelphij 205179895Sdelphijstruct et_bsize { 206179895Sdelphij int bufsize; 207179895Sdelphij et_newbuf_t newbuf; 208179895Sdelphij}; 209179895Sdelphij 210179895Sdelphijstatic const struct et_bsize et_bufsize_std[ET_RX_NRING] = { 211179895Sdelphij { .bufsize = ET_RXDMA_CTRL_RING0_128, 212179895Sdelphij .newbuf = et_newbuf_hdr }, 213179895Sdelphij { .bufsize = ET_RXDMA_CTRL_RING1_2048, 214179895Sdelphij .newbuf = et_newbuf_cluster }, 215179895Sdelphij}; 216179895Sdelphij 217179895Sdelphijstatic int 218179895Sdelphijet_probe(device_t dev) 219179895Sdelphij{ 220179895Sdelphij const struct et_dev *d; 221179895Sdelphij uint16_t did, vid; 222179895Sdelphij 223179895Sdelphij vid = pci_get_vendor(dev); 224179895Sdelphij did = pci_get_device(dev); 225179895Sdelphij 226179895Sdelphij for (d = et_devices; d->desc != NULL; ++d) { 227179895Sdelphij if (vid == d->vid && did == d->did) { 228179895Sdelphij device_set_desc(dev, d->desc); 229199556Syongari return (0); 230179895Sdelphij } 231179895Sdelphij } 232199556Syongari return (ENXIO); 233179895Sdelphij} 234179895Sdelphij 235179895Sdelphijstatic int 236179895Sdelphijet_attach(device_t dev) 237179895Sdelphij{ 238179895Sdelphij struct et_softc *sc; 239179895Sdelphij struct ifnet *ifp; 240179895Sdelphij uint8_t eaddr[ETHER_ADDR_LEN]; 241199552Syongari int cap, error, msic; 242179895Sdelphij 243179895Sdelphij sc = device_get_softc(dev); 244179895Sdelphij sc->dev = dev; 245179895Sdelphij mtx_init(&sc->sc_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK, 246179895Sdelphij MTX_DEF); 247179895Sdelphij 248179895Sdelphij ifp = sc->ifp = if_alloc(IFT_ETHER); 249179895Sdelphij if (ifp == NULL) { 250179895Sdelphij device_printf(dev, "can not if_alloc()\n"); 251179895Sdelphij error = ENOSPC; 252179895Sdelphij goto fail; 253179895Sdelphij } 254179895Sdelphij 255179895Sdelphij /* 256179895Sdelphij * Initialize tunables 257179895Sdelphij */ 258179895Sdelphij sc->sc_rx_intr_npkts = et_rx_intr_npkts; 259179895Sdelphij sc->sc_rx_intr_delay = et_rx_intr_delay; 260179895Sdelphij sc->sc_tx_intr_nsegs = et_tx_intr_nsegs; 261179895Sdelphij sc->sc_timer = et_timer; 262179895Sdelphij 263179895Sdelphij /* Enable bus mastering */ 264179895Sdelphij pci_enable_busmaster(dev); 265179895Sdelphij 266179895Sdelphij /* 267179895Sdelphij * Allocate IO memory 268179895Sdelphij */ 269179895Sdelphij sc->sc_mem_rid = ET_PCIR_BAR; 270179895Sdelphij sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 271179895Sdelphij &sc->sc_mem_rid, RF_ACTIVE); 272179895Sdelphij if (sc->sc_mem_res == NULL) { 273179895Sdelphij device_printf(dev, "can't allocate IO memory\n"); 274199556Syongari return (ENXIO); 275179895Sdelphij } 276179895Sdelphij 277199552Syongari msic = 0; 278219902Sjhb if (pci_find_cap(dev, PCIY_EXPRESS, &cap) == 0) { 279199552Syongari sc->sc_expcap = cap; 280199552Syongari sc->sc_flags |= ET_FLAG_PCIE; 281199552Syongari msic = pci_msi_count(dev); 282199552Syongari if (bootverbose) 283199563Syongari device_printf(dev, "MSI count: %d\n", msic); 284199552Syongari } 285199552Syongari if (msic > 0 && msi_disable == 0) { 286199552Syongari msic = 1; 287199552Syongari if (pci_alloc_msi(dev, &msic) == 0) { 288199552Syongari if (msic == 1) { 289199552Syongari device_printf(dev, "Using %d MSI message\n", 290199552Syongari msic); 291199552Syongari sc->sc_flags |= ET_FLAG_MSI; 292199552Syongari } else 293199552Syongari pci_release_msi(dev); 294199552Syongari } 295199552Syongari } 296199552Syongari 297179895Sdelphij /* 298179895Sdelphij * Allocate IRQ 299179895Sdelphij */ 300199552Syongari if ((sc->sc_flags & ET_FLAG_MSI) == 0) { 301199552Syongari sc->sc_irq_rid = 0; 302199552Syongari sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, 303199552Syongari &sc->sc_irq_rid, RF_SHAREABLE | RF_ACTIVE); 304199552Syongari } else { 305199552Syongari sc->sc_irq_rid = 1; 306199552Syongari sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, 307199552Syongari &sc->sc_irq_rid, RF_ACTIVE); 308199552Syongari } 309179895Sdelphij if (sc->sc_irq_res == NULL) { 310179895Sdelphij device_printf(dev, "can't allocate irq\n"); 311179895Sdelphij error = ENXIO; 312179895Sdelphij goto fail; 313179895Sdelphij } 314179895Sdelphij 315199561Syongari error = et_bus_config(sc); 316179895Sdelphij if (error) 317179895Sdelphij goto fail; 318179895Sdelphij 319179895Sdelphij et_get_eaddr(dev, eaddr); 320179895Sdelphij 321179895Sdelphij CSR_WRITE_4(sc, ET_PM, 322179895Sdelphij ET_PM_SYSCLK_GATE | ET_PM_TXCLK_GATE | ET_PM_RXCLK_GATE); 323179895Sdelphij 324179895Sdelphij et_reset(sc); 325179895Sdelphij 326179895Sdelphij et_disable_intrs(sc); 327179895Sdelphij 328179895Sdelphij error = et_dma_alloc(dev); 329179895Sdelphij if (error) 330179895Sdelphij goto fail; 331179895Sdelphij 332179895Sdelphij ifp->if_softc = sc; 333179895Sdelphij if_initname(ifp, device_get_name(dev), device_get_unit(dev)); 334179895Sdelphij ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 335179895Sdelphij ifp->if_init = et_init; 336179895Sdelphij ifp->if_ioctl = et_ioctl; 337179895Sdelphij ifp->if_start = et_start; 338179895Sdelphij ifp->if_mtu = ETHERMTU; 339199613Syongari ifp->if_capabilities = IFCAP_TXCSUM | IFCAP_VLAN_MTU; 340179895Sdelphij ifp->if_capenable = ifp->if_capabilities; 341179895Sdelphij IFQ_SET_MAXLEN(&ifp->if_snd, ET_TX_NDESC); 342179895Sdelphij IFQ_SET_READY(&ifp->if_snd); 343179895Sdelphij 344179895Sdelphij et_chip_attach(sc); 345179895Sdelphij 346213894Smarius error = mii_attach(dev, &sc->sc_miibus, ifp, et_ifmedia_upd, 347213894Smarius et_ifmedia_sts, BMSR_DEFCAPMASK, MII_PHY_ANY, MII_OFFSET_ANY, 0); 348179895Sdelphij if (error) { 349213894Smarius device_printf(dev, "attaching PHYs failed\n"); 350179895Sdelphij goto fail; 351179895Sdelphij } 352179895Sdelphij 353179895Sdelphij ether_ifattach(ifp, eaddr); 354179895Sdelphij callout_init_mtx(&sc->sc_tick, &sc->sc_mtx, 0); 355179895Sdelphij 356179895Sdelphij error = bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_NET | INTR_MPSAFE, 357199552Syongari NULL, et_intr, sc, &sc->sc_irq_handle); 358179895Sdelphij if (error) { 359179895Sdelphij ether_ifdetach(ifp); 360179895Sdelphij device_printf(dev, "can't setup intr\n"); 361179895Sdelphij goto fail; 362179895Sdelphij } 363179895Sdelphij 364179895Sdelphij et_add_sysctls(sc); 365179895Sdelphij 366199556Syongari return (0); 367179895Sdelphijfail: 368179895Sdelphij et_detach(dev); 369199556Syongari return (error); 370179895Sdelphij} 371179895Sdelphij 372179895Sdelphijstatic int 373179895Sdelphijet_detach(device_t dev) 374179895Sdelphij{ 375179895Sdelphij struct et_softc *sc = device_get_softc(dev); 376179895Sdelphij 377179895Sdelphij if (device_is_attached(dev)) { 378179895Sdelphij struct ifnet *ifp = sc->ifp; 379179895Sdelphij 380179895Sdelphij ET_LOCK(sc); 381179895Sdelphij et_stop(sc); 382179895Sdelphij bus_teardown_intr(dev, sc->sc_irq_res, sc->sc_irq_handle); 383179895Sdelphij ET_UNLOCK(sc); 384179895Sdelphij 385179895Sdelphij ether_ifdetach(ifp); 386179895Sdelphij } 387179895Sdelphij 388179895Sdelphij if (sc->sc_miibus != NULL) 389179895Sdelphij device_delete_child(dev, sc->sc_miibus); 390179895Sdelphij bus_generic_detach(dev); 391179895Sdelphij 392179895Sdelphij if (sc->sc_irq_res != NULL) { 393179895Sdelphij bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irq_rid, 394179895Sdelphij sc->sc_irq_res); 395179895Sdelphij } 396199552Syongari if ((sc->sc_flags & ET_FLAG_MSI) != 0) 397199552Syongari pci_release_msi(dev); 398179895Sdelphij 399179895Sdelphij if (sc->sc_mem_res != NULL) { 400179895Sdelphij bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_mem_rid, 401179895Sdelphij sc->sc_mem_res); 402179895Sdelphij } 403179895Sdelphij 404179895Sdelphij if (sc->ifp != NULL) 405179895Sdelphij if_free(sc->ifp); 406179895Sdelphij 407179895Sdelphij et_dma_free(dev); 408179895Sdelphij 409199551Syongari mtx_destroy(&sc->sc_mtx); 410199551Syongari 411199556Syongari return (0); 412179895Sdelphij} 413179895Sdelphij 414179895Sdelphijstatic int 415179895Sdelphijet_shutdown(device_t dev) 416179895Sdelphij{ 417179895Sdelphij struct et_softc *sc = device_get_softc(dev); 418179895Sdelphij 419179895Sdelphij ET_LOCK(sc); 420179895Sdelphij et_stop(sc); 421179895Sdelphij ET_UNLOCK(sc); 422199556Syongari return (0); 423179895Sdelphij} 424179895Sdelphij 425179895Sdelphijstatic int 426179895Sdelphijet_miibus_readreg(device_t dev, int phy, int reg) 427179895Sdelphij{ 428179895Sdelphij struct et_softc *sc = device_get_softc(dev); 429179895Sdelphij uint32_t val; 430179895Sdelphij int i, ret; 431179895Sdelphij 432179895Sdelphij /* Stop any pending operations */ 433179895Sdelphij CSR_WRITE_4(sc, ET_MII_CMD, 0); 434179895Sdelphij 435199548Syongari val = (phy << ET_MII_ADDR_PHY_SHIFT) & ET_MII_ADDR_PHY_MASK; 436199548Syongari val |= (reg << ET_MII_ADDR_REG_SHIFT) & ET_MII_ADDR_REG_MASK; 437179895Sdelphij CSR_WRITE_4(sc, ET_MII_ADDR, val); 438179895Sdelphij 439179895Sdelphij /* Start reading */ 440179895Sdelphij CSR_WRITE_4(sc, ET_MII_CMD, ET_MII_CMD_READ); 441179895Sdelphij 442179895Sdelphij#define NRETRY 50 443179895Sdelphij 444179895Sdelphij for (i = 0; i < NRETRY; ++i) { 445179895Sdelphij val = CSR_READ_4(sc, ET_MII_IND); 446179895Sdelphij if ((val & (ET_MII_IND_BUSY | ET_MII_IND_INVALID)) == 0) 447179895Sdelphij break; 448179895Sdelphij DELAY(50); 449179895Sdelphij } 450179895Sdelphij if (i == NRETRY) { 451179895Sdelphij if_printf(sc->ifp, 452179895Sdelphij "read phy %d, reg %d timed out\n", phy, reg); 453179895Sdelphij ret = 0; 454179895Sdelphij goto back; 455179895Sdelphij } 456179895Sdelphij 457179895Sdelphij#undef NRETRY 458179895Sdelphij 459179895Sdelphij val = CSR_READ_4(sc, ET_MII_STAT); 460199548Syongari ret = val & ET_MII_STAT_VALUE_MASK; 461179895Sdelphij 462179895Sdelphijback: 463179895Sdelphij /* Make sure that the current operation is stopped */ 464179895Sdelphij CSR_WRITE_4(sc, ET_MII_CMD, 0); 465199556Syongari return (ret); 466179895Sdelphij} 467179895Sdelphij 468179895Sdelphijstatic int 469179895Sdelphijet_miibus_writereg(device_t dev, int phy, int reg, int val0) 470179895Sdelphij{ 471179895Sdelphij struct et_softc *sc = device_get_softc(dev); 472179895Sdelphij uint32_t val; 473179895Sdelphij int i; 474179895Sdelphij 475179895Sdelphij /* Stop any pending operations */ 476179895Sdelphij CSR_WRITE_4(sc, ET_MII_CMD, 0); 477179895Sdelphij 478199548Syongari val = (phy << ET_MII_ADDR_PHY_SHIFT) & ET_MII_ADDR_PHY_MASK; 479199548Syongari val |= (reg << ET_MII_ADDR_REG_SHIFT) & ET_MII_ADDR_REG_MASK; 480179895Sdelphij CSR_WRITE_4(sc, ET_MII_ADDR, val); 481179895Sdelphij 482179895Sdelphij /* Start writing */ 483199548Syongari CSR_WRITE_4(sc, ET_MII_CTRL, 484199548Syongari (val0 << ET_MII_CTRL_VALUE_SHIFT) & ET_MII_CTRL_VALUE_MASK); 485179895Sdelphij 486179895Sdelphij#define NRETRY 100 487179895Sdelphij 488179895Sdelphij for (i = 0; i < NRETRY; ++i) { 489179895Sdelphij val = CSR_READ_4(sc, ET_MII_IND); 490179895Sdelphij if ((val & ET_MII_IND_BUSY) == 0) 491179895Sdelphij break; 492179895Sdelphij DELAY(50); 493179895Sdelphij } 494179895Sdelphij if (i == NRETRY) { 495179895Sdelphij if_printf(sc->ifp, 496179895Sdelphij "write phy %d, reg %d timed out\n", phy, reg); 497179895Sdelphij et_miibus_readreg(dev, phy, reg); 498179895Sdelphij } 499179895Sdelphij 500179895Sdelphij#undef NRETRY 501179895Sdelphij 502179895Sdelphij /* Make sure that the current operation is stopped */ 503179895Sdelphij CSR_WRITE_4(sc, ET_MII_CMD, 0); 504199556Syongari return (0); 505179895Sdelphij} 506179895Sdelphij 507179895Sdelphijstatic void 508179895Sdelphijet_miibus_statchg(device_t dev) 509179895Sdelphij{ 510179895Sdelphij et_setmedia(device_get_softc(dev)); 511179895Sdelphij} 512179895Sdelphij 513179895Sdelphijstatic int 514179895Sdelphijet_ifmedia_upd_locked(struct ifnet *ifp) 515179895Sdelphij{ 516179895Sdelphij struct et_softc *sc = ifp->if_softc; 517179895Sdelphij struct mii_data *mii = device_get_softc(sc->sc_miibus); 518179895Sdelphij 519179895Sdelphij if (mii->mii_instance != 0) { 520179895Sdelphij struct mii_softc *miisc; 521179895Sdelphij 522179895Sdelphij LIST_FOREACH(miisc, &mii->mii_phys, mii_list) 523179895Sdelphij mii_phy_reset(miisc); 524179895Sdelphij } 525179895Sdelphij mii_mediachg(mii); 526179895Sdelphij 527199556Syongari return (0); 528179895Sdelphij} 529179895Sdelphij 530179895Sdelphijstatic int 531179895Sdelphijet_ifmedia_upd(struct ifnet *ifp) 532179895Sdelphij{ 533179895Sdelphij struct et_softc *sc = ifp->if_softc; 534179895Sdelphij int res; 535179895Sdelphij 536179895Sdelphij ET_LOCK(sc); 537179895Sdelphij res = et_ifmedia_upd_locked(ifp); 538179895Sdelphij ET_UNLOCK(sc); 539179895Sdelphij 540199556Syongari return (res); 541179895Sdelphij} 542179895Sdelphij 543179895Sdelphijstatic void 544179895Sdelphijet_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr) 545179895Sdelphij{ 546179895Sdelphij struct et_softc *sc = ifp->if_softc; 547179895Sdelphij struct mii_data *mii = device_get_softc(sc->sc_miibus); 548179895Sdelphij 549179895Sdelphij mii_pollstat(mii); 550179895Sdelphij ifmr->ifm_active = mii->mii_media_active; 551179895Sdelphij ifmr->ifm_status = mii->mii_media_status; 552179895Sdelphij} 553179895Sdelphij 554179895Sdelphijstatic void 555179895Sdelphijet_stop(struct et_softc *sc) 556179895Sdelphij{ 557179895Sdelphij struct ifnet *ifp = sc->ifp; 558179895Sdelphij 559179895Sdelphij ET_LOCK_ASSERT(sc); 560179895Sdelphij 561179895Sdelphij callout_stop(&sc->sc_tick); 562179895Sdelphij 563179895Sdelphij et_stop_rxdma(sc); 564179895Sdelphij et_stop_txdma(sc); 565179895Sdelphij 566179895Sdelphij et_disable_intrs(sc); 567179895Sdelphij 568179895Sdelphij et_free_tx_ring(sc); 569179895Sdelphij et_free_rx_ring(sc); 570179895Sdelphij 571179895Sdelphij et_reset(sc); 572179895Sdelphij 573179895Sdelphij sc->sc_tx = 0; 574179895Sdelphij sc->sc_tx_intr = 0; 575179895Sdelphij sc->sc_flags &= ~ET_FLAG_TXRX_ENABLED; 576179895Sdelphij 577179895Sdelphij sc->watchdog_timer = 0; 578179895Sdelphij ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); 579179895Sdelphij} 580179895Sdelphij 581179895Sdelphijstatic int 582199561Syongariet_bus_config(struct et_softc *sc) 583179895Sdelphij{ 584179895Sdelphij uint32_t val, max_plsz; 585179895Sdelphij uint16_t ack_latency, replay_timer; 586179895Sdelphij 587179895Sdelphij /* 588179895Sdelphij * Test whether EEPROM is valid 589179895Sdelphij * NOTE: Read twice to get the correct value 590179895Sdelphij */ 591199561Syongari pci_read_config(sc->dev, ET_PCIR_EEPROM_STATUS, 1); 592199561Syongari val = pci_read_config(sc->dev, ET_PCIR_EEPROM_STATUS, 1); 593179895Sdelphij if (val & ET_PCIM_EEPROM_STATUS_ERROR) { 594199561Syongari device_printf(sc->dev, "EEPROM status error 0x%02x\n", val); 595199556Syongari return (ENXIO); 596179895Sdelphij } 597179895Sdelphij 598179895Sdelphij /* TODO: LED */ 599179895Sdelphij 600199561Syongari if ((sc->sc_flags & ET_FLAG_PCIE) == 0) 601199561Syongari return (0); 602199561Syongari 603179895Sdelphij /* 604179895Sdelphij * Configure ACK latency and replay timer according to 605179895Sdelphij * max playload size 606179895Sdelphij */ 607199561Syongari val = pci_read_config(sc->dev, 608199561Syongari sc->sc_expcap + PCIR_EXPRESS_DEVICE_CAP, 4); 609199561Syongari max_plsz = val & PCIM_EXP_CAP_MAX_PAYLOAD; 610179895Sdelphij 611179895Sdelphij switch (max_plsz) { 612179895Sdelphij case ET_PCIV_DEVICE_CAPS_PLSZ_128: 613179895Sdelphij ack_latency = ET_PCIV_ACK_LATENCY_128; 614179895Sdelphij replay_timer = ET_PCIV_REPLAY_TIMER_128; 615179895Sdelphij break; 616179895Sdelphij 617179895Sdelphij case ET_PCIV_DEVICE_CAPS_PLSZ_256: 618179895Sdelphij ack_latency = ET_PCIV_ACK_LATENCY_256; 619179895Sdelphij replay_timer = ET_PCIV_REPLAY_TIMER_256; 620179895Sdelphij break; 621179895Sdelphij 622179895Sdelphij default: 623199561Syongari ack_latency = pci_read_config(sc->dev, ET_PCIR_ACK_LATENCY, 2); 624199561Syongari replay_timer = pci_read_config(sc->dev, 625199561Syongari ET_PCIR_REPLAY_TIMER, 2); 626199561Syongari device_printf(sc->dev, "ack latency %u, replay timer %u\n", 627179895Sdelphij ack_latency, replay_timer); 628179895Sdelphij break; 629179895Sdelphij } 630179895Sdelphij if (ack_latency != 0) { 631199561Syongari pci_write_config(sc->dev, ET_PCIR_ACK_LATENCY, ack_latency, 2); 632199561Syongari pci_write_config(sc->dev, ET_PCIR_REPLAY_TIMER, replay_timer, 633199561Syongari 2); 634179895Sdelphij } 635179895Sdelphij 636179895Sdelphij /* 637179895Sdelphij * Set L0s and L1 latency timer to 2us 638179895Sdelphij */ 639199561Syongari val = pci_read_config(sc->dev, ET_PCIR_L0S_L1_LATENCY, 4); 640199548Syongari val &= ~(PCIM_LINK_CAP_L0S_EXIT | PCIM_LINK_CAP_L1_EXIT); 641199548Syongari /* L0s exit latency : 2us */ 642199548Syongari val |= 0x00005000; 643199548Syongari /* L1 exit latency : 2us */ 644199548Syongari val |= 0x00028000; 645199561Syongari pci_write_config(sc->dev, ET_PCIR_L0S_L1_LATENCY, val, 4); 646179895Sdelphij 647179895Sdelphij /* 648179895Sdelphij * Set max read request size to 2048 bytes 649179895Sdelphij */ 650199561Syongari val = pci_read_config(sc->dev, 651199561Syongari sc->sc_expcap + PCIR_EXPRESS_DEVICE_CTL, 2); 652199561Syongari val &= ~PCIM_EXP_CTL_MAX_READ_REQUEST; 653179895Sdelphij val |= ET_PCIV_DEVICE_CTRL_RRSZ_2K; 654199561Syongari pci_write_config(sc->dev, 655199561Syongari sc->sc_expcap + PCIR_EXPRESS_DEVICE_CTL, val, 2); 656179895Sdelphij 657199556Syongari return (0); 658179895Sdelphij} 659179895Sdelphij 660179895Sdelphijstatic void 661179895Sdelphijet_get_eaddr(device_t dev, uint8_t eaddr[]) 662179895Sdelphij{ 663179895Sdelphij uint32_t val; 664179895Sdelphij int i; 665179895Sdelphij 666179895Sdelphij val = pci_read_config(dev, ET_PCIR_MAC_ADDR0, 4); 667179895Sdelphij for (i = 0; i < 4; ++i) 668179895Sdelphij eaddr[i] = (val >> (8 * i)) & 0xff; 669179895Sdelphij 670179895Sdelphij val = pci_read_config(dev, ET_PCIR_MAC_ADDR1, 2); 671179895Sdelphij for (; i < ETHER_ADDR_LEN; ++i) 672179895Sdelphij eaddr[i] = (val >> (8 * (i - 4))) & 0xff; 673179895Sdelphij} 674179895Sdelphij 675179895Sdelphijstatic void 676179895Sdelphijet_reset(struct et_softc *sc) 677179895Sdelphij{ 678179895Sdelphij CSR_WRITE_4(sc, ET_MAC_CFG1, 679179895Sdelphij ET_MAC_CFG1_RST_TXFUNC | ET_MAC_CFG1_RST_RXFUNC | 680179895Sdelphij ET_MAC_CFG1_RST_TXMC | ET_MAC_CFG1_RST_RXMC | 681179895Sdelphij ET_MAC_CFG1_SIM_RST | ET_MAC_CFG1_SOFT_RST); 682179895Sdelphij 683179895Sdelphij CSR_WRITE_4(sc, ET_SWRST, 684179895Sdelphij ET_SWRST_TXDMA | ET_SWRST_RXDMA | 685179895Sdelphij ET_SWRST_TXMAC | ET_SWRST_RXMAC | 686179895Sdelphij ET_SWRST_MAC | ET_SWRST_MAC_STAT | ET_SWRST_MMC); 687179895Sdelphij 688179895Sdelphij CSR_WRITE_4(sc, ET_MAC_CFG1, 689179895Sdelphij ET_MAC_CFG1_RST_TXFUNC | ET_MAC_CFG1_RST_RXFUNC | 690179895Sdelphij ET_MAC_CFG1_RST_TXMC | ET_MAC_CFG1_RST_RXMC); 691179895Sdelphij CSR_WRITE_4(sc, ET_MAC_CFG1, 0); 692179895Sdelphij} 693179895Sdelphij 694179895Sdelphijstatic void 695179895Sdelphijet_disable_intrs(struct et_softc *sc) 696179895Sdelphij{ 697179895Sdelphij CSR_WRITE_4(sc, ET_INTR_MASK, 0xffffffff); 698179895Sdelphij} 699179895Sdelphij 700179895Sdelphijstatic void 701179895Sdelphijet_enable_intrs(struct et_softc *sc, uint32_t intrs) 702179895Sdelphij{ 703179895Sdelphij CSR_WRITE_4(sc, ET_INTR_MASK, ~intrs); 704179895Sdelphij} 705179895Sdelphij 706179895Sdelphijstatic int 707179895Sdelphijet_dma_alloc(device_t dev) 708179895Sdelphij{ 709179895Sdelphij struct et_softc *sc = device_get_softc(dev); 710179895Sdelphij struct et_txdesc_ring *tx_ring = &sc->sc_tx_ring; 711179895Sdelphij struct et_txstatus_data *txsd = &sc->sc_tx_status; 712179895Sdelphij struct et_rxstat_ring *rxst_ring = &sc->sc_rxstat_ring; 713179895Sdelphij struct et_rxstatus_data *rxsd = &sc->sc_rx_status; 714179895Sdelphij int i, error; 715179895Sdelphij 716179895Sdelphij /* 717179895Sdelphij * Create top level DMA tag 718179895Sdelphij */ 719179895Sdelphij error = bus_dma_tag_create(NULL, 1, 0, 720179895Sdelphij BUS_SPACE_MAXADDR_32BIT, 721179895Sdelphij BUS_SPACE_MAXADDR, 722179895Sdelphij NULL, NULL, 723179895Sdelphij MAXBSIZE, 724179895Sdelphij BUS_SPACE_UNRESTRICTED, 725179895Sdelphij BUS_SPACE_MAXSIZE_32BIT, 726179895Sdelphij 0, NULL, NULL, &sc->sc_dtag); 727179895Sdelphij if (error) { 728179895Sdelphij device_printf(dev, "can't create DMA tag\n"); 729199556Syongari return (error); 730179895Sdelphij } 731179895Sdelphij 732179895Sdelphij /* 733179895Sdelphij * Create TX ring DMA stuffs 734179895Sdelphij */ 735179895Sdelphij error = et_dma_mem_create(dev, ET_TX_RING_SIZE, &tx_ring->tr_dtag, 736179895Sdelphij (void **)&tx_ring->tr_desc, 737179895Sdelphij &tx_ring->tr_paddr, &tx_ring->tr_dmap); 738179895Sdelphij if (error) { 739179895Sdelphij device_printf(dev, "can't create TX ring DMA stuffs\n"); 740199556Syongari return (error); 741179895Sdelphij } 742179895Sdelphij 743179895Sdelphij /* 744179895Sdelphij * Create TX status DMA stuffs 745179895Sdelphij */ 746179895Sdelphij error = et_dma_mem_create(dev, sizeof(uint32_t), &txsd->txsd_dtag, 747179895Sdelphij (void **)&txsd->txsd_status, 748179895Sdelphij &txsd->txsd_paddr, &txsd->txsd_dmap); 749179895Sdelphij if (error) { 750179895Sdelphij device_printf(dev, "can't create TX status DMA stuffs\n"); 751199556Syongari return (error); 752179895Sdelphij } 753179895Sdelphij 754179895Sdelphij /* 755179895Sdelphij * Create DMA stuffs for RX rings 756179895Sdelphij */ 757179895Sdelphij for (i = 0; i < ET_RX_NRING; ++i) { 758179895Sdelphij static const uint32_t rx_ring_posreg[ET_RX_NRING] = 759179895Sdelphij { ET_RX_RING0_POS, ET_RX_RING1_POS }; 760179895Sdelphij 761179895Sdelphij struct et_rxdesc_ring *rx_ring = &sc->sc_rx_ring[i]; 762179895Sdelphij 763179895Sdelphij error = et_dma_mem_create(dev, ET_RX_RING_SIZE, 764179895Sdelphij &rx_ring->rr_dtag, 765179895Sdelphij (void **)&rx_ring->rr_desc, 766179895Sdelphij &rx_ring->rr_paddr, 767179895Sdelphij &rx_ring->rr_dmap); 768179895Sdelphij if (error) { 769179895Sdelphij device_printf(dev, "can't create DMA stuffs for " 770179895Sdelphij "the %d RX ring\n", i); 771199556Syongari return (error); 772179895Sdelphij } 773179895Sdelphij rx_ring->rr_posreg = rx_ring_posreg[i]; 774179895Sdelphij } 775179895Sdelphij 776179895Sdelphij /* 777179895Sdelphij * Create RX stat ring DMA stuffs 778179895Sdelphij */ 779179895Sdelphij error = et_dma_mem_create(dev, ET_RXSTAT_RING_SIZE, 780179895Sdelphij &rxst_ring->rsr_dtag, 781179895Sdelphij (void **)&rxst_ring->rsr_stat, 782179895Sdelphij &rxst_ring->rsr_paddr, &rxst_ring->rsr_dmap); 783179895Sdelphij if (error) { 784179895Sdelphij device_printf(dev, "can't create RX stat ring DMA stuffs\n"); 785199556Syongari return (error); 786179895Sdelphij } 787179895Sdelphij 788179895Sdelphij /* 789179895Sdelphij * Create RX status DMA stuffs 790179895Sdelphij */ 791179895Sdelphij error = et_dma_mem_create(dev, sizeof(struct et_rxstatus), 792179895Sdelphij &rxsd->rxsd_dtag, 793179895Sdelphij (void **)&rxsd->rxsd_status, 794179895Sdelphij &rxsd->rxsd_paddr, &rxsd->rxsd_dmap); 795179895Sdelphij if (error) { 796179895Sdelphij device_printf(dev, "can't create RX status DMA stuffs\n"); 797199556Syongari return (error); 798179895Sdelphij } 799179895Sdelphij 800179895Sdelphij /* 801179895Sdelphij * Create mbuf DMA stuffs 802179895Sdelphij */ 803179895Sdelphij error = et_dma_mbuf_create(dev); 804179895Sdelphij if (error) 805199556Syongari return (error); 806179895Sdelphij 807199556Syongari return (0); 808179895Sdelphij} 809179895Sdelphij 810179895Sdelphijstatic void 811179895Sdelphijet_dma_free(device_t dev) 812179895Sdelphij{ 813179895Sdelphij struct et_softc *sc = device_get_softc(dev); 814179895Sdelphij struct et_txdesc_ring *tx_ring = &sc->sc_tx_ring; 815179895Sdelphij struct et_txstatus_data *txsd = &sc->sc_tx_status; 816179895Sdelphij struct et_rxstat_ring *rxst_ring = &sc->sc_rxstat_ring; 817179895Sdelphij struct et_rxstatus_data *rxsd = &sc->sc_rx_status; 818179895Sdelphij int i, rx_done[ET_RX_NRING]; 819179895Sdelphij 820179895Sdelphij /* 821179895Sdelphij * Destroy TX ring DMA stuffs 822179895Sdelphij */ 823179895Sdelphij et_dma_mem_destroy(tx_ring->tr_dtag, tx_ring->tr_desc, 824179895Sdelphij tx_ring->tr_dmap); 825179895Sdelphij 826179895Sdelphij /* 827179895Sdelphij * Destroy TX status DMA stuffs 828179895Sdelphij */ 829179895Sdelphij et_dma_mem_destroy(txsd->txsd_dtag, txsd->txsd_status, 830179895Sdelphij txsd->txsd_dmap); 831179895Sdelphij 832179895Sdelphij /* 833179895Sdelphij * Destroy DMA stuffs for RX rings 834179895Sdelphij */ 835179895Sdelphij for (i = 0; i < ET_RX_NRING; ++i) { 836179895Sdelphij struct et_rxdesc_ring *rx_ring = &sc->sc_rx_ring[i]; 837179895Sdelphij 838179895Sdelphij et_dma_mem_destroy(rx_ring->rr_dtag, rx_ring->rr_desc, 839179895Sdelphij rx_ring->rr_dmap); 840179895Sdelphij } 841179895Sdelphij 842179895Sdelphij /* 843179895Sdelphij * Destroy RX stat ring DMA stuffs 844179895Sdelphij */ 845179895Sdelphij et_dma_mem_destroy(rxst_ring->rsr_dtag, rxst_ring->rsr_stat, 846179895Sdelphij rxst_ring->rsr_dmap); 847179895Sdelphij 848179895Sdelphij /* 849179895Sdelphij * Destroy RX status DMA stuffs 850179895Sdelphij */ 851179895Sdelphij et_dma_mem_destroy(rxsd->rxsd_dtag, rxsd->rxsd_status, 852179895Sdelphij rxsd->rxsd_dmap); 853179895Sdelphij 854179895Sdelphij /* 855179895Sdelphij * Destroy mbuf DMA stuffs 856179895Sdelphij */ 857179895Sdelphij for (i = 0; i < ET_RX_NRING; ++i) 858179895Sdelphij rx_done[i] = ET_RX_NDESC; 859179895Sdelphij et_dma_mbuf_destroy(dev, ET_TX_NDESC, rx_done); 860179895Sdelphij 861179895Sdelphij /* 862179895Sdelphij * Destroy top level DMA tag 863179895Sdelphij */ 864179895Sdelphij if (sc->sc_dtag != NULL) 865179895Sdelphij bus_dma_tag_destroy(sc->sc_dtag); 866179895Sdelphij} 867179895Sdelphij 868179895Sdelphijstatic int 869179895Sdelphijet_dma_mbuf_create(device_t dev) 870179895Sdelphij{ 871179895Sdelphij struct et_softc *sc = device_get_softc(dev); 872179895Sdelphij struct et_txbuf_data *tbd = &sc->sc_tx_data; 873179895Sdelphij int i, error, rx_done[ET_RX_NRING]; 874179895Sdelphij 875179895Sdelphij /* 876179895Sdelphij * Create mbuf DMA tag 877179895Sdelphij */ 878179895Sdelphij error = bus_dma_tag_create(sc->sc_dtag, 1, 0, 879179895Sdelphij BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, 880179895Sdelphij NULL, NULL, 881179895Sdelphij ET_JUMBO_FRAMELEN, ET_NSEG_MAX, 882179895Sdelphij BUS_SPACE_MAXSIZE_32BIT, 883179895Sdelphij BUS_DMA_ALLOCNOW, NULL, NULL, &sc->sc_mbuf_dtag); 884179895Sdelphij if (error) { 885179895Sdelphij device_printf(dev, "can't create mbuf DMA tag\n"); 886199556Syongari return (error); 887179895Sdelphij } 888179895Sdelphij 889179895Sdelphij /* 890179895Sdelphij * Create spare DMA map for RX mbufs 891179895Sdelphij */ 892179895Sdelphij error = bus_dmamap_create(sc->sc_mbuf_dtag, 0, &sc->sc_mbuf_tmp_dmap); 893179895Sdelphij if (error) { 894179895Sdelphij device_printf(dev, "can't create spare mbuf DMA map\n"); 895179895Sdelphij bus_dma_tag_destroy(sc->sc_mbuf_dtag); 896179895Sdelphij sc->sc_mbuf_dtag = NULL; 897199556Syongari return (error); 898179895Sdelphij } 899179895Sdelphij 900179895Sdelphij /* 901179895Sdelphij * Create DMA maps for RX mbufs 902179895Sdelphij */ 903179895Sdelphij bzero(rx_done, sizeof(rx_done)); 904179895Sdelphij for (i = 0; i < ET_RX_NRING; ++i) { 905179895Sdelphij struct et_rxbuf_data *rbd = &sc->sc_rx_data[i]; 906179895Sdelphij int j; 907179895Sdelphij 908179895Sdelphij for (j = 0; j < ET_RX_NDESC; ++j) { 909179895Sdelphij error = bus_dmamap_create(sc->sc_mbuf_dtag, 0, 910179895Sdelphij &rbd->rbd_buf[j].rb_dmap); 911179895Sdelphij if (error) { 912179895Sdelphij device_printf(dev, "can't create %d RX mbuf " 913179895Sdelphij "for %d RX ring\n", j, i); 914179895Sdelphij rx_done[i] = j; 915179895Sdelphij et_dma_mbuf_destroy(dev, 0, rx_done); 916199556Syongari return (error); 917179895Sdelphij } 918179895Sdelphij } 919179895Sdelphij rx_done[i] = ET_RX_NDESC; 920179895Sdelphij 921179895Sdelphij rbd->rbd_softc = sc; 922179895Sdelphij rbd->rbd_ring = &sc->sc_rx_ring[i]; 923179895Sdelphij } 924179895Sdelphij 925179895Sdelphij /* 926179895Sdelphij * Create DMA maps for TX mbufs 927179895Sdelphij */ 928179895Sdelphij for (i = 0; i < ET_TX_NDESC; ++i) { 929179895Sdelphij error = bus_dmamap_create(sc->sc_mbuf_dtag, 0, 930179895Sdelphij &tbd->tbd_buf[i].tb_dmap); 931179895Sdelphij if (error) { 932179895Sdelphij device_printf(dev, "can't create %d TX mbuf " 933179895Sdelphij "DMA map\n", i); 934179895Sdelphij et_dma_mbuf_destroy(dev, i, rx_done); 935199556Syongari return (error); 936179895Sdelphij } 937179895Sdelphij } 938179895Sdelphij 939199556Syongari return (0); 940179895Sdelphij} 941179895Sdelphij 942179895Sdelphijstatic void 943179895Sdelphijet_dma_mbuf_destroy(device_t dev, int tx_done, const int rx_done[]) 944179895Sdelphij{ 945179895Sdelphij struct et_softc *sc = device_get_softc(dev); 946179895Sdelphij struct et_txbuf_data *tbd = &sc->sc_tx_data; 947179895Sdelphij int i; 948179895Sdelphij 949179895Sdelphij if (sc->sc_mbuf_dtag == NULL) 950179895Sdelphij return; 951179895Sdelphij 952179895Sdelphij /* 953179895Sdelphij * Destroy DMA maps for RX mbufs 954179895Sdelphij */ 955179895Sdelphij for (i = 0; i < ET_RX_NRING; ++i) { 956179895Sdelphij struct et_rxbuf_data *rbd = &sc->sc_rx_data[i]; 957179895Sdelphij int j; 958179895Sdelphij 959179895Sdelphij for (j = 0; j < rx_done[i]; ++j) { 960179895Sdelphij struct et_rxbuf *rb = &rbd->rbd_buf[j]; 961179895Sdelphij 962179895Sdelphij KASSERT(rb->rb_mbuf == NULL, 963179895Sdelphij ("RX mbuf in %d RX ring is not freed yet\n", i)); 964179895Sdelphij bus_dmamap_destroy(sc->sc_mbuf_dtag, rb->rb_dmap); 965179895Sdelphij } 966179895Sdelphij } 967179895Sdelphij 968179895Sdelphij /* 969179895Sdelphij * Destroy DMA maps for TX mbufs 970179895Sdelphij */ 971179895Sdelphij for (i = 0; i < tx_done; ++i) { 972179895Sdelphij struct et_txbuf *tb = &tbd->tbd_buf[i]; 973179895Sdelphij 974179895Sdelphij KASSERT(tb->tb_mbuf == NULL, ("TX mbuf is not freed yet\n")); 975179895Sdelphij bus_dmamap_destroy(sc->sc_mbuf_dtag, tb->tb_dmap); 976179895Sdelphij } 977179895Sdelphij 978179895Sdelphij /* 979179895Sdelphij * Destroy spare mbuf DMA map 980179895Sdelphij */ 981179895Sdelphij bus_dmamap_destroy(sc->sc_mbuf_dtag, sc->sc_mbuf_tmp_dmap); 982179895Sdelphij 983179895Sdelphij /* 984179895Sdelphij * Destroy mbuf DMA tag 985179895Sdelphij */ 986179895Sdelphij bus_dma_tag_destroy(sc->sc_mbuf_dtag); 987179895Sdelphij sc->sc_mbuf_dtag = NULL; 988179895Sdelphij} 989179895Sdelphij 990179895Sdelphijstatic int 991179895Sdelphijet_dma_mem_create(device_t dev, bus_size_t size, bus_dma_tag_t *dtag, 992179895Sdelphij void **addr, bus_addr_t *paddr, bus_dmamap_t *dmap) 993179895Sdelphij{ 994179895Sdelphij struct et_softc *sc = device_get_softc(dev); 995179895Sdelphij int error; 996179895Sdelphij 997179895Sdelphij error = bus_dma_tag_create(sc->sc_dtag, ET_ALIGN, 0, 998179895Sdelphij BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, 999179895Sdelphij NULL, NULL, 1000179895Sdelphij size, 1, BUS_SPACE_MAXSIZE_32BIT, 1001179895Sdelphij 0, NULL, NULL, dtag); 1002179895Sdelphij if (error) { 1003179895Sdelphij device_printf(dev, "can't create DMA tag\n"); 1004199556Syongari return (error); 1005179895Sdelphij } 1006179895Sdelphij 1007179895Sdelphij error = bus_dmamem_alloc(*dtag, addr, BUS_DMA_WAITOK | BUS_DMA_ZERO, 1008179895Sdelphij dmap); 1009179895Sdelphij if (error) { 1010179895Sdelphij device_printf(dev, "can't allocate DMA mem\n"); 1011179895Sdelphij bus_dma_tag_destroy(*dtag); 1012179895Sdelphij *dtag = NULL; 1013199556Syongari return (error); 1014179895Sdelphij } 1015179895Sdelphij 1016179895Sdelphij error = bus_dmamap_load(*dtag, *dmap, *addr, size, 1017179895Sdelphij et_dma_ring_addr, paddr, BUS_DMA_WAITOK); 1018179895Sdelphij if (error) { 1019179895Sdelphij device_printf(dev, "can't load DMA mem\n"); 1020179895Sdelphij bus_dmamem_free(*dtag, *addr, *dmap); 1021179895Sdelphij bus_dma_tag_destroy(*dtag); 1022179895Sdelphij *dtag = NULL; 1023199556Syongari return (error); 1024179895Sdelphij } 1025199556Syongari return (0); 1026179895Sdelphij} 1027179895Sdelphij 1028179895Sdelphijstatic void 1029179895Sdelphijet_dma_mem_destroy(bus_dma_tag_t dtag, void *addr, bus_dmamap_t dmap) 1030179895Sdelphij{ 1031179895Sdelphij if (dtag != NULL) { 1032179895Sdelphij bus_dmamap_unload(dtag, dmap); 1033179895Sdelphij bus_dmamem_free(dtag, addr, dmap); 1034179895Sdelphij bus_dma_tag_destroy(dtag); 1035179895Sdelphij } 1036179895Sdelphij} 1037179895Sdelphij 1038179895Sdelphijstatic void 1039179895Sdelphijet_dma_ring_addr(void *arg, bus_dma_segment_t *seg, int nseg, int error) 1040179895Sdelphij{ 1041179895Sdelphij KASSERT(nseg == 1, ("too many segments\n")); 1042179895Sdelphij *((bus_addr_t *)arg) = seg->ds_addr; 1043179895Sdelphij} 1044179895Sdelphij 1045179895Sdelphijstatic void 1046179895Sdelphijet_chip_attach(struct et_softc *sc) 1047179895Sdelphij{ 1048179895Sdelphij uint32_t val; 1049179895Sdelphij 1050179895Sdelphij /* 1051179895Sdelphij * Perform minimal initialization 1052179895Sdelphij */ 1053179895Sdelphij 1054179895Sdelphij /* Disable loopback */ 1055179895Sdelphij CSR_WRITE_4(sc, ET_LOOPBACK, 0); 1056179895Sdelphij 1057179895Sdelphij /* Reset MAC */ 1058179895Sdelphij CSR_WRITE_4(sc, ET_MAC_CFG1, 1059179895Sdelphij ET_MAC_CFG1_RST_TXFUNC | ET_MAC_CFG1_RST_RXFUNC | 1060179895Sdelphij ET_MAC_CFG1_RST_TXMC | ET_MAC_CFG1_RST_RXMC | 1061179895Sdelphij ET_MAC_CFG1_SIM_RST | ET_MAC_CFG1_SOFT_RST); 1062179895Sdelphij 1063179895Sdelphij /* 1064179895Sdelphij * Setup half duplex mode 1065179895Sdelphij */ 1066199548Syongari val = (10 << ET_MAC_HDX_ALT_BEB_TRUNC_SHIFT) | 1067199548Syongari (15 << ET_MAC_HDX_REXMIT_MAX_SHIFT) | 1068199548Syongari (55 << ET_MAC_HDX_COLLWIN_SHIFT) | 1069199548Syongari ET_MAC_HDX_EXC_DEFER; 1070179895Sdelphij CSR_WRITE_4(sc, ET_MAC_HDX, val); 1071179895Sdelphij 1072179895Sdelphij /* Clear MAC control */ 1073179895Sdelphij CSR_WRITE_4(sc, ET_MAC_CTRL, 0); 1074179895Sdelphij 1075179895Sdelphij /* Reset MII */ 1076179895Sdelphij CSR_WRITE_4(sc, ET_MII_CFG, ET_MII_CFG_CLKRST); 1077179895Sdelphij 1078179895Sdelphij /* Bring MAC out of reset state */ 1079179895Sdelphij CSR_WRITE_4(sc, ET_MAC_CFG1, 0); 1080179895Sdelphij 1081179895Sdelphij /* Enable memory controllers */ 1082179895Sdelphij CSR_WRITE_4(sc, ET_MMC_CTRL, ET_MMC_CTRL_ENABLE); 1083179895Sdelphij} 1084179895Sdelphij 1085179895Sdelphijstatic void 1086179895Sdelphijet_intr(void *xsc) 1087179895Sdelphij{ 1088179895Sdelphij struct et_softc *sc = xsc; 1089179895Sdelphij struct ifnet *ifp; 1090179895Sdelphij uint32_t intrs; 1091179895Sdelphij 1092179895Sdelphij ET_LOCK(sc); 1093179895Sdelphij ifp = sc->ifp; 1094179895Sdelphij if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) { 1095179895Sdelphij ET_UNLOCK(sc); 1096179895Sdelphij return; 1097179895Sdelphij } 1098179895Sdelphij 1099179895Sdelphij et_disable_intrs(sc); 1100179895Sdelphij 1101179895Sdelphij intrs = CSR_READ_4(sc, ET_INTR_STATUS); 1102179895Sdelphij intrs &= ET_INTRS; 1103179895Sdelphij if (intrs == 0) /* Not interested */ 1104179895Sdelphij goto back; 1105179895Sdelphij 1106179895Sdelphij if (intrs & ET_INTR_RXEOF) 1107179895Sdelphij et_rxeof(sc); 1108179895Sdelphij if (intrs & (ET_INTR_TXEOF | ET_INTR_TIMER)) 1109179895Sdelphij et_txeof(sc); 1110179895Sdelphij if (intrs & ET_INTR_TIMER) 1111179895Sdelphij CSR_WRITE_4(sc, ET_TIMER, sc->sc_timer); 1112179895Sdelphijback: 1113179895Sdelphij et_enable_intrs(sc, ET_INTRS); 1114179895Sdelphij ET_UNLOCK(sc); 1115179895Sdelphij} 1116179895Sdelphij 1117179895Sdelphijstatic void 1118179895Sdelphijet_init_locked(struct et_softc *sc) 1119179895Sdelphij{ 1120179895Sdelphij struct ifnet *ifp = sc->ifp; 1121179895Sdelphij const struct et_bsize *arr; 1122179895Sdelphij int error, i; 1123179895Sdelphij 1124179895Sdelphij ET_LOCK_ASSERT(sc); 1125179895Sdelphij 1126179895Sdelphij if (ifp->if_drv_flags & IFF_DRV_RUNNING) 1127179895Sdelphij return; 1128179895Sdelphij 1129179895Sdelphij et_stop(sc); 1130179895Sdelphij 1131179895Sdelphij arr = et_bufsize_std; 1132179895Sdelphij for (i = 0; i < ET_RX_NRING; ++i) { 1133179895Sdelphij sc->sc_rx_data[i].rbd_bufsize = arr[i].bufsize; 1134179895Sdelphij sc->sc_rx_data[i].rbd_newbuf = arr[i].newbuf; 1135179895Sdelphij } 1136179895Sdelphij 1137179895Sdelphij error = et_init_tx_ring(sc); 1138179895Sdelphij if (error) 1139179895Sdelphij goto back; 1140179895Sdelphij 1141179895Sdelphij error = et_init_rx_ring(sc); 1142179895Sdelphij if (error) 1143179895Sdelphij goto back; 1144179895Sdelphij 1145179895Sdelphij error = et_chip_init(sc); 1146179895Sdelphij if (error) 1147179895Sdelphij goto back; 1148179895Sdelphij 1149179895Sdelphij error = et_enable_txrx(sc, 1); 1150179895Sdelphij if (error) 1151179895Sdelphij goto back; 1152179895Sdelphij 1153179895Sdelphij et_enable_intrs(sc, ET_INTRS); 1154179895Sdelphij 1155179895Sdelphij callout_reset(&sc->sc_tick, hz, et_tick, sc); 1156179895Sdelphij 1157179895Sdelphij CSR_WRITE_4(sc, ET_TIMER, sc->sc_timer); 1158179895Sdelphij 1159179895Sdelphij ifp->if_drv_flags |= IFF_DRV_RUNNING; 1160179895Sdelphij ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 1161179895Sdelphijback: 1162179895Sdelphij if (error) 1163179895Sdelphij et_stop(sc); 1164179895Sdelphij} 1165179895Sdelphij 1166179895Sdelphijstatic void 1167179895Sdelphijet_init(void *xsc) 1168179895Sdelphij{ 1169179895Sdelphij struct et_softc *sc = xsc; 1170179895Sdelphij 1171179895Sdelphij ET_LOCK(sc); 1172179895Sdelphij et_init_locked(sc); 1173179895Sdelphij ET_UNLOCK(sc); 1174179895Sdelphij} 1175179895Sdelphij 1176179895Sdelphijstatic int 1177179895Sdelphijet_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 1178179895Sdelphij{ 1179179895Sdelphij struct et_softc *sc = ifp->if_softc; 1180179895Sdelphij struct mii_data *mii = device_get_softc(sc->sc_miibus); 1181179895Sdelphij struct ifreq *ifr = (struct ifreq *)data; 1182199611Syongari int error = 0, mask, max_framelen; 1183179895Sdelphij 1184179895Sdelphij/* XXX LOCKSUSED */ 1185179895Sdelphij switch (cmd) { 1186179895Sdelphij case SIOCSIFFLAGS: 1187179895Sdelphij ET_LOCK(sc); 1188179895Sdelphij if (ifp->if_flags & IFF_UP) { 1189179895Sdelphij if (ifp->if_drv_flags & IFF_DRV_RUNNING) { 1190179895Sdelphij if ((ifp->if_flags ^ sc->sc_if_flags) & 1191179895Sdelphij (IFF_ALLMULTI | IFF_PROMISC | IFF_BROADCAST)) 1192179895Sdelphij et_setmulti(sc); 1193179895Sdelphij } else { 1194179895Sdelphij et_init_locked(sc); 1195179895Sdelphij } 1196179895Sdelphij } else { 1197179895Sdelphij if (ifp->if_drv_flags & IFF_DRV_RUNNING) 1198179895Sdelphij et_stop(sc); 1199179895Sdelphij } 1200179895Sdelphij sc->sc_if_flags = ifp->if_flags; 1201179895Sdelphij ET_UNLOCK(sc); 1202179895Sdelphij break; 1203179895Sdelphij 1204179895Sdelphij case SIOCSIFMEDIA: 1205179895Sdelphij case SIOCGIFMEDIA: 1206179895Sdelphij error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, cmd); 1207179895Sdelphij break; 1208179895Sdelphij 1209179895Sdelphij case SIOCADDMULTI: 1210179895Sdelphij case SIOCDELMULTI: 1211179895Sdelphij if (ifp->if_drv_flags & IFF_DRV_RUNNING) { 1212179895Sdelphij ET_LOCK(sc); 1213179895Sdelphij et_setmulti(sc); 1214179895Sdelphij ET_UNLOCK(sc); 1215179895Sdelphij error = 0; 1216179895Sdelphij } 1217179895Sdelphij break; 1218179895Sdelphij 1219179895Sdelphij case SIOCSIFMTU: 1220179895Sdelphij#if 0 1221179895Sdelphij if (sc->sc_flags & ET_FLAG_JUMBO) 1222179895Sdelphij max_framelen = ET_JUMBO_FRAMELEN; 1223179895Sdelphij else 1224179895Sdelphij#endif 1225179895Sdelphij max_framelen = MCLBYTES - 1; 1226179895Sdelphij 1227179895Sdelphij if (ET_FRAMELEN(ifr->ifr_mtu) > max_framelen) { 1228179895Sdelphij error = EOPNOTSUPP; 1229179895Sdelphij break; 1230179895Sdelphij } 1231179895Sdelphij 1232179895Sdelphij if (ifp->if_mtu != ifr->ifr_mtu) { 1233179895Sdelphij ifp->if_mtu = ifr->ifr_mtu; 1234179895Sdelphij ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 1235179895Sdelphij et_init(sc); 1236179895Sdelphij } 1237179895Sdelphij break; 1238179895Sdelphij 1239199611Syongari case SIOCSIFCAP: 1240199611Syongari ET_LOCK(sc); 1241199611Syongari mask = ifr->ifr_reqcap ^ ifp->if_capenable; 1242199611Syongari if ((mask & IFCAP_TXCSUM) != 0 && 1243199611Syongari (IFCAP_TXCSUM & ifp->if_capabilities) != 0) { 1244199611Syongari ifp->if_capenable ^= IFCAP_TXCSUM; 1245199611Syongari if ((IFCAP_TXCSUM & ifp->if_capenable) != 0) 1246199611Syongari ifp->if_hwassist |= ET_CSUM_FEATURES; 1247199611Syongari else 1248199611Syongari ifp->if_hwassist &= ~ET_CSUM_FEATURES; 1249199611Syongari } 1250199611Syongari ET_UNLOCK(sc); 1251199611Syongari break; 1252199611Syongari 1253179895Sdelphij default: 1254179895Sdelphij error = ether_ioctl(ifp, cmd, data); 1255179895Sdelphij break; 1256179895Sdelphij } 1257199556Syongari return (error); 1258179895Sdelphij} 1259179895Sdelphij 1260179895Sdelphijstatic void 1261179895Sdelphijet_start_locked(struct ifnet *ifp) 1262179895Sdelphij{ 1263179895Sdelphij struct et_softc *sc = ifp->if_softc; 1264179895Sdelphij struct et_txbuf_data *tbd; 1265179895Sdelphij int trans; 1266179895Sdelphij 1267179895Sdelphij ET_LOCK_ASSERT(sc); 1268179895Sdelphij tbd = &sc->sc_tx_data; 1269179895Sdelphij 1270179895Sdelphij if ((sc->sc_flags & ET_FLAG_TXRX_ENABLED) == 0) 1271179895Sdelphij return; 1272179895Sdelphij 1273179895Sdelphij if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) != IFF_DRV_RUNNING) 1274179895Sdelphij return; 1275179895Sdelphij 1276179895Sdelphij trans = 0; 1277179895Sdelphij for (;;) { 1278179895Sdelphij struct mbuf *m; 1279179895Sdelphij 1280179895Sdelphij if ((tbd->tbd_used + ET_NSEG_SPARE) > ET_TX_NDESC) { 1281179895Sdelphij ifp->if_drv_flags |= IFF_DRV_OACTIVE; 1282179895Sdelphij break; 1283179895Sdelphij } 1284179895Sdelphij 1285179895Sdelphij IFQ_DEQUEUE(&ifp->if_snd, m); 1286179895Sdelphij if (m == NULL) 1287179895Sdelphij break; 1288179895Sdelphij 1289179895Sdelphij if (et_encap(sc, &m)) { 1290179895Sdelphij ifp->if_oerrors++; 1291179895Sdelphij ifp->if_drv_flags |= IFF_DRV_OACTIVE; 1292179895Sdelphij break; 1293179895Sdelphij } 1294179895Sdelphij trans = 1; 1295179895Sdelphij 1296179895Sdelphij BPF_MTAP(ifp, m); 1297179895Sdelphij } 1298179895Sdelphij 1299179895Sdelphij if (trans) 1300179895Sdelphij sc->watchdog_timer = 5; 1301179895Sdelphij} 1302179895Sdelphij 1303179895Sdelphijstatic void 1304179895Sdelphijet_start(struct ifnet *ifp) 1305179895Sdelphij{ 1306179895Sdelphij struct et_softc *sc = ifp->if_softc; 1307179895Sdelphij 1308179895Sdelphij ET_LOCK(sc); 1309179895Sdelphij et_start_locked(ifp); 1310179895Sdelphij ET_UNLOCK(sc); 1311179895Sdelphij} 1312179895Sdelphij 1313179895Sdelphijstatic void 1314179895Sdelphijet_watchdog(struct et_softc *sc) 1315179895Sdelphij{ 1316179895Sdelphij ET_LOCK_ASSERT(sc); 1317179895Sdelphij 1318179895Sdelphij if (sc->watchdog_timer == 0 || --sc->watchdog_timer) 1319179895Sdelphij return; 1320179895Sdelphij 1321179895Sdelphij if_printf(sc->ifp, "watchdog timed out\n"); 1322179895Sdelphij 1323212969Syongari sc->ifp->if_oerrors++; 1324212969Syongari sc->ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 1325179895Sdelphij et_init_locked(sc); 1326179895Sdelphij et_start_locked(sc->ifp); 1327179895Sdelphij} 1328179895Sdelphij 1329179895Sdelphijstatic int 1330179895Sdelphijet_stop_rxdma(struct et_softc *sc) 1331179895Sdelphij{ 1332179895Sdelphij CSR_WRITE_4(sc, ET_RXDMA_CTRL, 1333179895Sdelphij ET_RXDMA_CTRL_HALT | ET_RXDMA_CTRL_RING1_ENABLE); 1334179895Sdelphij 1335179895Sdelphij DELAY(5); 1336179895Sdelphij if ((CSR_READ_4(sc, ET_RXDMA_CTRL) & ET_RXDMA_CTRL_HALTED) == 0) { 1337179895Sdelphij if_printf(sc->ifp, "can't stop RX DMA engine\n"); 1338199556Syongari return (ETIMEDOUT); 1339179895Sdelphij } 1340199556Syongari return (0); 1341179895Sdelphij} 1342179895Sdelphij 1343179895Sdelphijstatic int 1344179895Sdelphijet_stop_txdma(struct et_softc *sc) 1345179895Sdelphij{ 1346179895Sdelphij CSR_WRITE_4(sc, ET_TXDMA_CTRL, 1347179895Sdelphij ET_TXDMA_CTRL_HALT | ET_TXDMA_CTRL_SINGLE_EPKT); 1348199556Syongari return (0); 1349179895Sdelphij} 1350179895Sdelphij 1351179895Sdelphijstatic void 1352179895Sdelphijet_free_tx_ring(struct et_softc *sc) 1353179895Sdelphij{ 1354179895Sdelphij struct et_txbuf_data *tbd = &sc->sc_tx_data; 1355179895Sdelphij struct et_txdesc_ring *tx_ring = &sc->sc_tx_ring; 1356179895Sdelphij int i; 1357179895Sdelphij 1358179895Sdelphij for (i = 0; i < ET_TX_NDESC; ++i) { 1359179895Sdelphij struct et_txbuf *tb = &tbd->tbd_buf[i]; 1360179895Sdelphij 1361179895Sdelphij if (tb->tb_mbuf != NULL) { 1362179895Sdelphij bus_dmamap_unload(sc->sc_mbuf_dtag, tb->tb_dmap); 1363179895Sdelphij m_freem(tb->tb_mbuf); 1364179895Sdelphij tb->tb_mbuf = NULL; 1365179895Sdelphij } 1366179895Sdelphij } 1367179895Sdelphij 1368179895Sdelphij bzero(tx_ring->tr_desc, ET_TX_RING_SIZE); 1369179895Sdelphij bus_dmamap_sync(tx_ring->tr_dtag, tx_ring->tr_dmap, 1370179895Sdelphij BUS_DMASYNC_PREWRITE); 1371179895Sdelphij} 1372179895Sdelphij 1373179895Sdelphijstatic void 1374179895Sdelphijet_free_rx_ring(struct et_softc *sc) 1375179895Sdelphij{ 1376179895Sdelphij int n; 1377179895Sdelphij 1378179895Sdelphij for (n = 0; n < ET_RX_NRING; ++n) { 1379179895Sdelphij struct et_rxbuf_data *rbd = &sc->sc_rx_data[n]; 1380179895Sdelphij struct et_rxdesc_ring *rx_ring = &sc->sc_rx_ring[n]; 1381179895Sdelphij int i; 1382179895Sdelphij 1383179895Sdelphij for (i = 0; i < ET_RX_NDESC; ++i) { 1384179895Sdelphij struct et_rxbuf *rb = &rbd->rbd_buf[i]; 1385179895Sdelphij 1386179895Sdelphij if (rb->rb_mbuf != NULL) { 1387199553Syongari bus_dmamap_unload(sc->sc_mbuf_dtag, 1388180453Sdelphij rb->rb_dmap); 1389179895Sdelphij m_freem(rb->rb_mbuf); 1390179895Sdelphij rb->rb_mbuf = NULL; 1391179895Sdelphij } 1392179895Sdelphij } 1393179895Sdelphij 1394179895Sdelphij bzero(rx_ring->rr_desc, ET_RX_RING_SIZE); 1395179895Sdelphij bus_dmamap_sync(rx_ring->rr_dtag, rx_ring->rr_dmap, 1396179895Sdelphij BUS_DMASYNC_PREWRITE); 1397179895Sdelphij } 1398179895Sdelphij} 1399179895Sdelphij 1400179895Sdelphijstatic void 1401179895Sdelphijet_setmulti(struct et_softc *sc) 1402179895Sdelphij{ 1403179895Sdelphij struct ifnet *ifp; 1404179895Sdelphij uint32_t hash[4] = { 0, 0, 0, 0 }; 1405179895Sdelphij uint32_t rxmac_ctrl, pktfilt; 1406179895Sdelphij struct ifmultiaddr *ifma; 1407179895Sdelphij int i, count; 1408179895Sdelphij 1409179895Sdelphij ET_LOCK_ASSERT(sc); 1410179895Sdelphij ifp = sc->ifp; 1411179895Sdelphij 1412179895Sdelphij pktfilt = CSR_READ_4(sc, ET_PKTFILT); 1413179895Sdelphij rxmac_ctrl = CSR_READ_4(sc, ET_RXMAC_CTRL); 1414179895Sdelphij 1415179895Sdelphij pktfilt &= ~(ET_PKTFILT_BCAST | ET_PKTFILT_MCAST | ET_PKTFILT_UCAST); 1416179895Sdelphij if (ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI)) { 1417179895Sdelphij rxmac_ctrl |= ET_RXMAC_CTRL_NO_PKTFILT; 1418179895Sdelphij goto back; 1419179895Sdelphij } 1420179895Sdelphij 1421179895Sdelphij count = 0; 1422195049Srwatson if_maddr_rlock(ifp); 1423179895Sdelphij TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { 1424179895Sdelphij uint32_t *hp, h; 1425179895Sdelphij 1426179895Sdelphij if (ifma->ifma_addr->sa_family != AF_LINK) 1427179895Sdelphij continue; 1428179895Sdelphij 1429179895Sdelphij h = ether_crc32_be(LLADDR((struct sockaddr_dl *) 1430179895Sdelphij ifma->ifma_addr), ETHER_ADDR_LEN); 1431179895Sdelphij h = (h & 0x3f800000) >> 23; 1432179895Sdelphij 1433179895Sdelphij hp = &hash[0]; 1434179895Sdelphij if (h >= 32 && h < 64) { 1435179895Sdelphij h -= 32; 1436179895Sdelphij hp = &hash[1]; 1437179895Sdelphij } else if (h >= 64 && h < 96) { 1438179895Sdelphij h -= 64; 1439179895Sdelphij hp = &hash[2]; 1440179895Sdelphij } else if (h >= 96) { 1441179895Sdelphij h -= 96; 1442179895Sdelphij hp = &hash[3]; 1443179895Sdelphij } 1444179895Sdelphij *hp |= (1 << h); 1445179895Sdelphij 1446179895Sdelphij ++count; 1447179895Sdelphij } 1448195049Srwatson if_maddr_runlock(ifp); 1449179895Sdelphij 1450179895Sdelphij for (i = 0; i < 4; ++i) 1451179895Sdelphij CSR_WRITE_4(sc, ET_MULTI_HASH + (i * 4), hash[i]); 1452179895Sdelphij 1453179895Sdelphij if (count > 0) 1454179895Sdelphij pktfilt |= ET_PKTFILT_MCAST; 1455179895Sdelphij rxmac_ctrl &= ~ET_RXMAC_CTRL_NO_PKTFILT; 1456179895Sdelphijback: 1457179895Sdelphij CSR_WRITE_4(sc, ET_PKTFILT, pktfilt); 1458179895Sdelphij CSR_WRITE_4(sc, ET_RXMAC_CTRL, rxmac_ctrl); 1459179895Sdelphij} 1460179895Sdelphij 1461179895Sdelphijstatic int 1462179895Sdelphijet_chip_init(struct et_softc *sc) 1463179895Sdelphij{ 1464179895Sdelphij struct ifnet *ifp = sc->ifp; 1465179895Sdelphij uint32_t rxq_end; 1466179895Sdelphij int error, frame_len, rxmem_size; 1467179895Sdelphij 1468179895Sdelphij /* 1469179895Sdelphij * Split 16Kbytes internal memory between TX and RX 1470179895Sdelphij * according to frame length. 1471179895Sdelphij */ 1472179895Sdelphij frame_len = ET_FRAMELEN(ifp->if_mtu); 1473179895Sdelphij if (frame_len < 2048) { 1474179895Sdelphij rxmem_size = ET_MEM_RXSIZE_DEFAULT; 1475179895Sdelphij } else if (frame_len <= ET_RXMAC_CUT_THRU_FRMLEN) { 1476179895Sdelphij rxmem_size = ET_MEM_SIZE / 2; 1477179895Sdelphij } else { 1478179895Sdelphij rxmem_size = ET_MEM_SIZE - 1479179895Sdelphij roundup(frame_len + ET_MEM_TXSIZE_EX, ET_MEM_UNIT); 1480179895Sdelphij } 1481179895Sdelphij rxq_end = ET_QUEUE_ADDR(rxmem_size); 1482179895Sdelphij 1483179895Sdelphij CSR_WRITE_4(sc, ET_RXQUEUE_START, ET_QUEUE_ADDR_START); 1484179895Sdelphij CSR_WRITE_4(sc, ET_RXQUEUE_END, rxq_end); 1485179895Sdelphij CSR_WRITE_4(sc, ET_TXQUEUE_START, rxq_end + 1); 1486179895Sdelphij CSR_WRITE_4(sc, ET_TXQUEUE_END, ET_QUEUE_ADDR_END); 1487179895Sdelphij 1488179895Sdelphij /* No loopback */ 1489179895Sdelphij CSR_WRITE_4(sc, ET_LOOPBACK, 0); 1490179895Sdelphij 1491179895Sdelphij /* Clear MSI configure */ 1492199552Syongari if ((sc->sc_flags & ET_FLAG_MSI) == 0) 1493199552Syongari CSR_WRITE_4(sc, ET_MSI_CFG, 0); 1494179895Sdelphij 1495179895Sdelphij /* Disable timer */ 1496179895Sdelphij CSR_WRITE_4(sc, ET_TIMER, 0); 1497179895Sdelphij 1498179895Sdelphij /* Initialize MAC */ 1499179895Sdelphij et_init_mac(sc); 1500179895Sdelphij 1501179895Sdelphij /* Enable memory controllers */ 1502179895Sdelphij CSR_WRITE_4(sc, ET_MMC_CTRL, ET_MMC_CTRL_ENABLE); 1503179895Sdelphij 1504179895Sdelphij /* Initialize RX MAC */ 1505179895Sdelphij et_init_rxmac(sc); 1506179895Sdelphij 1507179895Sdelphij /* Initialize TX MAC */ 1508179895Sdelphij et_init_txmac(sc); 1509179895Sdelphij 1510179895Sdelphij /* Initialize RX DMA engine */ 1511179895Sdelphij error = et_init_rxdma(sc); 1512179895Sdelphij if (error) 1513199556Syongari return (error); 1514179895Sdelphij 1515179895Sdelphij /* Initialize TX DMA engine */ 1516179895Sdelphij error = et_init_txdma(sc); 1517179895Sdelphij if (error) 1518199556Syongari return (error); 1519179895Sdelphij 1520199556Syongari return (0); 1521179895Sdelphij} 1522179895Sdelphij 1523179895Sdelphijstatic int 1524179895Sdelphijet_init_tx_ring(struct et_softc *sc) 1525179895Sdelphij{ 1526179895Sdelphij struct et_txdesc_ring *tx_ring = &sc->sc_tx_ring; 1527179895Sdelphij struct et_txstatus_data *txsd = &sc->sc_tx_status; 1528179895Sdelphij struct et_txbuf_data *tbd = &sc->sc_tx_data; 1529179895Sdelphij 1530179895Sdelphij bzero(tx_ring->tr_desc, ET_TX_RING_SIZE); 1531179895Sdelphij bus_dmamap_sync(tx_ring->tr_dtag, tx_ring->tr_dmap, 1532179895Sdelphij BUS_DMASYNC_PREWRITE); 1533179895Sdelphij 1534179895Sdelphij tbd->tbd_start_index = 0; 1535179895Sdelphij tbd->tbd_start_wrap = 0; 1536179895Sdelphij tbd->tbd_used = 0; 1537179895Sdelphij 1538179895Sdelphij bzero(txsd->txsd_status, sizeof(uint32_t)); 1539179895Sdelphij bus_dmamap_sync(txsd->txsd_dtag, txsd->txsd_dmap, 1540179895Sdelphij BUS_DMASYNC_PREWRITE); 1541199556Syongari return (0); 1542179895Sdelphij} 1543179895Sdelphij 1544179895Sdelphijstatic int 1545179895Sdelphijet_init_rx_ring(struct et_softc *sc) 1546179895Sdelphij{ 1547179895Sdelphij struct et_rxstatus_data *rxsd = &sc->sc_rx_status; 1548179895Sdelphij struct et_rxstat_ring *rxst_ring = &sc->sc_rxstat_ring; 1549179895Sdelphij int n; 1550179895Sdelphij 1551179895Sdelphij for (n = 0; n < ET_RX_NRING; ++n) { 1552179895Sdelphij struct et_rxbuf_data *rbd = &sc->sc_rx_data[n]; 1553179895Sdelphij int i, error; 1554179895Sdelphij 1555179895Sdelphij for (i = 0; i < ET_RX_NDESC; ++i) { 1556179895Sdelphij error = rbd->rbd_newbuf(rbd, i, 1); 1557179895Sdelphij if (error) { 1558179895Sdelphij if_printf(sc->ifp, "%d ring %d buf, " 1559179895Sdelphij "newbuf failed: %d\n", n, i, error); 1560199556Syongari return (error); 1561179895Sdelphij } 1562179895Sdelphij } 1563179895Sdelphij } 1564179895Sdelphij 1565179895Sdelphij bzero(rxsd->rxsd_status, sizeof(struct et_rxstatus)); 1566179895Sdelphij bus_dmamap_sync(rxsd->rxsd_dtag, rxsd->rxsd_dmap, 1567179895Sdelphij BUS_DMASYNC_PREWRITE); 1568179895Sdelphij 1569179895Sdelphij bzero(rxst_ring->rsr_stat, ET_RXSTAT_RING_SIZE); 1570179895Sdelphij bus_dmamap_sync(rxst_ring->rsr_dtag, rxst_ring->rsr_dmap, 1571179895Sdelphij BUS_DMASYNC_PREWRITE); 1572179895Sdelphij 1573199556Syongari return (0); 1574179895Sdelphij} 1575179895Sdelphij 1576179895Sdelphijstatic void 1577179895Sdelphijet_dma_buf_addr(void *xctx, bus_dma_segment_t *segs, int nsegs, 1578179895Sdelphij bus_size_t mapsz __unused, int error) 1579179895Sdelphij{ 1580179895Sdelphij struct et_dmamap_ctx *ctx = xctx; 1581179895Sdelphij int i; 1582179895Sdelphij 1583179895Sdelphij if (error) 1584179895Sdelphij return; 1585179895Sdelphij 1586179895Sdelphij if (nsegs > ctx->nsegs) { 1587179895Sdelphij ctx->nsegs = 0; 1588179895Sdelphij return; 1589179895Sdelphij } 1590179895Sdelphij 1591179895Sdelphij ctx->nsegs = nsegs; 1592179895Sdelphij for (i = 0; i < nsegs; ++i) 1593179895Sdelphij ctx->segs[i] = segs[i]; 1594179895Sdelphij} 1595179895Sdelphij 1596179895Sdelphijstatic int 1597179895Sdelphijet_init_rxdma(struct et_softc *sc) 1598179895Sdelphij{ 1599179895Sdelphij struct et_rxstatus_data *rxsd = &sc->sc_rx_status; 1600179895Sdelphij struct et_rxstat_ring *rxst_ring = &sc->sc_rxstat_ring; 1601179895Sdelphij struct et_rxdesc_ring *rx_ring; 1602179895Sdelphij int error; 1603179895Sdelphij 1604179895Sdelphij error = et_stop_rxdma(sc); 1605179895Sdelphij if (error) { 1606179895Sdelphij if_printf(sc->ifp, "can't init RX DMA engine\n"); 1607199556Syongari return (error); 1608179895Sdelphij } 1609179895Sdelphij 1610179895Sdelphij /* 1611179895Sdelphij * Install RX status 1612179895Sdelphij */ 1613179895Sdelphij CSR_WRITE_4(sc, ET_RX_STATUS_HI, ET_ADDR_HI(rxsd->rxsd_paddr)); 1614179895Sdelphij CSR_WRITE_4(sc, ET_RX_STATUS_LO, ET_ADDR_LO(rxsd->rxsd_paddr)); 1615179895Sdelphij 1616179895Sdelphij /* 1617179895Sdelphij * Install RX stat ring 1618179895Sdelphij */ 1619179895Sdelphij CSR_WRITE_4(sc, ET_RXSTAT_HI, ET_ADDR_HI(rxst_ring->rsr_paddr)); 1620179895Sdelphij CSR_WRITE_4(sc, ET_RXSTAT_LO, ET_ADDR_LO(rxst_ring->rsr_paddr)); 1621179895Sdelphij CSR_WRITE_4(sc, ET_RXSTAT_CNT, ET_RX_NSTAT - 1); 1622179895Sdelphij CSR_WRITE_4(sc, ET_RXSTAT_POS, 0); 1623179895Sdelphij CSR_WRITE_4(sc, ET_RXSTAT_MINCNT, ((ET_RX_NSTAT * 15) / 100) - 1); 1624179895Sdelphij 1625179895Sdelphij /* Match ET_RXSTAT_POS */ 1626179895Sdelphij rxst_ring->rsr_index = 0; 1627179895Sdelphij rxst_ring->rsr_wrap = 0; 1628179895Sdelphij 1629179895Sdelphij /* 1630179895Sdelphij * Install the 2nd RX descriptor ring 1631179895Sdelphij */ 1632179895Sdelphij rx_ring = &sc->sc_rx_ring[1]; 1633179895Sdelphij CSR_WRITE_4(sc, ET_RX_RING1_HI, ET_ADDR_HI(rx_ring->rr_paddr)); 1634179895Sdelphij CSR_WRITE_4(sc, ET_RX_RING1_LO, ET_ADDR_LO(rx_ring->rr_paddr)); 1635179895Sdelphij CSR_WRITE_4(sc, ET_RX_RING1_CNT, ET_RX_NDESC - 1); 1636179895Sdelphij CSR_WRITE_4(sc, ET_RX_RING1_POS, ET_RX_RING1_POS_WRAP); 1637179895Sdelphij CSR_WRITE_4(sc, ET_RX_RING1_MINCNT, ((ET_RX_NDESC * 15) / 100) - 1); 1638179895Sdelphij 1639179895Sdelphij /* Match ET_RX_RING1_POS */ 1640179895Sdelphij rx_ring->rr_index = 0; 1641179895Sdelphij rx_ring->rr_wrap = 1; 1642179895Sdelphij 1643179895Sdelphij /* 1644179895Sdelphij * Install the 1st RX descriptor ring 1645179895Sdelphij */ 1646179895Sdelphij rx_ring = &sc->sc_rx_ring[0]; 1647179895Sdelphij CSR_WRITE_4(sc, ET_RX_RING0_HI, ET_ADDR_HI(rx_ring->rr_paddr)); 1648179895Sdelphij CSR_WRITE_4(sc, ET_RX_RING0_LO, ET_ADDR_LO(rx_ring->rr_paddr)); 1649179895Sdelphij CSR_WRITE_4(sc, ET_RX_RING0_CNT, ET_RX_NDESC - 1); 1650179895Sdelphij CSR_WRITE_4(sc, ET_RX_RING0_POS, ET_RX_RING0_POS_WRAP); 1651179895Sdelphij CSR_WRITE_4(sc, ET_RX_RING0_MINCNT, ((ET_RX_NDESC * 15) / 100) - 1); 1652179895Sdelphij 1653179895Sdelphij /* Match ET_RX_RING0_POS */ 1654179895Sdelphij rx_ring->rr_index = 0; 1655179895Sdelphij rx_ring->rr_wrap = 1; 1656179895Sdelphij 1657179895Sdelphij /* 1658179895Sdelphij * RX intr moderation 1659179895Sdelphij */ 1660179895Sdelphij CSR_WRITE_4(sc, ET_RX_INTR_NPKTS, sc->sc_rx_intr_npkts); 1661179895Sdelphij CSR_WRITE_4(sc, ET_RX_INTR_DELAY, sc->sc_rx_intr_delay); 1662179895Sdelphij 1663199556Syongari return (0); 1664179895Sdelphij} 1665179895Sdelphij 1666179895Sdelphijstatic int 1667179895Sdelphijet_init_txdma(struct et_softc *sc) 1668179895Sdelphij{ 1669179895Sdelphij struct et_txdesc_ring *tx_ring = &sc->sc_tx_ring; 1670179895Sdelphij struct et_txstatus_data *txsd = &sc->sc_tx_status; 1671179895Sdelphij int error; 1672179895Sdelphij 1673179895Sdelphij error = et_stop_txdma(sc); 1674179895Sdelphij if (error) { 1675179895Sdelphij if_printf(sc->ifp, "can't init TX DMA engine\n"); 1676199556Syongari return (error); 1677179895Sdelphij } 1678179895Sdelphij 1679179895Sdelphij /* 1680179895Sdelphij * Install TX descriptor ring 1681179895Sdelphij */ 1682179895Sdelphij CSR_WRITE_4(sc, ET_TX_RING_HI, ET_ADDR_HI(tx_ring->tr_paddr)); 1683179895Sdelphij CSR_WRITE_4(sc, ET_TX_RING_LO, ET_ADDR_LO(tx_ring->tr_paddr)); 1684179895Sdelphij CSR_WRITE_4(sc, ET_TX_RING_CNT, ET_TX_NDESC - 1); 1685179895Sdelphij 1686179895Sdelphij /* 1687179895Sdelphij * Install TX status 1688179895Sdelphij */ 1689179895Sdelphij CSR_WRITE_4(sc, ET_TX_STATUS_HI, ET_ADDR_HI(txsd->txsd_paddr)); 1690179895Sdelphij CSR_WRITE_4(sc, ET_TX_STATUS_LO, ET_ADDR_LO(txsd->txsd_paddr)); 1691179895Sdelphij 1692179895Sdelphij CSR_WRITE_4(sc, ET_TX_READY_POS, 0); 1693179895Sdelphij 1694179895Sdelphij /* Match ET_TX_READY_POS */ 1695179895Sdelphij tx_ring->tr_ready_index = 0; 1696179895Sdelphij tx_ring->tr_ready_wrap = 0; 1697179895Sdelphij 1698199556Syongari return (0); 1699179895Sdelphij} 1700179895Sdelphij 1701179895Sdelphijstatic void 1702179895Sdelphijet_init_mac(struct et_softc *sc) 1703179895Sdelphij{ 1704179895Sdelphij struct ifnet *ifp = sc->ifp; 1705179895Sdelphij const uint8_t *eaddr = IF_LLADDR(ifp); 1706179895Sdelphij uint32_t val; 1707179895Sdelphij 1708179895Sdelphij /* Reset MAC */ 1709179895Sdelphij CSR_WRITE_4(sc, ET_MAC_CFG1, 1710179895Sdelphij ET_MAC_CFG1_RST_TXFUNC | ET_MAC_CFG1_RST_RXFUNC | 1711179895Sdelphij ET_MAC_CFG1_RST_TXMC | ET_MAC_CFG1_RST_RXMC | 1712179895Sdelphij ET_MAC_CFG1_SIM_RST | ET_MAC_CFG1_SOFT_RST); 1713179895Sdelphij 1714179895Sdelphij /* 1715179895Sdelphij * Setup inter packet gap 1716179895Sdelphij */ 1717199548Syongari val = (56 << ET_IPG_NONB2B_1_SHIFT) | 1718199548Syongari (88 << ET_IPG_NONB2B_2_SHIFT) | 1719199548Syongari (80 << ET_IPG_MINIFG_SHIFT) | 1720199548Syongari (96 << ET_IPG_B2B_SHIFT); 1721179895Sdelphij CSR_WRITE_4(sc, ET_IPG, val); 1722179895Sdelphij 1723179895Sdelphij /* 1724179895Sdelphij * Setup half duplex mode 1725179895Sdelphij */ 1726199548Syongari val = (10 << ET_MAC_HDX_ALT_BEB_TRUNC_SHIFT) | 1727199548Syongari (15 << ET_MAC_HDX_REXMIT_MAX_SHIFT) | 1728199548Syongari (55 << ET_MAC_HDX_COLLWIN_SHIFT) | 1729199548Syongari ET_MAC_HDX_EXC_DEFER; 1730179895Sdelphij CSR_WRITE_4(sc, ET_MAC_HDX, val); 1731179895Sdelphij 1732179895Sdelphij /* Clear MAC control */ 1733179895Sdelphij CSR_WRITE_4(sc, ET_MAC_CTRL, 0); 1734179895Sdelphij 1735179895Sdelphij /* Reset MII */ 1736179895Sdelphij CSR_WRITE_4(sc, ET_MII_CFG, ET_MII_CFG_CLKRST); 1737179895Sdelphij 1738179895Sdelphij /* 1739179895Sdelphij * Set MAC address 1740179895Sdelphij */ 1741179895Sdelphij val = eaddr[2] | (eaddr[3] << 8) | (eaddr[4] << 16) | (eaddr[5] << 24); 1742179895Sdelphij CSR_WRITE_4(sc, ET_MAC_ADDR1, val); 1743179895Sdelphij val = (eaddr[0] << 16) | (eaddr[1] << 24); 1744179895Sdelphij CSR_WRITE_4(sc, ET_MAC_ADDR2, val); 1745179895Sdelphij 1746179895Sdelphij /* Set max frame length */ 1747179895Sdelphij CSR_WRITE_4(sc, ET_MAX_FRMLEN, ET_FRAMELEN(ifp->if_mtu)); 1748179895Sdelphij 1749179895Sdelphij /* Bring MAC out of reset state */ 1750179895Sdelphij CSR_WRITE_4(sc, ET_MAC_CFG1, 0); 1751179895Sdelphij} 1752179895Sdelphij 1753179895Sdelphijstatic void 1754179895Sdelphijet_init_rxmac(struct et_softc *sc) 1755179895Sdelphij{ 1756179895Sdelphij struct ifnet *ifp = sc->ifp; 1757179895Sdelphij const uint8_t *eaddr = IF_LLADDR(ifp); 1758179895Sdelphij uint32_t val; 1759179895Sdelphij int i; 1760179895Sdelphij 1761179895Sdelphij /* Disable RX MAC and WOL */ 1762179895Sdelphij CSR_WRITE_4(sc, ET_RXMAC_CTRL, ET_RXMAC_CTRL_WOL_DISABLE); 1763179895Sdelphij 1764179895Sdelphij /* 1765179895Sdelphij * Clear all WOL related registers 1766179895Sdelphij */ 1767179895Sdelphij for (i = 0; i < 3; ++i) 1768179895Sdelphij CSR_WRITE_4(sc, ET_WOL_CRC + (i * 4), 0); 1769179895Sdelphij for (i = 0; i < 20; ++i) 1770179895Sdelphij CSR_WRITE_4(sc, ET_WOL_MASK + (i * 4), 0); 1771179895Sdelphij 1772179895Sdelphij /* 1773179895Sdelphij * Set WOL source address. XXX is this necessary? 1774179895Sdelphij */ 1775179895Sdelphij val = (eaddr[2] << 24) | (eaddr[3] << 16) | (eaddr[4] << 8) | eaddr[5]; 1776179895Sdelphij CSR_WRITE_4(sc, ET_WOL_SA_LO, val); 1777179895Sdelphij val = (eaddr[0] << 8) | eaddr[1]; 1778179895Sdelphij CSR_WRITE_4(sc, ET_WOL_SA_HI, val); 1779179895Sdelphij 1780179895Sdelphij /* Clear packet filters */ 1781179895Sdelphij CSR_WRITE_4(sc, ET_PKTFILT, 0); 1782179895Sdelphij 1783179895Sdelphij /* No ucast filtering */ 1784179895Sdelphij CSR_WRITE_4(sc, ET_UCAST_FILTADDR1, 0); 1785179895Sdelphij CSR_WRITE_4(sc, ET_UCAST_FILTADDR2, 0); 1786179895Sdelphij CSR_WRITE_4(sc, ET_UCAST_FILTADDR3, 0); 1787179895Sdelphij 1788179895Sdelphij if (ET_FRAMELEN(ifp->if_mtu) > ET_RXMAC_CUT_THRU_FRMLEN) { 1789179895Sdelphij /* 1790179895Sdelphij * In order to transmit jumbo packets greater than 1791179895Sdelphij * ET_RXMAC_CUT_THRU_FRMLEN bytes, the FIFO between 1792179895Sdelphij * RX MAC and RX DMA needs to be reduced in size to 1793179895Sdelphij * (ET_MEM_SIZE - ET_MEM_TXSIZE_EX - framelen). In 1794179895Sdelphij * order to implement this, we must use "cut through" 1795179895Sdelphij * mode in the RX MAC, which chops packets down into 1796179895Sdelphij * segments. In this case we selected 256 bytes, 1797179895Sdelphij * since this is the size of the PCI-Express TLP's 1798179895Sdelphij * that the ET1310 uses. 1799179895Sdelphij */ 1800199548Syongari val = (ET_RXMAC_SEGSZ(256) & ET_RXMAC_MC_SEGSZ_MAX_MASK) | 1801179895Sdelphij ET_RXMAC_MC_SEGSZ_ENABLE; 1802179895Sdelphij } else { 1803179895Sdelphij val = 0; 1804179895Sdelphij } 1805179895Sdelphij CSR_WRITE_4(sc, ET_RXMAC_MC_SEGSZ, val); 1806179895Sdelphij 1807179895Sdelphij CSR_WRITE_4(sc, ET_RXMAC_MC_WATERMARK, 0); 1808179895Sdelphij 1809179895Sdelphij /* Initialize RX MAC management register */ 1810179895Sdelphij CSR_WRITE_4(sc, ET_RXMAC_MGT, 0); 1811179895Sdelphij 1812179895Sdelphij CSR_WRITE_4(sc, ET_RXMAC_SPACE_AVL, 0); 1813179895Sdelphij 1814179895Sdelphij CSR_WRITE_4(sc, ET_RXMAC_MGT, 1815179895Sdelphij ET_RXMAC_MGT_PASS_ECRC | 1816179895Sdelphij ET_RXMAC_MGT_PASS_ELEN | 1817179895Sdelphij ET_RXMAC_MGT_PASS_ETRUNC | 1818179895Sdelphij ET_RXMAC_MGT_CHECK_PKT); 1819179895Sdelphij 1820179895Sdelphij /* 1821179895Sdelphij * Configure runt filtering (may not work on certain chip generation) 1822179895Sdelphij */ 1823199548Syongari val = (ETHER_MIN_LEN << ET_PKTFILT_MINLEN_SHIFT) & 1824199548Syongari ET_PKTFILT_MINLEN_MASK; 1825199548Syongari val |= ET_PKTFILT_FRAG; 1826179895Sdelphij CSR_WRITE_4(sc, ET_PKTFILT, val); 1827179895Sdelphij 1828179895Sdelphij /* Enable RX MAC but leave WOL disabled */ 1829179895Sdelphij CSR_WRITE_4(sc, ET_RXMAC_CTRL, 1830179895Sdelphij ET_RXMAC_CTRL_WOL_DISABLE | ET_RXMAC_CTRL_ENABLE); 1831179895Sdelphij 1832179895Sdelphij /* 1833179895Sdelphij * Setup multicast hash and allmulti/promisc mode 1834179895Sdelphij */ 1835179895Sdelphij et_setmulti(sc); 1836179895Sdelphij} 1837179895Sdelphij 1838179895Sdelphijstatic void 1839179895Sdelphijet_init_txmac(struct et_softc *sc) 1840179895Sdelphij{ 1841179895Sdelphij /* Disable TX MAC and FC(?) */ 1842179895Sdelphij CSR_WRITE_4(sc, ET_TXMAC_CTRL, ET_TXMAC_CTRL_FC_DISABLE); 1843179895Sdelphij 1844179895Sdelphij /* No flow control yet */ 1845179895Sdelphij CSR_WRITE_4(sc, ET_TXMAC_FLOWCTRL, 0); 1846179895Sdelphij 1847179895Sdelphij /* Enable TX MAC but leave FC(?) diabled */ 1848179895Sdelphij CSR_WRITE_4(sc, ET_TXMAC_CTRL, 1849179895Sdelphij ET_TXMAC_CTRL_ENABLE | ET_TXMAC_CTRL_FC_DISABLE); 1850179895Sdelphij} 1851179895Sdelphij 1852179895Sdelphijstatic int 1853179895Sdelphijet_start_rxdma(struct et_softc *sc) 1854179895Sdelphij{ 1855179895Sdelphij uint32_t val = 0; 1856179895Sdelphij 1857199548Syongari val |= (sc->sc_rx_data[0].rbd_bufsize & ET_RXDMA_CTRL_RING0_SIZE_MASK) | 1858179895Sdelphij ET_RXDMA_CTRL_RING0_ENABLE; 1859199548Syongari val |= (sc->sc_rx_data[1].rbd_bufsize & ET_RXDMA_CTRL_RING1_SIZE_MASK) | 1860179895Sdelphij ET_RXDMA_CTRL_RING1_ENABLE; 1861179895Sdelphij 1862179895Sdelphij CSR_WRITE_4(sc, ET_RXDMA_CTRL, val); 1863179895Sdelphij 1864179895Sdelphij DELAY(5); 1865179895Sdelphij 1866179895Sdelphij if (CSR_READ_4(sc, ET_RXDMA_CTRL) & ET_RXDMA_CTRL_HALTED) { 1867179895Sdelphij if_printf(sc->ifp, "can't start RX DMA engine\n"); 1868199556Syongari return (ETIMEDOUT); 1869179895Sdelphij } 1870199556Syongari return (0); 1871179895Sdelphij} 1872179895Sdelphij 1873179895Sdelphijstatic int 1874179895Sdelphijet_start_txdma(struct et_softc *sc) 1875179895Sdelphij{ 1876179895Sdelphij CSR_WRITE_4(sc, ET_TXDMA_CTRL, ET_TXDMA_CTRL_SINGLE_EPKT); 1877199556Syongari return (0); 1878179895Sdelphij} 1879179895Sdelphij 1880179895Sdelphijstatic int 1881179895Sdelphijet_enable_txrx(struct et_softc *sc, int media_upd) 1882179895Sdelphij{ 1883179895Sdelphij struct ifnet *ifp = sc->ifp; 1884179895Sdelphij uint32_t val; 1885179895Sdelphij int i, error; 1886179895Sdelphij 1887179895Sdelphij val = CSR_READ_4(sc, ET_MAC_CFG1); 1888179895Sdelphij val |= ET_MAC_CFG1_TXEN | ET_MAC_CFG1_RXEN; 1889179895Sdelphij val &= ~(ET_MAC_CFG1_TXFLOW | ET_MAC_CFG1_RXFLOW | 1890179895Sdelphij ET_MAC_CFG1_LOOPBACK); 1891179895Sdelphij CSR_WRITE_4(sc, ET_MAC_CFG1, val); 1892179895Sdelphij 1893179895Sdelphij if (media_upd) 1894179895Sdelphij et_ifmedia_upd_locked(ifp); 1895179895Sdelphij else 1896179895Sdelphij et_setmedia(sc); 1897179895Sdelphij 1898179895Sdelphij#define NRETRY 50 1899179895Sdelphij 1900179895Sdelphij for (i = 0; i < NRETRY; ++i) { 1901179895Sdelphij val = CSR_READ_4(sc, ET_MAC_CFG1); 1902179895Sdelphij if ((val & (ET_MAC_CFG1_SYNC_TXEN | ET_MAC_CFG1_SYNC_RXEN)) == 1903179895Sdelphij (ET_MAC_CFG1_SYNC_TXEN | ET_MAC_CFG1_SYNC_RXEN)) 1904179895Sdelphij break; 1905179895Sdelphij 1906179895Sdelphij DELAY(100); 1907179895Sdelphij } 1908179895Sdelphij if (i == NRETRY) { 1909179895Sdelphij if_printf(ifp, "can't enable RX/TX\n"); 1910199556Syongari return (0); 1911179895Sdelphij } 1912179895Sdelphij sc->sc_flags |= ET_FLAG_TXRX_ENABLED; 1913179895Sdelphij 1914179895Sdelphij#undef NRETRY 1915179895Sdelphij 1916179895Sdelphij /* 1917179895Sdelphij * Start TX/RX DMA engine 1918179895Sdelphij */ 1919179895Sdelphij error = et_start_rxdma(sc); 1920179895Sdelphij if (error) 1921199556Syongari return (error); 1922179895Sdelphij 1923179895Sdelphij error = et_start_txdma(sc); 1924179895Sdelphij if (error) 1925199556Syongari return (error); 1926179895Sdelphij 1927199556Syongari return (0); 1928179895Sdelphij} 1929179895Sdelphij 1930179895Sdelphijstatic void 1931179895Sdelphijet_rxeof(struct et_softc *sc) 1932179895Sdelphij{ 1933179895Sdelphij struct ifnet *ifp; 1934179895Sdelphij struct et_rxstatus_data *rxsd; 1935179895Sdelphij struct et_rxstat_ring *rxst_ring; 1936199609Syongari uint32_t rxs_stat_ring, rxst_info2; 1937179895Sdelphij int rxst_wrap, rxst_index; 1938179895Sdelphij 1939179895Sdelphij ET_LOCK_ASSERT(sc); 1940179895Sdelphij ifp = sc->ifp; 1941179895Sdelphij rxsd = &sc->sc_rx_status; 1942179895Sdelphij rxst_ring = &sc->sc_rxstat_ring; 1943179895Sdelphij 1944179895Sdelphij if ((sc->sc_flags & ET_FLAG_TXRX_ENABLED) == 0) 1945179895Sdelphij return; 1946179895Sdelphij 1947179895Sdelphij bus_dmamap_sync(rxsd->rxsd_dtag, rxsd->rxsd_dmap, 1948179895Sdelphij BUS_DMASYNC_POSTREAD); 1949179895Sdelphij bus_dmamap_sync(rxst_ring->rsr_dtag, rxst_ring->rsr_dmap, 1950179895Sdelphij BUS_DMASYNC_POSTREAD); 1951179895Sdelphij 1952199609Syongari rxs_stat_ring = le32toh(rxsd->rxsd_status->rxs_stat_ring); 1953179895Sdelphij rxst_wrap = (rxs_stat_ring & ET_RXS_STATRING_WRAP) ? 1 : 0; 1954199548Syongari rxst_index = (rxs_stat_ring & ET_RXS_STATRING_INDEX_MASK) >> 1955199548Syongari ET_RXS_STATRING_INDEX_SHIFT; 1956179895Sdelphij 1957179895Sdelphij while (rxst_index != rxst_ring->rsr_index || 1958179895Sdelphij rxst_wrap != rxst_ring->rsr_wrap) { 1959179895Sdelphij struct et_rxbuf_data *rbd; 1960179895Sdelphij struct et_rxdesc_ring *rx_ring; 1961179895Sdelphij struct et_rxstat *st; 1962179895Sdelphij struct mbuf *m; 1963179895Sdelphij int buflen, buf_idx, ring_idx; 1964179895Sdelphij uint32_t rxstat_pos, rxring_pos; 1965179895Sdelphij 1966179895Sdelphij MPASS(rxst_ring->rsr_index < ET_RX_NSTAT); 1967179895Sdelphij st = &rxst_ring->rsr_stat[rxst_ring->rsr_index]; 1968199609Syongari rxst_info2 = le32toh(st->rxst_info2); 1969199609Syongari buflen = (rxst_info2 & ET_RXST_INFO2_LEN_MASK) >> 1970199548Syongari ET_RXST_INFO2_LEN_SHIFT; 1971199609Syongari buf_idx = (rxst_info2 & ET_RXST_INFO2_BUFIDX_MASK) >> 1972199548Syongari ET_RXST_INFO2_BUFIDX_SHIFT; 1973199609Syongari ring_idx = (rxst_info2 & ET_RXST_INFO2_RINGIDX_MASK) >> 1974199548Syongari ET_RXST_INFO2_RINGIDX_SHIFT; 1975179895Sdelphij 1976179895Sdelphij if (++rxst_ring->rsr_index == ET_RX_NSTAT) { 1977179895Sdelphij rxst_ring->rsr_index = 0; 1978179895Sdelphij rxst_ring->rsr_wrap ^= 1; 1979179895Sdelphij } 1980199548Syongari rxstat_pos = rxst_ring->rsr_index & ET_RXSTAT_POS_INDEX_MASK; 1981179895Sdelphij if (rxst_ring->rsr_wrap) 1982179895Sdelphij rxstat_pos |= ET_RXSTAT_POS_WRAP; 1983179895Sdelphij CSR_WRITE_4(sc, ET_RXSTAT_POS, rxstat_pos); 1984179895Sdelphij 1985179895Sdelphij if (ring_idx >= ET_RX_NRING) { 1986179895Sdelphij ifp->if_ierrors++; 1987179895Sdelphij if_printf(ifp, "invalid ring index %d\n", ring_idx); 1988179895Sdelphij continue; 1989179895Sdelphij } 1990179895Sdelphij if (buf_idx >= ET_RX_NDESC) { 1991179895Sdelphij ifp->if_ierrors++; 1992179895Sdelphij if_printf(ifp, "invalid buf index %d\n", buf_idx); 1993179895Sdelphij continue; 1994179895Sdelphij } 1995179895Sdelphij 1996179895Sdelphij rbd = &sc->sc_rx_data[ring_idx]; 1997179895Sdelphij m = rbd->rbd_buf[buf_idx].rb_mbuf; 1998179895Sdelphij 1999179895Sdelphij if (rbd->rbd_newbuf(rbd, buf_idx, 0) == 0) { 2000179895Sdelphij if (buflen < ETHER_CRC_LEN) { 2001179895Sdelphij m_freem(m); 2002179895Sdelphij m = NULL; 2003179895Sdelphij ifp->if_ierrors++; 2004179895Sdelphij } else { 2005199610Syongari m->m_pkthdr.len = m->m_len = 2006199610Syongari buflen - ETHER_CRC_LEN; 2007179895Sdelphij m->m_pkthdr.rcvif = ifp; 2008179895Sdelphij ifp->if_ipackets++; 2009179895Sdelphij ET_UNLOCK(sc); 2010179895Sdelphij ifp->if_input(ifp, m); 2011179895Sdelphij ET_LOCK(sc); 2012179895Sdelphij } 2013179895Sdelphij } else { 2014179895Sdelphij ifp->if_ierrors++; 2015179895Sdelphij } 2016179895Sdelphij m = NULL; /* Catch invalid reference */ 2017179895Sdelphij 2018179895Sdelphij rx_ring = &sc->sc_rx_ring[ring_idx]; 2019179895Sdelphij 2020179895Sdelphij if (buf_idx != rx_ring->rr_index) { 2021179895Sdelphij if_printf(ifp, "WARNING!! ring %d, " 2022179895Sdelphij "buf_idx %d, rr_idx %d\n", 2023179895Sdelphij ring_idx, buf_idx, rx_ring->rr_index); 2024179895Sdelphij } 2025179895Sdelphij 2026179895Sdelphij MPASS(rx_ring->rr_index < ET_RX_NDESC); 2027179895Sdelphij if (++rx_ring->rr_index == ET_RX_NDESC) { 2028179895Sdelphij rx_ring->rr_index = 0; 2029179895Sdelphij rx_ring->rr_wrap ^= 1; 2030179895Sdelphij } 2031199548Syongari rxring_pos = rx_ring->rr_index & ET_RX_RING_POS_INDEX_MASK; 2032179895Sdelphij if (rx_ring->rr_wrap) 2033179895Sdelphij rxring_pos |= ET_RX_RING_POS_WRAP; 2034179895Sdelphij CSR_WRITE_4(sc, rx_ring->rr_posreg, rxring_pos); 2035179895Sdelphij } 2036179895Sdelphij} 2037179895Sdelphij 2038179895Sdelphijstatic int 2039179895Sdelphijet_encap(struct et_softc *sc, struct mbuf **m0) 2040179895Sdelphij{ 2041179895Sdelphij struct mbuf *m = *m0; 2042179895Sdelphij bus_dma_segment_t segs[ET_NSEG_MAX]; 2043179895Sdelphij struct et_dmamap_ctx ctx; 2044179895Sdelphij struct et_txdesc_ring *tx_ring = &sc->sc_tx_ring; 2045179895Sdelphij struct et_txbuf_data *tbd = &sc->sc_tx_data; 2046179895Sdelphij struct et_txdesc *td; 2047179895Sdelphij bus_dmamap_t map; 2048179895Sdelphij int error, maxsegs, first_idx, last_idx, i; 2049199611Syongari uint32_t csum_flags, tx_ready_pos, last_td_ctrl2; 2050179895Sdelphij 2051179895Sdelphij maxsegs = ET_TX_NDESC - tbd->tbd_used; 2052179895Sdelphij if (maxsegs > ET_NSEG_MAX) 2053179895Sdelphij maxsegs = ET_NSEG_MAX; 2054179895Sdelphij KASSERT(maxsegs >= ET_NSEG_SPARE, 2055179895Sdelphij ("not enough spare TX desc (%d)\n", maxsegs)); 2056179895Sdelphij 2057179895Sdelphij MPASS(tx_ring->tr_ready_index < ET_TX_NDESC); 2058179895Sdelphij first_idx = tx_ring->tr_ready_index; 2059179895Sdelphij map = tbd->tbd_buf[first_idx].tb_dmap; 2060179895Sdelphij 2061179895Sdelphij ctx.nsegs = maxsegs; 2062179895Sdelphij ctx.segs = segs; 2063179895Sdelphij error = bus_dmamap_load_mbuf(sc->sc_mbuf_dtag, map, m, 2064179895Sdelphij et_dma_buf_addr, &ctx, BUS_DMA_NOWAIT); 2065179895Sdelphij if (!error && ctx.nsegs == 0) { 2066179895Sdelphij bus_dmamap_unload(sc->sc_mbuf_dtag, map); 2067179895Sdelphij error = EFBIG; 2068179895Sdelphij } 2069179895Sdelphij if (error && error != EFBIG) { 2070179895Sdelphij if_printf(sc->ifp, "can't load TX mbuf, error %d\n", 2071179895Sdelphij error); 2072179895Sdelphij goto back; 2073179895Sdelphij } 2074179895Sdelphij if (error) { /* error == EFBIG */ 2075179895Sdelphij struct mbuf *m_new; 2076179895Sdelphij 2077179895Sdelphij m_new = m_defrag(m, M_DONTWAIT); 2078179895Sdelphij if (m_new == NULL) { 2079179895Sdelphij if_printf(sc->ifp, "can't defrag TX mbuf\n"); 2080179895Sdelphij error = ENOBUFS; 2081179895Sdelphij goto back; 2082179895Sdelphij } else { 2083179895Sdelphij *m0 = m = m_new; 2084179895Sdelphij } 2085179895Sdelphij 2086179895Sdelphij ctx.nsegs = maxsegs; 2087179895Sdelphij ctx.segs = segs; 2088179895Sdelphij error = bus_dmamap_load_mbuf(sc->sc_mbuf_dtag, map, m, 2089179895Sdelphij et_dma_buf_addr, &ctx, 2090179895Sdelphij BUS_DMA_NOWAIT); 2091179895Sdelphij if (error || ctx.nsegs == 0) { 2092179895Sdelphij if (ctx.nsegs == 0) { 2093179895Sdelphij bus_dmamap_unload(sc->sc_mbuf_dtag, map); 2094179895Sdelphij error = EFBIG; 2095179895Sdelphij } 2096179895Sdelphij if_printf(sc->ifp, 2097179895Sdelphij "can't load defraged TX mbuf\n"); 2098179895Sdelphij goto back; 2099179895Sdelphij } 2100179895Sdelphij } 2101179895Sdelphij 2102179895Sdelphij bus_dmamap_sync(sc->sc_mbuf_dtag, map, BUS_DMASYNC_PREWRITE); 2103179895Sdelphij 2104179895Sdelphij last_td_ctrl2 = ET_TDCTRL2_LAST_FRAG; 2105179895Sdelphij sc->sc_tx += ctx.nsegs; 2106179895Sdelphij if (sc->sc_tx / sc->sc_tx_intr_nsegs != sc->sc_tx_intr) { 2107179895Sdelphij sc->sc_tx_intr = sc->sc_tx / sc->sc_tx_intr_nsegs; 2108179895Sdelphij last_td_ctrl2 |= ET_TDCTRL2_INTR; 2109179895Sdelphij } 2110179895Sdelphij 2111199611Syongari csum_flags = 0; 2112199611Syongari if ((m->m_pkthdr.csum_flags & ET_CSUM_FEATURES) != 0) { 2113199611Syongari if ((m->m_pkthdr.csum_flags & CSUM_IP) != 0) 2114199611Syongari csum_flags |= ET_TDCTRL2_CSUM_IP; 2115199611Syongari if ((m->m_pkthdr.csum_flags & CSUM_UDP) != 0) 2116199611Syongari csum_flags |= ET_TDCTRL2_CSUM_UDP; 2117199611Syongari else if ((m->m_pkthdr.csum_flags & CSUM_TCP) != 0) 2118199611Syongari csum_flags |= ET_TDCTRL2_CSUM_TCP; 2119199611Syongari } 2120179895Sdelphij last_idx = -1; 2121179895Sdelphij for (i = 0; i < ctx.nsegs; ++i) { 2122179895Sdelphij int idx; 2123179895Sdelphij 2124179895Sdelphij idx = (first_idx + i) % ET_TX_NDESC; 2125179895Sdelphij td = &tx_ring->tr_desc[idx]; 2126199609Syongari td->td_addr_hi = htole32(ET_ADDR_HI(segs[i].ds_addr)); 2127199609Syongari td->td_addr_lo = htole32(ET_ADDR_LO(segs[i].ds_addr)); 2128199609Syongari td->td_ctrl1 = htole32(segs[i].ds_len & ET_TDCTRL1_LEN_MASK); 2129179895Sdelphij if (i == ctx.nsegs - 1) { /* Last frag */ 2130199611Syongari td->td_ctrl2 = htole32(last_td_ctrl2 | csum_flags); 2131179895Sdelphij last_idx = idx; 2132199611Syongari } else 2133199611Syongari td->td_ctrl2 = htole32(csum_flags); 2134179895Sdelphij 2135179895Sdelphij MPASS(tx_ring->tr_ready_index < ET_TX_NDESC); 2136179895Sdelphij if (++tx_ring->tr_ready_index == ET_TX_NDESC) { 2137179895Sdelphij tx_ring->tr_ready_index = 0; 2138179895Sdelphij tx_ring->tr_ready_wrap ^= 1; 2139179895Sdelphij } 2140179895Sdelphij } 2141179895Sdelphij td = &tx_ring->tr_desc[first_idx]; 2142199609Syongari td->td_ctrl2 |= htole32(ET_TDCTRL2_FIRST_FRAG); /* First frag */ 2143179895Sdelphij 2144179895Sdelphij MPASS(last_idx >= 0); 2145179895Sdelphij tbd->tbd_buf[first_idx].tb_dmap = tbd->tbd_buf[last_idx].tb_dmap; 2146179895Sdelphij tbd->tbd_buf[last_idx].tb_dmap = map; 2147179895Sdelphij tbd->tbd_buf[last_idx].tb_mbuf = m; 2148179895Sdelphij 2149179895Sdelphij tbd->tbd_used += ctx.nsegs; 2150179895Sdelphij MPASS(tbd->tbd_used <= ET_TX_NDESC); 2151179895Sdelphij 2152179895Sdelphij bus_dmamap_sync(tx_ring->tr_dtag, tx_ring->tr_dmap, 2153179895Sdelphij BUS_DMASYNC_PREWRITE); 2154179895Sdelphij 2155199548Syongari tx_ready_pos = tx_ring->tr_ready_index & ET_TX_READY_POS_INDEX_MASK; 2156179895Sdelphij if (tx_ring->tr_ready_wrap) 2157179895Sdelphij tx_ready_pos |= ET_TX_READY_POS_WRAP; 2158179895Sdelphij CSR_WRITE_4(sc, ET_TX_READY_POS, tx_ready_pos); 2159179895Sdelphij 2160179895Sdelphij error = 0; 2161179895Sdelphijback: 2162179895Sdelphij if (error) { 2163179895Sdelphij m_freem(m); 2164179895Sdelphij *m0 = NULL; 2165179895Sdelphij } 2166199556Syongari return (error); 2167179895Sdelphij} 2168179895Sdelphij 2169179895Sdelphijstatic void 2170179895Sdelphijet_txeof(struct et_softc *sc) 2171179895Sdelphij{ 2172179895Sdelphij struct ifnet *ifp; 2173179895Sdelphij struct et_txdesc_ring *tx_ring; 2174179895Sdelphij struct et_txbuf_data *tbd; 2175179895Sdelphij uint32_t tx_done; 2176179895Sdelphij int end, wrap; 2177179895Sdelphij 2178179895Sdelphij ET_LOCK_ASSERT(sc); 2179179895Sdelphij ifp = sc->ifp; 2180179895Sdelphij tx_ring = &sc->sc_tx_ring; 2181179895Sdelphij tbd = &sc->sc_tx_data; 2182179895Sdelphij 2183179895Sdelphij if ((sc->sc_flags & ET_FLAG_TXRX_ENABLED) == 0) 2184179895Sdelphij return; 2185179895Sdelphij 2186179895Sdelphij if (tbd->tbd_used == 0) 2187179895Sdelphij return; 2188179895Sdelphij 2189179895Sdelphij tx_done = CSR_READ_4(sc, ET_TX_DONE_POS); 2190199548Syongari end = tx_done & ET_TX_DONE_POS_INDEX_MASK; 2191179895Sdelphij wrap = (tx_done & ET_TX_DONE_POS_WRAP) ? 1 : 0; 2192179895Sdelphij 2193179895Sdelphij while (tbd->tbd_start_index != end || tbd->tbd_start_wrap != wrap) { 2194179895Sdelphij struct et_txbuf *tb; 2195179895Sdelphij 2196179895Sdelphij MPASS(tbd->tbd_start_index < ET_TX_NDESC); 2197179895Sdelphij tb = &tbd->tbd_buf[tbd->tbd_start_index]; 2198179895Sdelphij 2199179895Sdelphij bzero(&tx_ring->tr_desc[tbd->tbd_start_index], 2200179895Sdelphij sizeof(struct et_txdesc)); 2201179895Sdelphij bus_dmamap_sync(tx_ring->tr_dtag, tx_ring->tr_dmap, 2202179895Sdelphij BUS_DMASYNC_PREWRITE); 2203179895Sdelphij 2204179895Sdelphij if (tb->tb_mbuf != NULL) { 2205179895Sdelphij bus_dmamap_unload(sc->sc_mbuf_dtag, tb->tb_dmap); 2206179895Sdelphij m_freem(tb->tb_mbuf); 2207179895Sdelphij tb->tb_mbuf = NULL; 2208179895Sdelphij ifp->if_opackets++; 2209179895Sdelphij } 2210179895Sdelphij 2211179895Sdelphij if (++tbd->tbd_start_index == ET_TX_NDESC) { 2212179895Sdelphij tbd->tbd_start_index = 0; 2213179895Sdelphij tbd->tbd_start_wrap ^= 1; 2214179895Sdelphij } 2215179895Sdelphij 2216179895Sdelphij MPASS(tbd->tbd_used > 0); 2217179895Sdelphij tbd->tbd_used--; 2218179895Sdelphij } 2219179895Sdelphij 2220179895Sdelphij if (tbd->tbd_used == 0) 2221179895Sdelphij sc->watchdog_timer = 0; 2222179895Sdelphij if (tbd->tbd_used + ET_NSEG_SPARE <= ET_TX_NDESC) 2223179895Sdelphij ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 2224179895Sdelphij 2225179895Sdelphij et_start_locked(ifp); 2226179895Sdelphij} 2227179895Sdelphij 2228179895Sdelphijstatic void 2229179895Sdelphijet_tick(void *xsc) 2230179895Sdelphij{ 2231179895Sdelphij struct et_softc *sc = xsc; 2232179895Sdelphij struct ifnet *ifp; 2233179895Sdelphij struct mii_data *mii; 2234179895Sdelphij 2235179895Sdelphij ET_LOCK_ASSERT(sc); 2236179895Sdelphij ifp = sc->ifp; 2237179895Sdelphij mii = device_get_softc(sc->sc_miibus); 2238179895Sdelphij 2239179895Sdelphij mii_tick(mii); 2240179895Sdelphij if ((sc->sc_flags & ET_FLAG_TXRX_ENABLED) == 0 && 2241179895Sdelphij (mii->mii_media_status & IFM_ACTIVE) && 2242179895Sdelphij IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) { 2243179895Sdelphij if_printf(ifp, "Link up, enable TX/RX\n"); 2244179895Sdelphij if (et_enable_txrx(sc, 0) == 0) 2245179895Sdelphij et_start_locked(ifp); 2246179895Sdelphij } 2247179895Sdelphij et_watchdog(sc); 2248179895Sdelphij callout_reset(&sc->sc_tick, hz, et_tick, sc); 2249179895Sdelphij} 2250179895Sdelphij 2251179895Sdelphijstatic int 2252179895Sdelphijet_newbuf_cluster(struct et_rxbuf_data *rbd, int buf_idx, int init) 2253179895Sdelphij{ 2254199556Syongari return (et_newbuf(rbd, buf_idx, init, MCLBYTES)); 2255179895Sdelphij} 2256179895Sdelphij 2257179895Sdelphijstatic int 2258179895Sdelphijet_newbuf_hdr(struct et_rxbuf_data *rbd, int buf_idx, int init) 2259179895Sdelphij{ 2260199556Syongari return (et_newbuf(rbd, buf_idx, init, MHLEN)); 2261179895Sdelphij} 2262179895Sdelphij 2263179895Sdelphijstatic int 2264179895Sdelphijet_newbuf(struct et_rxbuf_data *rbd, int buf_idx, int init, int len0) 2265179895Sdelphij{ 2266179895Sdelphij struct et_softc *sc = rbd->rbd_softc; 2267179895Sdelphij struct et_rxbuf *rb; 2268179895Sdelphij struct mbuf *m; 2269179895Sdelphij struct et_dmamap_ctx ctx; 2270179895Sdelphij bus_dma_segment_t seg; 2271179895Sdelphij bus_dmamap_t dmap; 2272179895Sdelphij int error, len; 2273179895Sdelphij 2274179895Sdelphij MPASS(buf_idx < ET_RX_NDESC); 2275179895Sdelphij rb = &rbd->rbd_buf[buf_idx]; 2276179895Sdelphij 2277179895Sdelphij m = m_getl(len0, /* init ? M_WAIT :*/ M_DONTWAIT, MT_DATA, M_PKTHDR, &len); 2278179895Sdelphij if (m == NULL) { 2279179895Sdelphij error = ENOBUFS; 2280179895Sdelphij 2281179895Sdelphij if (init) { 2282179895Sdelphij if_printf(sc->ifp, 2283179895Sdelphij "m_getl failed, size %d\n", len0); 2284199556Syongari return (error); 2285179895Sdelphij } else { 2286179895Sdelphij goto back; 2287179895Sdelphij } 2288179895Sdelphij } 2289179895Sdelphij m->m_len = m->m_pkthdr.len = len; 2290179895Sdelphij 2291179895Sdelphij /* 2292179895Sdelphij * Try load RX mbuf into temporary DMA tag 2293179895Sdelphij */ 2294179895Sdelphij ctx.nsegs = 1; 2295179895Sdelphij ctx.segs = &seg; 2296179895Sdelphij error = bus_dmamap_load_mbuf(sc->sc_mbuf_dtag, sc->sc_mbuf_tmp_dmap, m, 2297179895Sdelphij et_dma_buf_addr, &ctx, 2298179895Sdelphij init ? BUS_DMA_WAITOK : BUS_DMA_NOWAIT); 2299179895Sdelphij if (error || ctx.nsegs == 0) { 2300179895Sdelphij if (!error) { 2301179895Sdelphij bus_dmamap_unload(sc->sc_mbuf_dtag, 2302179895Sdelphij sc->sc_mbuf_tmp_dmap); 2303179895Sdelphij error = EFBIG; 2304179895Sdelphij if_printf(sc->ifp, "too many segments?!\n"); 2305179895Sdelphij } 2306179895Sdelphij m_freem(m); 2307179895Sdelphij m = NULL; 2308179895Sdelphij 2309179895Sdelphij if (init) { 2310179895Sdelphij if_printf(sc->ifp, "can't load RX mbuf\n"); 2311199556Syongari return (error); 2312179895Sdelphij } else { 2313179895Sdelphij goto back; 2314179895Sdelphij } 2315179895Sdelphij } 2316179895Sdelphij 2317179895Sdelphij if (!init) { 2318179895Sdelphij bus_dmamap_sync(sc->sc_mbuf_dtag, rb->rb_dmap, 2319179895Sdelphij BUS_DMASYNC_POSTREAD); 2320179895Sdelphij bus_dmamap_unload(sc->sc_mbuf_dtag, rb->rb_dmap); 2321179895Sdelphij } 2322179895Sdelphij rb->rb_mbuf = m; 2323179895Sdelphij rb->rb_paddr = seg.ds_addr; 2324179895Sdelphij 2325179895Sdelphij /* 2326179895Sdelphij * Swap RX buf's DMA map with the loaded temporary one 2327179895Sdelphij */ 2328179895Sdelphij dmap = rb->rb_dmap; 2329179895Sdelphij rb->rb_dmap = sc->sc_mbuf_tmp_dmap; 2330179895Sdelphij sc->sc_mbuf_tmp_dmap = dmap; 2331179895Sdelphij 2332179895Sdelphij error = 0; 2333179895Sdelphijback: 2334179895Sdelphij et_setup_rxdesc(rbd, buf_idx, rb->rb_paddr); 2335199556Syongari return (error); 2336179895Sdelphij} 2337179895Sdelphij 2338179895Sdelphij/* 2339179895Sdelphij * Create sysctl tree 2340179895Sdelphij */ 2341179895Sdelphijstatic void 2342179895Sdelphijet_add_sysctls(struct et_softc * sc) 2343179895Sdelphij{ 2344179895Sdelphij struct sysctl_ctx_list *ctx; 2345179895Sdelphij struct sysctl_oid_list *children; 2346179895Sdelphij 2347179895Sdelphij ctx = device_get_sysctl_ctx(sc->dev); 2348179895Sdelphij children = SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)); 2349179895Sdelphij 2350179895Sdelphij SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "rx_intr_npkts", 2351179895Sdelphij CTLTYPE_INT | CTLFLAG_RW, sc, 0, et_sysctl_rx_intr_npkts, "I", 2352179895Sdelphij "RX IM, # packets per RX interrupt"); 2353179895Sdelphij SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "rx_intr_delay", 2354179895Sdelphij CTLTYPE_INT | CTLFLAG_RW, sc, 0, et_sysctl_rx_intr_delay, "I", 2355179895Sdelphij "RX IM, RX interrupt delay (x10 usec)"); 2356179895Sdelphij SYSCTL_ADD_INT(ctx, children, OID_AUTO, "tx_intr_nsegs", 2357179895Sdelphij CTLFLAG_RW, &sc->sc_tx_intr_nsegs, 0, 2358179895Sdelphij "TX IM, # segments per TX interrupt"); 2359179895Sdelphij SYSCTL_ADD_UINT(ctx, children, OID_AUTO, "timer", 2360179895Sdelphij CTLFLAG_RW, &sc->sc_timer, 0, "TX timer"); 2361179895Sdelphij} 2362179895Sdelphij 2363179895Sdelphijstatic int 2364179895Sdelphijet_sysctl_rx_intr_npkts(SYSCTL_HANDLER_ARGS) 2365179895Sdelphij{ 2366179895Sdelphij struct et_softc *sc = arg1; 2367179895Sdelphij struct ifnet *ifp = sc->ifp; 2368179895Sdelphij int error = 0, v; 2369179895Sdelphij 2370179895Sdelphij v = sc->sc_rx_intr_npkts; 2371179895Sdelphij error = sysctl_handle_int(oidp, &v, 0, req); 2372179895Sdelphij if (error || req->newptr == NULL) 2373179895Sdelphij goto back; 2374179895Sdelphij if (v <= 0) { 2375179895Sdelphij error = EINVAL; 2376179895Sdelphij goto back; 2377179895Sdelphij } 2378179895Sdelphij 2379179895Sdelphij if (sc->sc_rx_intr_npkts != v) { 2380179895Sdelphij if (ifp->if_drv_flags & IFF_DRV_RUNNING) 2381179895Sdelphij CSR_WRITE_4(sc, ET_RX_INTR_NPKTS, v); 2382179895Sdelphij sc->sc_rx_intr_npkts = v; 2383179895Sdelphij } 2384179895Sdelphijback: 2385199556Syongari return (error); 2386179895Sdelphij} 2387179895Sdelphij 2388179895Sdelphijstatic int 2389179895Sdelphijet_sysctl_rx_intr_delay(SYSCTL_HANDLER_ARGS) 2390179895Sdelphij{ 2391179895Sdelphij struct et_softc *sc = arg1; 2392179895Sdelphij struct ifnet *ifp = sc->ifp; 2393179895Sdelphij int error = 0, v; 2394179895Sdelphij 2395179895Sdelphij v = sc->sc_rx_intr_delay; 2396179895Sdelphij error = sysctl_handle_int(oidp, &v, 0, req); 2397179895Sdelphij if (error || req->newptr == NULL) 2398179895Sdelphij goto back; 2399179895Sdelphij if (v <= 0) { 2400179895Sdelphij error = EINVAL; 2401179895Sdelphij goto back; 2402179895Sdelphij } 2403179895Sdelphij 2404179895Sdelphij if (sc->sc_rx_intr_delay != v) { 2405179895Sdelphij if (ifp->if_drv_flags & IFF_DRV_RUNNING) 2406179895Sdelphij CSR_WRITE_4(sc, ET_RX_INTR_DELAY, v); 2407179895Sdelphij sc->sc_rx_intr_delay = v; 2408179895Sdelphij } 2409179895Sdelphijback: 2410199556Syongari return (error); 2411179895Sdelphij} 2412179895Sdelphij 2413179895Sdelphijstatic void 2414179895Sdelphijet_setmedia(struct et_softc *sc) 2415179895Sdelphij{ 2416179895Sdelphij struct mii_data *mii = device_get_softc(sc->sc_miibus); 2417179895Sdelphij uint32_t cfg2, ctrl; 2418179895Sdelphij 2419179895Sdelphij cfg2 = CSR_READ_4(sc, ET_MAC_CFG2); 2420179895Sdelphij cfg2 &= ~(ET_MAC_CFG2_MODE_MII | ET_MAC_CFG2_MODE_GMII | 2421179895Sdelphij ET_MAC_CFG2_FDX | ET_MAC_CFG2_BIGFRM); 2422179895Sdelphij cfg2 |= ET_MAC_CFG2_LENCHK | ET_MAC_CFG2_CRC | ET_MAC_CFG2_PADCRC | 2423199548Syongari ((7 << ET_MAC_CFG2_PREAMBLE_LEN_SHIFT) & 2424199548Syongari ET_MAC_CFG2_PREAMBLE_LEN_MASK); 2425179895Sdelphij 2426179895Sdelphij ctrl = CSR_READ_4(sc, ET_MAC_CTRL); 2427179895Sdelphij ctrl &= ~(ET_MAC_CTRL_GHDX | ET_MAC_CTRL_MODE_MII); 2428179895Sdelphij 2429179895Sdelphij if (IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_T) { 2430179895Sdelphij cfg2 |= ET_MAC_CFG2_MODE_GMII; 2431179895Sdelphij } else { 2432179895Sdelphij cfg2 |= ET_MAC_CFG2_MODE_MII; 2433179895Sdelphij ctrl |= ET_MAC_CTRL_MODE_MII; 2434179895Sdelphij } 2435179895Sdelphij 2436179895Sdelphij if ((mii->mii_media_active & IFM_GMASK) == IFM_FDX) 2437179895Sdelphij cfg2 |= ET_MAC_CFG2_FDX; 2438179895Sdelphij else 2439179895Sdelphij ctrl |= ET_MAC_CTRL_GHDX; 2440179895Sdelphij 2441179895Sdelphij CSR_WRITE_4(sc, ET_MAC_CTRL, ctrl); 2442179895Sdelphij CSR_WRITE_4(sc, ET_MAC_CFG2, cfg2); 2443179895Sdelphij} 2444179895Sdelphij 2445179895Sdelphijstatic void 2446179895Sdelphijet_setup_rxdesc(struct et_rxbuf_data *rbd, int buf_idx, bus_addr_t paddr) 2447179895Sdelphij{ 2448179895Sdelphij struct et_rxdesc_ring *rx_ring = rbd->rbd_ring; 2449179895Sdelphij struct et_rxdesc *desc; 2450179895Sdelphij 2451179895Sdelphij MPASS(buf_idx < ET_RX_NDESC); 2452179895Sdelphij desc = &rx_ring->rr_desc[buf_idx]; 2453179895Sdelphij 2454199609Syongari desc->rd_addr_hi = htole32(ET_ADDR_HI(paddr)); 2455199609Syongari desc->rd_addr_lo = htole32(ET_ADDR_LO(paddr)); 2456199609Syongari desc->rd_ctrl = htole32(buf_idx & ET_RDCTRL_BUFIDX_MASK); 2457179895Sdelphij 2458179895Sdelphij bus_dmamap_sync(rx_ring->rr_dtag, rx_ring->rr_dmap, 2459179895Sdelphij BUS_DMASYNC_PREWRITE); 2460179895Sdelphij} 2461