if_gem.c revision 182060
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 182060 2008-08-23 15:03:26Z 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 87174987Smarius#define 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 122174987Smariusstatic __inline void gem_rxcksum(struct mbuf *m, uint64_t flags); 123174987Smariusstatic void gem_rxdrain(struct gem_softc *sc); 124174987Smariusstatic void gem_setladrf(struct gem_softc *sc); 125174987Smariusstatic void gem_start(struct ifnet *ifp); 126174987Smariusstatic void gem_start_locked(struct ifnet *ifp); 127174987Smariusstatic void gem_stop(struct ifnet *ifp, int disable); 128174987Smariusstatic void gem_tick(void *arg); 129174987Smariusstatic void gem_tint(struct gem_softc *sc); 130174987Smariusstatic int gem_watchdog(struct gem_softc *sc); 13191398Stmm 13291398Stmmdevclass_t gem_devclass; 13391398StmmDRIVER_MODULE(miibus, gem, miibus_driver, miibus_devclass, 0, 0); 13491398StmmMODULE_DEPEND(gem, miibus, 1, 1, 1); 13591398Stmm 13691398Stmm#ifdef GEM_DEBUG 13791398Stmm#include <sys/ktr.h> 13891398Stmm#define KTR_GEM KTR_CT2 13991398Stmm#endif 14091398Stmm 141177560Smarius#define GEM_BANK1_BITWAIT(sc, r, clr, set) \ 142177560Smarius gem_bitwait((sc), GEM_RES_BANK1, (r), (clr), (set)) 143177560Smarius#define GEM_BANK2_BITWAIT(sc, r, clr, set) \ 144177560Smarius gem_bitwait((sc), GEM_RES_BANK2, (r), (clr), (set)) 145177560Smarius 14691398Stmmint 147174987Smariusgem_attach(struct gem_softc *sc) 14891398Stmm{ 149174987Smarius struct gem_txsoft *txs; 150147256Sbrooks struct ifnet *ifp; 151174987Smarius int error, i; 152174987Smarius uint32_t v; 15391398Stmm 154147256Sbrooks ifp = sc->sc_ifp = if_alloc(IFT_ETHER); 155147256Sbrooks if (ifp == NULL) 156147256Sbrooks return (ENOSPC); 157147256Sbrooks 158150285Smarius callout_init_mtx(&sc->sc_tick_ch, &sc->sc_mtx, 0); 159150285Smarius#ifdef GEM_RINT_TIMEOUT 160150285Smarius callout_init_mtx(&sc->sc_rx_ch, &sc->sc_mtx, 0); 161150285Smarius#endif 162150285Smarius 16391398Stmm /* Make sure the chip is stopped. */ 16491398Stmm ifp->if_softc = sc; 16591398Stmm gem_reset(sc); 16691398Stmm 167161928Sjmg error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), 1, 0, 168161928Sjmg BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, 169174987Smarius BUS_SPACE_MAXSIZE_32BIT, 0, BUS_SPACE_MAXSIZE_32BIT, 0, NULL, 170174987Smarius NULL, &sc->sc_pdmatag); 17191398Stmm if (error) 172147256Sbrooks goto fail_ifnet; 17391398Stmm 17491398Stmm error = bus_dma_tag_create(sc->sc_pdmatag, 1, 0, 175170273Syongari BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, MCLBYTES, 176170273Syongari 1, MCLBYTES, BUS_DMA_ALLOCNOW, NULL, NULL, &sc->sc_rdmatag); 17791398Stmm if (error) 178108832Stmm goto fail_ptag; 17991398Stmm 180108832Stmm error = bus_dma_tag_create(sc->sc_pdmatag, 1, 0, 181170273Syongari BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, 182170273Syongari MCLBYTES * GEM_NTXSEGS, GEM_NTXSEGS, MCLBYTES, 183117126Sscottl BUS_DMA_ALLOCNOW, NULL, NULL, &sc->sc_tdmatag); 184108832Stmm if (error) 185108832Stmm goto fail_rtag; 186108832Stmm 18791398Stmm error = bus_dma_tag_create(sc->sc_pdmatag, PAGE_SIZE, 0, 188170273Syongari BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, 18991398Stmm sizeof(struct gem_control_data), 1, 190170273Syongari sizeof(struct gem_control_data), 0, 191170273Syongari NULL, NULL, &sc->sc_cdmatag); 19291398Stmm if (error) 193108832Stmm goto fail_ttag; 19491398Stmm 19591398Stmm /* 196174987Smarius * Allocate the control data structures, create and load the 19791398Stmm * DMA map for it. 19891398Stmm */ 19991398Stmm if ((error = bus_dmamem_alloc(sc->sc_cdmatag, 200170273Syongari (void **)&sc->sc_control_data, 201170273Syongari BUS_DMA_WAITOK | BUS_DMA_COHERENT | BUS_DMA_ZERO, 202170273Syongari &sc->sc_cddmamap))) { 203174987Smarius device_printf(sc->sc_dev, 204174987Smarius "unable to allocate control data, error = %d\n", error); 205108832Stmm goto fail_ctag; 20691398Stmm } 20791398Stmm 20891398Stmm sc->sc_cddma = 0; 20991398Stmm if ((error = bus_dmamap_load(sc->sc_cdmatag, sc->sc_cddmamap, 21091398Stmm sc->sc_control_data, sizeof(struct gem_control_data), 21191398Stmm gem_cddma_callback, sc, 0)) != 0 || sc->sc_cddma == 0) { 212174987Smarius device_printf(sc->sc_dev, 213174987Smarius "unable to load control data DMA map, error = %d\n", 214174987Smarius error); 215108832Stmm goto fail_cmem; 21691398Stmm } 21791398Stmm 21891398Stmm /* 21991398Stmm * Initialize the transmit job descriptors. 22091398Stmm */ 22191398Stmm STAILQ_INIT(&sc->sc_txfreeq); 22291398Stmm STAILQ_INIT(&sc->sc_txdirtyq); 22391398Stmm 22491398Stmm /* 22591398Stmm * Create the transmit buffer DMA maps. 22691398Stmm */ 22791398Stmm error = ENOMEM; 22891398Stmm for (i = 0; i < GEM_TXQUEUELEN; i++) { 22991398Stmm txs = &sc->sc_txsoft[i]; 23091398Stmm txs->txs_mbuf = NULL; 23191398Stmm txs->txs_ndescs = 0; 232108832Stmm if ((error = bus_dmamap_create(sc->sc_tdmatag, 0, 23391398Stmm &txs->txs_dmamap)) != 0) { 234174987Smarius device_printf(sc->sc_dev, 235174987Smarius "unable to create TX DMA map %d, error = %d\n", 236174987Smarius i, error); 237108832Stmm goto fail_txd; 23891398Stmm } 23991398Stmm STAILQ_INSERT_TAIL(&sc->sc_txfreeq, txs, txs_q); 24091398Stmm } 24191398Stmm 24291398Stmm /* 24391398Stmm * Create the receive buffer DMA maps. 24491398Stmm */ 24591398Stmm for (i = 0; i < GEM_NRXDESC; i++) { 246108832Stmm if ((error = bus_dmamap_create(sc->sc_rdmatag, 0, 24791398Stmm &sc->sc_rxsoft[i].rxs_dmamap)) != 0) { 248174987Smarius device_printf(sc->sc_dev, 249174987Smarius "unable to create RX DMA map %d, error = %d\n", 250174987Smarius i, error); 251108832Stmm goto fail_rxd; 25291398Stmm } 25391398Stmm sc->sc_rxsoft[i].rxs_mbuf = NULL; 25491398Stmm } 25591398Stmm 256172334Smarius /* Bad things will happen when touching this register on ERI. */ 257172334Smarius if (sc->sc_variant != GEM_SUN_ERI) 258177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MII_DATAPATH_MODE, 259172334Smarius GEM_MII_DATAPATH_MII); 260172334Smarius 26191398Stmm gem_mifinit(sc); 26291398Stmm 263172334Smarius /* 264172334Smarius * Look for an external PHY. 265172334Smarius */ 266172334Smarius error = ENXIO; 267177560Smarius v = GEM_BANK1_READ_4(sc, GEM_MIF_CONFIG); 268172334Smarius if ((v & GEM_MIF_CONFIG_MDI1) != 0) { 269172334Smarius v |= GEM_MIF_CONFIG_PHY_SEL; 270177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MIF_CONFIG, v); 271172334Smarius switch (sc->sc_variant) { 272172334Smarius case GEM_SUN_ERI: 273172334Smarius sc->sc_phyad = GEM_PHYAD_EXTERNAL; 274172334Smarius break; 275172334Smarius default: 276172334Smarius sc->sc_phyad = -1; 277172334Smarius break; 278172334Smarius } 279172334Smarius error = mii_phy_probe(sc->sc_dev, &sc->sc_miibus, 280172334Smarius gem_mediachange, gem_mediastatus); 281172334Smarius } 282172334Smarius 283172334Smarius /* 284172334Smarius * Fall back on an internal PHY if no external PHY was found. 285172334Smarius */ 286172334Smarius if (error != 0 && (v & GEM_MIF_CONFIG_MDI0) != 0) { 287172334Smarius v &= ~GEM_MIF_CONFIG_PHY_SEL; 288177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MIF_CONFIG, v); 289172334Smarius switch (sc->sc_variant) { 290172334Smarius case GEM_SUN_ERI: 291172334Smarius case GEM_APPLE_K2_GMAC: 292172334Smarius sc->sc_phyad = GEM_PHYAD_INTERNAL; 293172334Smarius break; 294172334Smarius case GEM_APPLE_GMAC: 295172334Smarius sc->sc_phyad = GEM_PHYAD_EXTERNAL; 296172334Smarius break; 297172334Smarius default: 298172334Smarius sc->sc_phyad = -1; 299172334Smarius break; 300172334Smarius } 301172334Smarius error = mii_phy_probe(sc->sc_dev, &sc->sc_miibus, 302172334Smarius gem_mediachange, gem_mediastatus); 303172334Smarius } 304172334Smarius 305172334Smarius /* 306172334Smarius * Try the external PCS SERDES if we didn't find any PHYs. 307172334Smarius */ 308172334Smarius if (error != 0 && sc->sc_variant == GEM_SUN_GEM) { 309177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MII_DATAPATH_MODE, 310172334Smarius GEM_MII_DATAPATH_SERDES); 311177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MII_SLINK_CONTROL, 312172334Smarius GEM_MII_SLINK_LOOPBACK | GEM_MII_SLINK_EN_SYNC_D); 313177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MII_CONFIG, GEM_MII_CONFIG_ENABLE); 314172334Smarius sc->sc_flags |= GEM_SERDES; 315172334Smarius sc->sc_phyad = GEM_PHYAD_EXTERNAL; 316172334Smarius error = mii_phy_probe(sc->sc_dev, &sc->sc_miibus, 317172334Smarius gem_mediachange, gem_mediastatus); 318172334Smarius } 319172334Smarius 320172334Smarius if (error != 0) { 321172334Smarius device_printf(sc->sc_dev, "PHY probe failed: %d\n", error); 322108832Stmm goto fail_rxd; 32391398Stmm } 32491398Stmm sc->sc_mii = device_get_softc(sc->sc_miibus); 32591398Stmm 32691398Stmm /* 32791398Stmm * From this point forward, the attachment cannot fail. A failure 32891398Stmm * before this point releases all resources that may have been 32991398Stmm * allocated. 33091398Stmm */ 33191398Stmm 332176996Smarius /* Get RX FIFO size. */ 33399726Sbenno sc->sc_rxfifosize = 64 * 334177560Smarius GEM_BANK1_READ_4(sc, GEM_RX_FIFO_SIZE); 33599726Sbenno 336176996Smarius /* Get TX FIFO size. */ 337177560Smarius v = GEM_BANK1_READ_4(sc, GEM_TX_FIFO_SIZE); 338128588Stmm device_printf(sc->sc_dev, "%ukB RX FIFO, %ukB TX FIFO\n", 339128588Stmm sc->sc_rxfifosize / 1024, v / 16); 34099726Sbenno 341170273Syongari sc->sc_csum_features = GEM_CSUM_FEATURES; 34291398Stmm /* Initialize ifnet structure. */ 34391398Stmm ifp->if_softc = sc; 344121816Sbrooks if_initname(ifp, device_get_name(sc->sc_dev), 345121816Sbrooks device_get_unit(sc->sc_dev)); 346148369Smarius ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 34791398Stmm ifp->if_start = gem_start; 34891398Stmm ifp->if_ioctl = gem_ioctl; 34991398Stmm ifp->if_init = gem_init; 350170273Syongari IFQ_SET_MAXLEN(&ifp->if_snd, GEM_TXQUEUELEN); 351170273Syongari ifp->if_snd.ifq_drv_maxlen = GEM_TXQUEUELEN; 352170273Syongari IFQ_SET_READY(&ifp->if_snd); 35391398Stmm 35491398Stmm /* Attach the interface. */ 355147256Sbrooks ether_ifattach(ifp, sc->sc_enaddr); 35691398Stmm 35791398Stmm /* 358170273Syongari * Tell the upper layer(s) we support long frames/checksum offloads. 359149552Smarius */ 360149552Smarius ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header); 361170273Syongari ifp->if_capabilities |= IFCAP_VLAN_MTU | IFCAP_HWCSUM; 362170273Syongari ifp->if_hwassist |= sc->sc_csum_features; 363170273Syongari ifp->if_capenable |= IFCAP_VLAN_MTU | IFCAP_HWCSUM; 364149552Smarius 36591398Stmm return (0); 36691398Stmm 36791398Stmm /* 36891398Stmm * Free any resources we've allocated during the failed attach 36991398Stmm * attempt. Do this in reverse order and fall through. 37091398Stmm */ 371174987Smarius fail_rxd: 372174987Smarius for (i = 0; i < GEM_NRXDESC; i++) 37391398Stmm if (sc->sc_rxsoft[i].rxs_dmamap != NULL) 374108832Stmm bus_dmamap_destroy(sc->sc_rdmatag, 37591398Stmm sc->sc_rxsoft[i].rxs_dmamap); 376174987Smarius fail_txd: 377174987Smarius for (i = 0; i < GEM_TXQUEUELEN; i++) 37891398Stmm if (sc->sc_txsoft[i].txs_dmamap != NULL) 379108832Stmm bus_dmamap_destroy(sc->sc_tdmatag, 38091398Stmm sc->sc_txsoft[i].txs_dmamap); 381108832Stmm bus_dmamap_unload(sc->sc_cdmatag, sc->sc_cddmamap); 382174987Smarius fail_cmem: 38391398Stmm bus_dmamem_free(sc->sc_cdmatag, sc->sc_control_data, 38491398Stmm sc->sc_cddmamap); 385174987Smarius fail_ctag: 38691398Stmm bus_dma_tag_destroy(sc->sc_cdmatag); 387174987Smarius fail_ttag: 388108832Stmm bus_dma_tag_destroy(sc->sc_tdmatag); 389174987Smarius fail_rtag: 390108832Stmm bus_dma_tag_destroy(sc->sc_rdmatag); 391174987Smarius fail_ptag: 39291398Stmm bus_dma_tag_destroy(sc->sc_pdmatag); 393174987Smarius fail_ifnet: 394147256Sbrooks if_free(ifp); 39591398Stmm return (error); 39691398Stmm} 39791398Stmm 398108964Stmmvoid 399174987Smariusgem_detach(struct gem_softc *sc) 400108964Stmm{ 401147256Sbrooks struct ifnet *ifp = sc->sc_ifp; 402108964Stmm int i; 403108964Stmm 404148369Smarius GEM_LOCK(sc); 405147317Sbrooks gem_stop(ifp, 1); 406148369Smarius GEM_UNLOCK(sc); 407150285Smarius callout_drain(&sc->sc_tick_ch); 408150285Smarius#ifdef GEM_RINT_TIMEOUT 409150285Smarius callout_drain(&sc->sc_rx_ch); 410150285Smarius#endif 411108964Stmm ether_ifdetach(ifp); 412147256Sbrooks if_free(ifp); 413108964Stmm device_delete_child(sc->sc_dev, sc->sc_miibus); 414108964Stmm 415174987Smarius for (i = 0; i < GEM_NRXDESC; i++) 416108964Stmm if (sc->sc_rxsoft[i].rxs_dmamap != NULL) 417108964Stmm bus_dmamap_destroy(sc->sc_rdmatag, 418108964Stmm sc->sc_rxsoft[i].rxs_dmamap); 419174987Smarius for (i = 0; i < GEM_TXQUEUELEN; i++) 420108964Stmm if (sc->sc_txsoft[i].txs_dmamap != NULL) 421108964Stmm bus_dmamap_destroy(sc->sc_tdmatag, 422108964Stmm sc->sc_txsoft[i].txs_dmamap); 423179925Smarius GEM_CDSYNC(sc, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 424108964Stmm bus_dmamap_unload(sc->sc_cdmatag, sc->sc_cddmamap); 425108964Stmm bus_dmamem_free(sc->sc_cdmatag, sc->sc_control_data, 426108964Stmm sc->sc_cddmamap); 427108964Stmm bus_dma_tag_destroy(sc->sc_cdmatag); 428108964Stmm bus_dma_tag_destroy(sc->sc_tdmatag); 429108964Stmm bus_dma_tag_destroy(sc->sc_rdmatag); 430108964Stmm bus_dma_tag_destroy(sc->sc_pdmatag); 431108964Stmm} 432108964Stmm 433108964Stmmvoid 434174987Smariusgem_suspend(struct gem_softc *sc) 435108964Stmm{ 436147256Sbrooks struct ifnet *ifp = sc->sc_ifp; 437108964Stmm 438148369Smarius GEM_LOCK(sc); 439108964Stmm gem_stop(ifp, 0); 440148369Smarius GEM_UNLOCK(sc); 441108964Stmm} 442108964Stmm 443108964Stmmvoid 444174987Smariusgem_resume(struct gem_softc *sc) 445108964Stmm{ 446147256Sbrooks struct ifnet *ifp = sc->sc_ifp; 447108964Stmm 448148369Smarius GEM_LOCK(sc); 449149552Smarius /* 450149552Smarius * On resume all registers have to be initialized again like 451149552Smarius * after power-on. 452149552Smarius */ 453172334Smarius sc->sc_flags &= ~GEM_INITED; 454108964Stmm if (ifp->if_flags & IFF_UP) 455148369Smarius gem_init_locked(sc); 456148369Smarius GEM_UNLOCK(sc); 457108964Stmm} 458108964Stmm 459170273Syongaristatic __inline void 460170273Syongarigem_rxcksum(struct mbuf *m, uint64_t flags) 461170273Syongari{ 462170273Syongari struct ether_header *eh; 463170273Syongari struct ip *ip; 464170273Syongari struct udphdr *uh; 465174987Smarius uint16_t *opts; 466170273Syongari int32_t hlen, len, pktlen; 467170273Syongari uint32_t temp32; 468174987Smarius uint16_t cksum; 469170273Syongari 470170273Syongari pktlen = m->m_pkthdr.len; 471170273Syongari if (pktlen < sizeof(struct ether_header) + sizeof(struct ip)) 472170273Syongari return; 473170273Syongari eh = mtod(m, struct ether_header *); 474170273Syongari if (eh->ether_type != htons(ETHERTYPE_IP)) 475170273Syongari return; 476170273Syongari ip = (struct ip *)(eh + 1); 477170273Syongari if (ip->ip_v != IPVERSION) 478170273Syongari return; 479170273Syongari 480170273Syongari hlen = ip->ip_hl << 2; 481170273Syongari pktlen -= sizeof(struct ether_header); 482170273Syongari if (hlen < sizeof(struct ip)) 483170273Syongari return; 484170273Syongari if (ntohs(ip->ip_len) < hlen) 485170273Syongari return; 486170273Syongari if (ntohs(ip->ip_len) != pktlen) 487170273Syongari return; 488170273Syongari if (ip->ip_off & htons(IP_MF | IP_OFFMASK)) 489174987Smarius return; /* Cannot handle fragmented packet. */ 490170273Syongari 491170273Syongari switch (ip->ip_p) { 492170273Syongari case IPPROTO_TCP: 493170273Syongari if (pktlen < (hlen + sizeof(struct tcphdr))) 494170273Syongari return; 495170273Syongari break; 496170273Syongari case IPPROTO_UDP: 497170273Syongari if (pktlen < (hlen + sizeof(struct udphdr))) 498170273Syongari return; 499170273Syongari uh = (struct udphdr *)((uint8_t *)ip + hlen); 500170273Syongari if (uh->uh_sum == 0) 501170273Syongari return; /* no checksum */ 502170273Syongari break; 503170273Syongari default: 504170273Syongari return; 505170273Syongari } 506170273Syongari 507170273Syongari cksum = ~(flags & GEM_RD_CHECKSUM); 508170273Syongari /* checksum fixup for IP options */ 509170273Syongari len = hlen - sizeof(struct ip); 510170273Syongari if (len > 0) { 511170273Syongari opts = (uint16_t *)(ip + 1); 512170273Syongari for (; len > 0; len -= sizeof(uint16_t), opts++) { 513170273Syongari temp32 = cksum - *opts; 514170273Syongari temp32 = (temp32 >> 16) + (temp32 & 65535); 515170273Syongari cksum = temp32 & 65535; 516170273Syongari } 517170273Syongari } 518170273Syongari m->m_pkthdr.csum_flags |= CSUM_DATA_VALID; 519170273Syongari m->m_pkthdr.csum_data = cksum; 520170273Syongari} 521170273Syongari 52291398Stmmstatic void 523174987Smariusgem_cddma_callback(void *xsc, bus_dma_segment_t *segs, int nsegs, int error) 52491398Stmm{ 525174987Smarius struct gem_softc *sc = xsc; 52691398Stmm 52791398Stmm if (error != 0) 52891398Stmm return; 529174987Smarius if (nsegs != 1) 530172334Smarius panic("%s: bad control buffer segment count", __func__); 53191398Stmm sc->sc_cddma = segs[0].ds_addr; 53291398Stmm} 53391398Stmm 53491398Stmmstatic void 535174987Smariusgem_tick(void *arg) 53691398Stmm{ 537170273Syongari struct gem_softc *sc = arg; 538170273Syongari struct ifnet *ifp; 539182060Smarius uint32_t v; 54091398Stmm 541170273Syongari GEM_LOCK_ASSERT(sc, MA_OWNED); 542170273Syongari 543170273Syongari ifp = sc->sc_ifp; 544108832Stmm /* 545182060Smarius * Unload collision and error counters. 546108832Stmm */ 547170273Syongari ifp->if_collisions += 548177560Smarius GEM_BANK1_READ_4(sc, GEM_MAC_NORM_COLL_CNT) + 549182060Smarius GEM_BANK1_READ_4(sc, GEM_MAC_FIRST_COLL_CNT); 550182060Smarius v = GEM_BANK1_READ_4(sc, GEM_MAC_EXCESS_COLL_CNT) + 551177560Smarius GEM_BANK1_READ_4(sc, GEM_MAC_LATE_COLL_CNT); 552182060Smarius ifp->if_collisions += v; 553182060Smarius ifp->if_oerrors += v; 554182060Smarius ifp->if_ierrors += 555182060Smarius GEM_BANK1_READ_4(sc, GEM_MAC_RX_LEN_ERR_CNT) + 556182060Smarius GEM_BANK1_READ_4(sc, GEM_MAC_RX_ALIGN_ERR) + 557182060Smarius GEM_BANK1_READ_4(sc, GEM_MAC_RX_CRC_ERR_CNT) + 558182060Smarius GEM_BANK1_READ_4(sc, GEM_MAC_RX_CODE_VIOL); 55991398Stmm 56091398Stmm /* 561176996Smarius * Then clear the hardware counters. 56291398Stmm */ 563177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_NORM_COLL_CNT, 0); 564177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_FIRST_COLL_CNT, 0); 565177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_EXCESS_COLL_CNT, 0); 566177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_LATE_COLL_CNT, 0); 567182060Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_LEN_ERR_CNT, 0); 568182060Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_ALIGN_ERR, 0); 569182060Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_CRC_ERR_CNT, 0); 570182060Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_CODE_VIOL, 0); 571108832Stmm 57291398Stmm mii_tick(sc->sc_mii); 57391398Stmm 574164931Smarius if (gem_watchdog(sc) == EJUSTRETURN) 575164931Smarius return; 576164931Smarius 57791398Stmm callout_reset(&sc->sc_tick_ch, hz, gem_tick, sc); 57891398Stmm} 57991398Stmm 58091398Stmmstatic int 581177560Smariusgem_bitwait(struct gem_softc *sc, u_int bank, bus_addr_t r, uint32_t clr, 582177560Smarius uint32_t set) 58391398Stmm{ 58491398Stmm int i; 585174987Smarius uint32_t reg; 58691398Stmm 58791398Stmm for (i = TRIES; i--; DELAY(100)) { 588177560Smarius reg = GEM_BANKN_READ_M(bank, 4, sc, r); 589170847Smarius if ((reg & clr) == 0 && (reg & set) == set) 59091398Stmm return (1); 59191398Stmm } 59291398Stmm return (0); 59391398Stmm} 59491398Stmm 595172334Smariusstatic void 59691398Stmmgem_reset(sc) 59791398Stmm struct gem_softc *sc; 59891398Stmm{ 59991398Stmm 600115030Stmm#ifdef GEM_DEBUG 601170273Syongari CTR2(KTR_GEM, "%s: %s", device_get_name(sc->sc_dev), __func__); 602115030Stmm#endif 60391398Stmm gem_reset_rx(sc); 60491398Stmm gem_reset_tx(sc); 60591398Stmm 606174987Smarius /* Do a full reset. */ 607177560Smarius GEM_BANK2_WRITE_4(sc, GEM_RESET, GEM_RESET_RX | GEM_RESET_TX); 608179925Smarius GEM_BANK2_BARRIER(sc, GEM_RESET, 4, 609179925Smarius BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 610177560Smarius if (!GEM_BANK2_BITWAIT(sc, GEM_RESET, GEM_RESET_RX | GEM_RESET_TX, 0)) 61191398Stmm device_printf(sc->sc_dev, "cannot reset device\n"); 61291398Stmm} 61391398Stmm 61491398Stmmstatic void 615174987Smariusgem_rxdrain(struct gem_softc *sc) 61691398Stmm{ 61791398Stmm struct gem_rxsoft *rxs; 61891398Stmm int i; 61991398Stmm 62091398Stmm for (i = 0; i < GEM_NRXDESC; i++) { 62191398Stmm rxs = &sc->sc_rxsoft[i]; 62291398Stmm if (rxs->rxs_mbuf != NULL) { 623109648Stmm bus_dmamap_sync(sc->sc_rdmatag, rxs->rxs_dmamap, 624109648Stmm BUS_DMASYNC_POSTREAD); 625108832Stmm bus_dmamap_unload(sc->sc_rdmatag, rxs->rxs_dmamap); 62691398Stmm m_freem(rxs->rxs_mbuf); 62791398Stmm rxs->rxs_mbuf = NULL; 62891398Stmm } 62991398Stmm } 63091398Stmm} 63191398Stmm 63291398Stmmstatic void 633174987Smariusgem_stop(struct ifnet *ifp, int disable) 63491398Stmm{ 635174987Smarius struct gem_softc *sc = ifp->if_softc; 63691398Stmm struct gem_txsoft *txs; 63791398Stmm 638115030Stmm#ifdef GEM_DEBUG 639170273Syongari CTR2(KTR_GEM, "%s: %s", device_get_name(sc->sc_dev), __func__); 640115030Stmm#endif 64191398Stmm 64291398Stmm callout_stop(&sc->sc_tick_ch); 643150285Smarius#ifdef GEM_RINT_TIMEOUT 644150285Smarius callout_stop(&sc->sc_rx_ch); 645172334Smarius#endif 64691398Stmm 647174987Smarius /* XXX should we reset these instead? */ 64891398Stmm gem_disable_tx(sc); 64991398Stmm gem_disable_rx(sc); 65091398Stmm 65191398Stmm /* 65291398Stmm * Release any queued transmit buffers. 65391398Stmm */ 65491398Stmm while ((txs = STAILQ_FIRST(&sc->sc_txdirtyq)) != NULL) { 65591398Stmm STAILQ_REMOVE_HEAD(&sc->sc_txdirtyq, txs_q); 65691398Stmm if (txs->txs_ndescs != 0) { 657109648Stmm bus_dmamap_sync(sc->sc_tdmatag, txs->txs_dmamap, 658109648Stmm BUS_DMASYNC_POSTWRITE); 659108832Stmm bus_dmamap_unload(sc->sc_tdmatag, txs->txs_dmamap); 66091398Stmm if (txs->txs_mbuf != NULL) { 66191398Stmm m_freem(txs->txs_mbuf); 66291398Stmm txs->txs_mbuf = NULL; 66391398Stmm } 66491398Stmm } 66591398Stmm STAILQ_INSERT_TAIL(&sc->sc_txfreeq, txs, txs_q); 66691398Stmm } 66791398Stmm 66891398Stmm if (disable) 66991398Stmm gem_rxdrain(sc); 67091398Stmm 67191398Stmm /* 67291398Stmm * Mark the interface down and cancel the watchdog timer. 67391398Stmm */ 674148887Srwatson ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); 675172334Smarius sc->sc_flags &= ~GEM_LINK; 676164931Smarius sc->sc_wdog_timer = 0; 67791398Stmm} 67891398Stmm 679172334Smariusstatic int 680174987Smariusgem_reset_rx(struct gem_softc *sc) 68191398Stmm{ 68291398Stmm 68391398Stmm /* 68491398Stmm * Resetting while DMA is in progress can cause a bus hang, so we 68591398Stmm * disable DMA first. 68691398Stmm */ 68791398Stmm gem_disable_rx(sc); 688177560Smarius GEM_BANK1_WRITE_4(sc, GEM_RX_CONFIG, 0); 689179925Smarius GEM_BANK1_BARRIER(sc, GEM_RX_CONFIG, 4, 690179925Smarius BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 691177560Smarius if (!GEM_BANK1_BITWAIT(sc, GEM_RX_CONFIG, GEM_RX_CONFIG_RXDMA_EN, 0)) 692172334Smarius device_printf(sc->sc_dev, "cannot disable RX DMA\n"); 69391398Stmm 694176996Smarius /* Finally, reset the ERX. */ 695177560Smarius GEM_BANK2_WRITE_4(sc, GEM_RESET, GEM_RESET_RX); 696179925Smarius GEM_BANK2_BARRIER(sc, GEM_RESET, 4, 697179925Smarius BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 698177560Smarius if (!GEM_BANK2_BITWAIT(sc, GEM_RESET, GEM_RESET_RX | GEM_RESET_TX, 699177560Smarius 0)) { 70091398Stmm device_printf(sc->sc_dev, "cannot reset receiver\n"); 70191398Stmm return (1); 70291398Stmm } 70391398Stmm return (0); 70491398Stmm} 70591398Stmm 706172334Smarius/* 707172334Smarius * Reset the receiver DMA engine. 708172334Smarius * 709172334Smarius * Intended to be used in case of GEM_INTR_RX_TAG_ERR, GEM_MAC_RX_OVERFLOW 710172334Smarius * etc in order to reset the receiver DMA engine only and not do a full 711172334Smarius * reset which amongst others also downs the link and clears the FIFOs. 712172334Smarius */ 713172334Smariusstatic void 714172334Smariusgem_reset_rxdma(struct gem_softc *sc) 715172334Smarius{ 716172334Smarius int i; 71791398Stmm 718172334Smarius if (gem_reset_rx(sc) != 0) 719172334Smarius return (gem_init_locked(sc)); 720172334Smarius for (i = 0; i < GEM_NRXDESC; i++) 721172334Smarius if (sc->sc_rxsoft[i].rxs_mbuf != NULL) 722172334Smarius GEM_UPDATE_RXDESC(sc, i); 723172334Smarius sc->sc_rxptr = 0; 724179925Smarius GEM_CDSYNC(sc, BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); 725172334Smarius 726172334Smarius /* NOTE: we use only 32-bit DMA addresses here. */ 727177560Smarius GEM_BANK1_WRITE_4(sc, GEM_RX_RING_PTR_HI, 0); 728177560Smarius GEM_BANK1_WRITE_4(sc, GEM_RX_RING_PTR_LO, GEM_CDRXADDR(sc, 0)); 729177560Smarius GEM_BANK1_WRITE_4(sc, GEM_RX_KICK, GEM_NRXDESC - 4); 730177560Smarius GEM_BANK1_WRITE_4(sc, GEM_RX_CONFIG, 731174987Smarius gem_ringsize(GEM_NRXDESC /* XXX */) | 732172334Smarius ((ETHER_HDR_LEN + sizeof(struct ip)) << 733172334Smarius GEM_RX_CONFIG_CXM_START_SHFT) | 734172334Smarius (GEM_THRSH_1024 << GEM_RX_CONFIG_FIFO_THRS_SHIFT) | 735172334Smarius (2 << GEM_RX_CONFIG_FBOFF_SHFT)); 736177560Smarius GEM_BANK1_WRITE_4(sc, GEM_RX_BLANKING, 737172334Smarius (6 << GEM_RX_BLANKING_TIME_SHIFT) | 6); 738177560Smarius GEM_BANK1_WRITE_4(sc, GEM_RX_PAUSE_THRESH, 739174987Smarius (3 * sc->sc_rxfifosize / 256) | 740174987Smarius ((sc->sc_rxfifosize / 256) << 12)); 741177560Smarius GEM_BANK1_WRITE_4(sc, GEM_RX_CONFIG, 742177560Smarius GEM_BANK1_READ_4(sc, GEM_RX_CONFIG) | GEM_RX_CONFIG_RXDMA_EN); 743177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_MASK, 744172334Smarius GEM_MAC_RX_DONE | GEM_MAC_RX_FRAME_CNT); 745177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_CONFIG, 746177560Smarius GEM_BANK1_READ_4(sc, GEM_MAC_RX_CONFIG) | GEM_MAC_RX_ENABLE); 747172334Smarius} 748172334Smarius 74991398Stmmstatic int 750174987Smariusgem_reset_tx(struct gem_softc *sc) 75191398Stmm{ 75291398Stmm 75391398Stmm /* 75491398Stmm * Resetting while DMA is in progress can cause a bus hang, so we 75591398Stmm * disable DMA first. 75691398Stmm */ 75791398Stmm gem_disable_tx(sc); 758177560Smarius GEM_BANK1_WRITE_4(sc, GEM_TX_CONFIG, 0); 759179925Smarius GEM_BANK1_BARRIER(sc, GEM_TX_CONFIG, 4, 760179925Smarius BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 761177560Smarius if (!GEM_BANK1_BITWAIT(sc, GEM_TX_CONFIG, GEM_TX_CONFIG_TXDMA_EN, 0)) 762172334Smarius device_printf(sc->sc_dev, "cannot disable TX DMA\n"); 76391398Stmm 764176996Smarius /* Finally, reset the ETX. */ 765177560Smarius GEM_BANK2_WRITE_4(sc, GEM_RESET, GEM_RESET_TX); 766179925Smarius GEM_BANK2_BARRIER(sc, GEM_RESET, 4, 767179925Smarius BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 768177560Smarius if (!GEM_BANK2_BITWAIT(sc, GEM_RESET, GEM_RESET_RX | GEM_RESET_TX, 769177560Smarius 0)) { 770172334Smarius device_printf(sc->sc_dev, "cannot reset transmitter\n"); 77191398Stmm return (1); 77291398Stmm } 77391398Stmm return (0); 77491398Stmm} 77591398Stmm 77691398Stmmstatic int 777174987Smariusgem_disable_rx(struct gem_softc *sc) 77891398Stmm{ 77991398Stmm 780177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_CONFIG, 781177560Smarius GEM_BANK1_READ_4(sc, GEM_MAC_RX_CONFIG) & ~GEM_MAC_RX_ENABLE); 782179925Smarius GEM_BANK1_BARRIER(sc, GEM_MAC_RX_CONFIG, 4, 783179925Smarius BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 784177560Smarius return (GEM_BANK1_BITWAIT(sc, GEM_MAC_RX_CONFIG, GEM_MAC_RX_ENABLE, 785177560Smarius 0)); 78691398Stmm} 78791398Stmm 78891398Stmmstatic int 789174987Smariusgem_disable_tx(struct gem_softc *sc) 79091398Stmm{ 79191398Stmm 792177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_TX_CONFIG, 793177560Smarius GEM_BANK1_READ_4(sc, GEM_MAC_TX_CONFIG) & ~GEM_MAC_TX_ENABLE); 794179925Smarius GEM_BANK1_BARRIER(sc, GEM_MAC_TX_CONFIG, 4, 795179925Smarius BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 796177560Smarius return (GEM_BANK1_BITWAIT(sc, GEM_MAC_TX_CONFIG, GEM_MAC_TX_ENABLE, 797177560Smarius 0)); 79891398Stmm} 79991398Stmm 80091398Stmmstatic int 80191398Stmmgem_meminit(sc) 80291398Stmm struct gem_softc *sc; 80391398Stmm{ 80491398Stmm struct gem_rxsoft *rxs; 805174987Smarius int error, i; 80691398Stmm 80791398Stmm /* 80891398Stmm * Initialize the transmit descriptor ring. 80991398Stmm */ 81091398Stmm for (i = 0; i < GEM_NTXDESC; i++) { 81191398Stmm sc->sc_txdescs[i].gd_flags = 0; 81291398Stmm sc->sc_txdescs[i].gd_addr = 0; 81391398Stmm } 814108832Stmm sc->sc_txfree = GEM_MAXTXFREE; 81591398Stmm sc->sc_txnext = 0; 81699726Sbenno sc->sc_txwin = 0; 81791398Stmm 81891398Stmm /* 81991398Stmm * Initialize the receive descriptor and receive job 82091398Stmm * descriptor rings. 82191398Stmm */ 82291398Stmm for (i = 0; i < GEM_NRXDESC; i++) { 82391398Stmm rxs = &sc->sc_rxsoft[i]; 82491398Stmm if (rxs->rxs_mbuf == NULL) { 82591398Stmm if ((error = gem_add_rxbuf(sc, i)) != 0) { 826174987Smarius device_printf(sc->sc_dev, 827174987Smarius "unable to allocate or map RX buffer %d, " 828174987Smarius "error = %d\n", i, error); 82991398Stmm /* 830174987Smarius * XXX we should attempt to run with fewer 831174987Smarius * receive buffers instead of just failing. 83291398Stmm */ 83391398Stmm gem_rxdrain(sc); 83491398Stmm return (1); 83591398Stmm } 83691398Stmm } else 83791398Stmm GEM_INIT_RXDESC(sc, i); 83891398Stmm } 83991398Stmm sc->sc_rxptr = 0; 840179925Smarius GEM_CDSYNC(sc, BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); 84191398Stmm 84291398Stmm return (0); 84391398Stmm} 84491398Stmm 845172334Smariusstatic u_int 846174987Smariusgem_ringsize(u_int sz) 84791398Stmm{ 84891398Stmm 84991398Stmm switch (sz) { 85091398Stmm case 32: 851172334Smarius return (GEM_RING_SZ_32); 85291398Stmm case 64: 853172334Smarius return (GEM_RING_SZ_64); 85491398Stmm case 128: 855172334Smarius return (GEM_RING_SZ_128); 85691398Stmm case 256: 857172334Smarius return (GEM_RING_SZ_256); 85891398Stmm case 512: 859172334Smarius return (GEM_RING_SZ_512); 86091398Stmm case 1024: 861172334Smarius return (GEM_RING_SZ_1024); 86291398Stmm case 2048: 863172334Smarius return (GEM_RING_SZ_2048); 86491398Stmm case 4096: 865172334Smarius return (GEM_RING_SZ_4096); 86691398Stmm case 8192: 867172334Smarius return (GEM_RING_SZ_8192); 86891398Stmm default: 869172334Smarius printf("%s: invalid ring size %d\n", __func__, sz); 870172334Smarius return (GEM_RING_SZ_32); 87191398Stmm } 87291398Stmm} 87391398Stmm 874148369Smariusstatic void 875174987Smariusgem_init(void *xsc) 876148369Smarius{ 877174987Smarius struct gem_softc *sc = xsc; 878148369Smarius 879148369Smarius GEM_LOCK(sc); 880148369Smarius gem_init_locked(sc); 881148369Smarius GEM_UNLOCK(sc); 882148369Smarius} 883148369Smarius 88491398Stmm/* 88591398Stmm * Initialization of interface; set up initialization block 88691398Stmm * and transmit/receive descriptor rings. 88791398Stmm */ 88891398Stmmstatic void 889174987Smariusgem_init_locked(struct gem_softc *sc) 89091398Stmm{ 891147256Sbrooks struct ifnet *ifp = sc->sc_ifp; 892174987Smarius uint32_t v; 89391398Stmm 894148369Smarius GEM_LOCK_ASSERT(sc, MA_OWNED); 89591398Stmm 896115030Stmm#ifdef GEM_DEBUG 897170273Syongari CTR2(KTR_GEM, "%s: %s: calling stop", device_get_name(sc->sc_dev), 898170273Syongari __func__); 899115030Stmm#endif 90091398Stmm /* 901174987Smarius * Initialization sequence. The numbered steps below correspond 90291398Stmm * to the sequence outlined in section 6.3.5.1 in the Ethernet 90391398Stmm * Channel Engine manual (part of the PCIO manual). 90491398Stmm * See also the STP2002-STQ document from Sun Microsystems. 90591398Stmm */ 90691398Stmm 907174987Smarius /* step 1 & 2. Reset the Ethernet Channel. */ 908179925Smarius gem_stop(ifp, 0); 90991398Stmm gem_reset(sc); 910115030Stmm#ifdef GEM_DEBUG 911170273Syongari CTR2(KTR_GEM, "%s: %s: restarting", device_get_name(sc->sc_dev), 912170273Syongari __func__); 913115030Stmm#endif 91491398Stmm 915174987Smarius /* Re-initialize the MIF. */ 91691398Stmm gem_mifinit(sc); 91791398Stmm 918174987Smarius /* step 3. Setup data structures in host memory. */ 919172334Smarius if (gem_meminit(sc) != 0) 920172334Smarius return; 92191398Stmm 922174987Smarius /* step 4. TX MAC registers & counters */ 92391398Stmm gem_init_regs(sc); 92491398Stmm 925174987Smarius /* step 5. RX MAC registers & counters */ 92691398Stmm gem_setladrf(sc); 92791398Stmm 928174987Smarius /* step 6 & 7. Program Descriptor Ring Base Addresses. */ 92991398Stmm /* NOTE: we use only 32-bit DMA addresses here. */ 930177560Smarius GEM_BANK1_WRITE_4(sc, GEM_TX_RING_PTR_HI, 0); 931177560Smarius GEM_BANK1_WRITE_4(sc, GEM_TX_RING_PTR_LO, GEM_CDTXADDR(sc, 0)); 93291398Stmm 933177560Smarius GEM_BANK1_WRITE_4(sc, GEM_RX_RING_PTR_HI, 0); 934177560Smarius GEM_BANK1_WRITE_4(sc, GEM_RX_RING_PTR_LO, GEM_CDRXADDR(sc, 0)); 935115030Stmm#ifdef GEM_DEBUG 936174987Smarius CTR3(KTR_GEM, "loading RX ring %lx, TX ring %lx, cddma %lx", 93791398Stmm GEM_CDRXADDR(sc, 0), GEM_CDTXADDR(sc, 0), sc->sc_cddma); 938115030Stmm#endif 93991398Stmm 940174987Smarius /* step 8. Global Configuration & Interrupt Mask */ 941177560Smarius GEM_BANK1_WRITE_4(sc, GEM_INTMASK, 942172334Smarius ~(GEM_INTR_TX_INTME | GEM_INTR_TX_EMPTY | GEM_INTR_RX_DONE | 943172334Smarius GEM_INTR_RX_NOBUF | GEM_INTR_RX_TAG_ERR | GEM_INTR_PERR | 944172334Smarius GEM_INTR_BERR 945172334Smarius#ifdef GEM_DEBUG 946172334Smarius | GEM_INTR_PCS | GEM_INTR_MIF 947172334Smarius#endif 948172334Smarius )); 949177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_MASK, 950172334Smarius GEM_MAC_RX_DONE | GEM_MAC_RX_FRAME_CNT); 951177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_TX_MASK, 952172334Smarius GEM_MAC_TX_XMIT_DONE | GEM_MAC_TX_DEFER_EXP); 953172334Smarius#ifdef GEM_DEBUG 954177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_CONTROL_MASK, 955172334Smarius ~(GEM_MAC_PAUSED | GEM_MAC_PAUSE | GEM_MAC_RESUME)); 956172334Smarius#else 957177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_CONTROL_MASK, 958172334Smarius GEM_MAC_PAUSED | GEM_MAC_PAUSE | GEM_MAC_RESUME); 959172334Smarius#endif 96091398Stmm 961174987Smarius /* step 9. ETX Configuration: use mostly default values. */ 96291398Stmm 963174987Smarius /* Enable DMA. */ 964174987Smarius v = gem_ringsize(GEM_NTXDESC /* XXX */); 965179925Smarius v |= ((sc->sc_variant == GEM_SUN_ERI ? 0x100 : 0x4ff) << 10) & 966179925Smarius GEM_TX_CONFIG_TXFIFO_TH; 967179925Smarius GEM_BANK1_WRITE_4(sc, GEM_TX_CONFIG, v | GEM_TX_CONFIG_TXDMA_EN); 96891398Stmm 969174987Smarius /* step 10. ERX Configuration */ 97091398Stmm 971172334Smarius /* Encode Receive Descriptor ring size. */ 972174987Smarius v = gem_ringsize(GEM_NRXDESC /* XXX */); 973174987Smarius /* RX TCP/UDP checksum offset */ 974170273Syongari v |= ((ETHER_HDR_LEN + sizeof(struct ip)) << 975170273Syongari GEM_RX_CONFIG_CXM_START_SHFT); 97691398Stmm 977174987Smarius /* Enable DMA. */ 978177560Smarius GEM_BANK1_WRITE_4(sc, GEM_RX_CONFIG, 979174987Smarius v | (GEM_THRSH_1024 << GEM_RX_CONFIG_FIFO_THRS_SHIFT) | 980174987Smarius (2 << GEM_RX_CONFIG_FBOFF_SHFT) | GEM_RX_CONFIG_RXDMA_EN); 981172334Smarius 982177560Smarius GEM_BANK1_WRITE_4(sc, GEM_RX_BLANKING, 983172334Smarius (6 << GEM_RX_BLANKING_TIME_SHIFT) | 6); 984172334Smarius 98591398Stmm /* 98699726Sbenno * The following value is for an OFF Threshold of about 3/4 full 98799726Sbenno * and an ON Threshold of 1/4 full. 98891398Stmm */ 989177560Smarius GEM_BANK1_WRITE_4(sc, GEM_RX_PAUSE_THRESH, 99099726Sbenno (3 * sc->sc_rxfifosize / 256) | 991174987Smarius ((sc->sc_rxfifosize / 256) << 12)); 99291398Stmm 993174987Smarius /* step 11. Configure Media. */ 99491398Stmm 995174987Smarius /* step 12. RX_MAC Configuration Register */ 996177560Smarius v = GEM_BANK1_READ_4(sc, GEM_MAC_RX_CONFIG); 997179925Smarius v |= GEM_MAC_RX_ENABLE | GEM_MAC_RX_STRIP_CRC; 998177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_CONFIG, 0); 999179925Smarius GEM_BANK1_BARRIER(sc, GEM_MAC_RX_CONFIG, 4, 1000179925Smarius BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 1001177560Smarius if (!GEM_BANK1_BITWAIT(sc, GEM_MAC_RX_CONFIG, GEM_MAC_RX_ENABLE, 0)) 1002179925Smarius device_printf(sc->sc_dev, "cannot configure RX MAC\n"); 1003177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_CONFIG, v); 100491398Stmm 1005179925Smarius /* step 13. TX_MAC Configuration Register */ 1006179925Smarius v = GEM_BANK1_READ_4(sc, GEM_MAC_TX_CONFIG); 1007179925Smarius v |= GEM_MAC_TX_ENABLE; 1008179925Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_TX_CONFIG, 0); 1009179925Smarius GEM_BANK1_BARRIER(sc, GEM_MAC_TX_CONFIG, 4, 1010179925Smarius BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 1011179925Smarius if (!GEM_BANK1_BITWAIT(sc, GEM_MAC_TX_CONFIG, GEM_MAC_TX_ENABLE, 0)) 1012179925Smarius device_printf(sc->sc_dev, "cannot configure TX MAC\n"); 1013179925Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_TX_CONFIG, v); 1014179925Smarius 1015174987Smarius /* step 14. Issue Transmit Pending command. */ 101691398Stmm 1017174987Smarius /* step 15. Give the reciever a swift kick. */ 1018177560Smarius GEM_BANK1_WRITE_4(sc, GEM_RX_KICK, GEM_NRXDESC - 4); 101991398Stmm 1020172334Smarius ifp->if_drv_flags |= IFF_DRV_RUNNING; 1021172334Smarius ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 1022172334Smarius 1023172334Smarius mii_mediachg(sc->sc_mii); 1024172334Smarius 102591398Stmm /* Start the one second timer. */ 1026164931Smarius sc->sc_wdog_timer = 0; 102791398Stmm callout_reset(&sc->sc_tick_ch, hz, gem_tick, sc); 102891398Stmm} 102991398Stmm 103091398Stmmstatic int 1031174987Smariusgem_load_txmbuf(struct gem_softc *sc, struct mbuf **m_head) 103291398Stmm{ 1033174987Smarius bus_dma_segment_t txsegs[GEM_NTXSEGS]; 103491398Stmm struct gem_txsoft *txs; 1035179925Smarius struct ip *ip; 1036170273Syongari struct mbuf *m; 1037174987Smarius uint64_t cflags, flags; 1038179925Smarius int error, nexttx, nsegs, offset, seg; 103991398Stmm 1040108832Stmm /* Get a work queue entry. */ 1041108832Stmm if ((txs = STAILQ_FIRST(&sc->sc_txfreeq)) == NULL) { 1042108832Stmm /* Ran out of descriptors. */ 1043170273Syongari return (ENOBUFS); 1044108832Stmm } 1045179925Smarius 1046179925Smarius cflags = 0; 1047179925Smarius if (((*m_head)->m_pkthdr.csum_flags & sc->sc_csum_features) != 0) { 1048179925Smarius if (M_WRITABLE(*m_head) == 0) { 1049179925Smarius m = m_dup(*m_head, M_DONTWAIT); 1050179925Smarius m_freem(*m_head); 1051179925Smarius *m_head = m; 1052179925Smarius if (m == NULL) 1053179925Smarius return (ENOBUFS); 1054179925Smarius } 1055179925Smarius offset = sizeof(struct ether_header); 1056179925Smarius m = m_pullup(*m_head, offset + sizeof(struct ip)); 1057179925Smarius if (m == NULL) { 1058179925Smarius *m_head = NULL; 1059179925Smarius return (ENOBUFS); 1060179925Smarius } 1061179925Smarius ip = (struct ip *)(mtod(m, caddr_t) + offset); 1062179925Smarius offset += (ip->ip_hl << 2); 1063179925Smarius cflags = offset << GEM_TD_CXSUM_STARTSHFT | 1064179925Smarius ((offset + m->m_pkthdr.csum_data) << 1065179925Smarius GEM_TD_CXSUM_STUFFSHFT) | GEM_TD_CXSUM_ENABLE; 1066179925Smarius *m_head = m; 1067179925Smarius } 1068179925Smarius 1069170273Syongari error = bus_dmamap_load_mbuf_sg(sc->sc_tdmatag, txs->txs_dmamap, 1070170273Syongari *m_head, txsegs, &nsegs, BUS_DMA_NOWAIT); 1071170273Syongari if (error == EFBIG) { 1072175418Sjhb m = m_collapse(*m_head, M_DONTWAIT, GEM_NTXSEGS); 1073170273Syongari if (m == NULL) { 1074170273Syongari m_freem(*m_head); 1075170273Syongari *m_head = NULL; 1076170273Syongari return (ENOBUFS); 1077170273Syongari } 1078170273Syongari *m_head = m; 1079174987Smarius error = bus_dmamap_load_mbuf_sg(sc->sc_tdmatag, 1080174987Smarius txs->txs_dmamap, *m_head, txsegs, &nsegs, 1081174987Smarius BUS_DMA_NOWAIT); 1082170273Syongari if (error != 0) { 1083170273Syongari m_freem(*m_head); 1084170273Syongari *m_head = NULL; 1085170273Syongari return (error); 1086170273Syongari } 1087170273Syongari } else if (error != 0) 1088170273Syongari return (error); 1089176996Smarius /* If nsegs is wrong then the stack is corrupt. */ 1090176996Smarius KASSERT(nsegs <= GEM_NTXSEGS, 1091176996Smarius ("%s: too many DMA segments (%d)", __func__, nsegs)); 1092170273Syongari if (nsegs == 0) { 1093170273Syongari m_freem(*m_head); 1094170273Syongari *m_head = NULL; 1095170273Syongari return (EIO); 1096170273Syongari } 1097170273Syongari 1098170273Syongari /* 1099170273Syongari * Ensure we have enough descriptors free to describe 1100170273Syongari * the packet. Note, we always reserve one descriptor 1101174987Smarius * at the end of the ring as a termination point, in 1102174987Smarius * order to prevent wrap-around. 1103170273Syongari */ 1104170273Syongari if (nsegs > sc->sc_txfree - 1) { 1105170273Syongari txs->txs_ndescs = 0; 1106170273Syongari bus_dmamap_unload(sc->sc_tdmatag, txs->txs_dmamap); 1107170273Syongari return (ENOBUFS); 1108170273Syongari } 1109170273Syongari 1110170273Syongari txs->txs_ndescs = nsegs; 1111108832Stmm txs->txs_firstdesc = sc->sc_txnext; 1112170273Syongari nexttx = txs->txs_firstdesc; 1113170273Syongari for (seg = 0; seg < nsegs; seg++, nexttx = GEM_NEXTTX(nexttx)) { 1114172334Smarius#ifdef GEM_DEBUG 1115174987Smarius CTR6(KTR_GEM, 1116174987Smarius "%s: mapping seg %d (txd %d), len %lx, addr %#lx (%#lx)", 1117174987Smarius __func__, seg, nexttx, txsegs[seg].ds_len, 1118174987Smarius txsegs[seg].ds_addr, 1119170273Syongari GEM_DMA_WRITE(sc, txsegs[seg].ds_addr)); 1120170273Syongari#endif 1121170273Syongari sc->sc_txdescs[nexttx].gd_addr = 1122170273Syongari GEM_DMA_WRITE(sc, txsegs[seg].ds_addr); 1123170273Syongari KASSERT(txsegs[seg].ds_len < GEM_TD_BUFSIZE, 1124170273Syongari ("%s: segment size too large!", __func__)); 1125170273Syongari flags = txsegs[seg].ds_len & GEM_TD_BUFSIZE; 1126170273Syongari sc->sc_txdescs[nexttx].gd_flags = 1127170273Syongari GEM_DMA_WRITE(sc, flags | cflags); 1128170273Syongari txs->txs_lastdesc = nexttx; 112991398Stmm } 113091398Stmm 1131174987Smarius /* Set EOP on the last descriptor. */ 1132172334Smarius#ifdef GEM_DEBUG 1133174987Smarius CTR3(KTR_GEM, "%s: end of packet at segment %d, TX %d", 1134174987Smarius __func__, seg, nexttx); 1135170273Syongari#endif 1136170273Syongari sc->sc_txdescs[txs->txs_lastdesc].gd_flags |= 1137170273Syongari GEM_DMA_WRITE(sc, GEM_TD_END_OF_PACKET); 1138170273Syongari 1139174987Smarius /* Lastly set SOP on the first descriptor. */ 1140172334Smarius#ifdef GEM_DEBUG 1141174987Smarius CTR3(KTR_GEM, "%s: start of packet at segment %d, TX %d", 1142174987Smarius __func__, seg, nexttx); 1143170273Syongari#endif 1144170273Syongari if (++sc->sc_txwin > GEM_NTXSEGS * 2 / 3) { 1145170273Syongari sc->sc_txwin = 0; 1146170273Syongari flags |= GEM_TD_INTERRUPT_ME; 1147170273Syongari sc->sc_txdescs[txs->txs_firstdesc].gd_flags |= 1148170273Syongari GEM_DMA_WRITE(sc, GEM_TD_INTERRUPT_ME | 1149170273Syongari GEM_TD_START_OF_PACKET); 1150170273Syongari } else 1151170273Syongari sc->sc_txdescs[txs->txs_firstdesc].gd_flags |= 1152170273Syongari GEM_DMA_WRITE(sc, GEM_TD_START_OF_PACKET); 1153170273Syongari 1154108832Stmm /* Sync the DMA map. */ 1155174987Smarius bus_dmamap_sync(sc->sc_tdmatag, txs->txs_dmamap, 1156174987Smarius BUS_DMASYNC_PREWRITE); 115791398Stmm 1158115030Stmm#ifdef GEM_DEBUG 1159170273Syongari CTR4(KTR_GEM, "%s: setting firstdesc=%d, lastdesc=%d, ndescs=%d", 1160174987Smarius __func__, txs->txs_firstdesc, txs->txs_lastdesc, 1161174987Smarius txs->txs_ndescs); 1162115030Stmm#endif 1163108832Stmm STAILQ_REMOVE_HEAD(&sc->sc_txfreeq, txs_q); 1164108832Stmm STAILQ_INSERT_TAIL(&sc->sc_txdirtyq, txs, txs_q); 1165170273Syongari txs->txs_mbuf = *m_head; 116691398Stmm 1167108832Stmm sc->sc_txnext = GEM_NEXTTX(txs->txs_lastdesc); 1168108832Stmm sc->sc_txfree -= txs->txs_ndescs; 1169170273Syongari 1170108832Stmm return (0); 117191398Stmm} 117291398Stmm 117391398Stmmstatic void 1174174987Smariusgem_init_regs(struct gem_softc *sc) 117591398Stmm{ 1176152315Sru const u_char *laddr = IF_LLADDR(sc->sc_ifp); 117791398Stmm 1178174987Smarius /* These registers are not cleared on reset. */ 1179172334Smarius if ((sc->sc_flags & GEM_INITED) == 0) { 1180174987Smarius /* magic values */ 1181177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_IPG0, 0); 1182177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_IPG1, 8); 1183177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_IPG2, 4); 118491398Stmm 1185177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_MAC_MIN_FRAME, ETHER_MIN_LEN); 1186174987Smarius /* max frame and max burst size */ 1187177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_MAC_MAX_FRAME, 1188172334Smarius (ETHER_MAX_LEN + ETHER_VLAN_ENCAP_LEN) | (0x2000 << 16)); 118999726Sbenno 1190177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_PREAMBLE_LEN, 0x7); 1191177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_JAM_SIZE, 0x4); 1192177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_ATTEMPT_LIMIT, 0x10); 1193174987Smarius /* dunno... */ 1194177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_CONTROL_TYPE, 0x8088); 1195177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_RANDOM_SEED, 1196174987Smarius ((laddr[5] << 8) | laddr[4]) & 0x3ff); 119799726Sbenno 1198174987Smarius /* secondary MAC address: 0:0:0:0:0:0 */ 1199177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_ADDR3, 0); 1200177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_ADDR4, 0); 1201177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_ADDR5, 0); 120299726Sbenno 1203174987Smarius /* MAC control address: 01:80:c2:00:00:01 */ 1204177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_ADDR6, 0x0001); 1205177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_ADDR7, 0xc200); 1206177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_ADDR8, 0x0180); 120791398Stmm 1208174987Smarius /* MAC filter address: 0:0:0:0:0:0 */ 1209177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_ADDR_FILTER0, 0); 1210177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_ADDR_FILTER1, 0); 1211177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_ADDR_FILTER2, 0); 121291398Stmm 1213177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_ADR_FLT_MASK1_2, 0); 1214177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_ADR_FLT_MASK0, 0); 121591398Stmm 1216172334Smarius sc->sc_flags |= GEM_INITED; 121791398Stmm } 121891398Stmm 1219174987Smarius /* Counters need to be zeroed. */ 1220177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_NORM_COLL_CNT, 0); 1221177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_FIRST_COLL_CNT, 0); 1222177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_EXCESS_COLL_CNT, 0); 1223177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_LATE_COLL_CNT, 0); 1224177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_DEFER_TMR_CNT, 0); 1225177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_PEAK_ATTEMPTS, 0); 1226177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_FRAME_COUNT, 0); 1227177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_LEN_ERR_CNT, 0); 1228177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_ALIGN_ERR, 0); 1229177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_CRC_ERR_CNT, 0); 1230177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_CODE_VIOL, 0); 123191398Stmm 1232172334Smarius /* Set XOFF PAUSE time. */ 1233177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_SEND_PAUSE_CMD, 0x1BF0); 123491398Stmm 123591398Stmm /* 1236172334Smarius * Set the internal arbitration to "infinite" bursts of the 1237172334Smarius * maximum length of 31 * 64 bytes so DMA transfers aren't 1238174987Smarius * split up in cache line size chunks. This greatly improves 1239172334Smarius * especially RX performance. 1240172334Smarius * Enable silicon bug workarounds for the Apple variants. 1241172334Smarius */ 1242177560Smarius GEM_BANK1_WRITE_4(sc, GEM_CONFIG, 1243172334Smarius GEM_CONFIG_TXDMA_LIMIT | GEM_CONFIG_RXDMA_LIMIT | 1244172334Smarius GEM_CONFIG_BURST_INF | (GEM_IS_APPLE(sc) ? 1245172334Smarius GEM_CONFIG_RONPAULBIT | GEM_CONFIG_BUG2FIX : 0)); 1246172334Smarius 1247174987Smarius /* Set the station address. */ 1248177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_ADDR0, (laddr[4] << 8) | laddr[5]); 1249177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_ADDR1, (laddr[2] << 8) | laddr[3]); 1250177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_ADDR2, (laddr[0] << 8) | laddr[1]); 125199726Sbenno 1252172334Smarius /* Enable MII outputs. */ 1253177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_XIF_CONFIG, GEM_MAC_XIF_TX_MII_ENA); 125491398Stmm} 125591398Stmm 125691398Stmmstatic void 1257174987Smariusgem_start(struct ifnet *ifp) 125891398Stmm{ 1259174987Smarius struct gem_softc *sc = ifp->if_softc; 1260148369Smarius 1261148369Smarius GEM_LOCK(sc); 1262148369Smarius gem_start_locked(ifp); 1263148369Smarius GEM_UNLOCK(sc); 1264148369Smarius} 1265148369Smarius 1266148369Smariusstatic void 1267174987Smariusgem_start_locked(struct ifnet *ifp) 1268148369Smarius{ 1269174987Smarius struct gem_softc *sc = ifp->if_softc; 1270170273Syongari struct mbuf *m; 1271174987Smarius int ntx; 127291398Stmm 1273148887Srwatson if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) != 1274172334Smarius IFF_DRV_RUNNING || (sc->sc_flags & GEM_LINK) == 0) 127591398Stmm return; 127691398Stmm 1277115030Stmm#ifdef GEM_DEBUG 1278170273Syongari CTR4(KTR_GEM, "%s: %s: txfree %d, txnext %d", 1279172334Smarius device_get_name(sc->sc_dev), __func__, sc->sc_txfree, 1280172334Smarius sc->sc_txnext); 1281115030Stmm#endif 1282174987Smarius ntx = 0; 1283170273Syongari for (; !IFQ_DRV_IS_EMPTY(&ifp->if_snd) && sc->sc_txfree > 1;) { 1284170273Syongari IFQ_DRV_DEQUEUE(&ifp->if_snd, m); 1285170273Syongari if (m == NULL) 128691398Stmm break; 1287172334Smarius if (gem_load_txmbuf(sc, &m) != 0) { 1288170273Syongari if (m == NULL) 1289170273Syongari break; 1290170273Syongari ifp->if_drv_flags |= IFF_DRV_OACTIVE; 1291170273Syongari IFQ_DRV_PREPEND(&ifp->if_snd, m); 129291398Stmm break; 129391398Stmm } 1294115030Stmm ntx++; 1295108832Stmm /* Kick the transmitter. */ 1296172334Smarius#ifdef GEM_DEBUG 1297174987Smarius CTR3(KTR_GEM, "%s: %s: kicking TX %d", 1298170273Syongari device_get_name(sc->sc_dev), __func__, sc->sc_txnext); 1299115030Stmm#endif 1300179925Smarius GEM_CDSYNC(sc, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 1301177560Smarius GEM_BANK1_WRITE_4(sc, GEM_TX_KICK, sc->sc_txnext); 1302108832Stmm 1303170273Syongari BPF_MTAP(ifp, m); 130491398Stmm } 130591398Stmm 130691398Stmm if (ntx > 0) { 1307115030Stmm#ifdef GEM_DEBUG 1308108832Stmm CTR2(KTR_GEM, "%s: packets enqueued, OWN on %d", 1309172334Smarius device_get_name(sc->sc_dev), sc->sc_txnext); 1310115030Stmm#endif 131191398Stmm 131291398Stmm /* Set a watchdog timer in case the chip flakes out. */ 1313164931Smarius sc->sc_wdog_timer = 5; 1314115030Stmm#ifdef GEM_DEBUG 1315170273Syongari CTR3(KTR_GEM, "%s: %s: watchdog %d", 1316174987Smarius device_get_name(sc->sc_dev), __func__, 1317174987Smarius sc->sc_wdog_timer); 1318115030Stmm#endif 131991398Stmm } 132091398Stmm} 132191398Stmm 132291398Stmmstatic void 1323174987Smariusgem_tint(struct gem_softc *sc) 132491398Stmm{ 1325147256Sbrooks struct ifnet *ifp = sc->sc_ifp; 132691398Stmm struct gem_txsoft *txs; 1327174987Smarius int txlast, progress; 1328174987Smarius#ifdef GEM_DEBUG 1329174987Smarius int i; 133091398Stmm 1331170273Syongari CTR2(KTR_GEM, "%s: %s", device_get_name(sc->sc_dev), __func__); 1332115030Stmm#endif 133391398Stmm 133491398Stmm /* 1335174987Smarius * Go through our TX list and free mbufs for those 133691398Stmm * frames that have been transmitted. 133791398Stmm */ 1338174987Smarius progress = 0; 1339109648Stmm GEM_CDSYNC(sc, BUS_DMASYNC_POSTREAD); 134091398Stmm while ((txs = STAILQ_FIRST(&sc->sc_txdirtyq)) != NULL) { 134191398Stmm 134291398Stmm#ifdef GEM_DEBUG 1343174987Smarius if ((ifp->if_flags & IFF_DEBUG) != 0) { 134491398Stmm printf(" txsoft %p transmit chain:\n", txs); 134591398Stmm for (i = txs->txs_firstdesc;; i = GEM_NEXTTX(i)) { 134691398Stmm printf("descriptor %d: ", i); 1347174987Smarius printf("gd_flags: 0x%016llx\t", 1348174987Smarius (long long)GEM_DMA_READ(sc, 1349174987Smarius sc->sc_txdescs[i].gd_flags)); 1350174987Smarius printf("gd_addr: 0x%016llx\n", 1351174987Smarius (long long)GEM_DMA_READ(sc, 1352174987Smarius sc->sc_txdescs[i].gd_addr)); 135391398Stmm if (i == txs->txs_lastdesc) 135491398Stmm break; 135591398Stmm } 135691398Stmm } 135791398Stmm#endif 135891398Stmm 135991398Stmm /* 1360172334Smarius * In theory, we could harvest some descriptors before 136191398Stmm * the ring is empty, but that's a bit complicated. 136291398Stmm * 136391398Stmm * GEM_TX_COMPLETION points to the last descriptor 1364174987Smarius * processed + 1. 136591398Stmm */ 1366177560Smarius txlast = GEM_BANK1_READ_4(sc, GEM_TX_COMPLETION); 1367115030Stmm#ifdef GEM_DEBUG 1368170273Syongari CTR4(KTR_GEM, "%s: txs->txs_firstdesc = %d, " 136991398Stmm "txs->txs_lastdesc = %d, txlast = %d", 1370170273Syongari __func__, txs->txs_firstdesc, txs->txs_lastdesc, txlast); 1371115030Stmm#endif 137291398Stmm if (txs->txs_firstdesc <= txs->txs_lastdesc) { 137391398Stmm if ((txlast >= txs->txs_firstdesc) && 1374174987Smarius (txlast <= txs->txs_lastdesc)) 137591398Stmm break; 137691398Stmm } else { 1377174987Smarius /* Ick -- this command wraps. */ 137891398Stmm if ((txlast >= txs->txs_firstdesc) || 1379174987Smarius (txlast <= txs->txs_lastdesc)) 138091398Stmm break; 138191398Stmm } 138291398Stmm 1383115030Stmm#ifdef GEM_DEBUG 1384174987Smarius CTR1(KTR_GEM, "%s: releasing a descriptor", __func__); 1385115030Stmm#endif 138691398Stmm STAILQ_REMOVE_HEAD(&sc->sc_txdirtyq, txs_q); 138791398Stmm 138891398Stmm sc->sc_txfree += txs->txs_ndescs; 138991398Stmm 1390108832Stmm bus_dmamap_sync(sc->sc_tdmatag, txs->txs_dmamap, 139191398Stmm BUS_DMASYNC_POSTWRITE); 1392108832Stmm bus_dmamap_unload(sc->sc_tdmatag, txs->txs_dmamap); 139391398Stmm if (txs->txs_mbuf != NULL) { 139491398Stmm m_freem(txs->txs_mbuf); 139591398Stmm txs->txs_mbuf = NULL; 139691398Stmm } 139791398Stmm 139891398Stmm STAILQ_INSERT_TAIL(&sc->sc_txfreeq, txs, txs_q); 139991398Stmm 140091398Stmm ifp->if_opackets++; 140199726Sbenno progress = 1; 140291398Stmm } 140391398Stmm 1404115030Stmm#ifdef GEM_DEBUG 1405174987Smarius CTR4(KTR_GEM, "%s: GEM_TX_STATE_MACHINE %x GEM_TX_DATA_PTR %llx " 1406172334Smarius "GEM_TX_COMPLETION %x", 1407177560Smarius __func__, GEM_BANK1_READ_4(sc, GEM_TX_STATE_MACHINE), 1408177560Smarius ((long long)GEM_BANK1_READ_4(sc, GEM_TX_DATA_PTR_HI) << 32) | 1409177560Smarius GEM_BANK1_READ_4(sc, GEM_TX_DATA_PTR_LO), 1410177560Smarius GEM_BANK1_READ_4(sc, GEM_TX_COMPLETION)); 1411115030Stmm#endif 141291398Stmm 141399726Sbenno if (progress) { 141499726Sbenno if (sc->sc_txfree == GEM_NTXDESC - 1) 141599726Sbenno sc->sc_txwin = 0; 141691398Stmm 1417174987Smarius /* 1418174987Smarius * We freed some descriptors, so reset IFF_DRV_OACTIVE 1419174987Smarius * and restart. 1420174987Smarius */ 1421148887Srwatson ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 1422170273Syongari sc->sc_wdog_timer = STAILQ_EMPTY(&sc->sc_txdirtyq) ? 0 : 5; 142391398Stmm 1424179925Smarius gem_start_locked(ifp); 142599726Sbenno } 142699726Sbenno 1427115030Stmm#ifdef GEM_DEBUG 1428170273Syongari CTR3(KTR_GEM, "%s: %s: watchdog %d", 1429170273Syongari device_get_name(sc->sc_dev), __func__, sc->sc_wdog_timer); 1430115030Stmm#endif 143191398Stmm} 143291398Stmm 1433148368Smarius#ifdef GEM_RINT_TIMEOUT 143493045Stmmstatic void 1435174987Smariusgem_rint_timeout(void *arg) 143693045Stmm{ 1437174987Smarius struct gem_softc *sc = arg; 143893045Stmm 1439150285Smarius GEM_LOCK_ASSERT(sc, MA_OWNED); 1440148369Smarius gem_rint(sc); 144193045Stmm} 1442100587Sjake#endif 144393045Stmm 144491398Stmmstatic void 1445174987Smariusgem_rint(struct gem_softc *sc) 144691398Stmm{ 1447147256Sbrooks struct ifnet *ifp = sc->sc_ifp; 144891398Stmm struct mbuf *m; 1449174987Smarius uint64_t rxstat; 1450174987Smarius uint32_t rxcomp; 145191398Stmm 1452148368Smarius#ifdef GEM_RINT_TIMEOUT 145393045Stmm callout_stop(&sc->sc_rx_ch); 1454148368Smarius#endif 1455115030Stmm#ifdef GEM_DEBUG 1456170273Syongari CTR2(KTR_GEM, "%s: %s", device_get_name(sc->sc_dev), __func__); 1457115030Stmm#endif 145899726Sbenno 145991398Stmm /* 146099726Sbenno * Read the completion register once. This limits 146199726Sbenno * how long the following loop can execute. 146299726Sbenno */ 1463177560Smarius rxcomp = GEM_BANK1_READ_4(sc, GEM_RX_COMPLETION); 146499726Sbenno 1465115030Stmm#ifdef GEM_DEBUG 1466170273Syongari CTR3(KTR_GEM, "%s: sc->rxptr %d, complete %d", 1467170273Syongari __func__, sc->sc_rxptr, rxcomp); 1468115030Stmm#endif 1469109648Stmm GEM_CDSYNC(sc, BUS_DMASYNC_POSTREAD); 1470172334Smarius for (; sc->sc_rxptr != rxcomp;) { 1471172334Smarius m = sc->sc_rxsoft[sc->sc_rxptr].rxs_mbuf; 1472172334Smarius rxstat = GEM_DMA_READ(sc, 1473172334Smarius sc->sc_rxdescs[sc->sc_rxptr].gd_flags); 147491398Stmm 147591398Stmm if (rxstat & GEM_RD_OWN) { 1476148368Smarius#ifdef GEM_RINT_TIMEOUT 147791398Stmm /* 147893045Stmm * The descriptor is still marked as owned, although 1479174987Smarius * it is supposed to have completed. This has been 1480174987Smarius * observed on some machines. Just exiting here 148193045Stmm * might leave the packet sitting around until another 148293045Stmm * one arrives to trigger a new interrupt, which is 148393045Stmm * generally undesirable, so set up a timeout. 148491398Stmm */ 148593045Stmm callout_reset(&sc->sc_rx_ch, GEM_RXOWN_TICKS, 148693045Stmm gem_rint_timeout, sc); 148799726Sbenno#endif 1488172334Smarius m = NULL; 1489172334Smarius goto kickit; 149091398Stmm } 149191398Stmm 149291398Stmm if (rxstat & GEM_RD_BAD_CRC) { 149399726Sbenno ifp->if_ierrors++; 149491398Stmm device_printf(sc->sc_dev, "receive error: CRC error\n"); 1495172334Smarius GEM_INIT_RXDESC(sc, sc->sc_rxptr); 1496172334Smarius m = NULL; 1497172334Smarius goto kickit; 149891398Stmm } 149991398Stmm 150091398Stmm#ifdef GEM_DEBUG 1501174987Smarius if ((ifp->if_flags & IFF_DEBUG) != 0) { 1502172334Smarius printf(" rxsoft %p descriptor %d: ", 1503172334Smarius &sc->sc_rxsoft[sc->sc_rxptr], sc->sc_rxptr); 1504174987Smarius printf("gd_flags: 0x%016llx\t", 1505174987Smarius (long long)GEM_DMA_READ(sc, 1506174987Smarius sc->sc_rxdescs[sc->sc_rxptr].gd_flags)); 1507174987Smarius printf("gd_addr: 0x%016llx\n", 1508174987Smarius (long long)GEM_DMA_READ(sc, 1509174987Smarius sc->sc_rxdescs[sc->sc_rxptr].gd_addr)); 151091398Stmm } 151191398Stmm#endif 151291398Stmm 151391398Stmm /* 151491398Stmm * Allocate a new mbuf cluster. If that fails, we are 151591398Stmm * out of memory, and must drop the packet and recycle 151691398Stmm * the buffer that's already attached to this descriptor. 151791398Stmm */ 1518172334Smarius if (gem_add_rxbuf(sc, sc->sc_rxptr) != 0) { 151991398Stmm ifp->if_ierrors++; 1520172334Smarius GEM_INIT_RXDESC(sc, sc->sc_rxptr); 1521172334Smarius m = NULL; 1522172334Smarius } 1523172334Smarius 1524174987Smarius kickit: 1525174987Smarius /* 1526174987Smarius * Update the RX kick register. This register has to point 1527172334Smarius * to the descriptor after the last valid one (before the 1528172334Smarius * current batch) and must be incremented in multiples of 1529172334Smarius * 4 (because the DMA engine fetches/updates descriptors 1530172334Smarius * in batches of 4). 1531172334Smarius */ 1532172334Smarius sc->sc_rxptr = GEM_NEXTRX(sc->sc_rxptr); 1533172334Smarius if ((sc->sc_rxptr % 4) == 0) { 1534179925Smarius GEM_CDSYNC(sc, 1535179925Smarius BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 1536177560Smarius GEM_BANK1_WRITE_4(sc, GEM_RX_KICK, 1537172334Smarius (sc->sc_rxptr + GEM_NRXDESC - 4) & 1538172334Smarius GEM_NRXDESC_MASK); 1539172334Smarius } 1540172334Smarius 1541172334Smarius if (m == NULL) { 1542172334Smarius if (rxstat & GEM_RD_OWN) 1543172334Smarius break; 154491398Stmm continue; 154591398Stmm } 1546172334Smarius 1547172334Smarius ifp->if_ipackets++; 154891398Stmm m->m_data += 2; /* We're already off by two */ 154991398Stmm m->m_pkthdr.rcvif = ifp; 1550172334Smarius m->m_pkthdr.len = m->m_len = GEM_RD_BUFLEN(rxstat); 155191398Stmm 1552170273Syongari if ((ifp->if_capenable & IFCAP_RXCSUM) != 0) 1553170273Syongari gem_rxcksum(m, rxstat); 1554170273Syongari 155591398Stmm /* Pass it on. */ 1556148369Smarius GEM_UNLOCK(sc); 1557106937Ssam (*ifp->if_input)(ifp, m); 1558148369Smarius GEM_LOCK(sc); 155991398Stmm } 156091398Stmm 1561115030Stmm#ifdef GEM_DEBUG 1562170273Syongari CTR3(KTR_GEM, "%s: done sc->rxptr %d, complete %d", __func__, 1563177560Smarius sc->sc_rxptr, GEM_BANK1_READ_4(sc, GEM_RX_COMPLETION)); 1564115030Stmm#endif 156591398Stmm} 156691398Stmm 156791398Stmmstatic int 1568174987Smariusgem_add_rxbuf(struct gem_softc *sc, int idx) 156991398Stmm{ 157091398Stmm struct gem_rxsoft *rxs = &sc->sc_rxsoft[idx]; 157191398Stmm struct mbuf *m; 1572148368Smarius bus_dma_segment_t segs[1]; 1573148368Smarius int error, nsegs; 157491398Stmm 1575111119Simp m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); 157691398Stmm if (m == NULL) 157791398Stmm return (ENOBUFS); 1578108832Stmm m->m_len = m->m_pkthdr.len = m->m_ext.ext_size; 157991398Stmm 158091398Stmm#ifdef GEM_DEBUG 1581174987Smarius /* Bzero the packet to check DMA. */ 158291398Stmm memset(m->m_ext.ext_buf, 0, m->m_ext.ext_size); 158391398Stmm#endif 158491398Stmm 1585109648Stmm if (rxs->rxs_mbuf != NULL) { 1586109648Stmm bus_dmamap_sync(sc->sc_rdmatag, rxs->rxs_dmamap, 1587109648Stmm BUS_DMASYNC_POSTREAD); 1588108832Stmm bus_dmamap_unload(sc->sc_rdmatag, rxs->rxs_dmamap); 1589109648Stmm } 159091398Stmm 1591148368Smarius error = bus_dmamap_load_mbuf_sg(sc->sc_rdmatag, rxs->rxs_dmamap, 1592148368Smarius m, segs, &nsegs, BUS_DMA_NOWAIT); 1593148368Smarius if (error != 0) { 1594174987Smarius device_printf(sc->sc_dev, 1595174987Smarius "cannot load RS DMA map %d, error = %d\n", idx, error); 1596148368Smarius m_freem(m); 1597172334Smarius return (error); 159891398Stmm } 1599174987Smarius /* If nsegs is wrong then the stack is corrupt. */ 1600176996Smarius KASSERT(nsegs == 1, 1601176996Smarius ("%s: too many DMA segments (%d)", __func__, nsegs)); 1602172334Smarius rxs->rxs_mbuf = m; 1603148368Smarius rxs->rxs_paddr = segs[0].ds_addr; 160491398Stmm 1605174987Smarius bus_dmamap_sync(sc->sc_rdmatag, rxs->rxs_dmamap, 1606174987Smarius BUS_DMASYNC_PREREAD); 160791398Stmm 160891398Stmm GEM_INIT_RXDESC(sc, idx); 160991398Stmm 161091398Stmm return (0); 161191398Stmm} 161291398Stmm 161391398Stmmstatic void 1614174987Smariusgem_eint(struct gem_softc *sc, u_int status) 161591398Stmm{ 161691398Stmm 1617172334Smarius sc->sc_ifp->if_ierrors++; 1618172334Smarius if ((status & GEM_INTR_RX_TAG_ERR) != 0) { 1619172334Smarius gem_reset_rxdma(sc); 162091398Stmm return; 162191398Stmm } 162291398Stmm 1623172334Smarius device_printf(sc->sc_dev, "%s: status=%x\n", __func__, status); 162491398Stmm} 162591398Stmm 162691398Stmmvoid 1627174987Smariusgem_intr(void *v) 162891398Stmm{ 1629174987Smarius struct gem_softc *sc = v; 1630172334Smarius uint32_t status, status2; 163191398Stmm 1632148369Smarius GEM_LOCK(sc); 1633177560Smarius status = GEM_BANK1_READ_4(sc, GEM_STATUS); 1634172334Smarius 1635115030Stmm#ifdef GEM_DEBUG 1636170273Syongari CTR4(KTR_GEM, "%s: %s: cplt %x, status %x", 1637174987Smarius device_get_name(sc->sc_dev), __func__, (status >> 19), 1638174987Smarius (u_int)status); 1639172334Smarius 1640172334Smarius /* 1641172334Smarius * PCS interrupts must be cleared, otherwise no traffic is passed! 1642172334Smarius */ 1643172334Smarius if ((status & GEM_INTR_PCS) != 0) { 1644174987Smarius status2 = 1645177560Smarius GEM_BANK1_READ_4(sc, GEM_MII_INTERRUP_STATUS) | 1646177560Smarius GEM_BANK1_READ_4(sc, GEM_MII_INTERRUP_STATUS); 1647172334Smarius if ((status2 & GEM_MII_INTERRUP_LINK) != 0) 1648172334Smarius device_printf(sc->sc_dev, 1649172334Smarius "%s: PCS link status changed\n", __func__); 1650172334Smarius } 1651172334Smarius if ((status & GEM_MAC_CONTROL_STATUS) != 0) { 1652177560Smarius status2 = GEM_BANK1_READ_4(sc, GEM_MAC_CONTROL_STATUS); 1653172334Smarius if ((status2 & GEM_MAC_PAUSED) != 0) 1654172334Smarius device_printf(sc->sc_dev, 1655172334Smarius "%s: PAUSE received (PAUSE time %d slots)\n", 1656172334Smarius __func__, GEM_MAC_PAUSE_TIME(status2)); 1657172334Smarius if ((status2 & GEM_MAC_PAUSE) != 0) 1658172334Smarius device_printf(sc->sc_dev, 1659172334Smarius "%s: transited to PAUSE state\n", __func__); 1660172334Smarius if ((status2 & GEM_MAC_RESUME) != 0) 1661172334Smarius device_printf(sc->sc_dev, 1662172334Smarius "%s: transited to non-PAUSE state\n", __func__); 1663172334Smarius } 1664172334Smarius if ((status & GEM_INTR_MIF) != 0) 1665172334Smarius device_printf(sc->sc_dev, "%s: MIF interrupt\n", __func__); 1666115030Stmm#endif 166791398Stmm 1668172334Smarius if ((status & 1669172334Smarius (GEM_INTR_RX_TAG_ERR | GEM_INTR_PERR | GEM_INTR_BERR)) != 0) 167091398Stmm gem_eint(sc, status); 167191398Stmm 1672172334Smarius if ((status & (GEM_INTR_RX_DONE | GEM_INTR_RX_NOBUF)) != 0) 1673172334Smarius gem_rint(sc); 1674172334Smarius 167591398Stmm if ((status & (GEM_INTR_TX_EMPTY | GEM_INTR_TX_INTME)) != 0) 167691398Stmm gem_tint(sc); 167791398Stmm 167891398Stmm if (status & GEM_INTR_TX_MAC) { 1679177560Smarius status2 = GEM_BANK1_READ_4(sc, GEM_MAC_TX_STATUS); 1680174987Smarius if ((status2 & 1681174987Smarius ~(GEM_MAC_TX_XMIT_DONE | GEM_MAC_TX_DEFER_EXP)) != 0) 1682174987Smarius device_printf(sc->sc_dev, 1683174987Smarius "MAC TX fault, status %x\n", status2); 1684174987Smarius if ((status2 & 1685174987Smarius (GEM_MAC_TX_UNDERRUN | GEM_MAC_TX_PKT_TOO_LONG)) != 0) 1686148369Smarius gem_init_locked(sc); 168791398Stmm } 168891398Stmm if (status & GEM_INTR_RX_MAC) { 1689177560Smarius status2 = GEM_BANK1_READ_4(sc, GEM_MAC_RX_STATUS); 1690149552Smarius /* 1691172334Smarius * At least with GEM_SUN_GEM and some GEM_SUN_ERI 1692172334Smarius * revisions GEM_MAC_RX_OVERFLOW happen often due to a 1693174987Smarius * silicon bug so handle them silently. Moreover, it's 1694172334Smarius * likely that the receiver has hung so we reset it. 1695149552Smarius */ 1696174987Smarius if ((status2 & GEM_MAC_RX_OVERFLOW) != 0) { 1697172334Smarius sc->sc_ifp->if_ierrors++; 1698172334Smarius gem_reset_rxdma(sc); 1699174987Smarius } else if ((status2 & 1700174987Smarius ~(GEM_MAC_RX_DONE | GEM_MAC_RX_FRAME_CNT)) != 0) 1701174987Smarius device_printf(sc->sc_dev, 1702174987Smarius "MAC RX fault, status %x\n", status2); 170391398Stmm } 1704148369Smarius GEM_UNLOCK(sc); 170591398Stmm} 170691398Stmm 1707164931Smariusstatic int 1708174987Smariusgem_watchdog(struct gem_softc *sc) 170991398Stmm{ 1710179925Smarius struct ifnet *ifp = sc->sc_ifp; 171191398Stmm 1712164931Smarius GEM_LOCK_ASSERT(sc, MA_OWNED); 1713164931Smarius 1714115030Stmm#ifdef GEM_DEBUG 1715174987Smarius CTR4(KTR_GEM, 1716174987Smarius "%s: GEM_RX_CONFIG %x GEM_MAC_RX_STATUS %x GEM_MAC_RX_CONFIG %x", 1717177560Smarius __func__, GEM_BANK1_READ_4(sc, GEM_RX_CONFIG), 1718177560Smarius GEM_BANK1_READ_4(sc, GEM_MAC_RX_STATUS), 1719177560Smarius GEM_BANK1_READ_4(sc, GEM_MAC_RX_CONFIG)); 1720174987Smarius CTR4(KTR_GEM, 1721174987Smarius "%s: GEM_TX_CONFIG %x GEM_MAC_TX_STATUS %x GEM_MAC_TX_CONFIG %x", 1722177560Smarius __func__, GEM_BANK1_READ_4(sc, GEM_TX_CONFIG), 1723177560Smarius GEM_BANK1_READ_4(sc, GEM_MAC_TX_STATUS), 1724177560Smarius GEM_BANK1_READ_4(sc, GEM_MAC_TX_CONFIG)); 1725115030Stmm#endif 172691398Stmm 1727164931Smarius if (sc->sc_wdog_timer == 0 || --sc->sc_wdog_timer != 0) 1728164931Smarius return (0); 1729164931Smarius 1730172334Smarius if ((sc->sc_flags & GEM_LINK) != 0) 1731172334Smarius device_printf(sc->sc_dev, "device timeout\n"); 1732172334Smarius else if (bootverbose) 1733172334Smarius device_printf(sc->sc_dev, "device timeout (no link)\n"); 1734179925Smarius ++ifp->if_oerrors; 173591398Stmm 173691398Stmm /* Try to get more packets going. */ 1737148369Smarius gem_init_locked(sc); 1738179925Smarius gem_start_locked(ifp); 1739164931Smarius return (EJUSTRETURN); 174091398Stmm} 174191398Stmm 174291398Stmmstatic void 1743174987Smariusgem_mifinit(struct gem_softc *sc) 174491398Stmm{ 174591398Stmm 1746176996Smarius /* Configure the MIF in frame mode. */ 1747177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MIF_CONFIG, 1748177560Smarius GEM_BANK1_READ_4(sc, GEM_MIF_CONFIG) & ~GEM_MIF_CONFIG_BB_ENA); 174991398Stmm} 175091398Stmm 175191398Stmm/* 175291398Stmm * MII interface 175391398Stmm * 1754182060Smarius * The MII interface supports at least three different operating modes: 175591398Stmm * 175691398Stmm * Bitbang mode is implemented using data, clock and output enable registers. 175791398Stmm * 175891398Stmm * Frame mode is implemented by loading a complete frame into the frame 175991398Stmm * register and polling the valid bit for completion. 176091398Stmm * 176191398Stmm * Polling mode uses the frame register but completion is indicated by 176291398Stmm * an interrupt. 176391398Stmm * 176491398Stmm */ 176591398Stmmint 1766174987Smariusgem_mii_readreg(device_t dev, int phy, int reg) 176791398Stmm{ 1768174987Smarius struct gem_softc *sc; 176991398Stmm int n; 1770174987Smarius uint32_t v; 177191398Stmm 177291398Stmm#ifdef GEM_DEBUG_PHY 1773172334Smarius printf("%s: phy %d reg %d\n", __func__, phy, reg); 177491398Stmm#endif 177591398Stmm 1776174987Smarius sc = device_get_softc(dev); 1777172334Smarius if (sc->sc_phyad != -1 && phy != sc->sc_phyad) 1778172334Smarius return (0); 177991398Stmm 1780172334Smarius if ((sc->sc_flags & GEM_SERDES) != 0) { 1781172334Smarius switch (reg) { 1782172334Smarius case MII_BMCR: 1783172334Smarius reg = GEM_MII_CONTROL; 1784172334Smarius break; 1785172334Smarius case MII_BMSR: 1786172334Smarius reg = GEM_MII_STATUS; 1787172334Smarius break; 1788172334Smarius case MII_PHYIDR1: 1789172334Smarius case MII_PHYIDR2: 1790172334Smarius return (0); 1791172334Smarius case MII_ANAR: 1792172334Smarius reg = GEM_MII_ANAR; 1793172334Smarius break; 1794172334Smarius case MII_ANLPAR: 1795172334Smarius reg = GEM_MII_ANLPAR; 1796172334Smarius break; 1797172334Smarius case MII_EXTSR: 1798172334Smarius return (EXTSR_1000XFDX | EXTSR_1000XHDX); 1799172334Smarius default: 1800172334Smarius device_printf(sc->sc_dev, 1801172334Smarius "%s: unhandled register %d\n", __func__, reg); 1802172334Smarius return (0); 1803172334Smarius } 1804177560Smarius return (GEM_BANK1_READ_4(sc, reg)); 1805172334Smarius } 1806172334Smarius 1807174987Smarius /* Construct the frame command. */ 1808172334Smarius v = GEM_MIF_FRAME_READ | 1809172334Smarius (phy << GEM_MIF_PHY_SHIFT) | 1810172334Smarius (reg << GEM_MIF_REG_SHIFT); 181191398Stmm 1812177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MIF_FRAME, v); 1813179925Smarius GEM_BANK1_BARRIER(sc, GEM_MIF_FRAME, 4, 1814179925Smarius BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 181591398Stmm for (n = 0; n < 100; n++) { 181691398Stmm DELAY(1); 1817177560Smarius v = GEM_BANK1_READ_4(sc, GEM_MIF_FRAME); 1818150285Smarius if (v & GEM_MIF_FRAME_TA0) 181991398Stmm return (v & GEM_MIF_FRAME_DATA); 182091398Stmm } 182191398Stmm 1822174987Smarius device_printf(sc->sc_dev, "%s: timed out\n", __func__); 182391398Stmm return (0); 182491398Stmm} 182591398Stmm 182691398Stmmint 1827174987Smariusgem_mii_writereg(device_t dev, int phy, int reg, int val) 182891398Stmm{ 1829174987Smarius struct gem_softc *sc; 183091398Stmm int n; 1831174987Smarius uint32_t v; 183291398Stmm 183391398Stmm#ifdef GEM_DEBUG_PHY 1834172334Smarius printf("%s: phy %d reg %d val %x\n", phy, reg, val, __func__); 183591398Stmm#endif 183691398Stmm 1837174987Smarius sc = device_get_softc(dev); 1838172334Smarius if (sc->sc_phyad != -1 && phy != sc->sc_phyad) 1839172334Smarius return (0); 1840172334Smarius 1841172334Smarius if ((sc->sc_flags & GEM_SERDES) != 0) { 1842172334Smarius switch (reg) { 1843172334Smarius case MII_BMSR: 1844172334Smarius reg = GEM_MII_STATUS; 1845172334Smarius break; 1846179925Smarius case MII_BMCR: 1847179925Smarius reg = GEM_MII_CONTROL; 1848179925Smarius if ((val & GEM_MII_CONTROL_RESET) == 0) 1849179925Smarius break; 1850179925Smarius GEM_BANK1_WRITE_4(sc, GEM_MII_CONTROL, val); 1851179925Smarius GEM_BANK1_BARRIER(sc, GEM_MII_CONTROL, 4, 1852179925Smarius BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 1853179925Smarius if (!GEM_BANK1_BITWAIT(sc, GEM_MII_CONTROL, 1854179925Smarius GEM_MII_CONTROL_RESET, 0)) 1855179925Smarius device_printf(sc->sc_dev, 1856179925Smarius "cannot reset PCS\n"); 1857179925Smarius /* FALLTHROUGH */ 1858172334Smarius case MII_ANAR: 1859177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MII_CONFIG, 0); 1860177560Smarius GEM_BANK1_BARRIER(sc, GEM_MII_CONFIG, 4, 1861172334Smarius BUS_SPACE_BARRIER_WRITE); 1862177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MII_ANAR, val); 1863177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MII_SLINK_CONTROL, 1864172334Smarius GEM_MII_SLINK_LOOPBACK | GEM_MII_SLINK_EN_SYNC_D); 1865177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MII_CONFIG, 1866172334Smarius GEM_MII_CONFIG_ENABLE); 1867172334Smarius return (0); 1868172334Smarius case MII_ANLPAR: 1869172334Smarius reg = GEM_MII_ANLPAR; 1870172334Smarius break; 1871172334Smarius default: 1872172334Smarius device_printf(sc->sc_dev, 1873172334Smarius "%s: unhandled register %d\n", __func__, reg); 1874172334Smarius return (0); 1875172334Smarius } 1876177560Smarius GEM_BANK1_WRITE_4(sc, reg, val); 1877172334Smarius return (0); 1878172334Smarius } 1879172334Smarius 1880174987Smarius /* Construct the frame command. */ 1881172334Smarius v = GEM_MIF_FRAME_WRITE | 1882172334Smarius (phy << GEM_MIF_PHY_SHIFT) | 1883172334Smarius (reg << GEM_MIF_REG_SHIFT) | 188491398Stmm (val & GEM_MIF_FRAME_DATA); 188591398Stmm 1886177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MIF_FRAME, v); 1887179925Smarius GEM_BANK1_BARRIER(sc, GEM_MIF_FRAME, 4, 1888179925Smarius BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 188991398Stmm for (n = 0; n < 100; n++) { 189091398Stmm DELAY(1); 1891177560Smarius v = GEM_BANK1_READ_4(sc, GEM_MIF_FRAME); 1892150285Smarius if (v & GEM_MIF_FRAME_TA0) 189391398Stmm return (1); 189491398Stmm } 189591398Stmm 1896174987Smarius device_printf(sc->sc_dev, "%s: timed out\n", __func__); 189791398Stmm return (0); 189891398Stmm} 189991398Stmm 190091398Stmmvoid 1901174987Smariusgem_mii_statchg(device_t dev) 190291398Stmm{ 1903174987Smarius struct gem_softc *sc; 1904172334Smarius int gigabit; 1905172334Smarius uint32_t rxcfg, txcfg, v; 190691398Stmm 1907174987Smarius sc = device_get_softc(dev); 1908174987Smarius 190991398Stmm#ifdef GEM_DEBUG 1910174987Smarius if ((sc->sc_ifp->if_flags & IFF_DEBUG) != 0) 1911172334Smarius device_printf(sc->sc_dev, "%s: status change: PHY = %d\n", 1912172334Smarius __func__, sc->sc_phyad); 191391398Stmm#endif 191491398Stmm 1915172334Smarius if ((sc->sc_mii->mii_media_status & IFM_ACTIVE) != 0 && 1916172334Smarius IFM_SUBTYPE(sc->sc_mii->mii_media_active) != IFM_NONE) 1917172334Smarius sc->sc_flags |= GEM_LINK; 1918172334Smarius else 1919172334Smarius sc->sc_flags &= ~GEM_LINK; 1920172334Smarius 1921172334Smarius switch (IFM_SUBTYPE(sc->sc_mii->mii_media_active)) { 1922172334Smarius case IFM_1000_SX: 1923172334Smarius case IFM_1000_LX: 1924172334Smarius case IFM_1000_CX: 1925172334Smarius case IFM_1000_T: 1926172334Smarius gigabit = 1; 1927172334Smarius break; 1928172334Smarius default: 1929172334Smarius gigabit = 0; 193091398Stmm } 193191398Stmm 1932172334Smarius /* 1933172334Smarius * The configuration done here corresponds to the steps F) and 1934172334Smarius * G) and as far as enabling of RX and TX MAC goes also step H) 1935172334Smarius * of the initialization sequence outlined in section 3.2.1 of 1936172334Smarius * the GEM Gigabit Ethernet ASIC Specification. 1937172334Smarius */ 1938172334Smarius 1939177560Smarius rxcfg = GEM_BANK1_READ_4(sc, GEM_MAC_RX_CONFIG); 1940172334Smarius rxcfg &= ~(GEM_MAC_RX_CARR_EXTEND | GEM_MAC_RX_ENABLE); 1941172334Smarius txcfg = GEM_MAC_TX_ENA_IPG0 | GEM_MAC_TX_NGU | GEM_MAC_TX_NGU_LIMIT; 1942172334Smarius if ((IFM_OPTIONS(sc->sc_mii->mii_media_active) & IFM_FDX) != 0) 1943172334Smarius txcfg |= GEM_MAC_TX_IGN_CARRIER | GEM_MAC_TX_IGN_COLLIS; 1944172334Smarius else if (gigabit != 0) { 1945172334Smarius rxcfg |= GEM_MAC_RX_CARR_EXTEND; 1946172334Smarius txcfg |= GEM_MAC_TX_CARR_EXTEND; 1947172334Smarius } 1948177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_TX_CONFIG, 0); 1949179925Smarius GEM_BANK1_BARRIER(sc, GEM_MAC_TX_CONFIG, 4, 1950179925Smarius BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 1951177560Smarius if (!GEM_BANK1_BITWAIT(sc, GEM_MAC_TX_CONFIG, GEM_MAC_TX_ENABLE, 0)) 1952172334Smarius device_printf(sc->sc_dev, "cannot disable TX MAC\n"); 1953177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_TX_CONFIG, txcfg); 1954177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_CONFIG, 0); 1955179925Smarius GEM_BANK1_BARRIER(sc, GEM_MAC_RX_CONFIG, 4, 1956179925Smarius BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 1957177560Smarius if (!GEM_BANK1_BITWAIT(sc, GEM_MAC_RX_CONFIG, GEM_MAC_RX_ENABLE, 0)) 1958172334Smarius device_printf(sc->sc_dev, "cannot disable RX MAC\n"); 1959177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_CONFIG, rxcfg); 1960172334Smarius 1961177560Smarius v = GEM_BANK1_READ_4(sc, GEM_MAC_CONTROL_CONFIG) & 1962172334Smarius ~(GEM_MAC_CC_RX_PAUSE | GEM_MAC_CC_TX_PAUSE); 1963172334Smarius#ifdef notyet 1964174987Smarius if ((IFM_OPTIONS(sc->sc_mii->mii_media_active) & 1965174987Smarius IFM_ETH_RXPAUSE) != 0) 1966172334Smarius v |= GEM_MAC_CC_RX_PAUSE; 1967174987Smarius if ((IFM_OPTIONS(sc->sc_mii->mii_media_active) & 1968174987Smarius IFM_ETH_TXPAUSE) != 0) 1969172334Smarius v |= GEM_MAC_CC_TX_PAUSE; 1970172334Smarius#endif 1971177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_CONTROL_CONFIG, v); 1972172334Smarius 1973172334Smarius if ((IFM_OPTIONS(sc->sc_mii->mii_media_active) & IFM_FDX) == 0 && 1974172334Smarius gigabit != 0) 1975177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_SLOT_TIME, 1976172334Smarius GEM_MAC_SLOT_TIME_CARR_EXTEND); 1977172334Smarius else 1978177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_SLOT_TIME, 1979172334Smarius GEM_MAC_SLOT_TIME_NORMAL); 1980172334Smarius 198191398Stmm /* XIF Configuration */ 198291398Stmm v = GEM_MAC_XIF_LINK_LED; 198391398Stmm v |= GEM_MAC_XIF_TX_MII_ENA; 1984172334Smarius if ((sc->sc_flags & GEM_SERDES) == 0) { 1985177560Smarius if ((GEM_BANK1_READ_4(sc, GEM_MIF_CONFIG) & 1986182060Smarius GEM_MIF_CONFIG_PHY_SEL) != 0) { 1987172334Smarius /* External MII needs echo disable if half duplex. */ 1988182060Smarius if ((IFM_OPTIONS(sc->sc_mii->mii_media_active) & 1989182060Smarius IFM_FDX) == 0) 1990182060Smarius v |= GEM_MAC_XIF_ECHO_DISABL; 1991182060Smarius } else 1992172334Smarius /* 1993172334Smarius * Internal MII needs buffer enable. 1994172334Smarius * XXX buffer enable makes only sense for an 1995172334Smarius * external PHY. 1996172334Smarius */ 1997172334Smarius v |= GEM_MAC_XIF_MII_BUF_ENA; 1998172334Smarius } 1999172334Smarius if (gigabit != 0) 2000172334Smarius v |= GEM_MAC_XIF_GMII_MODE; 2001172334Smarius if ((IFM_OPTIONS(sc->sc_mii->mii_media_active) & IFM_FDX) != 0) 2002172334Smarius v |= GEM_MAC_XIF_FDPLX_LED; 2003177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_XIF_CONFIG, v); 200499726Sbenno 2005172334Smarius if ((sc->sc_ifp->if_drv_flags & IFF_DRV_RUNNING) != 0 && 2006172334Smarius (sc->sc_flags & GEM_LINK) != 0) { 2007177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_TX_CONFIG, 2008172334Smarius txcfg | GEM_MAC_TX_ENABLE); 2009177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_CONFIG, 2010172334Smarius rxcfg | GEM_MAC_RX_ENABLE); 201191398Stmm } 201291398Stmm} 201391398Stmm 201491398Stmmint 2015174987Smariusgem_mediachange(struct ifnet *ifp) 201691398Stmm{ 201791398Stmm struct gem_softc *sc = ifp->if_softc; 2018150285Smarius int error; 201991398Stmm 2020174987Smarius /* XXX add support for serial media. */ 202191398Stmm 2022150285Smarius GEM_LOCK(sc); 2023150285Smarius error = mii_mediachg(sc->sc_mii); 2024150285Smarius GEM_UNLOCK(sc); 2025150285Smarius return (error); 202691398Stmm} 202791398Stmm 202891398Stmmvoid 2029174987Smariusgem_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr) 203091398Stmm{ 203191398Stmm struct gem_softc *sc = ifp->if_softc; 203291398Stmm 2033148369Smarius GEM_LOCK(sc); 2034148369Smarius if ((ifp->if_flags & IFF_UP) == 0) { 2035148369Smarius GEM_UNLOCK(sc); 203691398Stmm return; 2037148369Smarius } 203891398Stmm 203991398Stmm mii_pollstat(sc->sc_mii); 204091398Stmm ifmr->ifm_active = sc->sc_mii->mii_media_active; 204191398Stmm ifmr->ifm_status = sc->sc_mii->mii_media_status; 2042148369Smarius GEM_UNLOCK(sc); 204391398Stmm} 204491398Stmm 204591398Stmmstatic int 2046174987Smariusgem_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 204791398Stmm{ 204891398Stmm struct gem_softc *sc = ifp->if_softc; 204991398Stmm struct ifreq *ifr = (struct ifreq *)data; 2050174987Smarius int error; 205191398Stmm 2052174987Smarius error = 0; 205391398Stmm switch (cmd) { 2054150285Smarius case SIOCSIFFLAGS: 2055148369Smarius GEM_LOCK(sc); 2056174987Smarius if ((ifp->if_flags & IFF_UP) != 0) { 2057172334Smarius if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0 && 2058172334Smarius ((ifp->if_flags ^ sc->sc_ifflags) & 2059172334Smarius (IFF_ALLMULTI | IFF_PROMISC)) != 0) 206091398Stmm gem_setladrf(sc); 206191398Stmm else 2062148369Smarius gem_init_locked(sc); 2063174987Smarius } else if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) 2064174987Smarius gem_stop(ifp, 0); 2065170273Syongari if ((ifp->if_flags & IFF_LINK0) != 0) 2066170273Syongari sc->sc_csum_features |= CSUM_UDP; 2067170273Syongari else 2068170273Syongari sc->sc_csum_features &= ~CSUM_UDP; 2069170273Syongari if ((ifp->if_capenable & IFCAP_TXCSUM) != 0) 2070170273Syongari ifp->if_hwassist = sc->sc_csum_features; 207199726Sbenno sc->sc_ifflags = ifp->if_flags; 2072150285Smarius GEM_UNLOCK(sc); 207391398Stmm break; 207491398Stmm case SIOCADDMULTI: 207591398Stmm case SIOCDELMULTI: 2076150285Smarius GEM_LOCK(sc); 207791398Stmm gem_setladrf(sc); 2078150285Smarius GEM_UNLOCK(sc); 207991398Stmm break; 208091398Stmm case SIOCGIFMEDIA: 208191398Stmm case SIOCSIFMEDIA: 208291398Stmm error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii->mii_media, cmd); 208391398Stmm break; 2084170273Syongari case SIOCSIFCAP: 2085170273Syongari GEM_LOCK(sc); 2086170273Syongari ifp->if_capenable = ifr->ifr_reqcap; 2087170273Syongari if ((ifp->if_capenable & IFCAP_TXCSUM) != 0) 2088170273Syongari ifp->if_hwassist = sc->sc_csum_features; 2089170273Syongari else 2090170273Syongari ifp->if_hwassist = 0; 2091170273Syongari GEM_UNLOCK(sc); 2092170273Syongari break; 209391398Stmm default: 2094150285Smarius error = ether_ioctl(ifp, cmd, data); 209591398Stmm break; 209691398Stmm } 209791398Stmm 209891398Stmm return (error); 209991398Stmm} 210091398Stmm 210191398Stmmstatic void 2102174987Smariusgem_setladrf(struct gem_softc *sc) 210391398Stmm{ 2104147256Sbrooks struct ifnet *ifp = sc->sc_ifp; 210591398Stmm struct ifmultiaddr *inm; 210699726Sbenno int i; 2107174987Smarius uint32_t hash[16]; 2108174987Smarius uint32_t crc, v; 210991398Stmm 2110148369Smarius GEM_LOCK_ASSERT(sc, MA_OWNED); 2111148369Smarius 2112174987Smarius /* Get the current RX configuration. */ 2113177560Smarius v = GEM_BANK1_READ_4(sc, GEM_MAC_RX_CONFIG); 211491398Stmm 211599726Sbenno /* 211699726Sbenno * Turn off promiscuous mode, promiscuous group mode (all multicast), 211799726Sbenno * and hash filter. Depending on the case, the right bit will be 211899726Sbenno * enabled. 211999726Sbenno */ 2120174987Smarius v &= ~(GEM_MAC_RX_PROMISCUOUS | GEM_MAC_RX_HASH_FILTER | 212199726Sbenno GEM_MAC_RX_PROMISC_GRP); 212299726Sbenno 2123177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_CONFIG, v); 2124179925Smarius GEM_BANK1_BARRIER(sc, GEM_MAC_RX_CONFIG, 4, 2125179925Smarius BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); 2126177560Smarius if (!GEM_BANK1_BITWAIT(sc, GEM_MAC_RX_CONFIG, GEM_MAC_RX_HASH_FILTER, 2127177560Smarius 0)) 2128172334Smarius device_printf(sc->sc_dev, "cannot disable RX hash filter\n"); 2129172334Smarius 213091398Stmm if ((ifp->if_flags & IFF_PROMISC) != 0) { 213191398Stmm v |= GEM_MAC_RX_PROMISCUOUS; 213291398Stmm goto chipit; 213391398Stmm } 213491398Stmm if ((ifp->if_flags & IFF_ALLMULTI) != 0) { 213599726Sbenno v |= GEM_MAC_RX_PROMISC_GRP; 213691398Stmm goto chipit; 213791398Stmm } 213891398Stmm 213991398Stmm /* 2140174987Smarius * Set up multicast address filter by passing all multicast 2141174987Smarius * addresses through a crc generator, and then using the high 2142174987Smarius * order 8 bits as an index into the 256 bit logical address 2143174987Smarius * filter. The high order 4 bits selects the word, while the 2144174987Smarius * other 4 bits select the bit within the word (where bit 0 2145174987Smarius * is the MSB). 214691398Stmm */ 214791398Stmm 2148174987Smarius /* Clear the hash table. */ 214999726Sbenno memset(hash, 0, sizeof(hash)); 215099726Sbenno 2151148654Srwatson IF_ADDR_LOCK(ifp); 2152147256Sbrooks TAILQ_FOREACH(inm, &ifp->if_multiaddrs, ifma_link) { 215391398Stmm if (inm->ifma_addr->sa_family != AF_LINK) 215491398Stmm continue; 2155130288Smarius crc = ether_crc32_le(LLADDR((struct sockaddr_dl *) 2156130288Smarius inm->ifma_addr), ETHER_ADDR_LEN); 215791398Stmm 2158174987Smarius /* We just want the 8 most significant bits. */ 215991398Stmm crc >>= 24; 216091398Stmm 216191398Stmm /* Set the corresponding bit in the filter. */ 216299726Sbenno hash[crc >> 4] |= 1 << (15 - (crc & 15)); 216391398Stmm } 2164148654Srwatson IF_ADDR_UNLOCK(ifp); 216591398Stmm 216699726Sbenno v |= GEM_MAC_RX_HASH_FILTER; 216799726Sbenno 2168174987Smarius /* Now load the hash table into the chip (if we are using it). */ 2169174987Smarius for (i = 0; i < 16; i++) 2170177560Smarius GEM_BANK1_WRITE_4(sc, 2171174987Smarius GEM_MAC_HASH0 + i * (GEM_MAC_HASH1 - GEM_MAC_HASH0), 217299726Sbenno hash[i]); 217399726Sbenno 2174174987Smarius chipit: 2175177560Smarius GEM_BANK1_WRITE_4(sc, GEM_MAC_RX_CONFIG, v); 217691398Stmm} 2177