if_gem.c revision 174987
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 174987 2007-12-30 01:32:03Z 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/* 90174987Smarius * The GEM hardware support 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); 99174987Smariusstatic int gem_bitwait(struct gem_softc *sc, bus_addr_t r, uint32_t clr, 100174987Smarius uint32_t set); 101174987Smariusstatic void gem_cddma_callback(void *xsc, bus_dma_segment_t *segs, 102174987Smarius int nsegs, int error); 103174987Smariusstatic struct mbuf *gem_defrag(struct mbuf *m0, int how, int maxfrags); 104174987Smariusstatic int gem_disable_rx(struct gem_softc *sc); 105174987Smariusstatic int gem_disable_tx(struct gem_softc *sc); 106174987Smariusstatic void gem_eint(struct gem_softc *sc, u_int status); 107174987Smariusstatic void gem_init(void *xsc); 108174987Smariusstatic void gem_init_locked(struct gem_softc *sc); 109174987Smariusstatic void gem_init_regs(struct gem_softc *sc); 110174987Smariusstatic int gem_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data); 111174987Smariusstatic int gem_load_txmbuf(struct gem_softc *sc, struct mbuf **m_head); 112174987Smariusstatic int gem_meminit(struct gem_softc *sc); 113174987Smariusstatic void gem_mifinit(struct gem_softc *sc); 114174987Smariusstatic void gem_reset(struct gem_softc *sc); 115174987Smariusstatic int gem_reset_rx(struct gem_softc *sc); 116172334Smariusstatic void gem_reset_rxdma(struct gem_softc *sc); 117174987Smariusstatic int gem_reset_tx(struct gem_softc *sc); 118174987Smariusstatic u_int gem_ringsize(u_int sz); 119174987Smariusstatic void gem_rint(struct gem_softc *sc); 120148368Smarius#ifdef GEM_RINT_TIMEOUT 121174987Smariusstatic void gem_rint_timeout(void *arg); 122100587Sjake#endif 123174987Smariusstatic __inline void gem_rxcksum(struct mbuf *m, uint64_t flags); 124174987Smariusstatic void gem_rxdrain(struct gem_softc *sc); 125174987Smariusstatic void gem_setladrf(struct gem_softc *sc); 126174987Smariusstatic void gem_start(struct ifnet *ifp); 127174987Smariusstatic void gem_start_locked(struct ifnet *ifp); 128174987Smariusstatic void gem_stop(struct ifnet *ifp, int disable); 129174987Smariusstatic void gem_tick(void *arg); 130174987Smariusstatic void gem_tint(struct gem_softc *sc); 131174987Smariusstatic __inline void gem_txcksum(struct gem_softc *sc, struct mbuf *m, 132174987Smarius uint64_t *cflags); 133174987Smariusstatic int gem_watchdog(struct gem_softc *sc); 13491398Stmm 13591398Stmmdevclass_t gem_devclass; 13691398StmmDRIVER_MODULE(miibus, gem, miibus_driver, miibus_devclass, 0, 0); 13791398StmmMODULE_DEPEND(gem, miibus, 1, 1, 1); 13891398Stmm 13991398Stmm#ifdef GEM_DEBUG 14091398Stmm#include <sys/ktr.h> 14191398Stmm#define KTR_GEM KTR_CT2 14291398Stmm#endif 14391398Stmm 14491398Stmmint 145174987Smariusgem_attach(struct gem_softc *sc) 14691398Stmm{ 147174987Smarius struct gem_txsoft *txs; 148147256Sbrooks struct ifnet *ifp; 149174987Smarius int error, i; 150174987Smarius uint32_t v; 15191398Stmm 152147256Sbrooks ifp = sc->sc_ifp = if_alloc(IFT_ETHER); 153147256Sbrooks if (ifp == NULL) 154147256Sbrooks return (ENOSPC); 155147256Sbrooks 156150285Smarius callout_init_mtx(&sc->sc_tick_ch, &sc->sc_mtx, 0); 157150285Smarius#ifdef GEM_RINT_TIMEOUT 158150285Smarius callout_init_mtx(&sc->sc_rx_ch, &sc->sc_mtx, 0); 159150285Smarius#endif 160150285Smarius 16191398Stmm /* Make sure the chip is stopped. */ 16291398Stmm ifp->if_softc = sc; 16391398Stmm gem_reset(sc); 16491398Stmm 165161928Sjmg error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), 1, 0, 166161928Sjmg BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, 167174987Smarius BUS_SPACE_MAXSIZE_32BIT, 0, BUS_SPACE_MAXSIZE_32BIT, 0, NULL, 168174987Smarius NULL, &sc->sc_pdmatag); 16991398Stmm if (error) 170147256Sbrooks goto fail_ifnet; 17191398Stmm 17291398Stmm error = bus_dma_tag_create(sc->sc_pdmatag, 1, 0, 173170273Syongari BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, MCLBYTES, 174170273Syongari 1, MCLBYTES, BUS_DMA_ALLOCNOW, NULL, NULL, &sc->sc_rdmatag); 17591398Stmm if (error) 176108832Stmm goto fail_ptag; 17791398Stmm 178108832Stmm error = bus_dma_tag_create(sc->sc_pdmatag, 1, 0, 179170273Syongari BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, 180170273Syongari MCLBYTES * GEM_NTXSEGS, GEM_NTXSEGS, MCLBYTES, 181117126Sscottl BUS_DMA_ALLOCNOW, NULL, NULL, &sc->sc_tdmatag); 182108832Stmm if (error) 183108832Stmm goto fail_rtag; 184108832Stmm 18591398Stmm error = bus_dma_tag_create(sc->sc_pdmatag, PAGE_SIZE, 0, 186170273Syongari BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, 18791398Stmm sizeof(struct gem_control_data), 1, 188170273Syongari sizeof(struct gem_control_data), 0, 189170273Syongari NULL, NULL, &sc->sc_cdmatag); 19091398Stmm if (error) 191108832Stmm goto fail_ttag; 19291398Stmm 19391398Stmm /* 194174987Smarius * Allocate the control data structures, create and load the 19591398Stmm * DMA map for it. 19691398Stmm */ 19791398Stmm if ((error = bus_dmamem_alloc(sc->sc_cdmatag, 198170273Syongari (void **)&sc->sc_control_data, 199170273Syongari BUS_DMA_WAITOK | BUS_DMA_COHERENT | BUS_DMA_ZERO, 200170273Syongari &sc->sc_cddmamap))) { 201174987Smarius device_printf(sc->sc_dev, 202174987Smarius "unable to allocate control data, error = %d\n", error); 203108832Stmm goto fail_ctag; 20491398Stmm } 20591398Stmm 20691398Stmm sc->sc_cddma = 0; 20791398Stmm if ((error = bus_dmamap_load(sc->sc_cdmatag, sc->sc_cddmamap, 20891398Stmm sc->sc_control_data, sizeof(struct gem_control_data), 20991398Stmm gem_cddma_callback, sc, 0)) != 0 || sc->sc_cddma == 0) { 210174987Smarius device_printf(sc->sc_dev, 211174987Smarius "unable to load control data DMA map, error = %d\n", 212174987Smarius error); 213108832Stmm goto fail_cmem; 21491398Stmm } 21591398Stmm 21691398Stmm /* 21791398Stmm * Initialize the transmit job descriptors. 21891398Stmm */ 21991398Stmm STAILQ_INIT(&sc->sc_txfreeq); 22091398Stmm STAILQ_INIT(&sc->sc_txdirtyq); 22191398Stmm 22291398Stmm /* 22391398Stmm * Create the transmit buffer DMA maps. 22491398Stmm */ 22591398Stmm error = ENOMEM; 22691398Stmm for (i = 0; i < GEM_TXQUEUELEN; i++) { 22791398Stmm txs = &sc->sc_txsoft[i]; 22891398Stmm txs->txs_mbuf = NULL; 22991398Stmm txs->txs_ndescs = 0; 230108832Stmm if ((error = bus_dmamap_create(sc->sc_tdmatag, 0, 23191398Stmm &txs->txs_dmamap)) != 0) { 232174987Smarius device_printf(sc->sc_dev, 233174987Smarius "unable to create TX DMA map %d, error = %d\n", 234174987Smarius i, error); 235108832Stmm goto fail_txd; 23691398Stmm } 23791398Stmm STAILQ_INSERT_TAIL(&sc->sc_txfreeq, txs, txs_q); 23891398Stmm } 23991398Stmm 24091398Stmm /* 24191398Stmm * Create the receive buffer DMA maps. 24291398Stmm */ 24391398Stmm for (i = 0; i < GEM_NRXDESC; i++) { 244108832Stmm if ((error = bus_dmamap_create(sc->sc_rdmatag, 0, 24591398Stmm &sc->sc_rxsoft[i].rxs_dmamap)) != 0) { 246174987Smarius device_printf(sc->sc_dev, 247174987Smarius "unable to create RX DMA map %d, error = %d\n", 248174987Smarius i, error); 249108832Stmm goto fail_rxd; 25091398Stmm } 25191398Stmm sc->sc_rxsoft[i].rxs_mbuf = NULL; 25291398Stmm } 25391398Stmm 254172334Smarius /* Bad things will happen when touching this register on ERI. */ 255172334Smarius if (sc->sc_variant != GEM_SUN_ERI) 256172334Smarius bus_write_4(sc->sc_res[0], GEM_MII_DATAPATH_MODE, 257172334Smarius GEM_MII_DATAPATH_MII); 258172334Smarius 25991398Stmm gem_mifinit(sc); 26091398Stmm 261172334Smarius /* 262172334Smarius * Look for an external PHY. 263172334Smarius */ 264172334Smarius error = ENXIO; 265172334Smarius v = bus_read_4(sc->sc_res[0], GEM_MIF_CONFIG); 266172334Smarius if ((v & GEM_MIF_CONFIG_MDI1) != 0) { 267172334Smarius v |= GEM_MIF_CONFIG_PHY_SEL; 268172334Smarius bus_write_4(sc->sc_res[0], GEM_MIF_CONFIG, v); 269172334Smarius switch (sc->sc_variant) { 270172334Smarius case GEM_SUN_ERI: 271172334Smarius sc->sc_phyad = GEM_PHYAD_EXTERNAL; 272172334Smarius break; 273172334Smarius default: 274172334Smarius sc->sc_phyad = -1; 275172334Smarius break; 276172334Smarius } 277172334Smarius error = mii_phy_probe(sc->sc_dev, &sc->sc_miibus, 278172334Smarius gem_mediachange, gem_mediastatus); 279172334Smarius } 280172334Smarius 281172334Smarius /* 282172334Smarius * Fall back on an internal PHY if no external PHY was found. 283172334Smarius */ 284172334Smarius if (error != 0 && (v & GEM_MIF_CONFIG_MDI0) != 0) { 285172334Smarius v &= ~GEM_MIF_CONFIG_PHY_SEL; 286172334Smarius bus_write_4(sc->sc_res[0], GEM_MIF_CONFIG, v); 287172334Smarius switch (sc->sc_variant) { 288172334Smarius case GEM_SUN_ERI: 289172334Smarius case GEM_APPLE_K2_GMAC: 290172334Smarius sc->sc_phyad = GEM_PHYAD_INTERNAL; 291172334Smarius break; 292172334Smarius case GEM_APPLE_GMAC: 293172334Smarius sc->sc_phyad = GEM_PHYAD_EXTERNAL; 294172334Smarius break; 295172334Smarius default: 296172334Smarius sc->sc_phyad = -1; 297172334Smarius break; 298172334Smarius } 299172334Smarius error = mii_phy_probe(sc->sc_dev, &sc->sc_miibus, 300172334Smarius gem_mediachange, gem_mediastatus); 301172334Smarius } 302172334Smarius 303172334Smarius /* 304172334Smarius * Try the external PCS SERDES if we didn't find any PHYs. 305172334Smarius */ 306172334Smarius if (error != 0 && sc->sc_variant == GEM_SUN_GEM) { 307172334Smarius bus_write_4(sc->sc_res[0], GEM_MII_DATAPATH_MODE, 308172334Smarius GEM_MII_DATAPATH_SERDES); 309172334Smarius bus_write_4(sc->sc_res[0], GEM_MII_SLINK_CONTROL, 310172334Smarius GEM_MII_SLINK_LOOPBACK | GEM_MII_SLINK_EN_SYNC_D); 311172334Smarius bus_write_4(sc->sc_res[0], GEM_MII_CONFIG, 312172334Smarius GEM_MII_CONFIG_ENABLE); 313172334Smarius sc->sc_flags |= GEM_SERDES; 314172334Smarius sc->sc_phyad = GEM_PHYAD_EXTERNAL; 315172334Smarius error = mii_phy_probe(sc->sc_dev, &sc->sc_miibus, 316172334Smarius gem_mediachange, gem_mediastatus); 317172334Smarius } 318172334Smarius 319172334Smarius if (error != 0) { 320172334Smarius device_printf(sc->sc_dev, "PHY probe failed: %d\n", error); 321108832Stmm goto fail_rxd; 32291398Stmm } 32391398Stmm sc->sc_mii = device_get_softc(sc->sc_miibus); 32491398Stmm 32591398Stmm /* 32691398Stmm * From this point forward, the attachment cannot fail. A failure 32791398Stmm * before this point releases all resources that may have been 32891398Stmm * allocated. 32991398Stmm */ 33091398Stmm 33199726Sbenno /* Get RX FIFO size */ 33299726Sbenno sc->sc_rxfifosize = 64 * 333169269Sphk bus_read_4(sc->sc_res[0], GEM_RX_FIFO_SIZE); 33499726Sbenno 33599726Sbenno /* Get TX FIFO size */ 336169269Sphk v = bus_read_4(sc->sc_res[0], GEM_TX_FIFO_SIZE); 337128588Stmm device_printf(sc->sc_dev, "%ukB RX FIFO, %ukB TX FIFO\n", 338128588Stmm sc->sc_rxfifosize / 1024, v / 16); 33999726Sbenno 340170273Syongari sc->sc_csum_features = GEM_CSUM_FEATURES; 34191398Stmm /* Initialize ifnet structure. */ 34291398Stmm ifp->if_softc = sc; 343121816Sbrooks if_initname(ifp, device_get_name(sc->sc_dev), 344121816Sbrooks device_get_unit(sc->sc_dev)); 345148369Smarius ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 34691398Stmm ifp->if_start = gem_start; 34791398Stmm ifp->if_ioctl = gem_ioctl; 34891398Stmm ifp->if_init = gem_init; 349170273Syongari IFQ_SET_MAXLEN(&ifp->if_snd, GEM_TXQUEUELEN); 350170273Syongari ifp->if_snd.ifq_drv_maxlen = GEM_TXQUEUELEN; 351170273Syongari IFQ_SET_READY(&ifp->if_snd); 35291398Stmm 35391398Stmm /* Attach the interface. */ 354147256Sbrooks ether_ifattach(ifp, sc->sc_enaddr); 35591398Stmm 35691398Stmm /* 357170273Syongari * Tell the upper layer(s) we support long frames/checksum offloads. 358149552Smarius */ 359149552Smarius ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header); 360170273Syongari ifp->if_capabilities |= IFCAP_VLAN_MTU | IFCAP_HWCSUM; 361170273Syongari ifp->if_hwassist |= sc->sc_csum_features; 362170273Syongari ifp->if_capenable |= IFCAP_VLAN_MTU | IFCAP_HWCSUM; 363149552Smarius 36491398Stmm return (0); 36591398Stmm 36691398Stmm /* 36791398Stmm * Free any resources we've allocated during the failed attach 36891398Stmm * attempt. Do this in reverse order and fall through. 36991398Stmm */ 370174987Smarius fail_rxd: 371174987Smarius for (i = 0; i < GEM_NRXDESC; i++) 37291398Stmm if (sc->sc_rxsoft[i].rxs_dmamap != NULL) 373108832Stmm bus_dmamap_destroy(sc->sc_rdmatag, 37491398Stmm sc->sc_rxsoft[i].rxs_dmamap); 375174987Smarius fail_txd: 376174987Smarius for (i = 0; i < GEM_TXQUEUELEN; i++) 37791398Stmm if (sc->sc_txsoft[i].txs_dmamap != NULL) 378108832Stmm bus_dmamap_destroy(sc->sc_tdmatag, 37991398Stmm sc->sc_txsoft[i].txs_dmamap); 380108832Stmm bus_dmamap_unload(sc->sc_cdmatag, sc->sc_cddmamap); 381174987Smarius fail_cmem: 38291398Stmm bus_dmamem_free(sc->sc_cdmatag, sc->sc_control_data, 38391398Stmm sc->sc_cddmamap); 384174987Smarius fail_ctag: 38591398Stmm bus_dma_tag_destroy(sc->sc_cdmatag); 386174987Smarius fail_ttag: 387108832Stmm bus_dma_tag_destroy(sc->sc_tdmatag); 388174987Smarius fail_rtag: 389108832Stmm bus_dma_tag_destroy(sc->sc_rdmatag); 390174987Smarius fail_ptag: 39191398Stmm bus_dma_tag_destroy(sc->sc_pdmatag); 392174987Smarius fail_ifnet: 393147256Sbrooks if_free(ifp); 39491398Stmm return (error); 39591398Stmm} 39691398Stmm 397108964Stmmvoid 398174987Smariusgem_detach(struct gem_softc *sc) 399108964Stmm{ 400147256Sbrooks struct ifnet *ifp = sc->sc_ifp; 401108964Stmm int i; 402108964Stmm 403148369Smarius GEM_LOCK(sc); 404147317Sbrooks gem_stop(ifp, 1); 405148369Smarius GEM_UNLOCK(sc); 406150285Smarius callout_drain(&sc->sc_tick_ch); 407150285Smarius#ifdef GEM_RINT_TIMEOUT 408150285Smarius callout_drain(&sc->sc_rx_ch); 409150285Smarius#endif 410108964Stmm ether_ifdetach(ifp); 411147256Sbrooks if_free(ifp); 412108964Stmm device_delete_child(sc->sc_dev, sc->sc_miibus); 413108964Stmm 414174987Smarius for (i = 0; i < GEM_NRXDESC; i++) 415108964Stmm if (sc->sc_rxsoft[i].rxs_dmamap != NULL) 416108964Stmm bus_dmamap_destroy(sc->sc_rdmatag, 417108964Stmm sc->sc_rxsoft[i].rxs_dmamap); 418174987Smarius for (i = 0; i < GEM_TXQUEUELEN; i++) 419108964Stmm if (sc->sc_txsoft[i].txs_dmamap != NULL) 420108964Stmm bus_dmamap_destroy(sc->sc_tdmatag, 421108964Stmm sc->sc_txsoft[i].txs_dmamap); 422109648Stmm GEM_CDSYNC(sc, BUS_DMASYNC_POSTREAD); 423109648Stmm GEM_CDSYNC(sc, 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_txcksum(struct gem_softc *sc, struct mbuf *m, uint64_t *cflags) 461170273Syongari{ 462174987Smarius char *p; 463174987Smarius struct ip *ip; 464172607Syongari struct mbuf *m0; 465170273Syongari uint64_t offset, offset2; 466170273Syongari 467172607Syongari m0 = m; 468170273Syongari offset = sizeof(struct ip) + ETHER_HDR_LEN; 469170273Syongari for(; m && m->m_len == 0; m = m->m_next) 470170273Syongari ; 471170273Syongari if (m == NULL || m->m_len < ETHER_HDR_LEN) { 472170273Syongari device_printf(sc->sc_dev, "%s: m_len < ETHER_HDR_LEN\n", 473170273Syongari __func__); 474174987Smarius /* Checksum will be corrupted. */ 475172607Syongari m = m0; 476170273Syongari goto sendit; 477170273Syongari } 478170273Syongari if (m->m_len < ETHER_HDR_LEN + sizeof(uint32_t)) { 479170273Syongari if (m->m_len != ETHER_HDR_LEN) { 480170273Syongari device_printf(sc->sc_dev, 481170273Syongari "%s: m_len != ETHER_HDR_LEN\n", __func__); 482174987Smarius /* Checksum will be corrupted. */ 483172607Syongari m = m0; 484170273Syongari goto sendit; 485170273Syongari } 486170273Syongari for(m = m->m_next; m && m->m_len == 0; m = m->m_next) 487170273Syongari ; 488170273Syongari if (m == NULL) { 489174987Smarius /* Checksum will be corrupted. */ 490172607Syongari m = m0; 491170273Syongari goto sendit; 492170273Syongari } 493170273Syongari ip = mtod(m, struct ip *); 494170273Syongari } else { 495170273Syongari p = mtod(m, uint8_t *); 496170273Syongari p += ETHER_HDR_LEN; 497170273Syongari ip = (struct ip *)p; 498170273Syongari } 499170273Syongari offset = (ip->ip_hl << 2) + ETHER_HDR_LEN; 500170273Syongari 501174987Smarius sendit: 502170273Syongari offset2 = m->m_pkthdr.csum_data; 503170273Syongari *cflags = offset << GEM_TD_CXSUM_STARTSHFT; 504170273Syongari *cflags |= ((offset + offset2) << GEM_TD_CXSUM_STUFFSHFT); 505170273Syongari *cflags |= GEM_TD_CXSUM_ENABLE; 506170273Syongari} 507170273Syongari 508170273Syongaristatic __inline void 509170273Syongarigem_rxcksum(struct mbuf *m, uint64_t flags) 510170273Syongari{ 511170273Syongari struct ether_header *eh; 512170273Syongari struct ip *ip; 513170273Syongari struct udphdr *uh; 514174987Smarius uint16_t *opts; 515170273Syongari int32_t hlen, len, pktlen; 516170273Syongari uint32_t temp32; 517174987Smarius uint16_t cksum; 518170273Syongari 519170273Syongari pktlen = m->m_pkthdr.len; 520170273Syongari if (pktlen < sizeof(struct ether_header) + sizeof(struct ip)) 521170273Syongari return; 522170273Syongari eh = mtod(m, struct ether_header *); 523170273Syongari if (eh->ether_type != htons(ETHERTYPE_IP)) 524170273Syongari return; 525170273Syongari ip = (struct ip *)(eh + 1); 526170273Syongari if (ip->ip_v != IPVERSION) 527170273Syongari return; 528170273Syongari 529170273Syongari hlen = ip->ip_hl << 2; 530170273Syongari pktlen -= sizeof(struct ether_header); 531170273Syongari if (hlen < sizeof(struct ip)) 532170273Syongari return; 533170273Syongari if (ntohs(ip->ip_len) < hlen) 534170273Syongari return; 535170273Syongari if (ntohs(ip->ip_len) != pktlen) 536170273Syongari return; 537170273Syongari if (ip->ip_off & htons(IP_MF | IP_OFFMASK)) 538174987Smarius return; /* Cannot handle fragmented packet. */ 539170273Syongari 540170273Syongari switch (ip->ip_p) { 541170273Syongari case IPPROTO_TCP: 542170273Syongari if (pktlen < (hlen + sizeof(struct tcphdr))) 543170273Syongari return; 544170273Syongari break; 545170273Syongari case IPPROTO_UDP: 546170273Syongari if (pktlen < (hlen + sizeof(struct udphdr))) 547170273Syongari return; 548170273Syongari uh = (struct udphdr *)((uint8_t *)ip + hlen); 549170273Syongari if (uh->uh_sum == 0) 550170273Syongari return; /* no checksum */ 551170273Syongari break; 552170273Syongari default: 553170273Syongari return; 554170273Syongari } 555170273Syongari 556170273Syongari cksum = ~(flags & GEM_RD_CHECKSUM); 557170273Syongari /* checksum fixup for IP options */ 558170273Syongari len = hlen - sizeof(struct ip); 559170273Syongari if (len > 0) { 560170273Syongari opts = (uint16_t *)(ip + 1); 561170273Syongari for (; len > 0; len -= sizeof(uint16_t), opts++) { 562170273Syongari temp32 = cksum - *opts; 563170273Syongari temp32 = (temp32 >> 16) + (temp32 & 65535); 564170273Syongari cksum = temp32 & 65535; 565170273Syongari } 566170273Syongari } 567170273Syongari m->m_pkthdr.csum_flags |= CSUM_DATA_VALID; 568170273Syongari m->m_pkthdr.csum_data = cksum; 569170273Syongari} 570170273Syongari 57191398Stmmstatic void 572174987Smariusgem_cddma_callback(void *xsc, bus_dma_segment_t *segs, int nsegs, int error) 57391398Stmm{ 574174987Smarius struct gem_softc *sc = xsc; 57591398Stmm 57691398Stmm if (error != 0) 57791398Stmm return; 578174987Smarius if (nsegs != 1) 579172334Smarius panic("%s: bad control buffer segment count", __func__); 58091398Stmm sc->sc_cddma = segs[0].ds_addr; 58191398Stmm} 58291398Stmm 58391398Stmmstatic void 584174987Smariusgem_tick(void *arg) 58591398Stmm{ 586170273Syongari struct gem_softc *sc = arg; 587170273Syongari struct ifnet *ifp; 58891398Stmm 589170273Syongari GEM_LOCK_ASSERT(sc, MA_OWNED); 590170273Syongari 591170273Syongari ifp = sc->sc_ifp; 592108832Stmm /* 593174987Smarius * Unload collision counters. 594108832Stmm */ 595170273Syongari ifp->if_collisions += 596170273Syongari bus_read_4(sc->sc_res[0], GEM_MAC_NORM_COLL_CNT) + 597170273Syongari bus_read_4(sc->sc_res[0], GEM_MAC_FIRST_COLL_CNT) + 598170273Syongari bus_read_4(sc->sc_res[0], GEM_MAC_EXCESS_COLL_CNT) + 599170273Syongari bus_read_4(sc->sc_res[0], GEM_MAC_LATE_COLL_CNT); 60091398Stmm 60191398Stmm /* 602170273Syongari * then clear the hardware counters. 60391398Stmm */ 604170273Syongari bus_write_4(sc->sc_res[0], GEM_MAC_NORM_COLL_CNT, 0); 605170273Syongari bus_write_4(sc->sc_res[0], GEM_MAC_FIRST_COLL_CNT, 0); 606170273Syongari bus_write_4(sc->sc_res[0], GEM_MAC_EXCESS_COLL_CNT, 0); 607170273Syongari bus_write_4(sc->sc_res[0], GEM_MAC_LATE_COLL_CNT, 0); 608108832Stmm 60991398Stmm mii_tick(sc->sc_mii); 61091398Stmm 611164931Smarius if (gem_watchdog(sc) == EJUSTRETURN) 612164931Smarius return; 613164931Smarius 61491398Stmm callout_reset(&sc->sc_tick_ch, hz, gem_tick, sc); 61591398Stmm} 61691398Stmm 61791398Stmmstatic int 618174987Smariusgem_bitwait(struct gem_softc *sc, bus_addr_t r, uint32_t clr, uint32_t set) 61991398Stmm{ 62091398Stmm int i; 621174987Smarius uint32_t reg; 62291398Stmm 62391398Stmm for (i = TRIES; i--; DELAY(100)) { 624169269Sphk reg = bus_read_4(sc->sc_res[0], r); 625170847Smarius if ((reg & clr) == 0 && (reg & set) == set) 62691398Stmm return (1); 62791398Stmm } 62891398Stmm return (0); 62991398Stmm} 63091398Stmm 631172334Smariusstatic void 63291398Stmmgem_reset(sc) 63391398Stmm struct gem_softc *sc; 63491398Stmm{ 63591398Stmm 636115030Stmm#ifdef GEM_DEBUG 637170273Syongari CTR2(KTR_GEM, "%s: %s", device_get_name(sc->sc_dev), __func__); 638115030Stmm#endif 63991398Stmm gem_reset_rx(sc); 64091398Stmm gem_reset_tx(sc); 64191398Stmm 642174987Smarius /* Do a full reset. */ 643169269Sphk bus_write_4(sc->sc_res[0], GEM_RESET, GEM_RESET_RX | GEM_RESET_TX); 644172334Smarius bus_barrier(sc->sc_res[0], GEM_RESET, 4, BUS_SPACE_BARRIER_WRITE); 64591398Stmm if (!gem_bitwait(sc, GEM_RESET, GEM_RESET_RX | GEM_RESET_TX, 0)) 64691398Stmm device_printf(sc->sc_dev, "cannot reset device\n"); 64791398Stmm} 64891398Stmm 64991398Stmmstatic void 650174987Smariusgem_rxdrain(struct gem_softc *sc) 65191398Stmm{ 65291398Stmm struct gem_rxsoft *rxs; 65391398Stmm int i; 65491398Stmm 65591398Stmm for (i = 0; i < GEM_NRXDESC; i++) { 65691398Stmm rxs = &sc->sc_rxsoft[i]; 65791398Stmm if (rxs->rxs_mbuf != NULL) { 658109648Stmm bus_dmamap_sync(sc->sc_rdmatag, rxs->rxs_dmamap, 659109648Stmm BUS_DMASYNC_POSTREAD); 660108832Stmm bus_dmamap_unload(sc->sc_rdmatag, rxs->rxs_dmamap); 66191398Stmm m_freem(rxs->rxs_mbuf); 66291398Stmm rxs->rxs_mbuf = NULL; 66391398Stmm } 66491398Stmm } 66591398Stmm} 66691398Stmm 66791398Stmmstatic void 668174987Smariusgem_stop(struct ifnet *ifp, int disable) 66991398Stmm{ 670174987Smarius struct gem_softc *sc = ifp->if_softc; 67191398Stmm struct gem_txsoft *txs; 67291398Stmm 673115030Stmm#ifdef GEM_DEBUG 674170273Syongari CTR2(KTR_GEM, "%s: %s", device_get_name(sc->sc_dev), __func__); 675115030Stmm#endif 67691398Stmm 67791398Stmm callout_stop(&sc->sc_tick_ch); 678150285Smarius#ifdef GEM_RINT_TIMEOUT 679150285Smarius callout_stop(&sc->sc_rx_ch); 680172334Smarius#endif 68191398Stmm 682174987Smarius /* XXX should we reset these instead? */ 68391398Stmm gem_disable_tx(sc); 68491398Stmm gem_disable_rx(sc); 68591398Stmm 68691398Stmm /* 68791398Stmm * Release any queued transmit buffers. 68891398Stmm */ 68991398Stmm while ((txs = STAILQ_FIRST(&sc->sc_txdirtyq)) != NULL) { 69091398Stmm STAILQ_REMOVE_HEAD(&sc->sc_txdirtyq, txs_q); 69191398Stmm if (txs->txs_ndescs != 0) { 692109648Stmm bus_dmamap_sync(sc->sc_tdmatag, txs->txs_dmamap, 693109648Stmm BUS_DMASYNC_POSTWRITE); 694108832Stmm bus_dmamap_unload(sc->sc_tdmatag, txs->txs_dmamap); 69591398Stmm if (txs->txs_mbuf != NULL) { 69691398Stmm m_freem(txs->txs_mbuf); 69791398Stmm txs->txs_mbuf = NULL; 69891398Stmm } 69991398Stmm } 70091398Stmm STAILQ_INSERT_TAIL(&sc->sc_txfreeq, txs, txs_q); 70191398Stmm } 70291398Stmm 70391398Stmm if (disable) 70491398Stmm gem_rxdrain(sc); 70591398Stmm 70691398Stmm /* 70791398Stmm * Mark the interface down and cancel the watchdog timer. 70891398Stmm */ 709148887Srwatson ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); 710172334Smarius sc->sc_flags &= ~GEM_LINK; 711164931Smarius sc->sc_wdog_timer = 0; 71291398Stmm} 71391398Stmm 714172334Smariusstatic int 715174987Smariusgem_reset_rx(struct gem_softc *sc) 71691398Stmm{ 71791398Stmm 71891398Stmm /* 71991398Stmm * Resetting while DMA is in progress can cause a bus hang, so we 72091398Stmm * disable DMA first. 72191398Stmm */ 72291398Stmm gem_disable_rx(sc); 723169269Sphk bus_write_4(sc->sc_res[0], GEM_RX_CONFIG, 0); 724172334Smarius bus_barrier(sc->sc_res[0], GEM_RX_CONFIG, 4, BUS_SPACE_BARRIER_WRITE); 725172334Smarius if (!gem_bitwait(sc, GEM_RX_CONFIG, GEM_RX_CONFIG_RXDMA_EN, 0)) 726172334Smarius device_printf(sc->sc_dev, "cannot disable RX DMA\n"); 72791398Stmm 72891398Stmm /* Finally, reset the ERX */ 729169269Sphk bus_write_4(sc->sc_res[0], GEM_RESET, GEM_RESET_RX); 730172334Smarius bus_barrier(sc->sc_res[0], GEM_RESET, 4, BUS_SPACE_BARRIER_WRITE); 731172334Smarius if (!gem_bitwait(sc, GEM_RESET, GEM_RESET_RX | GEM_RESET_TX, 0)) { 73291398Stmm device_printf(sc->sc_dev, "cannot reset receiver\n"); 73391398Stmm return (1); 73491398Stmm } 73591398Stmm return (0); 73691398Stmm} 73791398Stmm 738172334Smarius/* 739172334Smarius * Reset the receiver DMA engine. 740172334Smarius * 741172334Smarius * Intended to be used in case of GEM_INTR_RX_TAG_ERR, GEM_MAC_RX_OVERFLOW 742172334Smarius * etc in order to reset the receiver DMA engine only and not do a full 743172334Smarius * reset which amongst others also downs the link and clears the FIFOs. 744172334Smarius */ 745172334Smariusstatic void 746172334Smariusgem_reset_rxdma(struct gem_softc *sc) 747172334Smarius{ 748172334Smarius int i; 74991398Stmm 750172334Smarius if (gem_reset_rx(sc) != 0) 751172334Smarius return (gem_init_locked(sc)); 752172334Smarius for (i = 0; i < GEM_NRXDESC; i++) 753172334Smarius if (sc->sc_rxsoft[i].rxs_mbuf != NULL) 754172334Smarius GEM_UPDATE_RXDESC(sc, i); 755172334Smarius sc->sc_rxptr = 0; 756172334Smarius GEM_CDSYNC(sc, BUS_DMASYNC_PREWRITE); 757172334Smarius GEM_CDSYNC(sc, BUS_DMASYNC_PREREAD); 758172334Smarius 759172334Smarius /* NOTE: we use only 32-bit DMA addresses here. */ 760172334Smarius bus_write_4(sc->sc_res[0], GEM_RX_RING_PTR_HI, 0); 761172334Smarius bus_write_4(sc->sc_res[0], GEM_RX_RING_PTR_LO, GEM_CDRXADDR(sc, 0)); 762172334Smarius bus_write_4(sc->sc_res[0], GEM_RX_KICK, GEM_NRXDESC - 4); 763172334Smarius bus_write_4(sc->sc_res[0], GEM_RX_CONFIG, 764174987Smarius gem_ringsize(GEM_NRXDESC /* XXX */) | 765172334Smarius ((ETHER_HDR_LEN + sizeof(struct ip)) << 766172334Smarius GEM_RX_CONFIG_CXM_START_SHFT) | 767172334Smarius (GEM_THRSH_1024 << GEM_RX_CONFIG_FIFO_THRS_SHIFT) | 768172334Smarius (2 << GEM_RX_CONFIG_FBOFF_SHFT)); 769172334Smarius bus_write_4(sc->sc_res[0], GEM_RX_BLANKING, 770172334Smarius (6 << GEM_RX_BLANKING_TIME_SHIFT) | 6); 771172334Smarius bus_write_4(sc->sc_res[0], GEM_RX_PAUSE_THRESH, 772174987Smarius (3 * sc->sc_rxfifosize / 256) | 773174987Smarius ((sc->sc_rxfifosize / 256) << 12)); 774172334Smarius bus_write_4(sc->sc_res[0], GEM_RX_CONFIG, 775174987Smarius bus_read_4(sc->sc_res[0], GEM_RX_CONFIG) | 776174987Smarius GEM_RX_CONFIG_RXDMA_EN); 777172334Smarius bus_write_4(sc->sc_res[0], GEM_MAC_RX_MASK, 778172334Smarius GEM_MAC_RX_DONE | GEM_MAC_RX_FRAME_CNT); 779172334Smarius bus_write_4(sc->sc_res[0], GEM_MAC_RX_CONFIG, 780174987Smarius bus_read_4(sc->sc_res[0], GEM_MAC_RX_CONFIG) | 781174987Smarius GEM_MAC_RX_ENABLE); 782172334Smarius} 783172334Smarius 78491398Stmmstatic int 785174987Smariusgem_reset_tx(struct gem_softc *sc) 78691398Stmm{ 78791398Stmm 78891398Stmm /* 78991398Stmm * Resetting while DMA is in progress can cause a bus hang, so we 79091398Stmm * disable DMA first. 79191398Stmm */ 79291398Stmm gem_disable_tx(sc); 793169269Sphk bus_write_4(sc->sc_res[0], GEM_TX_CONFIG, 0); 794172334Smarius bus_barrier(sc->sc_res[0], GEM_TX_CONFIG, 4, BUS_SPACE_BARRIER_WRITE); 795172334Smarius if (!gem_bitwait(sc, GEM_TX_CONFIG, GEM_TX_CONFIG_TXDMA_EN, 0)) 796172334Smarius device_printf(sc->sc_dev, "cannot disable TX DMA\n"); 79791398Stmm 79891398Stmm /* Finally, reset the ETX */ 799169269Sphk bus_write_4(sc->sc_res[0], GEM_RESET, GEM_RESET_TX); 800172334Smarius bus_barrier(sc->sc_res[0], GEM_RESET, 4, BUS_SPACE_BARRIER_WRITE); 801172334Smarius if (!gem_bitwait(sc, GEM_RESET, GEM_RESET_RX | GEM_RESET_TX, 0)) { 802172334Smarius device_printf(sc->sc_dev, "cannot reset transmitter\n"); 80391398Stmm return (1); 80491398Stmm } 80591398Stmm return (0); 80691398Stmm} 80791398Stmm 80891398Stmmstatic int 809174987Smariusgem_disable_rx(struct gem_softc *sc) 81091398Stmm{ 811174987Smarius uint32_t cfg; 81291398Stmm 813169269Sphk cfg = bus_read_4(sc->sc_res[0], GEM_MAC_RX_CONFIG); 81491398Stmm cfg &= ~GEM_MAC_RX_ENABLE; 815169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_RX_CONFIG, cfg); 816172334Smarius bus_barrier(sc->sc_res[0], GEM_MAC_RX_CONFIG, 4, 817174987Smarius BUS_SPACE_BARRIER_WRITE); 81891398Stmm return (gem_bitwait(sc, GEM_MAC_RX_CONFIG, GEM_MAC_RX_ENABLE, 0)); 81991398Stmm} 82091398Stmm 82191398Stmm/* 82291398Stmm * disable transmitter. 82391398Stmm */ 82491398Stmmstatic int 825174987Smariusgem_disable_tx(struct gem_softc *sc) 82691398Stmm{ 827174987Smarius uint32_t cfg; 82891398Stmm 829169269Sphk cfg = bus_read_4(sc->sc_res[0], GEM_MAC_TX_CONFIG); 83091398Stmm cfg &= ~GEM_MAC_TX_ENABLE; 831169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_TX_CONFIG, cfg); 832172334Smarius bus_barrier(sc->sc_res[0], GEM_MAC_TX_CONFIG, 4, 833172334Smarius BUS_SPACE_BARRIER_WRITE); 83491398Stmm return (gem_bitwait(sc, GEM_MAC_TX_CONFIG, GEM_MAC_TX_ENABLE, 0)); 83591398Stmm} 83691398Stmm 83791398Stmmstatic int 83891398Stmmgem_meminit(sc) 83991398Stmm struct gem_softc *sc; 84091398Stmm{ 84191398Stmm struct gem_rxsoft *rxs; 842174987Smarius int error, i; 84391398Stmm 84491398Stmm /* 84591398Stmm * Initialize the transmit descriptor ring. 84691398Stmm */ 84791398Stmm for (i = 0; i < GEM_NTXDESC; i++) { 84891398Stmm sc->sc_txdescs[i].gd_flags = 0; 84991398Stmm sc->sc_txdescs[i].gd_addr = 0; 85091398Stmm } 851108832Stmm sc->sc_txfree = GEM_MAXTXFREE; 85291398Stmm sc->sc_txnext = 0; 85399726Sbenno sc->sc_txwin = 0; 85491398Stmm 85591398Stmm /* 85691398Stmm * Initialize the receive descriptor and receive job 85791398Stmm * descriptor rings. 85891398Stmm */ 85991398Stmm for (i = 0; i < GEM_NRXDESC; i++) { 86091398Stmm rxs = &sc->sc_rxsoft[i]; 86191398Stmm if (rxs->rxs_mbuf == NULL) { 86291398Stmm if ((error = gem_add_rxbuf(sc, i)) != 0) { 863174987Smarius device_printf(sc->sc_dev, 864174987Smarius "unable to allocate or map RX buffer %d, " 865174987Smarius "error = %d\n", i, error); 86691398Stmm /* 867174987Smarius * XXX we should attempt to run with fewer 868174987Smarius * receive buffers instead of just failing. 86991398Stmm */ 87091398Stmm gem_rxdrain(sc); 87191398Stmm return (1); 87291398Stmm } 87391398Stmm } else 87491398Stmm GEM_INIT_RXDESC(sc, i); 87591398Stmm } 87691398Stmm sc->sc_rxptr = 0; 877109648Stmm GEM_CDSYNC(sc, BUS_DMASYNC_PREWRITE); 878109648Stmm GEM_CDSYNC(sc, BUS_DMASYNC_PREREAD); 87991398Stmm 88091398Stmm return (0); 88191398Stmm} 88291398Stmm 883172334Smariusstatic u_int 884174987Smariusgem_ringsize(u_int sz) 88591398Stmm{ 88691398Stmm 88791398Stmm switch (sz) { 88891398Stmm case 32: 889172334Smarius return (GEM_RING_SZ_32); 89091398Stmm case 64: 891172334Smarius return (GEM_RING_SZ_64); 89291398Stmm case 128: 893172334Smarius return (GEM_RING_SZ_128); 89491398Stmm case 256: 895172334Smarius return (GEM_RING_SZ_256); 89691398Stmm case 512: 897172334Smarius return (GEM_RING_SZ_512); 89891398Stmm case 1024: 899172334Smarius return (GEM_RING_SZ_1024); 90091398Stmm case 2048: 901172334Smarius return (GEM_RING_SZ_2048); 90291398Stmm case 4096: 903172334Smarius return (GEM_RING_SZ_4096); 90491398Stmm case 8192: 905172334Smarius return (GEM_RING_SZ_8192); 90691398Stmm default: 907172334Smarius printf("%s: invalid ring size %d\n", __func__, sz); 908172334Smarius return (GEM_RING_SZ_32); 90991398Stmm } 91091398Stmm} 91191398Stmm 912148369Smariusstatic void 913174987Smariusgem_init(void *xsc) 914148369Smarius{ 915174987Smarius struct gem_softc *sc = xsc; 916148369Smarius 917148369Smarius GEM_LOCK(sc); 918148369Smarius gem_init_locked(sc); 919148369Smarius GEM_UNLOCK(sc); 920148369Smarius} 921148369Smarius 92291398Stmm/* 92391398Stmm * Initialization of interface; set up initialization block 92491398Stmm * and transmit/receive descriptor rings. 92591398Stmm */ 92691398Stmmstatic void 927174987Smariusgem_init_locked(struct gem_softc *sc) 92891398Stmm{ 929147256Sbrooks struct ifnet *ifp = sc->sc_ifp; 930174987Smarius uint32_t v; 93191398Stmm 932148369Smarius GEM_LOCK_ASSERT(sc, MA_OWNED); 93391398Stmm 934115030Stmm#ifdef GEM_DEBUG 935170273Syongari CTR2(KTR_GEM, "%s: %s: calling stop", device_get_name(sc->sc_dev), 936170273Syongari __func__); 937115030Stmm#endif 93891398Stmm /* 939174987Smarius * Initialization sequence. The numbered steps below correspond 94091398Stmm * to the sequence outlined in section 6.3.5.1 in the Ethernet 94191398Stmm * Channel Engine manual (part of the PCIO manual). 94291398Stmm * See also the STP2002-STQ document from Sun Microsystems. 94391398Stmm */ 94491398Stmm 945174987Smarius /* step 1 & 2. Reset the Ethernet Channel. */ 946147256Sbrooks gem_stop(sc->sc_ifp, 0); 94791398Stmm gem_reset(sc); 948115030Stmm#ifdef GEM_DEBUG 949170273Syongari CTR2(KTR_GEM, "%s: %s: restarting", device_get_name(sc->sc_dev), 950170273Syongari __func__); 951115030Stmm#endif 95291398Stmm 953174987Smarius /* Re-initialize the MIF. */ 95491398Stmm gem_mifinit(sc); 95591398Stmm 956174987Smarius /* step 3. Setup data structures in host memory. */ 957172334Smarius if (gem_meminit(sc) != 0) 958172334Smarius return; 95991398Stmm 960174987Smarius /* step 4. TX MAC registers & counters */ 96191398Stmm gem_init_regs(sc); 96291398Stmm 963174987Smarius /* step 5. RX MAC registers & counters */ 96491398Stmm gem_setladrf(sc); 96591398Stmm 966174987Smarius /* step 6 & 7. Program Descriptor Ring Base Addresses. */ 96791398Stmm /* NOTE: we use only 32-bit DMA addresses here. */ 968169269Sphk bus_write_4(sc->sc_res[0], GEM_TX_RING_PTR_HI, 0); 969169269Sphk bus_write_4(sc->sc_res[0], GEM_TX_RING_PTR_LO, GEM_CDTXADDR(sc, 0)); 97091398Stmm 971169269Sphk bus_write_4(sc->sc_res[0], GEM_RX_RING_PTR_HI, 0); 972169269Sphk bus_write_4(sc->sc_res[0], GEM_RX_RING_PTR_LO, GEM_CDRXADDR(sc, 0)); 973115030Stmm#ifdef GEM_DEBUG 974174987Smarius CTR3(KTR_GEM, "loading RX ring %lx, TX ring %lx, cddma %lx", 97591398Stmm GEM_CDRXADDR(sc, 0), GEM_CDTXADDR(sc, 0), sc->sc_cddma); 976115030Stmm#endif 97791398Stmm 978174987Smarius /* step 8. Global Configuration & Interrupt Mask */ 979169269Sphk bus_write_4(sc->sc_res[0], GEM_INTMASK, 980172334Smarius ~(GEM_INTR_TX_INTME | GEM_INTR_TX_EMPTY | GEM_INTR_RX_DONE | 981172334Smarius GEM_INTR_RX_NOBUF | GEM_INTR_RX_TAG_ERR | GEM_INTR_PERR | 982172334Smarius GEM_INTR_BERR 983172334Smarius#ifdef GEM_DEBUG 984172334Smarius | GEM_INTR_PCS | GEM_INTR_MIF 985172334Smarius#endif 986172334Smarius )); 987169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_RX_MASK, 988172334Smarius GEM_MAC_RX_DONE | GEM_MAC_RX_FRAME_CNT); 989172334Smarius bus_write_4(sc->sc_res[0], GEM_MAC_TX_MASK, 990172334Smarius GEM_MAC_TX_XMIT_DONE | GEM_MAC_TX_DEFER_EXP); 991172334Smarius#ifdef GEM_DEBUG 992172334Smarius bus_write_4(sc->sc_res[0], GEM_MAC_CONTROL_MASK, 993172334Smarius ~(GEM_MAC_PAUSED | GEM_MAC_PAUSE | GEM_MAC_RESUME)); 994172334Smarius#else 995172334Smarius bus_write_4(sc->sc_res[0], GEM_MAC_CONTROL_MASK, 996172334Smarius GEM_MAC_PAUSED | GEM_MAC_PAUSE | GEM_MAC_RESUME); 997172334Smarius#endif 99891398Stmm 999174987Smarius /* step 9. ETX Configuration: use mostly default values. */ 100091398Stmm 1001174987Smarius /* Enable DMA. */ 1002174987Smarius v = gem_ringsize(GEM_NTXDESC /* XXX */); 1003169269Sphk bus_write_4(sc->sc_res[0], GEM_TX_CONFIG, 1004174987Smarius v | GEM_TX_CONFIG_TXDMA_EN | 1005174987Smarius ((0x400 << 10) & GEM_TX_CONFIG_TXFIFO_TH)); 100691398Stmm 1007174987Smarius /* step 10. ERX Configuration */ 100891398Stmm 1009172334Smarius /* Encode Receive Descriptor ring size. */ 1010174987Smarius v = gem_ringsize(GEM_NRXDESC /* XXX */); 1011174987Smarius /* RX TCP/UDP checksum offset */ 1012170273Syongari v |= ((ETHER_HDR_LEN + sizeof(struct ip)) << 1013170273Syongari GEM_RX_CONFIG_CXM_START_SHFT); 101491398Stmm 1015174987Smarius /* Enable DMA. */ 1016169269Sphk bus_write_4(sc->sc_res[0], GEM_RX_CONFIG, 1017174987Smarius v | (GEM_THRSH_1024 << GEM_RX_CONFIG_FIFO_THRS_SHIFT) | 1018174987Smarius (2 << GEM_RX_CONFIG_FBOFF_SHFT) | GEM_RX_CONFIG_RXDMA_EN); 1019172334Smarius 1020172334Smarius bus_write_4(sc->sc_res[0], GEM_RX_BLANKING, 1021172334Smarius (6 << GEM_RX_BLANKING_TIME_SHIFT) | 6); 1022172334Smarius 102391398Stmm /* 102499726Sbenno * The following value is for an OFF Threshold of about 3/4 full 102599726Sbenno * and an ON Threshold of 1/4 full. 102691398Stmm */ 1027169269Sphk bus_write_4(sc->sc_res[0], GEM_RX_PAUSE_THRESH, 102899726Sbenno (3 * sc->sc_rxfifosize / 256) | 1029174987Smarius ((sc->sc_rxfifosize / 256) << 12)); 103091398Stmm 1031174987Smarius /* step 11. Configure Media. */ 103291398Stmm 1033174987Smarius /* step 12. RX_MAC Configuration Register */ 1034169269Sphk v = bus_read_4(sc->sc_res[0], GEM_MAC_RX_CONFIG); 1035172334Smarius v |= GEM_MAC_RX_STRIP_CRC; 1036172334Smarius bus_write_4(sc->sc_res[0], GEM_MAC_RX_CONFIG, 0); 1037172334Smarius bus_barrier(sc->sc_res[0], GEM_MAC_RX_CONFIG, 4, 1038172334Smarius BUS_SPACE_BARRIER_WRITE); 1039172334Smarius if (!gem_bitwait(sc, GEM_MAC_RX_CONFIG, GEM_MAC_RX_ENABLE, 0)) 1040172334Smarius device_printf(sc->sc_dev, "cannot disable RX MAC\n"); 1041169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_RX_CONFIG, v); 104291398Stmm 1043174987Smarius /* step 14. Issue Transmit Pending command. */ 104491398Stmm 1045174987Smarius /* step 15. Give the reciever a swift kick. */ 1046174987Smarius bus_write_4(sc->sc_res[0], GEM_RX_KICK, GEM_NRXDESC - 4); 104791398Stmm 1048172334Smarius ifp->if_drv_flags |= IFF_DRV_RUNNING; 1049172334Smarius ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 1050172334Smarius sc->sc_ifflags = ifp->if_flags; 1051172334Smarius 1052172334Smarius sc->sc_flags &= ~GEM_LINK; 1053172334Smarius mii_mediachg(sc->sc_mii); 1054172334Smarius 105591398Stmm /* Start the one second timer. */ 1056164931Smarius sc->sc_wdog_timer = 0; 105791398Stmm callout_reset(&sc->sc_tick_ch, hz, gem_tick, sc); 105891398Stmm} 105991398Stmm 1060170273Syongari/* 1061174987Smarius * This is a copy of ath_defrag(ath(4)). 1062170273Syongari * 1063170273Syongari * Defragment an mbuf chain, returning at most maxfrags separate 1064170273Syongari * mbufs+clusters. If this is not possible NULL is returned and 1065170273Syongari * the original mbuf chain is left in it's present (potentially 1066170273Syongari * modified) state. We use two techniques: collapsing consecutive 1067170273Syongari * mbufs and replacing consecutive mbufs by a cluster. 1068170273Syongari */ 1069170273Syongaristatic struct mbuf * 1070174987Smariusgem_defrag(struct mbuf *m0, int how, int maxfrags) 1071170273Syongari{ 1072170273Syongari struct mbuf *m, *n, *n2, **prev; 1073170273Syongari u_int curfrags; 1074170273Syongari 1075170273Syongari /* 1076170273Syongari * Calculate the current number of frags. 1077170273Syongari */ 1078170273Syongari curfrags = 0; 1079170273Syongari for (m = m0; m != NULL; m = m->m_next) 1080170273Syongari curfrags++; 1081170273Syongari /* 1082170273Syongari * First, try to collapse mbufs. Note that we always collapse 1083170273Syongari * towards the front so we don't need to deal with moving the 1084170273Syongari * pkthdr. This may be suboptimal if the first mbuf has much 1085170273Syongari * less data than the following. 1086170273Syongari */ 1087170273Syongari m = m0; 1088174987Smarius again: 1089170273Syongari for (;;) { 1090170273Syongari n = m->m_next; 1091170273Syongari if (n == NULL) 1092170273Syongari break; 1093170273Syongari if ((m->m_flags & M_RDONLY) == 0 && 1094170273Syongari n->m_len < M_TRAILINGSPACE(m)) { 1095170273Syongari bcopy(mtod(n, void *), mtod(m, char *) + m->m_len, 1096170273Syongari n->m_len); 1097170273Syongari m->m_len += n->m_len; 1098170273Syongari m->m_next = n->m_next; 1099170273Syongari m_free(n); 1100170273Syongari if (--curfrags <= maxfrags) 1101170273Syongari return (m0); 1102170273Syongari } else 1103170273Syongari m = n; 1104170273Syongari } 1105170273Syongari KASSERT(maxfrags > 1, 1106174987Smarius ("maxfrags %u, but normal collapse failed", maxfrags)); 1107170273Syongari /* 1108170273Syongari * Collapse consecutive mbufs to a cluster. 1109170273Syongari */ 1110174987Smarius prev = &m0->m_next; /* NB: not the first mbuf. */ 1111170273Syongari while ((n = *prev) != NULL) { 1112170273Syongari if ((n2 = n->m_next) != NULL && 1113170273Syongari n->m_len + n2->m_len < MCLBYTES) { 1114170273Syongari m = m_getcl(how, MT_DATA, 0); 1115170273Syongari if (m == NULL) 1116170273Syongari goto bad; 1117170273Syongari bcopy(mtod(n, void *), mtod(m, void *), n->m_len); 1118170273Syongari bcopy(mtod(n2, void *), mtod(m, char *) + n->m_len, 1119170273Syongari n2->m_len); 1120170273Syongari m->m_len = n->m_len + n2->m_len; 1121170273Syongari m->m_next = n2->m_next; 1122170273Syongari *prev = m; 1123170273Syongari m_free(n); 1124170273Syongari m_free(n2); 1125170273Syongari if (--curfrags <= maxfrags) /* +1 cl -2 mbufs */ 1126174987Smarius return (m0); 1127170273Syongari /* 1128170273Syongari * Still not there, try the normal collapse 1129170273Syongari * again before we allocate another cluster. 1130170273Syongari */ 1131170273Syongari goto again; 1132170273Syongari } 1133170273Syongari prev = &n->m_next; 1134170273Syongari } 1135170273Syongari /* 1136170273Syongari * No place where we can collapse to a cluster; punt. 1137170273Syongari * This can occur if, for example, you request 2 frags 1138170273Syongari * but the packet requires that both be clusters (we 1139170273Syongari * never reallocate the first mbuf to avoid moving the 1140170273Syongari * packet header). 1141170273Syongari */ 1142174987Smarius bad: 1143170273Syongari return (NULL); 1144170273Syongari} 1145170273Syongari 114691398Stmmstatic int 1147174987Smariusgem_load_txmbuf(struct gem_softc *sc, struct mbuf **m_head) 114891398Stmm{ 1149174987Smarius bus_dma_segment_t txsegs[GEM_NTXSEGS]; 115091398Stmm struct gem_txsoft *txs; 1151170273Syongari struct mbuf *m; 1152174987Smarius uint64_t cflags, flags; 1153170273Syongari int error, nexttx, nsegs, seg; 115491398Stmm 1155108832Stmm /* Get a work queue entry. */ 1156108832Stmm if ((txs = STAILQ_FIRST(&sc->sc_txfreeq)) == NULL) { 1157108832Stmm /* Ran out of descriptors. */ 1158170273Syongari return (ENOBUFS); 1159108832Stmm } 1160170273Syongari error = bus_dmamap_load_mbuf_sg(sc->sc_tdmatag, txs->txs_dmamap, 1161170273Syongari *m_head, txsegs, &nsegs, BUS_DMA_NOWAIT); 1162170273Syongari if (error == EFBIG) { 1163170273Syongari m = gem_defrag(*m_head, M_DONTWAIT, GEM_NTXSEGS); 1164170273Syongari if (m == NULL) { 1165170273Syongari m_freem(*m_head); 1166170273Syongari *m_head = NULL; 1167170273Syongari return (ENOBUFS); 1168170273Syongari } 1169170273Syongari *m_head = m; 1170174987Smarius error = bus_dmamap_load_mbuf_sg(sc->sc_tdmatag, 1171174987Smarius txs->txs_dmamap, *m_head, txsegs, &nsegs, 1172174987Smarius BUS_DMA_NOWAIT); 1173170273Syongari if (error != 0) { 1174170273Syongari m_freem(*m_head); 1175170273Syongari *m_head = NULL; 1176170273Syongari return (error); 1177170273Syongari } 1178170273Syongari } else if (error != 0) 1179170273Syongari return (error); 1180170273Syongari if (nsegs == 0) { 1181170273Syongari m_freem(*m_head); 1182170273Syongari *m_head = NULL; 1183170273Syongari return (EIO); 1184170273Syongari } 1185170273Syongari 1186170273Syongari /* 1187170273Syongari * Ensure we have enough descriptors free to describe 1188170273Syongari * the packet. Note, we always reserve one descriptor 1189174987Smarius * at the end of the ring as a termination point, in 1190174987Smarius * order to prevent wrap-around. 1191170273Syongari */ 1192170273Syongari if (nsegs > sc->sc_txfree - 1) { 1193170273Syongari txs->txs_ndescs = 0; 1194170273Syongari bus_dmamap_unload(sc->sc_tdmatag, txs->txs_dmamap); 1195170273Syongari return (ENOBUFS); 1196170273Syongari } 1197170273Syongari 1198170273Syongari flags = cflags = 0; 1199170273Syongari if (((*m_head)->m_pkthdr.csum_flags & sc->sc_csum_features) != 0) 1200170273Syongari gem_txcksum(sc, *m_head, &cflags); 1201170273Syongari 1202170273Syongari txs->txs_ndescs = nsegs; 1203108832Stmm txs->txs_firstdesc = sc->sc_txnext; 1204170273Syongari nexttx = txs->txs_firstdesc; 1205170273Syongari for (seg = 0; seg < nsegs; seg++, nexttx = GEM_NEXTTX(nexttx)) { 1206172334Smarius#ifdef GEM_DEBUG 1207174987Smarius CTR6(KTR_GEM, 1208174987Smarius "%s: mapping seg %d (txd %d), len %lx, addr %#lx (%#lx)", 1209174987Smarius __func__, seg, nexttx, txsegs[seg].ds_len, 1210174987Smarius txsegs[seg].ds_addr, 1211170273Syongari GEM_DMA_WRITE(sc, txsegs[seg].ds_addr)); 1212170273Syongari#endif 1213170273Syongari sc->sc_txdescs[nexttx].gd_addr = 1214170273Syongari GEM_DMA_WRITE(sc, txsegs[seg].ds_addr); 1215170273Syongari KASSERT(txsegs[seg].ds_len < GEM_TD_BUFSIZE, 1216170273Syongari ("%s: segment size too large!", __func__)); 1217170273Syongari flags = txsegs[seg].ds_len & GEM_TD_BUFSIZE; 1218170273Syongari sc->sc_txdescs[nexttx].gd_flags = 1219170273Syongari GEM_DMA_WRITE(sc, flags | cflags); 1220170273Syongari txs->txs_lastdesc = nexttx; 122191398Stmm } 122291398Stmm 1223174987Smarius /* Set EOP on the last descriptor. */ 1224172334Smarius#ifdef GEM_DEBUG 1225174987Smarius CTR3(KTR_GEM, "%s: end of packet at segment %d, TX %d", 1226174987Smarius __func__, seg, nexttx); 1227170273Syongari#endif 1228170273Syongari sc->sc_txdescs[txs->txs_lastdesc].gd_flags |= 1229170273Syongari GEM_DMA_WRITE(sc, GEM_TD_END_OF_PACKET); 1230170273Syongari 1231174987Smarius /* Lastly set SOP on the first descriptor. */ 1232172334Smarius#ifdef GEM_DEBUG 1233174987Smarius CTR3(KTR_GEM, "%s: start of packet at segment %d, TX %d", 1234174987Smarius __func__, seg, nexttx); 1235170273Syongari#endif 1236170273Syongari if (++sc->sc_txwin > GEM_NTXSEGS * 2 / 3) { 1237170273Syongari sc->sc_txwin = 0; 1238170273Syongari flags |= GEM_TD_INTERRUPT_ME; 1239170273Syongari sc->sc_txdescs[txs->txs_firstdesc].gd_flags |= 1240170273Syongari GEM_DMA_WRITE(sc, GEM_TD_INTERRUPT_ME | 1241170273Syongari GEM_TD_START_OF_PACKET); 1242170273Syongari } else 1243170273Syongari sc->sc_txdescs[txs->txs_firstdesc].gd_flags |= 1244170273Syongari GEM_DMA_WRITE(sc, GEM_TD_START_OF_PACKET); 1245170273Syongari 1246108832Stmm /* Sync the DMA map. */ 1247174987Smarius bus_dmamap_sync(sc->sc_tdmatag, txs->txs_dmamap, 1248174987Smarius BUS_DMASYNC_PREWRITE); 124991398Stmm 1250115030Stmm#ifdef GEM_DEBUG 1251170273Syongari CTR4(KTR_GEM, "%s: setting firstdesc=%d, lastdesc=%d, ndescs=%d", 1252174987Smarius __func__, txs->txs_firstdesc, txs->txs_lastdesc, 1253174987Smarius txs->txs_ndescs); 1254115030Stmm#endif 1255108832Stmm STAILQ_REMOVE_HEAD(&sc->sc_txfreeq, txs_q); 1256108832Stmm STAILQ_INSERT_TAIL(&sc->sc_txdirtyq, txs, txs_q); 1257170273Syongari txs->txs_mbuf = *m_head; 125891398Stmm 1259108832Stmm sc->sc_txnext = GEM_NEXTTX(txs->txs_lastdesc); 1260108832Stmm sc->sc_txfree -= txs->txs_ndescs; 1261170273Syongari 1262108832Stmm return (0); 126391398Stmm} 126491398Stmm 126591398Stmmstatic void 1266174987Smariusgem_init_regs(struct gem_softc *sc) 126791398Stmm{ 1268152315Sru const u_char *laddr = IF_LLADDR(sc->sc_ifp); 126991398Stmm 1270174987Smarius /* These registers are not cleared on reset. */ 1271172334Smarius if ((sc->sc_flags & GEM_INITED) == 0) { 1272174987Smarius /* magic values */ 1273169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_IPG0, 0); 1274169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_IPG1, 8); 1275169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_IPG2, 4); 127691398Stmm 1277174987Smarius bus_write_4(sc->sc_res[0], GEM_MAC_MAC_MIN_FRAME, 1278174987Smarius ETHER_MIN_LEN); 1279174987Smarius /* max frame and max burst size */ 1280169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_MAC_MAX_FRAME, 1281172334Smarius (ETHER_MAX_LEN + ETHER_VLAN_ENCAP_LEN) | (0x2000 << 16)); 128299726Sbenno 1283169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_PREAMBLE_LEN, 0x7); 1284169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_JAM_SIZE, 0x4); 1285169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_ATTEMPT_LIMIT, 0x10); 1286174987Smarius /* dunno... */ 1287169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_CONTROL_TYPE, 0x8088); 1288169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_RANDOM_SEED, 1289174987Smarius ((laddr[5] << 8) | laddr[4]) & 0x3ff); 129099726Sbenno 1291174987Smarius /* secondary MAC address: 0:0:0:0:0:0 */ 1292169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_ADDR3, 0); 1293169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_ADDR4, 0); 1294169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_ADDR5, 0); 129599726Sbenno 1296174987Smarius /* MAC control address: 01:80:c2:00:00:01 */ 1297169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_ADDR6, 0x0001); 1298169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_ADDR7, 0xc200); 1299169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_ADDR8, 0x0180); 130091398Stmm 1301174987Smarius /* MAC filter address: 0:0:0:0:0:0 */ 1302169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_ADDR_FILTER0, 0); 1303169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_ADDR_FILTER1, 0); 1304169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_ADDR_FILTER2, 0); 130591398Stmm 1306169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_ADR_FLT_MASK1_2, 0); 1307169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_ADR_FLT_MASK0, 0); 130891398Stmm 1309172334Smarius sc->sc_flags |= GEM_INITED; 131091398Stmm } 131191398Stmm 1312174987Smarius /* Counters need to be zeroed. */ 1313169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_NORM_COLL_CNT, 0); 1314169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_FIRST_COLL_CNT, 0); 1315169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_EXCESS_COLL_CNT, 0); 1316169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_LATE_COLL_CNT, 0); 1317169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_DEFER_TMR_CNT, 0); 1318169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_PEAK_ATTEMPTS, 0); 1319169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_RX_FRAME_COUNT, 0); 1320169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_RX_LEN_ERR_CNT, 0); 1321169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_RX_ALIGN_ERR, 0); 1322169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_RX_CRC_ERR_CNT, 0); 1323169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_RX_CODE_VIOL, 0); 132491398Stmm 1325172334Smarius /* Set XOFF PAUSE time. */ 1326169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_SEND_PAUSE_CMD, 0x1BF0); 132791398Stmm 132891398Stmm /* 1329172334Smarius * Set the internal arbitration to "infinite" bursts of the 1330172334Smarius * maximum length of 31 * 64 bytes so DMA transfers aren't 1331174987Smarius * split up in cache line size chunks. This greatly improves 1332172334Smarius * especially RX performance. 1333172334Smarius * Enable silicon bug workarounds for the Apple variants. 1334172334Smarius */ 1335172334Smarius bus_write_4(sc->sc_res[0], GEM_CONFIG, 1336172334Smarius GEM_CONFIG_TXDMA_LIMIT | GEM_CONFIG_RXDMA_LIMIT | 1337172334Smarius GEM_CONFIG_BURST_INF | (GEM_IS_APPLE(sc) ? 1338172334Smarius GEM_CONFIG_RONPAULBIT | GEM_CONFIG_BUG2FIX : 0)); 1339172334Smarius 1340174987Smarius /* Set the station address. */ 1341174987Smarius bus_write_4(sc->sc_res[0], GEM_MAC_ADDR0, 1342174987Smarius (laddr[4] << 8) | laddr[5]); 1343174987Smarius bus_write_4(sc->sc_res[0], GEM_MAC_ADDR1, 1344174987Smarius (laddr[2] << 8) | laddr[3]); 1345174987Smarius bus_write_4(sc->sc_res[0], GEM_MAC_ADDR2, 1346174987Smarius (laddr[0] << 8) | laddr[1]); 134799726Sbenno 1348172334Smarius /* Enable MII outputs. */ 1349174987Smarius bus_write_4(sc->sc_res[0], GEM_MAC_XIF_CONFIG, 1350174987Smarius GEM_MAC_XIF_TX_MII_ENA); 135191398Stmm} 135291398Stmm 135391398Stmmstatic void 1354174987Smariusgem_start(struct ifnet *ifp) 135591398Stmm{ 1356174987Smarius struct gem_softc *sc = ifp->if_softc; 1357148369Smarius 1358148369Smarius GEM_LOCK(sc); 1359148369Smarius gem_start_locked(ifp); 1360148369Smarius GEM_UNLOCK(sc); 1361148369Smarius} 1362148369Smarius 1363148369Smariusstatic void 1364174987Smariusgem_start_locked(struct ifnet *ifp) 1365148369Smarius{ 1366174987Smarius struct gem_softc *sc = ifp->if_softc; 1367170273Syongari struct mbuf *m; 1368174987Smarius int ntx; 136991398Stmm 1370148887Srwatson if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) != 1371172334Smarius IFF_DRV_RUNNING || (sc->sc_flags & GEM_LINK) == 0) 137291398Stmm return; 137391398Stmm 1374115030Stmm#ifdef GEM_DEBUG 1375170273Syongari CTR4(KTR_GEM, "%s: %s: txfree %d, txnext %d", 1376172334Smarius device_get_name(sc->sc_dev), __func__, sc->sc_txfree, 1377172334Smarius sc->sc_txnext); 1378115030Stmm#endif 1379174987Smarius ntx = 0; 1380170273Syongari for (; !IFQ_DRV_IS_EMPTY(&ifp->if_snd) && sc->sc_txfree > 1;) { 1381170273Syongari IFQ_DRV_DEQUEUE(&ifp->if_snd, m); 1382170273Syongari if (m == NULL) 138391398Stmm break; 1384172334Smarius if (gem_load_txmbuf(sc, &m) != 0) { 1385170273Syongari if (m == NULL) 1386170273Syongari break; 1387170273Syongari ifp->if_drv_flags |= IFF_DRV_OACTIVE; 1388170273Syongari IFQ_DRV_PREPEND(&ifp->if_snd, m); 138991398Stmm break; 139091398Stmm } 1391115030Stmm ntx++; 1392108832Stmm /* Kick the transmitter. */ 1393172334Smarius#ifdef GEM_DEBUG 1394174987Smarius CTR3(KTR_GEM, "%s: %s: kicking TX %d", 1395170273Syongari device_get_name(sc->sc_dev), __func__, sc->sc_txnext); 1396115030Stmm#endif 1397172334Smarius GEM_CDSYNC(sc, BUS_DMASYNC_PREWRITE); 1398174987Smarius bus_write_4(sc->sc_res[0], GEM_TX_KICK, sc->sc_txnext); 1399108832Stmm 1400170273Syongari BPF_MTAP(ifp, m); 140191398Stmm } 140291398Stmm 140391398Stmm if (ntx > 0) { 1404115030Stmm#ifdef GEM_DEBUG 1405108832Stmm CTR2(KTR_GEM, "%s: packets enqueued, OWN on %d", 1406172334Smarius device_get_name(sc->sc_dev), sc->sc_txnext); 1407115030Stmm#endif 140891398Stmm 140991398Stmm /* Set a watchdog timer in case the chip flakes out. */ 1410164931Smarius sc->sc_wdog_timer = 5; 1411115030Stmm#ifdef GEM_DEBUG 1412170273Syongari CTR3(KTR_GEM, "%s: %s: watchdog %d", 1413174987Smarius device_get_name(sc->sc_dev), __func__, 1414174987Smarius sc->sc_wdog_timer); 1415115030Stmm#endif 141691398Stmm } 141791398Stmm} 141891398Stmm 141991398Stmmstatic void 1420174987Smariusgem_tint(struct gem_softc *sc) 142191398Stmm{ 1422147256Sbrooks struct ifnet *ifp = sc->sc_ifp; 142391398Stmm struct gem_txsoft *txs; 1424174987Smarius int txlast, progress; 1425174987Smarius#ifdef GEM_DEBUG 1426174987Smarius int i; 142791398Stmm 1428170273Syongari CTR2(KTR_GEM, "%s: %s", device_get_name(sc->sc_dev), __func__); 1429115030Stmm#endif 143091398Stmm 143191398Stmm /* 1432174987Smarius * Go through our TX list and free mbufs for those 143391398Stmm * frames that have been transmitted. 143491398Stmm */ 1435174987Smarius progress = 0; 1436109648Stmm GEM_CDSYNC(sc, BUS_DMASYNC_POSTREAD); 143791398Stmm while ((txs = STAILQ_FIRST(&sc->sc_txdirtyq)) != NULL) { 143891398Stmm 143991398Stmm#ifdef GEM_DEBUG 1440174987Smarius if ((ifp->if_flags & IFF_DEBUG) != 0) { 144191398Stmm printf(" txsoft %p transmit chain:\n", txs); 144291398Stmm for (i = txs->txs_firstdesc;; i = GEM_NEXTTX(i)) { 144391398Stmm printf("descriptor %d: ", i); 1444174987Smarius printf("gd_flags: 0x%016llx\t", 1445174987Smarius (long long)GEM_DMA_READ(sc, 1446174987Smarius sc->sc_txdescs[i].gd_flags)); 1447174987Smarius printf("gd_addr: 0x%016llx\n", 1448174987Smarius (long long)GEM_DMA_READ(sc, 1449174987Smarius sc->sc_txdescs[i].gd_addr)); 145091398Stmm if (i == txs->txs_lastdesc) 145191398Stmm break; 145291398Stmm } 145391398Stmm } 145491398Stmm#endif 145591398Stmm 145691398Stmm /* 1457172334Smarius * In theory, we could harvest some descriptors before 145891398Stmm * the ring is empty, but that's a bit complicated. 145991398Stmm * 146091398Stmm * GEM_TX_COMPLETION points to the last descriptor 1461174987Smarius * processed + 1. 146291398Stmm */ 1463169269Sphk txlast = bus_read_4(sc->sc_res[0], GEM_TX_COMPLETION); 1464115030Stmm#ifdef GEM_DEBUG 1465170273Syongari CTR4(KTR_GEM, "%s: txs->txs_firstdesc = %d, " 146691398Stmm "txs->txs_lastdesc = %d, txlast = %d", 1467170273Syongari __func__, txs->txs_firstdesc, txs->txs_lastdesc, txlast); 1468115030Stmm#endif 146991398Stmm if (txs->txs_firstdesc <= txs->txs_lastdesc) { 147091398Stmm if ((txlast >= txs->txs_firstdesc) && 1471174987Smarius (txlast <= txs->txs_lastdesc)) 147291398Stmm break; 147391398Stmm } else { 1474174987Smarius /* Ick -- this command wraps. */ 147591398Stmm if ((txlast >= txs->txs_firstdesc) || 1476174987Smarius (txlast <= txs->txs_lastdesc)) 147791398Stmm break; 147891398Stmm } 147991398Stmm 1480115030Stmm#ifdef GEM_DEBUG 1481174987Smarius CTR1(KTR_GEM, "%s: releasing a descriptor", __func__); 1482115030Stmm#endif 148391398Stmm STAILQ_REMOVE_HEAD(&sc->sc_txdirtyq, txs_q); 148491398Stmm 148591398Stmm sc->sc_txfree += txs->txs_ndescs; 148691398Stmm 1487108832Stmm bus_dmamap_sync(sc->sc_tdmatag, txs->txs_dmamap, 148891398Stmm BUS_DMASYNC_POSTWRITE); 1489108832Stmm bus_dmamap_unload(sc->sc_tdmatag, txs->txs_dmamap); 149091398Stmm if (txs->txs_mbuf != NULL) { 149191398Stmm m_freem(txs->txs_mbuf); 149291398Stmm txs->txs_mbuf = NULL; 149391398Stmm } 149491398Stmm 149591398Stmm STAILQ_INSERT_TAIL(&sc->sc_txfreeq, txs, txs_q); 149691398Stmm 149791398Stmm ifp->if_opackets++; 149899726Sbenno progress = 1; 149991398Stmm } 150091398Stmm 1501115030Stmm#ifdef GEM_DEBUG 1502174987Smarius CTR4(KTR_GEM, "%s: GEM_TX_STATE_MACHINE %x GEM_TX_DATA_PTR %llx " 1503172334Smarius "GEM_TX_COMPLETION %x", 1504174987Smarius __func__, bus_read_4(sc->sc_res[0], GEM_TX_STATE_MACHINE), 1505174987Smarius ((long long)bus_read_4(sc->sc_res[0], 1506174987Smarius GEM_TX_DATA_PTR_HI) << 32) | 1507172334Smarius bus_read_4(sc->sc_res[0], GEM_TX_DATA_PTR_LO), 1508172334Smarius bus_read_4(sc->sc_res[0], GEM_TX_COMPLETION)); 1509115030Stmm#endif 151091398Stmm 151199726Sbenno if (progress) { 151299726Sbenno if (sc->sc_txfree == GEM_NTXDESC - 1) 151399726Sbenno sc->sc_txwin = 0; 151491398Stmm 1515174987Smarius /* 1516174987Smarius * We freed some descriptors, so reset IFF_DRV_OACTIVE 1517174987Smarius * and restart. 1518174987Smarius */ 1519148887Srwatson ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 1520170273Syongari sc->sc_wdog_timer = STAILQ_EMPTY(&sc->sc_txdirtyq) ? 0 : 5; 152191398Stmm 1522170273Syongari if (ifp->if_drv_flags & IFF_DRV_RUNNING && 1523170273Syongari !IFQ_DRV_IS_EMPTY(&ifp->if_snd)) 1524170273Syongari gem_start_locked(ifp); 152599726Sbenno } 152699726Sbenno 1527115030Stmm#ifdef GEM_DEBUG 1528170273Syongari CTR3(KTR_GEM, "%s: %s: watchdog %d", 1529170273Syongari device_get_name(sc->sc_dev), __func__, sc->sc_wdog_timer); 1530115030Stmm#endif 153191398Stmm} 153291398Stmm 1533148368Smarius#ifdef GEM_RINT_TIMEOUT 153493045Stmmstatic void 1535174987Smariusgem_rint_timeout(void *arg) 153693045Stmm{ 1537174987Smarius struct gem_softc *sc = arg; 153893045Stmm 1539150285Smarius GEM_LOCK_ASSERT(sc, MA_OWNED); 1540148369Smarius gem_rint(sc); 154193045Stmm} 1542100587Sjake#endif 154393045Stmm 154491398Stmmstatic void 1545174987Smariusgem_rint(struct gem_softc *sc) 154691398Stmm{ 1547147256Sbrooks struct ifnet *ifp = sc->sc_ifp; 154891398Stmm struct mbuf *m; 1549174987Smarius uint64_t rxstat; 1550174987Smarius uint32_t rxcomp; 155191398Stmm 1552148368Smarius#ifdef GEM_RINT_TIMEOUT 155393045Stmm callout_stop(&sc->sc_rx_ch); 1554148368Smarius#endif 1555115030Stmm#ifdef GEM_DEBUG 1556170273Syongari CTR2(KTR_GEM, "%s: %s", device_get_name(sc->sc_dev), __func__); 1557115030Stmm#endif 155899726Sbenno 155991398Stmm /* 156099726Sbenno * Read the completion register once. This limits 156199726Sbenno * how long the following loop can execute. 156299726Sbenno */ 1563169269Sphk rxcomp = bus_read_4(sc->sc_res[0], GEM_RX_COMPLETION); 156499726Sbenno 1565115030Stmm#ifdef GEM_DEBUG 1566170273Syongari CTR3(KTR_GEM, "%s: sc->rxptr %d, complete %d", 1567170273Syongari __func__, sc->sc_rxptr, rxcomp); 1568115030Stmm#endif 1569109648Stmm GEM_CDSYNC(sc, BUS_DMASYNC_POSTREAD); 1570172334Smarius for (; sc->sc_rxptr != rxcomp;) { 1571172334Smarius m = sc->sc_rxsoft[sc->sc_rxptr].rxs_mbuf; 1572172334Smarius rxstat = GEM_DMA_READ(sc, 1573172334Smarius sc->sc_rxdescs[sc->sc_rxptr].gd_flags); 157491398Stmm 157591398Stmm if (rxstat & GEM_RD_OWN) { 1576148368Smarius#ifdef GEM_RINT_TIMEOUT 157791398Stmm /* 157893045Stmm * The descriptor is still marked as owned, although 1579174987Smarius * it is supposed to have completed. This has been 1580174987Smarius * observed on some machines. Just exiting here 158193045Stmm * might leave the packet sitting around until another 158293045Stmm * one arrives to trigger a new interrupt, which is 158393045Stmm * generally undesirable, so set up a timeout. 158491398Stmm */ 158593045Stmm callout_reset(&sc->sc_rx_ch, GEM_RXOWN_TICKS, 158693045Stmm gem_rint_timeout, sc); 158799726Sbenno#endif 1588172334Smarius m = NULL; 1589172334Smarius goto kickit; 159091398Stmm } 159191398Stmm 159291398Stmm if (rxstat & GEM_RD_BAD_CRC) { 159399726Sbenno ifp->if_ierrors++; 159491398Stmm device_printf(sc->sc_dev, "receive error: CRC error\n"); 1595172334Smarius GEM_INIT_RXDESC(sc, sc->sc_rxptr); 1596172334Smarius m = NULL; 1597172334Smarius goto kickit; 159891398Stmm } 159991398Stmm 160091398Stmm#ifdef GEM_DEBUG 1601174987Smarius if ((ifp->if_flags & IFF_DEBUG) != 0) { 1602172334Smarius printf(" rxsoft %p descriptor %d: ", 1603172334Smarius &sc->sc_rxsoft[sc->sc_rxptr], sc->sc_rxptr); 1604174987Smarius printf("gd_flags: 0x%016llx\t", 1605174987Smarius (long long)GEM_DMA_READ(sc, 1606174987Smarius sc->sc_rxdescs[sc->sc_rxptr].gd_flags)); 1607174987Smarius printf("gd_addr: 0x%016llx\n", 1608174987Smarius (long long)GEM_DMA_READ(sc, 1609174987Smarius sc->sc_rxdescs[sc->sc_rxptr].gd_addr)); 161091398Stmm } 161191398Stmm#endif 161291398Stmm 161391398Stmm /* 161491398Stmm * Allocate a new mbuf cluster. If that fails, we are 161591398Stmm * out of memory, and must drop the packet and recycle 161691398Stmm * the buffer that's already attached to this descriptor. 161791398Stmm */ 1618172334Smarius if (gem_add_rxbuf(sc, sc->sc_rxptr) != 0) { 161991398Stmm ifp->if_ierrors++; 1620172334Smarius GEM_INIT_RXDESC(sc, sc->sc_rxptr); 1621172334Smarius m = NULL; 1622172334Smarius } 1623172334Smarius 1624174987Smarius kickit: 1625174987Smarius /* 1626174987Smarius * Update the RX kick register. This register has to point 1627172334Smarius * to the descriptor after the last valid one (before the 1628172334Smarius * current batch) and must be incremented in multiples of 1629172334Smarius * 4 (because the DMA engine fetches/updates descriptors 1630172334Smarius * in batches of 4). 1631172334Smarius */ 1632172334Smarius sc->sc_rxptr = GEM_NEXTRX(sc->sc_rxptr); 1633172334Smarius if ((sc->sc_rxptr % 4) == 0) { 1634172334Smarius GEM_CDSYNC(sc, BUS_DMASYNC_PREWRITE); 1635172334Smarius bus_write_4(sc->sc_res[0], GEM_RX_KICK, 1636172334Smarius (sc->sc_rxptr + GEM_NRXDESC - 4) & 1637172334Smarius GEM_NRXDESC_MASK); 1638172334Smarius } 1639172334Smarius 1640172334Smarius if (m == NULL) { 1641172334Smarius if (rxstat & GEM_RD_OWN) 1642172334Smarius break; 164391398Stmm continue; 164491398Stmm } 1645172334Smarius 1646172334Smarius ifp->if_ipackets++; 164791398Stmm m->m_data += 2; /* We're already off by two */ 164891398Stmm m->m_pkthdr.rcvif = ifp; 1649172334Smarius m->m_pkthdr.len = m->m_len = GEM_RD_BUFLEN(rxstat); 165091398Stmm 1651170273Syongari if ((ifp->if_capenable & IFCAP_RXCSUM) != 0) 1652170273Syongari gem_rxcksum(m, rxstat); 1653170273Syongari 165491398Stmm /* Pass it on. */ 1655148369Smarius GEM_UNLOCK(sc); 1656106937Ssam (*ifp->if_input)(ifp, m); 1657148369Smarius GEM_LOCK(sc); 165891398Stmm } 165991398Stmm 1660115030Stmm#ifdef GEM_DEBUG 1661170273Syongari CTR3(KTR_GEM, "%s: done sc->rxptr %d, complete %d", __func__, 1662174987Smarius sc->sc_rxptr, bus_read_4(sc->sc_res[0], GEM_RX_COMPLETION)); 1663115030Stmm#endif 166491398Stmm} 166591398Stmm 166691398Stmmstatic int 1667174987Smariusgem_add_rxbuf(struct gem_softc *sc, int idx) 166891398Stmm{ 166991398Stmm struct gem_rxsoft *rxs = &sc->sc_rxsoft[idx]; 167091398Stmm struct mbuf *m; 1671148368Smarius bus_dma_segment_t segs[1]; 1672148368Smarius int error, nsegs; 167391398Stmm 1674111119Simp m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); 167591398Stmm if (m == NULL) 167691398Stmm return (ENOBUFS); 1677108832Stmm m->m_len = m->m_pkthdr.len = m->m_ext.ext_size; 167891398Stmm 167991398Stmm#ifdef GEM_DEBUG 1680174987Smarius /* Bzero the packet to check DMA. */ 168191398Stmm memset(m->m_ext.ext_buf, 0, m->m_ext.ext_size); 168291398Stmm#endif 168391398Stmm 1684109648Stmm if (rxs->rxs_mbuf != NULL) { 1685109648Stmm bus_dmamap_sync(sc->sc_rdmatag, rxs->rxs_dmamap, 1686109648Stmm BUS_DMASYNC_POSTREAD); 1687108832Stmm bus_dmamap_unload(sc->sc_rdmatag, rxs->rxs_dmamap); 1688109648Stmm } 168991398Stmm 1690148368Smarius error = bus_dmamap_load_mbuf_sg(sc->sc_rdmatag, rxs->rxs_dmamap, 1691148368Smarius m, segs, &nsegs, BUS_DMA_NOWAIT); 1692148368Smarius KASSERT(nsegs == 1, ("Too many segments returned!")); 1693148368Smarius if (error != 0) { 1694174987Smarius device_printf(sc->sc_dev, 1695174987Smarius "cannot load RS DMA map %d, error = %d\n", idx, error); 1696148368Smarius m_freem(m); 1697172334Smarius return (error); 169891398Stmm } 1699174987Smarius /* If nsegs is wrong then the stack is corrupt. */ 1700172334Smarius rxs->rxs_mbuf = m; 1701148368Smarius rxs->rxs_paddr = segs[0].ds_addr; 170291398Stmm 1703174987Smarius bus_dmamap_sync(sc->sc_rdmatag, rxs->rxs_dmamap, 1704174987Smarius BUS_DMASYNC_PREREAD); 170591398Stmm 170691398Stmm GEM_INIT_RXDESC(sc, idx); 170791398Stmm 170891398Stmm return (0); 170991398Stmm} 171091398Stmm 171191398Stmmstatic void 1712174987Smariusgem_eint(struct gem_softc *sc, u_int status) 171391398Stmm{ 171491398Stmm 1715172334Smarius sc->sc_ifp->if_ierrors++; 1716172334Smarius if ((status & GEM_INTR_RX_TAG_ERR) != 0) { 1717172334Smarius gem_reset_rxdma(sc); 171891398Stmm return; 171991398Stmm } 172091398Stmm 1721172334Smarius device_printf(sc->sc_dev, "%s: status=%x\n", __func__, status); 172291398Stmm} 172391398Stmm 172491398Stmmvoid 1725174987Smariusgem_intr(void *v) 172691398Stmm{ 1727174987Smarius struct gem_softc *sc = v; 1728172334Smarius uint32_t status, status2; 172991398Stmm 1730148369Smarius GEM_LOCK(sc); 1731169269Sphk status = bus_read_4(sc->sc_res[0], GEM_STATUS); 1732172334Smarius 1733115030Stmm#ifdef GEM_DEBUG 1734170273Syongari CTR4(KTR_GEM, "%s: %s: cplt %x, status %x", 1735174987Smarius device_get_name(sc->sc_dev), __func__, (status >> 19), 1736174987Smarius (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 = 1743174987Smarius bus_read_4(sc->sc_res[0], GEM_MII_INTERRUP_STATUS) | 1744172334Smarius bus_read_4(sc->sc_res[0], 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) { 1750172334Smarius status2 = bus_read_4(sc->sc_res[0], 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 1766172334Smarius if ((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 177691398Stmm if (status & GEM_INTR_TX_MAC) { 1777172334Smarius status2 = bus_read_4(sc->sc_res[0], GEM_MAC_TX_STATUS); 1778174987Smarius if ((status2 & 1779174987Smarius ~(GEM_MAC_TX_XMIT_DONE | GEM_MAC_TX_DEFER_EXP)) != 0) 1780174987Smarius device_printf(sc->sc_dev, 1781174987Smarius "MAC TX fault, status %x\n", status2); 1782174987Smarius if ((status2 & 1783174987Smarius (GEM_MAC_TX_UNDERRUN | GEM_MAC_TX_PKT_TOO_LONG)) != 0) 1784148369Smarius gem_init_locked(sc); 178591398Stmm } 178691398Stmm if (status & GEM_INTR_RX_MAC) { 1787172334Smarius status2 = bus_read_4(sc->sc_res[0], GEM_MAC_RX_STATUS); 1788149552Smarius /* 1789172334Smarius * At least with GEM_SUN_GEM and some GEM_SUN_ERI 1790172334Smarius * revisions GEM_MAC_RX_OVERFLOW happen often due to a 1791174987Smarius * silicon bug so handle them silently. Moreover, it's 1792172334Smarius * likely that the receiver has hung so we reset it. 1793149552Smarius */ 1794174987Smarius if ((status2 & GEM_MAC_RX_OVERFLOW) != 0) { 1795172334Smarius sc->sc_ifp->if_ierrors++; 1796172334Smarius gem_reset_rxdma(sc); 1797174987Smarius } else if ((status2 & 1798174987Smarius ~(GEM_MAC_RX_DONE | GEM_MAC_RX_FRAME_CNT)) != 0) 1799174987Smarius device_printf(sc->sc_dev, 1800174987Smarius "MAC RX fault, status %x\n", status2); 180191398Stmm } 1802148369Smarius GEM_UNLOCK(sc); 180391398Stmm} 180491398Stmm 1805164931Smariusstatic int 1806174987Smariusgem_watchdog(struct gem_softc *sc) 180791398Stmm{ 180891398Stmm 1809164931Smarius GEM_LOCK_ASSERT(sc, MA_OWNED); 1810164931Smarius 1811115030Stmm#ifdef GEM_DEBUG 1812174987Smarius CTR4(KTR_GEM, 1813174987Smarius "%s: GEM_RX_CONFIG %x GEM_MAC_RX_STATUS %x GEM_MAC_RX_CONFIG %x", 1814174987Smarius __func__, bus_read_4(sc->sc_res[0], GEM_RX_CONFIG), 1815174987Smarius bus_read_4(sc->sc_res[0], GEM_MAC_RX_STATUS), 1816174987Smarius bus_read_4(sc->sc_res[0], GEM_MAC_RX_CONFIG)); 1817174987Smarius CTR4(KTR_GEM, 1818174987Smarius "%s: GEM_TX_CONFIG %x GEM_MAC_TX_STATUS %x GEM_MAC_TX_CONFIG %x", 1819174987Smarius __func__, bus_read_4(sc->sc_res[0], GEM_TX_CONFIG), 1820174987Smarius bus_read_4(sc->sc_res[0], GEM_MAC_TX_STATUS), 1821174987Smarius bus_read_4(sc->sc_res[0], GEM_MAC_TX_CONFIG)); 1822115030Stmm#endif 182391398Stmm 1824164931Smarius if (sc->sc_wdog_timer == 0 || --sc->sc_wdog_timer != 0) 1825164931Smarius return (0); 1826164931Smarius 1827172334Smarius if ((sc->sc_flags & GEM_LINK) != 0) 1828172334Smarius device_printf(sc->sc_dev, "device timeout\n"); 1829172334Smarius else if (bootverbose) 1830172334Smarius device_printf(sc->sc_dev, "device timeout (no link)\n"); 1831164931Smarius ++sc->sc_ifp->if_oerrors; 183291398Stmm 183391398Stmm /* Try to get more packets going. */ 1834148369Smarius gem_init_locked(sc); 1835164931Smarius return (EJUSTRETURN); 183691398Stmm} 183791398Stmm 183891398Stmmstatic void 1839174987Smariusgem_mifinit(struct gem_softc *sc) 184091398Stmm{ 184191398Stmm 184291398Stmm /* Configure the MIF in frame mode */ 1843172334Smarius bus_write_4(sc->sc_res[0], GEM_MIF_CONFIG, bus_read_4(sc->sc_res[0], 1844172334Smarius GEM_MIF_CONFIG) & ~GEM_MIF_CONFIG_BB_ENA); 184591398Stmm} 184691398Stmm 184791398Stmm/* 184891398Stmm * MII interface 184991398Stmm * 185091398Stmm * The GEM MII interface supports at least three different operating modes: 185191398Stmm * 185291398Stmm * Bitbang mode is implemented using data, clock and output enable registers. 185391398Stmm * 185491398Stmm * Frame mode is implemented by loading a complete frame into the frame 185591398Stmm * register and polling the valid bit for completion. 185691398Stmm * 185791398Stmm * Polling mode uses the frame register but completion is indicated by 185891398Stmm * an interrupt. 185991398Stmm * 186091398Stmm */ 186191398Stmmint 1862174987Smariusgem_mii_readreg(device_t dev, int phy, int reg) 186391398Stmm{ 1864174987Smarius struct gem_softc *sc; 186591398Stmm int n; 1866174987Smarius uint32_t v; 186791398Stmm 186891398Stmm#ifdef GEM_DEBUG_PHY 1869172334Smarius printf("%s: phy %d reg %d\n", __func__, phy, reg); 187091398Stmm#endif 187191398Stmm 1872174987Smarius sc = device_get_softc(dev); 1873172334Smarius if (sc->sc_phyad != -1 && phy != sc->sc_phyad) 1874172334Smarius return (0); 187591398Stmm 1876172334Smarius if ((sc->sc_flags & GEM_SERDES) != 0) { 1877172334Smarius switch (reg) { 1878172334Smarius case MII_BMCR: 1879172334Smarius reg = GEM_MII_CONTROL; 1880172334Smarius break; 1881172334Smarius case MII_BMSR: 1882172334Smarius reg = GEM_MII_STATUS; 1883172334Smarius break; 1884172334Smarius case MII_PHYIDR1: 1885172334Smarius case MII_PHYIDR2: 1886172334Smarius return (0); 1887172334Smarius case MII_ANAR: 1888172334Smarius reg = GEM_MII_ANAR; 1889172334Smarius break; 1890172334Smarius case MII_ANLPAR: 1891172334Smarius reg = GEM_MII_ANLPAR; 1892172334Smarius break; 1893172334Smarius case MII_EXTSR: 1894172334Smarius return (EXTSR_1000XFDX | EXTSR_1000XHDX); 1895172334Smarius default: 1896172334Smarius device_printf(sc->sc_dev, 1897172334Smarius "%s: unhandled register %d\n", __func__, reg); 1898172334Smarius return (0); 1899172334Smarius } 1900172334Smarius return (bus_read_4(sc->sc_res[0], reg)); 1901172334Smarius } 1902172334Smarius 1903174987Smarius /* Construct the frame command. */ 1904172334Smarius v = GEM_MIF_FRAME_READ | 1905172334Smarius (phy << GEM_MIF_PHY_SHIFT) | 1906172334Smarius (reg << GEM_MIF_REG_SHIFT); 190791398Stmm 1908169269Sphk bus_write_4(sc->sc_res[0], GEM_MIF_FRAME, v); 190991398Stmm for (n = 0; n < 100; n++) { 191091398Stmm DELAY(1); 1911169269Sphk v = bus_read_4(sc->sc_res[0], GEM_MIF_FRAME); 1912150285Smarius if (v & GEM_MIF_FRAME_TA0) 191391398Stmm return (v & GEM_MIF_FRAME_DATA); 191491398Stmm } 191591398Stmm 1916174987Smarius device_printf(sc->sc_dev, "%s: timed out\n", __func__); 191791398Stmm return (0); 191891398Stmm} 191991398Stmm 192091398Stmmint 1921174987Smariusgem_mii_writereg(device_t dev, int phy, int reg, int val) 192291398Stmm{ 1923174987Smarius struct gem_softc *sc; 192491398Stmm int n; 1925174987Smarius uint32_t v; 192691398Stmm 192791398Stmm#ifdef GEM_DEBUG_PHY 1928172334Smarius printf("%s: phy %d reg %d val %x\n", phy, reg, val, __func__); 192991398Stmm#endif 193091398Stmm 1931174987Smarius sc = device_get_softc(dev); 1932172334Smarius if (sc->sc_phyad != -1 && phy != sc->sc_phyad) 1933172334Smarius return (0); 1934172334Smarius 1935172334Smarius if ((sc->sc_flags & GEM_SERDES) != 0) { 1936172334Smarius switch (reg) { 1937172334Smarius case MII_BMCR: 1938172334Smarius reg = GEM_MII_CONTROL; 1939172334Smarius break; 1940172334Smarius case MII_BMSR: 1941172334Smarius reg = GEM_MII_STATUS; 1942172334Smarius break; 1943172334Smarius case MII_ANAR: 1944172334Smarius bus_write_4(sc->sc_res[0], GEM_MII_CONFIG, 0); 1945172334Smarius bus_barrier(sc->sc_res[0], GEM_MII_CONFIG, 4, 1946172334Smarius BUS_SPACE_BARRIER_WRITE); 1947172334Smarius bus_write_4(sc->sc_res[0], GEM_MII_ANAR, val); 1948172334Smarius bus_write_4(sc->sc_res[0], GEM_MII_SLINK_CONTROL, 1949172334Smarius GEM_MII_SLINK_LOOPBACK | GEM_MII_SLINK_EN_SYNC_D); 1950172334Smarius bus_write_4(sc->sc_res[0], GEM_MII_CONFIG, 1951172334Smarius GEM_MII_CONFIG_ENABLE); 1952172334Smarius return (0); 1953172334Smarius case MII_ANLPAR: 1954172334Smarius reg = GEM_MII_ANLPAR; 1955172334Smarius break; 1956172334Smarius default: 1957172334Smarius device_printf(sc->sc_dev, 1958172334Smarius "%s: unhandled register %d\n", __func__, reg); 1959172334Smarius return (0); 1960172334Smarius } 1961172334Smarius bus_write_4(sc->sc_res[0], reg, val); 1962172334Smarius return (0); 1963172334Smarius } 1964172334Smarius 1965174987Smarius /* Construct the frame command. */ 1966172334Smarius v = GEM_MIF_FRAME_WRITE | 1967172334Smarius (phy << GEM_MIF_PHY_SHIFT) | 1968172334Smarius (reg << GEM_MIF_REG_SHIFT) | 196991398Stmm (val & GEM_MIF_FRAME_DATA); 197091398Stmm 1971169269Sphk bus_write_4(sc->sc_res[0], GEM_MIF_FRAME, v); 197291398Stmm for (n = 0; n < 100; n++) { 197391398Stmm DELAY(1); 1974169269Sphk v = bus_read_4(sc->sc_res[0], GEM_MIF_FRAME); 1975150285Smarius if (v & GEM_MIF_FRAME_TA0) 197691398Stmm return (1); 197791398Stmm } 197891398Stmm 1979174987Smarius device_printf(sc->sc_dev, "%s: timed out\n", __func__); 198091398Stmm return (0); 198191398Stmm} 198291398Stmm 198391398Stmmvoid 1984174987Smariusgem_mii_statchg(device_t dev) 198591398Stmm{ 1986174987Smarius struct gem_softc *sc; 1987172334Smarius int gigabit; 1988172334Smarius uint32_t rxcfg, txcfg, v; 198991398Stmm 1990174987Smarius sc = device_get_softc(dev); 1991174987Smarius 199291398Stmm#ifdef GEM_DEBUG 1993174987Smarius if ((sc->sc_ifp->if_flags & IFF_DEBUG) != 0) 1994172334Smarius device_printf(sc->sc_dev, "%s: status change: PHY = %d\n", 1995172334Smarius __func__, sc->sc_phyad); 199691398Stmm#endif 199791398Stmm 1998172334Smarius if ((sc->sc_mii->mii_media_status & IFM_ACTIVE) != 0 && 1999172334Smarius IFM_SUBTYPE(sc->sc_mii->mii_media_active) != IFM_NONE) 2000172334Smarius sc->sc_flags |= GEM_LINK; 2001172334Smarius else 2002172334Smarius sc->sc_flags &= ~GEM_LINK; 2003172334Smarius 2004172334Smarius switch (IFM_SUBTYPE(sc->sc_mii->mii_media_active)) { 2005172334Smarius case IFM_1000_SX: 2006172334Smarius case IFM_1000_LX: 2007172334Smarius case IFM_1000_CX: 2008172334Smarius case IFM_1000_T: 2009172334Smarius gigabit = 1; 2010172334Smarius break; 2011172334Smarius default: 2012172334Smarius gigabit = 0; 201391398Stmm } 201491398Stmm 2015172334Smarius /* 2016172334Smarius * The configuration done here corresponds to the steps F) and 2017172334Smarius * G) and as far as enabling of RX and TX MAC goes also step H) 2018172334Smarius * of the initialization sequence outlined in section 3.2.1 of 2019172334Smarius * the GEM Gigabit Ethernet ASIC Specification. 2020172334Smarius */ 2021172334Smarius 2022172334Smarius rxcfg = bus_read_4(sc->sc_res[0], GEM_MAC_RX_CONFIG); 2023172334Smarius rxcfg &= ~(GEM_MAC_RX_CARR_EXTEND | GEM_MAC_RX_ENABLE); 2024172334Smarius txcfg = GEM_MAC_TX_ENA_IPG0 | GEM_MAC_TX_NGU | GEM_MAC_TX_NGU_LIMIT; 2025172334Smarius if ((IFM_OPTIONS(sc->sc_mii->mii_media_active) & IFM_FDX) != 0) 2026172334Smarius txcfg |= GEM_MAC_TX_IGN_CARRIER | GEM_MAC_TX_IGN_COLLIS; 2027172334Smarius else if (gigabit != 0) { 2028172334Smarius rxcfg |= GEM_MAC_RX_CARR_EXTEND; 2029172334Smarius txcfg |= GEM_MAC_TX_CARR_EXTEND; 2030172334Smarius } 2031172334Smarius bus_write_4(sc->sc_res[0], GEM_MAC_TX_CONFIG, 0); 2032172334Smarius bus_barrier(sc->sc_res[0], GEM_MAC_TX_CONFIG, 4, 2033172334Smarius BUS_SPACE_BARRIER_WRITE); 2034172334Smarius if (!gem_bitwait(sc, GEM_MAC_TX_CONFIG, GEM_MAC_TX_ENABLE, 0)) 2035172334Smarius device_printf(sc->sc_dev, "cannot disable TX MAC\n"); 2036172334Smarius bus_write_4(sc->sc_res[0], GEM_MAC_TX_CONFIG, txcfg); 2037172334Smarius bus_write_4(sc->sc_res[0], GEM_MAC_RX_CONFIG, 0); 2038172334Smarius bus_barrier(sc->sc_res[0], GEM_MAC_RX_CONFIG, 4, 2039172334Smarius BUS_SPACE_BARRIER_WRITE); 2040172334Smarius if (!gem_bitwait(sc, GEM_MAC_RX_CONFIG, GEM_MAC_RX_ENABLE, 0)) 2041172334Smarius device_printf(sc->sc_dev, "cannot disable RX MAC\n"); 2042172334Smarius bus_write_4(sc->sc_res[0], GEM_MAC_RX_CONFIG, rxcfg); 2043172334Smarius 2044172334Smarius v = bus_read_4(sc->sc_res[0], GEM_MAC_CONTROL_CONFIG) & 2045172334Smarius ~(GEM_MAC_CC_RX_PAUSE | GEM_MAC_CC_TX_PAUSE); 2046172334Smarius#ifdef notyet 2047174987Smarius if ((IFM_OPTIONS(sc->sc_mii->mii_media_active) & 2048174987Smarius IFM_ETH_RXPAUSE) != 0) 2049172334Smarius v |= GEM_MAC_CC_RX_PAUSE; 2050174987Smarius if ((IFM_OPTIONS(sc->sc_mii->mii_media_active) & 2051174987Smarius IFM_ETH_TXPAUSE) != 0) 2052172334Smarius v |= GEM_MAC_CC_TX_PAUSE; 2053172334Smarius#endif 2054172334Smarius bus_write_4(sc->sc_res[0], GEM_MAC_CONTROL_CONFIG, v); 2055172334Smarius 2056172334Smarius if ((IFM_OPTIONS(sc->sc_mii->mii_media_active) & IFM_FDX) == 0 && 2057172334Smarius gigabit != 0) 2058172334Smarius bus_write_4(sc->sc_res[0], GEM_MAC_SLOT_TIME, 2059172334Smarius GEM_MAC_SLOT_TIME_CARR_EXTEND); 2060172334Smarius else 2061172334Smarius bus_write_4(sc->sc_res[0], GEM_MAC_SLOT_TIME, 2062172334Smarius GEM_MAC_SLOT_TIME_NORMAL); 2063172334Smarius 206491398Stmm /* XIF Configuration */ 206591398Stmm v = GEM_MAC_XIF_LINK_LED; 206691398Stmm v |= GEM_MAC_XIF_TX_MII_ENA; 2067172334Smarius if ((sc->sc_flags & GEM_SERDES) == 0) { 2068172334Smarius if ((bus_read_4(sc->sc_res[0], GEM_MIF_CONFIG) & 2069172334Smarius GEM_MIF_CONFIG_PHY_SEL) != 0 && 2070174987Smarius (IFM_OPTIONS(sc->sc_mii->mii_media_active) & 2071174987Smarius IFM_FDX) == 0) 2072172334Smarius /* External MII needs echo disable if half duplex. */ 2073174987Smarius v |= GEM_MAC_XIF_ECHO_DISABL; 207499726Sbenno else 2075172334Smarius /* 2076172334Smarius * Internal MII needs buffer enable. 2077172334Smarius * XXX buffer enable makes only sense for an 2078172334Smarius * external PHY. 2079172334Smarius */ 2080172334Smarius v |= GEM_MAC_XIF_MII_BUF_ENA; 2081172334Smarius } 2082172334Smarius if (gigabit != 0) 2083172334Smarius v |= GEM_MAC_XIF_GMII_MODE; 2084172334Smarius if ((IFM_OPTIONS(sc->sc_mii->mii_media_active) & IFM_FDX) != 0) 2085172334Smarius v |= GEM_MAC_XIF_FDPLX_LED; 2086172334Smarius bus_write_4(sc->sc_res[0], GEM_MAC_XIF_CONFIG, v); 208799726Sbenno 2088172334Smarius if ((sc->sc_ifp->if_drv_flags & IFF_DRV_RUNNING) != 0 && 2089172334Smarius (sc->sc_flags & GEM_LINK) != 0) { 2090172334Smarius bus_write_4(sc->sc_res[0], GEM_MAC_TX_CONFIG, 2091172334Smarius txcfg | GEM_MAC_TX_ENABLE); 2092172334Smarius bus_write_4(sc->sc_res[0], GEM_MAC_RX_CONFIG, 2093172334Smarius rxcfg | GEM_MAC_RX_ENABLE); 209491398Stmm } 209591398Stmm} 209691398Stmm 209791398Stmmint 2098174987Smariusgem_mediachange(struct ifnet *ifp) 209991398Stmm{ 210091398Stmm struct gem_softc *sc = ifp->if_softc; 2101150285Smarius int error; 210291398Stmm 2103174987Smarius /* XXX add support for serial media. */ 210491398Stmm 2105150285Smarius GEM_LOCK(sc); 2106150285Smarius error = mii_mediachg(sc->sc_mii); 2107150285Smarius GEM_UNLOCK(sc); 2108150285Smarius return (error); 210991398Stmm} 211091398Stmm 211191398Stmmvoid 2112174987Smariusgem_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr) 211391398Stmm{ 211491398Stmm struct gem_softc *sc = ifp->if_softc; 211591398Stmm 2116148369Smarius GEM_LOCK(sc); 2117148369Smarius if ((ifp->if_flags & IFF_UP) == 0) { 2118148369Smarius GEM_UNLOCK(sc); 211991398Stmm return; 2120148369Smarius } 212191398Stmm 212291398Stmm mii_pollstat(sc->sc_mii); 212391398Stmm ifmr->ifm_active = sc->sc_mii->mii_media_active; 212491398Stmm ifmr->ifm_status = sc->sc_mii->mii_media_status; 2125148369Smarius GEM_UNLOCK(sc); 212691398Stmm} 212791398Stmm 212891398Stmmstatic int 2129174987Smariusgem_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 213091398Stmm{ 213191398Stmm struct gem_softc *sc = ifp->if_softc; 213291398Stmm struct ifreq *ifr = (struct ifreq *)data; 2133174987Smarius int error; 213491398Stmm 2135174987Smarius error = 0; 213691398Stmm switch (cmd) { 2137150285Smarius case SIOCSIFFLAGS: 2138148369Smarius GEM_LOCK(sc); 2139174987Smarius if ((ifp->if_flags & IFF_UP) != 0) { 2140172334Smarius if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0 && 2141172334Smarius ((ifp->if_flags ^ sc->sc_ifflags) & 2142172334Smarius (IFF_ALLMULTI | IFF_PROMISC)) != 0) 214391398Stmm gem_setladrf(sc); 214491398Stmm else 2145148369Smarius gem_init_locked(sc); 2146174987Smarius } else if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) 2147174987Smarius gem_stop(ifp, 0); 2148170273Syongari if ((ifp->if_flags & IFF_LINK0) != 0) 2149170273Syongari sc->sc_csum_features |= CSUM_UDP; 2150170273Syongari else 2151170273Syongari sc->sc_csum_features &= ~CSUM_UDP; 2152170273Syongari if ((ifp->if_capenable & IFCAP_TXCSUM) != 0) 2153170273Syongari ifp->if_hwassist = sc->sc_csum_features; 215499726Sbenno sc->sc_ifflags = ifp->if_flags; 2155150285Smarius GEM_UNLOCK(sc); 215691398Stmm break; 215791398Stmm case SIOCADDMULTI: 215891398Stmm case SIOCDELMULTI: 2159150285Smarius GEM_LOCK(sc); 216091398Stmm gem_setladrf(sc); 2161150285Smarius GEM_UNLOCK(sc); 216291398Stmm break; 216391398Stmm case SIOCGIFMEDIA: 216491398Stmm case SIOCSIFMEDIA: 216591398Stmm error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii->mii_media, cmd); 216691398Stmm break; 2167170273Syongari case SIOCSIFCAP: 2168170273Syongari GEM_LOCK(sc); 2169170273Syongari ifp->if_capenable = ifr->ifr_reqcap; 2170170273Syongari if ((ifp->if_capenable & IFCAP_TXCSUM) != 0) 2171170273Syongari ifp->if_hwassist = sc->sc_csum_features; 2172170273Syongari else 2173170273Syongari ifp->if_hwassist = 0; 2174170273Syongari GEM_UNLOCK(sc); 2175170273Syongari break; 217691398Stmm default: 2177150285Smarius error = ether_ioctl(ifp, cmd, data); 217891398Stmm break; 217991398Stmm } 218091398Stmm 218191398Stmm return (error); 218291398Stmm} 218391398Stmm 218491398Stmmstatic void 2185174987Smariusgem_setladrf(struct gem_softc *sc) 218691398Stmm{ 2187147256Sbrooks struct ifnet *ifp = sc->sc_ifp; 218891398Stmm struct ifmultiaddr *inm; 218999726Sbenno int i; 2190174987Smarius uint32_t hash[16]; 2191174987Smarius uint32_t crc, v; 219291398Stmm 2193148369Smarius GEM_LOCK_ASSERT(sc, MA_OWNED); 2194148369Smarius 2195174987Smarius /* Get the current RX configuration. */ 2196169269Sphk v = bus_read_4(sc->sc_res[0], GEM_MAC_RX_CONFIG); 219791398Stmm 219899726Sbenno /* 219999726Sbenno * Turn off promiscuous mode, promiscuous group mode (all multicast), 220099726Sbenno * and hash filter. Depending on the case, the right bit will be 220199726Sbenno * enabled. 220299726Sbenno */ 2203174987Smarius v &= ~(GEM_MAC_RX_PROMISCUOUS | GEM_MAC_RX_HASH_FILTER | 220499726Sbenno GEM_MAC_RX_PROMISC_GRP); 220599726Sbenno 2206172334Smarius bus_write_4(sc->sc_res[0], GEM_MAC_RX_CONFIG, v); 2207172334Smarius bus_barrier(sc->sc_res[0], GEM_MAC_RX_CONFIG, 4, 2208172334Smarius BUS_SPACE_BARRIER_WRITE); 2209172334Smarius if (!gem_bitwait(sc, GEM_MAC_RX_CONFIG, GEM_MAC_RX_HASH_FILTER, 0)) 2210172334Smarius device_printf(sc->sc_dev, "cannot disable RX hash filter\n"); 2211172334Smarius 221291398Stmm if ((ifp->if_flags & IFF_PROMISC) != 0) { 221391398Stmm v |= GEM_MAC_RX_PROMISCUOUS; 221491398Stmm goto chipit; 221591398Stmm } 221691398Stmm if ((ifp->if_flags & IFF_ALLMULTI) != 0) { 221799726Sbenno v |= GEM_MAC_RX_PROMISC_GRP; 221891398Stmm goto chipit; 221991398Stmm } 222091398Stmm 222191398Stmm /* 2222174987Smarius * Set up multicast address filter by passing all multicast 2223174987Smarius * addresses through a crc generator, and then using the high 2224174987Smarius * order 8 bits as an index into the 256 bit logical address 2225174987Smarius * filter. The high order 4 bits selects the word, while the 2226174987Smarius * other 4 bits select the bit within the word (where bit 0 2227174987Smarius * is the MSB). 222891398Stmm */ 222991398Stmm 2230174987Smarius /* Clear the hash table. */ 223199726Sbenno memset(hash, 0, sizeof(hash)); 223299726Sbenno 2233148654Srwatson IF_ADDR_LOCK(ifp); 2234147256Sbrooks TAILQ_FOREACH(inm, &ifp->if_multiaddrs, ifma_link) { 223591398Stmm if (inm->ifma_addr->sa_family != AF_LINK) 223691398Stmm continue; 2237130288Smarius crc = ether_crc32_le(LLADDR((struct sockaddr_dl *) 2238130288Smarius inm->ifma_addr), ETHER_ADDR_LEN); 223991398Stmm 2240174987Smarius /* We just want the 8 most significant bits. */ 224191398Stmm crc >>= 24; 224291398Stmm 224391398Stmm /* Set the corresponding bit in the filter. */ 224499726Sbenno hash[crc >> 4] |= 1 << (15 - (crc & 15)); 224591398Stmm } 2246148654Srwatson IF_ADDR_UNLOCK(ifp); 224791398Stmm 224899726Sbenno v |= GEM_MAC_RX_HASH_FILTER; 224999726Sbenno 2250174987Smarius /* Now load the hash table into the chip (if we are using it). */ 2251174987Smarius for (i = 0; i < 16; i++) 2252169269Sphk bus_write_4(sc->sc_res[0], 2253174987Smarius GEM_MAC_HASH0 + i * (GEM_MAC_HASH1 - GEM_MAC_HASH0), 225499726Sbenno hash[i]); 225599726Sbenno 2256174987Smarius chipit: 2257169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_RX_CONFIG, v); 225891398Stmm} 2259