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$"); 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> 64257176Sglebius#include <net/if_var.h> 6591398Stmm#include <net/if_arp.h> 6691398Stmm#include <net/if_dl.h> 6791398Stmm#include <net/if_media.h> 68147256Sbrooks#include <net/if_types.h> 69149552Smarius#include <net/if_vlan_var.h> 7091398Stmm 71170273Syongari#include <netinet/in.h> 72170273Syongari#include <netinet/in_systm.h> 73170273Syongari#include <netinet/ip.h> 74170273Syongari#include <netinet/tcp.h> 75170273Syongari#include <netinet/udp.h> 76170273Syongari 7791398Stmm#include <machine/bus.h> 7891398Stmm 7991398Stmm#include <dev/mii/mii.h> 8091398Stmm#include <dev/mii/miivar.h> 8191398Stmm 82119355Simp#include <dev/gem/if_gemreg.h> 83119355Simp#include <dev/gem/if_gemvar.h> 8491398Stmm 85172334SmariusCTASSERT(powerof2(GEM_NRXDESC) && GEM_NRXDESC >= 32 && GEM_NRXDESC <= 8192); 86172334SmariusCTASSERT(powerof2(GEM_NTXDESC) && GEM_NTXDESC >= 32 && GEM_NTXDESC <= 8192); 87172334Smarius 88194763Smarius#define GEM_TRIES 10000 89172334Smarius 90170273Syongari/* 91182060Smarius * The hardware supports basic TCP/UDP checksum offloading. However, 92170273Syongari * the hardware doesn't compensate the checksum for UDP datagram which 93174987Smarius * can yield to 0x0. As a safe guard, UDP checksum offload is disabled 94174987Smarius * by default. It can be reactivated by setting special link option 95170273Syongari * link0 with ifconfig(8). 96170273Syongari */ 97170273Syongari#define GEM_CSUM_FEATURES (CSUM_TCP) 9891398Stmm 99174987Smariusstatic int gem_add_rxbuf(struct gem_softc *sc, int idx); 100177560Smariusstatic int gem_bitwait(struct gem_softc *sc, u_int bank, bus_addr_t r, 101177560Smarius uint32_t clr, uint32_t set); 102174987Smariusstatic void gem_cddma_callback(void *xsc, bus_dma_segment_t *segs, 103174987Smarius int nsegs, int error); 104174987Smariusstatic int gem_disable_rx(struct gem_softc *sc); 105174987Smariusstatic int gem_disable_tx(struct gem_softc *sc); 106174987Smariusstatic void gem_eint(struct gem_softc *sc, u_int status); 107174987Smariusstatic void gem_init(void *xsc); 108174987Smariusstatic void gem_init_locked(struct gem_softc *sc); 109174987Smariusstatic void gem_init_regs(struct gem_softc *sc); 110174987Smariusstatic int gem_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data); 111174987Smariusstatic int gem_load_txmbuf(struct gem_softc *sc, struct mbuf **m_head); 112174987Smariusstatic int gem_meminit(struct gem_softc *sc); 113174987Smariusstatic void gem_mifinit(struct gem_softc *sc); 114174987Smariusstatic void gem_reset(struct gem_softc *sc); 115174987Smariusstatic int gem_reset_rx(struct gem_softc *sc); 116172334Smariusstatic void gem_reset_rxdma(struct gem_softc *sc); 117174987Smariusstatic int gem_reset_tx(struct gem_softc *sc); 118174987Smariusstatic u_int gem_ringsize(u_int sz); 119174987Smariusstatic void gem_rint(struct gem_softc *sc); 120148368Smarius#ifdef GEM_RINT_TIMEOUT 121174987Smariusstatic void gem_rint_timeout(void *arg); 122100587Sjake#endif 123194763Smariusstatic inline void gem_rxcksum(struct mbuf *m, uint64_t flags); 124174987Smariusstatic void gem_rxdrain(struct gem_softc *sc); 125223949Smariusstatic void gem_setladrf(struct gem_softc *sc); 126174987Smariusstatic void gem_start(struct ifnet *ifp); 127174987Smariusstatic void gem_start_locked(struct ifnet *ifp); 128174987Smariusstatic void gem_stop(struct ifnet *ifp, int disable); 129174987Smariusstatic void gem_tick(void *arg); 130174987Smariusstatic void gem_tint(struct gem_softc *sc); 131194763Smariusstatic inline void gem_txkick(struct gem_softc *sc); 132174987Smariusstatic int gem_watchdog(struct gem_softc *sc); 13391398Stmm 13491398Stmmdevclass_t gem_devclass; 13591398StmmDRIVER_MODULE(miibus, gem, miibus_driver, miibus_devclass, 0, 0); 13691398StmmMODULE_DEPEND(gem, miibus, 1, 1, 1); 13791398Stmm 13891398Stmm#ifdef GEM_DEBUG 13991398Stmm#include <sys/ktr.h> 140210334Sattilio#define KTR_GEM KTR_SPARE2 14191398Stmm#endif 14291398Stmm 143177560Smarius#define GEM_BANK1_BITWAIT(sc, r, clr, set) \ 144177560Smarius gem_bitwait((sc), GEM_RES_BANK1, (r), (clr), (set)) 145177560Smarius#define GEM_BANK2_BITWAIT(sc, r, clr, set) \ 146177560Smarius gem_bitwait((sc), GEM_RES_BANK2, (r), (clr), (set)) 147177560Smarius 14891398Stmmint 149174987Smariusgem_attach(struct gem_softc *sc) 15091398Stmm{ 151174987Smarius struct gem_txsoft *txs; 152147256Sbrooks struct ifnet *ifp; 153213893Smarius int error, i, phy; 154174987Smarius uint32_t v; 15591398Stmm 156194763Smarius if (bootverbose) 157194763Smarius device_printf(sc->sc_dev, "flags=0x%x\n", sc->sc_flags); 158194763Smarius 159194763Smarius /* Set up ifnet structure. */ 160147256Sbrooks ifp = sc->sc_ifp = if_alloc(IFT_ETHER); 161147256Sbrooks if (ifp == NULL) 162147256Sbrooks return (ENOSPC); 163194763Smarius sc->sc_csum_features = GEM_CSUM_FEATURES; 164194763Smarius ifp->if_softc = sc; 165194763Smarius if_initname(ifp, device_get_name(sc->sc_dev), 166194763Smarius device_get_unit(sc->sc_dev)); 167194763Smarius ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 168194763Smarius ifp->if_start = gem_start; 169194763Smarius ifp->if_ioctl = gem_ioctl; 170194763Smarius ifp->if_init = gem_init; 171194763Smarius IFQ_SET_MAXLEN(&ifp->if_snd, GEM_TXQUEUELEN); 172194763Smarius ifp->if_snd.ifq_drv_maxlen = GEM_TXQUEUELEN; 173194763Smarius IFQ_SET_READY(&ifp->if_snd); 174147256Sbrooks 175150285Smarius callout_init_mtx(&sc->sc_tick_ch, &sc->sc_mtx, 0); 176150285Smarius#ifdef GEM_RINT_TIMEOUT 177150285Smarius callout_init_mtx(&sc->sc_rx_ch, &sc->sc_mtx, 0); 178150285Smarius#endif 179150285Smarius 18091398Stmm /* Make sure the chip is stopped. */ 18191398Stmm gem_reset(sc); 18291398Stmm 183161928Sjmg error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), 1, 0, 184161928Sjmg BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, 185174987Smarius BUS_SPACE_MAXSIZE_32BIT, 0, BUS_SPACE_MAXSIZE_32BIT, 0, NULL, 186174987Smarius NULL, &sc->sc_pdmatag); 187194763Smarius if (error != 0) 188147256Sbrooks goto fail_ifnet; 18991398Stmm 19091398Stmm error = bus_dma_tag_create(sc->sc_pdmatag, 1, 0, 191170273Syongari BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, MCLBYTES, 192170273Syongari 1, MCLBYTES, BUS_DMA_ALLOCNOW, NULL, NULL, &sc->sc_rdmatag); 193194763Smarius if (error != 0) 194108832Stmm goto fail_ptag; 19591398Stmm 196108832Stmm error = bus_dma_tag_create(sc->sc_pdmatag, 1, 0, 197170273Syongari BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, 198170273Syongari MCLBYTES * GEM_NTXSEGS, GEM_NTXSEGS, MCLBYTES, 199117126Sscottl BUS_DMA_ALLOCNOW, NULL, NULL, &sc->sc_tdmatag); 200194763Smarius if (error != 0) 201108832Stmm goto fail_rtag; 202108832Stmm 20391398Stmm error = bus_dma_tag_create(sc->sc_pdmatag, PAGE_SIZE, 0, 204170273Syongari BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, 20591398Stmm sizeof(struct gem_control_data), 1, 206170273Syongari sizeof(struct gem_control_data), 0, 207170273Syongari NULL, NULL, &sc->sc_cdmatag); 208194763Smarius if (error != 0) 209108832Stmm goto fail_ttag; 21091398Stmm 21191398Stmm /* 212174987Smarius * Allocate the control data structures, create and load the 21391398Stmm * DMA map for it. 21491398Stmm */ 21591398Stmm if ((error = bus_dmamem_alloc(sc->sc_cdmatag, 216170273Syongari (void **)&sc->sc_control_data, 217170273Syongari BUS_DMA_WAITOK | BUS_DMA_COHERENT | BUS_DMA_ZERO, 218194763Smarius &sc->sc_cddmamap)) != 0) { 219174987Smarius device_printf(sc->sc_dev, 220174987Smarius "unable to allocate control data, error = %d\n", error); 221108832Stmm goto fail_ctag; 22291398Stmm } 22391398Stmm 22491398Stmm sc->sc_cddma = 0; 22591398Stmm if ((error = bus_dmamap_load(sc->sc_cdmatag, sc->sc_cddmamap, 22691398Stmm sc->sc_control_data, sizeof(struct gem_control_data), 22791398Stmm gem_cddma_callback, sc, 0)) != 0 || sc->sc_cddma == 0) { 228174987Smarius device_printf(sc->sc_dev, 229174987Smarius "unable to load control data DMA map, error = %d\n", 230174987Smarius error); 231108832Stmm goto fail_cmem; 23291398Stmm } 23391398Stmm 23491398Stmm /* 23591398Stmm * Initialize the transmit job descriptors. 23691398Stmm */ 23791398Stmm STAILQ_INIT(&sc->sc_txfreeq); 23891398Stmm STAILQ_INIT(&sc->sc_txdirtyq); 23991398Stmm 24091398Stmm /* 24191398Stmm * Create the transmit buffer DMA maps. 24291398Stmm */ 24391398Stmm error = ENOMEM; 24491398Stmm for (i = 0; i < GEM_TXQUEUELEN; i++) { 24591398Stmm txs = &sc->sc_txsoft[i]; 24691398Stmm txs->txs_mbuf = NULL; 24791398Stmm txs->txs_ndescs = 0; 248108832Stmm if ((error = bus_dmamap_create(sc->sc_tdmatag, 0, 24991398Stmm &txs->txs_dmamap)) != 0) { 250174987Smarius device_printf(sc->sc_dev, 251174987Smarius "unable to create TX DMA map %d, error = %d\n", 252174987Smarius i, error); 253108832Stmm goto fail_txd; 25491398Stmm } 25591398Stmm STAILQ_INSERT_TAIL(&sc->sc_txfreeq, txs, txs_q); 25691398Stmm } 25791398Stmm 25891398Stmm /* 25991398Stmm * Create the receive buffer DMA maps. 26091398Stmm */ 26191398Stmm for (i = 0; i < GEM_NRXDESC; i++) { 262108832Stmm if ((error = bus_dmamap_create(sc->sc_rdmatag, 0, 26391398Stmm &sc->sc_rxsoft[i].rxs_dmamap)) != 0) { 264174987Smarius device_printf(sc->sc_dev, 265174987Smarius "unable to create RX DMA map %d, error = %d\n", 266174987Smarius i, error); 267108832Stmm goto fail_rxd; 26891398Stmm } 26991398Stmm sc->sc_rxsoft[i].rxs_mbuf = NULL; 27091398Stmm } 27191398Stmm 272212725Smarius /* Bypass probing PHYs if we already know for sure to use a SERDES. */ 273212725Smarius if ((sc->sc_flags & GEM_SERDES) != 0) 274212725Smarius goto serdes; 275212725Smarius 276172334Smarius /* Bad things will happen when touching this register on ERI. */ 277212725Smarius if (sc->sc_variant != GEM_SUN_ERI) { 278177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MII_DATAPATH_MODE, 279172334Smarius GEM_MII_DATAPATH_MII); 280212725Smarius GEM_BANK1_BARRIER(sc, GEM_MII_DATAPATH_MODE, 4, 281212725Smarius BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 282212725Smarius } 283172334Smarius 28491398Stmm gem_mifinit(sc); 28591398Stmm 286172334Smarius /* 287172334Smarius * Look for an external PHY. 288172334Smarius */ 289172334Smarius error = ENXIO; 290177560Smarius v = GEM_BANK1_READ_4(sc, GEM_MIF_CONFIG); 291172334Smarius if ((v & GEM_MIF_CONFIG_MDI1) != 0) { 292172334Smarius v |= GEM_MIF_CONFIG_PHY_SEL; 293177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MIF_CONFIG, v); 294212725Smarius GEM_BANK1_BARRIER(sc, GEM_MIF_CONFIG, 4, 295212725Smarius BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 296172334Smarius switch (sc->sc_variant) { 297172334Smarius case GEM_SUN_ERI: 298213893Smarius phy = GEM_PHYAD_EXTERNAL; 299172334Smarius break; 300172334Smarius default: 301213893Smarius phy = MII_PHY_ANY; 302172334Smarius break; 303172334Smarius } 304213893Smarius error = mii_attach(sc->sc_dev, &sc->sc_miibus, ifp, 305213893Smarius gem_mediachange, gem_mediastatus, BMSR_DEFCAPMASK, phy, 306215722Smarius MII_OFFSET_ANY, MIIF_DOPAUSE); 307172334Smarius } 308172334Smarius 309172334Smarius /* 310172334Smarius * Fall back on an internal PHY if no external PHY was found. 311204222Smarius * Note that with Apple (K2) GMACs GEM_MIF_CONFIG_MDI0 can't be 312204222Smarius * trusted when the firmware has powered down the chip. 313172334Smarius */ 314204222Smarius if (error != 0 && 315204222Smarius ((v & GEM_MIF_CONFIG_MDI0) != 0 || GEM_IS_APPLE(sc))) { 316172334Smarius v &= ~GEM_MIF_CONFIG_PHY_SEL; 317177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MIF_CONFIG, v); 318212725Smarius GEM_BANK1_BARRIER(sc, GEM_MIF_CONFIG, 4, 319212725Smarius BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 320172334Smarius switch (sc->sc_variant) { 321172334Smarius case GEM_SUN_ERI: 322172334Smarius case GEM_APPLE_K2_GMAC: 323213893Smarius phy = GEM_PHYAD_INTERNAL; 324172334Smarius break; 325172334Smarius case GEM_APPLE_GMAC: 326213893Smarius phy = GEM_PHYAD_EXTERNAL; 327172334Smarius break; 328172334Smarius default: 329213893Smarius phy = MII_PHY_ANY; 330172334Smarius break; 331172334Smarius } 332213893Smarius error = mii_attach(sc->sc_dev, &sc->sc_miibus, ifp, 333213893Smarius gem_mediachange, gem_mediastatus, BMSR_DEFCAPMASK, phy, 334215722Smarius MII_OFFSET_ANY, MIIF_DOPAUSE); 335172334Smarius } 336172334Smarius 337172334Smarius /* 338172334Smarius * Try the external PCS SERDES if we didn't find any PHYs. 339172334Smarius */ 340172334Smarius if (error != 0 && sc->sc_variant == GEM_SUN_GEM) { 341212725Smarius serdes: 342177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MII_DATAPATH_MODE, 343172334Smarius GEM_MII_DATAPATH_SERDES); 344212725Smarius GEM_BANK1_BARRIER(sc, GEM_MII_DATAPATH_MODE, 4, 345212725Smarius BUS_SPACE_BARRIER_WRITE); 346177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MII_SLINK_CONTROL, 347172334Smarius GEM_MII_SLINK_LOOPBACK | GEM_MII_SLINK_EN_SYNC_D); 348212725Smarius GEM_BANK1_BARRIER(sc, GEM_MII_SLINK_CONTROL, 4, 349212725Smarius BUS_SPACE_BARRIER_WRITE); 350177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MII_CONFIG, GEM_MII_CONFIG_ENABLE); 351212725Smarius GEM_BANK1_BARRIER(sc, GEM_MII_CONFIG, 4, 352212725Smarius BUS_SPACE_BARRIER_WRITE); 353172334Smarius sc->sc_flags |= GEM_SERDES; 354213893Smarius error = mii_attach(sc->sc_dev, &sc->sc_miibus, ifp, 355213893Smarius gem_mediachange, gem_mediastatus, BMSR_DEFCAPMASK, 356215722Smarius GEM_PHYAD_EXTERNAL, MII_OFFSET_ANY, MIIF_DOPAUSE); 357172334Smarius } 358172334Smarius if (error != 0) { 359213893Smarius device_printf(sc->sc_dev, "attaching PHYs failed\n"); 360108832Stmm goto fail_rxd; 36191398Stmm } 36291398Stmm sc->sc_mii = device_get_softc(sc->sc_miibus); 36391398Stmm 36491398Stmm /* 36591398Stmm * From this point forward, the attachment cannot fail. A failure 36691398Stmm * before this point releases all resources that may have been 36791398Stmm * allocated. 36891398Stmm */ 36991398Stmm 370176996Smarius /* Get RX FIFO size. */ 37199726Sbenno sc->sc_rxfifosize = 64 * 372177560Smarius GEM_BANK1_READ_4(sc, GEM_RX_FIFO_SIZE); 37399726Sbenno 374176996Smarius /* Get TX FIFO size. */ 375177560Smarius v = GEM_BANK1_READ_4(sc, GEM_TX_FIFO_SIZE); 376128588Stmm device_printf(sc->sc_dev, "%ukB RX FIFO, %ukB TX FIFO\n", 377128588Stmm sc->sc_rxfifosize / 1024, v / 16); 37899726Sbenno 37991398Stmm /* Attach the interface. */ 380147256Sbrooks ether_ifattach(ifp, sc->sc_enaddr); 38191398Stmm 38291398Stmm /* 383170273Syongari * Tell the upper layer(s) we support long frames/checksum offloads. 384149552Smarius */ 385270856Sglebius ifp->if_hdrlen = sizeof(struct ether_vlan_header); 386170273Syongari ifp->if_capabilities |= IFCAP_VLAN_MTU | IFCAP_HWCSUM; 387170273Syongari ifp->if_hwassist |= sc->sc_csum_features; 388170273Syongari ifp->if_capenable |= IFCAP_VLAN_MTU | IFCAP_HWCSUM; 389149552Smarius 39091398Stmm return (0); 39191398Stmm 39291398Stmm /* 39391398Stmm * Free any resources we've allocated during the failed attach 39491398Stmm * attempt. Do this in reverse order and fall through. 39591398Stmm */ 396174987Smarius fail_rxd: 397174987Smarius for (i = 0; i < GEM_NRXDESC; i++) 39891398Stmm if (sc->sc_rxsoft[i].rxs_dmamap != NULL) 399108832Stmm bus_dmamap_destroy(sc->sc_rdmatag, 40091398Stmm sc->sc_rxsoft[i].rxs_dmamap); 401174987Smarius fail_txd: 402174987Smarius for (i = 0; i < GEM_TXQUEUELEN; i++) 40391398Stmm if (sc->sc_txsoft[i].txs_dmamap != NULL) 404108832Stmm bus_dmamap_destroy(sc->sc_tdmatag, 40591398Stmm sc->sc_txsoft[i].txs_dmamap); 406108832Stmm bus_dmamap_unload(sc->sc_cdmatag, sc->sc_cddmamap); 407174987Smarius fail_cmem: 40891398Stmm bus_dmamem_free(sc->sc_cdmatag, sc->sc_control_data, 40991398Stmm sc->sc_cddmamap); 410174987Smarius fail_ctag: 41191398Stmm bus_dma_tag_destroy(sc->sc_cdmatag); 412174987Smarius fail_ttag: 413108832Stmm bus_dma_tag_destroy(sc->sc_tdmatag); 414174987Smarius fail_rtag: 415108832Stmm bus_dma_tag_destroy(sc->sc_rdmatag); 416174987Smarius fail_ptag: 41791398Stmm bus_dma_tag_destroy(sc->sc_pdmatag); 418174987Smarius fail_ifnet: 419147256Sbrooks if_free(ifp); 42091398Stmm return (error); 42191398Stmm} 42291398Stmm 423108964Stmmvoid 424174987Smariusgem_detach(struct gem_softc *sc) 425108964Stmm{ 426147256Sbrooks struct ifnet *ifp = sc->sc_ifp; 427108964Stmm int i; 428108964Stmm 429194886Smarius ether_ifdetach(ifp); 430148369Smarius GEM_LOCK(sc); 431147317Sbrooks gem_stop(ifp, 1); 432148369Smarius GEM_UNLOCK(sc); 433150285Smarius callout_drain(&sc->sc_tick_ch); 434150285Smarius#ifdef GEM_RINT_TIMEOUT 435150285Smarius callout_drain(&sc->sc_rx_ch); 436150285Smarius#endif 437147256Sbrooks if_free(ifp); 438108964Stmm device_delete_child(sc->sc_dev, sc->sc_miibus); 439108964Stmm 440174987Smarius for (i = 0; i < GEM_NRXDESC; i++) 441108964Stmm if (sc->sc_rxsoft[i].rxs_dmamap != NULL) 442108964Stmm bus_dmamap_destroy(sc->sc_rdmatag, 443108964Stmm sc->sc_rxsoft[i].rxs_dmamap); 444174987Smarius for (i = 0; i < GEM_TXQUEUELEN; i++) 445108964Stmm if (sc->sc_txsoft[i].txs_dmamap != NULL) 446108964Stmm bus_dmamap_destroy(sc->sc_tdmatag, 447108964Stmm sc->sc_txsoft[i].txs_dmamap); 448179925Smarius GEM_CDSYNC(sc, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 449108964Stmm bus_dmamap_unload(sc->sc_cdmatag, sc->sc_cddmamap); 450108964Stmm bus_dmamem_free(sc->sc_cdmatag, sc->sc_control_data, 451108964Stmm sc->sc_cddmamap); 452108964Stmm bus_dma_tag_destroy(sc->sc_cdmatag); 453108964Stmm bus_dma_tag_destroy(sc->sc_tdmatag); 454108964Stmm bus_dma_tag_destroy(sc->sc_rdmatag); 455108964Stmm bus_dma_tag_destroy(sc->sc_pdmatag); 456108964Stmm} 457108964Stmm 458108964Stmmvoid 459174987Smariusgem_suspend(struct gem_softc *sc) 460108964Stmm{ 461147256Sbrooks struct ifnet *ifp = sc->sc_ifp; 462108964Stmm 463148369Smarius GEM_LOCK(sc); 464108964Stmm gem_stop(ifp, 0); 465148369Smarius GEM_UNLOCK(sc); 466108964Stmm} 467108964Stmm 468108964Stmmvoid 469174987Smariusgem_resume(struct gem_softc *sc) 470108964Stmm{ 471147256Sbrooks struct ifnet *ifp = sc->sc_ifp; 472108964Stmm 473148369Smarius GEM_LOCK(sc); 474149552Smarius /* 475149552Smarius * On resume all registers have to be initialized again like 476149552Smarius * after power-on. 477149552Smarius */ 478172334Smarius sc->sc_flags &= ~GEM_INITED; 479108964Stmm if (ifp->if_flags & IFF_UP) 480148369Smarius gem_init_locked(sc); 481148369Smarius GEM_UNLOCK(sc); 482108964Stmm} 483108964Stmm 484194763Smariusstatic inline void 485170273Syongarigem_rxcksum(struct mbuf *m, uint64_t flags) 486170273Syongari{ 487170273Syongari struct ether_header *eh; 488170273Syongari struct ip *ip; 489170273Syongari struct udphdr *uh; 490174987Smarius uint16_t *opts; 491170273Syongari int32_t hlen, len, pktlen; 492170273Syongari uint32_t temp32; 493174987Smarius uint16_t cksum; 494170273Syongari 495170273Syongari pktlen = m->m_pkthdr.len; 496170273Syongari if (pktlen < sizeof(struct ether_header) + sizeof(struct ip)) 497170273Syongari return; 498170273Syongari eh = mtod(m, struct ether_header *); 499170273Syongari if (eh->ether_type != htons(ETHERTYPE_IP)) 500170273Syongari return; 501170273Syongari ip = (struct ip *)(eh + 1); 502170273Syongari if (ip->ip_v != IPVERSION) 503170273Syongari return; 504170273Syongari 505170273Syongari hlen = ip->ip_hl << 2; 506170273Syongari pktlen -= sizeof(struct ether_header); 507170273Syongari if (hlen < sizeof(struct ip)) 508170273Syongari return; 509170273Syongari if (ntohs(ip->ip_len) < hlen) 510170273Syongari return; 511170273Syongari if (ntohs(ip->ip_len) != pktlen) 512170273Syongari return; 513170273Syongari if (ip->ip_off & htons(IP_MF | IP_OFFMASK)) 514174987Smarius return; /* Cannot handle fragmented packet. */ 515170273Syongari 516170273Syongari switch (ip->ip_p) { 517170273Syongari case IPPROTO_TCP: 518170273Syongari if (pktlen < (hlen + sizeof(struct tcphdr))) 519170273Syongari return; 520170273Syongari break; 521170273Syongari case IPPROTO_UDP: 522170273Syongari if (pktlen < (hlen + sizeof(struct udphdr))) 523170273Syongari return; 524170273Syongari uh = (struct udphdr *)((uint8_t *)ip + hlen); 525170273Syongari if (uh->uh_sum == 0) 526170273Syongari return; /* no checksum */ 527170273Syongari break; 528170273Syongari default: 529170273Syongari return; 530170273Syongari } 531170273Syongari 532170273Syongari cksum = ~(flags & GEM_RD_CHECKSUM); 533170273Syongari /* checksum fixup for IP options */ 534170273Syongari len = hlen - sizeof(struct ip); 535170273Syongari if (len > 0) { 536170273Syongari opts = (uint16_t *)(ip + 1); 537170273Syongari for (; len > 0; len -= sizeof(uint16_t), opts++) { 538170273Syongari temp32 = cksum - *opts; 539170273Syongari temp32 = (temp32 >> 16) + (temp32 & 65535); 540170273Syongari cksum = temp32 & 65535; 541170273Syongari } 542170273Syongari } 543170273Syongari m->m_pkthdr.csum_flags |= CSUM_DATA_VALID; 544170273Syongari m->m_pkthdr.csum_data = cksum; 545170273Syongari} 546170273Syongari 54791398Stmmstatic void 548174987Smariusgem_cddma_callback(void *xsc, bus_dma_segment_t *segs, int nsegs, int error) 54991398Stmm{ 550174987Smarius struct gem_softc *sc = xsc; 55191398Stmm 55291398Stmm if (error != 0) 55391398Stmm return; 554174987Smarius if (nsegs != 1) 555172334Smarius panic("%s: bad control buffer segment count", __func__); 55691398Stmm sc->sc_cddma = segs[0].ds_addr; 55791398Stmm} 55891398Stmm 55991398Stmmstatic void 560174987Smariusgem_tick(void *arg) 56191398Stmm{ 562170273Syongari struct gem_softc *sc = arg; 563194763Smarius struct ifnet *ifp = sc->sc_ifp; 564182060Smarius uint32_t v; 56591398Stmm 566170273Syongari GEM_LOCK_ASSERT(sc, MA_OWNED); 567170273Syongari 568108832Stmm /* 569182060Smarius * Unload collision and error counters. 570108832Stmm */ 571271811Sglebius if_inc_counter(ifp, IFCOUNTER_COLLISIONS, 572177560Smarius GEM_BANK1_READ_4(sc, GEM_MAC_NORM_COLL_CNT) + 573271811Sglebius GEM_BANK1_READ_4(sc, GEM_MAC_FIRST_COLL_CNT)); 574182060Smarius v = GEM_BANK1_READ_4(sc, GEM_MAC_EXCESS_COLL_CNT) + 575177560Smarius GEM_BANK1_READ_4(sc, GEM_MAC_LATE_COLL_CNT); 576271811Sglebius if_inc_counter(ifp, IFCOUNTER_COLLISIONS, v); 577271811Sglebius if_inc_counter(ifp, IFCOUNTER_OERRORS, v); 578271811Sglebius if_inc_counter(ifp, IFCOUNTER_IERRORS, 579182060Smarius GEM_BANK1_READ_4(sc, GEM_MAC_RX_LEN_ERR_CNT) + 580182060Smarius GEM_BANK1_READ_4(sc, GEM_MAC_RX_ALIGN_ERR) + 581182060Smarius GEM_BANK1_READ_4(sc, GEM_MAC_RX_CRC_ERR_CNT) + 582271811Sglebius GEM_BANK1_READ_4(sc, GEM_MAC_RX_CODE_VIOL)); 58391398Stmm 58491398Stmm /* 585176996Smarius * Then clear the hardware counters. 58691398Stmm */ 587177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_NORM_COLL_CNT, 0); 588177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_FIRST_COLL_CNT, 0); 589177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_EXCESS_COLL_CNT, 0); 590177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_LATE_COLL_CNT, 0); 591182060Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_LEN_ERR_CNT, 0); 592182060Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_ALIGN_ERR, 0); 593182060Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_CRC_ERR_CNT, 0); 594182060Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_CODE_VIOL, 0); 595108832Stmm 59691398Stmm mii_tick(sc->sc_mii); 59791398Stmm 598164931Smarius if (gem_watchdog(sc) == EJUSTRETURN) 599164931Smarius return; 600164931Smarius 60191398Stmm callout_reset(&sc->sc_tick_ch, hz, gem_tick, sc); 60291398Stmm} 60391398Stmm 60491398Stmmstatic int 605177560Smariusgem_bitwait(struct gem_softc *sc, u_int bank, bus_addr_t r, uint32_t clr, 606177560Smarius uint32_t set) 60791398Stmm{ 60891398Stmm int i; 609174987Smarius uint32_t reg; 61091398Stmm 611194763Smarius for (i = GEM_TRIES; i--; DELAY(100)) { 612177560Smarius reg = GEM_BANKN_READ_M(bank, 4, sc, r); 613170847Smarius if ((reg & clr) == 0 && (reg & set) == set) 61491398Stmm return (1); 61591398Stmm } 61691398Stmm return (0); 61791398Stmm} 61891398Stmm 619172334Smariusstatic void 620194763Smariusgem_reset(struct gem_softc *sc) 62191398Stmm{ 62291398Stmm 623115030Stmm#ifdef GEM_DEBUG 624170273Syongari CTR2(KTR_GEM, "%s: %s", device_get_name(sc->sc_dev), __func__); 625115030Stmm#endif 62691398Stmm gem_reset_rx(sc); 62791398Stmm gem_reset_tx(sc); 62891398Stmm 629174987Smarius /* Do a full reset. */ 630223944Smarius GEM_BANK2_WRITE_4(sc, GEM_RESET, GEM_RESET_RX | GEM_RESET_TX | 631223944Smarius (sc->sc_variant == GEM_SUN_ERI ? GEM_ERI_CACHE_LINE_SIZE << 632223944Smarius GEM_RESET_CLSZ_SHFT : 0)); 633179925Smarius GEM_BANK2_BARRIER(sc, GEM_RESET, 4, 634179925Smarius BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 635177560Smarius if (!GEM_BANK2_BITWAIT(sc, GEM_RESET, GEM_RESET_RX | GEM_RESET_TX, 0)) 63691398Stmm device_printf(sc->sc_dev, "cannot reset device\n"); 63791398Stmm} 63891398Stmm 63991398Stmmstatic void 640174987Smariusgem_rxdrain(struct gem_softc *sc) 64191398Stmm{ 64291398Stmm struct gem_rxsoft *rxs; 64391398Stmm int i; 64491398Stmm 64591398Stmm for (i = 0; i < GEM_NRXDESC; i++) { 64691398Stmm rxs = &sc->sc_rxsoft[i]; 64791398Stmm if (rxs->rxs_mbuf != NULL) { 648109648Stmm bus_dmamap_sync(sc->sc_rdmatag, rxs->rxs_dmamap, 649109648Stmm BUS_DMASYNC_POSTREAD); 650108832Stmm bus_dmamap_unload(sc->sc_rdmatag, rxs->rxs_dmamap); 65191398Stmm m_freem(rxs->rxs_mbuf); 65291398Stmm rxs->rxs_mbuf = NULL; 65391398Stmm } 65491398Stmm } 65591398Stmm} 65691398Stmm 65791398Stmmstatic void 658174987Smariusgem_stop(struct ifnet *ifp, int disable) 65991398Stmm{ 660174987Smarius struct gem_softc *sc = ifp->if_softc; 66191398Stmm struct gem_txsoft *txs; 66291398Stmm 663115030Stmm#ifdef GEM_DEBUG 664170273Syongari CTR2(KTR_GEM, "%s: %s", device_get_name(sc->sc_dev), __func__); 665115030Stmm#endif 66691398Stmm 66791398Stmm callout_stop(&sc->sc_tick_ch); 668150285Smarius#ifdef GEM_RINT_TIMEOUT 669150285Smarius callout_stop(&sc->sc_rx_ch); 670172334Smarius#endif 67191398Stmm 672194763Smarius gem_reset_tx(sc); 673194763Smarius gem_reset_rx(sc); 67491398Stmm 67591398Stmm /* 67691398Stmm * Release any queued transmit buffers. 67791398Stmm */ 67891398Stmm while ((txs = STAILQ_FIRST(&sc->sc_txdirtyq)) != NULL) { 67991398Stmm STAILQ_REMOVE_HEAD(&sc->sc_txdirtyq, txs_q); 68091398Stmm if (txs->txs_ndescs != 0) { 681109648Stmm bus_dmamap_sync(sc->sc_tdmatag, txs->txs_dmamap, 682109648Stmm BUS_DMASYNC_POSTWRITE); 683108832Stmm bus_dmamap_unload(sc->sc_tdmatag, txs->txs_dmamap); 68491398Stmm if (txs->txs_mbuf != NULL) { 68591398Stmm m_freem(txs->txs_mbuf); 68691398Stmm txs->txs_mbuf = NULL; 68791398Stmm } 68891398Stmm } 68991398Stmm STAILQ_INSERT_TAIL(&sc->sc_txfreeq, txs, txs_q); 69091398Stmm } 69191398Stmm 69291398Stmm if (disable) 69391398Stmm gem_rxdrain(sc); 69491398Stmm 69591398Stmm /* 69691398Stmm * Mark the interface down and cancel the watchdog timer. 69791398Stmm */ 698148887Srwatson ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); 699172334Smarius sc->sc_flags &= ~GEM_LINK; 700164931Smarius sc->sc_wdog_timer = 0; 70191398Stmm} 70291398Stmm 703172334Smariusstatic int 704174987Smariusgem_reset_rx(struct gem_softc *sc) 70591398Stmm{ 70691398Stmm 70791398Stmm /* 70891398Stmm * Resetting while DMA is in progress can cause a bus hang, so we 70991398Stmm * disable DMA first. 71091398Stmm */ 711223648Smarius (void)gem_disable_rx(sc); 712177560Smarius GEM_BANK1_WRITE_4(sc, GEM_RX_CONFIG, 0); 713179925Smarius GEM_BANK1_BARRIER(sc, GEM_RX_CONFIG, 4, 714179925Smarius BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 715177560Smarius if (!GEM_BANK1_BITWAIT(sc, GEM_RX_CONFIG, GEM_RX_CONFIG_RXDMA_EN, 0)) 716172334Smarius device_printf(sc->sc_dev, "cannot disable RX DMA\n"); 71791398Stmm 718215722Smarius /* Wait 5ms extra. */ 719215722Smarius DELAY(5000); 720215722Smarius 721223648Smarius /* Reset the ERX. */ 722223944Smarius GEM_BANK2_WRITE_4(sc, GEM_RESET, GEM_RESET_RX | 723223944Smarius (sc->sc_variant == GEM_SUN_ERI ? GEM_ERI_CACHE_LINE_SIZE << 724223944Smarius GEM_RESET_CLSZ_SHFT : 0)); 725179925Smarius GEM_BANK2_BARRIER(sc, GEM_RESET, 4, 726179925Smarius BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 727223944Smarius if (!GEM_BANK2_BITWAIT(sc, GEM_RESET, GEM_RESET_RX, 0)) { 72891398Stmm device_printf(sc->sc_dev, "cannot reset receiver\n"); 72991398Stmm return (1); 73091398Stmm } 731223648Smarius 732223648Smarius /* Finally, reset RX MAC. */ 733223648Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_RXRESET, 1); 734223648Smarius GEM_BANK1_BARRIER(sc, GEM_MAC_RXRESET, 4, 735223648Smarius BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 736223648Smarius if (!GEM_BANK1_BITWAIT(sc, GEM_MAC_RXRESET, 1, 0)) { 737223648Smarius device_printf(sc->sc_dev, "cannot reset RX MAC\n"); 738223648Smarius return (1); 739223648Smarius } 740223648Smarius 74191398Stmm return (0); 74291398Stmm} 74391398Stmm 744172334Smarius/* 745172334Smarius * Reset the receiver DMA engine. 746172334Smarius * 747172334Smarius * Intended to be used in case of GEM_INTR_RX_TAG_ERR, GEM_MAC_RX_OVERFLOW 748172334Smarius * etc in order to reset the receiver DMA engine only and not do a full 749172334Smarius * reset which amongst others also downs the link and clears the FIFOs. 750172334Smarius */ 751172334Smariusstatic void 752172334Smariusgem_reset_rxdma(struct gem_softc *sc) 753172334Smarius{ 754172334Smarius int i; 75591398Stmm 756222135Syongari if (gem_reset_rx(sc) != 0) { 757222135Syongari sc->sc_ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 758172334Smarius return (gem_init_locked(sc)); 759222135Syongari } 760172334Smarius for (i = 0; i < GEM_NRXDESC; i++) 761172334Smarius if (sc->sc_rxsoft[i].rxs_mbuf != NULL) 762172334Smarius GEM_UPDATE_RXDESC(sc, i); 763172334Smarius sc->sc_rxptr = 0; 764194763Smarius GEM_CDSYNC(sc, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 765172334Smarius 766172334Smarius /* NOTE: we use only 32-bit DMA addresses here. */ 767177560Smarius GEM_BANK1_WRITE_4(sc, GEM_RX_RING_PTR_HI, 0); 768177560Smarius GEM_BANK1_WRITE_4(sc, GEM_RX_RING_PTR_LO, GEM_CDRXADDR(sc, 0)); 769177560Smarius GEM_BANK1_WRITE_4(sc, GEM_RX_KICK, GEM_NRXDESC - 4); 770177560Smarius GEM_BANK1_WRITE_4(sc, GEM_RX_CONFIG, 771174987Smarius gem_ringsize(GEM_NRXDESC /* XXX */) | 772172334Smarius ((ETHER_HDR_LEN + sizeof(struct ip)) << 773172334Smarius GEM_RX_CONFIG_CXM_START_SHFT) | 774172334Smarius (GEM_THRSH_1024 << GEM_RX_CONFIG_FIFO_THRS_SHIFT) | 775194763Smarius (ETHER_ALIGN << GEM_RX_CONFIG_FBOFF_SHFT)); 776223949Smarius /* Adjusting for the SBus clock probably isn't worth the fuzz. */ 777177560Smarius GEM_BANK1_WRITE_4(sc, GEM_RX_BLANKING, 778194763Smarius ((6 * (sc->sc_flags & GEM_PCI66) != 0 ? 2 : 1) << 779194763Smarius GEM_RX_BLANKING_TIME_SHIFT) | 6); 780177560Smarius GEM_BANK1_WRITE_4(sc, GEM_RX_PAUSE_THRESH, 781174987Smarius (3 * sc->sc_rxfifosize / 256) | 782174987Smarius ((sc->sc_rxfifosize / 256) << 12)); 783177560Smarius GEM_BANK1_WRITE_4(sc, GEM_RX_CONFIG, 784177560Smarius GEM_BANK1_READ_4(sc, GEM_RX_CONFIG) | GEM_RX_CONFIG_RXDMA_EN); 785177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_MASK, 786172334Smarius GEM_MAC_RX_DONE | GEM_MAC_RX_FRAME_CNT); 787223949Smarius /* 788223949Smarius * Clear the RX filter and reprogram it. This will also set the 789223949Smarius * current RX MAC configuration and enable it. 790223949Smarius */ 791223949Smarius gem_setladrf(sc); 792172334Smarius} 793172334Smarius 79491398Stmmstatic int 795174987Smariusgem_reset_tx(struct gem_softc *sc) 79691398Stmm{ 79791398Stmm 79891398Stmm /* 79991398Stmm * Resetting while DMA is in progress can cause a bus hang, so we 80091398Stmm * disable DMA first. 80191398Stmm */ 802223648Smarius (void)gem_disable_tx(sc); 803177560Smarius GEM_BANK1_WRITE_4(sc, GEM_TX_CONFIG, 0); 804179925Smarius GEM_BANK1_BARRIER(sc, GEM_TX_CONFIG, 4, 805179925Smarius BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 806177560Smarius if (!GEM_BANK1_BITWAIT(sc, GEM_TX_CONFIG, GEM_TX_CONFIG_TXDMA_EN, 0)) 807172334Smarius device_printf(sc->sc_dev, "cannot disable TX DMA\n"); 80891398Stmm 809215722Smarius /* Wait 5ms extra. */ 810215722Smarius DELAY(5000); 811215722Smarius 812176996Smarius /* Finally, reset the ETX. */ 813223944Smarius GEM_BANK2_WRITE_4(sc, GEM_RESET, GEM_RESET_TX | 814223944Smarius (sc->sc_variant == GEM_SUN_ERI ? GEM_ERI_CACHE_LINE_SIZE << 815223944Smarius GEM_RESET_CLSZ_SHFT : 0)); 816179925Smarius GEM_BANK2_BARRIER(sc, GEM_RESET, 4, 817179925Smarius BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 818223944Smarius if (!GEM_BANK2_BITWAIT(sc, GEM_RESET, GEM_RESET_TX, 0)) { 819172334Smarius device_printf(sc->sc_dev, "cannot reset transmitter\n"); 82091398Stmm return (1); 82191398Stmm } 82291398Stmm return (0); 82391398Stmm} 82491398Stmm 82591398Stmmstatic int 826174987Smariusgem_disable_rx(struct gem_softc *sc) 82791398Stmm{ 82891398Stmm 829177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_CONFIG, 830177560Smarius GEM_BANK1_READ_4(sc, GEM_MAC_RX_CONFIG) & ~GEM_MAC_RX_ENABLE); 831179925Smarius GEM_BANK1_BARRIER(sc, GEM_MAC_RX_CONFIG, 4, 832179925Smarius BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 833223648Smarius if (GEM_BANK1_BITWAIT(sc, GEM_MAC_RX_CONFIG, GEM_MAC_RX_ENABLE, 0)) 834223648Smarius return (1); 835223648Smarius device_printf(sc->sc_dev, "cannot disable RX MAC\n"); 836223648Smarius return (0); 83791398Stmm} 83891398Stmm 83991398Stmmstatic int 840174987Smariusgem_disable_tx(struct gem_softc *sc) 84191398Stmm{ 84291398Stmm 843177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_TX_CONFIG, 844177560Smarius GEM_BANK1_READ_4(sc, GEM_MAC_TX_CONFIG) & ~GEM_MAC_TX_ENABLE); 845179925Smarius GEM_BANK1_BARRIER(sc, GEM_MAC_TX_CONFIG, 4, 846179925Smarius BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 847223648Smarius if (GEM_BANK1_BITWAIT(sc, GEM_MAC_TX_CONFIG, GEM_MAC_TX_ENABLE, 0)) 848223648Smarius return (1); 849223648Smarius device_printf(sc->sc_dev, "cannot disable TX MAC\n"); 850223648Smarius return (0); 85191398Stmm} 85291398Stmm 85391398Stmmstatic int 854194763Smariusgem_meminit(struct gem_softc *sc) 85591398Stmm{ 85691398Stmm struct gem_rxsoft *rxs; 857174987Smarius int error, i; 85891398Stmm 859194763Smarius GEM_LOCK_ASSERT(sc, MA_OWNED); 860194763Smarius 86191398Stmm /* 86291398Stmm * Initialize the transmit descriptor ring. 86391398Stmm */ 86491398Stmm for (i = 0; i < GEM_NTXDESC; i++) { 86591398Stmm sc->sc_txdescs[i].gd_flags = 0; 86691398Stmm sc->sc_txdescs[i].gd_addr = 0; 86791398Stmm } 868108832Stmm sc->sc_txfree = GEM_MAXTXFREE; 86991398Stmm sc->sc_txnext = 0; 87099726Sbenno sc->sc_txwin = 0; 87191398Stmm 87291398Stmm /* 87391398Stmm * Initialize the receive descriptor and receive job 87491398Stmm * descriptor rings. 87591398Stmm */ 87691398Stmm for (i = 0; i < GEM_NRXDESC; i++) { 87791398Stmm rxs = &sc->sc_rxsoft[i]; 87891398Stmm if (rxs->rxs_mbuf == NULL) { 87991398Stmm if ((error = gem_add_rxbuf(sc, i)) != 0) { 880174987Smarius device_printf(sc->sc_dev, 881174987Smarius "unable to allocate or map RX buffer %d, " 882174987Smarius "error = %d\n", i, error); 88391398Stmm /* 884174987Smarius * XXX we should attempt to run with fewer 885174987Smarius * receive buffers instead of just failing. 88691398Stmm */ 88791398Stmm gem_rxdrain(sc); 88891398Stmm return (1); 88991398Stmm } 89091398Stmm } else 89191398Stmm GEM_INIT_RXDESC(sc, i); 89291398Stmm } 89391398Stmm sc->sc_rxptr = 0; 89491398Stmm 895194763Smarius GEM_CDSYNC(sc, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 896194763Smarius 89791398Stmm return (0); 89891398Stmm} 89991398Stmm 900172334Smariusstatic u_int 901174987Smariusgem_ringsize(u_int sz) 90291398Stmm{ 90391398Stmm 90491398Stmm switch (sz) { 90591398Stmm case 32: 906172334Smarius return (GEM_RING_SZ_32); 90791398Stmm case 64: 908172334Smarius return (GEM_RING_SZ_64); 90991398Stmm case 128: 910172334Smarius return (GEM_RING_SZ_128); 91191398Stmm case 256: 912172334Smarius return (GEM_RING_SZ_256); 91391398Stmm case 512: 914172334Smarius return (GEM_RING_SZ_512); 91591398Stmm case 1024: 916172334Smarius return (GEM_RING_SZ_1024); 91791398Stmm case 2048: 918172334Smarius return (GEM_RING_SZ_2048); 91991398Stmm case 4096: 920172334Smarius return (GEM_RING_SZ_4096); 92191398Stmm case 8192: 922172334Smarius return (GEM_RING_SZ_8192); 92391398Stmm default: 924172334Smarius printf("%s: invalid ring size %d\n", __func__, sz); 925172334Smarius return (GEM_RING_SZ_32); 92691398Stmm } 92791398Stmm} 92891398Stmm 929148369Smariusstatic void 930174987Smariusgem_init(void *xsc) 931148369Smarius{ 932174987Smarius struct gem_softc *sc = xsc; 933148369Smarius 934148369Smarius GEM_LOCK(sc); 935148369Smarius gem_init_locked(sc); 936148369Smarius GEM_UNLOCK(sc); 937148369Smarius} 938148369Smarius 93991398Stmm/* 94091398Stmm * Initialization of interface; set up initialization block 94191398Stmm * and transmit/receive descriptor rings. 94291398Stmm */ 94391398Stmmstatic void 944174987Smariusgem_init_locked(struct gem_softc *sc) 94591398Stmm{ 946147256Sbrooks struct ifnet *ifp = sc->sc_ifp; 947174987Smarius uint32_t v; 94891398Stmm 949148369Smarius GEM_LOCK_ASSERT(sc, MA_OWNED); 95091398Stmm 951222135Syongari if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) 952222135Syongari return; 953222135Syongari 954115030Stmm#ifdef GEM_DEBUG 955170273Syongari CTR2(KTR_GEM, "%s: %s: calling stop", device_get_name(sc->sc_dev), 956170273Syongari __func__); 957115030Stmm#endif 95891398Stmm /* 959174987Smarius * Initialization sequence. The numbered steps below correspond 96091398Stmm * to the sequence outlined in section 6.3.5.1 in the Ethernet 96191398Stmm * Channel Engine manual (part of the PCIO manual). 96291398Stmm * See also the STP2002-STQ document from Sun Microsystems. 96391398Stmm */ 96491398Stmm 965174987Smarius /* step 1 & 2. Reset the Ethernet Channel. */ 966179925Smarius gem_stop(ifp, 0); 96791398Stmm gem_reset(sc); 968115030Stmm#ifdef GEM_DEBUG 969170273Syongari CTR2(KTR_GEM, "%s: %s: restarting", device_get_name(sc->sc_dev), 970170273Syongari __func__); 971115030Stmm#endif 97291398Stmm 973212725Smarius if ((sc->sc_flags & GEM_SERDES) == 0) 974212725Smarius /* Re-initialize the MIF. */ 975212725Smarius gem_mifinit(sc); 97691398Stmm 977174987Smarius /* step 3. Setup data structures in host memory. */ 978172334Smarius if (gem_meminit(sc) != 0) 979172334Smarius return; 98091398Stmm 981174987Smarius /* step 4. TX MAC registers & counters */ 98291398Stmm gem_init_regs(sc); 98391398Stmm 984174987Smarius /* step 5. RX MAC registers & counters */ 98591398Stmm 986174987Smarius /* step 6 & 7. Program Descriptor Ring Base Addresses. */ 98791398Stmm /* NOTE: we use only 32-bit DMA addresses here. */ 988177560Smarius GEM_BANK1_WRITE_4(sc, GEM_TX_RING_PTR_HI, 0); 989177560Smarius GEM_BANK1_WRITE_4(sc, GEM_TX_RING_PTR_LO, GEM_CDTXADDR(sc, 0)); 99091398Stmm 991177560Smarius GEM_BANK1_WRITE_4(sc, GEM_RX_RING_PTR_HI, 0); 992177560Smarius GEM_BANK1_WRITE_4(sc, GEM_RX_RING_PTR_LO, GEM_CDRXADDR(sc, 0)); 993115030Stmm#ifdef GEM_DEBUG 994174987Smarius CTR3(KTR_GEM, "loading RX ring %lx, TX ring %lx, cddma %lx", 99591398Stmm GEM_CDRXADDR(sc, 0), GEM_CDTXADDR(sc, 0), sc->sc_cddma); 996115030Stmm#endif 99791398Stmm 998174987Smarius /* step 8. Global Configuration & Interrupt Mask */ 999194763Smarius 1000194763Smarius /* 1001194763Smarius * Set the internal arbitration to "infinite" bursts of the 1002194763Smarius * maximum length of 31 * 64 bytes so DMA transfers aren't 1003194763Smarius * split up in cache line size chunks. This greatly improves 1004194763Smarius * RX performance. 1005194763Smarius * Enable silicon bug workarounds for the Apple variants. 1006194763Smarius */ 1007194763Smarius GEM_BANK1_WRITE_4(sc, GEM_CONFIG, 1008194763Smarius GEM_CONFIG_TXDMA_LIMIT | GEM_CONFIG_RXDMA_LIMIT | 1009194763Smarius ((sc->sc_flags & GEM_PCI) != 0 ? GEM_CONFIG_BURST_INF : 1010194763Smarius GEM_CONFIG_BURST_64) | (GEM_IS_APPLE(sc) ? 1011194763Smarius GEM_CONFIG_RONPAULBIT | GEM_CONFIG_BUG2FIX : 0)); 1012194763Smarius 1013177560Smarius GEM_BANK1_WRITE_4(sc, GEM_INTMASK, 1014172334Smarius ~(GEM_INTR_TX_INTME | GEM_INTR_TX_EMPTY | GEM_INTR_RX_DONE | 1015172334Smarius GEM_INTR_RX_NOBUF | GEM_INTR_RX_TAG_ERR | GEM_INTR_PERR | 1016172334Smarius GEM_INTR_BERR 1017172334Smarius#ifdef GEM_DEBUG 1018172334Smarius | GEM_INTR_PCS | GEM_INTR_MIF 1019172334Smarius#endif 1020172334Smarius )); 1021177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_MASK, 1022172334Smarius GEM_MAC_RX_DONE | GEM_MAC_RX_FRAME_CNT); 1023177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_TX_MASK, 1024194763Smarius GEM_MAC_TX_XMIT_DONE | GEM_MAC_TX_DEFER_EXP | 1025194763Smarius GEM_MAC_TX_PEAK_EXP); 1026172334Smarius#ifdef GEM_DEBUG 1027177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_CONTROL_MASK, 1028172334Smarius ~(GEM_MAC_PAUSED | GEM_MAC_PAUSE | GEM_MAC_RESUME)); 1029172334Smarius#else 1030177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_CONTROL_MASK, 1031172334Smarius GEM_MAC_PAUSED | GEM_MAC_PAUSE | GEM_MAC_RESUME); 1032172334Smarius#endif 103391398Stmm 1034174987Smarius /* step 9. ETX Configuration: use mostly default values. */ 103591398Stmm 1036174987Smarius /* Enable DMA. */ 1037194763Smarius v = gem_ringsize(GEM_NTXDESC); 1038194763Smarius /* Set TX FIFO threshold and enable DMA. */ 1039179925Smarius v |= ((sc->sc_variant == GEM_SUN_ERI ? 0x100 : 0x4ff) << 10) & 1040179925Smarius GEM_TX_CONFIG_TXFIFO_TH; 1041179925Smarius GEM_BANK1_WRITE_4(sc, GEM_TX_CONFIG, v | GEM_TX_CONFIG_TXDMA_EN); 104291398Stmm 1043174987Smarius /* step 10. ERX Configuration */ 104491398Stmm 1045172334Smarius /* Encode Receive Descriptor ring size. */ 1046174987Smarius v = gem_ringsize(GEM_NRXDESC /* XXX */); 1047174987Smarius /* RX TCP/UDP checksum offset */ 1048170273Syongari v |= ((ETHER_HDR_LEN + sizeof(struct ip)) << 1049170273Syongari GEM_RX_CONFIG_CXM_START_SHFT); 1050194763Smarius /* Set RX FIFO threshold, set first byte offset and enable DMA. */ 1051177560Smarius GEM_BANK1_WRITE_4(sc, GEM_RX_CONFIG, 1052174987Smarius v | (GEM_THRSH_1024 << GEM_RX_CONFIG_FIFO_THRS_SHIFT) | 1053194763Smarius (ETHER_ALIGN << GEM_RX_CONFIG_FBOFF_SHFT) | 1054194763Smarius GEM_RX_CONFIG_RXDMA_EN); 1055172334Smarius 1056223949Smarius /* Adjusting for the SBus clock probably isn't worth the fuzz. */ 1057177560Smarius GEM_BANK1_WRITE_4(sc, GEM_RX_BLANKING, 1058194763Smarius ((6 * (sc->sc_flags & GEM_PCI66) != 0 ? 2 : 1) << 1059194763Smarius GEM_RX_BLANKING_TIME_SHIFT) | 6); 1060172334Smarius 106191398Stmm /* 106299726Sbenno * The following value is for an OFF Threshold of about 3/4 full 106399726Sbenno * and an ON Threshold of 1/4 full. 106491398Stmm */ 1065177560Smarius GEM_BANK1_WRITE_4(sc, GEM_RX_PAUSE_THRESH, 106699726Sbenno (3 * sc->sc_rxfifosize / 256) | 1067174987Smarius ((sc->sc_rxfifosize / 256) << 12)); 106891398Stmm 1069174987Smarius /* step 11. Configure Media. */ 107091398Stmm 1071174987Smarius /* step 12. RX_MAC Configuration Register */ 1072177560Smarius v = GEM_BANK1_READ_4(sc, GEM_MAC_RX_CONFIG); 1073223949Smarius v &= ~GEM_MAC_RX_ENABLE; 1074223949Smarius v |= GEM_MAC_RX_STRIP_CRC; 1075223949Smarius sc->sc_mac_rxcfg = v; 1076223949Smarius /* 1077223949Smarius * Clear the RX filter and reprogram it. This will also set the 1078223949Smarius * current RX MAC configuration and enable it. 1079223949Smarius */ 1080223949Smarius gem_setladrf(sc); 108191398Stmm 1082194763Smarius /* step 13. TX_MAC Configuration Register */ 1083179925Smarius v = GEM_BANK1_READ_4(sc, GEM_MAC_TX_CONFIG); 1084179925Smarius v |= GEM_MAC_TX_ENABLE; 1085223648Smarius (void)gem_disable_tx(sc); 1086179925Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_TX_CONFIG, v); 1087179925Smarius 1088174987Smarius /* step 14. Issue Transmit Pending command. */ 108991398Stmm 1090220941Smarius /* step 15. Give the receiver a swift kick. */ 1091177560Smarius GEM_BANK1_WRITE_4(sc, GEM_RX_KICK, GEM_NRXDESC - 4); 109291398Stmm 1093172334Smarius ifp->if_drv_flags |= IFF_DRV_RUNNING; 1094172334Smarius ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 1095172334Smarius 1096172334Smarius mii_mediachg(sc->sc_mii); 1097172334Smarius 109891398Stmm /* Start the one second timer. */ 1099164931Smarius sc->sc_wdog_timer = 0; 110091398Stmm callout_reset(&sc->sc_tick_ch, hz, gem_tick, sc); 110191398Stmm} 110291398Stmm 110391398Stmmstatic int 1104174987Smariusgem_load_txmbuf(struct gem_softc *sc, struct mbuf **m_head) 110591398Stmm{ 1106174987Smarius bus_dma_segment_t txsegs[GEM_NTXSEGS]; 110791398Stmm struct gem_txsoft *txs; 1108179925Smarius struct ip *ip; 1109170273Syongari struct mbuf *m; 1110174987Smarius uint64_t cflags, flags; 1111179925Smarius int error, nexttx, nsegs, offset, seg; 111291398Stmm 1113194763Smarius GEM_LOCK_ASSERT(sc, MA_OWNED); 1114194763Smarius 1115108832Stmm /* Get a work queue entry. */ 1116108832Stmm if ((txs = STAILQ_FIRST(&sc->sc_txfreeq)) == NULL) { 1117108832Stmm /* Ran out of descriptors. */ 1118170273Syongari return (ENOBUFS); 1119108832Stmm } 1120179925Smarius 1121179925Smarius cflags = 0; 1122179925Smarius if (((*m_head)->m_pkthdr.csum_flags & sc->sc_csum_features) != 0) { 1123179925Smarius if (M_WRITABLE(*m_head) == 0) { 1124243857Sglebius m = m_dup(*m_head, M_NOWAIT); 1125179925Smarius m_freem(*m_head); 1126179925Smarius *m_head = m; 1127179925Smarius if (m == NULL) 1128179925Smarius return (ENOBUFS); 1129179925Smarius } 1130179925Smarius offset = sizeof(struct ether_header); 1131179925Smarius m = m_pullup(*m_head, offset + sizeof(struct ip)); 1132179925Smarius if (m == NULL) { 1133179925Smarius *m_head = NULL; 1134179925Smarius return (ENOBUFS); 1135179925Smarius } 1136179925Smarius ip = (struct ip *)(mtod(m, caddr_t) + offset); 1137179925Smarius offset += (ip->ip_hl << 2); 1138179925Smarius cflags = offset << GEM_TD_CXSUM_STARTSHFT | 1139179925Smarius ((offset + m->m_pkthdr.csum_data) << 1140179925Smarius GEM_TD_CXSUM_STUFFSHFT) | GEM_TD_CXSUM_ENABLE; 1141179925Smarius *m_head = m; 1142179925Smarius } 1143179925Smarius 1144170273Syongari error = bus_dmamap_load_mbuf_sg(sc->sc_tdmatag, txs->txs_dmamap, 1145170273Syongari *m_head, txsegs, &nsegs, BUS_DMA_NOWAIT); 1146170273Syongari if (error == EFBIG) { 1147243857Sglebius m = m_collapse(*m_head, M_NOWAIT, GEM_NTXSEGS); 1148170273Syongari if (m == NULL) { 1149170273Syongari m_freem(*m_head); 1150170273Syongari *m_head = NULL; 1151170273Syongari return (ENOBUFS); 1152170273Syongari } 1153170273Syongari *m_head = m; 1154174987Smarius error = bus_dmamap_load_mbuf_sg(sc->sc_tdmatag, 1155174987Smarius txs->txs_dmamap, *m_head, txsegs, &nsegs, 1156174987Smarius BUS_DMA_NOWAIT); 1157170273Syongari if (error != 0) { 1158170273Syongari m_freem(*m_head); 1159170273Syongari *m_head = NULL; 1160170273Syongari return (error); 1161170273Syongari } 1162170273Syongari } else if (error != 0) 1163170273Syongari return (error); 1164176996Smarius /* If nsegs is wrong then the stack is corrupt. */ 1165176996Smarius KASSERT(nsegs <= GEM_NTXSEGS, 1166176996Smarius ("%s: too many DMA segments (%d)", __func__, nsegs)); 1167170273Syongari if (nsegs == 0) { 1168170273Syongari m_freem(*m_head); 1169170273Syongari *m_head = NULL; 1170170273Syongari return (EIO); 1171170273Syongari } 1172170273Syongari 1173170273Syongari /* 1174170273Syongari * Ensure we have enough descriptors free to describe 1175170273Syongari * the packet. Note, we always reserve one descriptor 1176174987Smarius * at the end of the ring as a termination point, in 1177174987Smarius * order to prevent wrap-around. 1178170273Syongari */ 1179170273Syongari if (nsegs > sc->sc_txfree - 1) { 1180170273Syongari txs->txs_ndescs = 0; 1181170273Syongari bus_dmamap_unload(sc->sc_tdmatag, txs->txs_dmamap); 1182170273Syongari return (ENOBUFS); 1183170273Syongari } 1184170273Syongari 1185170273Syongari txs->txs_ndescs = nsegs; 1186108832Stmm txs->txs_firstdesc = sc->sc_txnext; 1187170273Syongari nexttx = txs->txs_firstdesc; 1188170273Syongari for (seg = 0; seg < nsegs; seg++, nexttx = GEM_NEXTTX(nexttx)) { 1189172334Smarius#ifdef GEM_DEBUG 1190174987Smarius CTR6(KTR_GEM, 1191174987Smarius "%s: mapping seg %d (txd %d), len %lx, addr %#lx (%#lx)", 1192174987Smarius __func__, seg, nexttx, txsegs[seg].ds_len, 1193174987Smarius txsegs[seg].ds_addr, 1194170273Syongari GEM_DMA_WRITE(sc, txsegs[seg].ds_addr)); 1195170273Syongari#endif 1196170273Syongari sc->sc_txdescs[nexttx].gd_addr = 1197170273Syongari GEM_DMA_WRITE(sc, txsegs[seg].ds_addr); 1198170273Syongari KASSERT(txsegs[seg].ds_len < GEM_TD_BUFSIZE, 1199170273Syongari ("%s: segment size too large!", __func__)); 1200170273Syongari flags = txsegs[seg].ds_len & GEM_TD_BUFSIZE; 1201170273Syongari sc->sc_txdescs[nexttx].gd_flags = 1202170273Syongari GEM_DMA_WRITE(sc, flags | cflags); 1203170273Syongari txs->txs_lastdesc = nexttx; 120491398Stmm } 120591398Stmm 1206174987Smarius /* Set EOP on the last descriptor. */ 1207172334Smarius#ifdef GEM_DEBUG 1208174987Smarius CTR3(KTR_GEM, "%s: end of packet at segment %d, TX %d", 1209174987Smarius __func__, seg, nexttx); 1210170273Syongari#endif 1211170273Syongari sc->sc_txdescs[txs->txs_lastdesc].gd_flags |= 1212170273Syongari GEM_DMA_WRITE(sc, GEM_TD_END_OF_PACKET); 1213170273Syongari 1214174987Smarius /* Lastly set SOP on the first descriptor. */ 1215172334Smarius#ifdef GEM_DEBUG 1216174987Smarius CTR3(KTR_GEM, "%s: start of packet at segment %d, TX %d", 1217174987Smarius __func__, seg, nexttx); 1218170273Syongari#endif 1219170273Syongari if (++sc->sc_txwin > GEM_NTXSEGS * 2 / 3) { 1220170273Syongari sc->sc_txwin = 0; 1221170273Syongari sc->sc_txdescs[txs->txs_firstdesc].gd_flags |= 1222170273Syongari GEM_DMA_WRITE(sc, GEM_TD_INTERRUPT_ME | 1223170273Syongari GEM_TD_START_OF_PACKET); 1224170273Syongari } else 1225170273Syongari sc->sc_txdescs[txs->txs_firstdesc].gd_flags |= 1226170273Syongari GEM_DMA_WRITE(sc, GEM_TD_START_OF_PACKET); 1227170273Syongari 1228108832Stmm /* Sync the DMA map. */ 1229174987Smarius bus_dmamap_sync(sc->sc_tdmatag, txs->txs_dmamap, 1230174987Smarius BUS_DMASYNC_PREWRITE); 123191398Stmm 1232115030Stmm#ifdef GEM_DEBUG 1233170273Syongari CTR4(KTR_GEM, "%s: setting firstdesc=%d, lastdesc=%d, ndescs=%d", 1234174987Smarius __func__, txs->txs_firstdesc, txs->txs_lastdesc, 1235174987Smarius txs->txs_ndescs); 1236115030Stmm#endif 1237108832Stmm STAILQ_REMOVE_HEAD(&sc->sc_txfreeq, txs_q); 1238108832Stmm STAILQ_INSERT_TAIL(&sc->sc_txdirtyq, txs, txs_q); 1239170273Syongari txs->txs_mbuf = *m_head; 124091398Stmm 1241108832Stmm sc->sc_txnext = GEM_NEXTTX(txs->txs_lastdesc); 1242108832Stmm sc->sc_txfree -= txs->txs_ndescs; 1243170273Syongari 1244108832Stmm return (0); 124591398Stmm} 124691398Stmm 124791398Stmmstatic void 1248174987Smariusgem_init_regs(struct gem_softc *sc) 124991398Stmm{ 1250152315Sru const u_char *laddr = IF_LLADDR(sc->sc_ifp); 125191398Stmm 1252194763Smarius GEM_LOCK_ASSERT(sc, MA_OWNED); 1253194763Smarius 1254174987Smarius /* These registers are not cleared on reset. */ 1255172334Smarius if ((sc->sc_flags & GEM_INITED) == 0) { 1256174987Smarius /* magic values */ 1257177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_IPG0, 0); 1258177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_IPG1, 8); 1259177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_IPG2, 4); 126091398Stmm 1261194763Smarius /* min frame length */ 1262177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_MAC_MIN_FRAME, ETHER_MIN_LEN); 1263194763Smarius /* max frame length and max burst size */ 1264177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_MAC_MAX_FRAME, 1265172334Smarius (ETHER_MAX_LEN + ETHER_VLAN_ENCAP_LEN) | (0x2000 << 16)); 126699726Sbenno 1267194763Smarius /* more magic values */ 1268177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_PREAMBLE_LEN, 0x7); 1269177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_JAM_SIZE, 0x4); 1270177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_ATTEMPT_LIMIT, 0x10); 1271215722Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_CONTROL_TYPE, 0x8808); 1272194763Smarius 1273194763Smarius /* random number seed */ 1274177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_RANDOM_SEED, 1275174987Smarius ((laddr[5] << 8) | laddr[4]) & 0x3ff); 127699726Sbenno 1277174987Smarius /* secondary MAC address: 0:0:0:0:0:0 */ 1278177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_ADDR3, 0); 1279177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_ADDR4, 0); 1280177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_ADDR5, 0); 128199726Sbenno 1282174987Smarius /* MAC control address: 01:80:c2:00:00:01 */ 1283177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_ADDR6, 0x0001); 1284177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_ADDR7, 0xc200); 1285177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_ADDR8, 0x0180); 128691398Stmm 1287174987Smarius /* MAC filter address: 0:0:0:0:0:0 */ 1288177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_ADDR_FILTER0, 0); 1289177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_ADDR_FILTER1, 0); 1290177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_ADDR_FILTER2, 0); 1291177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_ADR_FLT_MASK1_2, 0); 1292177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_ADR_FLT_MASK0, 0); 129391398Stmm 1294172334Smarius sc->sc_flags |= GEM_INITED; 129591398Stmm } 129691398Stmm 1297174987Smarius /* Counters need to be zeroed. */ 1298177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_NORM_COLL_CNT, 0); 1299177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_FIRST_COLL_CNT, 0); 1300177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_EXCESS_COLL_CNT, 0); 1301177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_LATE_COLL_CNT, 0); 1302177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_DEFER_TMR_CNT, 0); 1303177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_PEAK_ATTEMPTS, 0); 1304177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_FRAME_COUNT, 0); 1305177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_LEN_ERR_CNT, 0); 1306177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_ALIGN_ERR, 0); 1307177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_CRC_ERR_CNT, 0); 1308177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_CODE_VIOL, 0); 130991398Stmm 1310172334Smarius /* Set XOFF PAUSE time. */ 1311177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_SEND_PAUSE_CMD, 0x1BF0); 131291398Stmm 1313174987Smarius /* Set the station address. */ 1314177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_ADDR0, (laddr[4] << 8) | laddr[5]); 1315177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_ADDR1, (laddr[2] << 8) | laddr[3]); 1316177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_ADDR2, (laddr[0] << 8) | laddr[1]); 131799726Sbenno 1318172334Smarius /* Enable MII outputs. */ 1319177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_XIF_CONFIG, GEM_MAC_XIF_TX_MII_ENA); 132091398Stmm} 132191398Stmm 132291398Stmmstatic void 1323174987Smariusgem_start(struct ifnet *ifp) 132491398Stmm{ 1325174987Smarius struct gem_softc *sc = ifp->if_softc; 1326148369Smarius 1327148369Smarius GEM_LOCK(sc); 1328148369Smarius gem_start_locked(ifp); 1329148369Smarius GEM_UNLOCK(sc); 1330148369Smarius} 1331148369Smarius 1332194763Smariusstatic inline void 1333194763Smariusgem_txkick(struct gem_softc *sc) 1334194763Smarius{ 1335194763Smarius 1336194763Smarius /* 1337194763Smarius * Update the TX kick register. This register has to point to the 1338194763Smarius * descriptor after the last valid one and for optimum performance 1339194763Smarius * should be incremented in multiples of 4 (the DMA engine fetches/ 1340194763Smarius * updates descriptors in batches of 4). 1341194763Smarius */ 1342194763Smarius#ifdef GEM_DEBUG 1343194763Smarius CTR3(KTR_GEM, "%s: %s: kicking TX %d", 1344194763Smarius device_get_name(sc->sc_dev), __func__, sc->sc_txnext); 1345194763Smarius#endif 1346194763Smarius GEM_CDSYNC(sc, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 1347194763Smarius GEM_BANK1_WRITE_4(sc, GEM_TX_KICK, sc->sc_txnext); 1348194763Smarius} 1349194763Smarius 1350148369Smariusstatic void 1351174987Smariusgem_start_locked(struct ifnet *ifp) 1352148369Smarius{ 1353174987Smarius struct gem_softc *sc = ifp->if_softc; 1354170273Syongari struct mbuf *m; 1355194763Smarius int kicked, ntx; 135691398Stmm 1357194763Smarius GEM_LOCK_ASSERT(sc, MA_OWNED); 1358194763Smarius 1359148887Srwatson if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) != 1360172334Smarius IFF_DRV_RUNNING || (sc->sc_flags & GEM_LINK) == 0) 136191398Stmm return; 136291398Stmm 1363115030Stmm#ifdef GEM_DEBUG 1364170273Syongari CTR4(KTR_GEM, "%s: %s: txfree %d, txnext %d", 1365172334Smarius device_get_name(sc->sc_dev), __func__, sc->sc_txfree, 1366172334Smarius sc->sc_txnext); 1367115030Stmm#endif 1368174987Smarius ntx = 0; 1369194763Smarius kicked = 0; 1370170273Syongari for (; !IFQ_DRV_IS_EMPTY(&ifp->if_snd) && sc->sc_txfree > 1;) { 1371170273Syongari IFQ_DRV_DEQUEUE(&ifp->if_snd, m); 1372170273Syongari if (m == NULL) 137391398Stmm break; 1374172334Smarius if (gem_load_txmbuf(sc, &m) != 0) { 1375170273Syongari if (m == NULL) 1376170273Syongari break; 1377170273Syongari ifp->if_drv_flags |= IFF_DRV_OACTIVE; 1378170273Syongari IFQ_DRV_PREPEND(&ifp->if_snd, m); 137991398Stmm break; 138091398Stmm } 1381194763Smarius if ((sc->sc_txnext % 4) == 0) { 1382194763Smarius gem_txkick(sc); 1383194763Smarius kicked = 1; 1384194763Smarius } else 1385194763Smarius kicked = 0; 1386115030Stmm ntx++; 1387170273Syongari BPF_MTAP(ifp, m); 138891398Stmm } 138991398Stmm 139091398Stmm if (ntx > 0) { 1391194763Smarius if (kicked == 0) 1392194763Smarius gem_txkick(sc); 1393115030Stmm#ifdef GEM_DEBUG 1394108832Stmm CTR2(KTR_GEM, "%s: packets enqueued, OWN on %d", 1395172334Smarius device_get_name(sc->sc_dev), sc->sc_txnext); 1396115030Stmm#endif 139791398Stmm 139891398Stmm /* Set a watchdog timer in case the chip flakes out. */ 1399164931Smarius sc->sc_wdog_timer = 5; 1400115030Stmm#ifdef GEM_DEBUG 1401170273Syongari CTR3(KTR_GEM, "%s: %s: watchdog %d", 1402174987Smarius device_get_name(sc->sc_dev), __func__, 1403174987Smarius sc->sc_wdog_timer); 1404115030Stmm#endif 140591398Stmm } 140691398Stmm} 140791398Stmm 140891398Stmmstatic void 1409174987Smariusgem_tint(struct gem_softc *sc) 141091398Stmm{ 1411147256Sbrooks struct ifnet *ifp = sc->sc_ifp; 141291398Stmm struct gem_txsoft *txs; 1413194763Smarius int progress; 1414194763Smarius uint32_t txlast; 1415174987Smarius#ifdef GEM_DEBUG 1416174987Smarius int i; 141791398Stmm 1418194763Smarius GEM_LOCK_ASSERT(sc, MA_OWNED); 1419194763Smarius 1420170273Syongari CTR2(KTR_GEM, "%s: %s", device_get_name(sc->sc_dev), __func__); 1421115030Stmm#endif 142291398Stmm 142391398Stmm /* 1424174987Smarius * Go through our TX list and free mbufs for those 142591398Stmm * frames that have been transmitted. 142691398Stmm */ 1427174987Smarius progress = 0; 1428109648Stmm GEM_CDSYNC(sc, BUS_DMASYNC_POSTREAD); 142991398Stmm while ((txs = STAILQ_FIRST(&sc->sc_txdirtyq)) != NULL) { 143091398Stmm#ifdef GEM_DEBUG 1431174987Smarius if ((ifp->if_flags & IFF_DEBUG) != 0) { 143291398Stmm printf(" txsoft %p transmit chain:\n", txs); 143391398Stmm for (i = txs->txs_firstdesc;; i = GEM_NEXTTX(i)) { 143491398Stmm printf("descriptor %d: ", i); 1435174987Smarius printf("gd_flags: 0x%016llx\t", 1436174987Smarius (long long)GEM_DMA_READ(sc, 1437174987Smarius sc->sc_txdescs[i].gd_flags)); 1438174987Smarius printf("gd_addr: 0x%016llx\n", 1439174987Smarius (long long)GEM_DMA_READ(sc, 1440174987Smarius sc->sc_txdescs[i].gd_addr)); 144191398Stmm if (i == txs->txs_lastdesc) 144291398Stmm break; 144391398Stmm } 144491398Stmm } 144591398Stmm#endif 144691398Stmm 144791398Stmm /* 1448172334Smarius * In theory, we could harvest some descriptors before 144991398Stmm * the ring is empty, but that's a bit complicated. 145091398Stmm * 145191398Stmm * GEM_TX_COMPLETION points to the last descriptor 1452174987Smarius * processed + 1. 145391398Stmm */ 1454177560Smarius txlast = GEM_BANK1_READ_4(sc, GEM_TX_COMPLETION); 1455115030Stmm#ifdef GEM_DEBUG 1456170273Syongari CTR4(KTR_GEM, "%s: txs->txs_firstdesc = %d, " 145791398Stmm "txs->txs_lastdesc = %d, txlast = %d", 1458170273Syongari __func__, txs->txs_firstdesc, txs->txs_lastdesc, txlast); 1459115030Stmm#endif 146091398Stmm if (txs->txs_firstdesc <= txs->txs_lastdesc) { 146191398Stmm if ((txlast >= txs->txs_firstdesc) && 1462174987Smarius (txlast <= txs->txs_lastdesc)) 146391398Stmm break; 146491398Stmm } else { 1465174987Smarius /* Ick -- this command wraps. */ 146691398Stmm if ((txlast >= txs->txs_firstdesc) || 1467174987Smarius (txlast <= txs->txs_lastdesc)) 146891398Stmm break; 146991398Stmm } 147091398Stmm 1471115030Stmm#ifdef GEM_DEBUG 1472174987Smarius CTR1(KTR_GEM, "%s: releasing a descriptor", __func__); 1473115030Stmm#endif 147491398Stmm STAILQ_REMOVE_HEAD(&sc->sc_txdirtyq, txs_q); 147591398Stmm 147691398Stmm sc->sc_txfree += txs->txs_ndescs; 147791398Stmm 1478108832Stmm bus_dmamap_sync(sc->sc_tdmatag, txs->txs_dmamap, 147991398Stmm BUS_DMASYNC_POSTWRITE); 1480108832Stmm bus_dmamap_unload(sc->sc_tdmatag, txs->txs_dmamap); 148191398Stmm if (txs->txs_mbuf != NULL) { 148291398Stmm m_freem(txs->txs_mbuf); 148391398Stmm txs->txs_mbuf = NULL; 148491398Stmm } 148591398Stmm 148691398Stmm STAILQ_INSERT_TAIL(&sc->sc_txfreeq, txs, txs_q); 148791398Stmm 1488271811Sglebius if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); 148999726Sbenno progress = 1; 149091398Stmm } 149191398Stmm 1492115030Stmm#ifdef GEM_DEBUG 1493174987Smarius CTR4(KTR_GEM, "%s: GEM_TX_STATE_MACHINE %x GEM_TX_DATA_PTR %llx " 1494172334Smarius "GEM_TX_COMPLETION %x", 1495177560Smarius __func__, GEM_BANK1_READ_4(sc, GEM_TX_STATE_MACHINE), 1496177560Smarius ((long long)GEM_BANK1_READ_4(sc, GEM_TX_DATA_PTR_HI) << 32) | 1497177560Smarius GEM_BANK1_READ_4(sc, GEM_TX_DATA_PTR_LO), 1498177560Smarius GEM_BANK1_READ_4(sc, GEM_TX_COMPLETION)); 1499115030Stmm#endif 150091398Stmm 150199726Sbenno if (progress) { 150299726Sbenno if (sc->sc_txfree == GEM_NTXDESC - 1) 150399726Sbenno sc->sc_txwin = 0; 150491398Stmm 1505174987Smarius /* 1506174987Smarius * We freed some descriptors, so reset IFF_DRV_OACTIVE 1507174987Smarius * and restart. 1508174987Smarius */ 1509148887Srwatson ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 1510194763Smarius if (STAILQ_EMPTY(&sc->sc_txdirtyq)) 1511194763Smarius sc->sc_wdog_timer = 0; 1512179925Smarius gem_start_locked(ifp); 151399726Sbenno } 151499726Sbenno 1515115030Stmm#ifdef GEM_DEBUG 1516170273Syongari CTR3(KTR_GEM, "%s: %s: watchdog %d", 1517170273Syongari device_get_name(sc->sc_dev), __func__, sc->sc_wdog_timer); 1518115030Stmm#endif 151991398Stmm} 152091398Stmm 1521148368Smarius#ifdef GEM_RINT_TIMEOUT 152293045Stmmstatic void 1523174987Smariusgem_rint_timeout(void *arg) 152493045Stmm{ 1525174987Smarius struct gem_softc *sc = arg; 152693045Stmm 1527150285Smarius GEM_LOCK_ASSERT(sc, MA_OWNED); 1528194763Smarius 1529148369Smarius gem_rint(sc); 153093045Stmm} 1531100587Sjake#endif 153293045Stmm 153391398Stmmstatic void 1534174987Smariusgem_rint(struct gem_softc *sc) 153591398Stmm{ 1536147256Sbrooks struct ifnet *ifp = sc->sc_ifp; 153791398Stmm struct mbuf *m; 1538174987Smarius uint64_t rxstat; 1539174987Smarius uint32_t rxcomp; 154091398Stmm 1541194763Smarius GEM_LOCK_ASSERT(sc, MA_OWNED); 1542194763Smarius 1543148368Smarius#ifdef GEM_RINT_TIMEOUT 154493045Stmm callout_stop(&sc->sc_rx_ch); 1545148368Smarius#endif 1546115030Stmm#ifdef GEM_DEBUG 1547170273Syongari CTR2(KTR_GEM, "%s: %s", device_get_name(sc->sc_dev), __func__); 1548115030Stmm#endif 154999726Sbenno 155091398Stmm /* 155199726Sbenno * Read the completion register once. This limits 155299726Sbenno * how long the following loop can execute. 155399726Sbenno */ 1554177560Smarius rxcomp = GEM_BANK1_READ_4(sc, GEM_RX_COMPLETION); 1555115030Stmm#ifdef GEM_DEBUG 1556194763Smarius CTR3(KTR_GEM, "%s: sc->sc_rxptr %d, complete %d", 1557170273Syongari __func__, sc->sc_rxptr, rxcomp); 1558115030Stmm#endif 1559194763Smarius GEM_CDSYNC(sc, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 1560172334Smarius for (; sc->sc_rxptr != rxcomp;) { 1561172334Smarius m = sc->sc_rxsoft[sc->sc_rxptr].rxs_mbuf; 1562172334Smarius rxstat = GEM_DMA_READ(sc, 1563172334Smarius sc->sc_rxdescs[sc->sc_rxptr].gd_flags); 156491398Stmm 156591398Stmm if (rxstat & GEM_RD_OWN) { 1566148368Smarius#ifdef GEM_RINT_TIMEOUT 156791398Stmm /* 156893045Stmm * The descriptor is still marked as owned, although 1569174987Smarius * it is supposed to have completed. This has been 1570174987Smarius * observed on some machines. Just exiting here 157193045Stmm * might leave the packet sitting around until another 157293045Stmm * one arrives to trigger a new interrupt, which is 157393045Stmm * generally undesirable, so set up a timeout. 157491398Stmm */ 157593045Stmm callout_reset(&sc->sc_rx_ch, GEM_RXOWN_TICKS, 157693045Stmm gem_rint_timeout, sc); 157799726Sbenno#endif 1578172334Smarius m = NULL; 1579172334Smarius goto kickit; 158091398Stmm } 158191398Stmm 158291398Stmm if (rxstat & GEM_RD_BAD_CRC) { 1583271811Sglebius if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); 158491398Stmm device_printf(sc->sc_dev, "receive error: CRC error\n"); 1585172334Smarius GEM_INIT_RXDESC(sc, sc->sc_rxptr); 1586172334Smarius m = NULL; 1587172334Smarius goto kickit; 158891398Stmm } 158991398Stmm 159091398Stmm#ifdef GEM_DEBUG 1591174987Smarius if ((ifp->if_flags & IFF_DEBUG) != 0) { 1592172334Smarius printf(" rxsoft %p descriptor %d: ", 1593172334Smarius &sc->sc_rxsoft[sc->sc_rxptr], sc->sc_rxptr); 1594174987Smarius printf("gd_flags: 0x%016llx\t", 1595174987Smarius (long long)GEM_DMA_READ(sc, 1596174987Smarius sc->sc_rxdescs[sc->sc_rxptr].gd_flags)); 1597174987Smarius printf("gd_addr: 0x%016llx\n", 1598174987Smarius (long long)GEM_DMA_READ(sc, 1599174987Smarius sc->sc_rxdescs[sc->sc_rxptr].gd_addr)); 160091398Stmm } 160191398Stmm#endif 160291398Stmm 160391398Stmm /* 160491398Stmm * Allocate a new mbuf cluster. If that fails, we are 160591398Stmm * out of memory, and must drop the packet and recycle 160691398Stmm * the buffer that's already attached to this descriptor. 160791398Stmm */ 1608172334Smarius if (gem_add_rxbuf(sc, sc->sc_rxptr) != 0) { 1609271811Sglebius if_inc_counter(ifp, IFCOUNTER_IQDROPS, 1); 1610172334Smarius GEM_INIT_RXDESC(sc, sc->sc_rxptr); 1611172334Smarius m = NULL; 1612172334Smarius } 1613172334Smarius 1614174987Smarius kickit: 1615174987Smarius /* 1616174987Smarius * Update the RX kick register. This register has to point 1617172334Smarius * to the descriptor after the last valid one (before the 1618194763Smarius * current batch) and for optimum performance should be 1619194763Smarius * incremented in multiples of 4 (the DMA engine fetches/ 1620194763Smarius * updates descriptors in batches of 4). 1621172334Smarius */ 1622172334Smarius sc->sc_rxptr = GEM_NEXTRX(sc->sc_rxptr); 1623172334Smarius if ((sc->sc_rxptr % 4) == 0) { 1624179925Smarius GEM_CDSYNC(sc, 1625179925Smarius BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 1626177560Smarius GEM_BANK1_WRITE_4(sc, GEM_RX_KICK, 1627172334Smarius (sc->sc_rxptr + GEM_NRXDESC - 4) & 1628172334Smarius GEM_NRXDESC_MASK); 1629172334Smarius } 1630172334Smarius 1631172334Smarius if (m == NULL) { 1632172334Smarius if (rxstat & GEM_RD_OWN) 1633172334Smarius break; 163491398Stmm continue; 163591398Stmm } 1636172334Smarius 1637271811Sglebius if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1); 1638194763Smarius m->m_data += ETHER_ALIGN; /* first byte offset */ 163991398Stmm m->m_pkthdr.rcvif = ifp; 1640172334Smarius m->m_pkthdr.len = m->m_len = GEM_RD_BUFLEN(rxstat); 164191398Stmm 1642170273Syongari if ((ifp->if_capenable & IFCAP_RXCSUM) != 0) 1643170273Syongari gem_rxcksum(m, rxstat); 1644170273Syongari 164591398Stmm /* Pass it on. */ 1646148369Smarius GEM_UNLOCK(sc); 1647106937Ssam (*ifp->if_input)(ifp, m); 1648148369Smarius GEM_LOCK(sc); 164991398Stmm } 165091398Stmm 1651115030Stmm#ifdef GEM_DEBUG 1652194763Smarius CTR3(KTR_GEM, "%s: done sc->sc_rxptr %d, complete %d", __func__, 1653177560Smarius sc->sc_rxptr, GEM_BANK1_READ_4(sc, GEM_RX_COMPLETION)); 1654115030Stmm#endif 165591398Stmm} 165691398Stmm 165791398Stmmstatic int 1658174987Smariusgem_add_rxbuf(struct gem_softc *sc, int idx) 165991398Stmm{ 166091398Stmm struct gem_rxsoft *rxs = &sc->sc_rxsoft[idx]; 166191398Stmm struct mbuf *m; 1662148368Smarius bus_dma_segment_t segs[1]; 1663148368Smarius int error, nsegs; 166491398Stmm 1665194763Smarius GEM_LOCK_ASSERT(sc, MA_OWNED); 1666194763Smarius 1667243857Sglebius m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); 166891398Stmm if (m == NULL) 166991398Stmm return (ENOBUFS); 1670108832Stmm m->m_len = m->m_pkthdr.len = m->m_ext.ext_size; 167191398Stmm 167291398Stmm#ifdef GEM_DEBUG 1673174987Smarius /* Bzero the packet to check DMA. */ 167491398Stmm memset(m->m_ext.ext_buf, 0, m->m_ext.ext_size); 167591398Stmm#endif 167691398Stmm 1677109648Stmm if (rxs->rxs_mbuf != NULL) { 1678109648Stmm bus_dmamap_sync(sc->sc_rdmatag, rxs->rxs_dmamap, 1679109648Stmm BUS_DMASYNC_POSTREAD); 1680108832Stmm bus_dmamap_unload(sc->sc_rdmatag, rxs->rxs_dmamap); 1681109648Stmm } 168291398Stmm 1683148368Smarius error = bus_dmamap_load_mbuf_sg(sc->sc_rdmatag, rxs->rxs_dmamap, 1684148368Smarius m, segs, &nsegs, BUS_DMA_NOWAIT); 1685148368Smarius if (error != 0) { 1686174987Smarius device_printf(sc->sc_dev, 1687174987Smarius "cannot load RS DMA map %d, error = %d\n", idx, error); 1688148368Smarius m_freem(m); 1689172334Smarius return (error); 169091398Stmm } 1691174987Smarius /* If nsegs is wrong then the stack is corrupt. */ 1692176996Smarius KASSERT(nsegs == 1, 1693176996Smarius ("%s: too many DMA segments (%d)", __func__, nsegs)); 1694172334Smarius rxs->rxs_mbuf = m; 1695148368Smarius rxs->rxs_paddr = segs[0].ds_addr; 169691398Stmm 1697174987Smarius bus_dmamap_sync(sc->sc_rdmatag, rxs->rxs_dmamap, 1698174987Smarius BUS_DMASYNC_PREREAD); 169991398Stmm 170091398Stmm GEM_INIT_RXDESC(sc, idx); 170191398Stmm 170291398Stmm return (0); 170391398Stmm} 170491398Stmm 170591398Stmmstatic void 1706174987Smariusgem_eint(struct gem_softc *sc, u_int status) 170791398Stmm{ 170891398Stmm 1709271811Sglebius if_inc_counter(sc->sc_ifp, IFCOUNTER_IERRORS, 1); 1710172334Smarius if ((status & GEM_INTR_RX_TAG_ERR) != 0) { 1711172334Smarius gem_reset_rxdma(sc); 171291398Stmm return; 171391398Stmm } 171491398Stmm 1715194763Smarius device_printf(sc->sc_dev, "%s: status 0x%x", __func__, status); 1716194763Smarius if ((status & GEM_INTR_BERR) != 0) { 1717194763Smarius if ((sc->sc_flags & GEM_PCI) != 0) 1718194763Smarius printf(", PCI bus error 0x%x\n", 1719194763Smarius GEM_BANK1_READ_4(sc, GEM_PCI_ERROR_STATUS)); 1720194763Smarius else 1721194763Smarius printf(", SBus error 0x%x\n", 1722194763Smarius GEM_BANK1_READ_4(sc, GEM_SBUS_STATUS)); 1723194763Smarius } 172491398Stmm} 172591398Stmm 172691398Stmmvoid 1727174987Smariusgem_intr(void *v) 172891398Stmm{ 1729174987Smarius struct gem_softc *sc = v; 1730172334Smarius uint32_t status, status2; 173191398Stmm 1732148369Smarius GEM_LOCK(sc); 1733177560Smarius status = GEM_BANK1_READ_4(sc, GEM_STATUS); 1734172334Smarius 1735115030Stmm#ifdef GEM_DEBUG 1736170273Syongari CTR4(KTR_GEM, "%s: %s: cplt %x, status %x", 1737194763Smarius device_get_name(sc->sc_dev), __func__, 1738194763Smarius (status >> GEM_STATUS_TX_COMPLETION_SHFT), (u_int)status); 1739172334Smarius 1740172334Smarius /* 1741172334Smarius * PCS interrupts must be cleared, otherwise no traffic is passed! 1742172334Smarius */ 1743172334Smarius if ((status & GEM_INTR_PCS) != 0) { 1744174987Smarius status2 = 1745177560Smarius GEM_BANK1_READ_4(sc, GEM_MII_INTERRUP_STATUS) | 1746177560Smarius GEM_BANK1_READ_4(sc, GEM_MII_INTERRUP_STATUS); 1747172334Smarius if ((status2 & GEM_MII_INTERRUP_LINK) != 0) 1748172334Smarius device_printf(sc->sc_dev, 1749172334Smarius "%s: PCS link status changed\n", __func__); 1750172334Smarius } 1751172334Smarius if ((status & GEM_MAC_CONTROL_STATUS) != 0) { 1752177560Smarius status2 = GEM_BANK1_READ_4(sc, GEM_MAC_CONTROL_STATUS); 1753172334Smarius if ((status2 & GEM_MAC_PAUSED) != 0) 1754172334Smarius device_printf(sc->sc_dev, 1755172334Smarius "%s: PAUSE received (PAUSE time %d slots)\n", 1756172334Smarius __func__, GEM_MAC_PAUSE_TIME(status2)); 1757172334Smarius if ((status2 & GEM_MAC_PAUSE) != 0) 1758172334Smarius device_printf(sc->sc_dev, 1759172334Smarius "%s: transited to PAUSE state\n", __func__); 1760172334Smarius if ((status2 & GEM_MAC_RESUME) != 0) 1761172334Smarius device_printf(sc->sc_dev, 1762172334Smarius "%s: transited to non-PAUSE state\n", __func__); 1763172334Smarius } 1764172334Smarius if ((status & GEM_INTR_MIF) != 0) 1765172334Smarius device_printf(sc->sc_dev, "%s: MIF interrupt\n", __func__); 1766115030Stmm#endif 176791398Stmm 1768194763Smarius if (__predict_false(status & 1769172334Smarius (GEM_INTR_RX_TAG_ERR | GEM_INTR_PERR | GEM_INTR_BERR)) != 0) 177091398Stmm gem_eint(sc, status); 177191398Stmm 1772172334Smarius if ((status & (GEM_INTR_RX_DONE | GEM_INTR_RX_NOBUF)) != 0) 1773172334Smarius gem_rint(sc); 1774172334Smarius 177591398Stmm if ((status & (GEM_INTR_TX_EMPTY | GEM_INTR_TX_INTME)) != 0) 177691398Stmm gem_tint(sc); 177791398Stmm 1778194763Smarius if (__predict_false((status & GEM_INTR_TX_MAC) != 0)) { 1779177560Smarius status2 = GEM_BANK1_READ_4(sc, GEM_MAC_TX_STATUS); 1780174987Smarius if ((status2 & 1781194763Smarius ~(GEM_MAC_TX_XMIT_DONE | GEM_MAC_TX_DEFER_EXP | 1782194763Smarius GEM_MAC_TX_PEAK_EXP)) != 0) 1783174987Smarius device_printf(sc->sc_dev, 1784174987Smarius "MAC TX fault, status %x\n", status2); 1785174987Smarius if ((status2 & 1786194763Smarius (GEM_MAC_TX_UNDERRUN | GEM_MAC_TX_PKT_TOO_LONG)) != 0) { 1787271811Sglebius if_inc_counter(sc->sc_ifp, IFCOUNTER_OERRORS, 1); 1788222135Syongari sc->sc_ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 1789148369Smarius gem_init_locked(sc); 1790194763Smarius } 179191398Stmm } 1792194763Smarius if (__predict_false((status & GEM_INTR_RX_MAC) != 0)) { 1793177560Smarius status2 = GEM_BANK1_READ_4(sc, GEM_MAC_RX_STATUS); 1794149552Smarius /* 1795172334Smarius * At least with GEM_SUN_GEM and some GEM_SUN_ERI 1796172334Smarius * revisions GEM_MAC_RX_OVERFLOW happen often due to a 1797174987Smarius * silicon bug so handle them silently. Moreover, it's 1798172334Smarius * likely that the receiver has hung so we reset it. 1799149552Smarius */ 1800174987Smarius if ((status2 & GEM_MAC_RX_OVERFLOW) != 0) { 1801271811Sglebius if_inc_counter(sc->sc_ifp, IFCOUNTER_IERRORS, 1); 1802172334Smarius gem_reset_rxdma(sc); 1803174987Smarius } else if ((status2 & 1804174987Smarius ~(GEM_MAC_RX_DONE | GEM_MAC_RX_FRAME_CNT)) != 0) 1805174987Smarius device_printf(sc->sc_dev, 1806174987Smarius "MAC RX fault, status %x\n", status2); 180791398Stmm } 1808148369Smarius GEM_UNLOCK(sc); 180991398Stmm} 181091398Stmm 1811164931Smariusstatic int 1812174987Smariusgem_watchdog(struct gem_softc *sc) 181391398Stmm{ 1814179925Smarius struct ifnet *ifp = sc->sc_ifp; 181591398Stmm 1816164931Smarius GEM_LOCK_ASSERT(sc, MA_OWNED); 1817164931Smarius 1818115030Stmm#ifdef GEM_DEBUG 1819174987Smarius CTR4(KTR_GEM, 1820174987Smarius "%s: GEM_RX_CONFIG %x GEM_MAC_RX_STATUS %x GEM_MAC_RX_CONFIG %x", 1821177560Smarius __func__, GEM_BANK1_READ_4(sc, GEM_RX_CONFIG), 1822177560Smarius GEM_BANK1_READ_4(sc, GEM_MAC_RX_STATUS), 1823177560Smarius GEM_BANK1_READ_4(sc, GEM_MAC_RX_CONFIG)); 1824174987Smarius CTR4(KTR_GEM, 1825174987Smarius "%s: GEM_TX_CONFIG %x GEM_MAC_TX_STATUS %x GEM_MAC_TX_CONFIG %x", 1826177560Smarius __func__, GEM_BANK1_READ_4(sc, GEM_TX_CONFIG), 1827177560Smarius GEM_BANK1_READ_4(sc, GEM_MAC_TX_STATUS), 1828177560Smarius GEM_BANK1_READ_4(sc, GEM_MAC_TX_CONFIG)); 1829115030Stmm#endif 183091398Stmm 1831164931Smarius if (sc->sc_wdog_timer == 0 || --sc->sc_wdog_timer != 0) 1832164931Smarius return (0); 1833164931Smarius 1834172334Smarius if ((sc->sc_flags & GEM_LINK) != 0) 1835172334Smarius device_printf(sc->sc_dev, "device timeout\n"); 1836172334Smarius else if (bootverbose) 1837172334Smarius device_printf(sc->sc_dev, "device timeout (no link)\n"); 1838271811Sglebius if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); 183991398Stmm 184091398Stmm /* Try to get more packets going. */ 1841222135Syongari ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 1842148369Smarius gem_init_locked(sc); 1843179925Smarius gem_start_locked(ifp); 1844164931Smarius return (EJUSTRETURN); 184591398Stmm} 184691398Stmm 184791398Stmmstatic void 1848174987Smariusgem_mifinit(struct gem_softc *sc) 184991398Stmm{ 185091398Stmm 1851176996Smarius /* Configure the MIF in frame mode. */ 1852177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MIF_CONFIG, 1853177560Smarius GEM_BANK1_READ_4(sc, GEM_MIF_CONFIG) & ~GEM_MIF_CONFIG_BB_ENA); 1854212725Smarius GEM_BANK1_BARRIER(sc, GEM_MIF_CONFIG, 4, 1855212725Smarius BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 185691398Stmm} 185791398Stmm 185891398Stmm/* 185991398Stmm * MII interface 186091398Stmm * 1861182060Smarius * The MII interface supports at least three different operating modes: 186291398Stmm * 186391398Stmm * Bitbang mode is implemented using data, clock and output enable registers. 186491398Stmm * 186591398Stmm * Frame mode is implemented by loading a complete frame into the frame 186691398Stmm * register and polling the valid bit for completion. 186791398Stmm * 186891398Stmm * Polling mode uses the frame register but completion is indicated by 186991398Stmm * an interrupt. 187091398Stmm * 187191398Stmm */ 187291398Stmmint 1873174987Smariusgem_mii_readreg(device_t dev, int phy, int reg) 187491398Stmm{ 1875174987Smarius struct gem_softc *sc; 187691398Stmm int n; 1877174987Smarius uint32_t v; 187891398Stmm 187991398Stmm#ifdef GEM_DEBUG_PHY 1880172334Smarius printf("%s: phy %d reg %d\n", __func__, phy, reg); 188191398Stmm#endif 188291398Stmm 1883174987Smarius sc = device_get_softc(dev); 1884172334Smarius if ((sc->sc_flags & GEM_SERDES) != 0) { 1885172334Smarius switch (reg) { 1886172334Smarius case MII_BMCR: 1887172334Smarius reg = GEM_MII_CONTROL; 1888172334Smarius break; 1889172334Smarius case MII_BMSR: 1890172334Smarius reg = GEM_MII_STATUS; 1891172334Smarius break; 1892172334Smarius case MII_PHYIDR1: 1893172334Smarius case MII_PHYIDR2: 1894172334Smarius return (0); 1895172334Smarius case MII_ANAR: 1896172334Smarius reg = GEM_MII_ANAR; 1897172334Smarius break; 1898172334Smarius case MII_ANLPAR: 1899172334Smarius reg = GEM_MII_ANLPAR; 1900172334Smarius break; 1901172334Smarius case MII_EXTSR: 1902172334Smarius return (EXTSR_1000XFDX | EXTSR_1000XHDX); 1903172334Smarius default: 1904172334Smarius device_printf(sc->sc_dev, 1905172334Smarius "%s: unhandled register %d\n", __func__, reg); 1906172334Smarius return (0); 1907172334Smarius } 1908177560Smarius return (GEM_BANK1_READ_4(sc, reg)); 1909172334Smarius } 1910172334Smarius 1911174987Smarius /* Construct the frame command. */ 1912172334Smarius v = GEM_MIF_FRAME_READ | 1913172334Smarius (phy << GEM_MIF_PHY_SHIFT) | 1914172334Smarius (reg << GEM_MIF_REG_SHIFT); 191591398Stmm 1916177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MIF_FRAME, v); 1917179925Smarius GEM_BANK1_BARRIER(sc, GEM_MIF_FRAME, 4, 1918179925Smarius BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 191991398Stmm for (n = 0; n < 100; n++) { 192091398Stmm DELAY(1); 1921177560Smarius v = GEM_BANK1_READ_4(sc, GEM_MIF_FRAME); 1922150285Smarius if (v & GEM_MIF_FRAME_TA0) 192391398Stmm return (v & GEM_MIF_FRAME_DATA); 192491398Stmm } 192591398Stmm 1926174987Smarius device_printf(sc->sc_dev, "%s: timed out\n", __func__); 192791398Stmm return (0); 192891398Stmm} 192991398Stmm 193091398Stmmint 1931174987Smariusgem_mii_writereg(device_t dev, int phy, int reg, int val) 193291398Stmm{ 1933174987Smarius struct gem_softc *sc; 193491398Stmm int n; 1935174987Smarius uint32_t v; 193691398Stmm 193791398Stmm#ifdef GEM_DEBUG_PHY 1938172334Smarius printf("%s: phy %d reg %d val %x\n", phy, reg, val, __func__); 193991398Stmm#endif 194091398Stmm 1941174987Smarius sc = device_get_softc(dev); 1942172334Smarius if ((sc->sc_flags & GEM_SERDES) != 0) { 1943172334Smarius switch (reg) { 1944172334Smarius case MII_BMSR: 1945172334Smarius reg = GEM_MII_STATUS; 1946172334Smarius break; 1947179925Smarius case MII_BMCR: 1948179925Smarius reg = GEM_MII_CONTROL; 1949179925Smarius if ((val & GEM_MII_CONTROL_RESET) == 0) 1950179925Smarius break; 1951179925Smarius GEM_BANK1_WRITE_4(sc, GEM_MII_CONTROL, val); 1952179925Smarius GEM_BANK1_BARRIER(sc, GEM_MII_CONTROL, 4, 1953179925Smarius BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 1954179925Smarius if (!GEM_BANK1_BITWAIT(sc, GEM_MII_CONTROL, 1955179925Smarius GEM_MII_CONTROL_RESET, 0)) 1956179925Smarius device_printf(sc->sc_dev, 1957179925Smarius "cannot reset PCS\n"); 1958179925Smarius /* FALLTHROUGH */ 1959172334Smarius case MII_ANAR: 1960177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MII_CONFIG, 0); 1961177560Smarius GEM_BANK1_BARRIER(sc, GEM_MII_CONFIG, 4, 1962172334Smarius BUS_SPACE_BARRIER_WRITE); 1963177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MII_ANAR, val); 1964212725Smarius GEM_BANK1_BARRIER(sc, GEM_MII_ANAR, 4, 1965212725Smarius BUS_SPACE_BARRIER_WRITE); 1966177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MII_SLINK_CONTROL, 1967172334Smarius GEM_MII_SLINK_LOOPBACK | GEM_MII_SLINK_EN_SYNC_D); 1968212725Smarius GEM_BANK1_BARRIER(sc, GEM_MII_SLINK_CONTROL, 4, 1969212725Smarius BUS_SPACE_BARRIER_WRITE); 1970177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MII_CONFIG, 1971172334Smarius GEM_MII_CONFIG_ENABLE); 1972212725Smarius GEM_BANK1_BARRIER(sc, GEM_MII_CONFIG, 4, 1973212725Smarius BUS_SPACE_BARRIER_WRITE); 1974172334Smarius return (0); 1975172334Smarius case MII_ANLPAR: 1976172334Smarius reg = GEM_MII_ANLPAR; 1977172334Smarius break; 1978172334Smarius default: 1979172334Smarius device_printf(sc->sc_dev, 1980172334Smarius "%s: unhandled register %d\n", __func__, reg); 1981172334Smarius return (0); 1982172334Smarius } 1983177560Smarius GEM_BANK1_WRITE_4(sc, reg, val); 1984212725Smarius GEM_BANK1_BARRIER(sc, reg, 4, 1985212725Smarius BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 1986172334Smarius return (0); 1987172334Smarius } 1988172334Smarius 1989174987Smarius /* Construct the frame command. */ 1990172334Smarius v = GEM_MIF_FRAME_WRITE | 1991172334Smarius (phy << GEM_MIF_PHY_SHIFT) | 1992172334Smarius (reg << GEM_MIF_REG_SHIFT) | 199391398Stmm (val & GEM_MIF_FRAME_DATA); 199491398Stmm 1995177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MIF_FRAME, v); 1996179925Smarius GEM_BANK1_BARRIER(sc, GEM_MIF_FRAME, 4, 1997179925Smarius BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 199891398Stmm for (n = 0; n < 100; n++) { 199991398Stmm DELAY(1); 2000177560Smarius v = GEM_BANK1_READ_4(sc, GEM_MIF_FRAME); 2001150285Smarius if (v & GEM_MIF_FRAME_TA0) 200291398Stmm return (1); 200391398Stmm } 200491398Stmm 2005174987Smarius device_printf(sc->sc_dev, "%s: timed out\n", __func__); 200691398Stmm return (0); 200791398Stmm} 200891398Stmm 200991398Stmmvoid 2010174987Smariusgem_mii_statchg(device_t dev) 201191398Stmm{ 2012174987Smarius struct gem_softc *sc; 2013172334Smarius int gigabit; 2014172334Smarius uint32_t rxcfg, txcfg, v; 201591398Stmm 2016174987Smarius sc = device_get_softc(dev); 2017174987Smarius 2018194763Smarius GEM_LOCK_ASSERT(sc, MA_OWNED); 2019194763Smarius 202091398Stmm#ifdef GEM_DEBUG 2021174987Smarius if ((sc->sc_ifp->if_flags & IFF_DEBUG) != 0) 2022213893Smarius device_printf(sc->sc_dev, "%s: status change\n", __func__); 202391398Stmm#endif 202491398Stmm 2025172334Smarius if ((sc->sc_mii->mii_media_status & IFM_ACTIVE) != 0 && 2026172334Smarius IFM_SUBTYPE(sc->sc_mii->mii_media_active) != IFM_NONE) 2027172334Smarius sc->sc_flags |= GEM_LINK; 2028172334Smarius else 2029172334Smarius sc->sc_flags &= ~GEM_LINK; 2030172334Smarius 2031172334Smarius switch (IFM_SUBTYPE(sc->sc_mii->mii_media_active)) { 2032172334Smarius case IFM_1000_SX: 2033172334Smarius case IFM_1000_LX: 2034172334Smarius case IFM_1000_CX: 2035172334Smarius case IFM_1000_T: 2036172334Smarius gigabit = 1; 2037172334Smarius break; 2038172334Smarius default: 2039172334Smarius gigabit = 0; 204091398Stmm } 204191398Stmm 2042172334Smarius /* 2043172334Smarius * The configuration done here corresponds to the steps F) and 2044172334Smarius * G) and as far as enabling of RX and TX MAC goes also step H) 2045172334Smarius * of the initialization sequence outlined in section 3.2.1 of 2046172334Smarius * the GEM Gigabit Ethernet ASIC Specification. 2047172334Smarius */ 2048172334Smarius 2049223648Smarius rxcfg = sc->sc_mac_rxcfg; 2050223648Smarius rxcfg &= ~GEM_MAC_RX_CARR_EXTEND; 2051172334Smarius txcfg = GEM_MAC_TX_ENA_IPG0 | GEM_MAC_TX_NGU | GEM_MAC_TX_NGU_LIMIT; 2052172334Smarius if ((IFM_OPTIONS(sc->sc_mii->mii_media_active) & IFM_FDX) != 0) 2053172334Smarius txcfg |= GEM_MAC_TX_IGN_CARRIER | GEM_MAC_TX_IGN_COLLIS; 2054172334Smarius else if (gigabit != 0) { 2055172334Smarius rxcfg |= GEM_MAC_RX_CARR_EXTEND; 2056172334Smarius txcfg |= GEM_MAC_TX_CARR_EXTEND; 2057172334Smarius } 2058223648Smarius (void)gem_disable_tx(sc); 2059177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_TX_CONFIG, txcfg); 2060223648Smarius (void)gem_disable_rx(sc); 2061177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_CONFIG, rxcfg); 2062172334Smarius 2063177560Smarius v = GEM_BANK1_READ_4(sc, GEM_MAC_CONTROL_CONFIG) & 2064172334Smarius ~(GEM_MAC_CC_RX_PAUSE | GEM_MAC_CC_TX_PAUSE); 2065174987Smarius if ((IFM_OPTIONS(sc->sc_mii->mii_media_active) & 2066174987Smarius IFM_ETH_RXPAUSE) != 0) 2067172334Smarius v |= GEM_MAC_CC_RX_PAUSE; 2068174987Smarius if ((IFM_OPTIONS(sc->sc_mii->mii_media_active) & 2069174987Smarius IFM_ETH_TXPAUSE) != 0) 2070172334Smarius v |= GEM_MAC_CC_TX_PAUSE; 2071177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_CONTROL_CONFIG, v); 2072172334Smarius 2073172334Smarius if ((IFM_OPTIONS(sc->sc_mii->mii_media_active) & IFM_FDX) == 0 && 2074172334Smarius gigabit != 0) 2075177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_SLOT_TIME, 2076172334Smarius GEM_MAC_SLOT_TIME_CARR_EXTEND); 2077172334Smarius else 2078177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_SLOT_TIME, 2079172334Smarius GEM_MAC_SLOT_TIME_NORMAL); 2080172334Smarius 208191398Stmm /* XIF Configuration */ 208291398Stmm v = GEM_MAC_XIF_LINK_LED; 208391398Stmm v |= GEM_MAC_XIF_TX_MII_ENA; 2084172334Smarius if ((sc->sc_flags & GEM_SERDES) == 0) { 2085177560Smarius if ((GEM_BANK1_READ_4(sc, GEM_MIF_CONFIG) & 2086182060Smarius GEM_MIF_CONFIG_PHY_SEL) != 0) { 2087172334Smarius /* External MII needs echo disable if half duplex. */ 2088194763Smarius if ((IFM_OPTIONS(sc->sc_mii->mii_media_active) & 2089182060Smarius IFM_FDX) == 0) 2090182060Smarius v |= GEM_MAC_XIF_ECHO_DISABL; 2091182060Smarius } else 2092172334Smarius /* 2093172334Smarius * Internal MII needs buffer enable. 2094172334Smarius * XXX buffer enable makes only sense for an 2095172334Smarius * external PHY. 2096172334Smarius */ 2097172334Smarius v |= GEM_MAC_XIF_MII_BUF_ENA; 2098172334Smarius } 2099172334Smarius if (gigabit != 0) 2100172334Smarius v |= GEM_MAC_XIF_GMII_MODE; 2101172334Smarius if ((IFM_OPTIONS(sc->sc_mii->mii_media_active) & IFM_FDX) != 0) 2102172334Smarius v |= GEM_MAC_XIF_FDPLX_LED; 2103177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_XIF_CONFIG, v); 210499726Sbenno 2105223648Smarius sc->sc_mac_rxcfg = rxcfg; 2106172334Smarius if ((sc->sc_ifp->if_drv_flags & IFF_DRV_RUNNING) != 0 && 2107172334Smarius (sc->sc_flags & GEM_LINK) != 0) { 2108177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_TX_CONFIG, 2109172334Smarius txcfg | GEM_MAC_TX_ENABLE); 2110177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_CONFIG, 2111172334Smarius rxcfg | GEM_MAC_RX_ENABLE); 211291398Stmm } 211391398Stmm} 211491398Stmm 211591398Stmmint 2116174987Smariusgem_mediachange(struct ifnet *ifp) 211791398Stmm{ 211891398Stmm struct gem_softc *sc = ifp->if_softc; 2119150285Smarius int error; 212091398Stmm 2121174987Smarius /* XXX add support for serial media. */ 212291398Stmm 2123150285Smarius GEM_LOCK(sc); 2124150285Smarius error = mii_mediachg(sc->sc_mii); 2125150285Smarius GEM_UNLOCK(sc); 2126150285Smarius return (error); 212791398Stmm} 212891398Stmm 212991398Stmmvoid 2130174987Smariusgem_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr) 213191398Stmm{ 213291398Stmm struct gem_softc *sc = ifp->if_softc; 213391398Stmm 2134148369Smarius GEM_LOCK(sc); 2135148369Smarius if ((ifp->if_flags & IFF_UP) == 0) { 2136148369Smarius GEM_UNLOCK(sc); 213791398Stmm return; 2138148369Smarius } 213991398Stmm 214091398Stmm mii_pollstat(sc->sc_mii); 214191398Stmm ifmr->ifm_active = sc->sc_mii->mii_media_active; 214291398Stmm ifmr->ifm_status = sc->sc_mii->mii_media_status; 2143148369Smarius GEM_UNLOCK(sc); 214491398Stmm} 214591398Stmm 214691398Stmmstatic int 2147174987Smariusgem_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 214891398Stmm{ 214991398Stmm struct gem_softc *sc = ifp->if_softc; 215091398Stmm struct ifreq *ifr = (struct ifreq *)data; 2151174987Smarius int error; 215291398Stmm 2153174987Smarius error = 0; 215491398Stmm switch (cmd) { 2155150285Smarius case SIOCSIFFLAGS: 2156148369Smarius GEM_LOCK(sc); 2157174987Smarius if ((ifp->if_flags & IFF_UP) != 0) { 2158172334Smarius if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0 && 2159172334Smarius ((ifp->if_flags ^ sc->sc_ifflags) & 2160172334Smarius (IFF_ALLMULTI | IFF_PROMISC)) != 0) 2161223949Smarius gem_setladrf(sc); 216291398Stmm else 2163148369Smarius gem_init_locked(sc); 2164174987Smarius } else if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) 2165174987Smarius gem_stop(ifp, 0); 2166170273Syongari if ((ifp->if_flags & IFF_LINK0) != 0) 2167170273Syongari sc->sc_csum_features |= CSUM_UDP; 2168170273Syongari else 2169170273Syongari sc->sc_csum_features &= ~CSUM_UDP; 2170170273Syongari if ((ifp->if_capenable & IFCAP_TXCSUM) != 0) 2171170273Syongari ifp->if_hwassist = sc->sc_csum_features; 217299726Sbenno sc->sc_ifflags = ifp->if_flags; 2173150285Smarius GEM_UNLOCK(sc); 217491398Stmm break; 217591398Stmm case SIOCADDMULTI: 217691398Stmm case SIOCDELMULTI: 2177150285Smarius GEM_LOCK(sc); 2178223648Smarius if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) 2179223949Smarius gem_setladrf(sc); 2180150285Smarius GEM_UNLOCK(sc); 218191398Stmm break; 218291398Stmm case SIOCGIFMEDIA: 218391398Stmm case SIOCSIFMEDIA: 218491398Stmm error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii->mii_media, cmd); 218591398Stmm break; 2186170273Syongari case SIOCSIFCAP: 2187170273Syongari GEM_LOCK(sc); 2188170273Syongari ifp->if_capenable = ifr->ifr_reqcap; 2189170273Syongari if ((ifp->if_capenable & IFCAP_TXCSUM) != 0) 2190170273Syongari ifp->if_hwassist = sc->sc_csum_features; 2191170273Syongari else 2192170273Syongari ifp->if_hwassist = 0; 2193170273Syongari GEM_UNLOCK(sc); 2194170273Syongari break; 219591398Stmm default: 2196150285Smarius error = ether_ioctl(ifp, cmd, data); 219791398Stmm break; 219891398Stmm } 219991398Stmm 220091398Stmm return (error); 220191398Stmm} 220291398Stmm 220391398Stmmstatic void 2204223949Smariusgem_setladrf(struct gem_softc *sc) 220591398Stmm{ 2206147256Sbrooks struct ifnet *ifp = sc->sc_ifp; 220791398Stmm struct ifmultiaddr *inm; 220899726Sbenno int i; 2209174987Smarius uint32_t hash[16]; 2210174987Smarius uint32_t crc, v; 221191398Stmm 2212148369Smarius GEM_LOCK_ASSERT(sc, MA_OWNED); 2213148369Smarius 221499726Sbenno /* 2215223648Smarius * Turn off the RX MAC and the hash filter as required by the Sun GEM 2216223648Smarius * programming restrictions. 221799726Sbenno */ 2218223649Smarius v = sc->sc_mac_rxcfg & ~GEM_MAC_RX_HASH_FILTER; 2219177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_CONFIG, v); 2220179925Smarius GEM_BANK1_BARRIER(sc, GEM_MAC_RX_CONFIG, 4, 2221179925Smarius BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 2222223648Smarius if (!GEM_BANK1_BITWAIT(sc, GEM_MAC_RX_CONFIG, GEM_MAC_RX_HASH_FILTER | 2223223648Smarius GEM_MAC_RX_ENABLE, 0)) 2224223648Smarius device_printf(sc->sc_dev, 2225223648Smarius "cannot disable RX MAC or hash filter\n"); 2226172334Smarius 2227223648Smarius v &= ~(GEM_MAC_RX_PROMISCUOUS | GEM_MAC_RX_PROMISC_GRP); 222891398Stmm if ((ifp->if_flags & IFF_PROMISC) != 0) { 222991398Stmm v |= GEM_MAC_RX_PROMISCUOUS; 223091398Stmm goto chipit; 223191398Stmm } 223291398Stmm if ((ifp->if_flags & IFF_ALLMULTI) != 0) { 223399726Sbenno v |= GEM_MAC_RX_PROMISC_GRP; 223491398Stmm goto chipit; 223591398Stmm } 223691398Stmm 223791398Stmm /* 2238174987Smarius * Set up multicast address filter by passing all multicast 2239174987Smarius * addresses through a crc generator, and then using the high 2240174987Smarius * order 8 bits as an index into the 256 bit logical address 2241174987Smarius * filter. The high order 4 bits selects the word, while the 2242174987Smarius * other 4 bits select the bit within the word (where bit 0 2243174987Smarius * is the MSB). 224491398Stmm */ 224591398Stmm 2246174987Smarius /* Clear the hash table. */ 224799726Sbenno memset(hash, 0, sizeof(hash)); 224899726Sbenno 2249195049Srwatson if_maddr_rlock(ifp); 2250147256Sbrooks TAILQ_FOREACH(inm, &ifp->if_multiaddrs, ifma_link) { 225191398Stmm if (inm->ifma_addr->sa_family != AF_LINK) 225291398Stmm continue; 2253130288Smarius crc = ether_crc32_le(LLADDR((struct sockaddr_dl *) 2254130288Smarius inm->ifma_addr), ETHER_ADDR_LEN); 225591398Stmm 2256174987Smarius /* We just want the 8 most significant bits. */ 225791398Stmm crc >>= 24; 225891398Stmm 225991398Stmm /* Set the corresponding bit in the filter. */ 226099726Sbenno hash[crc >> 4] |= 1 << (15 - (crc & 15)); 226191398Stmm } 2262195049Srwatson if_maddr_runlock(ifp); 226391398Stmm 226499726Sbenno v |= GEM_MAC_RX_HASH_FILTER; 226599726Sbenno 2266174987Smarius /* Now load the hash table into the chip (if we are using it). */ 2267174987Smarius for (i = 0; i < 16; i++) 2268177560Smarius GEM_BANK1_WRITE_4(sc, 2269174987Smarius GEM_MAC_HASH0 + i * (GEM_MAC_HASH1 - GEM_MAC_HASH0), 227099726Sbenno hash[i]); 227199726Sbenno 2272174987Smarius chipit: 2273223648Smarius sc->sc_mac_rxcfg = v; 2274223949Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_CONFIG, v | GEM_MAC_RX_ENABLE); 227591398Stmm} 2276