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$"); 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> 56257176Sglebius#include <net/if_var.h> 57179895Sdelphij#include <net/if_dl.h> 58179895Sdelphij#include <net/if_types.h> 59179895Sdelphij#include <net/bpf.h> 60179895Sdelphij#include <net/if_arp.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); 91228292Syongaristatic int et_suspend(device_t); 92228292Syongaristatic int et_resume(device_t); 93179895Sdelphij 94179895Sdelphijstatic int et_miibus_readreg(device_t, int, int); 95179895Sdelphijstatic int et_miibus_writereg(device_t, int, int, int); 96179895Sdelphijstatic void et_miibus_statchg(device_t); 97179895Sdelphij 98179895Sdelphijstatic void et_init_locked(struct et_softc *); 99179895Sdelphijstatic void et_init(void *); 100179895Sdelphijstatic int et_ioctl(struct ifnet *, u_long, caddr_t); 101179895Sdelphijstatic void et_start_locked(struct ifnet *); 102179895Sdelphijstatic void et_start(struct ifnet *); 103228325Syongaristatic int et_watchdog(struct et_softc *); 104179895Sdelphijstatic int et_ifmedia_upd_locked(struct ifnet *); 105179895Sdelphijstatic int et_ifmedia_upd(struct ifnet *); 106179895Sdelphijstatic void et_ifmedia_sts(struct ifnet *, struct ifmediareq *); 107272064Sglebiusstatic uint64_t et_get_counter(struct ifnet *, ift_counter); 108179895Sdelphij 109179895Sdelphijstatic void et_add_sysctls(struct et_softc *); 110179895Sdelphijstatic int et_sysctl_rx_intr_npkts(SYSCTL_HANDLER_ARGS); 111179895Sdelphijstatic int et_sysctl_rx_intr_delay(SYSCTL_HANDLER_ARGS); 112179895Sdelphij 113179895Sdelphijstatic void et_intr(void *); 114179895Sdelphijstatic void et_rxeof(struct et_softc *); 115179895Sdelphijstatic void et_txeof(struct et_softc *); 116179895Sdelphij 117228325Syongaristatic int et_dma_alloc(struct et_softc *); 118228325Syongaristatic void et_dma_free(struct et_softc *); 119228325Syongaristatic void et_dma_map_addr(void *, bus_dma_segment_t *, int, int); 120228325Syongaristatic int et_dma_ring_alloc(struct et_softc *, bus_size_t, bus_size_t, 121228325Syongari bus_dma_tag_t *, uint8_t **, bus_dmamap_t *, bus_addr_t *, 122228325Syongari const char *); 123228325Syongaristatic void et_dma_ring_free(struct et_softc *, bus_dma_tag_t *, uint8_t **, 124267580Sjhb bus_dmamap_t, bus_addr_t *); 125228325Syongaristatic void et_init_tx_ring(struct et_softc *); 126179895Sdelphijstatic int et_init_rx_ring(struct et_softc *); 127179895Sdelphijstatic void et_free_tx_ring(struct et_softc *); 128179895Sdelphijstatic void et_free_rx_ring(struct et_softc *); 129179895Sdelphijstatic int et_encap(struct et_softc *, struct mbuf **); 130228325Syongaristatic int et_newbuf_cluster(struct et_rxbuf_data *, int); 131228325Syongaristatic int et_newbuf_hdr(struct et_rxbuf_data *, int); 132228325Syongaristatic void et_rxbuf_discard(struct et_rxbuf_data *, int); 133179895Sdelphij 134179895Sdelphijstatic void et_stop(struct et_softc *); 135179895Sdelphijstatic int et_chip_init(struct et_softc *); 136179895Sdelphijstatic void et_chip_attach(struct et_softc *); 137179895Sdelphijstatic void et_init_mac(struct et_softc *); 138179895Sdelphijstatic void et_init_rxmac(struct et_softc *); 139179895Sdelphijstatic void et_init_txmac(struct et_softc *); 140179895Sdelphijstatic int et_init_rxdma(struct et_softc *); 141179895Sdelphijstatic int et_init_txdma(struct et_softc *); 142179895Sdelphijstatic int et_start_rxdma(struct et_softc *); 143179895Sdelphijstatic int et_start_txdma(struct et_softc *); 144179895Sdelphijstatic int et_stop_rxdma(struct et_softc *); 145179895Sdelphijstatic int et_stop_txdma(struct et_softc *); 146179895Sdelphijstatic void et_reset(struct et_softc *); 147199561Syongaristatic int et_bus_config(struct et_softc *); 148179895Sdelphijstatic void et_get_eaddr(device_t, uint8_t[]); 149179895Sdelphijstatic void et_setmulti(struct et_softc *); 150179895Sdelphijstatic void et_tick(void *); 151228332Syongaristatic void et_stats_update(struct et_softc *); 152179895Sdelphij 153179895Sdelphijstatic const struct et_dev { 154179895Sdelphij uint16_t vid; 155179895Sdelphij uint16_t did; 156179895Sdelphij const char *desc; 157179895Sdelphij} et_devices[] = { 158179895Sdelphij { PCI_VENDOR_LUCENT, PCI_PRODUCT_LUCENT_ET1310, 159179895Sdelphij "Agere ET1310 Gigabit Ethernet" }, 160179895Sdelphij { PCI_VENDOR_LUCENT, PCI_PRODUCT_LUCENT_ET1310_FAST, 161179895Sdelphij "Agere ET1310 Fast Ethernet" }, 162179895Sdelphij { 0, 0, NULL } 163179895Sdelphij}; 164179895Sdelphij 165179895Sdelphijstatic device_method_t et_methods[] = { 166179895Sdelphij DEVMETHOD(device_probe, et_probe), 167179895Sdelphij DEVMETHOD(device_attach, et_attach), 168179895Sdelphij DEVMETHOD(device_detach, et_detach), 169179895Sdelphij DEVMETHOD(device_shutdown, et_shutdown), 170228292Syongari DEVMETHOD(device_suspend, et_suspend), 171228292Syongari DEVMETHOD(device_resume, et_resume), 172179895Sdelphij 173179895Sdelphij DEVMETHOD(miibus_readreg, et_miibus_readreg), 174179895Sdelphij DEVMETHOD(miibus_writereg, et_miibus_writereg), 175179895Sdelphij DEVMETHOD(miibus_statchg, et_miibus_statchg), 176179895Sdelphij 177227843Smarius DEVMETHOD_END 178179895Sdelphij}; 179179895Sdelphij 180179895Sdelphijstatic driver_t et_driver = { 181179895Sdelphij "et", 182179895Sdelphij et_methods, 183179895Sdelphij sizeof(struct et_softc) 184179895Sdelphij}; 185179895Sdelphij 186179895Sdelphijstatic devclass_t et_devclass; 187179895Sdelphij 188179895SdelphijDRIVER_MODULE(et, pci, et_driver, et_devclass, 0, 0); 189179895SdelphijDRIVER_MODULE(miibus, et, miibus_driver, miibus_devclass, 0, 0); 190179895Sdelphij 191179895Sdelphijstatic int et_rx_intr_npkts = 32; 192179895Sdelphijstatic int et_rx_intr_delay = 20; /* x10 usec */ 193179895Sdelphijstatic int et_tx_intr_nsegs = 126; 194179895Sdelphijstatic uint32_t et_timer = 1000 * 1000 * 1000; /* nanosec */ 195179895Sdelphij 196179895SdelphijTUNABLE_INT("hw.et.timer", &et_timer); 197179895SdelphijTUNABLE_INT("hw.et.rx_intr_npkts", &et_rx_intr_npkts); 198179895SdelphijTUNABLE_INT("hw.et.rx_intr_delay", &et_rx_intr_delay); 199179895SdelphijTUNABLE_INT("hw.et.tx_intr_nsegs", &et_tx_intr_nsegs); 200179895Sdelphij 201179895Sdelphijstatic int 202179895Sdelphijet_probe(device_t dev) 203179895Sdelphij{ 204179895Sdelphij const struct et_dev *d; 205179895Sdelphij uint16_t did, vid; 206179895Sdelphij 207179895Sdelphij vid = pci_get_vendor(dev); 208179895Sdelphij did = pci_get_device(dev); 209179895Sdelphij 210179895Sdelphij for (d = et_devices; d->desc != NULL; ++d) { 211179895Sdelphij if (vid == d->vid && did == d->did) { 212179895Sdelphij device_set_desc(dev, d->desc); 213228298Syongari return (BUS_PROBE_DEFAULT); 214179895Sdelphij } 215179895Sdelphij } 216199556Syongari return (ENXIO); 217179895Sdelphij} 218179895Sdelphij 219179895Sdelphijstatic int 220179895Sdelphijet_attach(device_t dev) 221179895Sdelphij{ 222179895Sdelphij struct et_softc *sc; 223179895Sdelphij struct ifnet *ifp; 224179895Sdelphij uint8_t eaddr[ETHER_ADDR_LEN]; 225228336Syongari uint32_t pmcfg; 226199552Syongari int cap, error, msic; 227179895Sdelphij 228179895Sdelphij sc = device_get_softc(dev); 229179895Sdelphij sc->dev = dev; 230179895Sdelphij mtx_init(&sc->sc_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK, 231179895Sdelphij MTX_DEF); 232228297Syongari callout_init_mtx(&sc->sc_tick, &sc->sc_mtx, 0); 233179895Sdelphij 234179895Sdelphij ifp = sc->ifp = if_alloc(IFT_ETHER); 235179895Sdelphij if (ifp == NULL) { 236179895Sdelphij device_printf(dev, "can not if_alloc()\n"); 237179895Sdelphij error = ENOSPC; 238179895Sdelphij goto fail; 239179895Sdelphij } 240179895Sdelphij 241179895Sdelphij /* 242179895Sdelphij * Initialize tunables 243179895Sdelphij */ 244179895Sdelphij sc->sc_rx_intr_npkts = et_rx_intr_npkts; 245179895Sdelphij sc->sc_rx_intr_delay = et_rx_intr_delay; 246179895Sdelphij sc->sc_tx_intr_nsegs = et_tx_intr_nsegs; 247179895Sdelphij sc->sc_timer = et_timer; 248179895Sdelphij 249179895Sdelphij /* Enable bus mastering */ 250179895Sdelphij pci_enable_busmaster(dev); 251179895Sdelphij 252179895Sdelphij /* 253179895Sdelphij * Allocate IO memory 254179895Sdelphij */ 255228368Syongari sc->sc_mem_rid = PCIR_BAR(0); 256179895Sdelphij sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 257228368Syongari &sc->sc_mem_rid, RF_ACTIVE); 258179895Sdelphij if (sc->sc_mem_res == NULL) { 259179895Sdelphij device_printf(dev, "can't allocate IO memory\n"); 260199556Syongari return (ENXIO); 261179895Sdelphij } 262179895Sdelphij 263199552Syongari msic = 0; 264219902Sjhb if (pci_find_cap(dev, PCIY_EXPRESS, &cap) == 0) { 265199552Syongari sc->sc_expcap = cap; 266199552Syongari sc->sc_flags |= ET_FLAG_PCIE; 267199552Syongari msic = pci_msi_count(dev); 268199552Syongari if (bootverbose) 269199563Syongari device_printf(dev, "MSI count: %d\n", msic); 270199552Syongari } 271199552Syongari if (msic > 0 && msi_disable == 0) { 272199552Syongari msic = 1; 273199552Syongari if (pci_alloc_msi(dev, &msic) == 0) { 274199552Syongari if (msic == 1) { 275199552Syongari device_printf(dev, "Using %d MSI message\n", 276199552Syongari msic); 277199552Syongari sc->sc_flags |= ET_FLAG_MSI; 278199552Syongari } else 279199552Syongari pci_release_msi(dev); 280199552Syongari } 281199552Syongari } 282199552Syongari 283179895Sdelphij /* 284179895Sdelphij * Allocate IRQ 285179895Sdelphij */ 286199552Syongari if ((sc->sc_flags & ET_FLAG_MSI) == 0) { 287199552Syongari sc->sc_irq_rid = 0; 288199552Syongari sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, 289199552Syongari &sc->sc_irq_rid, RF_SHAREABLE | RF_ACTIVE); 290199552Syongari } else { 291199552Syongari sc->sc_irq_rid = 1; 292199552Syongari sc->sc_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, 293199552Syongari &sc->sc_irq_rid, RF_ACTIVE); 294199552Syongari } 295179895Sdelphij if (sc->sc_irq_res == NULL) { 296179895Sdelphij device_printf(dev, "can't allocate irq\n"); 297179895Sdelphij error = ENXIO; 298179895Sdelphij goto fail; 299179895Sdelphij } 300179895Sdelphij 301228331Syongari if (pci_get_device(dev) == PCI_PRODUCT_LUCENT_ET1310_FAST) 302228331Syongari sc->sc_flags |= ET_FLAG_FASTETHER; 303228331Syongari 304199561Syongari error = et_bus_config(sc); 305179895Sdelphij if (error) 306179895Sdelphij goto fail; 307179895Sdelphij 308179895Sdelphij et_get_eaddr(dev, eaddr); 309179895Sdelphij 310228336Syongari /* Take PHY out of COMA and enable clocks. */ 311228336Syongari pmcfg = ET_PM_SYSCLK_GATE | ET_PM_TXCLK_GATE | ET_PM_RXCLK_GATE; 312228336Syongari if ((sc->sc_flags & ET_FLAG_FASTETHER) == 0) 313228336Syongari pmcfg |= EM_PM_GIGEPHY_ENB; 314228336Syongari CSR_WRITE_4(sc, ET_PM, pmcfg); 315179895Sdelphij 316179895Sdelphij et_reset(sc); 317179895Sdelphij 318228325Syongari error = et_dma_alloc(sc); 319179895Sdelphij if (error) 320179895Sdelphij goto fail; 321179895Sdelphij 322179895Sdelphij ifp->if_softc = sc; 323179895Sdelphij if_initname(ifp, device_get_name(dev), device_get_unit(dev)); 324179895Sdelphij ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 325179895Sdelphij ifp->if_init = et_init; 326179895Sdelphij ifp->if_ioctl = et_ioctl; 327179895Sdelphij ifp->if_start = et_start; 328272064Sglebius ifp->if_get_counter = et_get_counter; 329199613Syongari ifp->if_capabilities = IFCAP_TXCSUM | IFCAP_VLAN_MTU; 330179895Sdelphij ifp->if_capenable = ifp->if_capabilities; 331228293Syongari ifp->if_snd.ifq_drv_maxlen = ET_TX_NDESC - 1; 332228293Syongari IFQ_SET_MAXLEN(&ifp->if_snd, ET_TX_NDESC - 1); 333179895Sdelphij IFQ_SET_READY(&ifp->if_snd); 334179895Sdelphij 335179895Sdelphij et_chip_attach(sc); 336179895Sdelphij 337213894Smarius error = mii_attach(dev, &sc->sc_miibus, ifp, et_ifmedia_upd, 338228369Syongari et_ifmedia_sts, BMSR_DEFCAPMASK, MII_PHY_ANY, MII_OFFSET_ANY, 339228369Syongari MIIF_DOPAUSE); 340179895Sdelphij if (error) { 341213894Smarius device_printf(dev, "attaching PHYs failed\n"); 342179895Sdelphij goto fail; 343179895Sdelphij } 344179895Sdelphij 345179895Sdelphij ether_ifattach(ifp, eaddr); 346179895Sdelphij 347228297Syongari /* Tell the upper layer(s) we support long frames. */ 348228297Syongari ifp->if_hdrlen = sizeof(struct ether_vlan_header); 349228297Syongari 350179895Sdelphij error = bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_NET | INTR_MPSAFE, 351199552Syongari NULL, et_intr, sc, &sc->sc_irq_handle); 352179895Sdelphij if (error) { 353179895Sdelphij ether_ifdetach(ifp); 354179895Sdelphij device_printf(dev, "can't setup intr\n"); 355179895Sdelphij goto fail; 356179895Sdelphij } 357179895Sdelphij 358179895Sdelphij et_add_sysctls(sc); 359179895Sdelphij 360199556Syongari return (0); 361179895Sdelphijfail: 362179895Sdelphij et_detach(dev); 363199556Syongari return (error); 364179895Sdelphij} 365179895Sdelphij 366179895Sdelphijstatic int 367179895Sdelphijet_detach(device_t dev) 368179895Sdelphij{ 369229940Syongari struct et_softc *sc; 370179895Sdelphij 371229940Syongari sc = device_get_softc(dev); 372179895Sdelphij if (device_is_attached(dev)) { 373228298Syongari ether_ifdetach(sc->ifp); 374179895Sdelphij ET_LOCK(sc); 375179895Sdelphij et_stop(sc); 376179895Sdelphij ET_UNLOCK(sc); 377228298Syongari callout_drain(&sc->sc_tick); 378179895Sdelphij } 379179895Sdelphij 380179895Sdelphij if (sc->sc_miibus != NULL) 381179895Sdelphij device_delete_child(dev, sc->sc_miibus); 382179895Sdelphij bus_generic_detach(dev); 383179895Sdelphij 384228298Syongari if (sc->sc_irq_handle != NULL) 385228298Syongari bus_teardown_intr(dev, sc->sc_irq_res, sc->sc_irq_handle); 386228298Syongari if (sc->sc_irq_res != NULL) 387228298Syongari bus_release_resource(dev, SYS_RES_IRQ, 388228298Syongari rman_get_rid(sc->sc_irq_res), sc->sc_irq_res); 389199552Syongari if ((sc->sc_flags & ET_FLAG_MSI) != 0) 390199552Syongari pci_release_msi(dev); 391228298Syongari if (sc->sc_mem_res != NULL) 392228298Syongari bus_release_resource(dev, SYS_RES_MEMORY, 393228298Syongari rman_get_rid(sc->sc_mem_res), sc->sc_mem_res); 394179895Sdelphij 395179895Sdelphij if (sc->ifp != NULL) 396179895Sdelphij if_free(sc->ifp); 397179895Sdelphij 398228325Syongari et_dma_free(sc); 399179895Sdelphij 400199551Syongari mtx_destroy(&sc->sc_mtx); 401199551Syongari 402199556Syongari return (0); 403179895Sdelphij} 404179895Sdelphij 405179895Sdelphijstatic int 406179895Sdelphijet_shutdown(device_t dev) 407179895Sdelphij{ 408229940Syongari struct et_softc *sc; 409179895Sdelphij 410229940Syongari sc = device_get_softc(dev); 411179895Sdelphij ET_LOCK(sc); 412179895Sdelphij et_stop(sc); 413179895Sdelphij ET_UNLOCK(sc); 414199556Syongari return (0); 415179895Sdelphij} 416179895Sdelphij 417179895Sdelphijstatic int 418179895Sdelphijet_miibus_readreg(device_t dev, int phy, int reg) 419179895Sdelphij{ 420229940Syongari struct et_softc *sc; 421179895Sdelphij uint32_t val; 422179895Sdelphij int i, ret; 423179895Sdelphij 424229940Syongari sc = device_get_softc(dev); 425179895Sdelphij /* Stop any pending operations */ 426179895Sdelphij CSR_WRITE_4(sc, ET_MII_CMD, 0); 427179895Sdelphij 428199548Syongari val = (phy << ET_MII_ADDR_PHY_SHIFT) & ET_MII_ADDR_PHY_MASK; 429199548Syongari val |= (reg << ET_MII_ADDR_REG_SHIFT) & ET_MII_ADDR_REG_MASK; 430179895Sdelphij CSR_WRITE_4(sc, ET_MII_ADDR, val); 431179895Sdelphij 432179895Sdelphij /* Start reading */ 433179895Sdelphij CSR_WRITE_4(sc, ET_MII_CMD, ET_MII_CMD_READ); 434179895Sdelphij 435179895Sdelphij#define NRETRY 50 436179895Sdelphij 437179895Sdelphij for (i = 0; i < NRETRY; ++i) { 438179895Sdelphij val = CSR_READ_4(sc, ET_MII_IND); 439179895Sdelphij if ((val & (ET_MII_IND_BUSY | ET_MII_IND_INVALID)) == 0) 440179895Sdelphij break; 441179895Sdelphij DELAY(50); 442179895Sdelphij } 443179895Sdelphij if (i == NRETRY) { 444179895Sdelphij if_printf(sc->ifp, 445179895Sdelphij "read phy %d, reg %d timed out\n", phy, reg); 446179895Sdelphij ret = 0; 447179895Sdelphij goto back; 448179895Sdelphij } 449179895Sdelphij 450179895Sdelphij#undef NRETRY 451179895Sdelphij 452179895Sdelphij val = CSR_READ_4(sc, ET_MII_STAT); 453199548Syongari ret = val & ET_MII_STAT_VALUE_MASK; 454179895Sdelphij 455179895Sdelphijback: 456179895Sdelphij /* Make sure that the current operation is stopped */ 457179895Sdelphij CSR_WRITE_4(sc, ET_MII_CMD, 0); 458199556Syongari return (ret); 459179895Sdelphij} 460179895Sdelphij 461179895Sdelphijstatic int 462179895Sdelphijet_miibus_writereg(device_t dev, int phy, int reg, int val0) 463179895Sdelphij{ 464229940Syongari struct et_softc *sc; 465179895Sdelphij uint32_t val; 466179895Sdelphij int i; 467179895Sdelphij 468229940Syongari sc = device_get_softc(dev); 469179895Sdelphij /* Stop any pending operations */ 470179895Sdelphij CSR_WRITE_4(sc, ET_MII_CMD, 0); 471179895Sdelphij 472199548Syongari val = (phy << ET_MII_ADDR_PHY_SHIFT) & ET_MII_ADDR_PHY_MASK; 473199548Syongari val |= (reg << ET_MII_ADDR_REG_SHIFT) & ET_MII_ADDR_REG_MASK; 474179895Sdelphij CSR_WRITE_4(sc, ET_MII_ADDR, val); 475179895Sdelphij 476179895Sdelphij /* Start writing */ 477199548Syongari CSR_WRITE_4(sc, ET_MII_CTRL, 478199548Syongari (val0 << ET_MII_CTRL_VALUE_SHIFT) & ET_MII_CTRL_VALUE_MASK); 479179895Sdelphij 480179895Sdelphij#define NRETRY 100 481179895Sdelphij 482179895Sdelphij for (i = 0; i < NRETRY; ++i) { 483179895Sdelphij val = CSR_READ_4(sc, ET_MII_IND); 484179895Sdelphij if ((val & ET_MII_IND_BUSY) == 0) 485179895Sdelphij break; 486179895Sdelphij DELAY(50); 487179895Sdelphij } 488179895Sdelphij if (i == NRETRY) { 489179895Sdelphij if_printf(sc->ifp, 490179895Sdelphij "write phy %d, reg %d timed out\n", phy, reg); 491179895Sdelphij et_miibus_readreg(dev, phy, reg); 492179895Sdelphij } 493179895Sdelphij 494179895Sdelphij#undef NRETRY 495179895Sdelphij 496179895Sdelphij /* Make sure that the current operation is stopped */ 497179895Sdelphij CSR_WRITE_4(sc, ET_MII_CMD, 0); 498199556Syongari return (0); 499179895Sdelphij} 500179895Sdelphij 501179895Sdelphijstatic void 502179895Sdelphijet_miibus_statchg(device_t dev) 503179895Sdelphij{ 504228331Syongari struct et_softc *sc; 505228331Syongari struct mii_data *mii; 506228331Syongari struct ifnet *ifp; 507228331Syongari uint32_t cfg1, cfg2, ctrl; 508228331Syongari int i; 509228331Syongari 510228331Syongari sc = device_get_softc(dev); 511228331Syongari 512228331Syongari mii = device_get_softc(sc->sc_miibus); 513228331Syongari ifp = sc->ifp; 514228331Syongari if (mii == NULL || ifp == NULL || 515228331Syongari (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) 516228331Syongari return; 517228331Syongari 518228331Syongari sc->sc_flags &= ~ET_FLAG_LINK; 519228331Syongari if ((mii->mii_media_status & (IFM_ACTIVE | IFM_AVALID)) == 520228331Syongari (IFM_ACTIVE | IFM_AVALID)) { 521228331Syongari switch (IFM_SUBTYPE(mii->mii_media_active)) { 522228331Syongari case IFM_10_T: 523228331Syongari case IFM_100_TX: 524228331Syongari sc->sc_flags |= ET_FLAG_LINK; 525228331Syongari break; 526228331Syongari case IFM_1000_T: 527228331Syongari if ((sc->sc_flags & ET_FLAG_FASTETHER) == 0) 528228331Syongari sc->sc_flags |= ET_FLAG_LINK; 529228331Syongari break; 530228331Syongari } 531228331Syongari } 532228331Syongari 533228331Syongari /* XXX Stop TX/RX MAC? */ 534228331Syongari if ((sc->sc_flags & ET_FLAG_LINK) == 0) 535228331Syongari return; 536228331Syongari 537228331Syongari /* Program MACs with resolved speed/duplex/flow-control. */ 538228331Syongari ctrl = CSR_READ_4(sc, ET_MAC_CTRL); 539228331Syongari ctrl &= ~(ET_MAC_CTRL_GHDX | ET_MAC_CTRL_MODE_MII); 540228331Syongari cfg1 = CSR_READ_4(sc, ET_MAC_CFG1); 541228331Syongari cfg1 &= ~(ET_MAC_CFG1_TXFLOW | ET_MAC_CFG1_RXFLOW | 542228331Syongari ET_MAC_CFG1_LOOPBACK); 543228331Syongari cfg2 = CSR_READ_4(sc, ET_MAC_CFG2); 544228331Syongari cfg2 &= ~(ET_MAC_CFG2_MODE_MII | ET_MAC_CFG2_MODE_GMII | 545228331Syongari ET_MAC_CFG2_FDX | ET_MAC_CFG2_BIGFRM); 546228331Syongari cfg2 |= ET_MAC_CFG2_LENCHK | ET_MAC_CFG2_CRC | ET_MAC_CFG2_PADCRC | 547228331Syongari ((7 << ET_MAC_CFG2_PREAMBLE_LEN_SHIFT) & 548228331Syongari ET_MAC_CFG2_PREAMBLE_LEN_MASK); 549228331Syongari 550228331Syongari if (IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_T) 551228331Syongari cfg2 |= ET_MAC_CFG2_MODE_GMII; 552228331Syongari else { 553228331Syongari cfg2 |= ET_MAC_CFG2_MODE_MII; 554228331Syongari ctrl |= ET_MAC_CTRL_MODE_MII; 555228331Syongari } 556228331Syongari 557228331Syongari if (IFM_OPTIONS(mii->mii_media_active) & IFM_FDX) { 558228331Syongari cfg2 |= ET_MAC_CFG2_FDX; 559228369Syongari /* 560228369Syongari * Controller lacks automatic TX pause frame 561228369Syongari * generation so it should be handled by driver. 562228369Syongari * Even though driver can send pause frame with 563228369Syongari * arbitrary pause time, controller does not 564228369Syongari * provide a way that tells how many free RX 565228369Syongari * buffers are available in controller. This 566228369Syongari * limitation makes it hard to generate XON frame 567228369Syongari * in time on driver side so don't enable TX flow 568228369Syongari * control. 569228369Syongari */ 570228331Syongari#ifdef notyet 571228331Syongari if (IFM_OPTIONS(mii->mii_media_active) & IFM_ETH_TXPAUSE) 572228331Syongari cfg1 |= ET_MAC_CFG1_TXFLOW; 573228369Syongari#endif 574228331Syongari if (IFM_OPTIONS(mii->mii_media_active) & IFM_ETH_RXPAUSE) 575228331Syongari cfg1 |= ET_MAC_CFG1_RXFLOW; 576228331Syongari } else 577228331Syongari ctrl |= ET_MAC_CTRL_GHDX; 578228331Syongari 579228331Syongari CSR_WRITE_4(sc, ET_MAC_CTRL, ctrl); 580228331Syongari CSR_WRITE_4(sc, ET_MAC_CFG2, cfg2); 581228331Syongari cfg1 |= ET_MAC_CFG1_TXEN | ET_MAC_CFG1_RXEN; 582228331Syongari CSR_WRITE_4(sc, ET_MAC_CFG1, cfg1); 583228331Syongari 584228331Syongari#define NRETRY 50 585228331Syongari 586228331Syongari for (i = 0; i < NRETRY; ++i) { 587228331Syongari cfg1 = CSR_READ_4(sc, ET_MAC_CFG1); 588228331Syongari if ((cfg1 & (ET_MAC_CFG1_SYNC_TXEN | ET_MAC_CFG1_SYNC_RXEN)) == 589228331Syongari (ET_MAC_CFG1_SYNC_TXEN | ET_MAC_CFG1_SYNC_RXEN)) 590228331Syongari break; 591228331Syongari DELAY(100); 592228331Syongari } 593228331Syongari if (i == NRETRY) 594228331Syongari if_printf(ifp, "can't enable RX/TX\n"); 595228331Syongari sc->sc_flags |= ET_FLAG_TXRX_ENABLED; 596228331Syongari 597228331Syongari#undef NRETRY 598179895Sdelphij} 599179895Sdelphij 600179895Sdelphijstatic int 601179895Sdelphijet_ifmedia_upd_locked(struct ifnet *ifp) 602179895Sdelphij{ 603229940Syongari struct et_softc *sc; 604229940Syongari struct mii_data *mii; 605221407Smarius struct mii_softc *miisc; 606179895Sdelphij 607229940Syongari sc = ifp->if_softc; 608229940Syongari mii = device_get_softc(sc->sc_miibus); 609221407Smarius LIST_FOREACH(miisc, &mii->mii_phys, mii_list) 610221407Smarius PHY_RESET(miisc); 611226481Syongari return (mii_mediachg(mii)); 612179895Sdelphij} 613179895Sdelphij 614179895Sdelphijstatic int 615179895Sdelphijet_ifmedia_upd(struct ifnet *ifp) 616179895Sdelphij{ 617229940Syongari struct et_softc *sc; 618179895Sdelphij int res; 619179895Sdelphij 620229940Syongari sc = ifp->if_softc; 621179895Sdelphij ET_LOCK(sc); 622179895Sdelphij res = et_ifmedia_upd_locked(ifp); 623179895Sdelphij ET_UNLOCK(sc); 624179895Sdelphij 625199556Syongari return (res); 626179895Sdelphij} 627179895Sdelphij 628179895Sdelphijstatic void 629179895Sdelphijet_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr) 630179895Sdelphij{ 631228331Syongari struct et_softc *sc; 632228331Syongari struct mii_data *mii; 633179895Sdelphij 634228331Syongari sc = ifp->if_softc; 635226480Syongari ET_LOCK(sc); 636228331Syongari if ((ifp->if_flags & IFF_UP) == 0) { 637228331Syongari ET_UNLOCK(sc); 638228331Syongari return; 639228331Syongari } 640228331Syongari 641228331Syongari mii = device_get_softc(sc->sc_miibus); 642179895Sdelphij mii_pollstat(mii); 643179895Sdelphij ifmr->ifm_active = mii->mii_media_active; 644179895Sdelphij ifmr->ifm_status = mii->mii_media_status; 645226480Syongari ET_UNLOCK(sc); 646179895Sdelphij} 647179895Sdelphij 648179895Sdelphijstatic void 649179895Sdelphijet_stop(struct et_softc *sc) 650179895Sdelphij{ 651229940Syongari struct ifnet *ifp; 652179895Sdelphij 653179895Sdelphij ET_LOCK_ASSERT(sc); 654179895Sdelphij 655229940Syongari ifp = sc->ifp; 656179895Sdelphij callout_stop(&sc->sc_tick); 657228327Syongari /* Disable interrupts. */ 658228327Syongari CSR_WRITE_4(sc, ET_INTR_MASK, 0xffffffff); 659179895Sdelphij 660228331Syongari CSR_WRITE_4(sc, ET_MAC_CFG1, CSR_READ_4(sc, ET_MAC_CFG1) & ~( 661228331Syongari ET_MAC_CFG1_TXEN | ET_MAC_CFG1_RXEN)); 662228331Syongari DELAY(100); 663228331Syongari 664179895Sdelphij et_stop_rxdma(sc); 665179895Sdelphij et_stop_txdma(sc); 666228332Syongari et_stats_update(sc); 667179895Sdelphij 668179895Sdelphij et_free_tx_ring(sc); 669179895Sdelphij et_free_rx_ring(sc); 670179895Sdelphij 671179895Sdelphij sc->sc_tx = 0; 672179895Sdelphij sc->sc_tx_intr = 0; 673179895Sdelphij sc->sc_flags &= ~ET_FLAG_TXRX_ENABLED; 674179895Sdelphij 675179895Sdelphij sc->watchdog_timer = 0; 676179895Sdelphij ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); 677179895Sdelphij} 678179895Sdelphij 679179895Sdelphijstatic int 680199561Syongariet_bus_config(struct et_softc *sc) 681179895Sdelphij{ 682179895Sdelphij uint32_t val, max_plsz; 683179895Sdelphij uint16_t ack_latency, replay_timer; 684179895Sdelphij 685179895Sdelphij /* 686179895Sdelphij * Test whether EEPROM is valid 687179895Sdelphij * NOTE: Read twice to get the correct value 688179895Sdelphij */ 689199561Syongari pci_read_config(sc->dev, ET_PCIR_EEPROM_STATUS, 1); 690199561Syongari val = pci_read_config(sc->dev, ET_PCIR_EEPROM_STATUS, 1); 691179895Sdelphij if (val & ET_PCIM_EEPROM_STATUS_ERROR) { 692199561Syongari device_printf(sc->dev, "EEPROM status error 0x%02x\n", val); 693199556Syongari return (ENXIO); 694179895Sdelphij } 695179895Sdelphij 696179895Sdelphij /* TODO: LED */ 697179895Sdelphij 698199561Syongari if ((sc->sc_flags & ET_FLAG_PCIE) == 0) 699199561Syongari return (0); 700199561Syongari 701179895Sdelphij /* 702179895Sdelphij * Configure ACK latency and replay timer according to 703179895Sdelphij * max playload size 704179895Sdelphij */ 705199561Syongari val = pci_read_config(sc->dev, 706240680Sgavin sc->sc_expcap + PCIER_DEVICE_CAP, 4); 707240680Sgavin max_plsz = val & PCIEM_CAP_MAX_PAYLOAD; 708179895Sdelphij 709179895Sdelphij switch (max_plsz) { 710179895Sdelphij case ET_PCIV_DEVICE_CAPS_PLSZ_128: 711179895Sdelphij ack_latency = ET_PCIV_ACK_LATENCY_128; 712179895Sdelphij replay_timer = ET_PCIV_REPLAY_TIMER_128; 713179895Sdelphij break; 714179895Sdelphij 715179895Sdelphij case ET_PCIV_DEVICE_CAPS_PLSZ_256: 716179895Sdelphij ack_latency = ET_PCIV_ACK_LATENCY_256; 717179895Sdelphij replay_timer = ET_PCIV_REPLAY_TIMER_256; 718179895Sdelphij break; 719179895Sdelphij 720179895Sdelphij default: 721199561Syongari ack_latency = pci_read_config(sc->dev, ET_PCIR_ACK_LATENCY, 2); 722199561Syongari replay_timer = pci_read_config(sc->dev, 723199561Syongari ET_PCIR_REPLAY_TIMER, 2); 724199561Syongari device_printf(sc->dev, "ack latency %u, replay timer %u\n", 725179895Sdelphij ack_latency, replay_timer); 726179895Sdelphij break; 727179895Sdelphij } 728179895Sdelphij if (ack_latency != 0) { 729199561Syongari pci_write_config(sc->dev, ET_PCIR_ACK_LATENCY, ack_latency, 2); 730199561Syongari pci_write_config(sc->dev, ET_PCIR_REPLAY_TIMER, replay_timer, 731199561Syongari 2); 732179895Sdelphij } 733179895Sdelphij 734179895Sdelphij /* 735179895Sdelphij * Set L0s and L1 latency timer to 2us 736179895Sdelphij */ 737199561Syongari val = pci_read_config(sc->dev, ET_PCIR_L0S_L1_LATENCY, 4); 738240680Sgavin val &= ~(PCIEM_LINK_CAP_L0S_EXIT | PCIEM_LINK_CAP_L1_EXIT); 739199548Syongari /* L0s exit latency : 2us */ 740199548Syongari val |= 0x00005000; 741199548Syongari /* L1 exit latency : 2us */ 742199548Syongari val |= 0x00028000; 743199561Syongari pci_write_config(sc->dev, ET_PCIR_L0S_L1_LATENCY, val, 4); 744179895Sdelphij 745179895Sdelphij /* 746179895Sdelphij * Set max read request size to 2048 bytes 747179895Sdelphij */ 748228368Syongari pci_set_max_read_req(sc->dev, 2048); 749179895Sdelphij 750199556Syongari return (0); 751179895Sdelphij} 752179895Sdelphij 753179895Sdelphijstatic void 754179895Sdelphijet_get_eaddr(device_t dev, uint8_t eaddr[]) 755179895Sdelphij{ 756179895Sdelphij uint32_t val; 757179895Sdelphij int i; 758179895Sdelphij 759179895Sdelphij val = pci_read_config(dev, ET_PCIR_MAC_ADDR0, 4); 760179895Sdelphij for (i = 0; i < 4; ++i) 761179895Sdelphij eaddr[i] = (val >> (8 * i)) & 0xff; 762179895Sdelphij 763179895Sdelphij val = pci_read_config(dev, ET_PCIR_MAC_ADDR1, 2); 764179895Sdelphij for (; i < ETHER_ADDR_LEN; ++i) 765179895Sdelphij eaddr[i] = (val >> (8 * (i - 4))) & 0xff; 766179895Sdelphij} 767179895Sdelphij 768179895Sdelphijstatic void 769179895Sdelphijet_reset(struct et_softc *sc) 770179895Sdelphij{ 771229940Syongari 772179895Sdelphij CSR_WRITE_4(sc, ET_MAC_CFG1, 773179895Sdelphij ET_MAC_CFG1_RST_TXFUNC | ET_MAC_CFG1_RST_RXFUNC | 774179895Sdelphij ET_MAC_CFG1_RST_TXMC | ET_MAC_CFG1_RST_RXMC | 775179895Sdelphij ET_MAC_CFG1_SIM_RST | ET_MAC_CFG1_SOFT_RST); 776179895Sdelphij 777179895Sdelphij CSR_WRITE_4(sc, ET_SWRST, 778179895Sdelphij ET_SWRST_TXDMA | ET_SWRST_RXDMA | 779179895Sdelphij ET_SWRST_TXMAC | ET_SWRST_RXMAC | 780179895Sdelphij ET_SWRST_MAC | ET_SWRST_MAC_STAT | ET_SWRST_MMC); 781179895Sdelphij 782179895Sdelphij CSR_WRITE_4(sc, ET_MAC_CFG1, 783179895Sdelphij ET_MAC_CFG1_RST_TXFUNC | ET_MAC_CFG1_RST_RXFUNC | 784179895Sdelphij ET_MAC_CFG1_RST_TXMC | ET_MAC_CFG1_RST_RXMC); 785179895Sdelphij CSR_WRITE_4(sc, ET_MAC_CFG1, 0); 786228327Syongari /* Disable interrupts. */ 787179895Sdelphij CSR_WRITE_4(sc, ET_INTR_MASK, 0xffffffff); 788179895Sdelphij} 789179895Sdelphij 790228325Syongaristruct et_dmamap_arg { 791228325Syongari bus_addr_t et_busaddr; 792228325Syongari}; 793228325Syongari 794228325Syongaristatic void 795228325Syongariet_dma_map_addr(void *arg, bus_dma_segment_t *segs, int nseg, int error) 796228325Syongari{ 797228325Syongari struct et_dmamap_arg *ctx; 798228325Syongari 799228325Syongari if (error) 800228325Syongari return; 801228325Syongari 802228325Syongari KASSERT(nseg == 1, ("%s: %d segments returned!", __func__, nseg)); 803228325Syongari 804228325Syongari ctx = arg; 805228325Syongari ctx->et_busaddr = segs->ds_addr; 806228325Syongari} 807228325Syongari 808179895Sdelphijstatic int 809228325Syongariet_dma_ring_alloc(struct et_softc *sc, bus_size_t alignment, bus_size_t maxsize, 810228325Syongari bus_dma_tag_t *tag, uint8_t **ring, bus_dmamap_t *map, bus_addr_t *paddr, 811228325Syongari const char *msg) 812179895Sdelphij{ 813228325Syongari struct et_dmamap_arg ctx; 814228325Syongari int error; 815179895Sdelphij 816228325Syongari error = bus_dma_tag_create(sc->sc_dtag, alignment, 0, BUS_SPACE_MAXADDR, 817228325Syongari BUS_SPACE_MAXADDR, NULL, NULL, maxsize, 1, maxsize, 0, NULL, NULL, 818228325Syongari tag); 819228325Syongari if (error != 0) { 820228325Syongari device_printf(sc->dev, "could not create %s dma tag\n", msg); 821199556Syongari return (error); 822179895Sdelphij } 823228325Syongari /* Allocate DMA'able memory for ring. */ 824228325Syongari error = bus_dmamem_alloc(*tag, (void **)ring, 825228325Syongari BUS_DMA_NOWAIT | BUS_DMA_ZERO | BUS_DMA_COHERENT, map); 826228325Syongari if (error != 0) { 827228325Syongari device_printf(sc->dev, 828228325Syongari "could not allocate DMA'able memory for %s\n", msg); 829199556Syongari return (error); 830179895Sdelphij } 831228325Syongari /* Load the address of the ring. */ 832228325Syongari ctx.et_busaddr = 0; 833228325Syongari error = bus_dmamap_load(*tag, *map, *ring, maxsize, et_dma_map_addr, 834228325Syongari &ctx, BUS_DMA_NOWAIT); 835228325Syongari if (error != 0) { 836228325Syongari device_printf(sc->dev, 837228325Syongari "could not load DMA'able memory for %s\n", msg); 838199556Syongari return (error); 839179895Sdelphij } 840228325Syongari *paddr = ctx.et_busaddr; 841228325Syongari return (0); 842228325Syongari} 843179895Sdelphij 844228325Syongaristatic void 845228325Syongariet_dma_ring_free(struct et_softc *sc, bus_dma_tag_t *tag, uint8_t **ring, 846267580Sjhb bus_dmamap_t map, bus_addr_t *paddr) 847228325Syongari{ 848179895Sdelphij 849267580Sjhb if (*paddr != 0) { 850267580Sjhb bus_dmamap_unload(*tag, map); 851267580Sjhb *paddr = 0; 852267580Sjhb } 853267580Sjhb if (*ring != NULL) { 854267580Sjhb bus_dmamem_free(*tag, *ring, map); 855228325Syongari *ring = NULL; 856179895Sdelphij } 857228325Syongari if (*tag) { 858228325Syongari bus_dma_tag_destroy(*tag); 859228325Syongari *tag = NULL; 860228325Syongari } 861228325Syongari} 862179895Sdelphij 863228325Syongaristatic int 864228325Syongariet_dma_alloc(struct et_softc *sc) 865228325Syongari{ 866228325Syongari struct et_txdesc_ring *tx_ring; 867228325Syongari struct et_rxdesc_ring *rx_ring; 868228325Syongari struct et_rxstat_ring *rxst_ring; 869228325Syongari struct et_rxstatus_data *rxsd; 870228325Syongari struct et_rxbuf_data *rbd; 871228325Syongari struct et_txbuf_data *tbd; 872228325Syongari struct et_txstatus_data *txsd; 873228325Syongari int i, error; 874228325Syongari 875228325Syongari error = bus_dma_tag_create(bus_get_dma_tag(sc->dev), 1, 0, 876228325Syongari BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, 877228325Syongari BUS_SPACE_MAXSIZE_32BIT, 0, BUS_SPACE_MAXSIZE_32BIT, 0, NULL, NULL, 878228325Syongari &sc->sc_dtag); 879228325Syongari if (error != 0) { 880228325Syongari device_printf(sc->dev, "could not allocate parent dma tag\n"); 881199556Syongari return (error); 882179895Sdelphij } 883179895Sdelphij 884228325Syongari /* TX ring. */ 885228325Syongari tx_ring = &sc->sc_tx_ring; 886228325Syongari error = et_dma_ring_alloc(sc, ET_RING_ALIGN, ET_TX_RING_SIZE, 887228325Syongari &tx_ring->tr_dtag, (uint8_t **)&tx_ring->tr_desc, &tx_ring->tr_dmap, 888228325Syongari &tx_ring->tr_paddr, "TX ring"); 889228325Syongari if (error) 890199556Syongari return (error); 891179895Sdelphij 892228325Syongari /* TX status block. */ 893228325Syongari txsd = &sc->sc_tx_status; 894228325Syongari error = et_dma_ring_alloc(sc, ET_STATUS_ALIGN, sizeof(uint32_t), 895228325Syongari &txsd->txsd_dtag, (uint8_t **)&txsd->txsd_status, &txsd->txsd_dmap, 896228325Syongari &txsd->txsd_paddr, "TX status block"); 897179895Sdelphij if (error) 898199556Syongari return (error); 899179895Sdelphij 900228325Syongari /* RX ring 0, used as to recive small sized frames. */ 901228325Syongari rx_ring = &sc->sc_rx_ring[0]; 902228325Syongari error = et_dma_ring_alloc(sc, ET_RING_ALIGN, ET_RX_RING_SIZE, 903228325Syongari &rx_ring->rr_dtag, (uint8_t **)&rx_ring->rr_desc, &rx_ring->rr_dmap, 904228325Syongari &rx_ring->rr_paddr, "RX ring 0"); 905228325Syongari rx_ring->rr_posreg = ET_RX_RING0_POS; 906228325Syongari if (error) 907228325Syongari return (error); 908179895Sdelphij 909228325Syongari /* RX ring 1, used as to store normal sized frames. */ 910228325Syongari rx_ring = &sc->sc_rx_ring[1]; 911228325Syongari error = et_dma_ring_alloc(sc, ET_RING_ALIGN, ET_RX_RING_SIZE, 912228325Syongari &rx_ring->rr_dtag, (uint8_t **)&rx_ring->rr_desc, &rx_ring->rr_dmap, 913228325Syongari &rx_ring->rr_paddr, "RX ring 1"); 914228325Syongari rx_ring->rr_posreg = ET_RX_RING1_POS; 915228325Syongari if (error) 916228325Syongari return (error); 917179895Sdelphij 918228325Syongari /* RX stat ring. */ 919228325Syongari rxst_ring = &sc->sc_rxstat_ring; 920228325Syongari error = et_dma_ring_alloc(sc, ET_RING_ALIGN, ET_RXSTAT_RING_SIZE, 921228325Syongari &rxst_ring->rsr_dtag, (uint8_t **)&rxst_ring->rsr_stat, 922228325Syongari &rxst_ring->rsr_dmap, &rxst_ring->rsr_paddr, "RX stat ring"); 923228325Syongari if (error) 924228325Syongari return (error); 925179895Sdelphij 926228325Syongari /* RX status block. */ 927228325Syongari rxsd = &sc->sc_rx_status; 928228325Syongari error = et_dma_ring_alloc(sc, ET_STATUS_ALIGN, 929228325Syongari sizeof(struct et_rxstatus), &rxsd->rxsd_dtag, 930228325Syongari (uint8_t **)&rxsd->rxsd_status, &rxsd->rxsd_dmap, 931228325Syongari &rxsd->rxsd_paddr, "RX status block"); 932228325Syongari if (error) 933228325Syongari return (error); 934179895Sdelphij 935228325Syongari /* Create parent DMA tag for mbufs. */ 936228325Syongari error = bus_dma_tag_create(bus_get_dma_tag(sc->dev), 1, 0, 937228325Syongari BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, 938228325Syongari BUS_SPACE_MAXSIZE_32BIT, 0, BUS_SPACE_MAXSIZE_32BIT, 0, NULL, NULL, 939228325Syongari &sc->sc_mbuf_dtag); 940228325Syongari if (error != 0) { 941228325Syongari device_printf(sc->dev, 942228325Syongari "could not allocate parent dma tag for mbuf\n"); 943228325Syongari return (error); 944228325Syongari } 945179895Sdelphij 946228325Syongari /* Create DMA tag for mini RX mbufs to use RX ring 0. */ 947228325Syongari error = bus_dma_tag_create(sc->sc_mbuf_dtag, 1, 0, 948228325Syongari BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, MHLEN, 1, 949228325Syongari MHLEN, 0, NULL, NULL, &sc->sc_rx_mini_tag); 950228325Syongari if (error) { 951228325Syongari device_printf(sc->dev, "could not create mini RX dma tag\n"); 952228325Syongari return (error); 953179895Sdelphij } 954179895Sdelphij 955228325Syongari /* Create DMA tag for standard RX mbufs to use RX ring 1. */ 956228325Syongari error = bus_dma_tag_create(sc->sc_mbuf_dtag, 1, 0, 957228325Syongari BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, MCLBYTES, 1, 958228325Syongari MCLBYTES, 0, NULL, NULL, &sc->sc_rx_tag); 959228325Syongari if (error) { 960228325Syongari device_printf(sc->dev, "could not create RX dma tag\n"); 961228325Syongari return (error); 962228325Syongari } 963179895Sdelphij 964228325Syongari /* Create DMA tag for TX mbufs. */ 965228325Syongari error = bus_dma_tag_create(sc->sc_mbuf_dtag, 1, 0, 966228325Syongari BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, 967228325Syongari MCLBYTES * ET_NSEG_MAX, ET_NSEG_MAX, MCLBYTES, 0, NULL, NULL, 968228325Syongari &sc->sc_tx_tag); 969179895Sdelphij if (error) { 970228325Syongari device_printf(sc->dev, "could not create TX dma tag\n"); 971199556Syongari return (error); 972179895Sdelphij } 973179895Sdelphij 974228325Syongari /* Initialize RX ring 0. */ 975228325Syongari rbd = &sc->sc_rx_data[0]; 976228325Syongari rbd->rbd_bufsize = ET_RXDMA_CTRL_RING0_128; 977228325Syongari rbd->rbd_newbuf = et_newbuf_hdr; 978228325Syongari rbd->rbd_discard = et_rxbuf_discard; 979228325Syongari rbd->rbd_softc = sc; 980228325Syongari rbd->rbd_ring = &sc->sc_rx_ring[0]; 981228325Syongari /* Create DMA maps for mini RX buffers, ring 0. */ 982228325Syongari for (i = 0; i < ET_RX_NDESC; i++) { 983228325Syongari error = bus_dmamap_create(sc->sc_rx_mini_tag, 0, 984228325Syongari &rbd->rbd_buf[i].rb_dmap); 985228325Syongari if (error) { 986228325Syongari device_printf(sc->dev, 987228325Syongari "could not create DMA map for mini RX mbufs\n"); 988228325Syongari return (error); 989228325Syongari } 990228325Syongari } 991228325Syongari 992228325Syongari /* Create a spare DMA map for mini RX buffers, ring 0. */ 993228325Syongari error = bus_dmamap_create(sc->sc_rx_mini_tag, 0, 994228325Syongari &sc->sc_rx_mini_sparemap); 995179895Sdelphij if (error) { 996228325Syongari device_printf(sc->dev, 997228325Syongari "could not create spare DMA map for mini RX mbuf\n"); 998199556Syongari return (error); 999179895Sdelphij } 1000179895Sdelphij 1001228325Syongari /* Initialize RX ring 1. */ 1002228325Syongari rbd = &sc->sc_rx_data[1]; 1003228325Syongari rbd->rbd_bufsize = ET_RXDMA_CTRL_RING1_2048; 1004228325Syongari rbd->rbd_newbuf = et_newbuf_cluster; 1005228325Syongari rbd->rbd_discard = et_rxbuf_discard; 1006228325Syongari rbd->rbd_softc = sc; 1007228325Syongari rbd->rbd_ring = &sc->sc_rx_ring[1]; 1008228325Syongari /* Create DMA maps for standard RX buffers, ring 1. */ 1009228325Syongari for (i = 0; i < ET_RX_NDESC; i++) { 1010228325Syongari error = bus_dmamap_create(sc->sc_rx_tag, 0, 1011228325Syongari &rbd->rbd_buf[i].rb_dmap); 1012228325Syongari if (error) { 1013228325Syongari device_printf(sc->dev, 1014228325Syongari "could not create DMA map for mini RX mbufs\n"); 1015228325Syongari return (error); 1016179895Sdelphij } 1017228325Syongari } 1018179895Sdelphij 1019228325Syongari /* Create a spare DMA map for standard RX buffers, ring 1. */ 1020228325Syongari error = bus_dmamap_create(sc->sc_rx_tag, 0, &sc->sc_rx_sparemap); 1021228325Syongari if (error) { 1022228325Syongari device_printf(sc->dev, 1023228325Syongari "could not create spare DMA map for RX mbuf\n"); 1024228325Syongari return (error); 1025179895Sdelphij } 1026179895Sdelphij 1027228325Syongari /* Create DMA maps for TX buffers. */ 1028228325Syongari tbd = &sc->sc_tx_data; 1029228325Syongari for (i = 0; i < ET_TX_NDESC; i++) { 1030228325Syongari error = bus_dmamap_create(sc->sc_tx_tag, 0, 1031228325Syongari &tbd->tbd_buf[i].tb_dmap); 1032179895Sdelphij if (error) { 1033228325Syongari device_printf(sc->dev, 1034228325Syongari "could not create DMA map for TX mbufs\n"); 1035199556Syongari return (error); 1036179895Sdelphij } 1037179895Sdelphij } 1038179895Sdelphij 1039199556Syongari return (0); 1040179895Sdelphij} 1041179895Sdelphij 1042179895Sdelphijstatic void 1043228325Syongariet_dma_free(struct et_softc *sc) 1044179895Sdelphij{ 1045228325Syongari struct et_txdesc_ring *tx_ring; 1046228325Syongari struct et_rxdesc_ring *rx_ring; 1047228325Syongari struct et_txstatus_data *txsd; 1048228325Syongari struct et_rxstat_ring *rxst_ring; 1049228325Syongari struct et_rxstatus_data *rxsd; 1050228325Syongari struct et_rxbuf_data *rbd; 1051228325Syongari struct et_txbuf_data *tbd; 1052179895Sdelphij int i; 1053179895Sdelphij 1054228325Syongari /* Destroy DMA maps for mini RX buffers, ring 0. */ 1055228325Syongari rbd = &sc->sc_rx_data[0]; 1056228325Syongari for (i = 0; i < ET_RX_NDESC; i++) { 1057228325Syongari if (rbd->rbd_buf[i].rb_dmap) { 1058228325Syongari bus_dmamap_destroy(sc->sc_rx_mini_tag, 1059228325Syongari rbd->rbd_buf[i].rb_dmap); 1060228325Syongari rbd->rbd_buf[i].rb_dmap = NULL; 1061179895Sdelphij } 1062179895Sdelphij } 1063228325Syongari if (sc->sc_rx_mini_sparemap) { 1064228325Syongari bus_dmamap_destroy(sc->sc_rx_mini_tag, sc->sc_rx_mini_sparemap); 1065228325Syongari sc->sc_rx_mini_sparemap = NULL; 1066179895Sdelphij } 1067228325Syongari if (sc->sc_rx_mini_tag) { 1068228325Syongari bus_dma_tag_destroy(sc->sc_rx_mini_tag); 1069228325Syongari sc->sc_rx_mini_tag = NULL; 1070179895Sdelphij } 1071179895Sdelphij 1072228325Syongari /* Destroy DMA maps for standard RX buffers, ring 1. */ 1073228325Syongari rbd = &sc->sc_rx_data[1]; 1074228325Syongari for (i = 0; i < ET_RX_NDESC; i++) { 1075228325Syongari if (rbd->rbd_buf[i].rb_dmap) { 1076228325Syongari bus_dmamap_destroy(sc->sc_rx_tag, 1077228325Syongari rbd->rbd_buf[i].rb_dmap); 1078228325Syongari rbd->rbd_buf[i].rb_dmap = NULL; 1079228325Syongari } 1080179895Sdelphij } 1081228325Syongari if (sc->sc_rx_sparemap) { 1082228325Syongari bus_dmamap_destroy(sc->sc_rx_tag, sc->sc_rx_sparemap); 1083228325Syongari sc->sc_rx_sparemap = NULL; 1084228325Syongari } 1085228325Syongari if (sc->sc_rx_tag) { 1086228325Syongari bus_dma_tag_destroy(sc->sc_rx_tag); 1087228325Syongari sc->sc_rx_tag = NULL; 1088228325Syongari } 1089179895Sdelphij 1090228325Syongari /* Destroy DMA maps for TX buffers. */ 1091228325Syongari tbd = &sc->sc_tx_data; 1092228325Syongari for (i = 0; i < ET_TX_NDESC; i++) { 1093228325Syongari if (tbd->tbd_buf[i].tb_dmap) { 1094228325Syongari bus_dmamap_destroy(sc->sc_tx_tag, 1095228325Syongari tbd->tbd_buf[i].tb_dmap); 1096228325Syongari tbd->tbd_buf[i].tb_dmap = NULL; 1097228325Syongari } 1098179895Sdelphij } 1099228325Syongari if (sc->sc_tx_tag) { 1100228325Syongari bus_dma_tag_destroy(sc->sc_tx_tag); 1101228325Syongari sc->sc_tx_tag = NULL; 1102228325Syongari } 1103179895Sdelphij 1104228325Syongari /* Destroy mini RX ring, ring 0. */ 1105228325Syongari rx_ring = &sc->sc_rx_ring[0]; 1106228325Syongari et_dma_ring_free(sc, &rx_ring->rr_dtag, (void *)&rx_ring->rr_desc, 1107267580Sjhb rx_ring->rr_dmap, &rx_ring->rr_paddr); 1108228325Syongari /* Destroy standard RX ring, ring 1. */ 1109228325Syongari rx_ring = &sc->sc_rx_ring[1]; 1110228325Syongari et_dma_ring_free(sc, &rx_ring->rr_dtag, (void *)&rx_ring->rr_desc, 1111267580Sjhb rx_ring->rr_dmap, &rx_ring->rr_paddr); 1112228325Syongari /* Destroy RX stat ring. */ 1113228325Syongari rxst_ring = &sc->sc_rxstat_ring; 1114228325Syongari et_dma_ring_free(sc, &rxst_ring->rsr_dtag, (void *)&rxst_ring->rsr_stat, 1115267580Sjhb rxst_ring->rsr_dmap, &rxst_ring->rsr_paddr); 1116228325Syongari /* Destroy RX status block. */ 1117228325Syongari rxsd = &sc->sc_rx_status; 1118228325Syongari et_dma_ring_free(sc, &rxst_ring->rsr_dtag, (void *)&rxst_ring->rsr_stat, 1119267580Sjhb rxst_ring->rsr_dmap, &rxst_ring->rsr_paddr); 1120228325Syongari /* Destroy TX ring. */ 1121228325Syongari tx_ring = &sc->sc_tx_ring; 1122228325Syongari et_dma_ring_free(sc, &tx_ring->tr_dtag, (void *)&tx_ring->tr_desc, 1123267580Sjhb tx_ring->tr_dmap, &tx_ring->tr_paddr); 1124228325Syongari /* Destroy TX status block. */ 1125228325Syongari txsd = &sc->sc_tx_status; 1126228325Syongari et_dma_ring_free(sc, &txsd->txsd_dtag, (void *)&txsd->txsd_status, 1127267580Sjhb txsd->txsd_dmap, &txsd->txsd_paddr); 1128228325Syongari 1129228325Syongari /* Destroy the parent tag. */ 1130228325Syongari if (sc->sc_dtag) { 1131228325Syongari bus_dma_tag_destroy(sc->sc_dtag); 1132228325Syongari sc->sc_dtag = NULL; 1133179895Sdelphij } 1134179895Sdelphij} 1135179895Sdelphij 1136179895Sdelphijstatic void 1137179895Sdelphijet_chip_attach(struct et_softc *sc) 1138179895Sdelphij{ 1139179895Sdelphij uint32_t val; 1140179895Sdelphij 1141179895Sdelphij /* 1142179895Sdelphij * Perform minimal initialization 1143179895Sdelphij */ 1144179895Sdelphij 1145179895Sdelphij /* Disable loopback */ 1146179895Sdelphij CSR_WRITE_4(sc, ET_LOOPBACK, 0); 1147179895Sdelphij 1148179895Sdelphij /* Reset MAC */ 1149179895Sdelphij CSR_WRITE_4(sc, ET_MAC_CFG1, 1150179895Sdelphij ET_MAC_CFG1_RST_TXFUNC | ET_MAC_CFG1_RST_RXFUNC | 1151179895Sdelphij ET_MAC_CFG1_RST_TXMC | ET_MAC_CFG1_RST_RXMC | 1152179895Sdelphij ET_MAC_CFG1_SIM_RST | ET_MAC_CFG1_SOFT_RST); 1153179895Sdelphij 1154179895Sdelphij /* 1155179895Sdelphij * Setup half duplex mode 1156179895Sdelphij */ 1157199548Syongari val = (10 << ET_MAC_HDX_ALT_BEB_TRUNC_SHIFT) | 1158199548Syongari (15 << ET_MAC_HDX_REXMIT_MAX_SHIFT) | 1159199548Syongari (55 << ET_MAC_HDX_COLLWIN_SHIFT) | 1160199548Syongari ET_MAC_HDX_EXC_DEFER; 1161179895Sdelphij CSR_WRITE_4(sc, ET_MAC_HDX, val); 1162179895Sdelphij 1163179895Sdelphij /* Clear MAC control */ 1164179895Sdelphij CSR_WRITE_4(sc, ET_MAC_CTRL, 0); 1165179895Sdelphij 1166179895Sdelphij /* Reset MII */ 1167179895Sdelphij CSR_WRITE_4(sc, ET_MII_CFG, ET_MII_CFG_CLKRST); 1168179895Sdelphij 1169179895Sdelphij /* Bring MAC out of reset state */ 1170179895Sdelphij CSR_WRITE_4(sc, ET_MAC_CFG1, 0); 1171179895Sdelphij 1172179895Sdelphij /* Enable memory controllers */ 1173179895Sdelphij CSR_WRITE_4(sc, ET_MMC_CTRL, ET_MMC_CTRL_ENABLE); 1174179895Sdelphij} 1175179895Sdelphij 1176179895Sdelphijstatic void 1177179895Sdelphijet_intr(void *xsc) 1178179895Sdelphij{ 1179229940Syongari struct et_softc *sc; 1180179895Sdelphij struct ifnet *ifp; 1181228362Syongari uint32_t status; 1182179895Sdelphij 1183229940Syongari sc = xsc; 1184179895Sdelphij ET_LOCK(sc); 1185179895Sdelphij ifp = sc->ifp; 1186228362Syongari if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) 1187228362Syongari goto done; 1188179895Sdelphij 1189228362Syongari status = CSR_READ_4(sc, ET_INTR_STATUS); 1190228362Syongari if ((status & ET_INTRS) == 0) 1191228362Syongari goto done; 1192228362Syongari 1193228327Syongari /* Disable further interrupts. */ 1194228327Syongari CSR_WRITE_4(sc, ET_INTR_MASK, 0xffffffff); 1195179895Sdelphij 1196228362Syongari if (status & (ET_INTR_RXDMA_ERROR | ET_INTR_TXDMA_ERROR)) { 1197228362Syongari device_printf(sc->dev, "DMA error(0x%08x) -- resetting\n", 1198228362Syongari status); 1199228362Syongari ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 1200228362Syongari et_init_locked(sc); 1201228362Syongari ET_UNLOCK(sc); 1202228362Syongari return; 1203228362Syongari } 1204228362Syongari if (status & ET_INTR_RXDMA) 1205179895Sdelphij et_rxeof(sc); 1206228362Syongari if (status & (ET_INTR_TXDMA | ET_INTR_TIMER)) 1207179895Sdelphij et_txeof(sc); 1208228362Syongari if (status & ET_INTR_TIMER) 1209179895Sdelphij CSR_WRITE_4(sc, ET_TIMER, sc->sc_timer); 1210228326Syongari if (ifp->if_drv_flags & IFF_DRV_RUNNING) { 1211228327Syongari CSR_WRITE_4(sc, ET_INTR_MASK, ~ET_INTRS); 1212228326Syongari if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) 1213228326Syongari et_start_locked(ifp); 1214228326Syongari } 1215228362Syongaridone: 1216179895Sdelphij ET_UNLOCK(sc); 1217179895Sdelphij} 1218179895Sdelphij 1219179895Sdelphijstatic void 1220179895Sdelphijet_init_locked(struct et_softc *sc) 1221179895Sdelphij{ 1222228325Syongari struct ifnet *ifp; 1223228325Syongari int error; 1224179895Sdelphij 1225179895Sdelphij ET_LOCK_ASSERT(sc); 1226179895Sdelphij 1227228325Syongari ifp = sc->ifp; 1228179895Sdelphij if (ifp->if_drv_flags & IFF_DRV_RUNNING) 1229179895Sdelphij return; 1230179895Sdelphij 1231179895Sdelphij et_stop(sc); 1232228331Syongari et_reset(sc); 1233179895Sdelphij 1234228325Syongari et_init_tx_ring(sc); 1235179895Sdelphij error = et_init_rx_ring(sc); 1236179895Sdelphij if (error) 1237228325Syongari return; 1238179895Sdelphij 1239179895Sdelphij error = et_chip_init(sc); 1240179895Sdelphij if (error) 1241228331Syongari goto fail; 1242179895Sdelphij 1243228331Syongari /* 1244228331Syongari * Start TX/RX DMA engine 1245228331Syongari */ 1246228331Syongari error = et_start_rxdma(sc); 1247179895Sdelphij if (error) 1248228331Syongari return; 1249179895Sdelphij 1250228331Syongari error = et_start_txdma(sc); 1251228331Syongari if (error) 1252228331Syongari return; 1253228331Syongari 1254228327Syongari /* Enable interrupts. */ 1255228327Syongari CSR_WRITE_4(sc, ET_INTR_MASK, ~ET_INTRS); 1256179895Sdelphij 1257179895Sdelphij CSR_WRITE_4(sc, ET_TIMER, sc->sc_timer); 1258179895Sdelphij 1259179895Sdelphij ifp->if_drv_flags |= IFF_DRV_RUNNING; 1260179895Sdelphij ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 1261228331Syongari 1262228331Syongari sc->sc_flags &= ~ET_FLAG_LINK; 1263228331Syongari et_ifmedia_upd_locked(ifp); 1264228331Syongari 1265228331Syongari callout_reset(&sc->sc_tick, hz, et_tick, sc); 1266228331Syongari 1267228331Syongarifail: 1268179895Sdelphij if (error) 1269179895Sdelphij et_stop(sc); 1270179895Sdelphij} 1271179895Sdelphij 1272179895Sdelphijstatic void 1273179895Sdelphijet_init(void *xsc) 1274179895Sdelphij{ 1275179895Sdelphij struct et_softc *sc = xsc; 1276179895Sdelphij 1277179895Sdelphij ET_LOCK(sc); 1278179895Sdelphij et_init_locked(sc); 1279179895Sdelphij ET_UNLOCK(sc); 1280179895Sdelphij} 1281179895Sdelphij 1282179895Sdelphijstatic int 1283179895Sdelphijet_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 1284179895Sdelphij{ 1285229940Syongari struct et_softc *sc; 1286229940Syongari struct mii_data *mii; 1287229940Syongari struct ifreq *ifr; 1288229940Syongari int error, mask, max_framelen; 1289179895Sdelphij 1290229940Syongari sc = ifp->if_softc; 1291229940Syongari ifr = (struct ifreq *)data; 1292229940Syongari error = 0; 1293229940Syongari 1294179895Sdelphij/* XXX LOCKSUSED */ 1295179895Sdelphij switch (cmd) { 1296179895Sdelphij case SIOCSIFFLAGS: 1297179895Sdelphij ET_LOCK(sc); 1298179895Sdelphij if (ifp->if_flags & IFF_UP) { 1299179895Sdelphij if (ifp->if_drv_flags & IFF_DRV_RUNNING) { 1300179895Sdelphij if ((ifp->if_flags ^ sc->sc_if_flags) & 1301179895Sdelphij (IFF_ALLMULTI | IFF_PROMISC | IFF_BROADCAST)) 1302179895Sdelphij et_setmulti(sc); 1303179895Sdelphij } else { 1304179895Sdelphij et_init_locked(sc); 1305179895Sdelphij } 1306179895Sdelphij } else { 1307179895Sdelphij if (ifp->if_drv_flags & IFF_DRV_RUNNING) 1308179895Sdelphij et_stop(sc); 1309179895Sdelphij } 1310179895Sdelphij sc->sc_if_flags = ifp->if_flags; 1311179895Sdelphij ET_UNLOCK(sc); 1312179895Sdelphij break; 1313179895Sdelphij 1314179895Sdelphij case SIOCSIFMEDIA: 1315179895Sdelphij case SIOCGIFMEDIA: 1316229940Syongari mii = device_get_softc(sc->sc_miibus); 1317179895Sdelphij error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, cmd); 1318179895Sdelphij break; 1319179895Sdelphij 1320179895Sdelphij case SIOCADDMULTI: 1321179895Sdelphij case SIOCDELMULTI: 1322179895Sdelphij if (ifp->if_drv_flags & IFF_DRV_RUNNING) { 1323179895Sdelphij ET_LOCK(sc); 1324179895Sdelphij et_setmulti(sc); 1325179895Sdelphij ET_UNLOCK(sc); 1326179895Sdelphij } 1327179895Sdelphij break; 1328179895Sdelphij 1329179895Sdelphij case SIOCSIFMTU: 1330228333Syongari ET_LOCK(sc); 1331179895Sdelphij#if 0 1332179895Sdelphij if (sc->sc_flags & ET_FLAG_JUMBO) 1333179895Sdelphij max_framelen = ET_JUMBO_FRAMELEN; 1334179895Sdelphij else 1335179895Sdelphij#endif 1336179895Sdelphij max_framelen = MCLBYTES - 1; 1337179895Sdelphij 1338179895Sdelphij if (ET_FRAMELEN(ifr->ifr_mtu) > max_framelen) { 1339179895Sdelphij error = EOPNOTSUPP; 1340228333Syongari ET_UNLOCK(sc); 1341179895Sdelphij break; 1342179895Sdelphij } 1343179895Sdelphij 1344179895Sdelphij if (ifp->if_mtu != ifr->ifr_mtu) { 1345179895Sdelphij ifp->if_mtu = ifr->ifr_mtu; 1346228333Syongari if (ifp->if_drv_flags & IFF_DRV_RUNNING) { 1347228333Syongari ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 1348228333Syongari et_init_locked(sc); 1349228333Syongari } 1350179895Sdelphij } 1351228333Syongari ET_UNLOCK(sc); 1352179895Sdelphij break; 1353179895Sdelphij 1354199611Syongari case SIOCSIFCAP: 1355199611Syongari ET_LOCK(sc); 1356199611Syongari mask = ifr->ifr_reqcap ^ ifp->if_capenable; 1357199611Syongari if ((mask & IFCAP_TXCSUM) != 0 && 1358199611Syongari (IFCAP_TXCSUM & ifp->if_capabilities) != 0) { 1359199611Syongari ifp->if_capenable ^= IFCAP_TXCSUM; 1360199611Syongari if ((IFCAP_TXCSUM & ifp->if_capenable) != 0) 1361199611Syongari ifp->if_hwassist |= ET_CSUM_FEATURES; 1362199611Syongari else 1363199611Syongari ifp->if_hwassist &= ~ET_CSUM_FEATURES; 1364199611Syongari } 1365199611Syongari ET_UNLOCK(sc); 1366199611Syongari break; 1367199611Syongari 1368179895Sdelphij default: 1369179895Sdelphij error = ether_ioctl(ifp, cmd, data); 1370179895Sdelphij break; 1371179895Sdelphij } 1372199556Syongari return (error); 1373179895Sdelphij} 1374179895Sdelphij 1375179895Sdelphijstatic void 1376179895Sdelphijet_start_locked(struct ifnet *ifp) 1377179895Sdelphij{ 1378228293Syongari struct et_softc *sc; 1379228293Syongari struct mbuf *m_head = NULL; 1380228326Syongari struct et_txdesc_ring *tx_ring; 1381179895Sdelphij struct et_txbuf_data *tbd; 1382228326Syongari uint32_t tx_ready_pos; 1383228293Syongari int enq; 1384179895Sdelphij 1385228293Syongari sc = ifp->if_softc; 1386179895Sdelphij ET_LOCK_ASSERT(sc); 1387179895Sdelphij 1388228331Syongari if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) != 1389228331Syongari IFF_DRV_RUNNING || 1390228331Syongari (sc->sc_flags & (ET_FLAG_LINK | ET_FLAG_TXRX_ENABLED)) != 1391228331Syongari (ET_FLAG_LINK | ET_FLAG_TXRX_ENABLED)) 1392179895Sdelphij return; 1393179895Sdelphij 1394228326Syongari /* 1395228326Syongari * Driver does not request TX completion interrupt for every 1396228326Syongari * queued frames to prevent generating excessive interrupts. 1397228326Syongari * This means driver may wait for TX completion interrupt even 1398298955Spfg * though some frames were successfully transmitted. Reclaiming 1399228326Syongari * transmitted frames will ensure driver see all available 1400228326Syongari * descriptors. 1401228326Syongari */ 1402228293Syongari tbd = &sc->sc_tx_data; 1403228326Syongari if (tbd->tbd_used > (ET_TX_NDESC * 2) / 3) 1404228326Syongari et_txeof(sc); 1405228326Syongari 1406228293Syongari for (enq = 0; !IFQ_DRV_IS_EMPTY(&ifp->if_snd); ) { 1407228293Syongari if (tbd->tbd_used + ET_NSEG_SPARE >= ET_TX_NDESC) { 1408179895Sdelphij ifp->if_drv_flags |= IFF_DRV_OACTIVE; 1409179895Sdelphij break; 1410179895Sdelphij } 1411179895Sdelphij 1412228293Syongari IFQ_DRV_DEQUEUE(&ifp->if_snd, m_head); 1413228293Syongari if (m_head == NULL) 1414179895Sdelphij break; 1415179895Sdelphij 1416228293Syongari if (et_encap(sc, &m_head)) { 1417228293Syongari if (m_head == NULL) { 1418272064Sglebius if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); 1419228293Syongari break; 1420228293Syongari } 1421228293Syongari IFQ_DRV_PREPEND(&ifp->if_snd, m_head); 1422228293Syongari if (tbd->tbd_used > 0) 1423228293Syongari ifp->if_drv_flags |= IFF_DRV_OACTIVE; 1424179895Sdelphij break; 1425179895Sdelphij } 1426228293Syongari enq++; 1427228293Syongari ETHER_BPF_MTAP(ifp, m_head); 1428179895Sdelphij } 1429179895Sdelphij 1430228326Syongari if (enq > 0) { 1431228326Syongari tx_ring = &sc->sc_tx_ring; 1432228326Syongari bus_dmamap_sync(tx_ring->tr_dtag, tx_ring->tr_dmap, 1433228326Syongari BUS_DMASYNC_PREWRITE); 1434228326Syongari tx_ready_pos = tx_ring->tr_ready_index & 1435228326Syongari ET_TX_READY_POS_INDEX_MASK; 1436228326Syongari if (tx_ring->tr_ready_wrap) 1437228326Syongari tx_ready_pos |= ET_TX_READY_POS_WRAP; 1438228326Syongari CSR_WRITE_4(sc, ET_TX_READY_POS, tx_ready_pos); 1439179895Sdelphij sc->watchdog_timer = 5; 1440228326Syongari } 1441179895Sdelphij} 1442179895Sdelphij 1443179895Sdelphijstatic void 1444179895Sdelphijet_start(struct ifnet *ifp) 1445179895Sdelphij{ 1446229940Syongari struct et_softc *sc; 1447179895Sdelphij 1448229940Syongari sc = ifp->if_softc; 1449179895Sdelphij ET_LOCK(sc); 1450179895Sdelphij et_start_locked(ifp); 1451179895Sdelphij ET_UNLOCK(sc); 1452179895Sdelphij} 1453179895Sdelphij 1454228325Syongaristatic int 1455179895Sdelphijet_watchdog(struct et_softc *sc) 1456179895Sdelphij{ 1457228325Syongari uint32_t status; 1458228325Syongari 1459179895Sdelphij ET_LOCK_ASSERT(sc); 1460179895Sdelphij 1461179895Sdelphij if (sc->watchdog_timer == 0 || --sc->watchdog_timer) 1462228325Syongari return (0); 1463179895Sdelphij 1464228325Syongari bus_dmamap_sync(sc->sc_tx_status.txsd_dtag, sc->sc_tx_status.txsd_dmap, 1465228325Syongari BUS_DMASYNC_POSTREAD); 1466228325Syongari status = le32toh(*(sc->sc_tx_status.txsd_status)); 1467228325Syongari if_printf(sc->ifp, "watchdog timed out (0x%08x) -- resetting\n", 1468228325Syongari status); 1469179895Sdelphij 1470272064Sglebius if_inc_counter(sc->ifp, IFCOUNTER_OERRORS, 1); 1471212969Syongari sc->ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 1472179895Sdelphij et_init_locked(sc); 1473228325Syongari return (EJUSTRETURN); 1474179895Sdelphij} 1475179895Sdelphij 1476179895Sdelphijstatic int 1477179895Sdelphijet_stop_rxdma(struct et_softc *sc) 1478179895Sdelphij{ 1479229940Syongari 1480179895Sdelphij CSR_WRITE_4(sc, ET_RXDMA_CTRL, 1481179895Sdelphij ET_RXDMA_CTRL_HALT | ET_RXDMA_CTRL_RING1_ENABLE); 1482179895Sdelphij 1483179895Sdelphij DELAY(5); 1484179895Sdelphij if ((CSR_READ_4(sc, ET_RXDMA_CTRL) & ET_RXDMA_CTRL_HALTED) == 0) { 1485179895Sdelphij if_printf(sc->ifp, "can't stop RX DMA engine\n"); 1486199556Syongari return (ETIMEDOUT); 1487179895Sdelphij } 1488199556Syongari return (0); 1489179895Sdelphij} 1490179895Sdelphij 1491179895Sdelphijstatic int 1492179895Sdelphijet_stop_txdma(struct et_softc *sc) 1493179895Sdelphij{ 1494229940Syongari 1495179895Sdelphij CSR_WRITE_4(sc, ET_TXDMA_CTRL, 1496179895Sdelphij ET_TXDMA_CTRL_HALT | ET_TXDMA_CTRL_SINGLE_EPKT); 1497199556Syongari return (0); 1498179895Sdelphij} 1499179895Sdelphij 1500179895Sdelphijstatic void 1501179895Sdelphijet_free_tx_ring(struct et_softc *sc) 1502179895Sdelphij{ 1503228325Syongari struct et_txdesc_ring *tx_ring; 1504228325Syongari struct et_txbuf_data *tbd; 1505228325Syongari struct et_txbuf *tb; 1506179895Sdelphij int i; 1507179895Sdelphij 1508228325Syongari tbd = &sc->sc_tx_data; 1509228325Syongari tx_ring = &sc->sc_tx_ring; 1510179895Sdelphij for (i = 0; i < ET_TX_NDESC; ++i) { 1511228325Syongari tb = &tbd->tbd_buf[i]; 1512179895Sdelphij if (tb->tb_mbuf != NULL) { 1513228325Syongari bus_dmamap_sync(sc->sc_tx_tag, tb->tb_dmap, 1514228325Syongari BUS_DMASYNC_POSTWRITE); 1515179895Sdelphij bus_dmamap_unload(sc->sc_mbuf_dtag, tb->tb_dmap); 1516179895Sdelphij m_freem(tb->tb_mbuf); 1517179895Sdelphij tb->tb_mbuf = NULL; 1518179895Sdelphij } 1519179895Sdelphij } 1520179895Sdelphij} 1521179895Sdelphij 1522179895Sdelphijstatic void 1523179895Sdelphijet_free_rx_ring(struct et_softc *sc) 1524179895Sdelphij{ 1525228325Syongari struct et_rxbuf_data *rbd; 1526228325Syongari struct et_rxdesc_ring *rx_ring; 1527228325Syongari struct et_rxbuf *rb; 1528228325Syongari int i; 1529179895Sdelphij 1530228325Syongari /* Ring 0 */ 1531228325Syongari rx_ring = &sc->sc_rx_ring[0]; 1532228325Syongari rbd = &sc->sc_rx_data[0]; 1533228325Syongari for (i = 0; i < ET_RX_NDESC; ++i) { 1534228325Syongari rb = &rbd->rbd_buf[i]; 1535228325Syongari if (rb->rb_mbuf != NULL) { 1536228325Syongari bus_dmamap_sync(sc->sc_rx_mini_tag, rx_ring->rr_dmap, 1537228325Syongari BUS_DMASYNC_POSTREAD); 1538228325Syongari bus_dmamap_unload(sc->sc_rx_mini_tag, rb->rb_dmap); 1539228325Syongari m_freem(rb->rb_mbuf); 1540228325Syongari rb->rb_mbuf = NULL; 1541228325Syongari } 1542228325Syongari } 1543179895Sdelphij 1544228325Syongari /* Ring 1 */ 1545228325Syongari rx_ring = &sc->sc_rx_ring[1]; 1546228325Syongari rbd = &sc->sc_rx_data[1]; 1547228325Syongari for (i = 0; i < ET_RX_NDESC; ++i) { 1548228325Syongari rb = &rbd->rbd_buf[i]; 1549228325Syongari if (rb->rb_mbuf != NULL) { 1550228325Syongari bus_dmamap_sync(sc->sc_rx_tag, rx_ring->rr_dmap, 1551228325Syongari BUS_DMASYNC_POSTREAD); 1552228325Syongari bus_dmamap_unload(sc->sc_rx_tag, rb->rb_dmap); 1553228325Syongari m_freem(rb->rb_mbuf); 1554228325Syongari rb->rb_mbuf = NULL; 1555179895Sdelphij } 1556179895Sdelphij } 1557179895Sdelphij} 1558179895Sdelphij 1559179895Sdelphijstatic void 1560179895Sdelphijet_setmulti(struct et_softc *sc) 1561179895Sdelphij{ 1562179895Sdelphij struct ifnet *ifp; 1563179895Sdelphij uint32_t hash[4] = { 0, 0, 0, 0 }; 1564179895Sdelphij uint32_t rxmac_ctrl, pktfilt; 1565179895Sdelphij struct ifmultiaddr *ifma; 1566179895Sdelphij int i, count; 1567179895Sdelphij 1568179895Sdelphij ET_LOCK_ASSERT(sc); 1569179895Sdelphij ifp = sc->ifp; 1570179895Sdelphij 1571179895Sdelphij pktfilt = CSR_READ_4(sc, ET_PKTFILT); 1572179895Sdelphij rxmac_ctrl = CSR_READ_4(sc, ET_RXMAC_CTRL); 1573179895Sdelphij 1574179895Sdelphij pktfilt &= ~(ET_PKTFILT_BCAST | ET_PKTFILT_MCAST | ET_PKTFILT_UCAST); 1575179895Sdelphij if (ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI)) { 1576179895Sdelphij rxmac_ctrl |= ET_RXMAC_CTRL_NO_PKTFILT; 1577179895Sdelphij goto back; 1578179895Sdelphij } 1579179895Sdelphij 1580179895Sdelphij count = 0; 1581195049Srwatson if_maddr_rlock(ifp); 1582179895Sdelphij TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { 1583179895Sdelphij uint32_t *hp, h; 1584179895Sdelphij 1585179895Sdelphij if (ifma->ifma_addr->sa_family != AF_LINK) 1586179895Sdelphij continue; 1587179895Sdelphij 1588179895Sdelphij h = ether_crc32_be(LLADDR((struct sockaddr_dl *) 1589179895Sdelphij ifma->ifma_addr), ETHER_ADDR_LEN); 1590179895Sdelphij h = (h & 0x3f800000) >> 23; 1591179895Sdelphij 1592179895Sdelphij hp = &hash[0]; 1593179895Sdelphij if (h >= 32 && h < 64) { 1594179895Sdelphij h -= 32; 1595179895Sdelphij hp = &hash[1]; 1596179895Sdelphij } else if (h >= 64 && h < 96) { 1597179895Sdelphij h -= 64; 1598179895Sdelphij hp = &hash[2]; 1599179895Sdelphij } else if (h >= 96) { 1600179895Sdelphij h -= 96; 1601179895Sdelphij hp = &hash[3]; 1602179895Sdelphij } 1603179895Sdelphij *hp |= (1 << h); 1604179895Sdelphij 1605179895Sdelphij ++count; 1606179895Sdelphij } 1607195049Srwatson if_maddr_runlock(ifp); 1608179895Sdelphij 1609179895Sdelphij for (i = 0; i < 4; ++i) 1610179895Sdelphij CSR_WRITE_4(sc, ET_MULTI_HASH + (i * 4), hash[i]); 1611179895Sdelphij 1612179895Sdelphij if (count > 0) 1613179895Sdelphij pktfilt |= ET_PKTFILT_MCAST; 1614179895Sdelphij rxmac_ctrl &= ~ET_RXMAC_CTRL_NO_PKTFILT; 1615179895Sdelphijback: 1616179895Sdelphij CSR_WRITE_4(sc, ET_PKTFILT, pktfilt); 1617179895Sdelphij CSR_WRITE_4(sc, ET_RXMAC_CTRL, rxmac_ctrl); 1618179895Sdelphij} 1619179895Sdelphij 1620179895Sdelphijstatic int 1621179895Sdelphijet_chip_init(struct et_softc *sc) 1622179895Sdelphij{ 1623229940Syongari struct ifnet *ifp; 1624179895Sdelphij uint32_t rxq_end; 1625179895Sdelphij int error, frame_len, rxmem_size; 1626179895Sdelphij 1627229940Syongari ifp = sc->ifp; 1628179895Sdelphij /* 1629179895Sdelphij * Split 16Kbytes internal memory between TX and RX 1630179895Sdelphij * according to frame length. 1631179895Sdelphij */ 1632179895Sdelphij frame_len = ET_FRAMELEN(ifp->if_mtu); 1633179895Sdelphij if (frame_len < 2048) { 1634179895Sdelphij rxmem_size = ET_MEM_RXSIZE_DEFAULT; 1635179895Sdelphij } else if (frame_len <= ET_RXMAC_CUT_THRU_FRMLEN) { 1636179895Sdelphij rxmem_size = ET_MEM_SIZE / 2; 1637179895Sdelphij } else { 1638179895Sdelphij rxmem_size = ET_MEM_SIZE - 1639179895Sdelphij roundup(frame_len + ET_MEM_TXSIZE_EX, ET_MEM_UNIT); 1640179895Sdelphij } 1641179895Sdelphij rxq_end = ET_QUEUE_ADDR(rxmem_size); 1642179895Sdelphij 1643179895Sdelphij CSR_WRITE_4(sc, ET_RXQUEUE_START, ET_QUEUE_ADDR_START); 1644179895Sdelphij CSR_WRITE_4(sc, ET_RXQUEUE_END, rxq_end); 1645179895Sdelphij CSR_WRITE_4(sc, ET_TXQUEUE_START, rxq_end + 1); 1646179895Sdelphij CSR_WRITE_4(sc, ET_TXQUEUE_END, ET_QUEUE_ADDR_END); 1647179895Sdelphij 1648179895Sdelphij /* No loopback */ 1649179895Sdelphij CSR_WRITE_4(sc, ET_LOOPBACK, 0); 1650179895Sdelphij 1651179895Sdelphij /* Clear MSI configure */ 1652199552Syongari if ((sc->sc_flags & ET_FLAG_MSI) == 0) 1653199552Syongari CSR_WRITE_4(sc, ET_MSI_CFG, 0); 1654179895Sdelphij 1655179895Sdelphij /* Disable timer */ 1656179895Sdelphij CSR_WRITE_4(sc, ET_TIMER, 0); 1657179895Sdelphij 1658179895Sdelphij /* Initialize MAC */ 1659179895Sdelphij et_init_mac(sc); 1660179895Sdelphij 1661179895Sdelphij /* Enable memory controllers */ 1662179895Sdelphij CSR_WRITE_4(sc, ET_MMC_CTRL, ET_MMC_CTRL_ENABLE); 1663179895Sdelphij 1664179895Sdelphij /* Initialize RX MAC */ 1665179895Sdelphij et_init_rxmac(sc); 1666179895Sdelphij 1667179895Sdelphij /* Initialize TX MAC */ 1668179895Sdelphij et_init_txmac(sc); 1669179895Sdelphij 1670179895Sdelphij /* Initialize RX DMA engine */ 1671179895Sdelphij error = et_init_rxdma(sc); 1672179895Sdelphij if (error) 1673199556Syongari return (error); 1674179895Sdelphij 1675179895Sdelphij /* Initialize TX DMA engine */ 1676179895Sdelphij error = et_init_txdma(sc); 1677179895Sdelphij if (error) 1678199556Syongari return (error); 1679179895Sdelphij 1680199556Syongari return (0); 1681179895Sdelphij} 1682179895Sdelphij 1683228325Syongaristatic void 1684179895Sdelphijet_init_tx_ring(struct et_softc *sc) 1685179895Sdelphij{ 1686228325Syongari struct et_txdesc_ring *tx_ring; 1687228325Syongari struct et_txbuf_data *tbd; 1688228325Syongari struct et_txstatus_data *txsd; 1689179895Sdelphij 1690228325Syongari tx_ring = &sc->sc_tx_ring; 1691179895Sdelphij bzero(tx_ring->tr_desc, ET_TX_RING_SIZE); 1692179895Sdelphij bus_dmamap_sync(tx_ring->tr_dtag, tx_ring->tr_dmap, 1693228325Syongari BUS_DMASYNC_PREWRITE); 1694179895Sdelphij 1695228325Syongari tbd = &sc->sc_tx_data; 1696179895Sdelphij tbd->tbd_start_index = 0; 1697179895Sdelphij tbd->tbd_start_wrap = 0; 1698179895Sdelphij tbd->tbd_used = 0; 1699179895Sdelphij 1700228325Syongari txsd = &sc->sc_tx_status; 1701179895Sdelphij bzero(txsd->txsd_status, sizeof(uint32_t)); 1702179895Sdelphij bus_dmamap_sync(txsd->txsd_dtag, txsd->txsd_dmap, 1703228325Syongari BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 1704179895Sdelphij} 1705179895Sdelphij 1706179895Sdelphijstatic int 1707179895Sdelphijet_init_rx_ring(struct et_softc *sc) 1708179895Sdelphij{ 1709228325Syongari struct et_rxstatus_data *rxsd; 1710228325Syongari struct et_rxstat_ring *rxst_ring; 1711228325Syongari struct et_rxbuf_data *rbd; 1712228325Syongari int i, error, n; 1713179895Sdelphij 1714179895Sdelphij for (n = 0; n < ET_RX_NRING; ++n) { 1715228325Syongari rbd = &sc->sc_rx_data[n]; 1716179895Sdelphij for (i = 0; i < ET_RX_NDESC; ++i) { 1717228325Syongari error = rbd->rbd_newbuf(rbd, i); 1718179895Sdelphij if (error) { 1719179895Sdelphij if_printf(sc->ifp, "%d ring %d buf, " 1720179895Sdelphij "newbuf failed: %d\n", n, i, error); 1721199556Syongari return (error); 1722179895Sdelphij } 1723179895Sdelphij } 1724179895Sdelphij } 1725179895Sdelphij 1726228325Syongari rxsd = &sc->sc_rx_status; 1727179895Sdelphij bzero(rxsd->rxsd_status, sizeof(struct et_rxstatus)); 1728179895Sdelphij bus_dmamap_sync(rxsd->rxsd_dtag, rxsd->rxsd_dmap, 1729228325Syongari BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 1730179895Sdelphij 1731228325Syongari rxst_ring = &sc->sc_rxstat_ring; 1732179895Sdelphij bzero(rxst_ring->rsr_stat, ET_RXSTAT_RING_SIZE); 1733179895Sdelphij bus_dmamap_sync(rxst_ring->rsr_dtag, rxst_ring->rsr_dmap, 1734228325Syongari BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 1735179895Sdelphij 1736199556Syongari return (0); 1737179895Sdelphij} 1738179895Sdelphij 1739179895Sdelphijstatic int 1740179895Sdelphijet_init_rxdma(struct et_softc *sc) 1741179895Sdelphij{ 1742229940Syongari struct et_rxstatus_data *rxsd; 1743229940Syongari struct et_rxstat_ring *rxst_ring; 1744179895Sdelphij struct et_rxdesc_ring *rx_ring; 1745179895Sdelphij int error; 1746179895Sdelphij 1747179895Sdelphij error = et_stop_rxdma(sc); 1748179895Sdelphij if (error) { 1749179895Sdelphij if_printf(sc->ifp, "can't init RX DMA engine\n"); 1750199556Syongari return (error); 1751179895Sdelphij } 1752179895Sdelphij 1753179895Sdelphij /* 1754179895Sdelphij * Install RX status 1755179895Sdelphij */ 1756229940Syongari rxsd = &sc->sc_rx_status; 1757179895Sdelphij CSR_WRITE_4(sc, ET_RX_STATUS_HI, ET_ADDR_HI(rxsd->rxsd_paddr)); 1758179895Sdelphij CSR_WRITE_4(sc, ET_RX_STATUS_LO, ET_ADDR_LO(rxsd->rxsd_paddr)); 1759179895Sdelphij 1760179895Sdelphij /* 1761179895Sdelphij * Install RX stat ring 1762179895Sdelphij */ 1763229940Syongari rxst_ring = &sc->sc_rxstat_ring; 1764179895Sdelphij CSR_WRITE_4(sc, ET_RXSTAT_HI, ET_ADDR_HI(rxst_ring->rsr_paddr)); 1765179895Sdelphij CSR_WRITE_4(sc, ET_RXSTAT_LO, ET_ADDR_LO(rxst_ring->rsr_paddr)); 1766179895Sdelphij CSR_WRITE_4(sc, ET_RXSTAT_CNT, ET_RX_NSTAT - 1); 1767179895Sdelphij CSR_WRITE_4(sc, ET_RXSTAT_POS, 0); 1768179895Sdelphij CSR_WRITE_4(sc, ET_RXSTAT_MINCNT, ((ET_RX_NSTAT * 15) / 100) - 1); 1769179895Sdelphij 1770179895Sdelphij /* Match ET_RXSTAT_POS */ 1771179895Sdelphij rxst_ring->rsr_index = 0; 1772179895Sdelphij rxst_ring->rsr_wrap = 0; 1773179895Sdelphij 1774179895Sdelphij /* 1775179895Sdelphij * Install the 2nd RX descriptor ring 1776179895Sdelphij */ 1777179895Sdelphij rx_ring = &sc->sc_rx_ring[1]; 1778179895Sdelphij CSR_WRITE_4(sc, ET_RX_RING1_HI, ET_ADDR_HI(rx_ring->rr_paddr)); 1779179895Sdelphij CSR_WRITE_4(sc, ET_RX_RING1_LO, ET_ADDR_LO(rx_ring->rr_paddr)); 1780179895Sdelphij CSR_WRITE_4(sc, ET_RX_RING1_CNT, ET_RX_NDESC - 1); 1781179895Sdelphij CSR_WRITE_4(sc, ET_RX_RING1_POS, ET_RX_RING1_POS_WRAP); 1782179895Sdelphij CSR_WRITE_4(sc, ET_RX_RING1_MINCNT, ((ET_RX_NDESC * 15) / 100) - 1); 1783179895Sdelphij 1784179895Sdelphij /* Match ET_RX_RING1_POS */ 1785179895Sdelphij rx_ring->rr_index = 0; 1786179895Sdelphij rx_ring->rr_wrap = 1; 1787179895Sdelphij 1788179895Sdelphij /* 1789179895Sdelphij * Install the 1st RX descriptor ring 1790179895Sdelphij */ 1791179895Sdelphij rx_ring = &sc->sc_rx_ring[0]; 1792179895Sdelphij CSR_WRITE_4(sc, ET_RX_RING0_HI, ET_ADDR_HI(rx_ring->rr_paddr)); 1793179895Sdelphij CSR_WRITE_4(sc, ET_RX_RING0_LO, ET_ADDR_LO(rx_ring->rr_paddr)); 1794179895Sdelphij CSR_WRITE_4(sc, ET_RX_RING0_CNT, ET_RX_NDESC - 1); 1795179895Sdelphij CSR_WRITE_4(sc, ET_RX_RING0_POS, ET_RX_RING0_POS_WRAP); 1796179895Sdelphij CSR_WRITE_4(sc, ET_RX_RING0_MINCNT, ((ET_RX_NDESC * 15) / 100) - 1); 1797179895Sdelphij 1798179895Sdelphij /* Match ET_RX_RING0_POS */ 1799179895Sdelphij rx_ring->rr_index = 0; 1800179895Sdelphij rx_ring->rr_wrap = 1; 1801179895Sdelphij 1802179895Sdelphij /* 1803179895Sdelphij * RX intr moderation 1804179895Sdelphij */ 1805179895Sdelphij CSR_WRITE_4(sc, ET_RX_INTR_NPKTS, sc->sc_rx_intr_npkts); 1806179895Sdelphij CSR_WRITE_4(sc, ET_RX_INTR_DELAY, sc->sc_rx_intr_delay); 1807179895Sdelphij 1808199556Syongari return (0); 1809179895Sdelphij} 1810179895Sdelphij 1811179895Sdelphijstatic int 1812179895Sdelphijet_init_txdma(struct et_softc *sc) 1813179895Sdelphij{ 1814229940Syongari struct et_txdesc_ring *tx_ring; 1815229940Syongari struct et_txstatus_data *txsd; 1816179895Sdelphij int error; 1817179895Sdelphij 1818179895Sdelphij error = et_stop_txdma(sc); 1819179895Sdelphij if (error) { 1820179895Sdelphij if_printf(sc->ifp, "can't init TX DMA engine\n"); 1821199556Syongari return (error); 1822179895Sdelphij } 1823179895Sdelphij 1824179895Sdelphij /* 1825179895Sdelphij * Install TX descriptor ring 1826179895Sdelphij */ 1827229940Syongari tx_ring = &sc->sc_tx_ring; 1828179895Sdelphij CSR_WRITE_4(sc, ET_TX_RING_HI, ET_ADDR_HI(tx_ring->tr_paddr)); 1829179895Sdelphij CSR_WRITE_4(sc, ET_TX_RING_LO, ET_ADDR_LO(tx_ring->tr_paddr)); 1830179895Sdelphij CSR_WRITE_4(sc, ET_TX_RING_CNT, ET_TX_NDESC - 1); 1831179895Sdelphij 1832179895Sdelphij /* 1833179895Sdelphij * Install TX status 1834179895Sdelphij */ 1835229940Syongari txsd = &sc->sc_tx_status; 1836179895Sdelphij CSR_WRITE_4(sc, ET_TX_STATUS_HI, ET_ADDR_HI(txsd->txsd_paddr)); 1837179895Sdelphij CSR_WRITE_4(sc, ET_TX_STATUS_LO, ET_ADDR_LO(txsd->txsd_paddr)); 1838179895Sdelphij 1839179895Sdelphij CSR_WRITE_4(sc, ET_TX_READY_POS, 0); 1840179895Sdelphij 1841179895Sdelphij /* Match ET_TX_READY_POS */ 1842179895Sdelphij tx_ring->tr_ready_index = 0; 1843179895Sdelphij tx_ring->tr_ready_wrap = 0; 1844179895Sdelphij 1845199556Syongari return (0); 1846179895Sdelphij} 1847179895Sdelphij 1848179895Sdelphijstatic void 1849179895Sdelphijet_init_mac(struct et_softc *sc) 1850179895Sdelphij{ 1851229940Syongari struct ifnet *ifp; 1852229940Syongari const uint8_t *eaddr; 1853179895Sdelphij uint32_t val; 1854179895Sdelphij 1855179895Sdelphij /* Reset MAC */ 1856179895Sdelphij CSR_WRITE_4(sc, ET_MAC_CFG1, 1857179895Sdelphij ET_MAC_CFG1_RST_TXFUNC | ET_MAC_CFG1_RST_RXFUNC | 1858179895Sdelphij ET_MAC_CFG1_RST_TXMC | ET_MAC_CFG1_RST_RXMC | 1859179895Sdelphij ET_MAC_CFG1_SIM_RST | ET_MAC_CFG1_SOFT_RST); 1860179895Sdelphij 1861179895Sdelphij /* 1862179895Sdelphij * Setup inter packet gap 1863179895Sdelphij */ 1864199548Syongari val = (56 << ET_IPG_NONB2B_1_SHIFT) | 1865199548Syongari (88 << ET_IPG_NONB2B_2_SHIFT) | 1866199548Syongari (80 << ET_IPG_MINIFG_SHIFT) | 1867199548Syongari (96 << ET_IPG_B2B_SHIFT); 1868179895Sdelphij CSR_WRITE_4(sc, ET_IPG, val); 1869179895Sdelphij 1870179895Sdelphij /* 1871179895Sdelphij * Setup half duplex mode 1872179895Sdelphij */ 1873199548Syongari val = (10 << ET_MAC_HDX_ALT_BEB_TRUNC_SHIFT) | 1874199548Syongari (15 << ET_MAC_HDX_REXMIT_MAX_SHIFT) | 1875199548Syongari (55 << ET_MAC_HDX_COLLWIN_SHIFT) | 1876199548Syongari ET_MAC_HDX_EXC_DEFER; 1877179895Sdelphij CSR_WRITE_4(sc, ET_MAC_HDX, val); 1878179895Sdelphij 1879179895Sdelphij /* Clear MAC control */ 1880179895Sdelphij CSR_WRITE_4(sc, ET_MAC_CTRL, 0); 1881179895Sdelphij 1882179895Sdelphij /* Reset MII */ 1883179895Sdelphij CSR_WRITE_4(sc, ET_MII_CFG, ET_MII_CFG_CLKRST); 1884179895Sdelphij 1885179895Sdelphij /* 1886179895Sdelphij * Set MAC address 1887179895Sdelphij */ 1888229940Syongari ifp = sc->ifp; 1889229940Syongari eaddr = IF_LLADDR(ifp); 1890179895Sdelphij val = eaddr[2] | (eaddr[3] << 8) | (eaddr[4] << 16) | (eaddr[5] << 24); 1891179895Sdelphij CSR_WRITE_4(sc, ET_MAC_ADDR1, val); 1892179895Sdelphij val = (eaddr[0] << 16) | (eaddr[1] << 24); 1893179895Sdelphij CSR_WRITE_4(sc, ET_MAC_ADDR2, val); 1894179895Sdelphij 1895179895Sdelphij /* Set max frame length */ 1896179895Sdelphij CSR_WRITE_4(sc, ET_MAX_FRMLEN, ET_FRAMELEN(ifp->if_mtu)); 1897179895Sdelphij 1898179895Sdelphij /* Bring MAC out of reset state */ 1899179895Sdelphij CSR_WRITE_4(sc, ET_MAC_CFG1, 0); 1900179895Sdelphij} 1901179895Sdelphij 1902179895Sdelphijstatic void 1903179895Sdelphijet_init_rxmac(struct et_softc *sc) 1904179895Sdelphij{ 1905229940Syongari struct ifnet *ifp; 1906229940Syongari const uint8_t *eaddr; 1907179895Sdelphij uint32_t val; 1908179895Sdelphij int i; 1909179895Sdelphij 1910179895Sdelphij /* Disable RX MAC and WOL */ 1911179895Sdelphij CSR_WRITE_4(sc, ET_RXMAC_CTRL, ET_RXMAC_CTRL_WOL_DISABLE); 1912179895Sdelphij 1913179895Sdelphij /* 1914179895Sdelphij * Clear all WOL related registers 1915179895Sdelphij */ 1916179895Sdelphij for (i = 0; i < 3; ++i) 1917179895Sdelphij CSR_WRITE_4(sc, ET_WOL_CRC + (i * 4), 0); 1918179895Sdelphij for (i = 0; i < 20; ++i) 1919179895Sdelphij CSR_WRITE_4(sc, ET_WOL_MASK + (i * 4), 0); 1920179895Sdelphij 1921179895Sdelphij /* 1922179895Sdelphij * Set WOL source address. XXX is this necessary? 1923179895Sdelphij */ 1924229940Syongari ifp = sc->ifp; 1925229940Syongari eaddr = IF_LLADDR(ifp); 1926179895Sdelphij val = (eaddr[2] << 24) | (eaddr[3] << 16) | (eaddr[4] << 8) | eaddr[5]; 1927179895Sdelphij CSR_WRITE_4(sc, ET_WOL_SA_LO, val); 1928179895Sdelphij val = (eaddr[0] << 8) | eaddr[1]; 1929179895Sdelphij CSR_WRITE_4(sc, ET_WOL_SA_HI, val); 1930179895Sdelphij 1931179895Sdelphij /* Clear packet filters */ 1932179895Sdelphij CSR_WRITE_4(sc, ET_PKTFILT, 0); 1933179895Sdelphij 1934179895Sdelphij /* No ucast filtering */ 1935179895Sdelphij CSR_WRITE_4(sc, ET_UCAST_FILTADDR1, 0); 1936179895Sdelphij CSR_WRITE_4(sc, ET_UCAST_FILTADDR2, 0); 1937179895Sdelphij CSR_WRITE_4(sc, ET_UCAST_FILTADDR3, 0); 1938179895Sdelphij 1939179895Sdelphij if (ET_FRAMELEN(ifp->if_mtu) > ET_RXMAC_CUT_THRU_FRMLEN) { 1940179895Sdelphij /* 1941179895Sdelphij * In order to transmit jumbo packets greater than 1942179895Sdelphij * ET_RXMAC_CUT_THRU_FRMLEN bytes, the FIFO between 1943179895Sdelphij * RX MAC and RX DMA needs to be reduced in size to 1944179895Sdelphij * (ET_MEM_SIZE - ET_MEM_TXSIZE_EX - framelen). In 1945179895Sdelphij * order to implement this, we must use "cut through" 1946179895Sdelphij * mode in the RX MAC, which chops packets down into 1947179895Sdelphij * segments. In this case we selected 256 bytes, 1948179895Sdelphij * since this is the size of the PCI-Express TLP's 1949179895Sdelphij * that the ET1310 uses. 1950179895Sdelphij */ 1951199548Syongari val = (ET_RXMAC_SEGSZ(256) & ET_RXMAC_MC_SEGSZ_MAX_MASK) | 1952179895Sdelphij ET_RXMAC_MC_SEGSZ_ENABLE; 1953179895Sdelphij } else { 1954179895Sdelphij val = 0; 1955179895Sdelphij } 1956179895Sdelphij CSR_WRITE_4(sc, ET_RXMAC_MC_SEGSZ, val); 1957179895Sdelphij 1958179895Sdelphij CSR_WRITE_4(sc, ET_RXMAC_MC_WATERMARK, 0); 1959179895Sdelphij 1960179895Sdelphij /* Initialize RX MAC management register */ 1961179895Sdelphij CSR_WRITE_4(sc, ET_RXMAC_MGT, 0); 1962179895Sdelphij 1963179895Sdelphij CSR_WRITE_4(sc, ET_RXMAC_SPACE_AVL, 0); 1964179895Sdelphij 1965179895Sdelphij CSR_WRITE_4(sc, ET_RXMAC_MGT, 1966179895Sdelphij ET_RXMAC_MGT_PASS_ECRC | 1967179895Sdelphij ET_RXMAC_MGT_PASS_ELEN | 1968179895Sdelphij ET_RXMAC_MGT_PASS_ETRUNC | 1969179895Sdelphij ET_RXMAC_MGT_CHECK_PKT); 1970179895Sdelphij 1971179895Sdelphij /* 1972179895Sdelphij * Configure runt filtering (may not work on certain chip generation) 1973179895Sdelphij */ 1974199548Syongari val = (ETHER_MIN_LEN << ET_PKTFILT_MINLEN_SHIFT) & 1975199548Syongari ET_PKTFILT_MINLEN_MASK; 1976199548Syongari val |= ET_PKTFILT_FRAG; 1977179895Sdelphij CSR_WRITE_4(sc, ET_PKTFILT, val); 1978179895Sdelphij 1979179895Sdelphij /* Enable RX MAC but leave WOL disabled */ 1980179895Sdelphij CSR_WRITE_4(sc, ET_RXMAC_CTRL, 1981179895Sdelphij ET_RXMAC_CTRL_WOL_DISABLE | ET_RXMAC_CTRL_ENABLE); 1982179895Sdelphij 1983179895Sdelphij /* 1984179895Sdelphij * Setup multicast hash and allmulti/promisc mode 1985179895Sdelphij */ 1986179895Sdelphij et_setmulti(sc); 1987179895Sdelphij} 1988179895Sdelphij 1989179895Sdelphijstatic void 1990179895Sdelphijet_init_txmac(struct et_softc *sc) 1991179895Sdelphij{ 1992229940Syongari 1993179895Sdelphij /* Disable TX MAC and FC(?) */ 1994179895Sdelphij CSR_WRITE_4(sc, ET_TXMAC_CTRL, ET_TXMAC_CTRL_FC_DISABLE); 1995179895Sdelphij 1996228369Syongari /* 1997228369Syongari * Initialize pause time. 1998228369Syongari * This register should be set before XON/XOFF frame is 1999228369Syongari * sent by driver. 2000228369Syongari */ 2001228369Syongari CSR_WRITE_4(sc, ET_TXMAC_FLOWCTRL, 0 << ET_TXMAC_FLOWCTRL_CFPT_SHIFT); 2002179895Sdelphij 2003179895Sdelphij /* Enable TX MAC but leave FC(?) diabled */ 2004179895Sdelphij CSR_WRITE_4(sc, ET_TXMAC_CTRL, 2005179895Sdelphij ET_TXMAC_CTRL_ENABLE | ET_TXMAC_CTRL_FC_DISABLE); 2006179895Sdelphij} 2007179895Sdelphij 2008179895Sdelphijstatic int 2009179895Sdelphijet_start_rxdma(struct et_softc *sc) 2010179895Sdelphij{ 2011229940Syongari uint32_t val; 2012179895Sdelphij 2013229940Syongari val = (sc->sc_rx_data[0].rbd_bufsize & ET_RXDMA_CTRL_RING0_SIZE_MASK) | 2014229940Syongari ET_RXDMA_CTRL_RING0_ENABLE; 2015199548Syongari val |= (sc->sc_rx_data[1].rbd_bufsize & ET_RXDMA_CTRL_RING1_SIZE_MASK) | 2016229940Syongari ET_RXDMA_CTRL_RING1_ENABLE; 2017179895Sdelphij 2018179895Sdelphij CSR_WRITE_4(sc, ET_RXDMA_CTRL, val); 2019179895Sdelphij 2020179895Sdelphij DELAY(5); 2021179895Sdelphij 2022179895Sdelphij if (CSR_READ_4(sc, ET_RXDMA_CTRL) & ET_RXDMA_CTRL_HALTED) { 2023179895Sdelphij if_printf(sc->ifp, "can't start RX DMA engine\n"); 2024199556Syongari return (ETIMEDOUT); 2025179895Sdelphij } 2026199556Syongari return (0); 2027179895Sdelphij} 2028179895Sdelphij 2029179895Sdelphijstatic int 2030179895Sdelphijet_start_txdma(struct et_softc *sc) 2031179895Sdelphij{ 2032229940Syongari 2033179895Sdelphij CSR_WRITE_4(sc, ET_TXDMA_CTRL, ET_TXDMA_CTRL_SINGLE_EPKT); 2034199556Syongari return (0); 2035179895Sdelphij} 2036179895Sdelphij 2037179895Sdelphijstatic void 2038179895Sdelphijet_rxeof(struct et_softc *sc) 2039179895Sdelphij{ 2040179895Sdelphij struct et_rxstatus_data *rxsd; 2041179895Sdelphij struct et_rxstat_ring *rxst_ring; 2042228325Syongari struct et_rxbuf_data *rbd; 2043228325Syongari struct et_rxdesc_ring *rx_ring; 2044228325Syongari struct et_rxstat *st; 2045228325Syongari struct ifnet *ifp; 2046228325Syongari struct mbuf *m; 2047228325Syongari uint32_t rxstat_pos, rxring_pos; 2048228325Syongari uint32_t rxst_info1, rxst_info2, rxs_stat_ring; 2049228325Syongari int buflen, buf_idx, npost[2], ring_idx; 2050228325Syongari int rxst_index, rxst_wrap; 2051179895Sdelphij 2052179895Sdelphij ET_LOCK_ASSERT(sc); 2053228325Syongari 2054179895Sdelphij ifp = sc->ifp; 2055179895Sdelphij rxsd = &sc->sc_rx_status; 2056179895Sdelphij rxst_ring = &sc->sc_rxstat_ring; 2057179895Sdelphij 2058179895Sdelphij if ((sc->sc_flags & ET_FLAG_TXRX_ENABLED) == 0) 2059179895Sdelphij return; 2060179895Sdelphij 2061179895Sdelphij bus_dmamap_sync(rxsd->rxsd_dtag, rxsd->rxsd_dmap, 2062228325Syongari BUS_DMASYNC_POSTREAD); 2063179895Sdelphij bus_dmamap_sync(rxst_ring->rsr_dtag, rxst_ring->rsr_dmap, 2064228325Syongari BUS_DMASYNC_POSTREAD); 2065179895Sdelphij 2066228325Syongari npost[0] = npost[1] = 0; 2067199609Syongari rxs_stat_ring = le32toh(rxsd->rxsd_status->rxs_stat_ring); 2068179895Sdelphij rxst_wrap = (rxs_stat_ring & ET_RXS_STATRING_WRAP) ? 1 : 0; 2069199548Syongari rxst_index = (rxs_stat_ring & ET_RXS_STATRING_INDEX_MASK) >> 2070199548Syongari ET_RXS_STATRING_INDEX_SHIFT; 2071179895Sdelphij 2072179895Sdelphij while (rxst_index != rxst_ring->rsr_index || 2073228325Syongari rxst_wrap != rxst_ring->rsr_wrap) { 2074228325Syongari if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) 2075228325Syongari break; 2076179895Sdelphij 2077179895Sdelphij MPASS(rxst_ring->rsr_index < ET_RX_NSTAT); 2078179895Sdelphij st = &rxst_ring->rsr_stat[rxst_ring->rsr_index]; 2079228325Syongari rxst_info1 = le32toh(st->rxst_info1); 2080199609Syongari rxst_info2 = le32toh(st->rxst_info2); 2081199609Syongari buflen = (rxst_info2 & ET_RXST_INFO2_LEN_MASK) >> 2082199548Syongari ET_RXST_INFO2_LEN_SHIFT; 2083199609Syongari buf_idx = (rxst_info2 & ET_RXST_INFO2_BUFIDX_MASK) >> 2084199548Syongari ET_RXST_INFO2_BUFIDX_SHIFT; 2085199609Syongari ring_idx = (rxst_info2 & ET_RXST_INFO2_RINGIDX_MASK) >> 2086199548Syongari ET_RXST_INFO2_RINGIDX_SHIFT; 2087179895Sdelphij 2088179895Sdelphij if (++rxst_ring->rsr_index == ET_RX_NSTAT) { 2089179895Sdelphij rxst_ring->rsr_index = 0; 2090179895Sdelphij rxst_ring->rsr_wrap ^= 1; 2091179895Sdelphij } 2092199548Syongari rxstat_pos = rxst_ring->rsr_index & ET_RXSTAT_POS_INDEX_MASK; 2093179895Sdelphij if (rxst_ring->rsr_wrap) 2094179895Sdelphij rxstat_pos |= ET_RXSTAT_POS_WRAP; 2095179895Sdelphij CSR_WRITE_4(sc, ET_RXSTAT_POS, rxstat_pos); 2096179895Sdelphij 2097179895Sdelphij if (ring_idx >= ET_RX_NRING) { 2098272064Sglebius if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); 2099179895Sdelphij if_printf(ifp, "invalid ring index %d\n", ring_idx); 2100179895Sdelphij continue; 2101179895Sdelphij } 2102179895Sdelphij if (buf_idx >= ET_RX_NDESC) { 2103272064Sglebius if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); 2104179895Sdelphij if_printf(ifp, "invalid buf index %d\n", buf_idx); 2105179895Sdelphij continue; 2106179895Sdelphij } 2107179895Sdelphij 2108179895Sdelphij rbd = &sc->sc_rx_data[ring_idx]; 2109179895Sdelphij m = rbd->rbd_buf[buf_idx].rb_mbuf; 2110228325Syongari if ((rxst_info1 & ET_RXST_INFO1_OK) == 0){ 2111228325Syongari /* Discard errored frame. */ 2112228325Syongari rbd->rbd_discard(rbd, buf_idx); 2113228325Syongari } else if (rbd->rbd_newbuf(rbd, buf_idx) != 0) { 2114228325Syongari /* No available mbufs, discard it. */ 2115272064Sglebius if_inc_counter(ifp, IFCOUNTER_IQDROPS, 1); 2116228325Syongari rbd->rbd_discard(rbd, buf_idx); 2117228325Syongari } else { 2118228325Syongari buflen -= ETHER_CRC_LEN; 2119228325Syongari if (buflen < ETHER_HDR_LEN) { 2120179895Sdelphij m_freem(m); 2121272064Sglebius if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); 2122179895Sdelphij } else { 2123228325Syongari m->m_pkthdr.len = m->m_len = buflen; 2124179895Sdelphij m->m_pkthdr.rcvif = ifp; 2125179895Sdelphij ET_UNLOCK(sc); 2126179895Sdelphij ifp->if_input(ifp, m); 2127179895Sdelphij ET_LOCK(sc); 2128179895Sdelphij } 2129179895Sdelphij } 2130179895Sdelphij 2131179895Sdelphij rx_ring = &sc->sc_rx_ring[ring_idx]; 2132179895Sdelphij if (buf_idx != rx_ring->rr_index) { 2133228325Syongari if_printf(ifp, 2134228325Syongari "WARNING!! ring %d, buf_idx %d, rr_idx %d\n", 2135228325Syongari ring_idx, buf_idx, rx_ring->rr_index); 2136179895Sdelphij } 2137179895Sdelphij 2138179895Sdelphij MPASS(rx_ring->rr_index < ET_RX_NDESC); 2139179895Sdelphij if (++rx_ring->rr_index == ET_RX_NDESC) { 2140179895Sdelphij rx_ring->rr_index = 0; 2141179895Sdelphij rx_ring->rr_wrap ^= 1; 2142179895Sdelphij } 2143199548Syongari rxring_pos = rx_ring->rr_index & ET_RX_RING_POS_INDEX_MASK; 2144179895Sdelphij if (rx_ring->rr_wrap) 2145179895Sdelphij rxring_pos |= ET_RX_RING_POS_WRAP; 2146179895Sdelphij CSR_WRITE_4(sc, rx_ring->rr_posreg, rxring_pos); 2147179895Sdelphij } 2148228325Syongari 2149228325Syongari bus_dmamap_sync(rxsd->rxsd_dtag, rxsd->rxsd_dmap, 2150228325Syongari BUS_DMASYNC_PREREAD); 2151228325Syongari bus_dmamap_sync(rxst_ring->rsr_dtag, rxst_ring->rsr_dmap, 2152228325Syongari BUS_DMASYNC_PREREAD); 2153179895Sdelphij} 2154179895Sdelphij 2155179895Sdelphijstatic int 2156179895Sdelphijet_encap(struct et_softc *sc, struct mbuf **m0) 2157179895Sdelphij{ 2158228325Syongari struct et_txdesc_ring *tx_ring; 2159228325Syongari struct et_txbuf_data *tbd; 2160228325Syongari struct et_txdesc *td; 2161228325Syongari struct mbuf *m; 2162179895Sdelphij bus_dma_segment_t segs[ET_NSEG_MAX]; 2163179895Sdelphij bus_dmamap_t map; 2164228326Syongari uint32_t csum_flags, last_td_ctrl2; 2165228325Syongari int error, i, idx, first_idx, last_idx, nsegs; 2166179895Sdelphij 2167228325Syongari tx_ring = &sc->sc_tx_ring; 2168179895Sdelphij MPASS(tx_ring->tr_ready_index < ET_TX_NDESC); 2169228325Syongari tbd = &sc->sc_tx_data; 2170179895Sdelphij first_idx = tx_ring->tr_ready_index; 2171179895Sdelphij map = tbd->tbd_buf[first_idx].tb_dmap; 2172179895Sdelphij 2173228325Syongari error = bus_dmamap_load_mbuf_sg(sc->sc_tx_tag, map, *m0, segs, &nsegs, 2174228325Syongari 0); 2175228325Syongari if (error == EFBIG) { 2176243857Sglebius m = m_collapse(*m0, M_NOWAIT, ET_NSEG_MAX); 2177228325Syongari if (m == NULL) { 2178228325Syongari m_freem(*m0); 2179228325Syongari *m0 = NULL; 2180228325Syongari return (ENOMEM); 2181179895Sdelphij } 2182228325Syongari *m0 = m; 2183228325Syongari error = bus_dmamap_load_mbuf_sg(sc->sc_tx_tag, map, *m0, segs, 2184228325Syongari &nsegs, 0); 2185228325Syongari if (error != 0) { 2186228325Syongari m_freem(*m0); 2187228325Syongari *m0 = NULL; 2188228325Syongari return (error); 2189228325Syongari } 2190228325Syongari } else if (error != 0) 2191228325Syongari return (error); 2192179895Sdelphij 2193228325Syongari /* Check for descriptor overruns. */ 2194228325Syongari if (tbd->tbd_used + nsegs > ET_TX_NDESC - 1) { 2195228325Syongari bus_dmamap_unload(sc->sc_tx_tag, map); 2196228325Syongari return (ENOBUFS); 2197179895Sdelphij } 2198228325Syongari bus_dmamap_sync(sc->sc_tx_tag, map, BUS_DMASYNC_PREWRITE); 2199179895Sdelphij 2200179895Sdelphij last_td_ctrl2 = ET_TDCTRL2_LAST_FRAG; 2201228325Syongari sc->sc_tx += nsegs; 2202179895Sdelphij if (sc->sc_tx / sc->sc_tx_intr_nsegs != sc->sc_tx_intr) { 2203179895Sdelphij sc->sc_tx_intr = sc->sc_tx / sc->sc_tx_intr_nsegs; 2204179895Sdelphij last_td_ctrl2 |= ET_TDCTRL2_INTR; 2205179895Sdelphij } 2206179895Sdelphij 2207228325Syongari m = *m0; 2208199611Syongari csum_flags = 0; 2209199611Syongari if ((m->m_pkthdr.csum_flags & ET_CSUM_FEATURES) != 0) { 2210199611Syongari if ((m->m_pkthdr.csum_flags & CSUM_IP) != 0) 2211199611Syongari csum_flags |= ET_TDCTRL2_CSUM_IP; 2212199611Syongari if ((m->m_pkthdr.csum_flags & CSUM_UDP) != 0) 2213199611Syongari csum_flags |= ET_TDCTRL2_CSUM_UDP; 2214199611Syongari else if ((m->m_pkthdr.csum_flags & CSUM_TCP) != 0) 2215199611Syongari csum_flags |= ET_TDCTRL2_CSUM_TCP; 2216199611Syongari } 2217179895Sdelphij last_idx = -1; 2218228325Syongari for (i = 0; i < nsegs; ++i) { 2219179895Sdelphij idx = (first_idx + i) % ET_TX_NDESC; 2220179895Sdelphij td = &tx_ring->tr_desc[idx]; 2221199609Syongari td->td_addr_hi = htole32(ET_ADDR_HI(segs[i].ds_addr)); 2222199609Syongari td->td_addr_lo = htole32(ET_ADDR_LO(segs[i].ds_addr)); 2223199609Syongari td->td_ctrl1 = htole32(segs[i].ds_len & ET_TDCTRL1_LEN_MASK); 2224228325Syongari if (i == nsegs - 1) { 2225228325Syongari /* Last frag */ 2226199611Syongari td->td_ctrl2 = htole32(last_td_ctrl2 | csum_flags); 2227179895Sdelphij last_idx = idx; 2228199611Syongari } else 2229199611Syongari td->td_ctrl2 = htole32(csum_flags); 2230179895Sdelphij 2231179895Sdelphij MPASS(tx_ring->tr_ready_index < ET_TX_NDESC); 2232179895Sdelphij if (++tx_ring->tr_ready_index == ET_TX_NDESC) { 2233179895Sdelphij tx_ring->tr_ready_index = 0; 2234179895Sdelphij tx_ring->tr_ready_wrap ^= 1; 2235179895Sdelphij } 2236179895Sdelphij } 2237179895Sdelphij td = &tx_ring->tr_desc[first_idx]; 2238228325Syongari /* First frag */ 2239228325Syongari td->td_ctrl2 |= htole32(ET_TDCTRL2_FIRST_FRAG); 2240179895Sdelphij 2241179895Sdelphij MPASS(last_idx >= 0); 2242179895Sdelphij tbd->tbd_buf[first_idx].tb_dmap = tbd->tbd_buf[last_idx].tb_dmap; 2243179895Sdelphij tbd->tbd_buf[last_idx].tb_dmap = map; 2244179895Sdelphij tbd->tbd_buf[last_idx].tb_mbuf = m; 2245179895Sdelphij 2246228325Syongari tbd->tbd_used += nsegs; 2247179895Sdelphij MPASS(tbd->tbd_used <= ET_TX_NDESC); 2248179895Sdelphij 2249228325Syongari return (0); 2250179895Sdelphij} 2251179895Sdelphij 2252179895Sdelphijstatic void 2253179895Sdelphijet_txeof(struct et_softc *sc) 2254179895Sdelphij{ 2255179895Sdelphij struct et_txdesc_ring *tx_ring; 2256179895Sdelphij struct et_txbuf_data *tbd; 2257228325Syongari struct et_txbuf *tb; 2258228325Syongari struct ifnet *ifp; 2259179895Sdelphij uint32_t tx_done; 2260179895Sdelphij int end, wrap; 2261179895Sdelphij 2262179895Sdelphij ET_LOCK_ASSERT(sc); 2263228325Syongari 2264179895Sdelphij ifp = sc->ifp; 2265179895Sdelphij tx_ring = &sc->sc_tx_ring; 2266179895Sdelphij tbd = &sc->sc_tx_data; 2267179895Sdelphij 2268179895Sdelphij if ((sc->sc_flags & ET_FLAG_TXRX_ENABLED) == 0) 2269179895Sdelphij return; 2270179895Sdelphij 2271179895Sdelphij if (tbd->tbd_used == 0) 2272179895Sdelphij return; 2273179895Sdelphij 2274228325Syongari bus_dmamap_sync(tx_ring->tr_dtag, tx_ring->tr_dmap, 2275228325Syongari BUS_DMASYNC_POSTWRITE); 2276228325Syongari 2277179895Sdelphij tx_done = CSR_READ_4(sc, ET_TX_DONE_POS); 2278199548Syongari end = tx_done & ET_TX_DONE_POS_INDEX_MASK; 2279179895Sdelphij wrap = (tx_done & ET_TX_DONE_POS_WRAP) ? 1 : 0; 2280179895Sdelphij 2281179895Sdelphij while (tbd->tbd_start_index != end || tbd->tbd_start_wrap != wrap) { 2282179895Sdelphij MPASS(tbd->tbd_start_index < ET_TX_NDESC); 2283179895Sdelphij tb = &tbd->tbd_buf[tbd->tbd_start_index]; 2284179895Sdelphij if (tb->tb_mbuf != NULL) { 2285228325Syongari bus_dmamap_sync(sc->sc_tx_tag, tb->tb_dmap, 2286228325Syongari BUS_DMASYNC_POSTWRITE); 2287228325Syongari bus_dmamap_unload(sc->sc_tx_tag, tb->tb_dmap); 2288179895Sdelphij m_freem(tb->tb_mbuf); 2289179895Sdelphij tb->tb_mbuf = NULL; 2290179895Sdelphij } 2291179895Sdelphij 2292179895Sdelphij if (++tbd->tbd_start_index == ET_TX_NDESC) { 2293179895Sdelphij tbd->tbd_start_index = 0; 2294179895Sdelphij tbd->tbd_start_wrap ^= 1; 2295179895Sdelphij } 2296179895Sdelphij 2297179895Sdelphij MPASS(tbd->tbd_used > 0); 2298179895Sdelphij tbd->tbd_used--; 2299179895Sdelphij } 2300179895Sdelphij 2301179895Sdelphij if (tbd->tbd_used == 0) 2302179895Sdelphij sc->watchdog_timer = 0; 2303228325Syongari if (tbd->tbd_used + ET_NSEG_SPARE < ET_TX_NDESC) 2304179895Sdelphij ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 2305179895Sdelphij} 2306228331Syongari 2307179895Sdelphijstatic void 2308179895Sdelphijet_tick(void *xsc) 2309179895Sdelphij{ 2310229940Syongari struct et_softc *sc; 2311179895Sdelphij struct ifnet *ifp; 2312179895Sdelphij struct mii_data *mii; 2313179895Sdelphij 2314229940Syongari sc = xsc; 2315179895Sdelphij ET_LOCK_ASSERT(sc); 2316179895Sdelphij ifp = sc->ifp; 2317179895Sdelphij mii = device_get_softc(sc->sc_miibus); 2318179895Sdelphij 2319179895Sdelphij mii_tick(mii); 2320228332Syongari et_stats_update(sc); 2321228325Syongari if (et_watchdog(sc) == EJUSTRETURN) 2322228325Syongari return; 2323179895Sdelphij callout_reset(&sc->sc_tick, hz, et_tick, sc); 2324179895Sdelphij} 2325179895Sdelphij 2326179895Sdelphijstatic int 2327228325Syongariet_newbuf_cluster(struct et_rxbuf_data *rbd, int buf_idx) 2328179895Sdelphij{ 2329228325Syongari struct et_softc *sc; 2330228325Syongari struct et_rxdesc *desc; 2331228325Syongari struct et_rxbuf *rb; 2332228325Syongari struct mbuf *m; 2333228325Syongari bus_dma_segment_t segs[1]; 2334228325Syongari bus_dmamap_t dmap; 2335228325Syongari int nsegs; 2336228325Syongari 2337228325Syongari MPASS(buf_idx < ET_RX_NDESC); 2338243857Sglebius m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); 2339228325Syongari if (m == NULL) 2340228325Syongari return (ENOBUFS); 2341228325Syongari m->m_len = m->m_pkthdr.len = MCLBYTES; 2342228325Syongari m_adj(m, ETHER_ALIGN); 2343228325Syongari 2344228325Syongari sc = rbd->rbd_softc; 2345228325Syongari rb = &rbd->rbd_buf[buf_idx]; 2346228325Syongari 2347228325Syongari if (bus_dmamap_load_mbuf_sg(sc->sc_rx_tag, sc->sc_rx_sparemap, m, 2348228325Syongari segs, &nsegs, 0) != 0) { 2349228325Syongari m_freem(m); 2350228325Syongari return (ENOBUFS); 2351228325Syongari } 2352228325Syongari KASSERT(nsegs == 1, ("%s: %d segments returned!", __func__, nsegs)); 2353228325Syongari 2354228325Syongari if (rb->rb_mbuf != NULL) { 2355228325Syongari bus_dmamap_sync(sc->sc_rx_tag, rb->rb_dmap, 2356228325Syongari BUS_DMASYNC_POSTREAD); 2357228325Syongari bus_dmamap_unload(sc->sc_rx_tag, rb->rb_dmap); 2358228325Syongari } 2359228325Syongari dmap = rb->rb_dmap; 2360228325Syongari rb->rb_dmap = sc->sc_rx_sparemap; 2361228325Syongari sc->sc_rx_sparemap = dmap; 2362228325Syongari bus_dmamap_sync(sc->sc_rx_tag, rb->rb_dmap, BUS_DMASYNC_PREREAD); 2363228325Syongari 2364228325Syongari rb->rb_mbuf = m; 2365228325Syongari desc = &rbd->rbd_ring->rr_desc[buf_idx]; 2366228325Syongari desc->rd_addr_hi = htole32(ET_ADDR_HI(segs[0].ds_addr)); 2367228325Syongari desc->rd_addr_lo = htole32(ET_ADDR_LO(segs[0].ds_addr)); 2368228325Syongari desc->rd_ctrl = htole32(buf_idx & ET_RDCTRL_BUFIDX_MASK); 2369228325Syongari bus_dmamap_sync(rbd->rbd_ring->rr_dtag, rbd->rbd_ring->rr_dmap, 2370228325Syongari BUS_DMASYNC_PREWRITE); 2371228325Syongari return (0); 2372179895Sdelphij} 2373179895Sdelphij 2374228325Syongaristatic void 2375228325Syongariet_rxbuf_discard(struct et_rxbuf_data *rbd, int buf_idx) 2376179895Sdelphij{ 2377228325Syongari struct et_rxdesc *desc; 2378228325Syongari 2379228325Syongari desc = &rbd->rbd_ring->rr_desc[buf_idx]; 2380228325Syongari desc->rd_ctrl = htole32(buf_idx & ET_RDCTRL_BUFIDX_MASK); 2381228325Syongari bus_dmamap_sync(rbd->rbd_ring->rr_dtag, rbd->rbd_ring->rr_dmap, 2382228325Syongari BUS_DMASYNC_PREWRITE); 2383179895Sdelphij} 2384179895Sdelphij 2385179895Sdelphijstatic int 2386228325Syongariet_newbuf_hdr(struct et_rxbuf_data *rbd, int buf_idx) 2387179895Sdelphij{ 2388228325Syongari struct et_softc *sc; 2389228325Syongari struct et_rxdesc *desc; 2390179895Sdelphij struct et_rxbuf *rb; 2391179895Sdelphij struct mbuf *m; 2392228325Syongari bus_dma_segment_t segs[1]; 2393179895Sdelphij bus_dmamap_t dmap; 2394228325Syongari int nsegs; 2395179895Sdelphij 2396179895Sdelphij MPASS(buf_idx < ET_RX_NDESC); 2397243857Sglebius MGETHDR(m, M_NOWAIT, MT_DATA); 2398228325Syongari if (m == NULL) 2399228325Syongari return (ENOBUFS); 2400228325Syongari m->m_len = m->m_pkthdr.len = MHLEN; 2401228325Syongari m_adj(m, ETHER_ALIGN); 2402228325Syongari 2403228325Syongari sc = rbd->rbd_softc; 2404179895Sdelphij rb = &rbd->rbd_buf[buf_idx]; 2405179895Sdelphij 2406228325Syongari if (bus_dmamap_load_mbuf_sg(sc->sc_rx_mini_tag, sc->sc_rx_mini_sparemap, 2407228325Syongari m, segs, &nsegs, 0) != 0) { 2408179895Sdelphij m_freem(m); 2409228325Syongari return (ENOBUFS); 2410179895Sdelphij } 2411228325Syongari KASSERT(nsegs == 1, ("%s: %d segments returned!", __func__, nsegs)); 2412179895Sdelphij 2413228325Syongari if (rb->rb_mbuf != NULL) { 2414228325Syongari bus_dmamap_sync(sc->sc_rx_mini_tag, rb->rb_dmap, 2415228325Syongari BUS_DMASYNC_POSTREAD); 2416228325Syongari bus_dmamap_unload(sc->sc_rx_mini_tag, rb->rb_dmap); 2417179895Sdelphij } 2418179895Sdelphij dmap = rb->rb_dmap; 2419228325Syongari rb->rb_dmap = sc->sc_rx_mini_sparemap; 2420228325Syongari sc->sc_rx_mini_sparemap = dmap; 2421228325Syongari bus_dmamap_sync(sc->sc_rx_mini_tag, rb->rb_dmap, BUS_DMASYNC_PREREAD); 2422179895Sdelphij 2423228325Syongari rb->rb_mbuf = m; 2424228325Syongari desc = &rbd->rbd_ring->rr_desc[buf_idx]; 2425228325Syongari desc->rd_addr_hi = htole32(ET_ADDR_HI(segs[0].ds_addr)); 2426228325Syongari desc->rd_addr_lo = htole32(ET_ADDR_LO(segs[0].ds_addr)); 2427228325Syongari desc->rd_ctrl = htole32(buf_idx & ET_RDCTRL_BUFIDX_MASK); 2428228325Syongari bus_dmamap_sync(rbd->rbd_ring->rr_dtag, rbd->rbd_ring->rr_dmap, 2429228325Syongari BUS_DMASYNC_PREWRITE); 2430228325Syongari return (0); 2431179895Sdelphij} 2432179895Sdelphij 2433228332Syongari#define ET_SYSCTL_STAT_ADD32(c, h, n, p, d) \ 2434228332Syongari SYSCTL_ADD_UINT(c, h, OID_AUTO, n, CTLFLAG_RD, p, 0, d) 2435228332Syongari#define ET_SYSCTL_STAT_ADD64(c, h, n, p, d) \ 2436228332Syongari SYSCTL_ADD_UQUAD(c, h, OID_AUTO, n, CTLFLAG_RD, p, d) 2437228332Syongari 2438179895Sdelphij/* 2439179895Sdelphij * Create sysctl tree 2440179895Sdelphij */ 2441179895Sdelphijstatic void 2442179895Sdelphijet_add_sysctls(struct et_softc * sc) 2443179895Sdelphij{ 2444179895Sdelphij struct sysctl_ctx_list *ctx; 2445228332Syongari struct sysctl_oid_list *children, *parent; 2446228332Syongari struct sysctl_oid *tree; 2447228332Syongari struct et_hw_stats *stats; 2448179895Sdelphij 2449179895Sdelphij ctx = device_get_sysctl_ctx(sc->dev); 2450179895Sdelphij children = SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)); 2451179895Sdelphij 2452179895Sdelphij SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "rx_intr_npkts", 2453179895Sdelphij CTLTYPE_INT | CTLFLAG_RW, sc, 0, et_sysctl_rx_intr_npkts, "I", 2454179895Sdelphij "RX IM, # packets per RX interrupt"); 2455179895Sdelphij SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "rx_intr_delay", 2456179895Sdelphij CTLTYPE_INT | CTLFLAG_RW, sc, 0, et_sysctl_rx_intr_delay, "I", 2457179895Sdelphij "RX IM, RX interrupt delay (x10 usec)"); 2458179895Sdelphij SYSCTL_ADD_INT(ctx, children, OID_AUTO, "tx_intr_nsegs", 2459179895Sdelphij CTLFLAG_RW, &sc->sc_tx_intr_nsegs, 0, 2460179895Sdelphij "TX IM, # segments per TX interrupt"); 2461179895Sdelphij SYSCTL_ADD_UINT(ctx, children, OID_AUTO, "timer", 2462179895Sdelphij CTLFLAG_RW, &sc->sc_timer, 0, "TX timer"); 2463228332Syongari 2464228332Syongari tree = SYSCTL_ADD_NODE(ctx, children, OID_AUTO, "stats", CTLFLAG_RD, 2465228332Syongari NULL, "ET statistics"); 2466228332Syongari parent = SYSCTL_CHILDREN(tree); 2467228332Syongari 2468228332Syongari /* TX/RX statistics. */ 2469228332Syongari stats = &sc->sc_stats; 2470228332Syongari ET_SYSCTL_STAT_ADD64(ctx, parent, "frames_64", &stats->pkts_64, 2471228332Syongari "0 to 64 bytes frames"); 2472228332Syongari ET_SYSCTL_STAT_ADD64(ctx, parent, "frames_65_127", &stats->pkts_65, 2473228332Syongari "65 to 127 bytes frames"); 2474228332Syongari ET_SYSCTL_STAT_ADD64(ctx, parent, "frames_128_255", &stats->pkts_128, 2475228332Syongari "128 to 255 bytes frames"); 2476228332Syongari ET_SYSCTL_STAT_ADD64(ctx, parent, "frames_256_511", &stats->pkts_256, 2477228332Syongari "256 to 511 bytes frames"); 2478228332Syongari ET_SYSCTL_STAT_ADD64(ctx, parent, "frames_512_1023", &stats->pkts_512, 2479228332Syongari "512 to 1023 bytes frames"); 2480228332Syongari ET_SYSCTL_STAT_ADD64(ctx, parent, "frames_1024_1518", &stats->pkts_1024, 2481228332Syongari "1024 to 1518 bytes frames"); 2482228332Syongari ET_SYSCTL_STAT_ADD64(ctx, parent, "frames_1519_1522", &stats->pkts_1519, 2483228332Syongari "1519 to 1522 bytes frames"); 2484228332Syongari 2485228332Syongari /* RX statistics. */ 2486228332Syongari tree = SYSCTL_ADD_NODE(ctx, parent, OID_AUTO, "rx", CTLFLAG_RD, 2487228332Syongari NULL, "RX MAC statistics"); 2488228332Syongari children = SYSCTL_CHILDREN(tree); 2489228332Syongari ET_SYSCTL_STAT_ADD64(ctx, children, "bytes", 2490228332Syongari &stats->rx_bytes, "Good bytes"); 2491228332Syongari ET_SYSCTL_STAT_ADD64(ctx, children, "frames", 2492228332Syongari &stats->rx_frames, "Good frames"); 2493228332Syongari ET_SYSCTL_STAT_ADD32(ctx, children, "crc_errs", 2494228332Syongari &stats->rx_crcerrs, "CRC errors"); 2495228332Syongari ET_SYSCTL_STAT_ADD64(ctx, children, "mcast_frames", 2496228332Syongari &stats->rx_mcast, "Multicast frames"); 2497228332Syongari ET_SYSCTL_STAT_ADD64(ctx, children, "bcast_frames", 2498228332Syongari &stats->rx_bcast, "Broadcast frames"); 2499228332Syongari ET_SYSCTL_STAT_ADD32(ctx, children, "control", 2500228332Syongari &stats->rx_control, "Control frames"); 2501228332Syongari ET_SYSCTL_STAT_ADD32(ctx, children, "pause", 2502228332Syongari &stats->rx_pause, "Pause frames"); 2503228332Syongari ET_SYSCTL_STAT_ADD32(ctx, children, "unknown_control", 2504228332Syongari &stats->rx_unknown_control, "Unknown control frames"); 2505228332Syongari ET_SYSCTL_STAT_ADD32(ctx, children, "align_errs", 2506228332Syongari &stats->rx_alignerrs, "Alignment errors"); 2507228332Syongari ET_SYSCTL_STAT_ADD32(ctx, children, "len_errs", 2508228332Syongari &stats->rx_lenerrs, "Frames with length mismatched"); 2509228332Syongari ET_SYSCTL_STAT_ADD32(ctx, children, "code_errs", 2510228332Syongari &stats->rx_codeerrs, "Frames with code error"); 2511228332Syongari ET_SYSCTL_STAT_ADD32(ctx, children, "cs_errs", 2512228332Syongari &stats->rx_cserrs, "Frames with carrier sense error"); 2513228332Syongari ET_SYSCTL_STAT_ADD32(ctx, children, "runts", 2514228332Syongari &stats->rx_runts, "Too short frames"); 2515228332Syongari ET_SYSCTL_STAT_ADD64(ctx, children, "oversize", 2516228332Syongari &stats->rx_oversize, "Oversized frames"); 2517228332Syongari ET_SYSCTL_STAT_ADD32(ctx, children, "fragments", 2518228332Syongari &stats->rx_fragments, "Fragmented frames"); 2519228332Syongari ET_SYSCTL_STAT_ADD32(ctx, children, "jabbers", 2520228332Syongari &stats->rx_jabbers, "Frames with jabber error"); 2521228332Syongari ET_SYSCTL_STAT_ADD32(ctx, children, "drop", 2522228332Syongari &stats->rx_drop, "Dropped frames"); 2523228332Syongari 2524228332Syongari /* TX statistics. */ 2525228332Syongari tree = SYSCTL_ADD_NODE(ctx, parent, OID_AUTO, "tx", CTLFLAG_RD, 2526228332Syongari NULL, "TX MAC statistics"); 2527228332Syongari children = SYSCTL_CHILDREN(tree); 2528228332Syongari ET_SYSCTL_STAT_ADD64(ctx, children, "bytes", 2529228332Syongari &stats->tx_bytes, "Good bytes"); 2530228332Syongari ET_SYSCTL_STAT_ADD64(ctx, children, "frames", 2531228332Syongari &stats->tx_frames, "Good frames"); 2532228332Syongari ET_SYSCTL_STAT_ADD64(ctx, children, "mcast_frames", 2533228332Syongari &stats->tx_mcast, "Multicast frames"); 2534228332Syongari ET_SYSCTL_STAT_ADD64(ctx, children, "bcast_frames", 2535228332Syongari &stats->tx_bcast, "Broadcast frames"); 2536228332Syongari ET_SYSCTL_STAT_ADD32(ctx, children, "pause", 2537228332Syongari &stats->tx_pause, "Pause frames"); 2538228332Syongari ET_SYSCTL_STAT_ADD32(ctx, children, "deferred", 2539228332Syongari &stats->tx_deferred, "Deferred frames"); 2540228332Syongari ET_SYSCTL_STAT_ADD32(ctx, children, "excess_deferred", 2541228332Syongari &stats->tx_excess_deferred, "Excessively deferred frames"); 2542228332Syongari ET_SYSCTL_STAT_ADD32(ctx, children, "single_colls", 2543228332Syongari &stats->tx_single_colls, "Single collisions"); 2544228332Syongari ET_SYSCTL_STAT_ADD32(ctx, children, "multi_colls", 2545228332Syongari &stats->tx_multi_colls, "Multiple collisions"); 2546228332Syongari ET_SYSCTL_STAT_ADD32(ctx, children, "late_colls", 2547228332Syongari &stats->tx_late_colls, "Late collisions"); 2548228332Syongari ET_SYSCTL_STAT_ADD32(ctx, children, "excess_colls", 2549228332Syongari &stats->tx_excess_colls, "Excess collisions"); 2550228332Syongari ET_SYSCTL_STAT_ADD32(ctx, children, "total_colls", 2551228332Syongari &stats->tx_total_colls, "Total collisions"); 2552228332Syongari ET_SYSCTL_STAT_ADD32(ctx, children, "pause_honored", 2553228332Syongari &stats->tx_pause_honored, "Honored pause frames"); 2554228332Syongari ET_SYSCTL_STAT_ADD32(ctx, children, "drop", 2555228332Syongari &stats->tx_drop, "Dropped frames"); 2556228332Syongari ET_SYSCTL_STAT_ADD32(ctx, children, "jabbers", 2557228332Syongari &stats->tx_jabbers, "Frames with jabber errors"); 2558228332Syongari ET_SYSCTL_STAT_ADD32(ctx, children, "crc_errs", 2559228332Syongari &stats->tx_crcerrs, "Frames with CRC errors"); 2560228332Syongari ET_SYSCTL_STAT_ADD32(ctx, children, "control", 2561228332Syongari &stats->tx_control, "Control frames"); 2562228332Syongari ET_SYSCTL_STAT_ADD64(ctx, children, "oversize", 2563228332Syongari &stats->tx_oversize, "Oversized frames"); 2564228332Syongari ET_SYSCTL_STAT_ADD32(ctx, children, "undersize", 2565228332Syongari &stats->tx_undersize, "Undersized frames"); 2566228332Syongari ET_SYSCTL_STAT_ADD32(ctx, children, "fragments", 2567228332Syongari &stats->tx_fragments, "Fragmented frames"); 2568179895Sdelphij} 2569179895Sdelphij 2570228332Syongari#undef ET_SYSCTL_STAT_ADD32 2571228332Syongari#undef ET_SYSCTL_STAT_ADD64 2572228332Syongari 2573179895Sdelphijstatic int 2574179895Sdelphijet_sysctl_rx_intr_npkts(SYSCTL_HANDLER_ARGS) 2575179895Sdelphij{ 2576229940Syongari struct et_softc *sc; 2577229940Syongari struct ifnet *ifp; 2578229940Syongari int error, v; 2579179895Sdelphij 2580229940Syongari sc = arg1; 2581229940Syongari ifp = sc->ifp; 2582179895Sdelphij v = sc->sc_rx_intr_npkts; 2583179895Sdelphij error = sysctl_handle_int(oidp, &v, 0, req); 2584179895Sdelphij if (error || req->newptr == NULL) 2585179895Sdelphij goto back; 2586179895Sdelphij if (v <= 0) { 2587179895Sdelphij error = EINVAL; 2588179895Sdelphij goto back; 2589179895Sdelphij } 2590179895Sdelphij 2591179895Sdelphij if (sc->sc_rx_intr_npkts != v) { 2592179895Sdelphij if (ifp->if_drv_flags & IFF_DRV_RUNNING) 2593179895Sdelphij CSR_WRITE_4(sc, ET_RX_INTR_NPKTS, v); 2594179895Sdelphij sc->sc_rx_intr_npkts = v; 2595179895Sdelphij } 2596179895Sdelphijback: 2597199556Syongari return (error); 2598179895Sdelphij} 2599179895Sdelphij 2600179895Sdelphijstatic int 2601179895Sdelphijet_sysctl_rx_intr_delay(SYSCTL_HANDLER_ARGS) 2602179895Sdelphij{ 2603229940Syongari struct et_softc *sc; 2604229940Syongari struct ifnet *ifp; 2605229940Syongari int error, v; 2606179895Sdelphij 2607229940Syongari sc = arg1; 2608229940Syongari ifp = sc->ifp; 2609179895Sdelphij v = sc->sc_rx_intr_delay; 2610179895Sdelphij error = sysctl_handle_int(oidp, &v, 0, req); 2611179895Sdelphij if (error || req->newptr == NULL) 2612179895Sdelphij goto back; 2613179895Sdelphij if (v <= 0) { 2614179895Sdelphij error = EINVAL; 2615179895Sdelphij goto back; 2616179895Sdelphij } 2617179895Sdelphij 2618179895Sdelphij if (sc->sc_rx_intr_delay != v) { 2619179895Sdelphij if (ifp->if_drv_flags & IFF_DRV_RUNNING) 2620179895Sdelphij CSR_WRITE_4(sc, ET_RX_INTR_DELAY, v); 2621179895Sdelphij sc->sc_rx_intr_delay = v; 2622179895Sdelphij } 2623179895Sdelphijback: 2624199556Syongari return (error); 2625179895Sdelphij} 2626179895Sdelphij 2627228332Syongaristatic void 2628228332Syongariet_stats_update(struct et_softc *sc) 2629228332Syongari{ 2630228332Syongari struct et_hw_stats *stats; 2631228332Syongari 2632228332Syongari stats = &sc->sc_stats; 2633228332Syongari stats->pkts_64 += CSR_READ_4(sc, ET_STAT_PKTS_64); 2634228332Syongari stats->pkts_65 += CSR_READ_4(sc, ET_STAT_PKTS_65_127); 2635228332Syongari stats->pkts_128 += CSR_READ_4(sc, ET_STAT_PKTS_128_255); 2636228332Syongari stats->pkts_256 += CSR_READ_4(sc, ET_STAT_PKTS_256_511); 2637228332Syongari stats->pkts_512 += CSR_READ_4(sc, ET_STAT_PKTS_512_1023); 2638228332Syongari stats->pkts_1024 += CSR_READ_4(sc, ET_STAT_PKTS_1024_1518); 2639228332Syongari stats->pkts_1519 += CSR_READ_4(sc, ET_STAT_PKTS_1519_1522); 2640228332Syongari 2641228332Syongari stats->rx_bytes += CSR_READ_4(sc, ET_STAT_RX_BYTES); 2642228332Syongari stats->rx_frames += CSR_READ_4(sc, ET_STAT_RX_FRAMES); 2643228332Syongari stats->rx_crcerrs += CSR_READ_4(sc, ET_STAT_RX_CRC_ERR); 2644228332Syongari stats->rx_mcast += CSR_READ_4(sc, ET_STAT_RX_MCAST); 2645228332Syongari stats->rx_bcast += CSR_READ_4(sc, ET_STAT_RX_BCAST); 2646228332Syongari stats->rx_control += CSR_READ_4(sc, ET_STAT_RX_CTL); 2647228332Syongari stats->rx_pause += CSR_READ_4(sc, ET_STAT_RX_PAUSE); 2648228332Syongari stats->rx_unknown_control += CSR_READ_4(sc, ET_STAT_RX_UNKNOWN_CTL); 2649228332Syongari stats->rx_alignerrs += CSR_READ_4(sc, ET_STAT_RX_ALIGN_ERR); 2650228332Syongari stats->rx_lenerrs += CSR_READ_4(sc, ET_STAT_RX_LEN_ERR); 2651228332Syongari stats->rx_codeerrs += CSR_READ_4(sc, ET_STAT_RX_CODE_ERR); 2652228332Syongari stats->rx_cserrs += CSR_READ_4(sc, ET_STAT_RX_CS_ERR); 2653228332Syongari stats->rx_runts += CSR_READ_4(sc, ET_STAT_RX_RUNT); 2654228332Syongari stats->rx_oversize += CSR_READ_4(sc, ET_STAT_RX_OVERSIZE); 2655228332Syongari stats->rx_fragments += CSR_READ_4(sc, ET_STAT_RX_FRAG); 2656228332Syongari stats->rx_jabbers += CSR_READ_4(sc, ET_STAT_RX_JABBER); 2657228332Syongari stats->rx_drop += CSR_READ_4(sc, ET_STAT_RX_DROP); 2658228332Syongari 2659228332Syongari stats->tx_bytes += CSR_READ_4(sc, ET_STAT_TX_BYTES); 2660228332Syongari stats->tx_frames += CSR_READ_4(sc, ET_STAT_TX_FRAMES); 2661228332Syongari stats->tx_mcast += CSR_READ_4(sc, ET_STAT_TX_MCAST); 2662228332Syongari stats->tx_bcast += CSR_READ_4(sc, ET_STAT_TX_BCAST); 2663228332Syongari stats->tx_pause += CSR_READ_4(sc, ET_STAT_TX_PAUSE); 2664228332Syongari stats->tx_deferred += CSR_READ_4(sc, ET_STAT_TX_DEFER); 2665228332Syongari stats->tx_excess_deferred += CSR_READ_4(sc, ET_STAT_TX_EXCESS_DEFER); 2666228332Syongari stats->tx_single_colls += CSR_READ_4(sc, ET_STAT_TX_SINGLE_COL); 2667228332Syongari stats->tx_multi_colls += CSR_READ_4(sc, ET_STAT_TX_MULTI_COL); 2668228332Syongari stats->tx_late_colls += CSR_READ_4(sc, ET_STAT_TX_LATE_COL); 2669228332Syongari stats->tx_excess_colls += CSR_READ_4(sc, ET_STAT_TX_EXCESS_COL); 2670228332Syongari stats->tx_total_colls += CSR_READ_4(sc, ET_STAT_TX_TOTAL_COL); 2671228332Syongari stats->tx_pause_honored += CSR_READ_4(sc, ET_STAT_TX_PAUSE_HONOR); 2672228332Syongari stats->tx_drop += CSR_READ_4(sc, ET_STAT_TX_DROP); 2673228332Syongari stats->tx_jabbers += CSR_READ_4(sc, ET_STAT_TX_JABBER); 2674228332Syongari stats->tx_crcerrs += CSR_READ_4(sc, ET_STAT_TX_CRC_ERR); 2675228332Syongari stats->tx_control += CSR_READ_4(sc, ET_STAT_TX_CTL); 2676228332Syongari stats->tx_oversize += CSR_READ_4(sc, ET_STAT_TX_OVERSIZE); 2677228332Syongari stats->tx_undersize += CSR_READ_4(sc, ET_STAT_TX_UNDERSIZE); 2678228332Syongari stats->tx_fragments += CSR_READ_4(sc, ET_STAT_TX_FRAG); 2679272064Sglebius} 2680228332Syongari 2681272064Sglebiusstatic uint64_t 2682272064Sglebiuset_get_counter(struct ifnet *ifp, ift_counter cnt) 2683272064Sglebius{ 2684272064Sglebius struct et_softc *sc; 2685272064Sglebius struct et_hw_stats *stats; 2686272064Sglebius 2687272064Sglebius sc = if_getsoftc(ifp); 2688272064Sglebius stats = &sc->sc_stats; 2689272064Sglebius 2690272064Sglebius switch (cnt) { 2691272064Sglebius case IFCOUNTER_OPACKETS: 2692272064Sglebius return (stats->tx_frames); 2693272064Sglebius case IFCOUNTER_COLLISIONS: 2694272064Sglebius return (stats->tx_total_colls); 2695272064Sglebius case IFCOUNTER_OERRORS: 2696272064Sglebius return (stats->tx_drop + stats->tx_jabbers + 2697272064Sglebius stats->tx_crcerrs + stats->tx_excess_deferred + 2698272064Sglebius stats->tx_late_colls); 2699272064Sglebius case IFCOUNTER_IPACKETS: 2700272064Sglebius return (stats->rx_frames); 2701272064Sglebius case IFCOUNTER_IERRORS: 2702272064Sglebius return (stats->rx_crcerrs + stats->rx_alignerrs + 2703272064Sglebius stats->rx_lenerrs + stats->rx_codeerrs + stats->rx_cserrs + 2704272064Sglebius stats->rx_runts + stats->rx_jabbers + stats->rx_drop); 2705272064Sglebius default: 2706272064Sglebius return (if_get_counter_default(ifp, cnt)); 2707272064Sglebius } 2708228332Syongari} 2709228332Syongari 2710228292Syongaristatic int 2711228292Syongariet_suspend(device_t dev) 2712228292Syongari{ 2713228292Syongari struct et_softc *sc; 2714228336Syongari uint32_t pmcfg; 2715228292Syongari 2716228292Syongari sc = device_get_softc(dev); 2717228292Syongari ET_LOCK(sc); 2718228292Syongari if ((sc->ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) 2719228292Syongari et_stop(sc); 2720228336Syongari /* Diable all clocks and put PHY into COMA. */ 2721228336Syongari pmcfg = CSR_READ_4(sc, ET_PM); 2722228336Syongari pmcfg &= ~(EM_PM_GIGEPHY_ENB | ET_PM_SYSCLK_GATE | ET_PM_TXCLK_GATE | 2723228336Syongari ET_PM_RXCLK_GATE); 2724228336Syongari pmcfg |= ET_PM_PHY_SW_COMA; 2725228336Syongari CSR_WRITE_4(sc, ET_PM, pmcfg); 2726228292Syongari ET_UNLOCK(sc); 2727228292Syongari return (0); 2728228292Syongari} 2729228292Syongari 2730228292Syongaristatic int 2731228292Syongariet_resume(device_t dev) 2732228292Syongari{ 2733228292Syongari struct et_softc *sc; 2734228336Syongari uint32_t pmcfg; 2735228292Syongari 2736228292Syongari sc = device_get_softc(dev); 2737228292Syongari ET_LOCK(sc); 2738228336Syongari /* Take PHY out of COMA and enable clocks. */ 2739228336Syongari pmcfg = ET_PM_SYSCLK_GATE | ET_PM_TXCLK_GATE | ET_PM_RXCLK_GATE; 2740228336Syongari if ((sc->sc_flags & ET_FLAG_FASTETHER) == 0) 2741228336Syongari pmcfg |= EM_PM_GIGEPHY_ENB; 2742228336Syongari CSR_WRITE_4(sc, ET_PM, pmcfg); 2743228292Syongari if ((sc->ifp->if_flags & IFF_UP) != 0) 2744228292Syongari et_init_locked(sc); 2745228292Syongari ET_UNLOCK(sc); 2746228292Syongari return (0); 2747228292Syongari} 2748