if_gem.c revision 223944
1119418Sobrien/*- 291398Stmm * Copyright (C) 2001 Eduardo Horvath. 3108832Stmm * Copyright (c) 2001-2003 Thomas Moestl 4174987Smarius * Copyright (c) 2007 Marius Strobl <marius@FreeBSD.org> 591398Stmm * All rights reserved. 691398Stmm * 791398Stmm * Redistribution and use in source and binary forms, with or without 891398Stmm * modification, are permitted provided that the following conditions 991398Stmm * are met: 1091398Stmm * 1. Redistributions of source code must retain the above copyright 1191398Stmm * notice, this list of conditions and the following disclaimer. 1291398Stmm * 2. Redistributions in binary form must reproduce the above copyright 1391398Stmm * notice, this list of conditions and the following disclaimer in the 1491398Stmm * documentation and/or other materials provided with the distribution. 1591398Stmm * 1691398Stmm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND 1791398Stmm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1891398Stmm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1991398Stmm * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE 2091398Stmm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2191398Stmm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2291398Stmm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2391398Stmm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2491398Stmm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2591398Stmm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2691398Stmm * SUCH DAMAGE. 2791398Stmm * 2899726Sbenno * from: NetBSD: gem.c,v 1.21 2002/06/01 23:50:58 lukem Exp 2991398Stmm */ 3091398Stmm 31119418Sobrien#include <sys/cdefs.h> 32119418Sobrien__FBSDID("$FreeBSD: head/sys/dev/gem/if_gem.c 223944 2011-07-12 08:20:15Z marius $"); 33119418Sobrien 3491398Stmm/* 35172334Smarius * Driver for Apple GMAC, Sun ERI and Sun GEM Ethernet controllers 3691398Stmm */ 3791398Stmm 38115030Stmm#if 0 3991398Stmm#define GEM_DEBUG 40115030Stmm#endif 4191398Stmm 42148368Smarius#if 0 /* XXX: In case of emergency, re-enable this. */ 43148368Smarius#define GEM_RINT_TIMEOUT 44148368Smarius#endif 45148368Smarius 4691398Stmm#include <sys/param.h> 4791398Stmm#include <sys/systm.h> 4891398Stmm#include <sys/bus.h> 4991398Stmm#include <sys/callout.h> 5095533Smike#include <sys/endian.h> 5191398Stmm#include <sys/mbuf.h> 5291398Stmm#include <sys/malloc.h> 5391398Stmm#include <sys/kernel.h> 54148369Smarius#include <sys/lock.h> 55130026Sphk#include <sys/module.h> 56148369Smarius#include <sys/mutex.h> 5791398Stmm#include <sys/socket.h> 5891398Stmm#include <sys/sockio.h> 59169269Sphk#include <sys/rman.h> 6091398Stmm 61105982Stmm#include <net/bpf.h> 6291398Stmm#include <net/ethernet.h> 6391398Stmm#include <net/if.h> 6491398Stmm#include <net/if_arp.h> 6591398Stmm#include <net/if_dl.h> 6691398Stmm#include <net/if_media.h> 67147256Sbrooks#include <net/if_types.h> 68149552Smarius#include <net/if_vlan_var.h> 6991398Stmm 70170273Syongari#include <netinet/in.h> 71170273Syongari#include <netinet/in_systm.h> 72170273Syongari#include <netinet/ip.h> 73170273Syongari#include <netinet/tcp.h> 74170273Syongari#include <netinet/udp.h> 75170273Syongari 7691398Stmm#include <machine/bus.h> 7791398Stmm 7891398Stmm#include <dev/mii/mii.h> 7991398Stmm#include <dev/mii/miivar.h> 8091398Stmm 81119355Simp#include <dev/gem/if_gemreg.h> 82119355Simp#include <dev/gem/if_gemvar.h> 8391398Stmm 84172334SmariusCTASSERT(powerof2(GEM_NRXDESC) && GEM_NRXDESC >= 32 && GEM_NRXDESC <= 8192); 85172334SmariusCTASSERT(powerof2(GEM_NTXDESC) && GEM_NTXDESC >= 32 && GEM_NTXDESC <= 8192); 86172334Smarius 87194763Smarius#define GEM_TRIES 10000 88172334Smarius 89170273Syongari/* 90182060Smarius * The hardware supports basic TCP/UDP checksum offloading. However, 91170273Syongari * the hardware doesn't compensate the checksum for UDP datagram which 92174987Smarius * can yield to 0x0. As a safe guard, UDP checksum offload is disabled 93174987Smarius * by default. It can be reactivated by setting special link option 94170273Syongari * link0 with ifconfig(8). 95170273Syongari */ 96170273Syongari#define GEM_CSUM_FEATURES (CSUM_TCP) 9791398Stmm 98174987Smariusstatic int gem_add_rxbuf(struct gem_softc *sc, int idx); 99177560Smariusstatic int gem_bitwait(struct gem_softc *sc, u_int bank, bus_addr_t r, 100177560Smarius uint32_t clr, uint32_t set); 101174987Smariusstatic void gem_cddma_callback(void *xsc, bus_dma_segment_t *segs, 102174987Smarius int nsegs, int error); 103174987Smariusstatic int gem_disable_rx(struct gem_softc *sc); 104174987Smariusstatic int gem_disable_tx(struct gem_softc *sc); 105174987Smariusstatic void gem_eint(struct gem_softc *sc, u_int status); 106174987Smariusstatic void gem_init(void *xsc); 107174987Smariusstatic void gem_init_locked(struct gem_softc *sc); 108174987Smariusstatic void gem_init_regs(struct gem_softc *sc); 109174987Smariusstatic int gem_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data); 110174987Smariusstatic int gem_load_txmbuf(struct gem_softc *sc, struct mbuf **m_head); 111174987Smariusstatic int gem_meminit(struct gem_softc *sc); 112174987Smariusstatic void gem_mifinit(struct gem_softc *sc); 113174987Smariusstatic void gem_reset(struct gem_softc *sc); 114174987Smariusstatic int gem_reset_rx(struct gem_softc *sc); 115172334Smariusstatic void gem_reset_rxdma(struct gem_softc *sc); 116174987Smariusstatic int gem_reset_tx(struct gem_softc *sc); 117174987Smariusstatic u_int gem_ringsize(u_int sz); 118174987Smariusstatic void gem_rint(struct gem_softc *sc); 119148368Smarius#ifdef GEM_RINT_TIMEOUT 120174987Smariusstatic void gem_rint_timeout(void *arg); 121100587Sjake#endif 122194763Smariusstatic inline void gem_rxcksum(struct mbuf *m, uint64_t flags); 123174987Smariusstatic void gem_rxdrain(struct gem_softc *sc); 124223648Smariusstatic void gem_setladrf(struct gem_softc *sc, u_int enable); 125174987Smariusstatic void gem_start(struct ifnet *ifp); 126174987Smariusstatic void gem_start_locked(struct ifnet *ifp); 127174987Smariusstatic void gem_stop(struct ifnet *ifp, int disable); 128174987Smariusstatic void gem_tick(void *arg); 129174987Smariusstatic void gem_tint(struct gem_softc *sc); 130194763Smariusstatic inline void gem_txkick(struct gem_softc *sc); 131174987Smariusstatic int gem_watchdog(struct gem_softc *sc); 13291398Stmm 13391398Stmmdevclass_t gem_devclass; 13491398StmmDRIVER_MODULE(miibus, gem, miibus_driver, miibus_devclass, 0, 0); 13591398StmmMODULE_DEPEND(gem, miibus, 1, 1, 1); 13691398Stmm 13791398Stmm#ifdef GEM_DEBUG 13891398Stmm#include <sys/ktr.h> 139210334Sattilio#define KTR_GEM KTR_SPARE2 14091398Stmm#endif 14191398Stmm 142177560Smarius#define GEM_BANK1_BITWAIT(sc, r, clr, set) \ 143177560Smarius gem_bitwait((sc), GEM_RES_BANK1, (r), (clr), (set)) 144177560Smarius#define GEM_BANK2_BITWAIT(sc, r, clr, set) \ 145177560Smarius gem_bitwait((sc), GEM_RES_BANK2, (r), (clr), (set)) 146177560Smarius 14791398Stmmint 148174987Smariusgem_attach(struct gem_softc *sc) 14991398Stmm{ 150174987Smarius struct gem_txsoft *txs; 151147256Sbrooks struct ifnet *ifp; 152213893Smarius int error, i, phy; 153174987Smarius uint32_t v; 15491398Stmm 155194763Smarius if (bootverbose) 156194763Smarius device_printf(sc->sc_dev, "flags=0x%x\n", sc->sc_flags); 157194763Smarius 158194763Smarius /* Set up ifnet structure. */ 159147256Sbrooks ifp = sc->sc_ifp = if_alloc(IFT_ETHER); 160147256Sbrooks if (ifp == NULL) 161147256Sbrooks return (ENOSPC); 162194763Smarius sc->sc_csum_features = GEM_CSUM_FEATURES; 163194763Smarius ifp->if_softc = sc; 164194763Smarius if_initname(ifp, device_get_name(sc->sc_dev), 165194763Smarius device_get_unit(sc->sc_dev)); 166194763Smarius ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 167194763Smarius ifp->if_start = gem_start; 168194763Smarius ifp->if_ioctl = gem_ioctl; 169194763Smarius ifp->if_init = gem_init; 170194763Smarius IFQ_SET_MAXLEN(&ifp->if_snd, GEM_TXQUEUELEN); 171194763Smarius ifp->if_snd.ifq_drv_maxlen = GEM_TXQUEUELEN; 172194763Smarius IFQ_SET_READY(&ifp->if_snd); 173147256Sbrooks 174150285Smarius callout_init_mtx(&sc->sc_tick_ch, &sc->sc_mtx, 0); 175150285Smarius#ifdef GEM_RINT_TIMEOUT 176150285Smarius callout_init_mtx(&sc->sc_rx_ch, &sc->sc_mtx, 0); 177150285Smarius#endif 178150285Smarius 17991398Stmm /* Make sure the chip is stopped. */ 18091398Stmm gem_reset(sc); 18191398Stmm 182161928Sjmg error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), 1, 0, 183161928Sjmg BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, 184174987Smarius BUS_SPACE_MAXSIZE_32BIT, 0, BUS_SPACE_MAXSIZE_32BIT, 0, NULL, 185174987Smarius NULL, &sc->sc_pdmatag); 186194763Smarius if (error != 0) 187147256Sbrooks goto fail_ifnet; 18891398Stmm 18991398Stmm error = bus_dma_tag_create(sc->sc_pdmatag, 1, 0, 190170273Syongari BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, MCLBYTES, 191170273Syongari 1, MCLBYTES, BUS_DMA_ALLOCNOW, NULL, NULL, &sc->sc_rdmatag); 192194763Smarius if (error != 0) 193108832Stmm goto fail_ptag; 19491398Stmm 195108832Stmm error = bus_dma_tag_create(sc->sc_pdmatag, 1, 0, 196170273Syongari BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, 197170273Syongari MCLBYTES * GEM_NTXSEGS, GEM_NTXSEGS, MCLBYTES, 198117126Sscottl BUS_DMA_ALLOCNOW, NULL, NULL, &sc->sc_tdmatag); 199194763Smarius if (error != 0) 200108832Stmm goto fail_rtag; 201108832Stmm 20291398Stmm error = bus_dma_tag_create(sc->sc_pdmatag, PAGE_SIZE, 0, 203170273Syongari BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, 20491398Stmm sizeof(struct gem_control_data), 1, 205170273Syongari sizeof(struct gem_control_data), 0, 206170273Syongari NULL, NULL, &sc->sc_cdmatag); 207194763Smarius if (error != 0) 208108832Stmm goto fail_ttag; 20991398Stmm 21091398Stmm /* 211174987Smarius * Allocate the control data structures, create and load the 21291398Stmm * DMA map for it. 21391398Stmm */ 21491398Stmm if ((error = bus_dmamem_alloc(sc->sc_cdmatag, 215170273Syongari (void **)&sc->sc_control_data, 216170273Syongari BUS_DMA_WAITOK | BUS_DMA_COHERENT | BUS_DMA_ZERO, 217194763Smarius &sc->sc_cddmamap)) != 0) { 218174987Smarius device_printf(sc->sc_dev, 219174987Smarius "unable to allocate control data, error = %d\n", error); 220108832Stmm goto fail_ctag; 22191398Stmm } 22291398Stmm 22391398Stmm sc->sc_cddma = 0; 22491398Stmm if ((error = bus_dmamap_load(sc->sc_cdmatag, sc->sc_cddmamap, 22591398Stmm sc->sc_control_data, sizeof(struct gem_control_data), 22691398Stmm gem_cddma_callback, sc, 0)) != 0 || sc->sc_cddma == 0) { 227174987Smarius device_printf(sc->sc_dev, 228174987Smarius "unable to load control data DMA map, error = %d\n", 229174987Smarius error); 230108832Stmm goto fail_cmem; 23191398Stmm } 23291398Stmm 23391398Stmm /* 23491398Stmm * Initialize the transmit job descriptors. 23591398Stmm */ 23691398Stmm STAILQ_INIT(&sc->sc_txfreeq); 23791398Stmm STAILQ_INIT(&sc->sc_txdirtyq); 23891398Stmm 23991398Stmm /* 24091398Stmm * Create the transmit buffer DMA maps. 24191398Stmm */ 24291398Stmm error = ENOMEM; 24391398Stmm for (i = 0; i < GEM_TXQUEUELEN; i++) { 24491398Stmm txs = &sc->sc_txsoft[i]; 24591398Stmm txs->txs_mbuf = NULL; 24691398Stmm txs->txs_ndescs = 0; 247108832Stmm if ((error = bus_dmamap_create(sc->sc_tdmatag, 0, 24891398Stmm &txs->txs_dmamap)) != 0) { 249174987Smarius device_printf(sc->sc_dev, 250174987Smarius "unable to create TX DMA map %d, error = %d\n", 251174987Smarius i, error); 252108832Stmm goto fail_txd; 25391398Stmm } 25491398Stmm STAILQ_INSERT_TAIL(&sc->sc_txfreeq, txs, txs_q); 25591398Stmm } 25691398Stmm 25791398Stmm /* 25891398Stmm * Create the receive buffer DMA maps. 25991398Stmm */ 26091398Stmm for (i = 0; i < GEM_NRXDESC; i++) { 261108832Stmm if ((error = bus_dmamap_create(sc->sc_rdmatag, 0, 26291398Stmm &sc->sc_rxsoft[i].rxs_dmamap)) != 0) { 263174987Smarius device_printf(sc->sc_dev, 264174987Smarius "unable to create RX DMA map %d, error = %d\n", 265174987Smarius i, error); 266108832Stmm goto fail_rxd; 26791398Stmm } 26891398Stmm sc->sc_rxsoft[i].rxs_mbuf = NULL; 26991398Stmm } 27091398Stmm 271212725Smarius /* Bypass probing PHYs if we already know for sure to use a SERDES. */ 272212725Smarius if ((sc->sc_flags & GEM_SERDES) != 0) 273212725Smarius goto serdes; 274212725Smarius 275172334Smarius /* Bad things will happen when touching this register on ERI. */ 276212725Smarius if (sc->sc_variant != GEM_SUN_ERI) { 277177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MII_DATAPATH_MODE, 278172334Smarius GEM_MII_DATAPATH_MII); 279212725Smarius GEM_BANK1_BARRIER(sc, GEM_MII_DATAPATH_MODE, 4, 280212725Smarius BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 281212725Smarius } 282172334Smarius 28391398Stmm gem_mifinit(sc); 28491398Stmm 285172334Smarius /* 286172334Smarius * Look for an external PHY. 287172334Smarius */ 288172334Smarius error = ENXIO; 289177560Smarius v = GEM_BANK1_READ_4(sc, GEM_MIF_CONFIG); 290172334Smarius if ((v & GEM_MIF_CONFIG_MDI1) != 0) { 291172334Smarius v |= GEM_MIF_CONFIG_PHY_SEL; 292177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MIF_CONFIG, v); 293212725Smarius GEM_BANK1_BARRIER(sc, GEM_MIF_CONFIG, 4, 294212725Smarius BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 295172334Smarius switch (sc->sc_variant) { 296172334Smarius case GEM_SUN_ERI: 297213893Smarius phy = GEM_PHYAD_EXTERNAL; 298172334Smarius break; 299172334Smarius default: 300213893Smarius phy = MII_PHY_ANY; 301172334Smarius break; 302172334Smarius } 303213893Smarius error = mii_attach(sc->sc_dev, &sc->sc_miibus, ifp, 304213893Smarius gem_mediachange, gem_mediastatus, BMSR_DEFCAPMASK, phy, 305215722Smarius MII_OFFSET_ANY, MIIF_DOPAUSE); 306172334Smarius } 307172334Smarius 308172334Smarius /* 309172334Smarius * Fall back on an internal PHY if no external PHY was found. 310204222Smarius * Note that with Apple (K2) GMACs GEM_MIF_CONFIG_MDI0 can't be 311204222Smarius * trusted when the firmware has powered down the chip. 312172334Smarius */ 313204222Smarius if (error != 0 && 314204222Smarius ((v & GEM_MIF_CONFIG_MDI0) != 0 || GEM_IS_APPLE(sc))) { 315172334Smarius v &= ~GEM_MIF_CONFIG_PHY_SEL; 316177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MIF_CONFIG, v); 317212725Smarius GEM_BANK1_BARRIER(sc, GEM_MIF_CONFIG, 4, 318212725Smarius BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 319172334Smarius switch (sc->sc_variant) { 320172334Smarius case GEM_SUN_ERI: 321172334Smarius case GEM_APPLE_K2_GMAC: 322213893Smarius phy = GEM_PHYAD_INTERNAL; 323172334Smarius break; 324172334Smarius case GEM_APPLE_GMAC: 325213893Smarius phy = GEM_PHYAD_EXTERNAL; 326172334Smarius break; 327172334Smarius default: 328213893Smarius phy = MII_PHY_ANY; 329172334Smarius break; 330172334Smarius } 331213893Smarius error = mii_attach(sc->sc_dev, &sc->sc_miibus, ifp, 332213893Smarius gem_mediachange, gem_mediastatus, BMSR_DEFCAPMASK, phy, 333215722Smarius MII_OFFSET_ANY, MIIF_DOPAUSE); 334172334Smarius } 335172334Smarius 336172334Smarius /* 337172334Smarius * Try the external PCS SERDES if we didn't find any PHYs. 338172334Smarius */ 339172334Smarius if (error != 0 && sc->sc_variant == GEM_SUN_GEM) { 340212725Smarius serdes: 341177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MII_DATAPATH_MODE, 342172334Smarius GEM_MII_DATAPATH_SERDES); 343212725Smarius GEM_BANK1_BARRIER(sc, GEM_MII_DATAPATH_MODE, 4, 344212725Smarius BUS_SPACE_BARRIER_WRITE); 345177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MII_SLINK_CONTROL, 346172334Smarius GEM_MII_SLINK_LOOPBACK | GEM_MII_SLINK_EN_SYNC_D); 347212725Smarius GEM_BANK1_BARRIER(sc, GEM_MII_SLINK_CONTROL, 4, 348212725Smarius BUS_SPACE_BARRIER_WRITE); 349177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MII_CONFIG, GEM_MII_CONFIG_ENABLE); 350212725Smarius GEM_BANK1_BARRIER(sc, GEM_MII_CONFIG, 4, 351212725Smarius BUS_SPACE_BARRIER_WRITE); 352172334Smarius sc->sc_flags |= GEM_SERDES; 353213893Smarius error = mii_attach(sc->sc_dev, &sc->sc_miibus, ifp, 354213893Smarius gem_mediachange, gem_mediastatus, BMSR_DEFCAPMASK, 355215722Smarius GEM_PHYAD_EXTERNAL, MII_OFFSET_ANY, MIIF_DOPAUSE); 356172334Smarius } 357172334Smarius if (error != 0) { 358213893Smarius device_printf(sc->sc_dev, "attaching PHYs failed\n"); 359108832Stmm goto fail_rxd; 36091398Stmm } 36191398Stmm sc->sc_mii = device_get_softc(sc->sc_miibus); 36291398Stmm 36391398Stmm /* 36491398Stmm * From this point forward, the attachment cannot fail. A failure 36591398Stmm * before this point releases all resources that may have been 36691398Stmm * allocated. 36791398Stmm */ 36891398Stmm 369176996Smarius /* Get RX FIFO size. */ 37099726Sbenno sc->sc_rxfifosize = 64 * 371177560Smarius GEM_BANK1_READ_4(sc, GEM_RX_FIFO_SIZE); 37299726Sbenno 373176996Smarius /* Get TX FIFO size. */ 374177560Smarius v = GEM_BANK1_READ_4(sc, GEM_TX_FIFO_SIZE); 375128588Stmm device_printf(sc->sc_dev, "%ukB RX FIFO, %ukB TX FIFO\n", 376128588Stmm sc->sc_rxfifosize / 1024, v / 16); 37799726Sbenno 37891398Stmm /* Attach the interface. */ 379147256Sbrooks ether_ifattach(ifp, sc->sc_enaddr); 38091398Stmm 38191398Stmm /* 382170273Syongari * Tell the upper layer(s) we support long frames/checksum offloads. 383149552Smarius */ 384149552Smarius ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header); 385170273Syongari ifp->if_capabilities |= IFCAP_VLAN_MTU | IFCAP_HWCSUM; 386170273Syongari ifp->if_hwassist |= sc->sc_csum_features; 387170273Syongari ifp->if_capenable |= IFCAP_VLAN_MTU | IFCAP_HWCSUM; 388149552Smarius 38991398Stmm return (0); 39091398Stmm 39191398Stmm /* 39291398Stmm * Free any resources we've allocated during the failed attach 39391398Stmm * attempt. Do this in reverse order and fall through. 39491398Stmm */ 395174987Smarius fail_rxd: 396174987Smarius for (i = 0; i < GEM_NRXDESC; i++) 39791398Stmm if (sc->sc_rxsoft[i].rxs_dmamap != NULL) 398108832Stmm bus_dmamap_destroy(sc->sc_rdmatag, 39991398Stmm sc->sc_rxsoft[i].rxs_dmamap); 400174987Smarius fail_txd: 401174987Smarius for (i = 0; i < GEM_TXQUEUELEN; i++) 40291398Stmm if (sc->sc_txsoft[i].txs_dmamap != NULL) 403108832Stmm bus_dmamap_destroy(sc->sc_tdmatag, 40491398Stmm sc->sc_txsoft[i].txs_dmamap); 405108832Stmm bus_dmamap_unload(sc->sc_cdmatag, sc->sc_cddmamap); 406174987Smarius fail_cmem: 40791398Stmm bus_dmamem_free(sc->sc_cdmatag, sc->sc_control_data, 40891398Stmm sc->sc_cddmamap); 409174987Smarius fail_ctag: 41091398Stmm bus_dma_tag_destroy(sc->sc_cdmatag); 411174987Smarius fail_ttag: 412108832Stmm bus_dma_tag_destroy(sc->sc_tdmatag); 413174987Smarius fail_rtag: 414108832Stmm bus_dma_tag_destroy(sc->sc_rdmatag); 415174987Smarius fail_ptag: 41691398Stmm bus_dma_tag_destroy(sc->sc_pdmatag); 417174987Smarius fail_ifnet: 418147256Sbrooks if_free(ifp); 41991398Stmm return (error); 42091398Stmm} 42191398Stmm 422108964Stmmvoid 423174987Smariusgem_detach(struct gem_softc *sc) 424108964Stmm{ 425147256Sbrooks struct ifnet *ifp = sc->sc_ifp; 426108964Stmm int i; 427108964Stmm 428194886Smarius ether_ifdetach(ifp); 429148369Smarius GEM_LOCK(sc); 430147317Sbrooks gem_stop(ifp, 1); 431148369Smarius GEM_UNLOCK(sc); 432150285Smarius callout_drain(&sc->sc_tick_ch); 433150285Smarius#ifdef GEM_RINT_TIMEOUT 434150285Smarius callout_drain(&sc->sc_rx_ch); 435150285Smarius#endif 436147256Sbrooks if_free(ifp); 437108964Stmm device_delete_child(sc->sc_dev, sc->sc_miibus); 438108964Stmm 439174987Smarius for (i = 0; i < GEM_NRXDESC; i++) 440108964Stmm if (sc->sc_rxsoft[i].rxs_dmamap != NULL) 441108964Stmm bus_dmamap_destroy(sc->sc_rdmatag, 442108964Stmm sc->sc_rxsoft[i].rxs_dmamap); 443174987Smarius for (i = 0; i < GEM_TXQUEUELEN; i++) 444108964Stmm if (sc->sc_txsoft[i].txs_dmamap != NULL) 445108964Stmm bus_dmamap_destroy(sc->sc_tdmatag, 446108964Stmm sc->sc_txsoft[i].txs_dmamap); 447179925Smarius GEM_CDSYNC(sc, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 448108964Stmm bus_dmamap_unload(sc->sc_cdmatag, sc->sc_cddmamap); 449108964Stmm bus_dmamem_free(sc->sc_cdmatag, sc->sc_control_data, 450108964Stmm sc->sc_cddmamap); 451108964Stmm bus_dma_tag_destroy(sc->sc_cdmatag); 452108964Stmm bus_dma_tag_destroy(sc->sc_tdmatag); 453108964Stmm bus_dma_tag_destroy(sc->sc_rdmatag); 454108964Stmm bus_dma_tag_destroy(sc->sc_pdmatag); 455108964Stmm} 456108964Stmm 457108964Stmmvoid 458174987Smariusgem_suspend(struct gem_softc *sc) 459108964Stmm{ 460147256Sbrooks struct ifnet *ifp = sc->sc_ifp; 461108964Stmm 462148369Smarius GEM_LOCK(sc); 463108964Stmm gem_stop(ifp, 0); 464148369Smarius GEM_UNLOCK(sc); 465108964Stmm} 466108964Stmm 467108964Stmmvoid 468174987Smariusgem_resume(struct gem_softc *sc) 469108964Stmm{ 470147256Sbrooks struct ifnet *ifp = sc->sc_ifp; 471108964Stmm 472148369Smarius GEM_LOCK(sc); 473149552Smarius /* 474149552Smarius * On resume all registers have to be initialized again like 475149552Smarius * after power-on. 476149552Smarius */ 477172334Smarius sc->sc_flags &= ~GEM_INITED; 478108964Stmm if (ifp->if_flags & IFF_UP) 479148369Smarius gem_init_locked(sc); 480148369Smarius GEM_UNLOCK(sc); 481108964Stmm} 482108964Stmm 483194763Smariusstatic inline void 484170273Syongarigem_rxcksum(struct mbuf *m, uint64_t flags) 485170273Syongari{ 486170273Syongari struct ether_header *eh; 487170273Syongari struct ip *ip; 488170273Syongari struct udphdr *uh; 489174987Smarius uint16_t *opts; 490170273Syongari int32_t hlen, len, pktlen; 491170273Syongari uint32_t temp32; 492174987Smarius uint16_t cksum; 493170273Syongari 494170273Syongari pktlen = m->m_pkthdr.len; 495170273Syongari if (pktlen < sizeof(struct ether_header) + sizeof(struct ip)) 496170273Syongari return; 497170273Syongari eh = mtod(m, struct ether_header *); 498170273Syongari if (eh->ether_type != htons(ETHERTYPE_IP)) 499170273Syongari return; 500170273Syongari ip = (struct ip *)(eh + 1); 501170273Syongari if (ip->ip_v != IPVERSION) 502170273Syongari return; 503170273Syongari 504170273Syongari hlen = ip->ip_hl << 2; 505170273Syongari pktlen -= sizeof(struct ether_header); 506170273Syongari if (hlen < sizeof(struct ip)) 507170273Syongari return; 508170273Syongari if (ntohs(ip->ip_len) < hlen) 509170273Syongari return; 510170273Syongari if (ntohs(ip->ip_len) != pktlen) 511170273Syongari return; 512170273Syongari if (ip->ip_off & htons(IP_MF | IP_OFFMASK)) 513174987Smarius return; /* Cannot handle fragmented packet. */ 514170273Syongari 515170273Syongari switch (ip->ip_p) { 516170273Syongari case IPPROTO_TCP: 517170273Syongari if (pktlen < (hlen + sizeof(struct tcphdr))) 518170273Syongari return; 519170273Syongari break; 520170273Syongari case IPPROTO_UDP: 521170273Syongari if (pktlen < (hlen + sizeof(struct udphdr))) 522170273Syongari return; 523170273Syongari uh = (struct udphdr *)((uint8_t *)ip + hlen); 524170273Syongari if (uh->uh_sum == 0) 525170273Syongari return; /* no checksum */ 526170273Syongari break; 527170273Syongari default: 528170273Syongari return; 529170273Syongari } 530170273Syongari 531170273Syongari cksum = ~(flags & GEM_RD_CHECKSUM); 532170273Syongari /* checksum fixup for IP options */ 533170273Syongari len = hlen - sizeof(struct ip); 534170273Syongari if (len > 0) { 535170273Syongari opts = (uint16_t *)(ip + 1); 536170273Syongari for (; len > 0; len -= sizeof(uint16_t), opts++) { 537170273Syongari temp32 = cksum - *opts; 538170273Syongari temp32 = (temp32 >> 16) + (temp32 & 65535); 539170273Syongari cksum = temp32 & 65535; 540170273Syongari } 541170273Syongari } 542170273Syongari m->m_pkthdr.csum_flags |= CSUM_DATA_VALID; 543170273Syongari m->m_pkthdr.csum_data = cksum; 544170273Syongari} 545170273Syongari 54691398Stmmstatic void 547174987Smariusgem_cddma_callback(void *xsc, bus_dma_segment_t *segs, int nsegs, int error) 54891398Stmm{ 549174987Smarius struct gem_softc *sc = xsc; 55091398Stmm 55191398Stmm if (error != 0) 55291398Stmm return; 553174987Smarius if (nsegs != 1) 554172334Smarius panic("%s: bad control buffer segment count", __func__); 55591398Stmm sc->sc_cddma = segs[0].ds_addr; 55691398Stmm} 55791398Stmm 55891398Stmmstatic void 559174987Smariusgem_tick(void *arg) 56091398Stmm{ 561170273Syongari struct gem_softc *sc = arg; 562194763Smarius struct ifnet *ifp = sc->sc_ifp; 563182060Smarius uint32_t v; 56491398Stmm 565170273Syongari GEM_LOCK_ASSERT(sc, MA_OWNED); 566170273Syongari 567108832Stmm /* 568182060Smarius * Unload collision and error counters. 569108832Stmm */ 570170273Syongari ifp->if_collisions += 571177560Smarius GEM_BANK1_READ_4(sc, GEM_MAC_NORM_COLL_CNT) + 572182060Smarius GEM_BANK1_READ_4(sc, GEM_MAC_FIRST_COLL_CNT); 573182060Smarius v = GEM_BANK1_READ_4(sc, GEM_MAC_EXCESS_COLL_CNT) + 574177560Smarius GEM_BANK1_READ_4(sc, GEM_MAC_LATE_COLL_CNT); 575182060Smarius ifp->if_collisions += v; 576182060Smarius ifp->if_oerrors += v; 577182060Smarius ifp->if_ierrors += 578182060Smarius GEM_BANK1_READ_4(sc, GEM_MAC_RX_LEN_ERR_CNT) + 579182060Smarius GEM_BANK1_READ_4(sc, GEM_MAC_RX_ALIGN_ERR) + 580182060Smarius GEM_BANK1_READ_4(sc, GEM_MAC_RX_CRC_ERR_CNT) + 581182060Smarius GEM_BANK1_READ_4(sc, GEM_MAC_RX_CODE_VIOL); 58291398Stmm 58391398Stmm /* 584176996Smarius * Then clear the hardware counters. 58591398Stmm */ 586177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_NORM_COLL_CNT, 0); 587177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_FIRST_COLL_CNT, 0); 588177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_EXCESS_COLL_CNT, 0); 589177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_LATE_COLL_CNT, 0); 590182060Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_LEN_ERR_CNT, 0); 591182060Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_ALIGN_ERR, 0); 592182060Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_CRC_ERR_CNT, 0); 593182060Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_CODE_VIOL, 0); 594108832Stmm 59591398Stmm mii_tick(sc->sc_mii); 59691398Stmm 597164931Smarius if (gem_watchdog(sc) == EJUSTRETURN) 598164931Smarius return; 599164931Smarius 60091398Stmm callout_reset(&sc->sc_tick_ch, hz, gem_tick, sc); 60191398Stmm} 60291398Stmm 60391398Stmmstatic int 604177560Smariusgem_bitwait(struct gem_softc *sc, u_int bank, bus_addr_t r, uint32_t clr, 605177560Smarius uint32_t set) 60691398Stmm{ 60791398Stmm int i; 608174987Smarius uint32_t reg; 60991398Stmm 610194763Smarius for (i = GEM_TRIES; i--; DELAY(100)) { 611177560Smarius reg = GEM_BANKN_READ_M(bank, 4, sc, r); 612170847Smarius if ((reg & clr) == 0 && (reg & set) == set) 61391398Stmm return (1); 61491398Stmm } 61591398Stmm return (0); 61691398Stmm} 61791398Stmm 618172334Smariusstatic void 619194763Smariusgem_reset(struct gem_softc *sc) 62091398Stmm{ 62191398Stmm 622115030Stmm#ifdef GEM_DEBUG 623170273Syongari CTR2(KTR_GEM, "%s: %s", device_get_name(sc->sc_dev), __func__); 624115030Stmm#endif 62591398Stmm gem_reset_rx(sc); 62691398Stmm gem_reset_tx(sc); 62791398Stmm 628174987Smarius /* Do a full reset. */ 629223944Smarius GEM_BANK2_WRITE_4(sc, GEM_RESET, GEM_RESET_RX | GEM_RESET_TX | 630223944Smarius (sc->sc_variant == GEM_SUN_ERI ? GEM_ERI_CACHE_LINE_SIZE << 631223944Smarius GEM_RESET_CLSZ_SHFT : 0)); 632179925Smarius GEM_BANK2_BARRIER(sc, GEM_RESET, 4, 633179925Smarius BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 634177560Smarius if (!GEM_BANK2_BITWAIT(sc, GEM_RESET, GEM_RESET_RX | GEM_RESET_TX, 0)) 63591398Stmm device_printf(sc->sc_dev, "cannot reset device\n"); 63691398Stmm} 63791398Stmm 63891398Stmmstatic void 639174987Smariusgem_rxdrain(struct gem_softc *sc) 64091398Stmm{ 64191398Stmm struct gem_rxsoft *rxs; 64291398Stmm int i; 64391398Stmm 64491398Stmm for (i = 0; i < GEM_NRXDESC; i++) { 64591398Stmm rxs = &sc->sc_rxsoft[i]; 64691398Stmm if (rxs->rxs_mbuf != NULL) { 647109648Stmm bus_dmamap_sync(sc->sc_rdmatag, rxs->rxs_dmamap, 648109648Stmm BUS_DMASYNC_POSTREAD); 649108832Stmm bus_dmamap_unload(sc->sc_rdmatag, rxs->rxs_dmamap); 65091398Stmm m_freem(rxs->rxs_mbuf); 65191398Stmm rxs->rxs_mbuf = NULL; 65291398Stmm } 65391398Stmm } 65491398Stmm} 65591398Stmm 65691398Stmmstatic void 657174987Smariusgem_stop(struct ifnet *ifp, int disable) 65891398Stmm{ 659174987Smarius struct gem_softc *sc = ifp->if_softc; 66091398Stmm struct gem_txsoft *txs; 66191398Stmm 662115030Stmm#ifdef GEM_DEBUG 663170273Syongari CTR2(KTR_GEM, "%s: %s", device_get_name(sc->sc_dev), __func__); 664115030Stmm#endif 66591398Stmm 66691398Stmm callout_stop(&sc->sc_tick_ch); 667150285Smarius#ifdef GEM_RINT_TIMEOUT 668150285Smarius callout_stop(&sc->sc_rx_ch); 669172334Smarius#endif 67091398Stmm 671194763Smarius gem_reset_tx(sc); 672194763Smarius gem_reset_rx(sc); 67391398Stmm 67491398Stmm /* 67591398Stmm * Release any queued transmit buffers. 67691398Stmm */ 67791398Stmm while ((txs = STAILQ_FIRST(&sc->sc_txdirtyq)) != NULL) { 67891398Stmm STAILQ_REMOVE_HEAD(&sc->sc_txdirtyq, txs_q); 67991398Stmm if (txs->txs_ndescs != 0) { 680109648Stmm bus_dmamap_sync(sc->sc_tdmatag, txs->txs_dmamap, 681109648Stmm BUS_DMASYNC_POSTWRITE); 682108832Stmm bus_dmamap_unload(sc->sc_tdmatag, txs->txs_dmamap); 68391398Stmm if (txs->txs_mbuf != NULL) { 68491398Stmm m_freem(txs->txs_mbuf); 68591398Stmm txs->txs_mbuf = NULL; 68691398Stmm } 68791398Stmm } 68891398Stmm STAILQ_INSERT_TAIL(&sc->sc_txfreeq, txs, txs_q); 68991398Stmm } 69091398Stmm 69191398Stmm if (disable) 69291398Stmm gem_rxdrain(sc); 69391398Stmm 69491398Stmm /* 69591398Stmm * Mark the interface down and cancel the watchdog timer. 69691398Stmm */ 697148887Srwatson ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); 698172334Smarius sc->sc_flags &= ~GEM_LINK; 699164931Smarius sc->sc_wdog_timer = 0; 70091398Stmm} 70191398Stmm 702172334Smariusstatic int 703174987Smariusgem_reset_rx(struct gem_softc *sc) 70491398Stmm{ 70591398Stmm 70691398Stmm /* 70791398Stmm * Resetting while DMA is in progress can cause a bus hang, so we 70891398Stmm * disable DMA first. 70991398Stmm */ 710223648Smarius (void)gem_disable_rx(sc); 711177560Smarius GEM_BANK1_WRITE_4(sc, GEM_RX_CONFIG, 0); 712179925Smarius GEM_BANK1_BARRIER(sc, GEM_RX_CONFIG, 4, 713179925Smarius BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 714177560Smarius if (!GEM_BANK1_BITWAIT(sc, GEM_RX_CONFIG, GEM_RX_CONFIG_RXDMA_EN, 0)) 715172334Smarius device_printf(sc->sc_dev, "cannot disable RX DMA\n"); 71691398Stmm 717215722Smarius /* Wait 5ms extra. */ 718215722Smarius DELAY(5000); 719215722Smarius 720223648Smarius /* Reset the ERX. */ 721223944Smarius GEM_BANK2_WRITE_4(sc, GEM_RESET, GEM_RESET_RX | 722223944Smarius (sc->sc_variant == GEM_SUN_ERI ? GEM_ERI_CACHE_LINE_SIZE << 723223944Smarius GEM_RESET_CLSZ_SHFT : 0)); 724179925Smarius GEM_BANK2_BARRIER(sc, GEM_RESET, 4, 725179925Smarius BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 726223944Smarius if (!GEM_BANK2_BITWAIT(sc, GEM_RESET, GEM_RESET_RX, 0)) { 72791398Stmm device_printf(sc->sc_dev, "cannot reset receiver\n"); 72891398Stmm return (1); 72991398Stmm } 730223648Smarius 731223648Smarius /* Finally, reset RX MAC. */ 732223648Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_RXRESET, 1); 733223648Smarius GEM_BANK1_BARRIER(sc, GEM_MAC_RXRESET, 4, 734223648Smarius BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 735223648Smarius if (!GEM_BANK1_BITWAIT(sc, GEM_MAC_RXRESET, 1, 0)) { 736223648Smarius device_printf(sc->sc_dev, "cannot reset RX MAC\n"); 737223648Smarius return (1); 738223648Smarius } 739223648Smarius 74091398Stmm return (0); 74191398Stmm} 74291398Stmm 743172334Smarius/* 744172334Smarius * Reset the receiver DMA engine. 745172334Smarius * 746172334Smarius * Intended to be used in case of GEM_INTR_RX_TAG_ERR, GEM_MAC_RX_OVERFLOW 747172334Smarius * etc in order to reset the receiver DMA engine only and not do a full 748172334Smarius * reset which amongst others also downs the link and clears the FIFOs. 749172334Smarius */ 750172334Smariusstatic void 751172334Smariusgem_reset_rxdma(struct gem_softc *sc) 752172334Smarius{ 753172334Smarius int i; 75491398Stmm 755222135Syongari if (gem_reset_rx(sc) != 0) { 756222135Syongari sc->sc_ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 757172334Smarius return (gem_init_locked(sc)); 758222135Syongari } 759172334Smarius for (i = 0; i < GEM_NRXDESC; i++) 760172334Smarius if (sc->sc_rxsoft[i].rxs_mbuf != NULL) 761172334Smarius GEM_UPDATE_RXDESC(sc, i); 762172334Smarius sc->sc_rxptr = 0; 763194763Smarius GEM_CDSYNC(sc, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 764172334Smarius 765172334Smarius /* NOTE: we use only 32-bit DMA addresses here. */ 766177560Smarius GEM_BANK1_WRITE_4(sc, GEM_RX_RING_PTR_HI, 0); 767177560Smarius GEM_BANK1_WRITE_4(sc, GEM_RX_RING_PTR_LO, GEM_CDRXADDR(sc, 0)); 768177560Smarius GEM_BANK1_WRITE_4(sc, GEM_RX_KICK, GEM_NRXDESC - 4); 769177560Smarius GEM_BANK1_WRITE_4(sc, GEM_RX_CONFIG, 770174987Smarius gem_ringsize(GEM_NRXDESC /* XXX */) | 771172334Smarius ((ETHER_HDR_LEN + sizeof(struct ip)) << 772172334Smarius GEM_RX_CONFIG_CXM_START_SHFT) | 773172334Smarius (GEM_THRSH_1024 << GEM_RX_CONFIG_FIFO_THRS_SHIFT) | 774194763Smarius (ETHER_ALIGN << GEM_RX_CONFIG_FBOFF_SHFT)); 775194763Smarius /* Adjust for the SBus clock probably isn't worth the fuzz. */ 776177560Smarius GEM_BANK1_WRITE_4(sc, GEM_RX_BLANKING, 777194763Smarius ((6 * (sc->sc_flags & GEM_PCI66) != 0 ? 2 : 1) << 778194763Smarius GEM_RX_BLANKING_TIME_SHIFT) | 6); 779177560Smarius GEM_BANK1_WRITE_4(sc, GEM_RX_PAUSE_THRESH, 780174987Smarius (3 * sc->sc_rxfifosize / 256) | 781174987Smarius ((sc->sc_rxfifosize / 256) << 12)); 782223648Smarius /* 783223648Smarius * Clear the RX filter and reprogram it. This will also set the 784223648Smarius * current RX MAC configuration. 785223648Smarius */ 786223648Smarius gem_setladrf(sc, 0); 787177560Smarius GEM_BANK1_WRITE_4(sc, GEM_RX_CONFIG, 788177560Smarius GEM_BANK1_READ_4(sc, GEM_RX_CONFIG) | GEM_RX_CONFIG_RXDMA_EN); 789177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_MASK, 790172334Smarius GEM_MAC_RX_DONE | GEM_MAC_RX_FRAME_CNT); 791177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_CONFIG, 792223648Smarius sc->sc_mac_rxcfg | GEM_MAC_RX_ENABLE); 793172334Smarius} 794172334Smarius 79591398Stmmstatic int 796174987Smariusgem_reset_tx(struct gem_softc *sc) 79791398Stmm{ 79891398Stmm 79991398Stmm /* 80091398Stmm * Resetting while DMA is in progress can cause a bus hang, so we 80191398Stmm * disable DMA first. 80291398Stmm */ 803223648Smarius (void)gem_disable_tx(sc); 804177560Smarius GEM_BANK1_WRITE_4(sc, GEM_TX_CONFIG, 0); 805179925Smarius GEM_BANK1_BARRIER(sc, GEM_TX_CONFIG, 4, 806179925Smarius BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 807177560Smarius if (!GEM_BANK1_BITWAIT(sc, GEM_TX_CONFIG, GEM_TX_CONFIG_TXDMA_EN, 0)) 808172334Smarius device_printf(sc->sc_dev, "cannot disable TX DMA\n"); 80991398Stmm 810215722Smarius /* Wait 5ms extra. */ 811215722Smarius DELAY(5000); 812215722Smarius 813176996Smarius /* Finally, reset the ETX. */ 814223944Smarius GEM_BANK2_WRITE_4(sc, GEM_RESET, GEM_RESET_TX | 815223944Smarius (sc->sc_variant == GEM_SUN_ERI ? GEM_ERI_CACHE_LINE_SIZE << 816223944Smarius GEM_RESET_CLSZ_SHFT : 0)); 817179925Smarius GEM_BANK2_BARRIER(sc, GEM_RESET, 4, 818179925Smarius BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 819223944Smarius if (!GEM_BANK2_BITWAIT(sc, GEM_RESET, GEM_RESET_TX, 0)) { 820172334Smarius device_printf(sc->sc_dev, "cannot reset transmitter\n"); 82191398Stmm return (1); 82291398Stmm } 82391398Stmm return (0); 82491398Stmm} 82591398Stmm 82691398Stmmstatic int 827174987Smariusgem_disable_rx(struct gem_softc *sc) 82891398Stmm{ 82991398Stmm 830177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_CONFIG, 831177560Smarius GEM_BANK1_READ_4(sc, GEM_MAC_RX_CONFIG) & ~GEM_MAC_RX_ENABLE); 832179925Smarius GEM_BANK1_BARRIER(sc, GEM_MAC_RX_CONFIG, 4, 833179925Smarius BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 834223648Smarius if (GEM_BANK1_BITWAIT(sc, GEM_MAC_RX_CONFIG, GEM_MAC_RX_ENABLE, 0)) 835223648Smarius return (1); 836223648Smarius device_printf(sc->sc_dev, "cannot disable RX MAC\n"); 837223648Smarius return (0); 83891398Stmm} 83991398Stmm 84091398Stmmstatic int 841174987Smariusgem_disable_tx(struct gem_softc *sc) 84291398Stmm{ 84391398Stmm 844177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_TX_CONFIG, 845177560Smarius GEM_BANK1_READ_4(sc, GEM_MAC_TX_CONFIG) & ~GEM_MAC_TX_ENABLE); 846179925Smarius GEM_BANK1_BARRIER(sc, GEM_MAC_TX_CONFIG, 4, 847179925Smarius BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 848223648Smarius if (GEM_BANK1_BITWAIT(sc, GEM_MAC_TX_CONFIG, GEM_MAC_TX_ENABLE, 0)) 849223648Smarius return (1); 850223648Smarius device_printf(sc->sc_dev, "cannot disable TX MAC\n"); 851223648Smarius return (0); 85291398Stmm} 85391398Stmm 85491398Stmmstatic int 855194763Smariusgem_meminit(struct gem_softc *sc) 85691398Stmm{ 85791398Stmm struct gem_rxsoft *rxs; 858174987Smarius int error, i; 85991398Stmm 860194763Smarius GEM_LOCK_ASSERT(sc, MA_OWNED); 861194763Smarius 86291398Stmm /* 86391398Stmm * Initialize the transmit descriptor ring. 86491398Stmm */ 86591398Stmm for (i = 0; i < GEM_NTXDESC; i++) { 86691398Stmm sc->sc_txdescs[i].gd_flags = 0; 86791398Stmm sc->sc_txdescs[i].gd_addr = 0; 86891398Stmm } 869108832Stmm sc->sc_txfree = GEM_MAXTXFREE; 87091398Stmm sc->sc_txnext = 0; 87199726Sbenno sc->sc_txwin = 0; 87291398Stmm 87391398Stmm /* 87491398Stmm * Initialize the receive descriptor and receive job 87591398Stmm * descriptor rings. 87691398Stmm */ 87791398Stmm for (i = 0; i < GEM_NRXDESC; i++) { 87891398Stmm rxs = &sc->sc_rxsoft[i]; 87991398Stmm if (rxs->rxs_mbuf == NULL) { 88091398Stmm if ((error = gem_add_rxbuf(sc, i)) != 0) { 881174987Smarius device_printf(sc->sc_dev, 882174987Smarius "unable to allocate or map RX buffer %d, " 883174987Smarius "error = %d\n", i, error); 88491398Stmm /* 885174987Smarius * XXX we should attempt to run with fewer 886174987Smarius * receive buffers instead of just failing. 88791398Stmm */ 88891398Stmm gem_rxdrain(sc); 88991398Stmm return (1); 89091398Stmm } 89191398Stmm } else 89291398Stmm GEM_INIT_RXDESC(sc, i); 89391398Stmm } 89491398Stmm sc->sc_rxptr = 0; 89591398Stmm 896194763Smarius GEM_CDSYNC(sc, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 897194763Smarius 89891398Stmm return (0); 89991398Stmm} 90091398Stmm 901172334Smariusstatic u_int 902174987Smariusgem_ringsize(u_int sz) 90391398Stmm{ 90491398Stmm 90591398Stmm switch (sz) { 90691398Stmm case 32: 907172334Smarius return (GEM_RING_SZ_32); 90891398Stmm case 64: 909172334Smarius return (GEM_RING_SZ_64); 91091398Stmm case 128: 911172334Smarius return (GEM_RING_SZ_128); 91291398Stmm case 256: 913172334Smarius return (GEM_RING_SZ_256); 91491398Stmm case 512: 915172334Smarius return (GEM_RING_SZ_512); 91691398Stmm case 1024: 917172334Smarius return (GEM_RING_SZ_1024); 91891398Stmm case 2048: 919172334Smarius return (GEM_RING_SZ_2048); 92091398Stmm case 4096: 921172334Smarius return (GEM_RING_SZ_4096); 92291398Stmm case 8192: 923172334Smarius return (GEM_RING_SZ_8192); 92491398Stmm default: 925172334Smarius printf("%s: invalid ring size %d\n", __func__, sz); 926172334Smarius return (GEM_RING_SZ_32); 92791398Stmm } 92891398Stmm} 92991398Stmm 930148369Smariusstatic void 931174987Smariusgem_init(void *xsc) 932148369Smarius{ 933174987Smarius struct gem_softc *sc = xsc; 934148369Smarius 935148369Smarius GEM_LOCK(sc); 936148369Smarius gem_init_locked(sc); 937148369Smarius GEM_UNLOCK(sc); 938148369Smarius} 939148369Smarius 94091398Stmm/* 94191398Stmm * Initialization of interface; set up initialization block 94291398Stmm * and transmit/receive descriptor rings. 94391398Stmm */ 94491398Stmmstatic void 945174987Smariusgem_init_locked(struct gem_softc *sc) 94691398Stmm{ 947147256Sbrooks struct ifnet *ifp = sc->sc_ifp; 948174987Smarius uint32_t v; 94991398Stmm 950148369Smarius GEM_LOCK_ASSERT(sc, MA_OWNED); 95191398Stmm 952222135Syongari if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) 953222135Syongari return; 954222135Syongari 955115030Stmm#ifdef GEM_DEBUG 956170273Syongari CTR2(KTR_GEM, "%s: %s: calling stop", device_get_name(sc->sc_dev), 957170273Syongari __func__); 958115030Stmm#endif 95991398Stmm /* 960174987Smarius * Initialization sequence. The numbered steps below correspond 96191398Stmm * to the sequence outlined in section 6.3.5.1 in the Ethernet 96291398Stmm * Channel Engine manual (part of the PCIO manual). 96391398Stmm * See also the STP2002-STQ document from Sun Microsystems. 96491398Stmm */ 96591398Stmm 966174987Smarius /* step 1 & 2. Reset the Ethernet Channel. */ 967179925Smarius gem_stop(ifp, 0); 96891398Stmm gem_reset(sc); 969115030Stmm#ifdef GEM_DEBUG 970170273Syongari CTR2(KTR_GEM, "%s: %s: restarting", device_get_name(sc->sc_dev), 971170273Syongari __func__); 972115030Stmm#endif 97391398Stmm 974212725Smarius if ((sc->sc_flags & GEM_SERDES) == 0) 975212725Smarius /* Re-initialize the MIF. */ 976212725Smarius gem_mifinit(sc); 97791398Stmm 978174987Smarius /* step 3. Setup data structures in host memory. */ 979172334Smarius if (gem_meminit(sc) != 0) 980172334Smarius return; 98191398Stmm 982174987Smarius /* step 4. TX MAC registers & counters */ 98391398Stmm gem_init_regs(sc); 98491398Stmm 985174987Smarius /* step 5. RX MAC registers & counters */ 986223648Smarius gem_setladrf(sc, 0); 98791398Stmm 988174987Smarius /* step 6 & 7. Program Descriptor Ring Base Addresses. */ 98991398Stmm /* NOTE: we use only 32-bit DMA addresses here. */ 990177560Smarius GEM_BANK1_WRITE_4(sc, GEM_TX_RING_PTR_HI, 0); 991177560Smarius GEM_BANK1_WRITE_4(sc, GEM_TX_RING_PTR_LO, GEM_CDTXADDR(sc, 0)); 99291398Stmm 993177560Smarius GEM_BANK1_WRITE_4(sc, GEM_RX_RING_PTR_HI, 0); 994177560Smarius GEM_BANK1_WRITE_4(sc, GEM_RX_RING_PTR_LO, GEM_CDRXADDR(sc, 0)); 995115030Stmm#ifdef GEM_DEBUG 996174987Smarius CTR3(KTR_GEM, "loading RX ring %lx, TX ring %lx, cddma %lx", 99791398Stmm GEM_CDRXADDR(sc, 0), GEM_CDTXADDR(sc, 0), sc->sc_cddma); 998115030Stmm#endif 99991398Stmm 1000174987Smarius /* step 8. Global Configuration & Interrupt Mask */ 1001194763Smarius 1002194763Smarius /* 1003194763Smarius * Set the internal arbitration to "infinite" bursts of the 1004194763Smarius * maximum length of 31 * 64 bytes so DMA transfers aren't 1005194763Smarius * split up in cache line size chunks. This greatly improves 1006194763Smarius * RX performance. 1007194763Smarius * Enable silicon bug workarounds for the Apple variants. 1008194763Smarius */ 1009194763Smarius GEM_BANK1_WRITE_4(sc, GEM_CONFIG, 1010194763Smarius GEM_CONFIG_TXDMA_LIMIT | GEM_CONFIG_RXDMA_LIMIT | 1011194763Smarius ((sc->sc_flags & GEM_PCI) != 0 ? GEM_CONFIG_BURST_INF : 1012194763Smarius GEM_CONFIG_BURST_64) | (GEM_IS_APPLE(sc) ? 1013194763Smarius GEM_CONFIG_RONPAULBIT | GEM_CONFIG_BUG2FIX : 0)); 1014194763Smarius 1015177560Smarius GEM_BANK1_WRITE_4(sc, GEM_INTMASK, 1016172334Smarius ~(GEM_INTR_TX_INTME | GEM_INTR_TX_EMPTY | GEM_INTR_RX_DONE | 1017172334Smarius GEM_INTR_RX_NOBUF | GEM_INTR_RX_TAG_ERR | GEM_INTR_PERR | 1018172334Smarius GEM_INTR_BERR 1019172334Smarius#ifdef GEM_DEBUG 1020172334Smarius | GEM_INTR_PCS | GEM_INTR_MIF 1021172334Smarius#endif 1022172334Smarius )); 1023177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_MASK, 1024172334Smarius GEM_MAC_RX_DONE | GEM_MAC_RX_FRAME_CNT); 1025177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_TX_MASK, 1026194763Smarius GEM_MAC_TX_XMIT_DONE | GEM_MAC_TX_DEFER_EXP | 1027194763Smarius GEM_MAC_TX_PEAK_EXP); 1028172334Smarius#ifdef GEM_DEBUG 1029177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_CONTROL_MASK, 1030172334Smarius ~(GEM_MAC_PAUSED | GEM_MAC_PAUSE | GEM_MAC_RESUME)); 1031172334Smarius#else 1032177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_CONTROL_MASK, 1033172334Smarius GEM_MAC_PAUSED | GEM_MAC_PAUSE | GEM_MAC_RESUME); 1034172334Smarius#endif 103591398Stmm 1036174987Smarius /* step 9. ETX Configuration: use mostly default values. */ 103791398Stmm 1038174987Smarius /* Enable DMA. */ 1039194763Smarius v = gem_ringsize(GEM_NTXDESC); 1040194763Smarius /* Set TX FIFO threshold and enable DMA. */ 1041179925Smarius v |= ((sc->sc_variant == GEM_SUN_ERI ? 0x100 : 0x4ff) << 10) & 1042179925Smarius GEM_TX_CONFIG_TXFIFO_TH; 1043179925Smarius GEM_BANK1_WRITE_4(sc, GEM_TX_CONFIG, v | GEM_TX_CONFIG_TXDMA_EN); 104491398Stmm 1045174987Smarius /* step 10. ERX Configuration */ 104691398Stmm 1047172334Smarius /* Encode Receive Descriptor ring size. */ 1048174987Smarius v = gem_ringsize(GEM_NRXDESC /* XXX */); 1049174987Smarius /* RX TCP/UDP checksum offset */ 1050170273Syongari v |= ((ETHER_HDR_LEN + sizeof(struct ip)) << 1051170273Syongari GEM_RX_CONFIG_CXM_START_SHFT); 1052194763Smarius /* Set RX FIFO threshold, set first byte offset and enable DMA. */ 1053177560Smarius GEM_BANK1_WRITE_4(sc, GEM_RX_CONFIG, 1054174987Smarius v | (GEM_THRSH_1024 << GEM_RX_CONFIG_FIFO_THRS_SHIFT) | 1055194763Smarius (ETHER_ALIGN << GEM_RX_CONFIG_FBOFF_SHFT) | 1056194763Smarius GEM_RX_CONFIG_RXDMA_EN); 1057172334Smarius 1058194763Smarius /* Adjust for the SBus clock probably isn't worth the fuzz. */ 1059177560Smarius GEM_BANK1_WRITE_4(sc, GEM_RX_BLANKING, 1060194763Smarius ((6 * (sc->sc_flags & GEM_PCI66) != 0 ? 2 : 1) << 1061194763Smarius GEM_RX_BLANKING_TIME_SHIFT) | 6); 1062172334Smarius 106391398Stmm /* 106499726Sbenno * The following value is for an OFF Threshold of about 3/4 full 106599726Sbenno * and an ON Threshold of 1/4 full. 106691398Stmm */ 1067177560Smarius GEM_BANK1_WRITE_4(sc, GEM_RX_PAUSE_THRESH, 106899726Sbenno (3 * sc->sc_rxfifosize / 256) | 1069174987Smarius ((sc->sc_rxfifosize / 256) << 12)); 107091398Stmm 1071174987Smarius /* step 11. Configure Media. */ 107291398Stmm 1073174987Smarius /* step 12. RX_MAC Configuration Register */ 1074177560Smarius v = GEM_BANK1_READ_4(sc, GEM_MAC_RX_CONFIG); 1075179925Smarius v |= GEM_MAC_RX_ENABLE | GEM_MAC_RX_STRIP_CRC; 1076223648Smarius (void)gem_disable_rx(sc); 1077223648Smarius sc->sc_mac_rxcfg = v & ~GEM_MAC_RX_ENABLE; 1078177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_CONFIG, v); 107991398Stmm 1080194763Smarius /* step 13. TX_MAC Configuration Register */ 1081179925Smarius v = GEM_BANK1_READ_4(sc, GEM_MAC_TX_CONFIG); 1082179925Smarius v |= GEM_MAC_TX_ENABLE; 1083223648Smarius (void)gem_disable_tx(sc); 1084179925Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_TX_CONFIG, v); 1085179925Smarius 1086174987Smarius /* step 14. Issue Transmit Pending command. */ 108791398Stmm 1088220941Smarius /* step 15. Give the receiver a swift kick. */ 1089177560Smarius GEM_BANK1_WRITE_4(sc, GEM_RX_KICK, GEM_NRXDESC - 4); 109091398Stmm 1091172334Smarius ifp->if_drv_flags |= IFF_DRV_RUNNING; 1092172334Smarius ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 1093172334Smarius 1094172334Smarius mii_mediachg(sc->sc_mii); 1095172334Smarius 109691398Stmm /* Start the one second timer. */ 1097164931Smarius sc->sc_wdog_timer = 0; 109891398Stmm callout_reset(&sc->sc_tick_ch, hz, gem_tick, sc); 109991398Stmm} 110091398Stmm 110191398Stmmstatic int 1102174987Smariusgem_load_txmbuf(struct gem_softc *sc, struct mbuf **m_head) 110391398Stmm{ 1104174987Smarius bus_dma_segment_t txsegs[GEM_NTXSEGS]; 110591398Stmm struct gem_txsoft *txs; 1106179925Smarius struct ip *ip; 1107170273Syongari struct mbuf *m; 1108174987Smarius uint64_t cflags, flags; 1109179925Smarius int error, nexttx, nsegs, offset, seg; 111091398Stmm 1111194763Smarius GEM_LOCK_ASSERT(sc, MA_OWNED); 1112194763Smarius 1113108832Stmm /* Get a work queue entry. */ 1114108832Stmm if ((txs = STAILQ_FIRST(&sc->sc_txfreeq)) == NULL) { 1115108832Stmm /* Ran out of descriptors. */ 1116170273Syongari return (ENOBUFS); 1117108832Stmm } 1118179925Smarius 1119179925Smarius cflags = 0; 1120179925Smarius if (((*m_head)->m_pkthdr.csum_flags & sc->sc_csum_features) != 0) { 1121179925Smarius if (M_WRITABLE(*m_head) == 0) { 1122179925Smarius m = m_dup(*m_head, M_DONTWAIT); 1123179925Smarius m_freem(*m_head); 1124179925Smarius *m_head = m; 1125179925Smarius if (m == NULL) 1126179925Smarius return (ENOBUFS); 1127179925Smarius } 1128179925Smarius offset = sizeof(struct ether_header); 1129179925Smarius m = m_pullup(*m_head, offset + sizeof(struct ip)); 1130179925Smarius if (m == NULL) { 1131179925Smarius *m_head = NULL; 1132179925Smarius return (ENOBUFS); 1133179925Smarius } 1134179925Smarius ip = (struct ip *)(mtod(m, caddr_t) + offset); 1135179925Smarius offset += (ip->ip_hl << 2); 1136179925Smarius cflags = offset << GEM_TD_CXSUM_STARTSHFT | 1137179925Smarius ((offset + m->m_pkthdr.csum_data) << 1138179925Smarius GEM_TD_CXSUM_STUFFSHFT) | GEM_TD_CXSUM_ENABLE; 1139179925Smarius *m_head = m; 1140179925Smarius } 1141179925Smarius 1142170273Syongari error = bus_dmamap_load_mbuf_sg(sc->sc_tdmatag, txs->txs_dmamap, 1143170273Syongari *m_head, txsegs, &nsegs, BUS_DMA_NOWAIT); 1144170273Syongari if (error == EFBIG) { 1145175418Sjhb m = m_collapse(*m_head, M_DONTWAIT, GEM_NTXSEGS); 1146170273Syongari if (m == NULL) { 1147170273Syongari m_freem(*m_head); 1148170273Syongari *m_head = NULL; 1149170273Syongari return (ENOBUFS); 1150170273Syongari } 1151170273Syongari *m_head = m; 1152174987Smarius error = bus_dmamap_load_mbuf_sg(sc->sc_tdmatag, 1153174987Smarius txs->txs_dmamap, *m_head, txsegs, &nsegs, 1154174987Smarius BUS_DMA_NOWAIT); 1155170273Syongari if (error != 0) { 1156170273Syongari m_freem(*m_head); 1157170273Syongari *m_head = NULL; 1158170273Syongari return (error); 1159170273Syongari } 1160170273Syongari } else if (error != 0) 1161170273Syongari return (error); 1162176996Smarius /* If nsegs is wrong then the stack is corrupt. */ 1163176996Smarius KASSERT(nsegs <= GEM_NTXSEGS, 1164176996Smarius ("%s: too many DMA segments (%d)", __func__, nsegs)); 1165170273Syongari if (nsegs == 0) { 1166170273Syongari m_freem(*m_head); 1167170273Syongari *m_head = NULL; 1168170273Syongari return (EIO); 1169170273Syongari } 1170170273Syongari 1171170273Syongari /* 1172170273Syongari * Ensure we have enough descriptors free to describe 1173170273Syongari * the packet. Note, we always reserve one descriptor 1174174987Smarius * at the end of the ring as a termination point, in 1175174987Smarius * order to prevent wrap-around. 1176170273Syongari */ 1177170273Syongari if (nsegs > sc->sc_txfree - 1) { 1178170273Syongari txs->txs_ndescs = 0; 1179170273Syongari bus_dmamap_unload(sc->sc_tdmatag, txs->txs_dmamap); 1180170273Syongari return (ENOBUFS); 1181170273Syongari } 1182170273Syongari 1183170273Syongari txs->txs_ndescs = nsegs; 1184108832Stmm txs->txs_firstdesc = sc->sc_txnext; 1185170273Syongari nexttx = txs->txs_firstdesc; 1186170273Syongari for (seg = 0; seg < nsegs; seg++, nexttx = GEM_NEXTTX(nexttx)) { 1187172334Smarius#ifdef GEM_DEBUG 1188174987Smarius CTR6(KTR_GEM, 1189174987Smarius "%s: mapping seg %d (txd %d), len %lx, addr %#lx (%#lx)", 1190174987Smarius __func__, seg, nexttx, txsegs[seg].ds_len, 1191174987Smarius txsegs[seg].ds_addr, 1192170273Syongari GEM_DMA_WRITE(sc, txsegs[seg].ds_addr)); 1193170273Syongari#endif 1194170273Syongari sc->sc_txdescs[nexttx].gd_addr = 1195170273Syongari GEM_DMA_WRITE(sc, txsegs[seg].ds_addr); 1196170273Syongari KASSERT(txsegs[seg].ds_len < GEM_TD_BUFSIZE, 1197170273Syongari ("%s: segment size too large!", __func__)); 1198170273Syongari flags = txsegs[seg].ds_len & GEM_TD_BUFSIZE; 1199170273Syongari sc->sc_txdescs[nexttx].gd_flags = 1200170273Syongari GEM_DMA_WRITE(sc, flags | cflags); 1201170273Syongari txs->txs_lastdesc = nexttx; 120291398Stmm } 120391398Stmm 1204174987Smarius /* Set EOP on the last descriptor. */ 1205172334Smarius#ifdef GEM_DEBUG 1206174987Smarius CTR3(KTR_GEM, "%s: end of packet at segment %d, TX %d", 1207174987Smarius __func__, seg, nexttx); 1208170273Syongari#endif 1209170273Syongari sc->sc_txdescs[txs->txs_lastdesc].gd_flags |= 1210170273Syongari GEM_DMA_WRITE(sc, GEM_TD_END_OF_PACKET); 1211170273Syongari 1212174987Smarius /* Lastly set SOP on the first descriptor. */ 1213172334Smarius#ifdef GEM_DEBUG 1214174987Smarius CTR3(KTR_GEM, "%s: start of packet at segment %d, TX %d", 1215174987Smarius __func__, seg, nexttx); 1216170273Syongari#endif 1217170273Syongari if (++sc->sc_txwin > GEM_NTXSEGS * 2 / 3) { 1218170273Syongari sc->sc_txwin = 0; 1219170273Syongari sc->sc_txdescs[txs->txs_firstdesc].gd_flags |= 1220170273Syongari GEM_DMA_WRITE(sc, GEM_TD_INTERRUPT_ME | 1221170273Syongari GEM_TD_START_OF_PACKET); 1222170273Syongari } else 1223170273Syongari sc->sc_txdescs[txs->txs_firstdesc].gd_flags |= 1224170273Syongari GEM_DMA_WRITE(sc, GEM_TD_START_OF_PACKET); 1225170273Syongari 1226108832Stmm /* Sync the DMA map. */ 1227174987Smarius bus_dmamap_sync(sc->sc_tdmatag, txs->txs_dmamap, 1228174987Smarius BUS_DMASYNC_PREWRITE); 122991398Stmm 1230115030Stmm#ifdef GEM_DEBUG 1231170273Syongari CTR4(KTR_GEM, "%s: setting firstdesc=%d, lastdesc=%d, ndescs=%d", 1232174987Smarius __func__, txs->txs_firstdesc, txs->txs_lastdesc, 1233174987Smarius txs->txs_ndescs); 1234115030Stmm#endif 1235108832Stmm STAILQ_REMOVE_HEAD(&sc->sc_txfreeq, txs_q); 1236108832Stmm STAILQ_INSERT_TAIL(&sc->sc_txdirtyq, txs, txs_q); 1237170273Syongari txs->txs_mbuf = *m_head; 123891398Stmm 1239108832Stmm sc->sc_txnext = GEM_NEXTTX(txs->txs_lastdesc); 1240108832Stmm sc->sc_txfree -= txs->txs_ndescs; 1241170273Syongari 1242108832Stmm return (0); 124391398Stmm} 124491398Stmm 124591398Stmmstatic void 1246174987Smariusgem_init_regs(struct gem_softc *sc) 124791398Stmm{ 1248152315Sru const u_char *laddr = IF_LLADDR(sc->sc_ifp); 124991398Stmm 1250194763Smarius GEM_LOCK_ASSERT(sc, MA_OWNED); 1251194763Smarius 1252174987Smarius /* These registers are not cleared on reset. */ 1253172334Smarius if ((sc->sc_flags & GEM_INITED) == 0) { 1254174987Smarius /* magic values */ 1255177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_IPG0, 0); 1256177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_IPG1, 8); 1257177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_IPG2, 4); 125891398Stmm 1259194763Smarius /* min frame length */ 1260177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_MAC_MIN_FRAME, ETHER_MIN_LEN); 1261194763Smarius /* max frame length and max burst size */ 1262177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_MAC_MAX_FRAME, 1263172334Smarius (ETHER_MAX_LEN + ETHER_VLAN_ENCAP_LEN) | (0x2000 << 16)); 126499726Sbenno 1265194763Smarius /* more magic values */ 1266177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_PREAMBLE_LEN, 0x7); 1267177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_JAM_SIZE, 0x4); 1268177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_ATTEMPT_LIMIT, 0x10); 1269215722Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_CONTROL_TYPE, 0x8808); 1270194763Smarius 1271194763Smarius /* random number seed */ 1272177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_RANDOM_SEED, 1273174987Smarius ((laddr[5] << 8) | laddr[4]) & 0x3ff); 127499726Sbenno 1275174987Smarius /* secondary MAC address: 0:0:0:0:0:0 */ 1276177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_ADDR3, 0); 1277177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_ADDR4, 0); 1278177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_ADDR5, 0); 127999726Sbenno 1280174987Smarius /* MAC control address: 01:80:c2:00:00:01 */ 1281177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_ADDR6, 0x0001); 1282177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_ADDR7, 0xc200); 1283177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_ADDR8, 0x0180); 128491398Stmm 1285174987Smarius /* MAC filter address: 0:0:0:0:0:0 */ 1286177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_ADDR_FILTER0, 0); 1287177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_ADDR_FILTER1, 0); 1288177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_ADDR_FILTER2, 0); 1289177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_ADR_FLT_MASK1_2, 0); 1290177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_ADR_FLT_MASK0, 0); 129191398Stmm 1292172334Smarius sc->sc_flags |= GEM_INITED; 129391398Stmm } 129491398Stmm 1295174987Smarius /* Counters need to be zeroed. */ 1296177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_NORM_COLL_CNT, 0); 1297177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_FIRST_COLL_CNT, 0); 1298177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_EXCESS_COLL_CNT, 0); 1299177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_LATE_COLL_CNT, 0); 1300177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_DEFER_TMR_CNT, 0); 1301177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_PEAK_ATTEMPTS, 0); 1302177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_FRAME_COUNT, 0); 1303177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_LEN_ERR_CNT, 0); 1304177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_ALIGN_ERR, 0); 1305177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_CRC_ERR_CNT, 0); 1306177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_CODE_VIOL, 0); 130791398Stmm 1308172334Smarius /* Set XOFF PAUSE time. */ 1309177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_SEND_PAUSE_CMD, 0x1BF0); 131091398Stmm 1311174987Smarius /* Set the station address. */ 1312177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_ADDR0, (laddr[4] << 8) | laddr[5]); 1313177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_ADDR1, (laddr[2] << 8) | laddr[3]); 1314177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_ADDR2, (laddr[0] << 8) | laddr[1]); 131599726Sbenno 1316172334Smarius /* Enable MII outputs. */ 1317177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_XIF_CONFIG, GEM_MAC_XIF_TX_MII_ENA); 131891398Stmm} 131991398Stmm 132091398Stmmstatic void 1321174987Smariusgem_start(struct ifnet *ifp) 132291398Stmm{ 1323174987Smarius struct gem_softc *sc = ifp->if_softc; 1324148369Smarius 1325148369Smarius GEM_LOCK(sc); 1326148369Smarius gem_start_locked(ifp); 1327148369Smarius GEM_UNLOCK(sc); 1328148369Smarius} 1329148369Smarius 1330194763Smariusstatic inline void 1331194763Smariusgem_txkick(struct gem_softc *sc) 1332194763Smarius{ 1333194763Smarius 1334194763Smarius /* 1335194763Smarius * Update the TX kick register. This register has to point to the 1336194763Smarius * descriptor after the last valid one and for optimum performance 1337194763Smarius * should be incremented in multiples of 4 (the DMA engine fetches/ 1338194763Smarius * updates descriptors in batches of 4). 1339194763Smarius */ 1340194763Smarius#ifdef GEM_DEBUG 1341194763Smarius CTR3(KTR_GEM, "%s: %s: kicking TX %d", 1342194763Smarius device_get_name(sc->sc_dev), __func__, sc->sc_txnext); 1343194763Smarius#endif 1344194763Smarius GEM_CDSYNC(sc, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 1345194763Smarius GEM_BANK1_WRITE_4(sc, GEM_TX_KICK, sc->sc_txnext); 1346194763Smarius} 1347194763Smarius 1348148369Smariusstatic void 1349174987Smariusgem_start_locked(struct ifnet *ifp) 1350148369Smarius{ 1351174987Smarius struct gem_softc *sc = ifp->if_softc; 1352170273Syongari struct mbuf *m; 1353194763Smarius int kicked, ntx; 135491398Stmm 1355194763Smarius GEM_LOCK_ASSERT(sc, MA_OWNED); 1356194763Smarius 1357148887Srwatson if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) != 1358172334Smarius IFF_DRV_RUNNING || (sc->sc_flags & GEM_LINK) == 0) 135991398Stmm return; 136091398Stmm 1361115030Stmm#ifdef GEM_DEBUG 1362170273Syongari CTR4(KTR_GEM, "%s: %s: txfree %d, txnext %d", 1363172334Smarius device_get_name(sc->sc_dev), __func__, sc->sc_txfree, 1364172334Smarius sc->sc_txnext); 1365115030Stmm#endif 1366174987Smarius ntx = 0; 1367194763Smarius kicked = 0; 1368170273Syongari for (; !IFQ_DRV_IS_EMPTY(&ifp->if_snd) && sc->sc_txfree > 1;) { 1369170273Syongari IFQ_DRV_DEQUEUE(&ifp->if_snd, m); 1370170273Syongari if (m == NULL) 137191398Stmm break; 1372172334Smarius if (gem_load_txmbuf(sc, &m) != 0) { 1373170273Syongari if (m == NULL) 1374170273Syongari break; 1375170273Syongari ifp->if_drv_flags |= IFF_DRV_OACTIVE; 1376170273Syongari IFQ_DRV_PREPEND(&ifp->if_snd, m); 137791398Stmm break; 137891398Stmm } 1379194763Smarius if ((sc->sc_txnext % 4) == 0) { 1380194763Smarius gem_txkick(sc); 1381194763Smarius kicked = 1; 1382194763Smarius } else 1383194763Smarius kicked = 0; 1384115030Stmm ntx++; 1385170273Syongari BPF_MTAP(ifp, m); 138691398Stmm } 138791398Stmm 138891398Stmm if (ntx > 0) { 1389194763Smarius if (kicked == 0) 1390194763Smarius gem_txkick(sc); 1391115030Stmm#ifdef GEM_DEBUG 1392108832Stmm CTR2(KTR_GEM, "%s: packets enqueued, OWN on %d", 1393172334Smarius device_get_name(sc->sc_dev), sc->sc_txnext); 1394115030Stmm#endif 139591398Stmm 139691398Stmm /* Set a watchdog timer in case the chip flakes out. */ 1397164931Smarius sc->sc_wdog_timer = 5; 1398115030Stmm#ifdef GEM_DEBUG 1399170273Syongari CTR3(KTR_GEM, "%s: %s: watchdog %d", 1400174987Smarius device_get_name(sc->sc_dev), __func__, 1401174987Smarius sc->sc_wdog_timer); 1402115030Stmm#endif 140391398Stmm } 140491398Stmm} 140591398Stmm 140691398Stmmstatic void 1407174987Smariusgem_tint(struct gem_softc *sc) 140891398Stmm{ 1409147256Sbrooks struct ifnet *ifp = sc->sc_ifp; 141091398Stmm struct gem_txsoft *txs; 1411194763Smarius int progress; 1412194763Smarius uint32_t txlast; 1413174987Smarius#ifdef GEM_DEBUG 1414174987Smarius int i; 141591398Stmm 1416194763Smarius GEM_LOCK_ASSERT(sc, MA_OWNED); 1417194763Smarius 1418170273Syongari CTR2(KTR_GEM, "%s: %s", device_get_name(sc->sc_dev), __func__); 1419115030Stmm#endif 142091398Stmm 142191398Stmm /* 1422174987Smarius * Go through our TX list and free mbufs for those 142391398Stmm * frames that have been transmitted. 142491398Stmm */ 1425174987Smarius progress = 0; 1426109648Stmm GEM_CDSYNC(sc, BUS_DMASYNC_POSTREAD); 142791398Stmm while ((txs = STAILQ_FIRST(&sc->sc_txdirtyq)) != NULL) { 142891398Stmm#ifdef GEM_DEBUG 1429174987Smarius if ((ifp->if_flags & IFF_DEBUG) != 0) { 143091398Stmm printf(" txsoft %p transmit chain:\n", txs); 143191398Stmm for (i = txs->txs_firstdesc;; i = GEM_NEXTTX(i)) { 143291398Stmm printf("descriptor %d: ", i); 1433174987Smarius printf("gd_flags: 0x%016llx\t", 1434174987Smarius (long long)GEM_DMA_READ(sc, 1435174987Smarius sc->sc_txdescs[i].gd_flags)); 1436174987Smarius printf("gd_addr: 0x%016llx\n", 1437174987Smarius (long long)GEM_DMA_READ(sc, 1438174987Smarius sc->sc_txdescs[i].gd_addr)); 143991398Stmm if (i == txs->txs_lastdesc) 144091398Stmm break; 144191398Stmm } 144291398Stmm } 144391398Stmm#endif 144491398Stmm 144591398Stmm /* 1446172334Smarius * In theory, we could harvest some descriptors before 144791398Stmm * the ring is empty, but that's a bit complicated. 144891398Stmm * 144991398Stmm * GEM_TX_COMPLETION points to the last descriptor 1450174987Smarius * processed + 1. 145191398Stmm */ 1452177560Smarius txlast = GEM_BANK1_READ_4(sc, GEM_TX_COMPLETION); 1453115030Stmm#ifdef GEM_DEBUG 1454170273Syongari CTR4(KTR_GEM, "%s: txs->txs_firstdesc = %d, " 145591398Stmm "txs->txs_lastdesc = %d, txlast = %d", 1456170273Syongari __func__, txs->txs_firstdesc, txs->txs_lastdesc, txlast); 1457115030Stmm#endif 145891398Stmm if (txs->txs_firstdesc <= txs->txs_lastdesc) { 145991398Stmm if ((txlast >= txs->txs_firstdesc) && 1460174987Smarius (txlast <= txs->txs_lastdesc)) 146191398Stmm break; 146291398Stmm } else { 1463174987Smarius /* Ick -- this command wraps. */ 146491398Stmm if ((txlast >= txs->txs_firstdesc) || 1465174987Smarius (txlast <= txs->txs_lastdesc)) 146691398Stmm break; 146791398Stmm } 146891398Stmm 1469115030Stmm#ifdef GEM_DEBUG 1470174987Smarius CTR1(KTR_GEM, "%s: releasing a descriptor", __func__); 1471115030Stmm#endif 147291398Stmm STAILQ_REMOVE_HEAD(&sc->sc_txdirtyq, txs_q); 147391398Stmm 147491398Stmm sc->sc_txfree += txs->txs_ndescs; 147591398Stmm 1476108832Stmm bus_dmamap_sync(sc->sc_tdmatag, txs->txs_dmamap, 147791398Stmm BUS_DMASYNC_POSTWRITE); 1478108832Stmm bus_dmamap_unload(sc->sc_tdmatag, txs->txs_dmamap); 147991398Stmm if (txs->txs_mbuf != NULL) { 148091398Stmm m_freem(txs->txs_mbuf); 148191398Stmm txs->txs_mbuf = NULL; 148291398Stmm } 148391398Stmm 148491398Stmm STAILQ_INSERT_TAIL(&sc->sc_txfreeq, txs, txs_q); 148591398Stmm 148691398Stmm ifp->if_opackets++; 148799726Sbenno progress = 1; 148891398Stmm } 148991398Stmm 1490115030Stmm#ifdef GEM_DEBUG 1491174987Smarius CTR4(KTR_GEM, "%s: GEM_TX_STATE_MACHINE %x GEM_TX_DATA_PTR %llx " 1492172334Smarius "GEM_TX_COMPLETION %x", 1493177560Smarius __func__, GEM_BANK1_READ_4(sc, GEM_TX_STATE_MACHINE), 1494177560Smarius ((long long)GEM_BANK1_READ_4(sc, GEM_TX_DATA_PTR_HI) << 32) | 1495177560Smarius GEM_BANK1_READ_4(sc, GEM_TX_DATA_PTR_LO), 1496177560Smarius GEM_BANK1_READ_4(sc, GEM_TX_COMPLETION)); 1497115030Stmm#endif 149891398Stmm 149999726Sbenno if (progress) { 150099726Sbenno if (sc->sc_txfree == GEM_NTXDESC - 1) 150199726Sbenno sc->sc_txwin = 0; 150291398Stmm 1503174987Smarius /* 1504174987Smarius * We freed some descriptors, so reset IFF_DRV_OACTIVE 1505174987Smarius * and restart. 1506174987Smarius */ 1507148887Srwatson ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 1508194763Smarius if (STAILQ_EMPTY(&sc->sc_txdirtyq)) 1509194763Smarius sc->sc_wdog_timer = 0; 1510179925Smarius gem_start_locked(ifp); 151199726Sbenno } 151299726Sbenno 1513115030Stmm#ifdef GEM_DEBUG 1514170273Syongari CTR3(KTR_GEM, "%s: %s: watchdog %d", 1515170273Syongari device_get_name(sc->sc_dev), __func__, sc->sc_wdog_timer); 1516115030Stmm#endif 151791398Stmm} 151891398Stmm 1519148368Smarius#ifdef GEM_RINT_TIMEOUT 152093045Stmmstatic void 1521174987Smariusgem_rint_timeout(void *arg) 152293045Stmm{ 1523174987Smarius struct gem_softc *sc = arg; 152493045Stmm 1525150285Smarius GEM_LOCK_ASSERT(sc, MA_OWNED); 1526194763Smarius 1527148369Smarius gem_rint(sc); 152893045Stmm} 1529100587Sjake#endif 153093045Stmm 153191398Stmmstatic void 1532174987Smariusgem_rint(struct gem_softc *sc) 153391398Stmm{ 1534147256Sbrooks struct ifnet *ifp = sc->sc_ifp; 153591398Stmm struct mbuf *m; 1536174987Smarius uint64_t rxstat; 1537174987Smarius uint32_t rxcomp; 153891398Stmm 1539194763Smarius GEM_LOCK_ASSERT(sc, MA_OWNED); 1540194763Smarius 1541148368Smarius#ifdef GEM_RINT_TIMEOUT 154293045Stmm callout_stop(&sc->sc_rx_ch); 1543148368Smarius#endif 1544115030Stmm#ifdef GEM_DEBUG 1545170273Syongari CTR2(KTR_GEM, "%s: %s", device_get_name(sc->sc_dev), __func__); 1546115030Stmm#endif 154799726Sbenno 154891398Stmm /* 154999726Sbenno * Read the completion register once. This limits 155099726Sbenno * how long the following loop can execute. 155199726Sbenno */ 1552177560Smarius rxcomp = GEM_BANK1_READ_4(sc, GEM_RX_COMPLETION); 1553115030Stmm#ifdef GEM_DEBUG 1554194763Smarius CTR3(KTR_GEM, "%s: sc->sc_rxptr %d, complete %d", 1555170273Syongari __func__, sc->sc_rxptr, rxcomp); 1556115030Stmm#endif 1557194763Smarius GEM_CDSYNC(sc, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 1558172334Smarius for (; sc->sc_rxptr != rxcomp;) { 1559172334Smarius m = sc->sc_rxsoft[sc->sc_rxptr].rxs_mbuf; 1560172334Smarius rxstat = GEM_DMA_READ(sc, 1561172334Smarius sc->sc_rxdescs[sc->sc_rxptr].gd_flags); 156291398Stmm 156391398Stmm if (rxstat & GEM_RD_OWN) { 1564148368Smarius#ifdef GEM_RINT_TIMEOUT 156591398Stmm /* 156693045Stmm * The descriptor is still marked as owned, although 1567174987Smarius * it is supposed to have completed. This has been 1568174987Smarius * observed on some machines. Just exiting here 156993045Stmm * might leave the packet sitting around until another 157093045Stmm * one arrives to trigger a new interrupt, which is 157193045Stmm * generally undesirable, so set up a timeout. 157291398Stmm */ 157393045Stmm callout_reset(&sc->sc_rx_ch, GEM_RXOWN_TICKS, 157493045Stmm gem_rint_timeout, sc); 157599726Sbenno#endif 1576172334Smarius m = NULL; 1577172334Smarius goto kickit; 157891398Stmm } 157991398Stmm 158091398Stmm if (rxstat & GEM_RD_BAD_CRC) { 158199726Sbenno ifp->if_ierrors++; 158291398Stmm device_printf(sc->sc_dev, "receive error: CRC error\n"); 1583172334Smarius GEM_INIT_RXDESC(sc, sc->sc_rxptr); 1584172334Smarius m = NULL; 1585172334Smarius goto kickit; 158691398Stmm } 158791398Stmm 158891398Stmm#ifdef GEM_DEBUG 1589174987Smarius if ((ifp->if_flags & IFF_DEBUG) != 0) { 1590172334Smarius printf(" rxsoft %p descriptor %d: ", 1591172334Smarius &sc->sc_rxsoft[sc->sc_rxptr], sc->sc_rxptr); 1592174987Smarius printf("gd_flags: 0x%016llx\t", 1593174987Smarius (long long)GEM_DMA_READ(sc, 1594174987Smarius sc->sc_rxdescs[sc->sc_rxptr].gd_flags)); 1595174987Smarius printf("gd_addr: 0x%016llx\n", 1596174987Smarius (long long)GEM_DMA_READ(sc, 1597174987Smarius sc->sc_rxdescs[sc->sc_rxptr].gd_addr)); 159891398Stmm } 159991398Stmm#endif 160091398Stmm 160191398Stmm /* 160291398Stmm * Allocate a new mbuf cluster. If that fails, we are 160391398Stmm * out of memory, and must drop the packet and recycle 160491398Stmm * the buffer that's already attached to this descriptor. 160591398Stmm */ 1606172334Smarius if (gem_add_rxbuf(sc, sc->sc_rxptr) != 0) { 1607223648Smarius ifp->if_iqdrops++; 1608172334Smarius GEM_INIT_RXDESC(sc, sc->sc_rxptr); 1609172334Smarius m = NULL; 1610172334Smarius } 1611172334Smarius 1612174987Smarius kickit: 1613174987Smarius /* 1614174987Smarius * Update the RX kick register. This register has to point 1615172334Smarius * to the descriptor after the last valid one (before the 1616194763Smarius * current batch) and for optimum performance should be 1617194763Smarius * incremented in multiples of 4 (the DMA engine fetches/ 1618194763Smarius * updates descriptors in batches of 4). 1619172334Smarius */ 1620172334Smarius sc->sc_rxptr = GEM_NEXTRX(sc->sc_rxptr); 1621172334Smarius if ((sc->sc_rxptr % 4) == 0) { 1622179925Smarius GEM_CDSYNC(sc, 1623179925Smarius BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 1624177560Smarius GEM_BANK1_WRITE_4(sc, GEM_RX_KICK, 1625172334Smarius (sc->sc_rxptr + GEM_NRXDESC - 4) & 1626172334Smarius GEM_NRXDESC_MASK); 1627172334Smarius } 1628172334Smarius 1629172334Smarius if (m == NULL) { 1630172334Smarius if (rxstat & GEM_RD_OWN) 1631172334Smarius break; 163291398Stmm continue; 163391398Stmm } 1634172334Smarius 1635172334Smarius ifp->if_ipackets++; 1636194763Smarius m->m_data += ETHER_ALIGN; /* first byte offset */ 163791398Stmm m->m_pkthdr.rcvif = ifp; 1638172334Smarius m->m_pkthdr.len = m->m_len = GEM_RD_BUFLEN(rxstat); 163991398Stmm 1640170273Syongari if ((ifp->if_capenable & IFCAP_RXCSUM) != 0) 1641170273Syongari gem_rxcksum(m, rxstat); 1642170273Syongari 164391398Stmm /* Pass it on. */ 1644148369Smarius GEM_UNLOCK(sc); 1645106937Ssam (*ifp->if_input)(ifp, m); 1646148369Smarius GEM_LOCK(sc); 164791398Stmm } 164891398Stmm 1649115030Stmm#ifdef GEM_DEBUG 1650194763Smarius CTR3(KTR_GEM, "%s: done sc->sc_rxptr %d, complete %d", __func__, 1651177560Smarius sc->sc_rxptr, GEM_BANK1_READ_4(sc, GEM_RX_COMPLETION)); 1652115030Stmm#endif 165391398Stmm} 165491398Stmm 165591398Stmmstatic int 1656174987Smariusgem_add_rxbuf(struct gem_softc *sc, int idx) 165791398Stmm{ 165891398Stmm struct gem_rxsoft *rxs = &sc->sc_rxsoft[idx]; 165991398Stmm struct mbuf *m; 1660148368Smarius bus_dma_segment_t segs[1]; 1661148368Smarius int error, nsegs; 166291398Stmm 1663194763Smarius GEM_LOCK_ASSERT(sc, MA_OWNED); 1664194763Smarius 1665111119Simp m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); 166691398Stmm if (m == NULL) 166791398Stmm return (ENOBUFS); 1668108832Stmm m->m_len = m->m_pkthdr.len = m->m_ext.ext_size; 166991398Stmm 167091398Stmm#ifdef GEM_DEBUG 1671174987Smarius /* Bzero the packet to check DMA. */ 167291398Stmm memset(m->m_ext.ext_buf, 0, m->m_ext.ext_size); 167391398Stmm#endif 167491398Stmm 1675109648Stmm if (rxs->rxs_mbuf != NULL) { 1676109648Stmm bus_dmamap_sync(sc->sc_rdmatag, rxs->rxs_dmamap, 1677109648Stmm BUS_DMASYNC_POSTREAD); 1678108832Stmm bus_dmamap_unload(sc->sc_rdmatag, rxs->rxs_dmamap); 1679109648Stmm } 168091398Stmm 1681148368Smarius error = bus_dmamap_load_mbuf_sg(sc->sc_rdmatag, rxs->rxs_dmamap, 1682148368Smarius m, segs, &nsegs, BUS_DMA_NOWAIT); 1683148368Smarius if (error != 0) { 1684174987Smarius device_printf(sc->sc_dev, 1685174987Smarius "cannot load RS DMA map %d, error = %d\n", idx, error); 1686148368Smarius m_freem(m); 1687172334Smarius return (error); 168891398Stmm } 1689174987Smarius /* If nsegs is wrong then the stack is corrupt. */ 1690176996Smarius KASSERT(nsegs == 1, 1691176996Smarius ("%s: too many DMA segments (%d)", __func__, nsegs)); 1692172334Smarius rxs->rxs_mbuf = m; 1693148368Smarius rxs->rxs_paddr = segs[0].ds_addr; 169491398Stmm 1695174987Smarius bus_dmamap_sync(sc->sc_rdmatag, rxs->rxs_dmamap, 1696174987Smarius BUS_DMASYNC_PREREAD); 169791398Stmm 169891398Stmm GEM_INIT_RXDESC(sc, idx); 169991398Stmm 170091398Stmm return (0); 170191398Stmm} 170291398Stmm 170391398Stmmstatic void 1704174987Smariusgem_eint(struct gem_softc *sc, u_int status) 170591398Stmm{ 170691398Stmm 1707172334Smarius sc->sc_ifp->if_ierrors++; 1708172334Smarius if ((status & GEM_INTR_RX_TAG_ERR) != 0) { 1709172334Smarius gem_reset_rxdma(sc); 171091398Stmm return; 171191398Stmm } 171291398Stmm 1713194763Smarius device_printf(sc->sc_dev, "%s: status 0x%x", __func__, status); 1714194763Smarius if ((status & GEM_INTR_BERR) != 0) { 1715194763Smarius if ((sc->sc_flags & GEM_PCI) != 0) 1716194763Smarius printf(", PCI bus error 0x%x\n", 1717194763Smarius GEM_BANK1_READ_4(sc, GEM_PCI_ERROR_STATUS)); 1718194763Smarius else 1719194763Smarius printf(", SBus error 0x%x\n", 1720194763Smarius GEM_BANK1_READ_4(sc, GEM_SBUS_STATUS)); 1721194763Smarius } 172291398Stmm} 172391398Stmm 172491398Stmmvoid 1725174987Smariusgem_intr(void *v) 172691398Stmm{ 1727174987Smarius struct gem_softc *sc = v; 1728172334Smarius uint32_t status, status2; 172991398Stmm 1730148369Smarius GEM_LOCK(sc); 1731177560Smarius status = GEM_BANK1_READ_4(sc, GEM_STATUS); 1732172334Smarius 1733115030Stmm#ifdef GEM_DEBUG 1734170273Syongari CTR4(KTR_GEM, "%s: %s: cplt %x, status %x", 1735194763Smarius device_get_name(sc->sc_dev), __func__, 1736194763Smarius (status >> GEM_STATUS_TX_COMPLETION_SHFT), (u_int)status); 1737172334Smarius 1738172334Smarius /* 1739172334Smarius * PCS interrupts must be cleared, otherwise no traffic is passed! 1740172334Smarius */ 1741172334Smarius if ((status & GEM_INTR_PCS) != 0) { 1742174987Smarius status2 = 1743177560Smarius GEM_BANK1_READ_4(sc, GEM_MII_INTERRUP_STATUS) | 1744177560Smarius GEM_BANK1_READ_4(sc, GEM_MII_INTERRUP_STATUS); 1745172334Smarius if ((status2 & GEM_MII_INTERRUP_LINK) != 0) 1746172334Smarius device_printf(sc->sc_dev, 1747172334Smarius "%s: PCS link status changed\n", __func__); 1748172334Smarius } 1749172334Smarius if ((status & GEM_MAC_CONTROL_STATUS) != 0) { 1750177560Smarius status2 = GEM_BANK1_READ_4(sc, GEM_MAC_CONTROL_STATUS); 1751172334Smarius if ((status2 & GEM_MAC_PAUSED) != 0) 1752172334Smarius device_printf(sc->sc_dev, 1753172334Smarius "%s: PAUSE received (PAUSE time %d slots)\n", 1754172334Smarius __func__, GEM_MAC_PAUSE_TIME(status2)); 1755172334Smarius if ((status2 & GEM_MAC_PAUSE) != 0) 1756172334Smarius device_printf(sc->sc_dev, 1757172334Smarius "%s: transited to PAUSE state\n", __func__); 1758172334Smarius if ((status2 & GEM_MAC_RESUME) != 0) 1759172334Smarius device_printf(sc->sc_dev, 1760172334Smarius "%s: transited to non-PAUSE state\n", __func__); 1761172334Smarius } 1762172334Smarius if ((status & GEM_INTR_MIF) != 0) 1763172334Smarius device_printf(sc->sc_dev, "%s: MIF interrupt\n", __func__); 1764115030Stmm#endif 176591398Stmm 1766194763Smarius if (__predict_false(status & 1767172334Smarius (GEM_INTR_RX_TAG_ERR | GEM_INTR_PERR | GEM_INTR_BERR)) != 0) 176891398Stmm gem_eint(sc, status); 176991398Stmm 1770172334Smarius if ((status & (GEM_INTR_RX_DONE | GEM_INTR_RX_NOBUF)) != 0) 1771172334Smarius gem_rint(sc); 1772172334Smarius 177391398Stmm if ((status & (GEM_INTR_TX_EMPTY | GEM_INTR_TX_INTME)) != 0) 177491398Stmm gem_tint(sc); 177591398Stmm 1776194763Smarius if (__predict_false((status & GEM_INTR_TX_MAC) != 0)) { 1777177560Smarius status2 = GEM_BANK1_READ_4(sc, GEM_MAC_TX_STATUS); 1778174987Smarius if ((status2 & 1779194763Smarius ~(GEM_MAC_TX_XMIT_DONE | GEM_MAC_TX_DEFER_EXP | 1780194763Smarius GEM_MAC_TX_PEAK_EXP)) != 0) 1781174987Smarius device_printf(sc->sc_dev, 1782174987Smarius "MAC TX fault, status %x\n", status2); 1783174987Smarius if ((status2 & 1784194763Smarius (GEM_MAC_TX_UNDERRUN | GEM_MAC_TX_PKT_TOO_LONG)) != 0) { 1785194763Smarius sc->sc_ifp->if_oerrors++; 1786222135Syongari sc->sc_ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 1787148369Smarius gem_init_locked(sc); 1788194763Smarius } 178991398Stmm } 1790194763Smarius if (__predict_false((status & GEM_INTR_RX_MAC) != 0)) { 1791177560Smarius status2 = GEM_BANK1_READ_4(sc, GEM_MAC_RX_STATUS); 1792149552Smarius /* 1793172334Smarius * At least with GEM_SUN_GEM and some GEM_SUN_ERI 1794172334Smarius * revisions GEM_MAC_RX_OVERFLOW happen often due to a 1795174987Smarius * silicon bug so handle them silently. Moreover, it's 1796172334Smarius * likely that the receiver has hung so we reset it. 1797149552Smarius */ 1798174987Smarius if ((status2 & GEM_MAC_RX_OVERFLOW) != 0) { 1799172334Smarius sc->sc_ifp->if_ierrors++; 1800172334Smarius gem_reset_rxdma(sc); 1801174987Smarius } else if ((status2 & 1802174987Smarius ~(GEM_MAC_RX_DONE | GEM_MAC_RX_FRAME_CNT)) != 0) 1803174987Smarius device_printf(sc->sc_dev, 1804174987Smarius "MAC RX fault, status %x\n", status2); 180591398Stmm } 1806148369Smarius GEM_UNLOCK(sc); 180791398Stmm} 180891398Stmm 1809164931Smariusstatic int 1810174987Smariusgem_watchdog(struct gem_softc *sc) 181191398Stmm{ 1812179925Smarius struct ifnet *ifp = sc->sc_ifp; 181391398Stmm 1814164931Smarius GEM_LOCK_ASSERT(sc, MA_OWNED); 1815164931Smarius 1816115030Stmm#ifdef GEM_DEBUG 1817174987Smarius CTR4(KTR_GEM, 1818174987Smarius "%s: GEM_RX_CONFIG %x GEM_MAC_RX_STATUS %x GEM_MAC_RX_CONFIG %x", 1819177560Smarius __func__, GEM_BANK1_READ_4(sc, GEM_RX_CONFIG), 1820177560Smarius GEM_BANK1_READ_4(sc, GEM_MAC_RX_STATUS), 1821177560Smarius GEM_BANK1_READ_4(sc, GEM_MAC_RX_CONFIG)); 1822174987Smarius CTR4(KTR_GEM, 1823174987Smarius "%s: GEM_TX_CONFIG %x GEM_MAC_TX_STATUS %x GEM_MAC_TX_CONFIG %x", 1824177560Smarius __func__, GEM_BANK1_READ_4(sc, GEM_TX_CONFIG), 1825177560Smarius GEM_BANK1_READ_4(sc, GEM_MAC_TX_STATUS), 1826177560Smarius GEM_BANK1_READ_4(sc, GEM_MAC_TX_CONFIG)); 1827115030Stmm#endif 182891398Stmm 1829164931Smarius if (sc->sc_wdog_timer == 0 || --sc->sc_wdog_timer != 0) 1830164931Smarius return (0); 1831164931Smarius 1832172334Smarius if ((sc->sc_flags & GEM_LINK) != 0) 1833172334Smarius device_printf(sc->sc_dev, "device timeout\n"); 1834172334Smarius else if (bootverbose) 1835172334Smarius device_printf(sc->sc_dev, "device timeout (no link)\n"); 1836179925Smarius ++ifp->if_oerrors; 183791398Stmm 183891398Stmm /* Try to get more packets going. */ 1839222135Syongari ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 1840148369Smarius gem_init_locked(sc); 1841179925Smarius gem_start_locked(ifp); 1842164931Smarius return (EJUSTRETURN); 184391398Stmm} 184491398Stmm 184591398Stmmstatic void 1846174987Smariusgem_mifinit(struct gem_softc *sc) 184791398Stmm{ 184891398Stmm 1849176996Smarius /* Configure the MIF in frame mode. */ 1850177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MIF_CONFIG, 1851177560Smarius GEM_BANK1_READ_4(sc, GEM_MIF_CONFIG) & ~GEM_MIF_CONFIG_BB_ENA); 1852212725Smarius GEM_BANK1_BARRIER(sc, GEM_MIF_CONFIG, 4, 1853212725Smarius BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 185491398Stmm} 185591398Stmm 185691398Stmm/* 185791398Stmm * MII interface 185891398Stmm * 1859182060Smarius * The MII interface supports at least three different operating modes: 186091398Stmm * 186191398Stmm * Bitbang mode is implemented using data, clock and output enable registers. 186291398Stmm * 186391398Stmm * Frame mode is implemented by loading a complete frame into the frame 186491398Stmm * register and polling the valid bit for completion. 186591398Stmm * 186691398Stmm * Polling mode uses the frame register but completion is indicated by 186791398Stmm * an interrupt. 186891398Stmm * 186991398Stmm */ 187091398Stmmint 1871174987Smariusgem_mii_readreg(device_t dev, int phy, int reg) 187291398Stmm{ 1873174987Smarius struct gem_softc *sc; 187491398Stmm int n; 1875174987Smarius uint32_t v; 187691398Stmm 187791398Stmm#ifdef GEM_DEBUG_PHY 1878172334Smarius printf("%s: phy %d reg %d\n", __func__, phy, reg); 187991398Stmm#endif 188091398Stmm 1881174987Smarius sc = device_get_softc(dev); 1882172334Smarius if ((sc->sc_flags & GEM_SERDES) != 0) { 1883172334Smarius switch (reg) { 1884172334Smarius case MII_BMCR: 1885172334Smarius reg = GEM_MII_CONTROL; 1886172334Smarius break; 1887172334Smarius case MII_BMSR: 1888172334Smarius reg = GEM_MII_STATUS; 1889172334Smarius break; 1890172334Smarius case MII_PHYIDR1: 1891172334Smarius case MII_PHYIDR2: 1892172334Smarius return (0); 1893172334Smarius case MII_ANAR: 1894172334Smarius reg = GEM_MII_ANAR; 1895172334Smarius break; 1896172334Smarius case MII_ANLPAR: 1897172334Smarius reg = GEM_MII_ANLPAR; 1898172334Smarius break; 1899172334Smarius case MII_EXTSR: 1900172334Smarius return (EXTSR_1000XFDX | EXTSR_1000XHDX); 1901172334Smarius default: 1902172334Smarius device_printf(sc->sc_dev, 1903172334Smarius "%s: unhandled register %d\n", __func__, reg); 1904172334Smarius return (0); 1905172334Smarius } 1906177560Smarius return (GEM_BANK1_READ_4(sc, reg)); 1907172334Smarius } 1908172334Smarius 1909174987Smarius /* Construct the frame command. */ 1910172334Smarius v = GEM_MIF_FRAME_READ | 1911172334Smarius (phy << GEM_MIF_PHY_SHIFT) | 1912172334Smarius (reg << GEM_MIF_REG_SHIFT); 191391398Stmm 1914177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MIF_FRAME, v); 1915179925Smarius GEM_BANK1_BARRIER(sc, GEM_MIF_FRAME, 4, 1916179925Smarius BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 191791398Stmm for (n = 0; n < 100; n++) { 191891398Stmm DELAY(1); 1919177560Smarius v = GEM_BANK1_READ_4(sc, GEM_MIF_FRAME); 1920150285Smarius if (v & GEM_MIF_FRAME_TA0) 192191398Stmm return (v & GEM_MIF_FRAME_DATA); 192291398Stmm } 192391398Stmm 1924174987Smarius device_printf(sc->sc_dev, "%s: timed out\n", __func__); 192591398Stmm return (0); 192691398Stmm} 192791398Stmm 192891398Stmmint 1929174987Smariusgem_mii_writereg(device_t dev, int phy, int reg, int val) 193091398Stmm{ 1931174987Smarius struct gem_softc *sc; 193291398Stmm int n; 1933174987Smarius uint32_t v; 193491398Stmm 193591398Stmm#ifdef GEM_DEBUG_PHY 1936172334Smarius printf("%s: phy %d reg %d val %x\n", phy, reg, val, __func__); 193791398Stmm#endif 193891398Stmm 1939174987Smarius sc = device_get_softc(dev); 1940172334Smarius if ((sc->sc_flags & GEM_SERDES) != 0) { 1941172334Smarius switch (reg) { 1942172334Smarius case MII_BMSR: 1943172334Smarius reg = GEM_MII_STATUS; 1944172334Smarius break; 1945179925Smarius case MII_BMCR: 1946179925Smarius reg = GEM_MII_CONTROL; 1947179925Smarius if ((val & GEM_MII_CONTROL_RESET) == 0) 1948179925Smarius break; 1949179925Smarius GEM_BANK1_WRITE_4(sc, GEM_MII_CONTROL, val); 1950179925Smarius GEM_BANK1_BARRIER(sc, GEM_MII_CONTROL, 4, 1951179925Smarius BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 1952179925Smarius if (!GEM_BANK1_BITWAIT(sc, GEM_MII_CONTROL, 1953179925Smarius GEM_MII_CONTROL_RESET, 0)) 1954179925Smarius device_printf(sc->sc_dev, 1955179925Smarius "cannot reset PCS\n"); 1956179925Smarius /* FALLTHROUGH */ 1957172334Smarius case MII_ANAR: 1958177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MII_CONFIG, 0); 1959177560Smarius GEM_BANK1_BARRIER(sc, GEM_MII_CONFIG, 4, 1960172334Smarius BUS_SPACE_BARRIER_WRITE); 1961177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MII_ANAR, val); 1962212725Smarius GEM_BANK1_BARRIER(sc, GEM_MII_ANAR, 4, 1963212725Smarius BUS_SPACE_BARRIER_WRITE); 1964177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MII_SLINK_CONTROL, 1965172334Smarius GEM_MII_SLINK_LOOPBACK | GEM_MII_SLINK_EN_SYNC_D); 1966212725Smarius GEM_BANK1_BARRIER(sc, GEM_MII_SLINK_CONTROL, 4, 1967212725Smarius BUS_SPACE_BARRIER_WRITE); 1968177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MII_CONFIG, 1969172334Smarius GEM_MII_CONFIG_ENABLE); 1970212725Smarius GEM_BANK1_BARRIER(sc, GEM_MII_CONFIG, 4, 1971212725Smarius BUS_SPACE_BARRIER_WRITE); 1972172334Smarius return (0); 1973172334Smarius case MII_ANLPAR: 1974172334Smarius reg = GEM_MII_ANLPAR; 1975172334Smarius break; 1976172334Smarius default: 1977172334Smarius device_printf(sc->sc_dev, 1978172334Smarius "%s: unhandled register %d\n", __func__, reg); 1979172334Smarius return (0); 1980172334Smarius } 1981177560Smarius GEM_BANK1_WRITE_4(sc, reg, val); 1982212725Smarius GEM_BANK1_BARRIER(sc, reg, 4, 1983212725Smarius BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 1984172334Smarius return (0); 1985172334Smarius } 1986172334Smarius 1987174987Smarius /* Construct the frame command. */ 1988172334Smarius v = GEM_MIF_FRAME_WRITE | 1989172334Smarius (phy << GEM_MIF_PHY_SHIFT) | 1990172334Smarius (reg << GEM_MIF_REG_SHIFT) | 199191398Stmm (val & GEM_MIF_FRAME_DATA); 199291398Stmm 1993177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MIF_FRAME, v); 1994179925Smarius GEM_BANK1_BARRIER(sc, GEM_MIF_FRAME, 4, 1995179925Smarius BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 199691398Stmm for (n = 0; n < 100; n++) { 199791398Stmm DELAY(1); 1998177560Smarius v = GEM_BANK1_READ_4(sc, GEM_MIF_FRAME); 1999150285Smarius if (v & GEM_MIF_FRAME_TA0) 200091398Stmm return (1); 200191398Stmm } 200291398Stmm 2003174987Smarius device_printf(sc->sc_dev, "%s: timed out\n", __func__); 200491398Stmm return (0); 200591398Stmm} 200691398Stmm 200791398Stmmvoid 2008174987Smariusgem_mii_statchg(device_t dev) 200991398Stmm{ 2010174987Smarius struct gem_softc *sc; 2011172334Smarius int gigabit; 2012172334Smarius uint32_t rxcfg, txcfg, v; 201391398Stmm 2014174987Smarius sc = device_get_softc(dev); 2015174987Smarius 2016194763Smarius GEM_LOCK_ASSERT(sc, MA_OWNED); 2017194763Smarius 201891398Stmm#ifdef GEM_DEBUG 2019174987Smarius if ((sc->sc_ifp->if_flags & IFF_DEBUG) != 0) 2020213893Smarius device_printf(sc->sc_dev, "%s: status change\n", __func__); 202191398Stmm#endif 202291398Stmm 2023172334Smarius if ((sc->sc_mii->mii_media_status & IFM_ACTIVE) != 0 && 2024172334Smarius IFM_SUBTYPE(sc->sc_mii->mii_media_active) != IFM_NONE) 2025172334Smarius sc->sc_flags |= GEM_LINK; 2026172334Smarius else 2027172334Smarius sc->sc_flags &= ~GEM_LINK; 2028172334Smarius 2029172334Smarius switch (IFM_SUBTYPE(sc->sc_mii->mii_media_active)) { 2030172334Smarius case IFM_1000_SX: 2031172334Smarius case IFM_1000_LX: 2032172334Smarius case IFM_1000_CX: 2033172334Smarius case IFM_1000_T: 2034172334Smarius gigabit = 1; 2035172334Smarius break; 2036172334Smarius default: 2037172334Smarius gigabit = 0; 203891398Stmm } 203991398Stmm 2040172334Smarius /* 2041172334Smarius * The configuration done here corresponds to the steps F) and 2042172334Smarius * G) and as far as enabling of RX and TX MAC goes also step H) 2043172334Smarius * of the initialization sequence outlined in section 3.2.1 of 2044172334Smarius * the GEM Gigabit Ethernet ASIC Specification. 2045172334Smarius */ 2046172334Smarius 2047223648Smarius rxcfg = sc->sc_mac_rxcfg; 2048223648Smarius rxcfg &= ~GEM_MAC_RX_CARR_EXTEND; 2049172334Smarius txcfg = GEM_MAC_TX_ENA_IPG0 | GEM_MAC_TX_NGU | GEM_MAC_TX_NGU_LIMIT; 2050172334Smarius if ((IFM_OPTIONS(sc->sc_mii->mii_media_active) & IFM_FDX) != 0) 2051172334Smarius txcfg |= GEM_MAC_TX_IGN_CARRIER | GEM_MAC_TX_IGN_COLLIS; 2052172334Smarius else if (gigabit != 0) { 2053172334Smarius rxcfg |= GEM_MAC_RX_CARR_EXTEND; 2054172334Smarius txcfg |= GEM_MAC_TX_CARR_EXTEND; 2055172334Smarius } 2056223648Smarius (void)gem_disable_tx(sc); 2057177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_TX_CONFIG, txcfg); 2058223648Smarius (void)gem_disable_rx(sc); 2059177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_CONFIG, rxcfg); 2060172334Smarius 2061177560Smarius v = GEM_BANK1_READ_4(sc, GEM_MAC_CONTROL_CONFIG) & 2062172334Smarius ~(GEM_MAC_CC_RX_PAUSE | GEM_MAC_CC_TX_PAUSE); 2063174987Smarius if ((IFM_OPTIONS(sc->sc_mii->mii_media_active) & 2064174987Smarius IFM_ETH_RXPAUSE) != 0) 2065172334Smarius v |= GEM_MAC_CC_RX_PAUSE; 2066174987Smarius if ((IFM_OPTIONS(sc->sc_mii->mii_media_active) & 2067174987Smarius IFM_ETH_TXPAUSE) != 0) 2068172334Smarius v |= GEM_MAC_CC_TX_PAUSE; 2069177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_CONTROL_CONFIG, v); 2070172334Smarius 2071172334Smarius if ((IFM_OPTIONS(sc->sc_mii->mii_media_active) & IFM_FDX) == 0 && 2072172334Smarius gigabit != 0) 2073177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_SLOT_TIME, 2074172334Smarius GEM_MAC_SLOT_TIME_CARR_EXTEND); 2075172334Smarius else 2076177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_SLOT_TIME, 2077172334Smarius GEM_MAC_SLOT_TIME_NORMAL); 2078172334Smarius 207991398Stmm /* XIF Configuration */ 208091398Stmm v = GEM_MAC_XIF_LINK_LED; 208191398Stmm v |= GEM_MAC_XIF_TX_MII_ENA; 2082172334Smarius if ((sc->sc_flags & GEM_SERDES) == 0) { 2083177560Smarius if ((GEM_BANK1_READ_4(sc, GEM_MIF_CONFIG) & 2084182060Smarius GEM_MIF_CONFIG_PHY_SEL) != 0) { 2085172334Smarius /* External MII needs echo disable if half duplex. */ 2086194763Smarius if ((IFM_OPTIONS(sc->sc_mii->mii_media_active) & 2087182060Smarius IFM_FDX) == 0) 2088182060Smarius v |= GEM_MAC_XIF_ECHO_DISABL; 2089182060Smarius } else 2090172334Smarius /* 2091172334Smarius * Internal MII needs buffer enable. 2092172334Smarius * XXX buffer enable makes only sense for an 2093172334Smarius * external PHY. 2094172334Smarius */ 2095172334Smarius v |= GEM_MAC_XIF_MII_BUF_ENA; 2096172334Smarius } 2097172334Smarius if (gigabit != 0) 2098172334Smarius v |= GEM_MAC_XIF_GMII_MODE; 2099172334Smarius if ((IFM_OPTIONS(sc->sc_mii->mii_media_active) & IFM_FDX) != 0) 2100172334Smarius v |= GEM_MAC_XIF_FDPLX_LED; 2101177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_XIF_CONFIG, v); 210299726Sbenno 2103223648Smarius sc->sc_mac_rxcfg = rxcfg; 2104172334Smarius if ((sc->sc_ifp->if_drv_flags & IFF_DRV_RUNNING) != 0 && 2105172334Smarius (sc->sc_flags & GEM_LINK) != 0) { 2106177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_TX_CONFIG, 2107172334Smarius txcfg | GEM_MAC_TX_ENABLE); 2108177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_CONFIG, 2109172334Smarius rxcfg | GEM_MAC_RX_ENABLE); 211091398Stmm } 211191398Stmm} 211291398Stmm 211391398Stmmint 2114174987Smariusgem_mediachange(struct ifnet *ifp) 211591398Stmm{ 211691398Stmm struct gem_softc *sc = ifp->if_softc; 2117150285Smarius int error; 211891398Stmm 2119174987Smarius /* XXX add support for serial media. */ 212091398Stmm 2121150285Smarius GEM_LOCK(sc); 2122150285Smarius error = mii_mediachg(sc->sc_mii); 2123150285Smarius GEM_UNLOCK(sc); 2124150285Smarius return (error); 212591398Stmm} 212691398Stmm 212791398Stmmvoid 2128174987Smariusgem_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr) 212991398Stmm{ 213091398Stmm struct gem_softc *sc = ifp->if_softc; 213191398Stmm 2132148369Smarius GEM_LOCK(sc); 2133148369Smarius if ((ifp->if_flags & IFF_UP) == 0) { 2134148369Smarius GEM_UNLOCK(sc); 213591398Stmm return; 2136148369Smarius } 213791398Stmm 213891398Stmm mii_pollstat(sc->sc_mii); 213991398Stmm ifmr->ifm_active = sc->sc_mii->mii_media_active; 214091398Stmm ifmr->ifm_status = sc->sc_mii->mii_media_status; 2141148369Smarius GEM_UNLOCK(sc); 214291398Stmm} 214391398Stmm 214491398Stmmstatic int 2145174987Smariusgem_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 214691398Stmm{ 214791398Stmm struct gem_softc *sc = ifp->if_softc; 214891398Stmm struct ifreq *ifr = (struct ifreq *)data; 2149174987Smarius int error; 215091398Stmm 2151174987Smarius error = 0; 215291398Stmm switch (cmd) { 2153150285Smarius case SIOCSIFFLAGS: 2154148369Smarius GEM_LOCK(sc); 2155174987Smarius if ((ifp->if_flags & IFF_UP) != 0) { 2156172334Smarius if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0 && 2157172334Smarius ((ifp->if_flags ^ sc->sc_ifflags) & 2158172334Smarius (IFF_ALLMULTI | IFF_PROMISC)) != 0) 2159223648Smarius gem_setladrf(sc, 1); 216091398Stmm else 2161148369Smarius gem_init_locked(sc); 2162174987Smarius } else if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) 2163174987Smarius gem_stop(ifp, 0); 2164170273Syongari if ((ifp->if_flags & IFF_LINK0) != 0) 2165170273Syongari sc->sc_csum_features |= CSUM_UDP; 2166170273Syongari else 2167170273Syongari sc->sc_csum_features &= ~CSUM_UDP; 2168170273Syongari if ((ifp->if_capenable & IFCAP_TXCSUM) != 0) 2169170273Syongari ifp->if_hwassist = sc->sc_csum_features; 217099726Sbenno sc->sc_ifflags = ifp->if_flags; 2171150285Smarius GEM_UNLOCK(sc); 217291398Stmm break; 217391398Stmm case SIOCADDMULTI: 217491398Stmm case SIOCDELMULTI: 2175150285Smarius GEM_LOCK(sc); 2176223648Smarius if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) 2177223648Smarius gem_setladrf(sc, 1); 2178150285Smarius GEM_UNLOCK(sc); 217991398Stmm break; 218091398Stmm case SIOCGIFMEDIA: 218191398Stmm case SIOCSIFMEDIA: 218291398Stmm error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii->mii_media, cmd); 218391398Stmm break; 2184170273Syongari case SIOCSIFCAP: 2185170273Syongari GEM_LOCK(sc); 2186170273Syongari ifp->if_capenable = ifr->ifr_reqcap; 2187170273Syongari if ((ifp->if_capenable & IFCAP_TXCSUM) != 0) 2188170273Syongari ifp->if_hwassist = sc->sc_csum_features; 2189170273Syongari else 2190170273Syongari ifp->if_hwassist = 0; 2191170273Syongari GEM_UNLOCK(sc); 2192170273Syongari break; 219391398Stmm default: 2194150285Smarius error = ether_ioctl(ifp, cmd, data); 219591398Stmm break; 219691398Stmm } 219791398Stmm 219891398Stmm return (error); 219991398Stmm} 220091398Stmm 220191398Stmmstatic void 2202223648Smariusgem_setladrf(struct gem_softc *sc, u_int enable) 220391398Stmm{ 2204147256Sbrooks struct ifnet *ifp = sc->sc_ifp; 220591398Stmm struct ifmultiaddr *inm; 220699726Sbenno int i; 2207174987Smarius uint32_t hash[16]; 2208174987Smarius uint32_t crc, v; 220991398Stmm 2210148369Smarius GEM_LOCK_ASSERT(sc, MA_OWNED); 2211148369Smarius 221299726Sbenno /* 2213223648Smarius * Turn off the RX MAC and the hash filter as required by the Sun GEM 2214223648Smarius * programming restrictions. 221599726Sbenno */ 2216223649Smarius v = sc->sc_mac_rxcfg & ~GEM_MAC_RX_HASH_FILTER; 2217177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_CONFIG, v); 2218179925Smarius GEM_BANK1_BARRIER(sc, GEM_MAC_RX_CONFIG, 4, 2219179925Smarius BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 2220223648Smarius if (!GEM_BANK1_BITWAIT(sc, GEM_MAC_RX_CONFIG, GEM_MAC_RX_HASH_FILTER | 2221223648Smarius GEM_MAC_RX_ENABLE, 0)) 2222223648Smarius device_printf(sc->sc_dev, 2223223648Smarius "cannot disable RX MAC or hash filter\n"); 2224172334Smarius 2225223648Smarius v &= ~(GEM_MAC_RX_PROMISCUOUS | GEM_MAC_RX_PROMISC_GRP); 222691398Stmm if ((ifp->if_flags & IFF_PROMISC) != 0) { 222791398Stmm v |= GEM_MAC_RX_PROMISCUOUS; 222891398Stmm goto chipit; 222991398Stmm } 223091398Stmm if ((ifp->if_flags & IFF_ALLMULTI) != 0) { 223199726Sbenno v |= GEM_MAC_RX_PROMISC_GRP; 223291398Stmm goto chipit; 223391398Stmm } 223491398Stmm 223591398Stmm /* 2236174987Smarius * Set up multicast address filter by passing all multicast 2237174987Smarius * addresses through a crc generator, and then using the high 2238174987Smarius * order 8 bits as an index into the 256 bit logical address 2239174987Smarius * filter. The high order 4 bits selects the word, while the 2240174987Smarius * other 4 bits select the bit within the word (where bit 0 2241174987Smarius * is the MSB). 224291398Stmm */ 224391398Stmm 2244174987Smarius /* Clear the hash table. */ 224599726Sbenno memset(hash, 0, sizeof(hash)); 224699726Sbenno 2247195049Srwatson if_maddr_rlock(ifp); 2248147256Sbrooks TAILQ_FOREACH(inm, &ifp->if_multiaddrs, ifma_link) { 224991398Stmm if (inm->ifma_addr->sa_family != AF_LINK) 225091398Stmm continue; 2251130288Smarius crc = ether_crc32_le(LLADDR((struct sockaddr_dl *) 2252130288Smarius inm->ifma_addr), ETHER_ADDR_LEN); 225391398Stmm 2254174987Smarius /* We just want the 8 most significant bits. */ 225591398Stmm crc >>= 24; 225691398Stmm 225791398Stmm /* Set the corresponding bit in the filter. */ 225899726Sbenno hash[crc >> 4] |= 1 << (15 - (crc & 15)); 225991398Stmm } 2260195049Srwatson if_maddr_runlock(ifp); 226191398Stmm 226299726Sbenno v |= GEM_MAC_RX_HASH_FILTER; 226399726Sbenno 2264174987Smarius /* Now load the hash table into the chip (if we are using it). */ 2265174987Smarius for (i = 0; i < 16; i++) 2266177560Smarius GEM_BANK1_WRITE_4(sc, 2267174987Smarius GEM_MAC_HASH0 + i * (GEM_MAC_HASH1 - GEM_MAC_HASH0), 226899726Sbenno hash[i]); 226999726Sbenno 2270174987Smarius chipit: 2271223648Smarius sc->sc_mac_rxcfg = v; 2272223648Smarius if (enable) 2273223648Smarius v |= GEM_MAC_RX_ENABLE; 2274177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_CONFIG, v); 227591398Stmm} 2276