if_gem.c revision 194763
1119418Sobrien/*- 291398Stmm * Copyright (C) 2001 Eduardo Horvath. 3108832Stmm * Copyright (c) 2001-2003 Thomas Moestl 4174987Smarius * Copyright (c) 2007 Marius Strobl <marius@FreeBSD.org> 591398Stmm * All rights reserved. 691398Stmm * 791398Stmm * Redistribution and use in source and binary forms, with or without 891398Stmm * modification, are permitted provided that the following conditions 991398Stmm * are met: 1091398Stmm * 1. Redistributions of source code must retain the above copyright 1191398Stmm * notice, this list of conditions and the following disclaimer. 1291398Stmm * 2. Redistributions in binary form must reproduce the above copyright 1391398Stmm * notice, this list of conditions and the following disclaimer in the 1491398Stmm * documentation and/or other materials provided with the distribution. 1591398Stmm * 1691398Stmm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND 1791398Stmm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1891398Stmm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1991398Stmm * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE 2091398Stmm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2191398Stmm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2291398Stmm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2391398Stmm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2491398Stmm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2591398Stmm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2691398Stmm * SUCH DAMAGE. 2791398Stmm * 2899726Sbenno * from: NetBSD: gem.c,v 1.21 2002/06/01 23:50:58 lukem Exp 2991398Stmm */ 3091398Stmm 31119418Sobrien#include <sys/cdefs.h> 32119418Sobrien__FBSDID("$FreeBSD: head/sys/dev/gem/if_gem.c 194763 2009-06-23 20:36:59Z marius $"); 33119418Sobrien 3491398Stmm/* 35172334Smarius * Driver for Apple GMAC, Sun ERI and Sun GEM Ethernet controllers 3691398Stmm */ 3791398Stmm 38115030Stmm#if 0 3991398Stmm#define GEM_DEBUG 40115030Stmm#endif 4191398Stmm 42148368Smarius#if 0 /* XXX: In case of emergency, re-enable this. */ 43148368Smarius#define GEM_RINT_TIMEOUT 44148368Smarius#endif 45148368Smarius 4691398Stmm#include <sys/param.h> 4791398Stmm#include <sys/systm.h> 4891398Stmm#include <sys/bus.h> 4991398Stmm#include <sys/callout.h> 5095533Smike#include <sys/endian.h> 5191398Stmm#include <sys/mbuf.h> 5291398Stmm#include <sys/malloc.h> 5391398Stmm#include <sys/kernel.h> 54148369Smarius#include <sys/lock.h> 55130026Sphk#include <sys/module.h> 56148369Smarius#include <sys/mutex.h> 5791398Stmm#include <sys/socket.h> 5891398Stmm#include <sys/sockio.h> 59169269Sphk#include <sys/rman.h> 6091398Stmm 61105982Stmm#include <net/bpf.h> 6291398Stmm#include <net/ethernet.h> 6391398Stmm#include <net/if.h> 6491398Stmm#include <net/if_arp.h> 6591398Stmm#include <net/if_dl.h> 6691398Stmm#include <net/if_media.h> 67147256Sbrooks#include <net/if_types.h> 68149552Smarius#include <net/if_vlan_var.h> 6991398Stmm 70170273Syongari#include <netinet/in.h> 71170273Syongari#include <netinet/in_systm.h> 72170273Syongari#include <netinet/ip.h> 73170273Syongari#include <netinet/tcp.h> 74170273Syongari#include <netinet/udp.h> 75170273Syongari 7691398Stmm#include <machine/bus.h> 7791398Stmm 7891398Stmm#include <dev/mii/mii.h> 7991398Stmm#include <dev/mii/miivar.h> 8091398Stmm 81119355Simp#include <dev/gem/if_gemreg.h> 82119355Simp#include <dev/gem/if_gemvar.h> 8391398Stmm 84172334SmariusCTASSERT(powerof2(GEM_NRXDESC) && GEM_NRXDESC >= 32 && GEM_NRXDESC <= 8192); 85172334SmariusCTASSERT(powerof2(GEM_NTXDESC) && GEM_NTXDESC >= 32 && GEM_NTXDESC <= 8192); 86172334Smarius 87194763Smarius#define GEM_TRIES 10000 88172334Smarius 89170273Syongari/* 90182060Smarius * The hardware supports basic TCP/UDP checksum offloading. However, 91170273Syongari * the hardware doesn't compensate the checksum for UDP datagram which 92174987Smarius * can yield to 0x0. As a safe guard, UDP checksum offload is disabled 93174987Smarius * by default. It can be reactivated by setting special link option 94170273Syongari * link0 with ifconfig(8). 95170273Syongari */ 96170273Syongari#define GEM_CSUM_FEATURES (CSUM_TCP) 9791398Stmm 98174987Smariusstatic int gem_add_rxbuf(struct gem_softc *sc, int idx); 99177560Smariusstatic int gem_bitwait(struct gem_softc *sc, u_int bank, bus_addr_t r, 100177560Smarius uint32_t clr, uint32_t set); 101174987Smariusstatic void gem_cddma_callback(void *xsc, bus_dma_segment_t *segs, 102174987Smarius int nsegs, int error); 103174987Smariusstatic int gem_disable_rx(struct gem_softc *sc); 104174987Smariusstatic int gem_disable_tx(struct gem_softc *sc); 105174987Smariusstatic void gem_eint(struct gem_softc *sc, u_int status); 106174987Smariusstatic void gem_init(void *xsc); 107174987Smariusstatic void gem_init_locked(struct gem_softc *sc); 108174987Smariusstatic void gem_init_regs(struct gem_softc *sc); 109174987Smariusstatic int gem_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data); 110174987Smariusstatic int gem_load_txmbuf(struct gem_softc *sc, struct mbuf **m_head); 111174987Smariusstatic int gem_meminit(struct gem_softc *sc); 112174987Smariusstatic void gem_mifinit(struct gem_softc *sc); 113174987Smariusstatic void gem_reset(struct gem_softc *sc); 114174987Smariusstatic int gem_reset_rx(struct gem_softc *sc); 115172334Smariusstatic void gem_reset_rxdma(struct gem_softc *sc); 116174987Smariusstatic int gem_reset_tx(struct gem_softc *sc); 117174987Smariusstatic u_int gem_ringsize(u_int sz); 118174987Smariusstatic void gem_rint(struct gem_softc *sc); 119148368Smarius#ifdef GEM_RINT_TIMEOUT 120174987Smariusstatic void gem_rint_timeout(void *arg); 121100587Sjake#endif 122194763Smariusstatic inline void gem_rxcksum(struct mbuf *m, uint64_t flags); 123174987Smariusstatic void gem_rxdrain(struct gem_softc *sc); 124174987Smariusstatic void gem_setladrf(struct gem_softc *sc); 125174987Smariusstatic void gem_start(struct ifnet *ifp); 126174987Smariusstatic void gem_start_locked(struct ifnet *ifp); 127174987Smariusstatic void gem_stop(struct ifnet *ifp, int disable); 128174987Smariusstatic void gem_tick(void *arg); 129174987Smariusstatic void gem_tint(struct gem_softc *sc); 130194763Smariusstatic inline void gem_txkick(struct gem_softc *sc); 131174987Smariusstatic int gem_watchdog(struct gem_softc *sc); 13291398Stmm 13391398Stmmdevclass_t gem_devclass; 13491398StmmDRIVER_MODULE(miibus, gem, miibus_driver, miibus_devclass, 0, 0); 13591398StmmMODULE_DEPEND(gem, miibus, 1, 1, 1); 13691398Stmm 13791398Stmm#ifdef GEM_DEBUG 13891398Stmm#include <sys/ktr.h> 13991398Stmm#define KTR_GEM KTR_CT2 14091398Stmm#endif 14191398Stmm 142177560Smarius#define GEM_BANK1_BITWAIT(sc, r, clr, set) \ 143177560Smarius gem_bitwait((sc), GEM_RES_BANK1, (r), (clr), (set)) 144177560Smarius#define GEM_BANK2_BITWAIT(sc, r, clr, set) \ 145177560Smarius gem_bitwait((sc), GEM_RES_BANK2, (r), (clr), (set)) 146177560Smarius 14791398Stmmint 148174987Smariusgem_attach(struct gem_softc *sc) 14991398Stmm{ 150174987Smarius struct gem_txsoft *txs; 151147256Sbrooks struct ifnet *ifp; 152174987Smarius int error, i; 153174987Smarius uint32_t v; 15491398Stmm 155194763Smarius if (bootverbose) 156194763Smarius device_printf(sc->sc_dev, "flags=0x%x\n", sc->sc_flags); 157194763Smarius 158194763Smarius /* Set up ifnet structure. */ 159147256Sbrooks ifp = sc->sc_ifp = if_alloc(IFT_ETHER); 160147256Sbrooks if (ifp == NULL) 161147256Sbrooks return (ENOSPC); 162194763Smarius sc->sc_csum_features = GEM_CSUM_FEATURES; 163194763Smarius ifp->if_softc = sc; 164194763Smarius if_initname(ifp, device_get_name(sc->sc_dev), 165194763Smarius device_get_unit(sc->sc_dev)); 166194763Smarius ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 167194763Smarius ifp->if_start = gem_start; 168194763Smarius ifp->if_ioctl = gem_ioctl; 169194763Smarius ifp->if_init = gem_init; 170194763Smarius IFQ_SET_MAXLEN(&ifp->if_snd, GEM_TXQUEUELEN); 171194763Smarius ifp->if_snd.ifq_drv_maxlen = GEM_TXQUEUELEN; 172194763Smarius IFQ_SET_READY(&ifp->if_snd); 173147256Sbrooks 174150285Smarius callout_init_mtx(&sc->sc_tick_ch, &sc->sc_mtx, 0); 175150285Smarius#ifdef GEM_RINT_TIMEOUT 176150285Smarius callout_init_mtx(&sc->sc_rx_ch, &sc->sc_mtx, 0); 177150285Smarius#endif 178150285Smarius 17991398Stmm /* Make sure the chip is stopped. */ 18091398Stmm gem_reset(sc); 18191398Stmm 182161928Sjmg error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), 1, 0, 183161928Sjmg BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, 184174987Smarius BUS_SPACE_MAXSIZE_32BIT, 0, BUS_SPACE_MAXSIZE_32BIT, 0, NULL, 185174987Smarius NULL, &sc->sc_pdmatag); 186194763Smarius if (error != 0) 187147256Sbrooks goto fail_ifnet; 18891398Stmm 18991398Stmm error = bus_dma_tag_create(sc->sc_pdmatag, 1, 0, 190170273Syongari BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, MCLBYTES, 191170273Syongari 1, MCLBYTES, BUS_DMA_ALLOCNOW, NULL, NULL, &sc->sc_rdmatag); 192194763Smarius if (error != 0) 193108832Stmm goto fail_ptag; 19491398Stmm 195108832Stmm error = bus_dma_tag_create(sc->sc_pdmatag, 1, 0, 196170273Syongari BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, 197170273Syongari MCLBYTES * GEM_NTXSEGS, GEM_NTXSEGS, MCLBYTES, 198117126Sscottl BUS_DMA_ALLOCNOW, NULL, NULL, &sc->sc_tdmatag); 199194763Smarius if (error != 0) 200108832Stmm goto fail_rtag; 201108832Stmm 20291398Stmm error = bus_dma_tag_create(sc->sc_pdmatag, PAGE_SIZE, 0, 203170273Syongari BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, 20491398Stmm sizeof(struct gem_control_data), 1, 205170273Syongari sizeof(struct gem_control_data), 0, 206170273Syongari NULL, NULL, &sc->sc_cdmatag); 207194763Smarius if (error != 0) 208108832Stmm goto fail_ttag; 20991398Stmm 21091398Stmm /* 211174987Smarius * Allocate the control data structures, create and load the 21291398Stmm * DMA map for it. 21391398Stmm */ 21491398Stmm if ((error = bus_dmamem_alloc(sc->sc_cdmatag, 215170273Syongari (void **)&sc->sc_control_data, 216170273Syongari BUS_DMA_WAITOK | BUS_DMA_COHERENT | BUS_DMA_ZERO, 217194763Smarius &sc->sc_cddmamap)) != 0) { 218174987Smarius device_printf(sc->sc_dev, 219174987Smarius "unable to allocate control data, error = %d\n", error); 220108832Stmm goto fail_ctag; 22191398Stmm } 22291398Stmm 22391398Stmm sc->sc_cddma = 0; 22491398Stmm if ((error = bus_dmamap_load(sc->sc_cdmatag, sc->sc_cddmamap, 22591398Stmm sc->sc_control_data, sizeof(struct gem_control_data), 22691398Stmm gem_cddma_callback, sc, 0)) != 0 || sc->sc_cddma == 0) { 227174987Smarius device_printf(sc->sc_dev, 228174987Smarius "unable to load control data DMA map, error = %d\n", 229174987Smarius error); 230108832Stmm goto fail_cmem; 23191398Stmm } 23291398Stmm 23391398Stmm /* 23491398Stmm * Initialize the transmit job descriptors. 23591398Stmm */ 23691398Stmm STAILQ_INIT(&sc->sc_txfreeq); 23791398Stmm STAILQ_INIT(&sc->sc_txdirtyq); 23891398Stmm 23991398Stmm /* 24091398Stmm * Create the transmit buffer DMA maps. 24191398Stmm */ 24291398Stmm error = ENOMEM; 24391398Stmm for (i = 0; i < GEM_TXQUEUELEN; i++) { 24491398Stmm txs = &sc->sc_txsoft[i]; 24591398Stmm txs->txs_mbuf = NULL; 24691398Stmm txs->txs_ndescs = 0; 247108832Stmm if ((error = bus_dmamap_create(sc->sc_tdmatag, 0, 24891398Stmm &txs->txs_dmamap)) != 0) { 249174987Smarius device_printf(sc->sc_dev, 250174987Smarius "unable to create TX DMA map %d, error = %d\n", 251174987Smarius i, error); 252108832Stmm goto fail_txd; 25391398Stmm } 25491398Stmm STAILQ_INSERT_TAIL(&sc->sc_txfreeq, txs, txs_q); 25591398Stmm } 25691398Stmm 25791398Stmm /* 25891398Stmm * Create the receive buffer DMA maps. 25991398Stmm */ 26091398Stmm for (i = 0; i < GEM_NRXDESC; i++) { 261108832Stmm if ((error = bus_dmamap_create(sc->sc_rdmatag, 0, 26291398Stmm &sc->sc_rxsoft[i].rxs_dmamap)) != 0) { 263174987Smarius device_printf(sc->sc_dev, 264174987Smarius "unable to create RX DMA map %d, error = %d\n", 265174987Smarius i, error); 266108832Stmm goto fail_rxd; 26791398Stmm } 26891398Stmm sc->sc_rxsoft[i].rxs_mbuf = NULL; 26991398Stmm } 27091398Stmm 271172334Smarius /* Bad things will happen when touching this register on ERI. */ 272172334Smarius if (sc->sc_variant != GEM_SUN_ERI) 273177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MII_DATAPATH_MODE, 274172334Smarius GEM_MII_DATAPATH_MII); 275172334Smarius 27691398Stmm gem_mifinit(sc); 27791398Stmm 278172334Smarius /* 279172334Smarius * Look for an external PHY. 280172334Smarius */ 281172334Smarius error = ENXIO; 282177560Smarius v = GEM_BANK1_READ_4(sc, GEM_MIF_CONFIG); 283172334Smarius if ((v & GEM_MIF_CONFIG_MDI1) != 0) { 284172334Smarius v |= GEM_MIF_CONFIG_PHY_SEL; 285177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MIF_CONFIG, v); 286172334Smarius switch (sc->sc_variant) { 287172334Smarius case GEM_SUN_ERI: 288172334Smarius sc->sc_phyad = GEM_PHYAD_EXTERNAL; 289172334Smarius break; 290172334Smarius default: 291172334Smarius sc->sc_phyad = -1; 292172334Smarius break; 293172334Smarius } 294172334Smarius error = mii_phy_probe(sc->sc_dev, &sc->sc_miibus, 295172334Smarius gem_mediachange, gem_mediastatus); 296172334Smarius } 297172334Smarius 298172334Smarius /* 299172334Smarius * Fall back on an internal PHY if no external PHY was found. 300172334Smarius */ 301172334Smarius if (error != 0 && (v & GEM_MIF_CONFIG_MDI0) != 0) { 302172334Smarius v &= ~GEM_MIF_CONFIG_PHY_SEL; 303177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MIF_CONFIG, v); 304172334Smarius switch (sc->sc_variant) { 305172334Smarius case GEM_SUN_ERI: 306172334Smarius case GEM_APPLE_K2_GMAC: 307172334Smarius sc->sc_phyad = GEM_PHYAD_INTERNAL; 308172334Smarius break; 309172334Smarius case GEM_APPLE_GMAC: 310172334Smarius sc->sc_phyad = GEM_PHYAD_EXTERNAL; 311172334Smarius break; 312172334Smarius default: 313172334Smarius sc->sc_phyad = -1; 314172334Smarius break; 315172334Smarius } 316172334Smarius error = mii_phy_probe(sc->sc_dev, &sc->sc_miibus, 317172334Smarius gem_mediachange, gem_mediastatus); 318172334Smarius } 319172334Smarius 320172334Smarius /* 321172334Smarius * Try the external PCS SERDES if we didn't find any PHYs. 322172334Smarius */ 323172334Smarius if (error != 0 && sc->sc_variant == GEM_SUN_GEM) { 324177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MII_DATAPATH_MODE, 325172334Smarius GEM_MII_DATAPATH_SERDES); 326177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MII_SLINK_CONTROL, 327172334Smarius GEM_MII_SLINK_LOOPBACK | GEM_MII_SLINK_EN_SYNC_D); 328177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MII_CONFIG, GEM_MII_CONFIG_ENABLE); 329172334Smarius sc->sc_flags |= GEM_SERDES; 330172334Smarius sc->sc_phyad = GEM_PHYAD_EXTERNAL; 331172334Smarius error = mii_phy_probe(sc->sc_dev, &sc->sc_miibus, 332172334Smarius gem_mediachange, gem_mediastatus); 333172334Smarius } 334172334Smarius 335172334Smarius if (error != 0) { 336172334Smarius device_printf(sc->sc_dev, "PHY probe failed: %d\n", error); 337108832Stmm goto fail_rxd; 33891398Stmm } 33991398Stmm sc->sc_mii = device_get_softc(sc->sc_miibus); 34091398Stmm 34191398Stmm /* 34291398Stmm * From this point forward, the attachment cannot fail. A failure 34391398Stmm * before this point releases all resources that may have been 34491398Stmm * allocated. 34591398Stmm */ 34691398Stmm 347176996Smarius /* Get RX FIFO size. */ 34899726Sbenno sc->sc_rxfifosize = 64 * 349177560Smarius GEM_BANK1_READ_4(sc, GEM_RX_FIFO_SIZE); 35099726Sbenno 351176996Smarius /* Get TX FIFO size. */ 352177560Smarius v = GEM_BANK1_READ_4(sc, GEM_TX_FIFO_SIZE); 353128588Stmm device_printf(sc->sc_dev, "%ukB RX FIFO, %ukB TX FIFO\n", 354128588Stmm sc->sc_rxfifosize / 1024, v / 16); 35599726Sbenno 35691398Stmm /* Attach the interface. */ 357147256Sbrooks ether_ifattach(ifp, sc->sc_enaddr); 35891398Stmm 35991398Stmm /* 360170273Syongari * Tell the upper layer(s) we support long frames/checksum offloads. 361149552Smarius */ 362149552Smarius ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header); 363170273Syongari ifp->if_capabilities |= IFCAP_VLAN_MTU | IFCAP_HWCSUM; 364170273Syongari ifp->if_hwassist |= sc->sc_csum_features; 365170273Syongari ifp->if_capenable |= IFCAP_VLAN_MTU | IFCAP_HWCSUM; 366149552Smarius 36791398Stmm return (0); 36891398Stmm 36991398Stmm /* 37091398Stmm * Free any resources we've allocated during the failed attach 37191398Stmm * attempt. Do this in reverse order and fall through. 37291398Stmm */ 373174987Smarius fail_rxd: 374174987Smarius for (i = 0; i < GEM_NRXDESC; i++) 37591398Stmm if (sc->sc_rxsoft[i].rxs_dmamap != NULL) 376108832Stmm bus_dmamap_destroy(sc->sc_rdmatag, 37791398Stmm sc->sc_rxsoft[i].rxs_dmamap); 378174987Smarius fail_txd: 379174987Smarius for (i = 0; i < GEM_TXQUEUELEN; i++) 38091398Stmm if (sc->sc_txsoft[i].txs_dmamap != NULL) 381108832Stmm bus_dmamap_destroy(sc->sc_tdmatag, 38291398Stmm sc->sc_txsoft[i].txs_dmamap); 383108832Stmm bus_dmamap_unload(sc->sc_cdmatag, sc->sc_cddmamap); 384174987Smarius fail_cmem: 38591398Stmm bus_dmamem_free(sc->sc_cdmatag, sc->sc_control_data, 38691398Stmm sc->sc_cddmamap); 387174987Smarius fail_ctag: 38891398Stmm bus_dma_tag_destroy(sc->sc_cdmatag); 389174987Smarius fail_ttag: 390108832Stmm bus_dma_tag_destroy(sc->sc_tdmatag); 391174987Smarius fail_rtag: 392108832Stmm bus_dma_tag_destroy(sc->sc_rdmatag); 393174987Smarius fail_ptag: 39491398Stmm bus_dma_tag_destroy(sc->sc_pdmatag); 395174987Smarius fail_ifnet: 396147256Sbrooks if_free(ifp); 39791398Stmm return (error); 39891398Stmm} 39991398Stmm 400108964Stmmvoid 401174987Smariusgem_detach(struct gem_softc *sc) 402108964Stmm{ 403147256Sbrooks struct ifnet *ifp = sc->sc_ifp; 404108964Stmm int i; 405108964Stmm 406148369Smarius GEM_LOCK(sc); 407194763Smarius sc->sc_flags |= GEM_DYING; 408147317Sbrooks gem_stop(ifp, 1); 409148369Smarius GEM_UNLOCK(sc); 410150285Smarius callout_drain(&sc->sc_tick_ch); 411150285Smarius#ifdef GEM_RINT_TIMEOUT 412150285Smarius callout_drain(&sc->sc_rx_ch); 413150285Smarius#endif 414108964Stmm ether_ifdetach(ifp); 415147256Sbrooks if_free(ifp); 416108964Stmm device_delete_child(sc->sc_dev, sc->sc_miibus); 417108964Stmm 418174987Smarius for (i = 0; i < GEM_NRXDESC; i++) 419108964Stmm if (sc->sc_rxsoft[i].rxs_dmamap != NULL) 420108964Stmm bus_dmamap_destroy(sc->sc_rdmatag, 421108964Stmm sc->sc_rxsoft[i].rxs_dmamap); 422174987Smarius for (i = 0; i < GEM_TXQUEUELEN; i++) 423108964Stmm if (sc->sc_txsoft[i].txs_dmamap != NULL) 424108964Stmm bus_dmamap_destroy(sc->sc_tdmatag, 425108964Stmm sc->sc_txsoft[i].txs_dmamap); 426179925Smarius GEM_CDSYNC(sc, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 427108964Stmm bus_dmamap_unload(sc->sc_cdmatag, sc->sc_cddmamap); 428108964Stmm bus_dmamem_free(sc->sc_cdmatag, sc->sc_control_data, 429108964Stmm sc->sc_cddmamap); 430108964Stmm bus_dma_tag_destroy(sc->sc_cdmatag); 431108964Stmm bus_dma_tag_destroy(sc->sc_tdmatag); 432108964Stmm bus_dma_tag_destroy(sc->sc_rdmatag); 433108964Stmm bus_dma_tag_destroy(sc->sc_pdmatag); 434108964Stmm} 435108964Stmm 436108964Stmmvoid 437174987Smariusgem_suspend(struct gem_softc *sc) 438108964Stmm{ 439147256Sbrooks struct ifnet *ifp = sc->sc_ifp; 440108964Stmm 441148369Smarius GEM_LOCK(sc); 442108964Stmm gem_stop(ifp, 0); 443148369Smarius GEM_UNLOCK(sc); 444108964Stmm} 445108964Stmm 446108964Stmmvoid 447174987Smariusgem_resume(struct gem_softc *sc) 448108964Stmm{ 449147256Sbrooks struct ifnet *ifp = sc->sc_ifp; 450108964Stmm 451148369Smarius GEM_LOCK(sc); 452149552Smarius /* 453149552Smarius * On resume all registers have to be initialized again like 454149552Smarius * after power-on. 455149552Smarius */ 456172334Smarius sc->sc_flags &= ~GEM_INITED; 457108964Stmm if (ifp->if_flags & IFF_UP) 458148369Smarius gem_init_locked(sc); 459148369Smarius GEM_UNLOCK(sc); 460108964Stmm} 461108964Stmm 462194763Smariusstatic inline void 463170273Syongarigem_rxcksum(struct mbuf *m, uint64_t flags) 464170273Syongari{ 465170273Syongari struct ether_header *eh; 466170273Syongari struct ip *ip; 467170273Syongari struct udphdr *uh; 468174987Smarius uint16_t *opts; 469170273Syongari int32_t hlen, len, pktlen; 470170273Syongari uint32_t temp32; 471174987Smarius uint16_t cksum; 472170273Syongari 473170273Syongari pktlen = m->m_pkthdr.len; 474170273Syongari if (pktlen < sizeof(struct ether_header) + sizeof(struct ip)) 475170273Syongari return; 476170273Syongari eh = mtod(m, struct ether_header *); 477170273Syongari if (eh->ether_type != htons(ETHERTYPE_IP)) 478170273Syongari return; 479170273Syongari ip = (struct ip *)(eh + 1); 480170273Syongari if (ip->ip_v != IPVERSION) 481170273Syongari return; 482170273Syongari 483170273Syongari hlen = ip->ip_hl << 2; 484170273Syongari pktlen -= sizeof(struct ether_header); 485170273Syongari if (hlen < sizeof(struct ip)) 486170273Syongari return; 487170273Syongari if (ntohs(ip->ip_len) < hlen) 488170273Syongari return; 489170273Syongari if (ntohs(ip->ip_len) != pktlen) 490170273Syongari return; 491170273Syongari if (ip->ip_off & htons(IP_MF | IP_OFFMASK)) 492174987Smarius return; /* Cannot handle fragmented packet. */ 493170273Syongari 494170273Syongari switch (ip->ip_p) { 495170273Syongari case IPPROTO_TCP: 496170273Syongari if (pktlen < (hlen + sizeof(struct tcphdr))) 497170273Syongari return; 498170273Syongari break; 499170273Syongari case IPPROTO_UDP: 500170273Syongari if (pktlen < (hlen + sizeof(struct udphdr))) 501170273Syongari return; 502170273Syongari uh = (struct udphdr *)((uint8_t *)ip + hlen); 503170273Syongari if (uh->uh_sum == 0) 504170273Syongari return; /* no checksum */ 505170273Syongari break; 506170273Syongari default: 507170273Syongari return; 508170273Syongari } 509170273Syongari 510170273Syongari cksum = ~(flags & GEM_RD_CHECKSUM); 511170273Syongari /* checksum fixup for IP options */ 512170273Syongari len = hlen - sizeof(struct ip); 513170273Syongari if (len > 0) { 514170273Syongari opts = (uint16_t *)(ip + 1); 515170273Syongari for (; len > 0; len -= sizeof(uint16_t), opts++) { 516170273Syongari temp32 = cksum - *opts; 517170273Syongari temp32 = (temp32 >> 16) + (temp32 & 65535); 518170273Syongari cksum = temp32 & 65535; 519170273Syongari } 520170273Syongari } 521170273Syongari m->m_pkthdr.csum_flags |= CSUM_DATA_VALID; 522170273Syongari m->m_pkthdr.csum_data = cksum; 523170273Syongari} 524170273Syongari 52591398Stmmstatic void 526174987Smariusgem_cddma_callback(void *xsc, bus_dma_segment_t *segs, int nsegs, int error) 52791398Stmm{ 528174987Smarius struct gem_softc *sc = xsc; 52991398Stmm 53091398Stmm if (error != 0) 53191398Stmm return; 532174987Smarius if (nsegs != 1) 533172334Smarius panic("%s: bad control buffer segment count", __func__); 53491398Stmm sc->sc_cddma = segs[0].ds_addr; 53591398Stmm} 53691398Stmm 53791398Stmmstatic void 538174987Smariusgem_tick(void *arg) 53991398Stmm{ 540170273Syongari struct gem_softc *sc = arg; 541194763Smarius struct ifnet *ifp = sc->sc_ifp; 542182060Smarius uint32_t v; 54391398Stmm 544170273Syongari GEM_LOCK_ASSERT(sc, MA_OWNED); 545170273Syongari 546108832Stmm /* 547182060Smarius * Unload collision and error counters. 548108832Stmm */ 549170273Syongari ifp->if_collisions += 550177560Smarius GEM_BANK1_READ_4(sc, GEM_MAC_NORM_COLL_CNT) + 551182060Smarius GEM_BANK1_READ_4(sc, GEM_MAC_FIRST_COLL_CNT); 552182060Smarius v = GEM_BANK1_READ_4(sc, GEM_MAC_EXCESS_COLL_CNT) + 553177560Smarius GEM_BANK1_READ_4(sc, GEM_MAC_LATE_COLL_CNT); 554182060Smarius ifp->if_collisions += v; 555182060Smarius ifp->if_oerrors += v; 556182060Smarius ifp->if_ierrors += 557182060Smarius GEM_BANK1_READ_4(sc, GEM_MAC_RX_LEN_ERR_CNT) + 558182060Smarius GEM_BANK1_READ_4(sc, GEM_MAC_RX_ALIGN_ERR) + 559182060Smarius GEM_BANK1_READ_4(sc, GEM_MAC_RX_CRC_ERR_CNT) + 560182060Smarius GEM_BANK1_READ_4(sc, GEM_MAC_RX_CODE_VIOL); 56191398Stmm 56291398Stmm /* 563176996Smarius * Then clear the hardware counters. 56491398Stmm */ 565177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_NORM_COLL_CNT, 0); 566177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_FIRST_COLL_CNT, 0); 567177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_EXCESS_COLL_CNT, 0); 568177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_LATE_COLL_CNT, 0); 569182060Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_LEN_ERR_CNT, 0); 570182060Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_ALIGN_ERR, 0); 571182060Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_CRC_ERR_CNT, 0); 572182060Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_CODE_VIOL, 0); 573108832Stmm 57491398Stmm mii_tick(sc->sc_mii); 57591398Stmm 576164931Smarius if (gem_watchdog(sc) == EJUSTRETURN) 577164931Smarius return; 578164931Smarius 57991398Stmm callout_reset(&sc->sc_tick_ch, hz, gem_tick, sc); 58091398Stmm} 58191398Stmm 58291398Stmmstatic int 583177560Smariusgem_bitwait(struct gem_softc *sc, u_int bank, bus_addr_t r, uint32_t clr, 584177560Smarius uint32_t set) 58591398Stmm{ 58691398Stmm int i; 587174987Smarius uint32_t reg; 58891398Stmm 589194763Smarius for (i = GEM_TRIES; i--; DELAY(100)) { 590177560Smarius reg = GEM_BANKN_READ_M(bank, 4, sc, r); 591170847Smarius if ((reg & clr) == 0 && (reg & set) == set) 59291398Stmm return (1); 59391398Stmm } 59491398Stmm return (0); 59591398Stmm} 59691398Stmm 597172334Smariusstatic void 598194763Smariusgem_reset(struct gem_softc *sc) 59991398Stmm{ 60091398Stmm 601115030Stmm#ifdef GEM_DEBUG 602170273Syongari CTR2(KTR_GEM, "%s: %s", device_get_name(sc->sc_dev), __func__); 603115030Stmm#endif 60491398Stmm gem_reset_rx(sc); 60591398Stmm gem_reset_tx(sc); 60691398Stmm 607174987Smarius /* Do a full reset. */ 608177560Smarius GEM_BANK2_WRITE_4(sc, GEM_RESET, GEM_RESET_RX | GEM_RESET_TX); 609179925Smarius GEM_BANK2_BARRIER(sc, GEM_RESET, 4, 610179925Smarius BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 611177560Smarius if (!GEM_BANK2_BITWAIT(sc, GEM_RESET, GEM_RESET_RX | GEM_RESET_TX, 0)) 61291398Stmm device_printf(sc->sc_dev, "cannot reset device\n"); 61391398Stmm} 61491398Stmm 61591398Stmmstatic void 616174987Smariusgem_rxdrain(struct gem_softc *sc) 61791398Stmm{ 61891398Stmm struct gem_rxsoft *rxs; 61991398Stmm int i; 62091398Stmm 62191398Stmm for (i = 0; i < GEM_NRXDESC; i++) { 62291398Stmm rxs = &sc->sc_rxsoft[i]; 62391398Stmm if (rxs->rxs_mbuf != NULL) { 624109648Stmm bus_dmamap_sync(sc->sc_rdmatag, rxs->rxs_dmamap, 625109648Stmm BUS_DMASYNC_POSTREAD); 626108832Stmm bus_dmamap_unload(sc->sc_rdmatag, rxs->rxs_dmamap); 62791398Stmm m_freem(rxs->rxs_mbuf); 62891398Stmm rxs->rxs_mbuf = NULL; 62991398Stmm } 63091398Stmm } 63191398Stmm} 63291398Stmm 63391398Stmmstatic void 634174987Smariusgem_stop(struct ifnet *ifp, int disable) 63591398Stmm{ 636174987Smarius struct gem_softc *sc = ifp->if_softc; 63791398Stmm struct gem_txsoft *txs; 63891398Stmm 639115030Stmm#ifdef GEM_DEBUG 640170273Syongari CTR2(KTR_GEM, "%s: %s", device_get_name(sc->sc_dev), __func__); 641115030Stmm#endif 64291398Stmm 64391398Stmm callout_stop(&sc->sc_tick_ch); 644150285Smarius#ifdef GEM_RINT_TIMEOUT 645150285Smarius callout_stop(&sc->sc_rx_ch); 646172334Smarius#endif 64791398Stmm 648194763Smarius gem_reset_tx(sc); 649194763Smarius gem_reset_rx(sc); 65091398Stmm 65191398Stmm /* 65291398Stmm * Release any queued transmit buffers. 65391398Stmm */ 65491398Stmm while ((txs = STAILQ_FIRST(&sc->sc_txdirtyq)) != NULL) { 65591398Stmm STAILQ_REMOVE_HEAD(&sc->sc_txdirtyq, txs_q); 65691398Stmm if (txs->txs_ndescs != 0) { 657109648Stmm bus_dmamap_sync(sc->sc_tdmatag, txs->txs_dmamap, 658109648Stmm BUS_DMASYNC_POSTWRITE); 659108832Stmm bus_dmamap_unload(sc->sc_tdmatag, txs->txs_dmamap); 66091398Stmm if (txs->txs_mbuf != NULL) { 66191398Stmm m_freem(txs->txs_mbuf); 66291398Stmm txs->txs_mbuf = NULL; 66391398Stmm } 66491398Stmm } 66591398Stmm STAILQ_INSERT_TAIL(&sc->sc_txfreeq, txs, txs_q); 66691398Stmm } 66791398Stmm 66891398Stmm if (disable) 66991398Stmm gem_rxdrain(sc); 67091398Stmm 67191398Stmm /* 67291398Stmm * Mark the interface down and cancel the watchdog timer. 67391398Stmm */ 674148887Srwatson ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); 675172334Smarius sc->sc_flags &= ~GEM_LINK; 676164931Smarius sc->sc_wdog_timer = 0; 67791398Stmm} 67891398Stmm 679172334Smariusstatic int 680174987Smariusgem_reset_rx(struct gem_softc *sc) 68191398Stmm{ 68291398Stmm 68391398Stmm /* 68491398Stmm * Resetting while DMA is in progress can cause a bus hang, so we 68591398Stmm * disable DMA first. 68691398Stmm */ 68791398Stmm gem_disable_rx(sc); 688177560Smarius GEM_BANK1_WRITE_4(sc, GEM_RX_CONFIG, 0); 689179925Smarius GEM_BANK1_BARRIER(sc, GEM_RX_CONFIG, 4, 690179925Smarius BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 691177560Smarius if (!GEM_BANK1_BITWAIT(sc, GEM_RX_CONFIG, GEM_RX_CONFIG_RXDMA_EN, 0)) 692172334Smarius device_printf(sc->sc_dev, "cannot disable RX DMA\n"); 69391398Stmm 694176996Smarius /* Finally, reset the ERX. */ 695177560Smarius GEM_BANK2_WRITE_4(sc, GEM_RESET, GEM_RESET_RX); 696179925Smarius GEM_BANK2_BARRIER(sc, GEM_RESET, 4, 697179925Smarius BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 698177560Smarius if (!GEM_BANK2_BITWAIT(sc, GEM_RESET, GEM_RESET_RX | GEM_RESET_TX, 699177560Smarius 0)) { 70091398Stmm device_printf(sc->sc_dev, "cannot reset receiver\n"); 70191398Stmm return (1); 70291398Stmm } 70391398Stmm return (0); 70491398Stmm} 70591398Stmm 706172334Smarius/* 707172334Smarius * Reset the receiver DMA engine. 708172334Smarius * 709172334Smarius * Intended to be used in case of GEM_INTR_RX_TAG_ERR, GEM_MAC_RX_OVERFLOW 710172334Smarius * etc in order to reset the receiver DMA engine only and not do a full 711172334Smarius * reset which amongst others also downs the link and clears the FIFOs. 712172334Smarius */ 713172334Smariusstatic void 714172334Smariusgem_reset_rxdma(struct gem_softc *sc) 715172334Smarius{ 716172334Smarius int i; 71791398Stmm 718172334Smarius if (gem_reset_rx(sc) != 0) 719172334Smarius return (gem_init_locked(sc)); 720172334Smarius for (i = 0; i < GEM_NRXDESC; i++) 721172334Smarius if (sc->sc_rxsoft[i].rxs_mbuf != NULL) 722172334Smarius GEM_UPDATE_RXDESC(sc, i); 723172334Smarius sc->sc_rxptr = 0; 724194763Smarius GEM_CDSYNC(sc, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 725172334Smarius 726172334Smarius /* NOTE: we use only 32-bit DMA addresses here. */ 727177560Smarius GEM_BANK1_WRITE_4(sc, GEM_RX_RING_PTR_HI, 0); 728177560Smarius GEM_BANK1_WRITE_4(sc, GEM_RX_RING_PTR_LO, GEM_CDRXADDR(sc, 0)); 729177560Smarius GEM_BANK1_WRITE_4(sc, GEM_RX_KICK, GEM_NRXDESC - 4); 730177560Smarius GEM_BANK1_WRITE_4(sc, GEM_RX_CONFIG, 731174987Smarius gem_ringsize(GEM_NRXDESC /* XXX */) | 732172334Smarius ((ETHER_HDR_LEN + sizeof(struct ip)) << 733172334Smarius GEM_RX_CONFIG_CXM_START_SHFT) | 734172334Smarius (GEM_THRSH_1024 << GEM_RX_CONFIG_FIFO_THRS_SHIFT) | 735194763Smarius (ETHER_ALIGN << GEM_RX_CONFIG_FBOFF_SHFT)); 736194763Smarius /* Adjust for the SBus clock probably isn't worth the fuzz. */ 737177560Smarius GEM_BANK1_WRITE_4(sc, GEM_RX_BLANKING, 738194763Smarius ((6 * (sc->sc_flags & GEM_PCI66) != 0 ? 2 : 1) << 739194763Smarius GEM_RX_BLANKING_TIME_SHIFT) | 6); 740177560Smarius GEM_BANK1_WRITE_4(sc, GEM_RX_PAUSE_THRESH, 741174987Smarius (3 * sc->sc_rxfifosize / 256) | 742174987Smarius ((sc->sc_rxfifosize / 256) << 12)); 743177560Smarius GEM_BANK1_WRITE_4(sc, GEM_RX_CONFIG, 744177560Smarius GEM_BANK1_READ_4(sc, GEM_RX_CONFIG) | GEM_RX_CONFIG_RXDMA_EN); 745177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_MASK, 746172334Smarius GEM_MAC_RX_DONE | GEM_MAC_RX_FRAME_CNT); 747177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_CONFIG, 748177560Smarius GEM_BANK1_READ_4(sc, GEM_MAC_RX_CONFIG) | GEM_MAC_RX_ENABLE); 749172334Smarius} 750172334Smarius 75191398Stmmstatic int 752174987Smariusgem_reset_tx(struct gem_softc *sc) 75391398Stmm{ 75491398Stmm 75591398Stmm /* 75691398Stmm * Resetting while DMA is in progress can cause a bus hang, so we 75791398Stmm * disable DMA first. 75891398Stmm */ 75991398Stmm gem_disable_tx(sc); 760177560Smarius GEM_BANK1_WRITE_4(sc, GEM_TX_CONFIG, 0); 761179925Smarius GEM_BANK1_BARRIER(sc, GEM_TX_CONFIG, 4, 762179925Smarius BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 763177560Smarius if (!GEM_BANK1_BITWAIT(sc, GEM_TX_CONFIG, GEM_TX_CONFIG_TXDMA_EN, 0)) 764172334Smarius device_printf(sc->sc_dev, "cannot disable TX DMA\n"); 76591398Stmm 766176996Smarius /* Finally, reset the ETX. */ 767177560Smarius GEM_BANK2_WRITE_4(sc, GEM_RESET, GEM_RESET_TX); 768179925Smarius GEM_BANK2_BARRIER(sc, GEM_RESET, 4, 769179925Smarius BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 770177560Smarius if (!GEM_BANK2_BITWAIT(sc, GEM_RESET, GEM_RESET_RX | GEM_RESET_TX, 771177560Smarius 0)) { 772172334Smarius device_printf(sc->sc_dev, "cannot reset transmitter\n"); 77391398Stmm return (1); 77491398Stmm } 77591398Stmm return (0); 77691398Stmm} 77791398Stmm 77891398Stmmstatic int 779174987Smariusgem_disable_rx(struct gem_softc *sc) 78091398Stmm{ 78191398Stmm 782177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_CONFIG, 783177560Smarius GEM_BANK1_READ_4(sc, GEM_MAC_RX_CONFIG) & ~GEM_MAC_RX_ENABLE); 784179925Smarius GEM_BANK1_BARRIER(sc, GEM_MAC_RX_CONFIG, 4, 785179925Smarius BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 786177560Smarius return (GEM_BANK1_BITWAIT(sc, GEM_MAC_RX_CONFIG, GEM_MAC_RX_ENABLE, 787177560Smarius 0)); 78891398Stmm} 78991398Stmm 79091398Stmmstatic int 791174987Smariusgem_disable_tx(struct gem_softc *sc) 79291398Stmm{ 79391398Stmm 794177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_TX_CONFIG, 795177560Smarius GEM_BANK1_READ_4(sc, GEM_MAC_TX_CONFIG) & ~GEM_MAC_TX_ENABLE); 796179925Smarius GEM_BANK1_BARRIER(sc, GEM_MAC_TX_CONFIG, 4, 797179925Smarius BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 798177560Smarius return (GEM_BANK1_BITWAIT(sc, GEM_MAC_TX_CONFIG, GEM_MAC_TX_ENABLE, 799177560Smarius 0)); 80091398Stmm} 80191398Stmm 80291398Stmmstatic int 803194763Smariusgem_meminit(struct gem_softc *sc) 80491398Stmm{ 80591398Stmm struct gem_rxsoft *rxs; 806174987Smarius int error, i; 80791398Stmm 808194763Smarius GEM_LOCK_ASSERT(sc, MA_OWNED); 809194763Smarius 81091398Stmm /* 81191398Stmm * Initialize the transmit descriptor ring. 81291398Stmm */ 81391398Stmm for (i = 0; i < GEM_NTXDESC; i++) { 81491398Stmm sc->sc_txdescs[i].gd_flags = 0; 81591398Stmm sc->sc_txdescs[i].gd_addr = 0; 81691398Stmm } 817108832Stmm sc->sc_txfree = GEM_MAXTXFREE; 81891398Stmm sc->sc_txnext = 0; 81999726Sbenno sc->sc_txwin = 0; 82091398Stmm 82191398Stmm /* 82291398Stmm * Initialize the receive descriptor and receive job 82391398Stmm * descriptor rings. 82491398Stmm */ 82591398Stmm for (i = 0; i < GEM_NRXDESC; i++) { 82691398Stmm rxs = &sc->sc_rxsoft[i]; 82791398Stmm if (rxs->rxs_mbuf == NULL) { 82891398Stmm if ((error = gem_add_rxbuf(sc, i)) != 0) { 829174987Smarius device_printf(sc->sc_dev, 830174987Smarius "unable to allocate or map RX buffer %d, " 831174987Smarius "error = %d\n", i, error); 83291398Stmm /* 833174987Smarius * XXX we should attempt to run with fewer 834174987Smarius * receive buffers instead of just failing. 83591398Stmm */ 83691398Stmm gem_rxdrain(sc); 83791398Stmm return (1); 83891398Stmm } 83991398Stmm } else 84091398Stmm GEM_INIT_RXDESC(sc, i); 84191398Stmm } 84291398Stmm sc->sc_rxptr = 0; 84391398Stmm 844194763Smarius GEM_CDSYNC(sc, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 845194763Smarius 84691398Stmm return (0); 84791398Stmm} 84891398Stmm 849172334Smariusstatic u_int 850174987Smariusgem_ringsize(u_int sz) 85191398Stmm{ 85291398Stmm 85391398Stmm switch (sz) { 85491398Stmm case 32: 855172334Smarius return (GEM_RING_SZ_32); 85691398Stmm case 64: 857172334Smarius return (GEM_RING_SZ_64); 85891398Stmm case 128: 859172334Smarius return (GEM_RING_SZ_128); 86091398Stmm case 256: 861172334Smarius return (GEM_RING_SZ_256); 86291398Stmm case 512: 863172334Smarius return (GEM_RING_SZ_512); 86491398Stmm case 1024: 865172334Smarius return (GEM_RING_SZ_1024); 86691398Stmm case 2048: 867172334Smarius return (GEM_RING_SZ_2048); 86891398Stmm case 4096: 869172334Smarius return (GEM_RING_SZ_4096); 87091398Stmm case 8192: 871172334Smarius return (GEM_RING_SZ_8192); 87291398Stmm default: 873172334Smarius printf("%s: invalid ring size %d\n", __func__, sz); 874172334Smarius return (GEM_RING_SZ_32); 87591398Stmm } 87691398Stmm} 87791398Stmm 878148369Smariusstatic void 879174987Smariusgem_init(void *xsc) 880148369Smarius{ 881174987Smarius struct gem_softc *sc = xsc; 882148369Smarius 883148369Smarius GEM_LOCK(sc); 884148369Smarius gem_init_locked(sc); 885148369Smarius GEM_UNLOCK(sc); 886148369Smarius} 887148369Smarius 88891398Stmm/* 88991398Stmm * Initialization of interface; set up initialization block 89091398Stmm * and transmit/receive descriptor rings. 89191398Stmm */ 89291398Stmmstatic void 893174987Smariusgem_init_locked(struct gem_softc *sc) 89491398Stmm{ 895147256Sbrooks struct ifnet *ifp = sc->sc_ifp; 896174987Smarius uint32_t v; 89791398Stmm 898148369Smarius GEM_LOCK_ASSERT(sc, MA_OWNED); 89991398Stmm 900115030Stmm#ifdef GEM_DEBUG 901170273Syongari CTR2(KTR_GEM, "%s: %s: calling stop", device_get_name(sc->sc_dev), 902170273Syongari __func__); 903115030Stmm#endif 90491398Stmm /* 905174987Smarius * Initialization sequence. The numbered steps below correspond 90691398Stmm * to the sequence outlined in section 6.3.5.1 in the Ethernet 90791398Stmm * Channel Engine manual (part of the PCIO manual). 90891398Stmm * See also the STP2002-STQ document from Sun Microsystems. 90991398Stmm */ 91091398Stmm 911174987Smarius /* step 1 & 2. Reset the Ethernet Channel. */ 912179925Smarius gem_stop(ifp, 0); 91391398Stmm gem_reset(sc); 914115030Stmm#ifdef GEM_DEBUG 915170273Syongari CTR2(KTR_GEM, "%s: %s: restarting", device_get_name(sc->sc_dev), 916170273Syongari __func__); 917115030Stmm#endif 91891398Stmm 919174987Smarius /* Re-initialize the MIF. */ 92091398Stmm gem_mifinit(sc); 92191398Stmm 922174987Smarius /* step 3. Setup data structures in host memory. */ 923172334Smarius if (gem_meminit(sc) != 0) 924172334Smarius return; 92591398Stmm 926174987Smarius /* step 4. TX MAC registers & counters */ 92791398Stmm gem_init_regs(sc); 92891398Stmm 929174987Smarius /* step 5. RX MAC registers & counters */ 93091398Stmm gem_setladrf(sc); 93191398Stmm 932174987Smarius /* step 6 & 7. Program Descriptor Ring Base Addresses. */ 93391398Stmm /* NOTE: we use only 32-bit DMA addresses here. */ 934177560Smarius GEM_BANK1_WRITE_4(sc, GEM_TX_RING_PTR_HI, 0); 935177560Smarius GEM_BANK1_WRITE_4(sc, GEM_TX_RING_PTR_LO, GEM_CDTXADDR(sc, 0)); 93691398Stmm 937177560Smarius GEM_BANK1_WRITE_4(sc, GEM_RX_RING_PTR_HI, 0); 938177560Smarius GEM_BANK1_WRITE_4(sc, GEM_RX_RING_PTR_LO, GEM_CDRXADDR(sc, 0)); 939115030Stmm#ifdef GEM_DEBUG 940174987Smarius CTR3(KTR_GEM, "loading RX ring %lx, TX ring %lx, cddma %lx", 94191398Stmm GEM_CDRXADDR(sc, 0), GEM_CDTXADDR(sc, 0), sc->sc_cddma); 942115030Stmm#endif 94391398Stmm 944174987Smarius /* step 8. Global Configuration & Interrupt Mask */ 945194763Smarius 946194763Smarius /* 947194763Smarius * Set the internal arbitration to "infinite" bursts of the 948194763Smarius * maximum length of 31 * 64 bytes so DMA transfers aren't 949194763Smarius * split up in cache line size chunks. This greatly improves 950194763Smarius * RX performance. 951194763Smarius * Enable silicon bug workarounds for the Apple variants. 952194763Smarius */ 953194763Smarius GEM_BANK1_WRITE_4(sc, GEM_CONFIG, 954194763Smarius GEM_CONFIG_TXDMA_LIMIT | GEM_CONFIG_RXDMA_LIMIT | 955194763Smarius ((sc->sc_flags & GEM_PCI) != 0 ? GEM_CONFIG_BURST_INF : 956194763Smarius GEM_CONFIG_BURST_64) | (GEM_IS_APPLE(sc) ? 957194763Smarius GEM_CONFIG_RONPAULBIT | GEM_CONFIG_BUG2FIX : 0)); 958194763Smarius 959177560Smarius GEM_BANK1_WRITE_4(sc, GEM_INTMASK, 960172334Smarius ~(GEM_INTR_TX_INTME | GEM_INTR_TX_EMPTY | GEM_INTR_RX_DONE | 961172334Smarius GEM_INTR_RX_NOBUF | GEM_INTR_RX_TAG_ERR | GEM_INTR_PERR | 962172334Smarius GEM_INTR_BERR 963172334Smarius#ifdef GEM_DEBUG 964172334Smarius | GEM_INTR_PCS | GEM_INTR_MIF 965172334Smarius#endif 966172334Smarius )); 967177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_MASK, 968172334Smarius GEM_MAC_RX_DONE | GEM_MAC_RX_FRAME_CNT); 969177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_TX_MASK, 970194763Smarius GEM_MAC_TX_XMIT_DONE | GEM_MAC_TX_DEFER_EXP | 971194763Smarius GEM_MAC_TX_PEAK_EXP); 972172334Smarius#ifdef GEM_DEBUG 973177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_CONTROL_MASK, 974172334Smarius ~(GEM_MAC_PAUSED | GEM_MAC_PAUSE | GEM_MAC_RESUME)); 975172334Smarius#else 976177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_CONTROL_MASK, 977172334Smarius GEM_MAC_PAUSED | GEM_MAC_PAUSE | GEM_MAC_RESUME); 978172334Smarius#endif 97991398Stmm 980174987Smarius /* step 9. ETX Configuration: use mostly default values. */ 98191398Stmm 982174987Smarius /* Enable DMA. */ 983194763Smarius v = gem_ringsize(GEM_NTXDESC); 984194763Smarius /* Set TX FIFO threshold and enable DMA. */ 985179925Smarius v |= ((sc->sc_variant == GEM_SUN_ERI ? 0x100 : 0x4ff) << 10) & 986179925Smarius GEM_TX_CONFIG_TXFIFO_TH; 987179925Smarius GEM_BANK1_WRITE_4(sc, GEM_TX_CONFIG, v | GEM_TX_CONFIG_TXDMA_EN); 98891398Stmm 989174987Smarius /* step 10. ERX Configuration */ 99091398Stmm 991172334Smarius /* Encode Receive Descriptor ring size. */ 992174987Smarius v = gem_ringsize(GEM_NRXDESC /* XXX */); 993174987Smarius /* RX TCP/UDP checksum offset */ 994170273Syongari v |= ((ETHER_HDR_LEN + sizeof(struct ip)) << 995170273Syongari GEM_RX_CONFIG_CXM_START_SHFT); 996194763Smarius /* Set RX FIFO threshold, set first byte offset and enable DMA. */ 997177560Smarius GEM_BANK1_WRITE_4(sc, GEM_RX_CONFIG, 998174987Smarius v | (GEM_THRSH_1024 << GEM_RX_CONFIG_FIFO_THRS_SHIFT) | 999194763Smarius (ETHER_ALIGN << GEM_RX_CONFIG_FBOFF_SHFT) | 1000194763Smarius GEM_RX_CONFIG_RXDMA_EN); 1001172334Smarius 1002194763Smarius /* Adjust for the SBus clock probably isn't worth the fuzz. */ 1003177560Smarius GEM_BANK1_WRITE_4(sc, GEM_RX_BLANKING, 1004194763Smarius ((6 * (sc->sc_flags & GEM_PCI66) != 0 ? 2 : 1) << 1005194763Smarius GEM_RX_BLANKING_TIME_SHIFT) | 6); 1006172334Smarius 100791398Stmm /* 100899726Sbenno * The following value is for an OFF Threshold of about 3/4 full 100999726Sbenno * and an ON Threshold of 1/4 full. 101091398Stmm */ 1011177560Smarius GEM_BANK1_WRITE_4(sc, GEM_RX_PAUSE_THRESH, 101299726Sbenno (3 * sc->sc_rxfifosize / 256) | 1013174987Smarius ((sc->sc_rxfifosize / 256) << 12)); 101491398Stmm 1015174987Smarius /* step 11. Configure Media. */ 101691398Stmm 1017174987Smarius /* step 12. RX_MAC Configuration Register */ 1018177560Smarius v = GEM_BANK1_READ_4(sc, GEM_MAC_RX_CONFIG); 1019179925Smarius v |= GEM_MAC_RX_ENABLE | GEM_MAC_RX_STRIP_CRC; 1020177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_CONFIG, 0); 1021179925Smarius GEM_BANK1_BARRIER(sc, GEM_MAC_RX_CONFIG, 4, 1022179925Smarius BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 1023177560Smarius if (!GEM_BANK1_BITWAIT(sc, GEM_MAC_RX_CONFIG, GEM_MAC_RX_ENABLE, 0)) 1024179925Smarius device_printf(sc->sc_dev, "cannot configure RX MAC\n"); 1025177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_CONFIG, v); 102691398Stmm 1027194763Smarius /* step 13. TX_MAC Configuration Register */ 1028179925Smarius v = GEM_BANK1_READ_4(sc, GEM_MAC_TX_CONFIG); 1029179925Smarius v |= GEM_MAC_TX_ENABLE; 1030179925Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_TX_CONFIG, 0); 1031179925Smarius GEM_BANK1_BARRIER(sc, GEM_MAC_TX_CONFIG, 4, 1032179925Smarius BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 1033179925Smarius if (!GEM_BANK1_BITWAIT(sc, GEM_MAC_TX_CONFIG, GEM_MAC_TX_ENABLE, 0)) 1034179925Smarius device_printf(sc->sc_dev, "cannot configure TX MAC\n"); 1035179925Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_TX_CONFIG, v); 1036179925Smarius 1037174987Smarius /* step 14. Issue Transmit Pending command. */ 103891398Stmm 1039174987Smarius /* step 15. Give the reciever a swift kick. */ 1040177560Smarius GEM_BANK1_WRITE_4(sc, GEM_RX_KICK, GEM_NRXDESC - 4); 104191398Stmm 1042172334Smarius ifp->if_drv_flags |= IFF_DRV_RUNNING; 1043172334Smarius ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 1044172334Smarius 1045172334Smarius mii_mediachg(sc->sc_mii); 1046172334Smarius 104791398Stmm /* Start the one second timer. */ 1048164931Smarius sc->sc_wdog_timer = 0; 104991398Stmm callout_reset(&sc->sc_tick_ch, hz, gem_tick, sc); 105091398Stmm} 105191398Stmm 105291398Stmmstatic int 1053174987Smariusgem_load_txmbuf(struct gem_softc *sc, struct mbuf **m_head) 105491398Stmm{ 1055174987Smarius bus_dma_segment_t txsegs[GEM_NTXSEGS]; 105691398Stmm struct gem_txsoft *txs; 1057179925Smarius struct ip *ip; 1058170273Syongari struct mbuf *m; 1059174987Smarius uint64_t cflags, flags; 1060179925Smarius int error, nexttx, nsegs, offset, seg; 106191398Stmm 1062194763Smarius GEM_LOCK_ASSERT(sc, MA_OWNED); 1063194763Smarius 1064108832Stmm /* Get a work queue entry. */ 1065108832Stmm if ((txs = STAILQ_FIRST(&sc->sc_txfreeq)) == NULL) { 1066108832Stmm /* Ran out of descriptors. */ 1067170273Syongari return (ENOBUFS); 1068108832Stmm } 1069179925Smarius 1070179925Smarius cflags = 0; 1071179925Smarius if (((*m_head)->m_pkthdr.csum_flags & sc->sc_csum_features) != 0) { 1072179925Smarius if (M_WRITABLE(*m_head) == 0) { 1073179925Smarius m = m_dup(*m_head, M_DONTWAIT); 1074179925Smarius m_freem(*m_head); 1075179925Smarius *m_head = m; 1076179925Smarius if (m == NULL) 1077179925Smarius return (ENOBUFS); 1078179925Smarius } 1079179925Smarius offset = sizeof(struct ether_header); 1080179925Smarius m = m_pullup(*m_head, offset + sizeof(struct ip)); 1081179925Smarius if (m == NULL) { 1082179925Smarius *m_head = NULL; 1083179925Smarius return (ENOBUFS); 1084179925Smarius } 1085179925Smarius ip = (struct ip *)(mtod(m, caddr_t) + offset); 1086179925Smarius offset += (ip->ip_hl << 2); 1087179925Smarius cflags = offset << GEM_TD_CXSUM_STARTSHFT | 1088179925Smarius ((offset + m->m_pkthdr.csum_data) << 1089179925Smarius GEM_TD_CXSUM_STUFFSHFT) | GEM_TD_CXSUM_ENABLE; 1090179925Smarius *m_head = m; 1091179925Smarius } 1092179925Smarius 1093170273Syongari error = bus_dmamap_load_mbuf_sg(sc->sc_tdmatag, txs->txs_dmamap, 1094170273Syongari *m_head, txsegs, &nsegs, BUS_DMA_NOWAIT); 1095170273Syongari if (error == EFBIG) { 1096175418Sjhb m = m_collapse(*m_head, M_DONTWAIT, GEM_NTXSEGS); 1097170273Syongari if (m == NULL) { 1098170273Syongari m_freem(*m_head); 1099170273Syongari *m_head = NULL; 1100170273Syongari return (ENOBUFS); 1101170273Syongari } 1102170273Syongari *m_head = m; 1103174987Smarius error = bus_dmamap_load_mbuf_sg(sc->sc_tdmatag, 1104174987Smarius txs->txs_dmamap, *m_head, txsegs, &nsegs, 1105174987Smarius BUS_DMA_NOWAIT); 1106170273Syongari if (error != 0) { 1107170273Syongari m_freem(*m_head); 1108170273Syongari *m_head = NULL; 1109170273Syongari return (error); 1110170273Syongari } 1111170273Syongari } else if (error != 0) 1112170273Syongari return (error); 1113176996Smarius /* If nsegs is wrong then the stack is corrupt. */ 1114176996Smarius KASSERT(nsegs <= GEM_NTXSEGS, 1115176996Smarius ("%s: too many DMA segments (%d)", __func__, nsegs)); 1116170273Syongari if (nsegs == 0) { 1117170273Syongari m_freem(*m_head); 1118170273Syongari *m_head = NULL; 1119170273Syongari return (EIO); 1120170273Syongari } 1121170273Syongari 1122170273Syongari /* 1123170273Syongari * Ensure we have enough descriptors free to describe 1124170273Syongari * the packet. Note, we always reserve one descriptor 1125174987Smarius * at the end of the ring as a termination point, in 1126174987Smarius * order to prevent wrap-around. 1127170273Syongari */ 1128170273Syongari if (nsegs > sc->sc_txfree - 1) { 1129170273Syongari txs->txs_ndescs = 0; 1130170273Syongari bus_dmamap_unload(sc->sc_tdmatag, txs->txs_dmamap); 1131170273Syongari return (ENOBUFS); 1132170273Syongari } 1133170273Syongari 1134170273Syongari txs->txs_ndescs = nsegs; 1135108832Stmm txs->txs_firstdesc = sc->sc_txnext; 1136170273Syongari nexttx = txs->txs_firstdesc; 1137170273Syongari for (seg = 0; seg < nsegs; seg++, nexttx = GEM_NEXTTX(nexttx)) { 1138172334Smarius#ifdef GEM_DEBUG 1139174987Smarius CTR6(KTR_GEM, 1140174987Smarius "%s: mapping seg %d (txd %d), len %lx, addr %#lx (%#lx)", 1141174987Smarius __func__, seg, nexttx, txsegs[seg].ds_len, 1142174987Smarius txsegs[seg].ds_addr, 1143170273Syongari GEM_DMA_WRITE(sc, txsegs[seg].ds_addr)); 1144170273Syongari#endif 1145170273Syongari sc->sc_txdescs[nexttx].gd_addr = 1146170273Syongari GEM_DMA_WRITE(sc, txsegs[seg].ds_addr); 1147170273Syongari KASSERT(txsegs[seg].ds_len < GEM_TD_BUFSIZE, 1148170273Syongari ("%s: segment size too large!", __func__)); 1149170273Syongari flags = txsegs[seg].ds_len & GEM_TD_BUFSIZE; 1150170273Syongari sc->sc_txdescs[nexttx].gd_flags = 1151170273Syongari GEM_DMA_WRITE(sc, flags | cflags); 1152170273Syongari txs->txs_lastdesc = nexttx; 115391398Stmm } 115491398Stmm 1155174987Smarius /* Set EOP on the last descriptor. */ 1156172334Smarius#ifdef GEM_DEBUG 1157174987Smarius CTR3(KTR_GEM, "%s: end of packet at segment %d, TX %d", 1158174987Smarius __func__, seg, nexttx); 1159170273Syongari#endif 1160170273Syongari sc->sc_txdescs[txs->txs_lastdesc].gd_flags |= 1161170273Syongari GEM_DMA_WRITE(sc, GEM_TD_END_OF_PACKET); 1162170273Syongari 1163174987Smarius /* Lastly set SOP on the first descriptor. */ 1164172334Smarius#ifdef GEM_DEBUG 1165174987Smarius CTR3(KTR_GEM, "%s: start of packet at segment %d, TX %d", 1166174987Smarius __func__, seg, nexttx); 1167170273Syongari#endif 1168170273Syongari if (++sc->sc_txwin > GEM_NTXSEGS * 2 / 3) { 1169170273Syongari sc->sc_txwin = 0; 1170170273Syongari sc->sc_txdescs[txs->txs_firstdesc].gd_flags |= 1171170273Syongari GEM_DMA_WRITE(sc, GEM_TD_INTERRUPT_ME | 1172170273Syongari GEM_TD_START_OF_PACKET); 1173170273Syongari } else 1174170273Syongari sc->sc_txdescs[txs->txs_firstdesc].gd_flags |= 1175170273Syongari GEM_DMA_WRITE(sc, GEM_TD_START_OF_PACKET); 1176170273Syongari 1177108832Stmm /* Sync the DMA map. */ 1178174987Smarius bus_dmamap_sync(sc->sc_tdmatag, txs->txs_dmamap, 1179174987Smarius BUS_DMASYNC_PREWRITE); 118091398Stmm 1181115030Stmm#ifdef GEM_DEBUG 1182170273Syongari CTR4(KTR_GEM, "%s: setting firstdesc=%d, lastdesc=%d, ndescs=%d", 1183174987Smarius __func__, txs->txs_firstdesc, txs->txs_lastdesc, 1184174987Smarius txs->txs_ndescs); 1185115030Stmm#endif 1186108832Stmm STAILQ_REMOVE_HEAD(&sc->sc_txfreeq, txs_q); 1187108832Stmm STAILQ_INSERT_TAIL(&sc->sc_txdirtyq, txs, txs_q); 1188170273Syongari txs->txs_mbuf = *m_head; 118991398Stmm 1190108832Stmm sc->sc_txnext = GEM_NEXTTX(txs->txs_lastdesc); 1191108832Stmm sc->sc_txfree -= txs->txs_ndescs; 1192170273Syongari 1193108832Stmm return (0); 119491398Stmm} 119591398Stmm 119691398Stmmstatic void 1197174987Smariusgem_init_regs(struct gem_softc *sc) 119891398Stmm{ 1199152315Sru const u_char *laddr = IF_LLADDR(sc->sc_ifp); 120091398Stmm 1201194763Smarius GEM_LOCK_ASSERT(sc, MA_OWNED); 1202194763Smarius 1203174987Smarius /* These registers are not cleared on reset. */ 1204172334Smarius if ((sc->sc_flags & GEM_INITED) == 0) { 1205174987Smarius /* magic values */ 1206177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_IPG0, 0); 1207177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_IPG1, 8); 1208177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_IPG2, 4); 120991398Stmm 1210194763Smarius /* min frame length */ 1211177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_MAC_MIN_FRAME, ETHER_MIN_LEN); 1212194763Smarius /* max frame length and max burst size */ 1213177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_MAC_MAX_FRAME, 1214172334Smarius (ETHER_MAX_LEN + ETHER_VLAN_ENCAP_LEN) | (0x2000 << 16)); 121599726Sbenno 1216194763Smarius /* more magic values */ 1217177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_PREAMBLE_LEN, 0x7); 1218177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_JAM_SIZE, 0x4); 1219177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_ATTEMPT_LIMIT, 0x10); 1220177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_CONTROL_TYPE, 0x8088); 1221194763Smarius 1222194763Smarius /* random number seed */ 1223177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_RANDOM_SEED, 1224174987Smarius ((laddr[5] << 8) | laddr[4]) & 0x3ff); 122599726Sbenno 1226174987Smarius /* secondary MAC address: 0:0:0:0:0:0 */ 1227177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_ADDR3, 0); 1228177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_ADDR4, 0); 1229177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_ADDR5, 0); 123099726Sbenno 1231174987Smarius /* MAC control address: 01:80:c2:00:00:01 */ 1232177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_ADDR6, 0x0001); 1233177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_ADDR7, 0xc200); 1234177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_ADDR8, 0x0180); 123591398Stmm 1236174987Smarius /* MAC filter address: 0:0:0:0:0:0 */ 1237177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_ADDR_FILTER0, 0); 1238177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_ADDR_FILTER1, 0); 1239177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_ADDR_FILTER2, 0); 1240177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_ADR_FLT_MASK1_2, 0); 1241177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_ADR_FLT_MASK0, 0); 124291398Stmm 1243172334Smarius sc->sc_flags |= GEM_INITED; 124491398Stmm } 124591398Stmm 1246174987Smarius /* Counters need to be zeroed. */ 1247177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_NORM_COLL_CNT, 0); 1248177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_FIRST_COLL_CNT, 0); 1249177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_EXCESS_COLL_CNT, 0); 1250177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_LATE_COLL_CNT, 0); 1251177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_DEFER_TMR_CNT, 0); 1252177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_PEAK_ATTEMPTS, 0); 1253177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_FRAME_COUNT, 0); 1254177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_LEN_ERR_CNT, 0); 1255177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_ALIGN_ERR, 0); 1256177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_CRC_ERR_CNT, 0); 1257177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_CODE_VIOL, 0); 125891398Stmm 1259172334Smarius /* Set XOFF PAUSE time. */ 1260177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_SEND_PAUSE_CMD, 0x1BF0); 126191398Stmm 1262174987Smarius /* Set the station address. */ 1263177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_ADDR0, (laddr[4] << 8) | laddr[5]); 1264177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_ADDR1, (laddr[2] << 8) | laddr[3]); 1265177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_ADDR2, (laddr[0] << 8) | laddr[1]); 126699726Sbenno 1267172334Smarius /* Enable MII outputs. */ 1268177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_XIF_CONFIG, GEM_MAC_XIF_TX_MII_ENA); 126991398Stmm} 127091398Stmm 127191398Stmmstatic void 1272174987Smariusgem_start(struct ifnet *ifp) 127391398Stmm{ 1274174987Smarius struct gem_softc *sc = ifp->if_softc; 1275148369Smarius 1276148369Smarius GEM_LOCK(sc); 1277148369Smarius gem_start_locked(ifp); 1278148369Smarius GEM_UNLOCK(sc); 1279148369Smarius} 1280148369Smarius 1281194763Smariusstatic inline void 1282194763Smariusgem_txkick(struct gem_softc *sc) 1283194763Smarius{ 1284194763Smarius 1285194763Smarius /* 1286194763Smarius * Update the TX kick register. This register has to point to the 1287194763Smarius * descriptor after the last valid one and for optimum performance 1288194763Smarius * should be incremented in multiples of 4 (the DMA engine fetches/ 1289194763Smarius * updates descriptors in batches of 4). 1290194763Smarius */ 1291194763Smarius#ifdef GEM_DEBUG 1292194763Smarius CTR3(KTR_GEM, "%s: %s: kicking TX %d", 1293194763Smarius device_get_name(sc->sc_dev), __func__, sc->sc_txnext); 1294194763Smarius#endif 1295194763Smarius GEM_CDSYNC(sc, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 1296194763Smarius GEM_BANK1_WRITE_4(sc, GEM_TX_KICK, sc->sc_txnext); 1297194763Smarius} 1298194763Smarius 1299148369Smariusstatic void 1300174987Smariusgem_start_locked(struct ifnet *ifp) 1301148369Smarius{ 1302174987Smarius struct gem_softc *sc = ifp->if_softc; 1303170273Syongari struct mbuf *m; 1304194763Smarius int kicked, ntx; 130591398Stmm 1306194763Smarius GEM_LOCK_ASSERT(sc, MA_OWNED); 1307194763Smarius 1308148887Srwatson if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) != 1309172334Smarius IFF_DRV_RUNNING || (sc->sc_flags & GEM_LINK) == 0) 131091398Stmm return; 131191398Stmm 1312115030Stmm#ifdef GEM_DEBUG 1313170273Syongari CTR4(KTR_GEM, "%s: %s: txfree %d, txnext %d", 1314172334Smarius device_get_name(sc->sc_dev), __func__, sc->sc_txfree, 1315172334Smarius sc->sc_txnext); 1316115030Stmm#endif 1317174987Smarius ntx = 0; 1318194763Smarius kicked = 0; 1319170273Syongari for (; !IFQ_DRV_IS_EMPTY(&ifp->if_snd) && sc->sc_txfree > 1;) { 1320170273Syongari IFQ_DRV_DEQUEUE(&ifp->if_snd, m); 1321170273Syongari if (m == NULL) 132291398Stmm break; 1323172334Smarius if (gem_load_txmbuf(sc, &m) != 0) { 1324170273Syongari if (m == NULL) 1325170273Syongari break; 1326170273Syongari ifp->if_drv_flags |= IFF_DRV_OACTIVE; 1327170273Syongari IFQ_DRV_PREPEND(&ifp->if_snd, m); 132891398Stmm break; 132991398Stmm } 1330194763Smarius if ((sc->sc_txnext % 4) == 0) { 1331194763Smarius gem_txkick(sc); 1332194763Smarius kicked = 1; 1333194763Smarius } else 1334194763Smarius kicked = 0; 1335115030Stmm ntx++; 1336170273Syongari BPF_MTAP(ifp, m); 133791398Stmm } 133891398Stmm 133991398Stmm if (ntx > 0) { 1340194763Smarius if (kicked == 0) 1341194763Smarius gem_txkick(sc); 1342115030Stmm#ifdef GEM_DEBUG 1343108832Stmm CTR2(KTR_GEM, "%s: packets enqueued, OWN on %d", 1344172334Smarius device_get_name(sc->sc_dev), sc->sc_txnext); 1345115030Stmm#endif 134691398Stmm 134791398Stmm /* Set a watchdog timer in case the chip flakes out. */ 1348164931Smarius sc->sc_wdog_timer = 5; 1349115030Stmm#ifdef GEM_DEBUG 1350170273Syongari CTR3(KTR_GEM, "%s: %s: watchdog %d", 1351174987Smarius device_get_name(sc->sc_dev), __func__, 1352174987Smarius sc->sc_wdog_timer); 1353115030Stmm#endif 135491398Stmm } 135591398Stmm} 135691398Stmm 135791398Stmmstatic void 1358174987Smariusgem_tint(struct gem_softc *sc) 135991398Stmm{ 1360147256Sbrooks struct ifnet *ifp = sc->sc_ifp; 136191398Stmm struct gem_txsoft *txs; 1362194763Smarius int progress; 1363194763Smarius uint32_t txlast; 1364174987Smarius#ifdef GEM_DEBUG 1365174987Smarius int i; 136691398Stmm 1367194763Smarius GEM_LOCK_ASSERT(sc, MA_OWNED); 1368194763Smarius 1369170273Syongari CTR2(KTR_GEM, "%s: %s", device_get_name(sc->sc_dev), __func__); 1370115030Stmm#endif 137191398Stmm 137291398Stmm /* 1373174987Smarius * Go through our TX list and free mbufs for those 137491398Stmm * frames that have been transmitted. 137591398Stmm */ 1376174987Smarius progress = 0; 1377109648Stmm GEM_CDSYNC(sc, BUS_DMASYNC_POSTREAD); 137891398Stmm while ((txs = STAILQ_FIRST(&sc->sc_txdirtyq)) != NULL) { 137991398Stmm#ifdef GEM_DEBUG 1380174987Smarius if ((ifp->if_flags & IFF_DEBUG) != 0) { 138191398Stmm printf(" txsoft %p transmit chain:\n", txs); 138291398Stmm for (i = txs->txs_firstdesc;; i = GEM_NEXTTX(i)) { 138391398Stmm printf("descriptor %d: ", i); 1384174987Smarius printf("gd_flags: 0x%016llx\t", 1385174987Smarius (long long)GEM_DMA_READ(sc, 1386174987Smarius sc->sc_txdescs[i].gd_flags)); 1387174987Smarius printf("gd_addr: 0x%016llx\n", 1388174987Smarius (long long)GEM_DMA_READ(sc, 1389174987Smarius sc->sc_txdescs[i].gd_addr)); 139091398Stmm if (i == txs->txs_lastdesc) 139191398Stmm break; 139291398Stmm } 139391398Stmm } 139491398Stmm#endif 139591398Stmm 139691398Stmm /* 1397172334Smarius * In theory, we could harvest some descriptors before 139891398Stmm * the ring is empty, but that's a bit complicated. 139991398Stmm * 140091398Stmm * GEM_TX_COMPLETION points to the last descriptor 1401174987Smarius * processed + 1. 140291398Stmm */ 1403177560Smarius txlast = GEM_BANK1_READ_4(sc, GEM_TX_COMPLETION); 1404115030Stmm#ifdef GEM_DEBUG 1405170273Syongari CTR4(KTR_GEM, "%s: txs->txs_firstdesc = %d, " 140691398Stmm "txs->txs_lastdesc = %d, txlast = %d", 1407170273Syongari __func__, txs->txs_firstdesc, txs->txs_lastdesc, txlast); 1408115030Stmm#endif 140991398Stmm if (txs->txs_firstdesc <= txs->txs_lastdesc) { 141091398Stmm if ((txlast >= txs->txs_firstdesc) && 1411174987Smarius (txlast <= txs->txs_lastdesc)) 141291398Stmm break; 141391398Stmm } else { 1414174987Smarius /* Ick -- this command wraps. */ 141591398Stmm if ((txlast >= txs->txs_firstdesc) || 1416174987Smarius (txlast <= txs->txs_lastdesc)) 141791398Stmm break; 141891398Stmm } 141991398Stmm 1420115030Stmm#ifdef GEM_DEBUG 1421174987Smarius CTR1(KTR_GEM, "%s: releasing a descriptor", __func__); 1422115030Stmm#endif 142391398Stmm STAILQ_REMOVE_HEAD(&sc->sc_txdirtyq, txs_q); 142491398Stmm 142591398Stmm sc->sc_txfree += txs->txs_ndescs; 142691398Stmm 1427108832Stmm bus_dmamap_sync(sc->sc_tdmatag, txs->txs_dmamap, 142891398Stmm BUS_DMASYNC_POSTWRITE); 1429108832Stmm bus_dmamap_unload(sc->sc_tdmatag, txs->txs_dmamap); 143091398Stmm if (txs->txs_mbuf != NULL) { 143191398Stmm m_freem(txs->txs_mbuf); 143291398Stmm txs->txs_mbuf = NULL; 143391398Stmm } 143491398Stmm 143591398Stmm STAILQ_INSERT_TAIL(&sc->sc_txfreeq, txs, txs_q); 143691398Stmm 143791398Stmm ifp->if_opackets++; 143899726Sbenno progress = 1; 143991398Stmm } 144091398Stmm 1441115030Stmm#ifdef GEM_DEBUG 1442174987Smarius CTR4(KTR_GEM, "%s: GEM_TX_STATE_MACHINE %x GEM_TX_DATA_PTR %llx " 1443172334Smarius "GEM_TX_COMPLETION %x", 1444177560Smarius __func__, GEM_BANK1_READ_4(sc, GEM_TX_STATE_MACHINE), 1445177560Smarius ((long long)GEM_BANK1_READ_4(sc, GEM_TX_DATA_PTR_HI) << 32) | 1446177560Smarius GEM_BANK1_READ_4(sc, GEM_TX_DATA_PTR_LO), 1447177560Smarius GEM_BANK1_READ_4(sc, GEM_TX_COMPLETION)); 1448115030Stmm#endif 144991398Stmm 145099726Sbenno if (progress) { 145199726Sbenno if (sc->sc_txfree == GEM_NTXDESC - 1) 145299726Sbenno sc->sc_txwin = 0; 145391398Stmm 1454174987Smarius /* 1455174987Smarius * We freed some descriptors, so reset IFF_DRV_OACTIVE 1456174987Smarius * and restart. 1457174987Smarius */ 1458148887Srwatson ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 1459194763Smarius if (STAILQ_EMPTY(&sc->sc_txdirtyq)) 1460194763Smarius sc->sc_wdog_timer = 0; 1461179925Smarius gem_start_locked(ifp); 146299726Sbenno } 146399726Sbenno 1464115030Stmm#ifdef GEM_DEBUG 1465170273Syongari CTR3(KTR_GEM, "%s: %s: watchdog %d", 1466170273Syongari device_get_name(sc->sc_dev), __func__, sc->sc_wdog_timer); 1467115030Stmm#endif 146891398Stmm} 146991398Stmm 1470148368Smarius#ifdef GEM_RINT_TIMEOUT 147193045Stmmstatic void 1472174987Smariusgem_rint_timeout(void *arg) 147393045Stmm{ 1474174987Smarius struct gem_softc *sc = arg; 147593045Stmm 1476150285Smarius GEM_LOCK_ASSERT(sc, MA_OWNED); 1477194763Smarius 1478148369Smarius gem_rint(sc); 147993045Stmm} 1480100587Sjake#endif 148193045Stmm 148291398Stmmstatic void 1483174987Smariusgem_rint(struct gem_softc *sc) 148491398Stmm{ 1485147256Sbrooks struct ifnet *ifp = sc->sc_ifp; 148691398Stmm struct mbuf *m; 1487174987Smarius uint64_t rxstat; 1488174987Smarius uint32_t rxcomp; 148991398Stmm 1490194763Smarius GEM_LOCK_ASSERT(sc, MA_OWNED); 1491194763Smarius 1492148368Smarius#ifdef GEM_RINT_TIMEOUT 149393045Stmm callout_stop(&sc->sc_rx_ch); 1494148368Smarius#endif 1495115030Stmm#ifdef GEM_DEBUG 1496170273Syongari CTR2(KTR_GEM, "%s: %s", device_get_name(sc->sc_dev), __func__); 1497115030Stmm#endif 149899726Sbenno 149991398Stmm /* 150099726Sbenno * Read the completion register once. This limits 150199726Sbenno * how long the following loop can execute. 150299726Sbenno */ 1503177560Smarius rxcomp = GEM_BANK1_READ_4(sc, GEM_RX_COMPLETION); 1504115030Stmm#ifdef GEM_DEBUG 1505194763Smarius CTR3(KTR_GEM, "%s: sc->sc_rxptr %d, complete %d", 1506170273Syongari __func__, sc->sc_rxptr, rxcomp); 1507115030Stmm#endif 1508194763Smarius GEM_CDSYNC(sc, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 1509172334Smarius for (; sc->sc_rxptr != rxcomp;) { 1510172334Smarius m = sc->sc_rxsoft[sc->sc_rxptr].rxs_mbuf; 1511172334Smarius rxstat = GEM_DMA_READ(sc, 1512172334Smarius sc->sc_rxdescs[sc->sc_rxptr].gd_flags); 151391398Stmm 151491398Stmm if (rxstat & GEM_RD_OWN) { 1515148368Smarius#ifdef GEM_RINT_TIMEOUT 151691398Stmm /* 151793045Stmm * The descriptor is still marked as owned, although 1518174987Smarius * it is supposed to have completed. This has been 1519174987Smarius * observed on some machines. Just exiting here 152093045Stmm * might leave the packet sitting around until another 152193045Stmm * one arrives to trigger a new interrupt, which is 152293045Stmm * generally undesirable, so set up a timeout. 152391398Stmm */ 152493045Stmm callout_reset(&sc->sc_rx_ch, GEM_RXOWN_TICKS, 152593045Stmm gem_rint_timeout, sc); 152699726Sbenno#endif 1527172334Smarius m = NULL; 1528172334Smarius goto kickit; 152991398Stmm } 153091398Stmm 153191398Stmm if (rxstat & GEM_RD_BAD_CRC) { 153299726Sbenno ifp->if_ierrors++; 153391398Stmm device_printf(sc->sc_dev, "receive error: CRC error\n"); 1534172334Smarius GEM_INIT_RXDESC(sc, sc->sc_rxptr); 1535172334Smarius m = NULL; 1536172334Smarius goto kickit; 153791398Stmm } 153891398Stmm 153991398Stmm#ifdef GEM_DEBUG 1540174987Smarius if ((ifp->if_flags & IFF_DEBUG) != 0) { 1541172334Smarius printf(" rxsoft %p descriptor %d: ", 1542172334Smarius &sc->sc_rxsoft[sc->sc_rxptr], sc->sc_rxptr); 1543174987Smarius printf("gd_flags: 0x%016llx\t", 1544174987Smarius (long long)GEM_DMA_READ(sc, 1545174987Smarius sc->sc_rxdescs[sc->sc_rxptr].gd_flags)); 1546174987Smarius printf("gd_addr: 0x%016llx\n", 1547174987Smarius (long long)GEM_DMA_READ(sc, 1548174987Smarius sc->sc_rxdescs[sc->sc_rxptr].gd_addr)); 154991398Stmm } 155091398Stmm#endif 155191398Stmm 155291398Stmm /* 155391398Stmm * Allocate a new mbuf cluster. If that fails, we are 155491398Stmm * out of memory, and must drop the packet and recycle 155591398Stmm * the buffer that's already attached to this descriptor. 155691398Stmm */ 1557172334Smarius if (gem_add_rxbuf(sc, sc->sc_rxptr) != 0) { 155891398Stmm ifp->if_ierrors++; 1559172334Smarius GEM_INIT_RXDESC(sc, sc->sc_rxptr); 1560172334Smarius m = NULL; 1561172334Smarius } 1562172334Smarius 1563174987Smarius kickit: 1564174987Smarius /* 1565174987Smarius * Update the RX kick register. This register has to point 1566172334Smarius * to the descriptor after the last valid one (before the 1567194763Smarius * current batch) and for optimum performance should be 1568194763Smarius * incremented in multiples of 4 (the DMA engine fetches/ 1569194763Smarius * updates descriptors in batches of 4). 1570172334Smarius */ 1571172334Smarius sc->sc_rxptr = GEM_NEXTRX(sc->sc_rxptr); 1572172334Smarius if ((sc->sc_rxptr % 4) == 0) { 1573179925Smarius GEM_CDSYNC(sc, 1574179925Smarius BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 1575177560Smarius GEM_BANK1_WRITE_4(sc, GEM_RX_KICK, 1576172334Smarius (sc->sc_rxptr + GEM_NRXDESC - 4) & 1577172334Smarius GEM_NRXDESC_MASK); 1578172334Smarius } 1579172334Smarius 1580172334Smarius if (m == NULL) { 1581172334Smarius if (rxstat & GEM_RD_OWN) 1582172334Smarius break; 158391398Stmm continue; 158491398Stmm } 1585172334Smarius 1586172334Smarius ifp->if_ipackets++; 1587194763Smarius m->m_data += ETHER_ALIGN; /* first byte offset */ 158891398Stmm m->m_pkthdr.rcvif = ifp; 1589172334Smarius m->m_pkthdr.len = m->m_len = GEM_RD_BUFLEN(rxstat); 159091398Stmm 1591170273Syongari if ((ifp->if_capenable & IFCAP_RXCSUM) != 0) 1592170273Syongari gem_rxcksum(m, rxstat); 1593170273Syongari 159491398Stmm /* Pass it on. */ 1595148369Smarius GEM_UNLOCK(sc); 1596106937Ssam (*ifp->if_input)(ifp, m); 1597148369Smarius GEM_LOCK(sc); 159891398Stmm } 159991398Stmm 1600115030Stmm#ifdef GEM_DEBUG 1601194763Smarius CTR3(KTR_GEM, "%s: done sc->sc_rxptr %d, complete %d", __func__, 1602177560Smarius sc->sc_rxptr, GEM_BANK1_READ_4(sc, GEM_RX_COMPLETION)); 1603115030Stmm#endif 160491398Stmm} 160591398Stmm 160691398Stmmstatic int 1607174987Smariusgem_add_rxbuf(struct gem_softc *sc, int idx) 160891398Stmm{ 160991398Stmm struct gem_rxsoft *rxs = &sc->sc_rxsoft[idx]; 161091398Stmm struct mbuf *m; 1611148368Smarius bus_dma_segment_t segs[1]; 1612148368Smarius int error, nsegs; 161391398Stmm 1614194763Smarius GEM_LOCK_ASSERT(sc, MA_OWNED); 1615194763Smarius 1616111119Simp m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); 161791398Stmm if (m == NULL) 161891398Stmm return (ENOBUFS); 1619108832Stmm m->m_len = m->m_pkthdr.len = m->m_ext.ext_size; 162091398Stmm 162191398Stmm#ifdef GEM_DEBUG 1622174987Smarius /* Bzero the packet to check DMA. */ 162391398Stmm memset(m->m_ext.ext_buf, 0, m->m_ext.ext_size); 162491398Stmm#endif 162591398Stmm 1626109648Stmm if (rxs->rxs_mbuf != NULL) { 1627109648Stmm bus_dmamap_sync(sc->sc_rdmatag, rxs->rxs_dmamap, 1628109648Stmm BUS_DMASYNC_POSTREAD); 1629108832Stmm bus_dmamap_unload(sc->sc_rdmatag, rxs->rxs_dmamap); 1630109648Stmm } 163191398Stmm 1632148368Smarius error = bus_dmamap_load_mbuf_sg(sc->sc_rdmatag, rxs->rxs_dmamap, 1633148368Smarius m, segs, &nsegs, BUS_DMA_NOWAIT); 1634148368Smarius if (error != 0) { 1635174987Smarius device_printf(sc->sc_dev, 1636174987Smarius "cannot load RS DMA map %d, error = %d\n", idx, error); 1637148368Smarius m_freem(m); 1638172334Smarius return (error); 163991398Stmm } 1640174987Smarius /* If nsegs is wrong then the stack is corrupt. */ 1641176996Smarius KASSERT(nsegs == 1, 1642176996Smarius ("%s: too many DMA segments (%d)", __func__, nsegs)); 1643172334Smarius rxs->rxs_mbuf = m; 1644148368Smarius rxs->rxs_paddr = segs[0].ds_addr; 164591398Stmm 1646174987Smarius bus_dmamap_sync(sc->sc_rdmatag, rxs->rxs_dmamap, 1647174987Smarius BUS_DMASYNC_PREREAD); 164891398Stmm 164991398Stmm GEM_INIT_RXDESC(sc, idx); 165091398Stmm 165191398Stmm return (0); 165291398Stmm} 165391398Stmm 165491398Stmmstatic void 1655174987Smariusgem_eint(struct gem_softc *sc, u_int status) 165691398Stmm{ 165791398Stmm 1658172334Smarius sc->sc_ifp->if_ierrors++; 1659172334Smarius if ((status & GEM_INTR_RX_TAG_ERR) != 0) { 1660172334Smarius gem_reset_rxdma(sc); 166191398Stmm return; 166291398Stmm } 166391398Stmm 1664194763Smarius device_printf(sc->sc_dev, "%s: status 0x%x", __func__, status); 1665194763Smarius if ((status & GEM_INTR_BERR) != 0) { 1666194763Smarius if ((sc->sc_flags & GEM_PCI) != 0) 1667194763Smarius printf(", PCI bus error 0x%x\n", 1668194763Smarius GEM_BANK1_READ_4(sc, GEM_PCI_ERROR_STATUS)); 1669194763Smarius else 1670194763Smarius printf(", SBus error 0x%x\n", 1671194763Smarius GEM_BANK1_READ_4(sc, GEM_SBUS_STATUS)); 1672194763Smarius } 167391398Stmm} 167491398Stmm 167591398Stmmvoid 1676174987Smariusgem_intr(void *v) 167791398Stmm{ 1678174987Smarius struct gem_softc *sc = v; 1679172334Smarius uint32_t status, status2; 168091398Stmm 1681148369Smarius GEM_LOCK(sc); 1682177560Smarius status = GEM_BANK1_READ_4(sc, GEM_STATUS); 1683172334Smarius 1684115030Stmm#ifdef GEM_DEBUG 1685170273Syongari CTR4(KTR_GEM, "%s: %s: cplt %x, status %x", 1686194763Smarius device_get_name(sc->sc_dev), __func__, 1687194763Smarius (status >> GEM_STATUS_TX_COMPLETION_SHFT), (u_int)status); 1688172334Smarius 1689172334Smarius /* 1690172334Smarius * PCS interrupts must be cleared, otherwise no traffic is passed! 1691172334Smarius */ 1692172334Smarius if ((status & GEM_INTR_PCS) != 0) { 1693174987Smarius status2 = 1694177560Smarius GEM_BANK1_READ_4(sc, GEM_MII_INTERRUP_STATUS) | 1695177560Smarius GEM_BANK1_READ_4(sc, GEM_MII_INTERRUP_STATUS); 1696172334Smarius if ((status2 & GEM_MII_INTERRUP_LINK) != 0) 1697172334Smarius device_printf(sc->sc_dev, 1698172334Smarius "%s: PCS link status changed\n", __func__); 1699172334Smarius } 1700172334Smarius if ((status & GEM_MAC_CONTROL_STATUS) != 0) { 1701177560Smarius status2 = GEM_BANK1_READ_4(sc, GEM_MAC_CONTROL_STATUS); 1702172334Smarius if ((status2 & GEM_MAC_PAUSED) != 0) 1703172334Smarius device_printf(sc->sc_dev, 1704172334Smarius "%s: PAUSE received (PAUSE time %d slots)\n", 1705172334Smarius __func__, GEM_MAC_PAUSE_TIME(status2)); 1706172334Smarius if ((status2 & GEM_MAC_PAUSE) != 0) 1707172334Smarius device_printf(sc->sc_dev, 1708172334Smarius "%s: transited to PAUSE state\n", __func__); 1709172334Smarius if ((status2 & GEM_MAC_RESUME) != 0) 1710172334Smarius device_printf(sc->sc_dev, 1711172334Smarius "%s: transited to non-PAUSE state\n", __func__); 1712172334Smarius } 1713172334Smarius if ((status & GEM_INTR_MIF) != 0) 1714172334Smarius device_printf(sc->sc_dev, "%s: MIF interrupt\n", __func__); 1715115030Stmm#endif 171691398Stmm 1717194763Smarius if (__predict_false(status & 1718172334Smarius (GEM_INTR_RX_TAG_ERR | GEM_INTR_PERR | GEM_INTR_BERR)) != 0) 171991398Stmm gem_eint(sc, status); 172091398Stmm 1721172334Smarius if ((status & (GEM_INTR_RX_DONE | GEM_INTR_RX_NOBUF)) != 0) 1722172334Smarius gem_rint(sc); 1723172334Smarius 172491398Stmm if ((status & (GEM_INTR_TX_EMPTY | GEM_INTR_TX_INTME)) != 0) 172591398Stmm gem_tint(sc); 172691398Stmm 1727194763Smarius if (__predict_false((status & GEM_INTR_TX_MAC) != 0)) { 1728177560Smarius status2 = GEM_BANK1_READ_4(sc, GEM_MAC_TX_STATUS); 1729174987Smarius if ((status2 & 1730194763Smarius ~(GEM_MAC_TX_XMIT_DONE | GEM_MAC_TX_DEFER_EXP | 1731194763Smarius GEM_MAC_TX_PEAK_EXP)) != 0) 1732174987Smarius device_printf(sc->sc_dev, 1733174987Smarius "MAC TX fault, status %x\n", status2); 1734174987Smarius if ((status2 & 1735194763Smarius (GEM_MAC_TX_UNDERRUN | GEM_MAC_TX_PKT_TOO_LONG)) != 0) { 1736194763Smarius sc->sc_ifp->if_oerrors++; 1737148369Smarius gem_init_locked(sc); 1738194763Smarius } 173991398Stmm } 1740194763Smarius if (__predict_false((status & GEM_INTR_RX_MAC) != 0)) { 1741177560Smarius status2 = GEM_BANK1_READ_4(sc, GEM_MAC_RX_STATUS); 1742149552Smarius /* 1743172334Smarius * At least with GEM_SUN_GEM and some GEM_SUN_ERI 1744172334Smarius * revisions GEM_MAC_RX_OVERFLOW happen often due to a 1745174987Smarius * silicon bug so handle them silently. Moreover, it's 1746172334Smarius * likely that the receiver has hung so we reset it. 1747149552Smarius */ 1748174987Smarius if ((status2 & GEM_MAC_RX_OVERFLOW) != 0) { 1749172334Smarius sc->sc_ifp->if_ierrors++; 1750172334Smarius gem_reset_rxdma(sc); 1751174987Smarius } else if ((status2 & 1752174987Smarius ~(GEM_MAC_RX_DONE | GEM_MAC_RX_FRAME_CNT)) != 0) 1753174987Smarius device_printf(sc->sc_dev, 1754174987Smarius "MAC RX fault, status %x\n", status2); 175591398Stmm } 1756148369Smarius GEM_UNLOCK(sc); 175791398Stmm} 175891398Stmm 1759164931Smariusstatic int 1760174987Smariusgem_watchdog(struct gem_softc *sc) 176191398Stmm{ 1762179925Smarius struct ifnet *ifp = sc->sc_ifp; 176391398Stmm 1764164931Smarius GEM_LOCK_ASSERT(sc, MA_OWNED); 1765164931Smarius 1766115030Stmm#ifdef GEM_DEBUG 1767174987Smarius CTR4(KTR_GEM, 1768174987Smarius "%s: GEM_RX_CONFIG %x GEM_MAC_RX_STATUS %x GEM_MAC_RX_CONFIG %x", 1769177560Smarius __func__, GEM_BANK1_READ_4(sc, GEM_RX_CONFIG), 1770177560Smarius GEM_BANK1_READ_4(sc, GEM_MAC_RX_STATUS), 1771177560Smarius GEM_BANK1_READ_4(sc, GEM_MAC_RX_CONFIG)); 1772174987Smarius CTR4(KTR_GEM, 1773174987Smarius "%s: GEM_TX_CONFIG %x GEM_MAC_TX_STATUS %x GEM_MAC_TX_CONFIG %x", 1774177560Smarius __func__, GEM_BANK1_READ_4(sc, GEM_TX_CONFIG), 1775177560Smarius GEM_BANK1_READ_4(sc, GEM_MAC_TX_STATUS), 1776177560Smarius GEM_BANK1_READ_4(sc, GEM_MAC_TX_CONFIG)); 1777115030Stmm#endif 177891398Stmm 1779164931Smarius if (sc->sc_wdog_timer == 0 || --sc->sc_wdog_timer != 0) 1780164931Smarius return (0); 1781164931Smarius 1782172334Smarius if ((sc->sc_flags & GEM_LINK) != 0) 1783172334Smarius device_printf(sc->sc_dev, "device timeout\n"); 1784172334Smarius else if (bootverbose) 1785172334Smarius device_printf(sc->sc_dev, "device timeout (no link)\n"); 1786179925Smarius ++ifp->if_oerrors; 178791398Stmm 178891398Stmm /* Try to get more packets going. */ 1789148369Smarius gem_init_locked(sc); 1790179925Smarius gem_start_locked(ifp); 1791164931Smarius return (EJUSTRETURN); 179291398Stmm} 179391398Stmm 179491398Stmmstatic void 1795174987Smariusgem_mifinit(struct gem_softc *sc) 179691398Stmm{ 179791398Stmm 1798176996Smarius /* Configure the MIF in frame mode. */ 1799177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MIF_CONFIG, 1800177560Smarius GEM_BANK1_READ_4(sc, GEM_MIF_CONFIG) & ~GEM_MIF_CONFIG_BB_ENA); 180191398Stmm} 180291398Stmm 180391398Stmm/* 180491398Stmm * MII interface 180591398Stmm * 1806182060Smarius * The MII interface supports at least three different operating modes: 180791398Stmm * 180891398Stmm * Bitbang mode is implemented using data, clock and output enable registers. 180991398Stmm * 181091398Stmm * Frame mode is implemented by loading a complete frame into the frame 181191398Stmm * register and polling the valid bit for completion. 181291398Stmm * 181391398Stmm * Polling mode uses the frame register but completion is indicated by 181491398Stmm * an interrupt. 181591398Stmm * 181691398Stmm */ 181791398Stmmint 1818174987Smariusgem_mii_readreg(device_t dev, int phy, int reg) 181991398Stmm{ 1820174987Smarius struct gem_softc *sc; 182191398Stmm int n; 1822174987Smarius uint32_t v; 182391398Stmm 182491398Stmm#ifdef GEM_DEBUG_PHY 1825172334Smarius printf("%s: phy %d reg %d\n", __func__, phy, reg); 182691398Stmm#endif 182791398Stmm 1828174987Smarius sc = device_get_softc(dev); 1829172334Smarius if (sc->sc_phyad != -1 && phy != sc->sc_phyad) 1830172334Smarius return (0); 183191398Stmm 1832172334Smarius if ((sc->sc_flags & GEM_SERDES) != 0) { 1833172334Smarius switch (reg) { 1834172334Smarius case MII_BMCR: 1835172334Smarius reg = GEM_MII_CONTROL; 1836172334Smarius break; 1837172334Smarius case MII_BMSR: 1838172334Smarius reg = GEM_MII_STATUS; 1839172334Smarius break; 1840172334Smarius case MII_PHYIDR1: 1841172334Smarius case MII_PHYIDR2: 1842172334Smarius return (0); 1843172334Smarius case MII_ANAR: 1844172334Smarius reg = GEM_MII_ANAR; 1845172334Smarius break; 1846172334Smarius case MII_ANLPAR: 1847172334Smarius reg = GEM_MII_ANLPAR; 1848172334Smarius break; 1849172334Smarius case MII_EXTSR: 1850172334Smarius return (EXTSR_1000XFDX | EXTSR_1000XHDX); 1851172334Smarius default: 1852172334Smarius device_printf(sc->sc_dev, 1853172334Smarius "%s: unhandled register %d\n", __func__, reg); 1854172334Smarius return (0); 1855172334Smarius } 1856177560Smarius return (GEM_BANK1_READ_4(sc, reg)); 1857172334Smarius } 1858172334Smarius 1859174987Smarius /* Construct the frame command. */ 1860172334Smarius v = GEM_MIF_FRAME_READ | 1861172334Smarius (phy << GEM_MIF_PHY_SHIFT) | 1862172334Smarius (reg << GEM_MIF_REG_SHIFT); 186391398Stmm 1864177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MIF_FRAME, v); 1865179925Smarius GEM_BANK1_BARRIER(sc, GEM_MIF_FRAME, 4, 1866179925Smarius BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 186791398Stmm for (n = 0; n < 100; n++) { 186891398Stmm DELAY(1); 1869177560Smarius v = GEM_BANK1_READ_4(sc, GEM_MIF_FRAME); 1870150285Smarius if (v & GEM_MIF_FRAME_TA0) 187191398Stmm return (v & GEM_MIF_FRAME_DATA); 187291398Stmm } 187391398Stmm 1874174987Smarius device_printf(sc->sc_dev, "%s: timed out\n", __func__); 187591398Stmm return (0); 187691398Stmm} 187791398Stmm 187891398Stmmint 1879174987Smariusgem_mii_writereg(device_t dev, int phy, int reg, int val) 188091398Stmm{ 1881174987Smarius struct gem_softc *sc; 188291398Stmm int n; 1883174987Smarius uint32_t v; 188491398Stmm 188591398Stmm#ifdef GEM_DEBUG_PHY 1886172334Smarius printf("%s: phy %d reg %d val %x\n", phy, reg, val, __func__); 188791398Stmm#endif 188891398Stmm 1889174987Smarius sc = device_get_softc(dev); 1890172334Smarius if (sc->sc_phyad != -1 && phy != sc->sc_phyad) 1891172334Smarius return (0); 1892172334Smarius 1893172334Smarius if ((sc->sc_flags & GEM_SERDES) != 0) { 1894172334Smarius switch (reg) { 1895172334Smarius case MII_BMSR: 1896172334Smarius reg = GEM_MII_STATUS; 1897172334Smarius break; 1898179925Smarius case MII_BMCR: 1899179925Smarius reg = GEM_MII_CONTROL; 1900179925Smarius if ((val & GEM_MII_CONTROL_RESET) == 0) 1901179925Smarius break; 1902179925Smarius GEM_BANK1_WRITE_4(sc, GEM_MII_CONTROL, val); 1903179925Smarius GEM_BANK1_BARRIER(sc, GEM_MII_CONTROL, 4, 1904179925Smarius BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 1905179925Smarius if (!GEM_BANK1_BITWAIT(sc, GEM_MII_CONTROL, 1906179925Smarius GEM_MII_CONTROL_RESET, 0)) 1907179925Smarius device_printf(sc->sc_dev, 1908179925Smarius "cannot reset PCS\n"); 1909179925Smarius /* FALLTHROUGH */ 1910172334Smarius case MII_ANAR: 1911177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MII_CONFIG, 0); 1912177560Smarius GEM_BANK1_BARRIER(sc, GEM_MII_CONFIG, 4, 1913172334Smarius BUS_SPACE_BARRIER_WRITE); 1914177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MII_ANAR, val); 1915177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MII_SLINK_CONTROL, 1916172334Smarius GEM_MII_SLINK_LOOPBACK | GEM_MII_SLINK_EN_SYNC_D); 1917177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MII_CONFIG, 1918172334Smarius GEM_MII_CONFIG_ENABLE); 1919172334Smarius return (0); 1920172334Smarius case MII_ANLPAR: 1921172334Smarius reg = GEM_MII_ANLPAR; 1922172334Smarius break; 1923172334Smarius default: 1924172334Smarius device_printf(sc->sc_dev, 1925172334Smarius "%s: unhandled register %d\n", __func__, reg); 1926172334Smarius return (0); 1927172334Smarius } 1928177560Smarius GEM_BANK1_WRITE_4(sc, reg, val); 1929172334Smarius return (0); 1930172334Smarius } 1931172334Smarius 1932174987Smarius /* Construct the frame command. */ 1933172334Smarius v = GEM_MIF_FRAME_WRITE | 1934172334Smarius (phy << GEM_MIF_PHY_SHIFT) | 1935172334Smarius (reg << GEM_MIF_REG_SHIFT) | 193691398Stmm (val & GEM_MIF_FRAME_DATA); 193791398Stmm 1938177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MIF_FRAME, v); 1939179925Smarius GEM_BANK1_BARRIER(sc, GEM_MIF_FRAME, 4, 1940179925Smarius BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 194191398Stmm for (n = 0; n < 100; n++) { 194291398Stmm DELAY(1); 1943177560Smarius v = GEM_BANK1_READ_4(sc, GEM_MIF_FRAME); 1944150285Smarius if (v & GEM_MIF_FRAME_TA0) 194591398Stmm return (1); 194691398Stmm } 194791398Stmm 1948174987Smarius device_printf(sc->sc_dev, "%s: timed out\n", __func__); 194991398Stmm return (0); 195091398Stmm} 195191398Stmm 195291398Stmmvoid 1953174987Smariusgem_mii_statchg(device_t dev) 195491398Stmm{ 1955174987Smarius struct gem_softc *sc; 1956172334Smarius int gigabit; 1957172334Smarius uint32_t rxcfg, txcfg, v; 195891398Stmm 1959174987Smarius sc = device_get_softc(dev); 1960174987Smarius 1961194763Smarius GEM_LOCK_ASSERT(sc, MA_OWNED); 1962194763Smarius 196391398Stmm#ifdef GEM_DEBUG 1964174987Smarius if ((sc->sc_ifp->if_flags & IFF_DEBUG) != 0) 1965172334Smarius device_printf(sc->sc_dev, "%s: status change: PHY = %d\n", 1966172334Smarius __func__, sc->sc_phyad); 196791398Stmm#endif 196891398Stmm 1969172334Smarius if ((sc->sc_mii->mii_media_status & IFM_ACTIVE) != 0 && 1970172334Smarius IFM_SUBTYPE(sc->sc_mii->mii_media_active) != IFM_NONE) 1971172334Smarius sc->sc_flags |= GEM_LINK; 1972172334Smarius else 1973172334Smarius sc->sc_flags &= ~GEM_LINK; 1974172334Smarius 1975172334Smarius switch (IFM_SUBTYPE(sc->sc_mii->mii_media_active)) { 1976172334Smarius case IFM_1000_SX: 1977172334Smarius case IFM_1000_LX: 1978172334Smarius case IFM_1000_CX: 1979172334Smarius case IFM_1000_T: 1980172334Smarius gigabit = 1; 1981172334Smarius break; 1982172334Smarius default: 1983172334Smarius gigabit = 0; 198491398Stmm } 198591398Stmm 1986172334Smarius /* 1987172334Smarius * The configuration done here corresponds to the steps F) and 1988172334Smarius * G) and as far as enabling of RX and TX MAC goes also step H) 1989172334Smarius * of the initialization sequence outlined in section 3.2.1 of 1990172334Smarius * the GEM Gigabit Ethernet ASIC Specification. 1991172334Smarius */ 1992172334Smarius 1993177560Smarius rxcfg = GEM_BANK1_READ_4(sc, GEM_MAC_RX_CONFIG); 1994172334Smarius rxcfg &= ~(GEM_MAC_RX_CARR_EXTEND | GEM_MAC_RX_ENABLE); 1995172334Smarius txcfg = GEM_MAC_TX_ENA_IPG0 | GEM_MAC_TX_NGU | GEM_MAC_TX_NGU_LIMIT; 1996172334Smarius if ((IFM_OPTIONS(sc->sc_mii->mii_media_active) & IFM_FDX) != 0) 1997172334Smarius txcfg |= GEM_MAC_TX_IGN_CARRIER | GEM_MAC_TX_IGN_COLLIS; 1998172334Smarius else if (gigabit != 0) { 1999172334Smarius rxcfg |= GEM_MAC_RX_CARR_EXTEND; 2000172334Smarius txcfg |= GEM_MAC_TX_CARR_EXTEND; 2001172334Smarius } 2002177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_TX_CONFIG, 0); 2003179925Smarius GEM_BANK1_BARRIER(sc, GEM_MAC_TX_CONFIG, 4, 2004179925Smarius BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 2005177560Smarius if (!GEM_BANK1_BITWAIT(sc, GEM_MAC_TX_CONFIG, GEM_MAC_TX_ENABLE, 0)) 2006172334Smarius device_printf(sc->sc_dev, "cannot disable TX MAC\n"); 2007177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_TX_CONFIG, txcfg); 2008177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_CONFIG, 0); 2009179925Smarius GEM_BANK1_BARRIER(sc, GEM_MAC_RX_CONFIG, 4, 2010179925Smarius BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 2011177560Smarius if (!GEM_BANK1_BITWAIT(sc, GEM_MAC_RX_CONFIG, GEM_MAC_RX_ENABLE, 0)) 2012172334Smarius device_printf(sc->sc_dev, "cannot disable RX MAC\n"); 2013177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_CONFIG, rxcfg); 2014172334Smarius 2015177560Smarius v = GEM_BANK1_READ_4(sc, GEM_MAC_CONTROL_CONFIG) & 2016172334Smarius ~(GEM_MAC_CC_RX_PAUSE | GEM_MAC_CC_TX_PAUSE); 2017172334Smarius#ifdef notyet 2018174987Smarius if ((IFM_OPTIONS(sc->sc_mii->mii_media_active) & 2019174987Smarius IFM_ETH_RXPAUSE) != 0) 2020172334Smarius v |= GEM_MAC_CC_RX_PAUSE; 2021174987Smarius if ((IFM_OPTIONS(sc->sc_mii->mii_media_active) & 2022174987Smarius IFM_ETH_TXPAUSE) != 0) 2023172334Smarius v |= GEM_MAC_CC_TX_PAUSE; 2024172334Smarius#endif 2025177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_CONTROL_CONFIG, v); 2026172334Smarius 2027172334Smarius if ((IFM_OPTIONS(sc->sc_mii->mii_media_active) & IFM_FDX) == 0 && 2028172334Smarius gigabit != 0) 2029177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_SLOT_TIME, 2030172334Smarius GEM_MAC_SLOT_TIME_CARR_EXTEND); 2031172334Smarius else 2032177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_SLOT_TIME, 2033172334Smarius GEM_MAC_SLOT_TIME_NORMAL); 2034172334Smarius 203591398Stmm /* XIF Configuration */ 203691398Stmm v = GEM_MAC_XIF_LINK_LED; 203791398Stmm v |= GEM_MAC_XIF_TX_MII_ENA; 2038172334Smarius if ((sc->sc_flags & GEM_SERDES) == 0) { 2039177560Smarius if ((GEM_BANK1_READ_4(sc, GEM_MIF_CONFIG) & 2040182060Smarius GEM_MIF_CONFIG_PHY_SEL) != 0) { 2041172334Smarius /* External MII needs echo disable if half duplex. */ 2042194763Smarius if ((IFM_OPTIONS(sc->sc_mii->mii_media_active) & 2043182060Smarius IFM_FDX) == 0) 2044182060Smarius v |= GEM_MAC_XIF_ECHO_DISABL; 2045182060Smarius } else 2046172334Smarius /* 2047172334Smarius * Internal MII needs buffer enable. 2048172334Smarius * XXX buffer enable makes only sense for an 2049172334Smarius * external PHY. 2050172334Smarius */ 2051172334Smarius v |= GEM_MAC_XIF_MII_BUF_ENA; 2052172334Smarius } 2053172334Smarius if (gigabit != 0) 2054172334Smarius v |= GEM_MAC_XIF_GMII_MODE; 2055172334Smarius if ((IFM_OPTIONS(sc->sc_mii->mii_media_active) & IFM_FDX) != 0) 2056172334Smarius v |= GEM_MAC_XIF_FDPLX_LED; 2057177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_XIF_CONFIG, v); 205899726Sbenno 2059172334Smarius if ((sc->sc_ifp->if_drv_flags & IFF_DRV_RUNNING) != 0 && 2060172334Smarius (sc->sc_flags & GEM_LINK) != 0) { 2061177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_TX_CONFIG, 2062172334Smarius txcfg | GEM_MAC_TX_ENABLE); 2063177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_CONFIG, 2064172334Smarius rxcfg | GEM_MAC_RX_ENABLE); 206591398Stmm } 206691398Stmm} 206791398Stmm 206891398Stmmint 2069174987Smariusgem_mediachange(struct ifnet *ifp) 207091398Stmm{ 207191398Stmm struct gem_softc *sc = ifp->if_softc; 2072150285Smarius int error; 207391398Stmm 2074174987Smarius /* XXX add support for serial media. */ 207591398Stmm 2076150285Smarius GEM_LOCK(sc); 2077150285Smarius error = mii_mediachg(sc->sc_mii); 2078150285Smarius GEM_UNLOCK(sc); 2079150285Smarius return (error); 208091398Stmm} 208191398Stmm 208291398Stmmvoid 2083174987Smariusgem_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr) 208491398Stmm{ 208591398Stmm struct gem_softc *sc = ifp->if_softc; 208691398Stmm 2087148369Smarius GEM_LOCK(sc); 2088148369Smarius if ((ifp->if_flags & IFF_UP) == 0) { 2089148369Smarius GEM_UNLOCK(sc); 209091398Stmm return; 2091148369Smarius } 209291398Stmm 209391398Stmm mii_pollstat(sc->sc_mii); 209491398Stmm ifmr->ifm_active = sc->sc_mii->mii_media_active; 209591398Stmm ifmr->ifm_status = sc->sc_mii->mii_media_status; 2096148369Smarius GEM_UNLOCK(sc); 209791398Stmm} 209891398Stmm 209991398Stmmstatic int 2100174987Smariusgem_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 210191398Stmm{ 210291398Stmm struct gem_softc *sc = ifp->if_softc; 210391398Stmm struct ifreq *ifr = (struct ifreq *)data; 2104174987Smarius int error; 210591398Stmm 2106174987Smarius error = 0; 210791398Stmm switch (cmd) { 2108150285Smarius case SIOCSIFFLAGS: 2109148369Smarius GEM_LOCK(sc); 2110194763Smarius if ((sc->sc_flags & GEM_DYING) != 0) { 2111194763Smarius error = EINVAL; 2112194763Smarius GEM_UNLOCK(sc); 2113194763Smarius break; 2114194763Smarius } 2115174987Smarius if ((ifp->if_flags & IFF_UP) != 0) { 2116172334Smarius if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0 && 2117172334Smarius ((ifp->if_flags ^ sc->sc_ifflags) & 2118172334Smarius (IFF_ALLMULTI | IFF_PROMISC)) != 0) 211991398Stmm gem_setladrf(sc); 212091398Stmm else 2121148369Smarius gem_init_locked(sc); 2122174987Smarius } else if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) 2123174987Smarius gem_stop(ifp, 0); 2124170273Syongari if ((ifp->if_flags & IFF_LINK0) != 0) 2125170273Syongari sc->sc_csum_features |= CSUM_UDP; 2126170273Syongari else 2127170273Syongari sc->sc_csum_features &= ~CSUM_UDP; 2128170273Syongari if ((ifp->if_capenable & IFCAP_TXCSUM) != 0) 2129170273Syongari ifp->if_hwassist = sc->sc_csum_features; 213099726Sbenno sc->sc_ifflags = ifp->if_flags; 2131150285Smarius GEM_UNLOCK(sc); 213291398Stmm break; 213391398Stmm case SIOCADDMULTI: 213491398Stmm case SIOCDELMULTI: 2135150285Smarius GEM_LOCK(sc); 213691398Stmm gem_setladrf(sc); 2137150285Smarius GEM_UNLOCK(sc); 213891398Stmm break; 213991398Stmm case SIOCGIFMEDIA: 214091398Stmm case SIOCSIFMEDIA: 214191398Stmm error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii->mii_media, cmd); 214291398Stmm break; 2143170273Syongari case SIOCSIFCAP: 2144170273Syongari GEM_LOCK(sc); 2145170273Syongari ifp->if_capenable = ifr->ifr_reqcap; 2146170273Syongari if ((ifp->if_capenable & IFCAP_TXCSUM) != 0) 2147170273Syongari ifp->if_hwassist = sc->sc_csum_features; 2148170273Syongari else 2149170273Syongari ifp->if_hwassist = 0; 2150170273Syongari GEM_UNLOCK(sc); 2151170273Syongari break; 215291398Stmm default: 2153150285Smarius error = ether_ioctl(ifp, cmd, data); 215491398Stmm break; 215591398Stmm } 215691398Stmm 215791398Stmm return (error); 215891398Stmm} 215991398Stmm 216091398Stmmstatic void 2161174987Smariusgem_setladrf(struct gem_softc *sc) 216291398Stmm{ 2163147256Sbrooks struct ifnet *ifp = sc->sc_ifp; 216491398Stmm struct ifmultiaddr *inm; 216599726Sbenno int i; 2166174987Smarius uint32_t hash[16]; 2167174987Smarius uint32_t crc, v; 216891398Stmm 2169148369Smarius GEM_LOCK_ASSERT(sc, MA_OWNED); 2170148369Smarius 2171174987Smarius /* Get the current RX configuration. */ 2172177560Smarius v = GEM_BANK1_READ_4(sc, GEM_MAC_RX_CONFIG); 217391398Stmm 217499726Sbenno /* 217599726Sbenno * Turn off promiscuous mode, promiscuous group mode (all multicast), 217699726Sbenno * and hash filter. Depending on the case, the right bit will be 217799726Sbenno * enabled. 217899726Sbenno */ 2179174987Smarius v &= ~(GEM_MAC_RX_PROMISCUOUS | GEM_MAC_RX_HASH_FILTER | 218099726Sbenno GEM_MAC_RX_PROMISC_GRP); 218199726Sbenno 2182177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_CONFIG, v); 2183179925Smarius GEM_BANK1_BARRIER(sc, GEM_MAC_RX_CONFIG, 4, 2184179925Smarius BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 2185177560Smarius if (!GEM_BANK1_BITWAIT(sc, GEM_MAC_RX_CONFIG, GEM_MAC_RX_HASH_FILTER, 2186177560Smarius 0)) 2187172334Smarius device_printf(sc->sc_dev, "cannot disable RX hash filter\n"); 2188172334Smarius 218991398Stmm if ((ifp->if_flags & IFF_PROMISC) != 0) { 219091398Stmm v |= GEM_MAC_RX_PROMISCUOUS; 219191398Stmm goto chipit; 219291398Stmm } 219391398Stmm if ((ifp->if_flags & IFF_ALLMULTI) != 0) { 219499726Sbenno v |= GEM_MAC_RX_PROMISC_GRP; 219591398Stmm goto chipit; 219691398Stmm } 219791398Stmm 219891398Stmm /* 2199174987Smarius * Set up multicast address filter by passing all multicast 2200174987Smarius * addresses through a crc generator, and then using the high 2201174987Smarius * order 8 bits as an index into the 256 bit logical address 2202174987Smarius * filter. The high order 4 bits selects the word, while the 2203174987Smarius * other 4 bits select the bit within the word (where bit 0 2204174987Smarius * is the MSB). 220591398Stmm */ 220691398Stmm 2207174987Smarius /* Clear the hash table. */ 220899726Sbenno memset(hash, 0, sizeof(hash)); 220999726Sbenno 2210148654Srwatson IF_ADDR_LOCK(ifp); 2211147256Sbrooks TAILQ_FOREACH(inm, &ifp->if_multiaddrs, ifma_link) { 221291398Stmm if (inm->ifma_addr->sa_family != AF_LINK) 221391398Stmm continue; 2214130288Smarius crc = ether_crc32_le(LLADDR((struct sockaddr_dl *) 2215130288Smarius inm->ifma_addr), ETHER_ADDR_LEN); 221691398Stmm 2217174987Smarius /* We just want the 8 most significant bits. */ 221891398Stmm crc >>= 24; 221991398Stmm 222091398Stmm /* Set the corresponding bit in the filter. */ 222199726Sbenno hash[crc >> 4] |= 1 << (15 - (crc & 15)); 222291398Stmm } 2223148654Srwatson IF_ADDR_UNLOCK(ifp); 222491398Stmm 222599726Sbenno v |= GEM_MAC_RX_HASH_FILTER; 222699726Sbenno 2227174987Smarius /* Now load the hash table into the chip (if we are using it). */ 2228174987Smarius for (i = 0; i < 16; i++) 2229177560Smarius GEM_BANK1_WRITE_4(sc, 2230174987Smarius GEM_MAC_HASH0 + i * (GEM_MAC_HASH1 - GEM_MAC_HASH0), 223199726Sbenno hash[i]); 223299726Sbenno 2233174987Smarius chipit: 2234177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_CONFIG, v); 223591398Stmm} 2236