if_gem.c revision 175418
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 175418 2008-01-17 23:37:47Z jhb $"); 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 int gem_disable_rx(struct gem_softc *sc); 104174987Smariusstatic int gem_disable_tx(struct gem_softc *sc); 105174987Smariusstatic void gem_eint(struct gem_softc *sc, u_int status); 106174987Smariusstatic void gem_init(void *xsc); 107174987Smariusstatic void gem_init_locked(struct gem_softc *sc); 108174987Smariusstatic void gem_init_regs(struct gem_softc *sc); 109174987Smariusstatic int gem_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data); 110174987Smariusstatic int gem_load_txmbuf(struct gem_softc *sc, struct mbuf **m_head); 111174987Smariusstatic int gem_meminit(struct gem_softc *sc); 112174987Smariusstatic void gem_mifinit(struct gem_softc *sc); 113174987Smariusstatic void gem_reset(struct gem_softc *sc); 114174987Smariusstatic int gem_reset_rx(struct gem_softc *sc); 115172334Smariusstatic void gem_reset_rxdma(struct gem_softc *sc); 116174987Smariusstatic int gem_reset_tx(struct gem_softc *sc); 117174987Smariusstatic u_int gem_ringsize(u_int sz); 118174987Smariusstatic void gem_rint(struct gem_softc *sc); 119148368Smarius#ifdef GEM_RINT_TIMEOUT 120174987Smariusstatic void gem_rint_timeout(void *arg); 121100587Sjake#endif 122174987Smariusstatic __inline void gem_rxcksum(struct mbuf *m, uint64_t flags); 123174987Smariusstatic void gem_rxdrain(struct gem_softc *sc); 124174987Smariusstatic void gem_setladrf(struct gem_softc *sc); 125174987Smariusstatic void gem_start(struct ifnet *ifp); 126174987Smariusstatic void gem_start_locked(struct ifnet *ifp); 127174987Smariusstatic void gem_stop(struct ifnet *ifp, int disable); 128174987Smariusstatic void gem_tick(void *arg); 129174987Smariusstatic void gem_tint(struct gem_softc *sc); 130174987Smariusstatic __inline void gem_txcksum(struct gem_softc *sc, struct mbuf *m, 131174987Smarius uint64_t *cflags); 132174987Smariusstatic int gem_watchdog(struct gem_softc *sc); 13391398Stmm 13491398Stmmdevclass_t gem_devclass; 13591398StmmDRIVER_MODULE(miibus, gem, miibus_driver, miibus_devclass, 0, 0); 13691398StmmMODULE_DEPEND(gem, miibus, 1, 1, 1); 13791398Stmm 13891398Stmm#ifdef GEM_DEBUG 13991398Stmm#include <sys/ktr.h> 14091398Stmm#define KTR_GEM KTR_CT2 14191398Stmm#endif 14291398Stmm 14391398Stmmint 144174987Smariusgem_attach(struct gem_softc *sc) 14591398Stmm{ 146174987Smarius struct gem_txsoft *txs; 147147256Sbrooks struct ifnet *ifp; 148174987Smarius int error, i; 149174987Smarius uint32_t v; 15091398Stmm 151147256Sbrooks ifp = sc->sc_ifp = if_alloc(IFT_ETHER); 152147256Sbrooks if (ifp == NULL) 153147256Sbrooks return (ENOSPC); 154147256Sbrooks 155150285Smarius callout_init_mtx(&sc->sc_tick_ch, &sc->sc_mtx, 0); 156150285Smarius#ifdef GEM_RINT_TIMEOUT 157150285Smarius callout_init_mtx(&sc->sc_rx_ch, &sc->sc_mtx, 0); 158150285Smarius#endif 159150285Smarius 16091398Stmm /* Make sure the chip is stopped. */ 16191398Stmm ifp->if_softc = sc; 16291398Stmm gem_reset(sc); 16391398Stmm 164161928Sjmg error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), 1, 0, 165161928Sjmg BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, 166174987Smarius BUS_SPACE_MAXSIZE_32BIT, 0, BUS_SPACE_MAXSIZE_32BIT, 0, NULL, 167174987Smarius NULL, &sc->sc_pdmatag); 16891398Stmm if (error) 169147256Sbrooks goto fail_ifnet; 17091398Stmm 17191398Stmm error = bus_dma_tag_create(sc->sc_pdmatag, 1, 0, 172170273Syongari BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, MCLBYTES, 173170273Syongari 1, MCLBYTES, BUS_DMA_ALLOCNOW, NULL, NULL, &sc->sc_rdmatag); 17491398Stmm if (error) 175108832Stmm goto fail_ptag; 17691398Stmm 177108832Stmm error = bus_dma_tag_create(sc->sc_pdmatag, 1, 0, 178170273Syongari BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, 179170273Syongari MCLBYTES * GEM_NTXSEGS, GEM_NTXSEGS, MCLBYTES, 180117126Sscottl BUS_DMA_ALLOCNOW, NULL, NULL, &sc->sc_tdmatag); 181108832Stmm if (error) 182108832Stmm goto fail_rtag; 183108832Stmm 18491398Stmm error = bus_dma_tag_create(sc->sc_pdmatag, PAGE_SIZE, 0, 185170273Syongari BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, 18691398Stmm sizeof(struct gem_control_data), 1, 187170273Syongari sizeof(struct gem_control_data), 0, 188170273Syongari NULL, NULL, &sc->sc_cdmatag); 18991398Stmm if (error) 190108832Stmm goto fail_ttag; 19191398Stmm 19291398Stmm /* 193174987Smarius * Allocate the control data structures, create and load the 19491398Stmm * DMA map for it. 19591398Stmm */ 19691398Stmm if ((error = bus_dmamem_alloc(sc->sc_cdmatag, 197170273Syongari (void **)&sc->sc_control_data, 198170273Syongari BUS_DMA_WAITOK | BUS_DMA_COHERENT | BUS_DMA_ZERO, 199170273Syongari &sc->sc_cddmamap))) { 200174987Smarius device_printf(sc->sc_dev, 201174987Smarius "unable to allocate control data, error = %d\n", error); 202108832Stmm goto fail_ctag; 20391398Stmm } 20491398Stmm 20591398Stmm sc->sc_cddma = 0; 20691398Stmm if ((error = bus_dmamap_load(sc->sc_cdmatag, sc->sc_cddmamap, 20791398Stmm sc->sc_control_data, sizeof(struct gem_control_data), 20891398Stmm gem_cddma_callback, sc, 0)) != 0 || sc->sc_cddma == 0) { 209174987Smarius device_printf(sc->sc_dev, 210174987Smarius "unable to load control data DMA map, error = %d\n", 211174987Smarius error); 212108832Stmm goto fail_cmem; 21391398Stmm } 21491398Stmm 21591398Stmm /* 21691398Stmm * Initialize the transmit job descriptors. 21791398Stmm */ 21891398Stmm STAILQ_INIT(&sc->sc_txfreeq); 21991398Stmm STAILQ_INIT(&sc->sc_txdirtyq); 22091398Stmm 22191398Stmm /* 22291398Stmm * Create the transmit buffer DMA maps. 22391398Stmm */ 22491398Stmm error = ENOMEM; 22591398Stmm for (i = 0; i < GEM_TXQUEUELEN; i++) { 22691398Stmm txs = &sc->sc_txsoft[i]; 22791398Stmm txs->txs_mbuf = NULL; 22891398Stmm txs->txs_ndescs = 0; 229108832Stmm if ((error = bus_dmamap_create(sc->sc_tdmatag, 0, 23091398Stmm &txs->txs_dmamap)) != 0) { 231174987Smarius device_printf(sc->sc_dev, 232174987Smarius "unable to create TX DMA map %d, error = %d\n", 233174987Smarius i, error); 234108832Stmm goto fail_txd; 23591398Stmm } 23691398Stmm STAILQ_INSERT_TAIL(&sc->sc_txfreeq, txs, txs_q); 23791398Stmm } 23891398Stmm 23991398Stmm /* 24091398Stmm * Create the receive buffer DMA maps. 24191398Stmm */ 24291398Stmm for (i = 0; i < GEM_NRXDESC; i++) { 243108832Stmm if ((error = bus_dmamap_create(sc->sc_rdmatag, 0, 24491398Stmm &sc->sc_rxsoft[i].rxs_dmamap)) != 0) { 245174987Smarius device_printf(sc->sc_dev, 246174987Smarius "unable to create RX DMA map %d, error = %d\n", 247174987Smarius i, error); 248108832Stmm goto fail_rxd; 24991398Stmm } 25091398Stmm sc->sc_rxsoft[i].rxs_mbuf = NULL; 25191398Stmm } 25291398Stmm 253172334Smarius /* Bad things will happen when touching this register on ERI. */ 254172334Smarius if (sc->sc_variant != GEM_SUN_ERI) 255172334Smarius bus_write_4(sc->sc_res[0], GEM_MII_DATAPATH_MODE, 256172334Smarius GEM_MII_DATAPATH_MII); 257172334Smarius 25891398Stmm gem_mifinit(sc); 25991398Stmm 260172334Smarius /* 261172334Smarius * Look for an external PHY. 262172334Smarius */ 263172334Smarius error = ENXIO; 264172334Smarius v = bus_read_4(sc->sc_res[0], GEM_MIF_CONFIG); 265172334Smarius if ((v & GEM_MIF_CONFIG_MDI1) != 0) { 266172334Smarius v |= GEM_MIF_CONFIG_PHY_SEL; 267172334Smarius bus_write_4(sc->sc_res[0], GEM_MIF_CONFIG, v); 268172334Smarius switch (sc->sc_variant) { 269172334Smarius case GEM_SUN_ERI: 270172334Smarius sc->sc_phyad = GEM_PHYAD_EXTERNAL; 271172334Smarius break; 272172334Smarius default: 273172334Smarius sc->sc_phyad = -1; 274172334Smarius break; 275172334Smarius } 276172334Smarius error = mii_phy_probe(sc->sc_dev, &sc->sc_miibus, 277172334Smarius gem_mediachange, gem_mediastatus); 278172334Smarius } 279172334Smarius 280172334Smarius /* 281172334Smarius * Fall back on an internal PHY if no external PHY was found. 282172334Smarius */ 283172334Smarius if (error != 0 && (v & GEM_MIF_CONFIG_MDI0) != 0) { 284172334Smarius v &= ~GEM_MIF_CONFIG_PHY_SEL; 285172334Smarius bus_write_4(sc->sc_res[0], GEM_MIF_CONFIG, v); 286172334Smarius switch (sc->sc_variant) { 287172334Smarius case GEM_SUN_ERI: 288172334Smarius case GEM_APPLE_K2_GMAC: 289172334Smarius sc->sc_phyad = GEM_PHYAD_INTERNAL; 290172334Smarius break; 291172334Smarius case GEM_APPLE_GMAC: 292172334Smarius sc->sc_phyad = GEM_PHYAD_EXTERNAL; 293172334Smarius break; 294172334Smarius default: 295172334Smarius sc->sc_phyad = -1; 296172334Smarius break; 297172334Smarius } 298172334Smarius error = mii_phy_probe(sc->sc_dev, &sc->sc_miibus, 299172334Smarius gem_mediachange, gem_mediastatus); 300172334Smarius } 301172334Smarius 302172334Smarius /* 303172334Smarius * Try the external PCS SERDES if we didn't find any PHYs. 304172334Smarius */ 305172334Smarius if (error != 0 && sc->sc_variant == GEM_SUN_GEM) { 306172334Smarius bus_write_4(sc->sc_res[0], GEM_MII_DATAPATH_MODE, 307172334Smarius GEM_MII_DATAPATH_SERDES); 308172334Smarius bus_write_4(sc->sc_res[0], GEM_MII_SLINK_CONTROL, 309172334Smarius GEM_MII_SLINK_LOOPBACK | GEM_MII_SLINK_EN_SYNC_D); 310172334Smarius bus_write_4(sc->sc_res[0], GEM_MII_CONFIG, 311172334Smarius GEM_MII_CONFIG_ENABLE); 312172334Smarius sc->sc_flags |= GEM_SERDES; 313172334Smarius sc->sc_phyad = GEM_PHYAD_EXTERNAL; 314172334Smarius error = mii_phy_probe(sc->sc_dev, &sc->sc_miibus, 315172334Smarius gem_mediachange, gem_mediastatus); 316172334Smarius } 317172334Smarius 318172334Smarius if (error != 0) { 319172334Smarius device_printf(sc->sc_dev, "PHY probe failed: %d\n", error); 320108832Stmm goto fail_rxd; 32191398Stmm } 32291398Stmm sc->sc_mii = device_get_softc(sc->sc_miibus); 32391398Stmm 32491398Stmm /* 32591398Stmm * From this point forward, the attachment cannot fail. A failure 32691398Stmm * before this point releases all resources that may have been 32791398Stmm * allocated. 32891398Stmm */ 32991398Stmm 33099726Sbenno /* Get RX FIFO size */ 33199726Sbenno sc->sc_rxfifosize = 64 * 332169269Sphk bus_read_4(sc->sc_res[0], GEM_RX_FIFO_SIZE); 33399726Sbenno 33499726Sbenno /* Get TX FIFO size */ 335169269Sphk v = bus_read_4(sc->sc_res[0], GEM_TX_FIFO_SIZE); 336128588Stmm device_printf(sc->sc_dev, "%ukB RX FIFO, %ukB TX FIFO\n", 337128588Stmm sc->sc_rxfifosize / 1024, v / 16); 33899726Sbenno 339170273Syongari sc->sc_csum_features = GEM_CSUM_FEATURES; 34091398Stmm /* Initialize ifnet structure. */ 34191398Stmm ifp->if_softc = sc; 342121816Sbrooks if_initname(ifp, device_get_name(sc->sc_dev), 343121816Sbrooks device_get_unit(sc->sc_dev)); 344148369Smarius ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 34591398Stmm ifp->if_start = gem_start; 34691398Stmm ifp->if_ioctl = gem_ioctl; 34791398Stmm ifp->if_init = gem_init; 348170273Syongari IFQ_SET_MAXLEN(&ifp->if_snd, GEM_TXQUEUELEN); 349170273Syongari ifp->if_snd.ifq_drv_maxlen = GEM_TXQUEUELEN; 350170273Syongari IFQ_SET_READY(&ifp->if_snd); 35191398Stmm 35291398Stmm /* Attach the interface. */ 353147256Sbrooks ether_ifattach(ifp, sc->sc_enaddr); 35491398Stmm 35591398Stmm /* 356170273Syongari * Tell the upper layer(s) we support long frames/checksum offloads. 357149552Smarius */ 358149552Smarius ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header); 359170273Syongari ifp->if_capabilities |= IFCAP_VLAN_MTU | IFCAP_HWCSUM; 360170273Syongari ifp->if_hwassist |= sc->sc_csum_features; 361170273Syongari ifp->if_capenable |= IFCAP_VLAN_MTU | IFCAP_HWCSUM; 362149552Smarius 36391398Stmm return (0); 36491398Stmm 36591398Stmm /* 36691398Stmm * Free any resources we've allocated during the failed attach 36791398Stmm * attempt. Do this in reverse order and fall through. 36891398Stmm */ 369174987Smarius fail_rxd: 370174987Smarius for (i = 0; i < GEM_NRXDESC; i++) 37191398Stmm if (sc->sc_rxsoft[i].rxs_dmamap != NULL) 372108832Stmm bus_dmamap_destroy(sc->sc_rdmatag, 37391398Stmm sc->sc_rxsoft[i].rxs_dmamap); 374174987Smarius fail_txd: 375174987Smarius for (i = 0; i < GEM_TXQUEUELEN; i++) 37691398Stmm if (sc->sc_txsoft[i].txs_dmamap != NULL) 377108832Stmm bus_dmamap_destroy(sc->sc_tdmatag, 37891398Stmm sc->sc_txsoft[i].txs_dmamap); 379108832Stmm bus_dmamap_unload(sc->sc_cdmatag, sc->sc_cddmamap); 380174987Smarius fail_cmem: 38191398Stmm bus_dmamem_free(sc->sc_cdmatag, sc->sc_control_data, 38291398Stmm sc->sc_cddmamap); 383174987Smarius fail_ctag: 38491398Stmm bus_dma_tag_destroy(sc->sc_cdmatag); 385174987Smarius fail_ttag: 386108832Stmm bus_dma_tag_destroy(sc->sc_tdmatag); 387174987Smarius fail_rtag: 388108832Stmm bus_dma_tag_destroy(sc->sc_rdmatag); 389174987Smarius fail_ptag: 39091398Stmm bus_dma_tag_destroy(sc->sc_pdmatag); 391174987Smarius fail_ifnet: 392147256Sbrooks if_free(ifp); 39391398Stmm return (error); 39491398Stmm} 39591398Stmm 396108964Stmmvoid 397174987Smariusgem_detach(struct gem_softc *sc) 398108964Stmm{ 399147256Sbrooks struct ifnet *ifp = sc->sc_ifp; 400108964Stmm int i; 401108964Stmm 402148369Smarius GEM_LOCK(sc); 403147317Sbrooks gem_stop(ifp, 1); 404148369Smarius GEM_UNLOCK(sc); 405150285Smarius callout_drain(&sc->sc_tick_ch); 406150285Smarius#ifdef GEM_RINT_TIMEOUT 407150285Smarius callout_drain(&sc->sc_rx_ch); 408150285Smarius#endif 409108964Stmm ether_ifdetach(ifp); 410147256Sbrooks if_free(ifp); 411108964Stmm device_delete_child(sc->sc_dev, sc->sc_miibus); 412108964Stmm 413174987Smarius for (i = 0; i < GEM_NRXDESC; i++) 414108964Stmm if (sc->sc_rxsoft[i].rxs_dmamap != NULL) 415108964Stmm bus_dmamap_destroy(sc->sc_rdmatag, 416108964Stmm sc->sc_rxsoft[i].rxs_dmamap); 417174987Smarius for (i = 0; i < GEM_TXQUEUELEN; i++) 418108964Stmm if (sc->sc_txsoft[i].txs_dmamap != NULL) 419108964Stmm bus_dmamap_destroy(sc->sc_tdmatag, 420108964Stmm sc->sc_txsoft[i].txs_dmamap); 421109648Stmm GEM_CDSYNC(sc, BUS_DMASYNC_POSTREAD); 422109648Stmm GEM_CDSYNC(sc, BUS_DMASYNC_POSTWRITE); 423108964Stmm bus_dmamap_unload(sc->sc_cdmatag, sc->sc_cddmamap); 424108964Stmm bus_dmamem_free(sc->sc_cdmatag, sc->sc_control_data, 425108964Stmm sc->sc_cddmamap); 426108964Stmm bus_dma_tag_destroy(sc->sc_cdmatag); 427108964Stmm bus_dma_tag_destroy(sc->sc_tdmatag); 428108964Stmm bus_dma_tag_destroy(sc->sc_rdmatag); 429108964Stmm bus_dma_tag_destroy(sc->sc_pdmatag); 430108964Stmm} 431108964Stmm 432108964Stmmvoid 433174987Smariusgem_suspend(struct gem_softc *sc) 434108964Stmm{ 435147256Sbrooks struct ifnet *ifp = sc->sc_ifp; 436108964Stmm 437148369Smarius GEM_LOCK(sc); 438108964Stmm gem_stop(ifp, 0); 439148369Smarius GEM_UNLOCK(sc); 440108964Stmm} 441108964Stmm 442108964Stmmvoid 443174987Smariusgem_resume(struct gem_softc *sc) 444108964Stmm{ 445147256Sbrooks struct ifnet *ifp = sc->sc_ifp; 446108964Stmm 447148369Smarius GEM_LOCK(sc); 448149552Smarius /* 449149552Smarius * On resume all registers have to be initialized again like 450149552Smarius * after power-on. 451149552Smarius */ 452172334Smarius sc->sc_flags &= ~GEM_INITED; 453108964Stmm if (ifp->if_flags & IFF_UP) 454148369Smarius gem_init_locked(sc); 455148369Smarius GEM_UNLOCK(sc); 456108964Stmm} 457108964Stmm 458170273Syongaristatic __inline void 459170273Syongarigem_txcksum(struct gem_softc *sc, struct mbuf *m, uint64_t *cflags) 460170273Syongari{ 461174987Smarius char *p; 462174987Smarius struct ip *ip; 463172607Syongari struct mbuf *m0; 464170273Syongari uint64_t offset, offset2; 465170273Syongari 466172607Syongari m0 = m; 467170273Syongari offset = sizeof(struct ip) + ETHER_HDR_LEN; 468170273Syongari for(; m && m->m_len == 0; m = m->m_next) 469170273Syongari ; 470170273Syongari if (m == NULL || m->m_len < ETHER_HDR_LEN) { 471170273Syongari device_printf(sc->sc_dev, "%s: m_len < ETHER_HDR_LEN\n", 472170273Syongari __func__); 473174987Smarius /* Checksum will be corrupted. */ 474172607Syongari m = m0; 475170273Syongari goto sendit; 476170273Syongari } 477170273Syongari if (m->m_len < ETHER_HDR_LEN + sizeof(uint32_t)) { 478170273Syongari if (m->m_len != ETHER_HDR_LEN) { 479170273Syongari device_printf(sc->sc_dev, 480170273Syongari "%s: m_len != ETHER_HDR_LEN\n", __func__); 481174987Smarius /* Checksum will be corrupted. */ 482172607Syongari m = m0; 483170273Syongari goto sendit; 484170273Syongari } 485170273Syongari for(m = m->m_next; m && m->m_len == 0; m = m->m_next) 486170273Syongari ; 487170273Syongari if (m == NULL) { 488174987Smarius /* Checksum will be corrupted. */ 489172607Syongari m = m0; 490170273Syongari goto sendit; 491170273Syongari } 492170273Syongari ip = mtod(m, struct ip *); 493170273Syongari } else { 494170273Syongari p = mtod(m, uint8_t *); 495170273Syongari p += ETHER_HDR_LEN; 496170273Syongari ip = (struct ip *)p; 497170273Syongari } 498170273Syongari offset = (ip->ip_hl << 2) + ETHER_HDR_LEN; 499170273Syongari 500174987Smarius sendit: 501170273Syongari offset2 = m->m_pkthdr.csum_data; 502170273Syongari *cflags = offset << GEM_TD_CXSUM_STARTSHFT; 503170273Syongari *cflags |= ((offset + offset2) << GEM_TD_CXSUM_STUFFSHFT); 504170273Syongari *cflags |= GEM_TD_CXSUM_ENABLE; 505170273Syongari} 506170273Syongari 507170273Syongaristatic __inline void 508170273Syongarigem_rxcksum(struct mbuf *m, uint64_t flags) 509170273Syongari{ 510170273Syongari struct ether_header *eh; 511170273Syongari struct ip *ip; 512170273Syongari struct udphdr *uh; 513174987Smarius uint16_t *opts; 514170273Syongari int32_t hlen, len, pktlen; 515170273Syongari uint32_t temp32; 516174987Smarius uint16_t cksum; 517170273Syongari 518170273Syongari pktlen = m->m_pkthdr.len; 519170273Syongari if (pktlen < sizeof(struct ether_header) + sizeof(struct ip)) 520170273Syongari return; 521170273Syongari eh = mtod(m, struct ether_header *); 522170273Syongari if (eh->ether_type != htons(ETHERTYPE_IP)) 523170273Syongari return; 524170273Syongari ip = (struct ip *)(eh + 1); 525170273Syongari if (ip->ip_v != IPVERSION) 526170273Syongari return; 527170273Syongari 528170273Syongari hlen = ip->ip_hl << 2; 529170273Syongari pktlen -= sizeof(struct ether_header); 530170273Syongari if (hlen < sizeof(struct ip)) 531170273Syongari return; 532170273Syongari if (ntohs(ip->ip_len) < hlen) 533170273Syongari return; 534170273Syongari if (ntohs(ip->ip_len) != pktlen) 535170273Syongari return; 536170273Syongari if (ip->ip_off & htons(IP_MF | IP_OFFMASK)) 537174987Smarius return; /* Cannot handle fragmented packet. */ 538170273Syongari 539170273Syongari switch (ip->ip_p) { 540170273Syongari case IPPROTO_TCP: 541170273Syongari if (pktlen < (hlen + sizeof(struct tcphdr))) 542170273Syongari return; 543170273Syongari break; 544170273Syongari case IPPROTO_UDP: 545170273Syongari if (pktlen < (hlen + sizeof(struct udphdr))) 546170273Syongari return; 547170273Syongari uh = (struct udphdr *)((uint8_t *)ip + hlen); 548170273Syongari if (uh->uh_sum == 0) 549170273Syongari return; /* no checksum */ 550170273Syongari break; 551170273Syongari default: 552170273Syongari return; 553170273Syongari } 554170273Syongari 555170273Syongari cksum = ~(flags & GEM_RD_CHECKSUM); 556170273Syongari /* checksum fixup for IP options */ 557170273Syongari len = hlen - sizeof(struct ip); 558170273Syongari if (len > 0) { 559170273Syongari opts = (uint16_t *)(ip + 1); 560170273Syongari for (; len > 0; len -= sizeof(uint16_t), opts++) { 561170273Syongari temp32 = cksum - *opts; 562170273Syongari temp32 = (temp32 >> 16) + (temp32 & 65535); 563170273Syongari cksum = temp32 & 65535; 564170273Syongari } 565170273Syongari } 566170273Syongari m->m_pkthdr.csum_flags |= CSUM_DATA_VALID; 567170273Syongari m->m_pkthdr.csum_data = cksum; 568170273Syongari} 569170273Syongari 57091398Stmmstatic void 571174987Smariusgem_cddma_callback(void *xsc, bus_dma_segment_t *segs, int nsegs, int error) 57291398Stmm{ 573174987Smarius struct gem_softc *sc = xsc; 57491398Stmm 57591398Stmm if (error != 0) 57691398Stmm return; 577174987Smarius if (nsegs != 1) 578172334Smarius panic("%s: bad control buffer segment count", __func__); 57991398Stmm sc->sc_cddma = segs[0].ds_addr; 58091398Stmm} 58191398Stmm 58291398Stmmstatic void 583174987Smariusgem_tick(void *arg) 58491398Stmm{ 585170273Syongari struct gem_softc *sc = arg; 586170273Syongari struct ifnet *ifp; 58791398Stmm 588170273Syongari GEM_LOCK_ASSERT(sc, MA_OWNED); 589170273Syongari 590170273Syongari ifp = sc->sc_ifp; 591108832Stmm /* 592174987Smarius * Unload collision counters. 593108832Stmm */ 594170273Syongari ifp->if_collisions += 595170273Syongari bus_read_4(sc->sc_res[0], GEM_MAC_NORM_COLL_CNT) + 596170273Syongari bus_read_4(sc->sc_res[0], GEM_MAC_FIRST_COLL_CNT) + 597170273Syongari bus_read_4(sc->sc_res[0], GEM_MAC_EXCESS_COLL_CNT) + 598170273Syongari bus_read_4(sc->sc_res[0], GEM_MAC_LATE_COLL_CNT); 59991398Stmm 60091398Stmm /* 601170273Syongari * then clear the hardware counters. 60291398Stmm */ 603170273Syongari bus_write_4(sc->sc_res[0], GEM_MAC_NORM_COLL_CNT, 0); 604170273Syongari bus_write_4(sc->sc_res[0], GEM_MAC_FIRST_COLL_CNT, 0); 605170273Syongari bus_write_4(sc->sc_res[0], GEM_MAC_EXCESS_COLL_CNT, 0); 606170273Syongari bus_write_4(sc->sc_res[0], GEM_MAC_LATE_COLL_CNT, 0); 607108832Stmm 60891398Stmm mii_tick(sc->sc_mii); 60991398Stmm 610164931Smarius if (gem_watchdog(sc) == EJUSTRETURN) 611164931Smarius return; 612164931Smarius 61391398Stmm callout_reset(&sc->sc_tick_ch, hz, gem_tick, sc); 61491398Stmm} 61591398Stmm 61691398Stmmstatic int 617174987Smariusgem_bitwait(struct gem_softc *sc, bus_addr_t r, uint32_t clr, uint32_t set) 61891398Stmm{ 61991398Stmm int i; 620174987Smarius uint32_t reg; 62191398Stmm 62291398Stmm for (i = TRIES; i--; DELAY(100)) { 623169269Sphk reg = bus_read_4(sc->sc_res[0], r); 624170847Smarius if ((reg & clr) == 0 && (reg & set) == set) 62591398Stmm return (1); 62691398Stmm } 62791398Stmm return (0); 62891398Stmm} 62991398Stmm 630172334Smariusstatic void 63191398Stmmgem_reset(sc) 63291398Stmm struct gem_softc *sc; 63391398Stmm{ 63491398Stmm 635115030Stmm#ifdef GEM_DEBUG 636170273Syongari CTR2(KTR_GEM, "%s: %s", device_get_name(sc->sc_dev), __func__); 637115030Stmm#endif 63891398Stmm gem_reset_rx(sc); 63991398Stmm gem_reset_tx(sc); 64091398Stmm 641174987Smarius /* Do a full reset. */ 642169269Sphk bus_write_4(sc->sc_res[0], GEM_RESET, GEM_RESET_RX | GEM_RESET_TX); 643172334Smarius bus_barrier(sc->sc_res[0], GEM_RESET, 4, BUS_SPACE_BARRIER_WRITE); 64491398Stmm if (!gem_bitwait(sc, GEM_RESET, GEM_RESET_RX | GEM_RESET_TX, 0)) 64591398Stmm device_printf(sc->sc_dev, "cannot reset device\n"); 64691398Stmm} 64791398Stmm 64891398Stmmstatic void 649174987Smariusgem_rxdrain(struct gem_softc *sc) 65091398Stmm{ 65191398Stmm struct gem_rxsoft *rxs; 65291398Stmm int i; 65391398Stmm 65491398Stmm for (i = 0; i < GEM_NRXDESC; i++) { 65591398Stmm rxs = &sc->sc_rxsoft[i]; 65691398Stmm if (rxs->rxs_mbuf != NULL) { 657109648Stmm bus_dmamap_sync(sc->sc_rdmatag, rxs->rxs_dmamap, 658109648Stmm BUS_DMASYNC_POSTREAD); 659108832Stmm bus_dmamap_unload(sc->sc_rdmatag, rxs->rxs_dmamap); 66091398Stmm m_freem(rxs->rxs_mbuf); 66191398Stmm rxs->rxs_mbuf = NULL; 66291398Stmm } 66391398Stmm } 66491398Stmm} 66591398Stmm 66691398Stmmstatic void 667174987Smariusgem_stop(struct ifnet *ifp, int disable) 66891398Stmm{ 669174987Smarius struct gem_softc *sc = ifp->if_softc; 67091398Stmm struct gem_txsoft *txs; 67191398Stmm 672115030Stmm#ifdef GEM_DEBUG 673170273Syongari CTR2(KTR_GEM, "%s: %s", device_get_name(sc->sc_dev), __func__); 674115030Stmm#endif 67591398Stmm 67691398Stmm callout_stop(&sc->sc_tick_ch); 677150285Smarius#ifdef GEM_RINT_TIMEOUT 678150285Smarius callout_stop(&sc->sc_rx_ch); 679172334Smarius#endif 68091398Stmm 681174987Smarius /* XXX should we reset these instead? */ 68291398Stmm gem_disable_tx(sc); 68391398Stmm gem_disable_rx(sc); 68491398Stmm 68591398Stmm /* 68691398Stmm * Release any queued transmit buffers. 68791398Stmm */ 68891398Stmm while ((txs = STAILQ_FIRST(&sc->sc_txdirtyq)) != NULL) { 68991398Stmm STAILQ_REMOVE_HEAD(&sc->sc_txdirtyq, txs_q); 69091398Stmm if (txs->txs_ndescs != 0) { 691109648Stmm bus_dmamap_sync(sc->sc_tdmatag, txs->txs_dmamap, 692109648Stmm BUS_DMASYNC_POSTWRITE); 693108832Stmm bus_dmamap_unload(sc->sc_tdmatag, txs->txs_dmamap); 69491398Stmm if (txs->txs_mbuf != NULL) { 69591398Stmm m_freem(txs->txs_mbuf); 69691398Stmm txs->txs_mbuf = NULL; 69791398Stmm } 69891398Stmm } 69991398Stmm STAILQ_INSERT_TAIL(&sc->sc_txfreeq, txs, txs_q); 70091398Stmm } 70191398Stmm 70291398Stmm if (disable) 70391398Stmm gem_rxdrain(sc); 70491398Stmm 70591398Stmm /* 70691398Stmm * Mark the interface down and cancel the watchdog timer. 70791398Stmm */ 708148887Srwatson ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); 709172334Smarius sc->sc_flags &= ~GEM_LINK; 710164931Smarius sc->sc_wdog_timer = 0; 71191398Stmm} 71291398Stmm 713172334Smariusstatic int 714174987Smariusgem_reset_rx(struct gem_softc *sc) 71591398Stmm{ 71691398Stmm 71791398Stmm /* 71891398Stmm * Resetting while DMA is in progress can cause a bus hang, so we 71991398Stmm * disable DMA first. 72091398Stmm */ 72191398Stmm gem_disable_rx(sc); 722169269Sphk bus_write_4(sc->sc_res[0], GEM_RX_CONFIG, 0); 723172334Smarius bus_barrier(sc->sc_res[0], GEM_RX_CONFIG, 4, BUS_SPACE_BARRIER_WRITE); 724172334Smarius if (!gem_bitwait(sc, GEM_RX_CONFIG, GEM_RX_CONFIG_RXDMA_EN, 0)) 725172334Smarius device_printf(sc->sc_dev, "cannot disable RX DMA\n"); 72691398Stmm 72791398Stmm /* Finally, reset the ERX */ 728169269Sphk bus_write_4(sc->sc_res[0], GEM_RESET, GEM_RESET_RX); 729172334Smarius bus_barrier(sc->sc_res[0], GEM_RESET, 4, BUS_SPACE_BARRIER_WRITE); 730172334Smarius if (!gem_bitwait(sc, GEM_RESET, GEM_RESET_RX | GEM_RESET_TX, 0)) { 73191398Stmm device_printf(sc->sc_dev, "cannot reset receiver\n"); 73291398Stmm return (1); 73391398Stmm } 73491398Stmm return (0); 73591398Stmm} 73691398Stmm 737172334Smarius/* 738172334Smarius * Reset the receiver DMA engine. 739172334Smarius * 740172334Smarius * Intended to be used in case of GEM_INTR_RX_TAG_ERR, GEM_MAC_RX_OVERFLOW 741172334Smarius * etc in order to reset the receiver DMA engine only and not do a full 742172334Smarius * reset which amongst others also downs the link and clears the FIFOs. 743172334Smarius */ 744172334Smariusstatic void 745172334Smariusgem_reset_rxdma(struct gem_softc *sc) 746172334Smarius{ 747172334Smarius int i; 74891398Stmm 749172334Smarius if (gem_reset_rx(sc) != 0) 750172334Smarius return (gem_init_locked(sc)); 751172334Smarius for (i = 0; i < GEM_NRXDESC; i++) 752172334Smarius if (sc->sc_rxsoft[i].rxs_mbuf != NULL) 753172334Smarius GEM_UPDATE_RXDESC(sc, i); 754172334Smarius sc->sc_rxptr = 0; 755172334Smarius GEM_CDSYNC(sc, BUS_DMASYNC_PREWRITE); 756172334Smarius GEM_CDSYNC(sc, BUS_DMASYNC_PREREAD); 757172334Smarius 758172334Smarius /* NOTE: we use only 32-bit DMA addresses here. */ 759172334Smarius bus_write_4(sc->sc_res[0], GEM_RX_RING_PTR_HI, 0); 760172334Smarius bus_write_4(sc->sc_res[0], GEM_RX_RING_PTR_LO, GEM_CDRXADDR(sc, 0)); 761172334Smarius bus_write_4(sc->sc_res[0], GEM_RX_KICK, GEM_NRXDESC - 4); 762172334Smarius bus_write_4(sc->sc_res[0], GEM_RX_CONFIG, 763174987Smarius gem_ringsize(GEM_NRXDESC /* XXX */) | 764172334Smarius ((ETHER_HDR_LEN + sizeof(struct ip)) << 765172334Smarius GEM_RX_CONFIG_CXM_START_SHFT) | 766172334Smarius (GEM_THRSH_1024 << GEM_RX_CONFIG_FIFO_THRS_SHIFT) | 767172334Smarius (2 << GEM_RX_CONFIG_FBOFF_SHFT)); 768172334Smarius bus_write_4(sc->sc_res[0], GEM_RX_BLANKING, 769172334Smarius (6 << GEM_RX_BLANKING_TIME_SHIFT) | 6); 770172334Smarius bus_write_4(sc->sc_res[0], GEM_RX_PAUSE_THRESH, 771174987Smarius (3 * sc->sc_rxfifosize / 256) | 772174987Smarius ((sc->sc_rxfifosize / 256) << 12)); 773172334Smarius bus_write_4(sc->sc_res[0], GEM_RX_CONFIG, 774174987Smarius bus_read_4(sc->sc_res[0], GEM_RX_CONFIG) | 775174987Smarius GEM_RX_CONFIG_RXDMA_EN); 776172334Smarius bus_write_4(sc->sc_res[0], GEM_MAC_RX_MASK, 777172334Smarius GEM_MAC_RX_DONE | GEM_MAC_RX_FRAME_CNT); 778172334Smarius bus_write_4(sc->sc_res[0], GEM_MAC_RX_CONFIG, 779174987Smarius bus_read_4(sc->sc_res[0], GEM_MAC_RX_CONFIG) | 780174987Smarius GEM_MAC_RX_ENABLE); 781172334Smarius} 782172334Smarius 78391398Stmmstatic int 784174987Smariusgem_reset_tx(struct gem_softc *sc) 78591398Stmm{ 78691398Stmm 78791398Stmm /* 78891398Stmm * Resetting while DMA is in progress can cause a bus hang, so we 78991398Stmm * disable DMA first. 79091398Stmm */ 79191398Stmm gem_disable_tx(sc); 792169269Sphk bus_write_4(sc->sc_res[0], GEM_TX_CONFIG, 0); 793172334Smarius bus_barrier(sc->sc_res[0], GEM_TX_CONFIG, 4, BUS_SPACE_BARRIER_WRITE); 794172334Smarius if (!gem_bitwait(sc, GEM_TX_CONFIG, GEM_TX_CONFIG_TXDMA_EN, 0)) 795172334Smarius device_printf(sc->sc_dev, "cannot disable TX DMA\n"); 79691398Stmm 79791398Stmm /* Finally, reset the ETX */ 798169269Sphk bus_write_4(sc->sc_res[0], GEM_RESET, GEM_RESET_TX); 799172334Smarius bus_barrier(sc->sc_res[0], GEM_RESET, 4, BUS_SPACE_BARRIER_WRITE); 800172334Smarius if (!gem_bitwait(sc, GEM_RESET, GEM_RESET_RX | GEM_RESET_TX, 0)) { 801172334Smarius device_printf(sc->sc_dev, "cannot reset transmitter\n"); 80291398Stmm return (1); 80391398Stmm } 80491398Stmm return (0); 80591398Stmm} 80691398Stmm 80791398Stmmstatic int 808174987Smariusgem_disable_rx(struct gem_softc *sc) 80991398Stmm{ 810174987Smarius uint32_t cfg; 81191398Stmm 812169269Sphk cfg = bus_read_4(sc->sc_res[0], GEM_MAC_RX_CONFIG); 81391398Stmm cfg &= ~GEM_MAC_RX_ENABLE; 814169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_RX_CONFIG, cfg); 815172334Smarius bus_barrier(sc->sc_res[0], GEM_MAC_RX_CONFIG, 4, 816174987Smarius BUS_SPACE_BARRIER_WRITE); 81791398Stmm return (gem_bitwait(sc, GEM_MAC_RX_CONFIG, GEM_MAC_RX_ENABLE, 0)); 81891398Stmm} 81991398Stmm 82091398Stmm/* 82191398Stmm * disable transmitter. 82291398Stmm */ 82391398Stmmstatic int 824174987Smariusgem_disable_tx(struct gem_softc *sc) 82591398Stmm{ 826174987Smarius uint32_t cfg; 82791398Stmm 828169269Sphk cfg = bus_read_4(sc->sc_res[0], GEM_MAC_TX_CONFIG); 82991398Stmm cfg &= ~GEM_MAC_TX_ENABLE; 830169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_TX_CONFIG, cfg); 831172334Smarius bus_barrier(sc->sc_res[0], GEM_MAC_TX_CONFIG, 4, 832172334Smarius BUS_SPACE_BARRIER_WRITE); 83391398Stmm return (gem_bitwait(sc, GEM_MAC_TX_CONFIG, GEM_MAC_TX_ENABLE, 0)); 83491398Stmm} 83591398Stmm 83691398Stmmstatic int 83791398Stmmgem_meminit(sc) 83891398Stmm struct gem_softc *sc; 83991398Stmm{ 84091398Stmm struct gem_rxsoft *rxs; 841174987Smarius int error, i; 84291398Stmm 84391398Stmm /* 84491398Stmm * Initialize the transmit descriptor ring. 84591398Stmm */ 84691398Stmm for (i = 0; i < GEM_NTXDESC; i++) { 84791398Stmm sc->sc_txdescs[i].gd_flags = 0; 84891398Stmm sc->sc_txdescs[i].gd_addr = 0; 84991398Stmm } 850108832Stmm sc->sc_txfree = GEM_MAXTXFREE; 85191398Stmm sc->sc_txnext = 0; 85299726Sbenno sc->sc_txwin = 0; 85391398Stmm 85491398Stmm /* 85591398Stmm * Initialize the receive descriptor and receive job 85691398Stmm * descriptor rings. 85791398Stmm */ 85891398Stmm for (i = 0; i < GEM_NRXDESC; i++) { 85991398Stmm rxs = &sc->sc_rxsoft[i]; 86091398Stmm if (rxs->rxs_mbuf == NULL) { 86191398Stmm if ((error = gem_add_rxbuf(sc, i)) != 0) { 862174987Smarius device_printf(sc->sc_dev, 863174987Smarius "unable to allocate or map RX buffer %d, " 864174987Smarius "error = %d\n", i, error); 86591398Stmm /* 866174987Smarius * XXX we should attempt to run with fewer 867174987Smarius * receive buffers instead of just failing. 86891398Stmm */ 86991398Stmm gem_rxdrain(sc); 87091398Stmm return (1); 87191398Stmm } 87291398Stmm } else 87391398Stmm GEM_INIT_RXDESC(sc, i); 87491398Stmm } 87591398Stmm sc->sc_rxptr = 0; 876109648Stmm GEM_CDSYNC(sc, BUS_DMASYNC_PREWRITE); 877109648Stmm GEM_CDSYNC(sc, BUS_DMASYNC_PREREAD); 87891398Stmm 87991398Stmm return (0); 88091398Stmm} 88191398Stmm 882172334Smariusstatic u_int 883174987Smariusgem_ringsize(u_int sz) 88491398Stmm{ 88591398Stmm 88691398Stmm switch (sz) { 88791398Stmm case 32: 888172334Smarius return (GEM_RING_SZ_32); 88991398Stmm case 64: 890172334Smarius return (GEM_RING_SZ_64); 89191398Stmm case 128: 892172334Smarius return (GEM_RING_SZ_128); 89391398Stmm case 256: 894172334Smarius return (GEM_RING_SZ_256); 89591398Stmm case 512: 896172334Smarius return (GEM_RING_SZ_512); 89791398Stmm case 1024: 898172334Smarius return (GEM_RING_SZ_1024); 89991398Stmm case 2048: 900172334Smarius return (GEM_RING_SZ_2048); 90191398Stmm case 4096: 902172334Smarius return (GEM_RING_SZ_4096); 90391398Stmm case 8192: 904172334Smarius return (GEM_RING_SZ_8192); 90591398Stmm default: 906172334Smarius printf("%s: invalid ring size %d\n", __func__, sz); 907172334Smarius return (GEM_RING_SZ_32); 90891398Stmm } 90991398Stmm} 91091398Stmm 911148369Smariusstatic void 912174987Smariusgem_init(void *xsc) 913148369Smarius{ 914174987Smarius struct gem_softc *sc = xsc; 915148369Smarius 916148369Smarius GEM_LOCK(sc); 917148369Smarius gem_init_locked(sc); 918148369Smarius GEM_UNLOCK(sc); 919148369Smarius} 920148369Smarius 92191398Stmm/* 92291398Stmm * Initialization of interface; set up initialization block 92391398Stmm * and transmit/receive descriptor rings. 92491398Stmm */ 92591398Stmmstatic void 926174987Smariusgem_init_locked(struct gem_softc *sc) 92791398Stmm{ 928147256Sbrooks struct ifnet *ifp = sc->sc_ifp; 929174987Smarius uint32_t v; 93091398Stmm 931148369Smarius GEM_LOCK_ASSERT(sc, MA_OWNED); 93291398Stmm 933115030Stmm#ifdef GEM_DEBUG 934170273Syongari CTR2(KTR_GEM, "%s: %s: calling stop", device_get_name(sc->sc_dev), 935170273Syongari __func__); 936115030Stmm#endif 93791398Stmm /* 938174987Smarius * Initialization sequence. The numbered steps below correspond 93991398Stmm * to the sequence outlined in section 6.3.5.1 in the Ethernet 94091398Stmm * Channel Engine manual (part of the PCIO manual). 94191398Stmm * See also the STP2002-STQ document from Sun Microsystems. 94291398Stmm */ 94391398Stmm 944174987Smarius /* step 1 & 2. Reset the Ethernet Channel. */ 945147256Sbrooks gem_stop(sc->sc_ifp, 0); 94691398Stmm gem_reset(sc); 947115030Stmm#ifdef GEM_DEBUG 948170273Syongari CTR2(KTR_GEM, "%s: %s: restarting", device_get_name(sc->sc_dev), 949170273Syongari __func__); 950115030Stmm#endif 95191398Stmm 952174987Smarius /* Re-initialize the MIF. */ 95391398Stmm gem_mifinit(sc); 95491398Stmm 955174987Smarius /* step 3. Setup data structures in host memory. */ 956172334Smarius if (gem_meminit(sc) != 0) 957172334Smarius return; 95891398Stmm 959174987Smarius /* step 4. TX MAC registers & counters */ 96091398Stmm gem_init_regs(sc); 96191398Stmm 962174987Smarius /* step 5. RX MAC registers & counters */ 96391398Stmm gem_setladrf(sc); 96491398Stmm 965174987Smarius /* step 6 & 7. Program Descriptor Ring Base Addresses. */ 96691398Stmm /* NOTE: we use only 32-bit DMA addresses here. */ 967169269Sphk bus_write_4(sc->sc_res[0], GEM_TX_RING_PTR_HI, 0); 968169269Sphk bus_write_4(sc->sc_res[0], GEM_TX_RING_PTR_LO, GEM_CDTXADDR(sc, 0)); 96991398Stmm 970169269Sphk bus_write_4(sc->sc_res[0], GEM_RX_RING_PTR_HI, 0); 971169269Sphk bus_write_4(sc->sc_res[0], GEM_RX_RING_PTR_LO, GEM_CDRXADDR(sc, 0)); 972115030Stmm#ifdef GEM_DEBUG 973174987Smarius CTR3(KTR_GEM, "loading RX ring %lx, TX ring %lx, cddma %lx", 97491398Stmm GEM_CDRXADDR(sc, 0), GEM_CDTXADDR(sc, 0), sc->sc_cddma); 975115030Stmm#endif 97691398Stmm 977174987Smarius /* step 8. Global Configuration & Interrupt Mask */ 978169269Sphk bus_write_4(sc->sc_res[0], GEM_INTMASK, 979172334Smarius ~(GEM_INTR_TX_INTME | GEM_INTR_TX_EMPTY | GEM_INTR_RX_DONE | 980172334Smarius GEM_INTR_RX_NOBUF | GEM_INTR_RX_TAG_ERR | GEM_INTR_PERR | 981172334Smarius GEM_INTR_BERR 982172334Smarius#ifdef GEM_DEBUG 983172334Smarius | GEM_INTR_PCS | GEM_INTR_MIF 984172334Smarius#endif 985172334Smarius )); 986169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_RX_MASK, 987172334Smarius GEM_MAC_RX_DONE | GEM_MAC_RX_FRAME_CNT); 988172334Smarius bus_write_4(sc->sc_res[0], GEM_MAC_TX_MASK, 989172334Smarius GEM_MAC_TX_XMIT_DONE | GEM_MAC_TX_DEFER_EXP); 990172334Smarius#ifdef GEM_DEBUG 991172334Smarius bus_write_4(sc->sc_res[0], GEM_MAC_CONTROL_MASK, 992172334Smarius ~(GEM_MAC_PAUSED | GEM_MAC_PAUSE | GEM_MAC_RESUME)); 993172334Smarius#else 994172334Smarius bus_write_4(sc->sc_res[0], GEM_MAC_CONTROL_MASK, 995172334Smarius GEM_MAC_PAUSED | GEM_MAC_PAUSE | GEM_MAC_RESUME); 996172334Smarius#endif 99791398Stmm 998174987Smarius /* step 9. ETX Configuration: use mostly default values. */ 99991398Stmm 1000174987Smarius /* Enable DMA. */ 1001174987Smarius v = gem_ringsize(GEM_NTXDESC /* XXX */); 1002169269Sphk bus_write_4(sc->sc_res[0], GEM_TX_CONFIG, 1003174987Smarius v | GEM_TX_CONFIG_TXDMA_EN | 1004174987Smarius ((0x400 << 10) & GEM_TX_CONFIG_TXFIFO_TH)); 100591398Stmm 1006174987Smarius /* step 10. ERX Configuration */ 100791398Stmm 1008172334Smarius /* Encode Receive Descriptor ring size. */ 1009174987Smarius v = gem_ringsize(GEM_NRXDESC /* XXX */); 1010174987Smarius /* RX TCP/UDP checksum offset */ 1011170273Syongari v |= ((ETHER_HDR_LEN + sizeof(struct ip)) << 1012170273Syongari GEM_RX_CONFIG_CXM_START_SHFT); 101391398Stmm 1014174987Smarius /* Enable DMA. */ 1015169269Sphk bus_write_4(sc->sc_res[0], GEM_RX_CONFIG, 1016174987Smarius v | (GEM_THRSH_1024 << GEM_RX_CONFIG_FIFO_THRS_SHIFT) | 1017174987Smarius (2 << GEM_RX_CONFIG_FBOFF_SHFT) | GEM_RX_CONFIG_RXDMA_EN); 1018172334Smarius 1019172334Smarius bus_write_4(sc->sc_res[0], GEM_RX_BLANKING, 1020172334Smarius (6 << GEM_RX_BLANKING_TIME_SHIFT) | 6); 1021172334Smarius 102291398Stmm /* 102399726Sbenno * The following value is for an OFF Threshold of about 3/4 full 102499726Sbenno * and an ON Threshold of 1/4 full. 102591398Stmm */ 1026169269Sphk bus_write_4(sc->sc_res[0], GEM_RX_PAUSE_THRESH, 102799726Sbenno (3 * sc->sc_rxfifosize / 256) | 1028174987Smarius ((sc->sc_rxfifosize / 256) << 12)); 102991398Stmm 1030174987Smarius /* step 11. Configure Media. */ 103191398Stmm 1032174987Smarius /* step 12. RX_MAC Configuration Register */ 1033169269Sphk v = bus_read_4(sc->sc_res[0], GEM_MAC_RX_CONFIG); 1034172334Smarius v |= GEM_MAC_RX_STRIP_CRC; 1035172334Smarius bus_write_4(sc->sc_res[0], GEM_MAC_RX_CONFIG, 0); 1036172334Smarius bus_barrier(sc->sc_res[0], GEM_MAC_RX_CONFIG, 4, 1037172334Smarius BUS_SPACE_BARRIER_WRITE); 1038172334Smarius if (!gem_bitwait(sc, GEM_MAC_RX_CONFIG, GEM_MAC_RX_ENABLE, 0)) 1039172334Smarius device_printf(sc->sc_dev, "cannot disable RX MAC\n"); 1040169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_RX_CONFIG, v); 104191398Stmm 1042174987Smarius /* step 14. Issue Transmit Pending command. */ 104391398Stmm 1044174987Smarius /* step 15. Give the reciever a swift kick. */ 1045174987Smarius bus_write_4(sc->sc_res[0], GEM_RX_KICK, GEM_NRXDESC - 4); 104691398Stmm 1047172334Smarius ifp->if_drv_flags |= IFF_DRV_RUNNING; 1048172334Smarius ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 1049172334Smarius sc->sc_ifflags = ifp->if_flags; 1050172334Smarius 1051172334Smarius sc->sc_flags &= ~GEM_LINK; 1052172334Smarius mii_mediachg(sc->sc_mii); 1053172334Smarius 105491398Stmm /* Start the one second timer. */ 1055164931Smarius sc->sc_wdog_timer = 0; 105691398Stmm callout_reset(&sc->sc_tick_ch, hz, gem_tick, sc); 105791398Stmm} 105891398Stmm 105991398Stmmstatic int 1060174987Smariusgem_load_txmbuf(struct gem_softc *sc, struct mbuf **m_head) 106191398Stmm{ 1062174987Smarius bus_dma_segment_t txsegs[GEM_NTXSEGS]; 106391398Stmm struct gem_txsoft *txs; 1064170273Syongari struct mbuf *m; 1065174987Smarius uint64_t cflags, flags; 1066170273Syongari int error, nexttx, nsegs, seg; 106791398Stmm 1068108832Stmm /* Get a work queue entry. */ 1069108832Stmm if ((txs = STAILQ_FIRST(&sc->sc_txfreeq)) == NULL) { 1070108832Stmm /* Ran out of descriptors. */ 1071170273Syongari return (ENOBUFS); 1072108832Stmm } 1073170273Syongari error = bus_dmamap_load_mbuf_sg(sc->sc_tdmatag, txs->txs_dmamap, 1074170273Syongari *m_head, txsegs, &nsegs, BUS_DMA_NOWAIT); 1075170273Syongari if (error == EFBIG) { 1076175418Sjhb m = m_collapse(*m_head, M_DONTWAIT, GEM_NTXSEGS); 1077170273Syongari if (m == NULL) { 1078170273Syongari m_freem(*m_head); 1079170273Syongari *m_head = NULL; 1080170273Syongari return (ENOBUFS); 1081170273Syongari } 1082170273Syongari *m_head = m; 1083174987Smarius error = bus_dmamap_load_mbuf_sg(sc->sc_tdmatag, 1084174987Smarius txs->txs_dmamap, *m_head, txsegs, &nsegs, 1085174987Smarius BUS_DMA_NOWAIT); 1086170273Syongari if (error != 0) { 1087170273Syongari m_freem(*m_head); 1088170273Syongari *m_head = NULL; 1089170273Syongari return (error); 1090170273Syongari } 1091170273Syongari } else if (error != 0) 1092170273Syongari return (error); 1093170273Syongari if (nsegs == 0) { 1094170273Syongari m_freem(*m_head); 1095170273Syongari *m_head = NULL; 1096170273Syongari return (EIO); 1097170273Syongari } 1098170273Syongari 1099170273Syongari /* 1100170273Syongari * Ensure we have enough descriptors free to describe 1101170273Syongari * the packet. Note, we always reserve one descriptor 1102174987Smarius * at the end of the ring as a termination point, in 1103174987Smarius * order to prevent wrap-around. 1104170273Syongari */ 1105170273Syongari if (nsegs > sc->sc_txfree - 1) { 1106170273Syongari txs->txs_ndescs = 0; 1107170273Syongari bus_dmamap_unload(sc->sc_tdmatag, txs->txs_dmamap); 1108170273Syongari return (ENOBUFS); 1109170273Syongari } 1110170273Syongari 1111170273Syongari flags = cflags = 0; 1112170273Syongari if (((*m_head)->m_pkthdr.csum_flags & sc->sc_csum_features) != 0) 1113170273Syongari gem_txcksum(sc, *m_head, &cflags); 1114170273Syongari 1115170273Syongari txs->txs_ndescs = nsegs; 1116108832Stmm txs->txs_firstdesc = sc->sc_txnext; 1117170273Syongari nexttx = txs->txs_firstdesc; 1118170273Syongari for (seg = 0; seg < nsegs; seg++, nexttx = GEM_NEXTTX(nexttx)) { 1119172334Smarius#ifdef GEM_DEBUG 1120174987Smarius CTR6(KTR_GEM, 1121174987Smarius "%s: mapping seg %d (txd %d), len %lx, addr %#lx (%#lx)", 1122174987Smarius __func__, seg, nexttx, txsegs[seg].ds_len, 1123174987Smarius txsegs[seg].ds_addr, 1124170273Syongari GEM_DMA_WRITE(sc, txsegs[seg].ds_addr)); 1125170273Syongari#endif 1126170273Syongari sc->sc_txdescs[nexttx].gd_addr = 1127170273Syongari GEM_DMA_WRITE(sc, txsegs[seg].ds_addr); 1128170273Syongari KASSERT(txsegs[seg].ds_len < GEM_TD_BUFSIZE, 1129170273Syongari ("%s: segment size too large!", __func__)); 1130170273Syongari flags = txsegs[seg].ds_len & GEM_TD_BUFSIZE; 1131170273Syongari sc->sc_txdescs[nexttx].gd_flags = 1132170273Syongari GEM_DMA_WRITE(sc, flags | cflags); 1133170273Syongari txs->txs_lastdesc = nexttx; 113491398Stmm } 113591398Stmm 1136174987Smarius /* Set EOP on the last descriptor. */ 1137172334Smarius#ifdef GEM_DEBUG 1138174987Smarius CTR3(KTR_GEM, "%s: end of packet at segment %d, TX %d", 1139174987Smarius __func__, seg, nexttx); 1140170273Syongari#endif 1141170273Syongari sc->sc_txdescs[txs->txs_lastdesc].gd_flags |= 1142170273Syongari GEM_DMA_WRITE(sc, GEM_TD_END_OF_PACKET); 1143170273Syongari 1144174987Smarius /* Lastly set SOP on the first descriptor. */ 1145172334Smarius#ifdef GEM_DEBUG 1146174987Smarius CTR3(KTR_GEM, "%s: start of packet at segment %d, TX %d", 1147174987Smarius __func__, seg, nexttx); 1148170273Syongari#endif 1149170273Syongari if (++sc->sc_txwin > GEM_NTXSEGS * 2 / 3) { 1150170273Syongari sc->sc_txwin = 0; 1151170273Syongari flags |= GEM_TD_INTERRUPT_ME; 1152170273Syongari sc->sc_txdescs[txs->txs_firstdesc].gd_flags |= 1153170273Syongari GEM_DMA_WRITE(sc, GEM_TD_INTERRUPT_ME | 1154170273Syongari GEM_TD_START_OF_PACKET); 1155170273Syongari } else 1156170273Syongari sc->sc_txdescs[txs->txs_firstdesc].gd_flags |= 1157170273Syongari GEM_DMA_WRITE(sc, GEM_TD_START_OF_PACKET); 1158170273Syongari 1159108832Stmm /* Sync the DMA map. */ 1160174987Smarius bus_dmamap_sync(sc->sc_tdmatag, txs->txs_dmamap, 1161174987Smarius BUS_DMASYNC_PREWRITE); 116291398Stmm 1163115030Stmm#ifdef GEM_DEBUG 1164170273Syongari CTR4(KTR_GEM, "%s: setting firstdesc=%d, lastdesc=%d, ndescs=%d", 1165174987Smarius __func__, txs->txs_firstdesc, txs->txs_lastdesc, 1166174987Smarius txs->txs_ndescs); 1167115030Stmm#endif 1168108832Stmm STAILQ_REMOVE_HEAD(&sc->sc_txfreeq, txs_q); 1169108832Stmm STAILQ_INSERT_TAIL(&sc->sc_txdirtyq, txs, txs_q); 1170170273Syongari txs->txs_mbuf = *m_head; 117191398Stmm 1172108832Stmm sc->sc_txnext = GEM_NEXTTX(txs->txs_lastdesc); 1173108832Stmm sc->sc_txfree -= txs->txs_ndescs; 1174170273Syongari 1175108832Stmm return (0); 117691398Stmm} 117791398Stmm 117891398Stmmstatic void 1179174987Smariusgem_init_regs(struct gem_softc *sc) 118091398Stmm{ 1181152315Sru const u_char *laddr = IF_LLADDR(sc->sc_ifp); 118291398Stmm 1183174987Smarius /* These registers are not cleared on reset. */ 1184172334Smarius if ((sc->sc_flags & GEM_INITED) == 0) { 1185174987Smarius /* magic values */ 1186169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_IPG0, 0); 1187169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_IPG1, 8); 1188169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_IPG2, 4); 118991398Stmm 1190174987Smarius bus_write_4(sc->sc_res[0], GEM_MAC_MAC_MIN_FRAME, 1191174987Smarius ETHER_MIN_LEN); 1192174987Smarius /* max frame and max burst size */ 1193169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_MAC_MAX_FRAME, 1194172334Smarius (ETHER_MAX_LEN + ETHER_VLAN_ENCAP_LEN) | (0x2000 << 16)); 119599726Sbenno 1196169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_PREAMBLE_LEN, 0x7); 1197169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_JAM_SIZE, 0x4); 1198169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_ATTEMPT_LIMIT, 0x10); 1199174987Smarius /* dunno... */ 1200169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_CONTROL_TYPE, 0x8088); 1201169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_RANDOM_SEED, 1202174987Smarius ((laddr[5] << 8) | laddr[4]) & 0x3ff); 120399726Sbenno 1204174987Smarius /* secondary MAC address: 0:0:0:0:0:0 */ 1205169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_ADDR3, 0); 1206169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_ADDR4, 0); 1207169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_ADDR5, 0); 120899726Sbenno 1209174987Smarius /* MAC control address: 01:80:c2:00:00:01 */ 1210169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_ADDR6, 0x0001); 1211169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_ADDR7, 0xc200); 1212169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_ADDR8, 0x0180); 121391398Stmm 1214174987Smarius /* MAC filter address: 0:0:0:0:0:0 */ 1215169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_ADDR_FILTER0, 0); 1216169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_ADDR_FILTER1, 0); 1217169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_ADDR_FILTER2, 0); 121891398Stmm 1219169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_ADR_FLT_MASK1_2, 0); 1220169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_ADR_FLT_MASK0, 0); 122191398Stmm 1222172334Smarius sc->sc_flags |= GEM_INITED; 122391398Stmm } 122491398Stmm 1225174987Smarius /* Counters need to be zeroed. */ 1226169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_NORM_COLL_CNT, 0); 1227169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_FIRST_COLL_CNT, 0); 1228169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_EXCESS_COLL_CNT, 0); 1229169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_LATE_COLL_CNT, 0); 1230169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_DEFER_TMR_CNT, 0); 1231169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_PEAK_ATTEMPTS, 0); 1232169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_RX_FRAME_COUNT, 0); 1233169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_RX_LEN_ERR_CNT, 0); 1234169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_RX_ALIGN_ERR, 0); 1235169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_RX_CRC_ERR_CNT, 0); 1236169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_RX_CODE_VIOL, 0); 123791398Stmm 1238172334Smarius /* Set XOFF PAUSE time. */ 1239169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_SEND_PAUSE_CMD, 0x1BF0); 124091398Stmm 124191398Stmm /* 1242172334Smarius * Set the internal arbitration to "infinite" bursts of the 1243172334Smarius * maximum length of 31 * 64 bytes so DMA transfers aren't 1244174987Smarius * split up in cache line size chunks. This greatly improves 1245172334Smarius * especially RX performance. 1246172334Smarius * Enable silicon bug workarounds for the Apple variants. 1247172334Smarius */ 1248172334Smarius bus_write_4(sc->sc_res[0], GEM_CONFIG, 1249172334Smarius GEM_CONFIG_TXDMA_LIMIT | GEM_CONFIG_RXDMA_LIMIT | 1250172334Smarius GEM_CONFIG_BURST_INF | (GEM_IS_APPLE(sc) ? 1251172334Smarius GEM_CONFIG_RONPAULBIT | GEM_CONFIG_BUG2FIX : 0)); 1252172334Smarius 1253174987Smarius /* Set the station address. */ 1254174987Smarius bus_write_4(sc->sc_res[0], GEM_MAC_ADDR0, 1255174987Smarius (laddr[4] << 8) | laddr[5]); 1256174987Smarius bus_write_4(sc->sc_res[0], GEM_MAC_ADDR1, 1257174987Smarius (laddr[2] << 8) | laddr[3]); 1258174987Smarius bus_write_4(sc->sc_res[0], GEM_MAC_ADDR2, 1259174987Smarius (laddr[0] << 8) | laddr[1]); 126099726Sbenno 1261172334Smarius /* Enable MII outputs. */ 1262174987Smarius bus_write_4(sc->sc_res[0], GEM_MAC_XIF_CONFIG, 1263174987Smarius GEM_MAC_XIF_TX_MII_ENA); 126491398Stmm} 126591398Stmm 126691398Stmmstatic void 1267174987Smariusgem_start(struct ifnet *ifp) 126891398Stmm{ 1269174987Smarius struct gem_softc *sc = ifp->if_softc; 1270148369Smarius 1271148369Smarius GEM_LOCK(sc); 1272148369Smarius gem_start_locked(ifp); 1273148369Smarius GEM_UNLOCK(sc); 1274148369Smarius} 1275148369Smarius 1276148369Smariusstatic void 1277174987Smariusgem_start_locked(struct ifnet *ifp) 1278148369Smarius{ 1279174987Smarius struct gem_softc *sc = ifp->if_softc; 1280170273Syongari struct mbuf *m; 1281174987Smarius int ntx; 128291398Stmm 1283148887Srwatson if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) != 1284172334Smarius IFF_DRV_RUNNING || (sc->sc_flags & GEM_LINK) == 0) 128591398Stmm return; 128691398Stmm 1287115030Stmm#ifdef GEM_DEBUG 1288170273Syongari CTR4(KTR_GEM, "%s: %s: txfree %d, txnext %d", 1289172334Smarius device_get_name(sc->sc_dev), __func__, sc->sc_txfree, 1290172334Smarius sc->sc_txnext); 1291115030Stmm#endif 1292174987Smarius ntx = 0; 1293170273Syongari for (; !IFQ_DRV_IS_EMPTY(&ifp->if_snd) && sc->sc_txfree > 1;) { 1294170273Syongari IFQ_DRV_DEQUEUE(&ifp->if_snd, m); 1295170273Syongari if (m == NULL) 129691398Stmm break; 1297172334Smarius if (gem_load_txmbuf(sc, &m) != 0) { 1298170273Syongari if (m == NULL) 1299170273Syongari break; 1300170273Syongari ifp->if_drv_flags |= IFF_DRV_OACTIVE; 1301170273Syongari IFQ_DRV_PREPEND(&ifp->if_snd, m); 130291398Stmm break; 130391398Stmm } 1304115030Stmm ntx++; 1305108832Stmm /* Kick the transmitter. */ 1306172334Smarius#ifdef GEM_DEBUG 1307174987Smarius CTR3(KTR_GEM, "%s: %s: kicking TX %d", 1308170273Syongari device_get_name(sc->sc_dev), __func__, sc->sc_txnext); 1309115030Stmm#endif 1310172334Smarius GEM_CDSYNC(sc, BUS_DMASYNC_PREWRITE); 1311174987Smarius bus_write_4(sc->sc_res[0], GEM_TX_KICK, sc->sc_txnext); 1312108832Stmm 1313170273Syongari BPF_MTAP(ifp, m); 131491398Stmm } 131591398Stmm 131691398Stmm if (ntx > 0) { 1317115030Stmm#ifdef GEM_DEBUG 1318108832Stmm CTR2(KTR_GEM, "%s: packets enqueued, OWN on %d", 1319172334Smarius device_get_name(sc->sc_dev), sc->sc_txnext); 1320115030Stmm#endif 132191398Stmm 132291398Stmm /* Set a watchdog timer in case the chip flakes out. */ 1323164931Smarius sc->sc_wdog_timer = 5; 1324115030Stmm#ifdef GEM_DEBUG 1325170273Syongari CTR3(KTR_GEM, "%s: %s: watchdog %d", 1326174987Smarius device_get_name(sc->sc_dev), __func__, 1327174987Smarius sc->sc_wdog_timer); 1328115030Stmm#endif 132991398Stmm } 133091398Stmm} 133191398Stmm 133291398Stmmstatic void 1333174987Smariusgem_tint(struct gem_softc *sc) 133491398Stmm{ 1335147256Sbrooks struct ifnet *ifp = sc->sc_ifp; 133691398Stmm struct gem_txsoft *txs; 1337174987Smarius int txlast, progress; 1338174987Smarius#ifdef GEM_DEBUG 1339174987Smarius int i; 134091398Stmm 1341170273Syongari CTR2(KTR_GEM, "%s: %s", device_get_name(sc->sc_dev), __func__); 1342115030Stmm#endif 134391398Stmm 134491398Stmm /* 1345174987Smarius * Go through our TX list and free mbufs for those 134691398Stmm * frames that have been transmitted. 134791398Stmm */ 1348174987Smarius progress = 0; 1349109648Stmm GEM_CDSYNC(sc, BUS_DMASYNC_POSTREAD); 135091398Stmm while ((txs = STAILQ_FIRST(&sc->sc_txdirtyq)) != NULL) { 135191398Stmm 135291398Stmm#ifdef GEM_DEBUG 1353174987Smarius if ((ifp->if_flags & IFF_DEBUG) != 0) { 135491398Stmm printf(" txsoft %p transmit chain:\n", txs); 135591398Stmm for (i = txs->txs_firstdesc;; i = GEM_NEXTTX(i)) { 135691398Stmm printf("descriptor %d: ", i); 1357174987Smarius printf("gd_flags: 0x%016llx\t", 1358174987Smarius (long long)GEM_DMA_READ(sc, 1359174987Smarius sc->sc_txdescs[i].gd_flags)); 1360174987Smarius printf("gd_addr: 0x%016llx\n", 1361174987Smarius (long long)GEM_DMA_READ(sc, 1362174987Smarius sc->sc_txdescs[i].gd_addr)); 136391398Stmm if (i == txs->txs_lastdesc) 136491398Stmm break; 136591398Stmm } 136691398Stmm } 136791398Stmm#endif 136891398Stmm 136991398Stmm /* 1370172334Smarius * In theory, we could harvest some descriptors before 137191398Stmm * the ring is empty, but that's a bit complicated. 137291398Stmm * 137391398Stmm * GEM_TX_COMPLETION points to the last descriptor 1374174987Smarius * processed + 1. 137591398Stmm */ 1376169269Sphk txlast = bus_read_4(sc->sc_res[0], GEM_TX_COMPLETION); 1377115030Stmm#ifdef GEM_DEBUG 1378170273Syongari CTR4(KTR_GEM, "%s: txs->txs_firstdesc = %d, " 137991398Stmm "txs->txs_lastdesc = %d, txlast = %d", 1380170273Syongari __func__, txs->txs_firstdesc, txs->txs_lastdesc, txlast); 1381115030Stmm#endif 138291398Stmm if (txs->txs_firstdesc <= txs->txs_lastdesc) { 138391398Stmm if ((txlast >= txs->txs_firstdesc) && 1384174987Smarius (txlast <= txs->txs_lastdesc)) 138591398Stmm break; 138691398Stmm } else { 1387174987Smarius /* Ick -- this command wraps. */ 138891398Stmm if ((txlast >= txs->txs_firstdesc) || 1389174987Smarius (txlast <= txs->txs_lastdesc)) 139091398Stmm break; 139191398Stmm } 139291398Stmm 1393115030Stmm#ifdef GEM_DEBUG 1394174987Smarius CTR1(KTR_GEM, "%s: releasing a descriptor", __func__); 1395115030Stmm#endif 139691398Stmm STAILQ_REMOVE_HEAD(&sc->sc_txdirtyq, txs_q); 139791398Stmm 139891398Stmm sc->sc_txfree += txs->txs_ndescs; 139991398Stmm 1400108832Stmm bus_dmamap_sync(sc->sc_tdmatag, txs->txs_dmamap, 140191398Stmm BUS_DMASYNC_POSTWRITE); 1402108832Stmm bus_dmamap_unload(sc->sc_tdmatag, txs->txs_dmamap); 140391398Stmm if (txs->txs_mbuf != NULL) { 140491398Stmm m_freem(txs->txs_mbuf); 140591398Stmm txs->txs_mbuf = NULL; 140691398Stmm } 140791398Stmm 140891398Stmm STAILQ_INSERT_TAIL(&sc->sc_txfreeq, txs, txs_q); 140991398Stmm 141091398Stmm ifp->if_opackets++; 141199726Sbenno progress = 1; 141291398Stmm } 141391398Stmm 1414115030Stmm#ifdef GEM_DEBUG 1415174987Smarius CTR4(KTR_GEM, "%s: GEM_TX_STATE_MACHINE %x GEM_TX_DATA_PTR %llx " 1416172334Smarius "GEM_TX_COMPLETION %x", 1417174987Smarius __func__, bus_read_4(sc->sc_res[0], GEM_TX_STATE_MACHINE), 1418174987Smarius ((long long)bus_read_4(sc->sc_res[0], 1419174987Smarius GEM_TX_DATA_PTR_HI) << 32) | 1420172334Smarius bus_read_4(sc->sc_res[0], GEM_TX_DATA_PTR_LO), 1421172334Smarius bus_read_4(sc->sc_res[0], GEM_TX_COMPLETION)); 1422115030Stmm#endif 142391398Stmm 142499726Sbenno if (progress) { 142599726Sbenno if (sc->sc_txfree == GEM_NTXDESC - 1) 142699726Sbenno sc->sc_txwin = 0; 142791398Stmm 1428174987Smarius /* 1429174987Smarius * We freed some descriptors, so reset IFF_DRV_OACTIVE 1430174987Smarius * and restart. 1431174987Smarius */ 1432148887Srwatson ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 1433170273Syongari sc->sc_wdog_timer = STAILQ_EMPTY(&sc->sc_txdirtyq) ? 0 : 5; 143491398Stmm 1435170273Syongari if (ifp->if_drv_flags & IFF_DRV_RUNNING && 1436170273Syongari !IFQ_DRV_IS_EMPTY(&ifp->if_snd)) 1437170273Syongari gem_start_locked(ifp); 143899726Sbenno } 143999726Sbenno 1440115030Stmm#ifdef GEM_DEBUG 1441170273Syongari CTR3(KTR_GEM, "%s: %s: watchdog %d", 1442170273Syongari device_get_name(sc->sc_dev), __func__, sc->sc_wdog_timer); 1443115030Stmm#endif 144491398Stmm} 144591398Stmm 1446148368Smarius#ifdef GEM_RINT_TIMEOUT 144793045Stmmstatic void 1448174987Smariusgem_rint_timeout(void *arg) 144993045Stmm{ 1450174987Smarius struct gem_softc *sc = arg; 145193045Stmm 1452150285Smarius GEM_LOCK_ASSERT(sc, MA_OWNED); 1453148369Smarius gem_rint(sc); 145493045Stmm} 1455100587Sjake#endif 145693045Stmm 145791398Stmmstatic void 1458174987Smariusgem_rint(struct gem_softc *sc) 145991398Stmm{ 1460147256Sbrooks struct ifnet *ifp = sc->sc_ifp; 146191398Stmm struct mbuf *m; 1462174987Smarius uint64_t rxstat; 1463174987Smarius uint32_t rxcomp; 146491398Stmm 1465148368Smarius#ifdef GEM_RINT_TIMEOUT 146693045Stmm callout_stop(&sc->sc_rx_ch); 1467148368Smarius#endif 1468115030Stmm#ifdef GEM_DEBUG 1469170273Syongari CTR2(KTR_GEM, "%s: %s", device_get_name(sc->sc_dev), __func__); 1470115030Stmm#endif 147199726Sbenno 147291398Stmm /* 147399726Sbenno * Read the completion register once. This limits 147499726Sbenno * how long the following loop can execute. 147599726Sbenno */ 1476169269Sphk rxcomp = bus_read_4(sc->sc_res[0], GEM_RX_COMPLETION); 147799726Sbenno 1478115030Stmm#ifdef GEM_DEBUG 1479170273Syongari CTR3(KTR_GEM, "%s: sc->rxptr %d, complete %d", 1480170273Syongari __func__, sc->sc_rxptr, rxcomp); 1481115030Stmm#endif 1482109648Stmm GEM_CDSYNC(sc, BUS_DMASYNC_POSTREAD); 1483172334Smarius for (; sc->sc_rxptr != rxcomp;) { 1484172334Smarius m = sc->sc_rxsoft[sc->sc_rxptr].rxs_mbuf; 1485172334Smarius rxstat = GEM_DMA_READ(sc, 1486172334Smarius sc->sc_rxdescs[sc->sc_rxptr].gd_flags); 148791398Stmm 148891398Stmm if (rxstat & GEM_RD_OWN) { 1489148368Smarius#ifdef GEM_RINT_TIMEOUT 149091398Stmm /* 149193045Stmm * The descriptor is still marked as owned, although 1492174987Smarius * it is supposed to have completed. This has been 1493174987Smarius * observed on some machines. Just exiting here 149493045Stmm * might leave the packet sitting around until another 149593045Stmm * one arrives to trigger a new interrupt, which is 149693045Stmm * generally undesirable, so set up a timeout. 149791398Stmm */ 149893045Stmm callout_reset(&sc->sc_rx_ch, GEM_RXOWN_TICKS, 149993045Stmm gem_rint_timeout, sc); 150099726Sbenno#endif 1501172334Smarius m = NULL; 1502172334Smarius goto kickit; 150391398Stmm } 150491398Stmm 150591398Stmm if (rxstat & GEM_RD_BAD_CRC) { 150699726Sbenno ifp->if_ierrors++; 150791398Stmm device_printf(sc->sc_dev, "receive error: CRC error\n"); 1508172334Smarius GEM_INIT_RXDESC(sc, sc->sc_rxptr); 1509172334Smarius m = NULL; 1510172334Smarius goto kickit; 151191398Stmm } 151291398Stmm 151391398Stmm#ifdef GEM_DEBUG 1514174987Smarius if ((ifp->if_flags & IFF_DEBUG) != 0) { 1515172334Smarius printf(" rxsoft %p descriptor %d: ", 1516172334Smarius &sc->sc_rxsoft[sc->sc_rxptr], sc->sc_rxptr); 1517174987Smarius printf("gd_flags: 0x%016llx\t", 1518174987Smarius (long long)GEM_DMA_READ(sc, 1519174987Smarius sc->sc_rxdescs[sc->sc_rxptr].gd_flags)); 1520174987Smarius printf("gd_addr: 0x%016llx\n", 1521174987Smarius (long long)GEM_DMA_READ(sc, 1522174987Smarius sc->sc_rxdescs[sc->sc_rxptr].gd_addr)); 152391398Stmm } 152491398Stmm#endif 152591398Stmm 152691398Stmm /* 152791398Stmm * Allocate a new mbuf cluster. If that fails, we are 152891398Stmm * out of memory, and must drop the packet and recycle 152991398Stmm * the buffer that's already attached to this descriptor. 153091398Stmm */ 1531172334Smarius if (gem_add_rxbuf(sc, sc->sc_rxptr) != 0) { 153291398Stmm ifp->if_ierrors++; 1533172334Smarius GEM_INIT_RXDESC(sc, sc->sc_rxptr); 1534172334Smarius m = NULL; 1535172334Smarius } 1536172334Smarius 1537174987Smarius kickit: 1538174987Smarius /* 1539174987Smarius * Update the RX kick register. This register has to point 1540172334Smarius * to the descriptor after the last valid one (before the 1541172334Smarius * current batch) and must be incremented in multiples of 1542172334Smarius * 4 (because the DMA engine fetches/updates descriptors 1543172334Smarius * in batches of 4). 1544172334Smarius */ 1545172334Smarius sc->sc_rxptr = GEM_NEXTRX(sc->sc_rxptr); 1546172334Smarius if ((sc->sc_rxptr % 4) == 0) { 1547172334Smarius GEM_CDSYNC(sc, BUS_DMASYNC_PREWRITE); 1548172334Smarius bus_write_4(sc->sc_res[0], GEM_RX_KICK, 1549172334Smarius (sc->sc_rxptr + GEM_NRXDESC - 4) & 1550172334Smarius GEM_NRXDESC_MASK); 1551172334Smarius } 1552172334Smarius 1553172334Smarius if (m == NULL) { 1554172334Smarius if (rxstat & GEM_RD_OWN) 1555172334Smarius break; 155691398Stmm continue; 155791398Stmm } 1558172334Smarius 1559172334Smarius ifp->if_ipackets++; 156091398Stmm m->m_data += 2; /* We're already off by two */ 156191398Stmm m->m_pkthdr.rcvif = ifp; 1562172334Smarius m->m_pkthdr.len = m->m_len = GEM_RD_BUFLEN(rxstat); 156391398Stmm 1564170273Syongari if ((ifp->if_capenable & IFCAP_RXCSUM) != 0) 1565170273Syongari gem_rxcksum(m, rxstat); 1566170273Syongari 156791398Stmm /* Pass it on. */ 1568148369Smarius GEM_UNLOCK(sc); 1569106937Ssam (*ifp->if_input)(ifp, m); 1570148369Smarius GEM_LOCK(sc); 157191398Stmm } 157291398Stmm 1573115030Stmm#ifdef GEM_DEBUG 1574170273Syongari CTR3(KTR_GEM, "%s: done sc->rxptr %d, complete %d", __func__, 1575174987Smarius sc->sc_rxptr, bus_read_4(sc->sc_res[0], GEM_RX_COMPLETION)); 1576115030Stmm#endif 157791398Stmm} 157891398Stmm 157991398Stmmstatic int 1580174987Smariusgem_add_rxbuf(struct gem_softc *sc, int idx) 158191398Stmm{ 158291398Stmm struct gem_rxsoft *rxs = &sc->sc_rxsoft[idx]; 158391398Stmm struct mbuf *m; 1584148368Smarius bus_dma_segment_t segs[1]; 1585148368Smarius int error, nsegs; 158691398Stmm 1587111119Simp m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); 158891398Stmm if (m == NULL) 158991398Stmm return (ENOBUFS); 1590108832Stmm m->m_len = m->m_pkthdr.len = m->m_ext.ext_size; 159191398Stmm 159291398Stmm#ifdef GEM_DEBUG 1593174987Smarius /* Bzero the packet to check DMA. */ 159491398Stmm memset(m->m_ext.ext_buf, 0, m->m_ext.ext_size); 159591398Stmm#endif 159691398Stmm 1597109648Stmm if (rxs->rxs_mbuf != NULL) { 1598109648Stmm bus_dmamap_sync(sc->sc_rdmatag, rxs->rxs_dmamap, 1599109648Stmm BUS_DMASYNC_POSTREAD); 1600108832Stmm bus_dmamap_unload(sc->sc_rdmatag, rxs->rxs_dmamap); 1601109648Stmm } 160291398Stmm 1603148368Smarius error = bus_dmamap_load_mbuf_sg(sc->sc_rdmatag, rxs->rxs_dmamap, 1604148368Smarius m, segs, &nsegs, BUS_DMA_NOWAIT); 1605148368Smarius KASSERT(nsegs == 1, ("Too many segments returned!")); 1606148368Smarius if (error != 0) { 1607174987Smarius device_printf(sc->sc_dev, 1608174987Smarius "cannot load RS DMA map %d, error = %d\n", idx, error); 1609148368Smarius m_freem(m); 1610172334Smarius return (error); 161191398Stmm } 1612174987Smarius /* If nsegs is wrong then the stack is corrupt. */ 1613172334Smarius rxs->rxs_mbuf = m; 1614148368Smarius rxs->rxs_paddr = segs[0].ds_addr; 161591398Stmm 1616174987Smarius bus_dmamap_sync(sc->sc_rdmatag, rxs->rxs_dmamap, 1617174987Smarius BUS_DMASYNC_PREREAD); 161891398Stmm 161991398Stmm GEM_INIT_RXDESC(sc, idx); 162091398Stmm 162191398Stmm return (0); 162291398Stmm} 162391398Stmm 162491398Stmmstatic void 1625174987Smariusgem_eint(struct gem_softc *sc, u_int status) 162691398Stmm{ 162791398Stmm 1628172334Smarius sc->sc_ifp->if_ierrors++; 1629172334Smarius if ((status & GEM_INTR_RX_TAG_ERR) != 0) { 1630172334Smarius gem_reset_rxdma(sc); 163191398Stmm return; 163291398Stmm } 163391398Stmm 1634172334Smarius device_printf(sc->sc_dev, "%s: status=%x\n", __func__, status); 163591398Stmm} 163691398Stmm 163791398Stmmvoid 1638174987Smariusgem_intr(void *v) 163991398Stmm{ 1640174987Smarius struct gem_softc *sc = v; 1641172334Smarius uint32_t status, status2; 164291398Stmm 1643148369Smarius GEM_LOCK(sc); 1644169269Sphk status = bus_read_4(sc->sc_res[0], GEM_STATUS); 1645172334Smarius 1646115030Stmm#ifdef GEM_DEBUG 1647170273Syongari CTR4(KTR_GEM, "%s: %s: cplt %x, status %x", 1648174987Smarius device_get_name(sc->sc_dev), __func__, (status >> 19), 1649174987Smarius (u_int)status); 1650172334Smarius 1651172334Smarius /* 1652172334Smarius * PCS interrupts must be cleared, otherwise no traffic is passed! 1653172334Smarius */ 1654172334Smarius if ((status & GEM_INTR_PCS) != 0) { 1655174987Smarius status2 = 1656174987Smarius bus_read_4(sc->sc_res[0], GEM_MII_INTERRUP_STATUS) | 1657172334Smarius bus_read_4(sc->sc_res[0], GEM_MII_INTERRUP_STATUS); 1658172334Smarius if ((status2 & GEM_MII_INTERRUP_LINK) != 0) 1659172334Smarius device_printf(sc->sc_dev, 1660172334Smarius "%s: PCS link status changed\n", __func__); 1661172334Smarius } 1662172334Smarius if ((status & GEM_MAC_CONTROL_STATUS) != 0) { 1663172334Smarius status2 = bus_read_4(sc->sc_res[0], GEM_MAC_CONTROL_STATUS); 1664172334Smarius if ((status2 & GEM_MAC_PAUSED) != 0) 1665172334Smarius device_printf(sc->sc_dev, 1666172334Smarius "%s: PAUSE received (PAUSE time %d slots)\n", 1667172334Smarius __func__, GEM_MAC_PAUSE_TIME(status2)); 1668172334Smarius if ((status2 & GEM_MAC_PAUSE) != 0) 1669172334Smarius device_printf(sc->sc_dev, 1670172334Smarius "%s: transited to PAUSE state\n", __func__); 1671172334Smarius if ((status2 & GEM_MAC_RESUME) != 0) 1672172334Smarius device_printf(sc->sc_dev, 1673172334Smarius "%s: transited to non-PAUSE state\n", __func__); 1674172334Smarius } 1675172334Smarius if ((status & GEM_INTR_MIF) != 0) 1676172334Smarius device_printf(sc->sc_dev, "%s: MIF interrupt\n", __func__); 1677115030Stmm#endif 167891398Stmm 1679172334Smarius if ((status & 1680172334Smarius (GEM_INTR_RX_TAG_ERR | GEM_INTR_PERR | GEM_INTR_BERR)) != 0) 168191398Stmm gem_eint(sc, status); 168291398Stmm 1683172334Smarius if ((status & (GEM_INTR_RX_DONE | GEM_INTR_RX_NOBUF)) != 0) 1684172334Smarius gem_rint(sc); 1685172334Smarius 168691398Stmm if ((status & (GEM_INTR_TX_EMPTY | GEM_INTR_TX_INTME)) != 0) 168791398Stmm gem_tint(sc); 168891398Stmm 168991398Stmm if (status & GEM_INTR_TX_MAC) { 1690172334Smarius status2 = bus_read_4(sc->sc_res[0], GEM_MAC_TX_STATUS); 1691174987Smarius if ((status2 & 1692174987Smarius ~(GEM_MAC_TX_XMIT_DONE | GEM_MAC_TX_DEFER_EXP)) != 0) 1693174987Smarius device_printf(sc->sc_dev, 1694174987Smarius "MAC TX fault, status %x\n", status2); 1695174987Smarius if ((status2 & 1696174987Smarius (GEM_MAC_TX_UNDERRUN | GEM_MAC_TX_PKT_TOO_LONG)) != 0) 1697148369Smarius gem_init_locked(sc); 169891398Stmm } 169991398Stmm if (status & GEM_INTR_RX_MAC) { 1700172334Smarius status2 = bus_read_4(sc->sc_res[0], GEM_MAC_RX_STATUS); 1701149552Smarius /* 1702172334Smarius * At least with GEM_SUN_GEM and some GEM_SUN_ERI 1703172334Smarius * revisions GEM_MAC_RX_OVERFLOW happen often due to a 1704174987Smarius * silicon bug so handle them silently. Moreover, it's 1705172334Smarius * likely that the receiver has hung so we reset it. 1706149552Smarius */ 1707174987Smarius if ((status2 & GEM_MAC_RX_OVERFLOW) != 0) { 1708172334Smarius sc->sc_ifp->if_ierrors++; 1709172334Smarius gem_reset_rxdma(sc); 1710174987Smarius } else if ((status2 & 1711174987Smarius ~(GEM_MAC_RX_DONE | GEM_MAC_RX_FRAME_CNT)) != 0) 1712174987Smarius device_printf(sc->sc_dev, 1713174987Smarius "MAC RX fault, status %x\n", status2); 171491398Stmm } 1715148369Smarius GEM_UNLOCK(sc); 171691398Stmm} 171791398Stmm 1718164931Smariusstatic int 1719174987Smariusgem_watchdog(struct gem_softc *sc) 172091398Stmm{ 172191398Stmm 1722164931Smarius GEM_LOCK_ASSERT(sc, MA_OWNED); 1723164931Smarius 1724115030Stmm#ifdef GEM_DEBUG 1725174987Smarius CTR4(KTR_GEM, 1726174987Smarius "%s: GEM_RX_CONFIG %x GEM_MAC_RX_STATUS %x GEM_MAC_RX_CONFIG %x", 1727174987Smarius __func__, bus_read_4(sc->sc_res[0], GEM_RX_CONFIG), 1728174987Smarius bus_read_4(sc->sc_res[0], GEM_MAC_RX_STATUS), 1729174987Smarius bus_read_4(sc->sc_res[0], GEM_MAC_RX_CONFIG)); 1730174987Smarius CTR4(KTR_GEM, 1731174987Smarius "%s: GEM_TX_CONFIG %x GEM_MAC_TX_STATUS %x GEM_MAC_TX_CONFIG %x", 1732174987Smarius __func__, bus_read_4(sc->sc_res[0], GEM_TX_CONFIG), 1733174987Smarius bus_read_4(sc->sc_res[0], GEM_MAC_TX_STATUS), 1734174987Smarius bus_read_4(sc->sc_res[0], GEM_MAC_TX_CONFIG)); 1735115030Stmm#endif 173691398Stmm 1737164931Smarius if (sc->sc_wdog_timer == 0 || --sc->sc_wdog_timer != 0) 1738164931Smarius return (0); 1739164931Smarius 1740172334Smarius if ((sc->sc_flags & GEM_LINK) != 0) 1741172334Smarius device_printf(sc->sc_dev, "device timeout\n"); 1742172334Smarius else if (bootverbose) 1743172334Smarius device_printf(sc->sc_dev, "device timeout (no link)\n"); 1744164931Smarius ++sc->sc_ifp->if_oerrors; 174591398Stmm 174691398Stmm /* Try to get more packets going. */ 1747148369Smarius gem_init_locked(sc); 1748164931Smarius return (EJUSTRETURN); 174991398Stmm} 175091398Stmm 175191398Stmmstatic void 1752174987Smariusgem_mifinit(struct gem_softc *sc) 175391398Stmm{ 175491398Stmm 175591398Stmm /* Configure the MIF in frame mode */ 1756172334Smarius bus_write_4(sc->sc_res[0], GEM_MIF_CONFIG, bus_read_4(sc->sc_res[0], 1757172334Smarius GEM_MIF_CONFIG) & ~GEM_MIF_CONFIG_BB_ENA); 175891398Stmm} 175991398Stmm 176091398Stmm/* 176191398Stmm * MII interface 176291398Stmm * 176391398Stmm * The GEM MII interface supports at least three different operating modes: 176491398Stmm * 176591398Stmm * Bitbang mode is implemented using data, clock and output enable registers. 176691398Stmm * 176791398Stmm * Frame mode is implemented by loading a complete frame into the frame 176891398Stmm * register and polling the valid bit for completion. 176991398Stmm * 177091398Stmm * Polling mode uses the frame register but completion is indicated by 177191398Stmm * an interrupt. 177291398Stmm * 177391398Stmm */ 177491398Stmmint 1775174987Smariusgem_mii_readreg(device_t dev, int phy, int reg) 177691398Stmm{ 1777174987Smarius struct gem_softc *sc; 177891398Stmm int n; 1779174987Smarius uint32_t v; 178091398Stmm 178191398Stmm#ifdef GEM_DEBUG_PHY 1782172334Smarius printf("%s: phy %d reg %d\n", __func__, phy, reg); 178391398Stmm#endif 178491398Stmm 1785174987Smarius sc = device_get_softc(dev); 1786172334Smarius if (sc->sc_phyad != -1 && phy != sc->sc_phyad) 1787172334Smarius return (0); 178891398Stmm 1789172334Smarius if ((sc->sc_flags & GEM_SERDES) != 0) { 1790172334Smarius switch (reg) { 1791172334Smarius case MII_BMCR: 1792172334Smarius reg = GEM_MII_CONTROL; 1793172334Smarius break; 1794172334Smarius case MII_BMSR: 1795172334Smarius reg = GEM_MII_STATUS; 1796172334Smarius break; 1797172334Smarius case MII_PHYIDR1: 1798172334Smarius case MII_PHYIDR2: 1799172334Smarius return (0); 1800172334Smarius case MII_ANAR: 1801172334Smarius reg = GEM_MII_ANAR; 1802172334Smarius break; 1803172334Smarius case MII_ANLPAR: 1804172334Smarius reg = GEM_MII_ANLPAR; 1805172334Smarius break; 1806172334Smarius case MII_EXTSR: 1807172334Smarius return (EXTSR_1000XFDX | EXTSR_1000XHDX); 1808172334Smarius default: 1809172334Smarius device_printf(sc->sc_dev, 1810172334Smarius "%s: unhandled register %d\n", __func__, reg); 1811172334Smarius return (0); 1812172334Smarius } 1813172334Smarius return (bus_read_4(sc->sc_res[0], reg)); 1814172334Smarius } 1815172334Smarius 1816174987Smarius /* Construct the frame command. */ 1817172334Smarius v = GEM_MIF_FRAME_READ | 1818172334Smarius (phy << GEM_MIF_PHY_SHIFT) | 1819172334Smarius (reg << GEM_MIF_REG_SHIFT); 182091398Stmm 1821169269Sphk bus_write_4(sc->sc_res[0], GEM_MIF_FRAME, v); 182291398Stmm for (n = 0; n < 100; n++) { 182391398Stmm DELAY(1); 1824169269Sphk v = bus_read_4(sc->sc_res[0], GEM_MIF_FRAME); 1825150285Smarius if (v & GEM_MIF_FRAME_TA0) 182691398Stmm return (v & GEM_MIF_FRAME_DATA); 182791398Stmm } 182891398Stmm 1829174987Smarius device_printf(sc->sc_dev, "%s: timed out\n", __func__); 183091398Stmm return (0); 183191398Stmm} 183291398Stmm 183391398Stmmint 1834174987Smariusgem_mii_writereg(device_t dev, int phy, int reg, int val) 183591398Stmm{ 1836174987Smarius struct gem_softc *sc; 183791398Stmm int n; 1838174987Smarius uint32_t v; 183991398Stmm 184091398Stmm#ifdef GEM_DEBUG_PHY 1841172334Smarius printf("%s: phy %d reg %d val %x\n", phy, reg, val, __func__); 184291398Stmm#endif 184391398Stmm 1844174987Smarius sc = device_get_softc(dev); 1845172334Smarius if (sc->sc_phyad != -1 && phy != sc->sc_phyad) 1846172334Smarius return (0); 1847172334Smarius 1848172334Smarius if ((sc->sc_flags & GEM_SERDES) != 0) { 1849172334Smarius switch (reg) { 1850172334Smarius case MII_BMCR: 1851172334Smarius reg = GEM_MII_CONTROL; 1852172334Smarius break; 1853172334Smarius case MII_BMSR: 1854172334Smarius reg = GEM_MII_STATUS; 1855172334Smarius break; 1856172334Smarius case MII_ANAR: 1857172334Smarius bus_write_4(sc->sc_res[0], GEM_MII_CONFIG, 0); 1858172334Smarius bus_barrier(sc->sc_res[0], GEM_MII_CONFIG, 4, 1859172334Smarius BUS_SPACE_BARRIER_WRITE); 1860172334Smarius bus_write_4(sc->sc_res[0], GEM_MII_ANAR, val); 1861172334Smarius bus_write_4(sc->sc_res[0], GEM_MII_SLINK_CONTROL, 1862172334Smarius GEM_MII_SLINK_LOOPBACK | GEM_MII_SLINK_EN_SYNC_D); 1863172334Smarius bus_write_4(sc->sc_res[0], GEM_MII_CONFIG, 1864172334Smarius GEM_MII_CONFIG_ENABLE); 1865172334Smarius return (0); 1866172334Smarius case MII_ANLPAR: 1867172334Smarius reg = GEM_MII_ANLPAR; 1868172334Smarius break; 1869172334Smarius default: 1870172334Smarius device_printf(sc->sc_dev, 1871172334Smarius "%s: unhandled register %d\n", __func__, reg); 1872172334Smarius return (0); 1873172334Smarius } 1874172334Smarius bus_write_4(sc->sc_res[0], reg, val); 1875172334Smarius return (0); 1876172334Smarius } 1877172334Smarius 1878174987Smarius /* Construct the frame command. */ 1879172334Smarius v = GEM_MIF_FRAME_WRITE | 1880172334Smarius (phy << GEM_MIF_PHY_SHIFT) | 1881172334Smarius (reg << GEM_MIF_REG_SHIFT) | 188291398Stmm (val & GEM_MIF_FRAME_DATA); 188391398Stmm 1884169269Sphk bus_write_4(sc->sc_res[0], GEM_MIF_FRAME, v); 188591398Stmm for (n = 0; n < 100; n++) { 188691398Stmm DELAY(1); 1887169269Sphk v = bus_read_4(sc->sc_res[0], GEM_MIF_FRAME); 1888150285Smarius if (v & GEM_MIF_FRAME_TA0) 188991398Stmm return (1); 189091398Stmm } 189191398Stmm 1892174987Smarius device_printf(sc->sc_dev, "%s: timed out\n", __func__); 189391398Stmm return (0); 189491398Stmm} 189591398Stmm 189691398Stmmvoid 1897174987Smariusgem_mii_statchg(device_t dev) 189891398Stmm{ 1899174987Smarius struct gem_softc *sc; 1900172334Smarius int gigabit; 1901172334Smarius uint32_t rxcfg, txcfg, v; 190291398Stmm 1903174987Smarius sc = device_get_softc(dev); 1904174987Smarius 190591398Stmm#ifdef GEM_DEBUG 1906174987Smarius if ((sc->sc_ifp->if_flags & IFF_DEBUG) != 0) 1907172334Smarius device_printf(sc->sc_dev, "%s: status change: PHY = %d\n", 1908172334Smarius __func__, sc->sc_phyad); 190991398Stmm#endif 191091398Stmm 1911172334Smarius if ((sc->sc_mii->mii_media_status & IFM_ACTIVE) != 0 && 1912172334Smarius IFM_SUBTYPE(sc->sc_mii->mii_media_active) != IFM_NONE) 1913172334Smarius sc->sc_flags |= GEM_LINK; 1914172334Smarius else 1915172334Smarius sc->sc_flags &= ~GEM_LINK; 1916172334Smarius 1917172334Smarius switch (IFM_SUBTYPE(sc->sc_mii->mii_media_active)) { 1918172334Smarius case IFM_1000_SX: 1919172334Smarius case IFM_1000_LX: 1920172334Smarius case IFM_1000_CX: 1921172334Smarius case IFM_1000_T: 1922172334Smarius gigabit = 1; 1923172334Smarius break; 1924172334Smarius default: 1925172334Smarius gigabit = 0; 192691398Stmm } 192791398Stmm 1928172334Smarius /* 1929172334Smarius * The configuration done here corresponds to the steps F) and 1930172334Smarius * G) and as far as enabling of RX and TX MAC goes also step H) 1931172334Smarius * of the initialization sequence outlined in section 3.2.1 of 1932172334Smarius * the GEM Gigabit Ethernet ASIC Specification. 1933172334Smarius */ 1934172334Smarius 1935172334Smarius rxcfg = bus_read_4(sc->sc_res[0], GEM_MAC_RX_CONFIG); 1936172334Smarius rxcfg &= ~(GEM_MAC_RX_CARR_EXTEND | GEM_MAC_RX_ENABLE); 1937172334Smarius txcfg = GEM_MAC_TX_ENA_IPG0 | GEM_MAC_TX_NGU | GEM_MAC_TX_NGU_LIMIT; 1938172334Smarius if ((IFM_OPTIONS(sc->sc_mii->mii_media_active) & IFM_FDX) != 0) 1939172334Smarius txcfg |= GEM_MAC_TX_IGN_CARRIER | GEM_MAC_TX_IGN_COLLIS; 1940172334Smarius else if (gigabit != 0) { 1941172334Smarius rxcfg |= GEM_MAC_RX_CARR_EXTEND; 1942172334Smarius txcfg |= GEM_MAC_TX_CARR_EXTEND; 1943172334Smarius } 1944172334Smarius bus_write_4(sc->sc_res[0], GEM_MAC_TX_CONFIG, 0); 1945172334Smarius bus_barrier(sc->sc_res[0], GEM_MAC_TX_CONFIG, 4, 1946172334Smarius BUS_SPACE_BARRIER_WRITE); 1947172334Smarius if (!gem_bitwait(sc, GEM_MAC_TX_CONFIG, GEM_MAC_TX_ENABLE, 0)) 1948172334Smarius device_printf(sc->sc_dev, "cannot disable TX MAC\n"); 1949172334Smarius bus_write_4(sc->sc_res[0], GEM_MAC_TX_CONFIG, txcfg); 1950172334Smarius bus_write_4(sc->sc_res[0], GEM_MAC_RX_CONFIG, 0); 1951172334Smarius bus_barrier(sc->sc_res[0], GEM_MAC_RX_CONFIG, 4, 1952172334Smarius BUS_SPACE_BARRIER_WRITE); 1953172334Smarius if (!gem_bitwait(sc, GEM_MAC_RX_CONFIG, GEM_MAC_RX_ENABLE, 0)) 1954172334Smarius device_printf(sc->sc_dev, "cannot disable RX MAC\n"); 1955172334Smarius bus_write_4(sc->sc_res[0], GEM_MAC_RX_CONFIG, rxcfg); 1956172334Smarius 1957172334Smarius v = bus_read_4(sc->sc_res[0], GEM_MAC_CONTROL_CONFIG) & 1958172334Smarius ~(GEM_MAC_CC_RX_PAUSE | GEM_MAC_CC_TX_PAUSE); 1959172334Smarius#ifdef notyet 1960174987Smarius if ((IFM_OPTIONS(sc->sc_mii->mii_media_active) & 1961174987Smarius IFM_ETH_RXPAUSE) != 0) 1962172334Smarius v |= GEM_MAC_CC_RX_PAUSE; 1963174987Smarius if ((IFM_OPTIONS(sc->sc_mii->mii_media_active) & 1964174987Smarius IFM_ETH_TXPAUSE) != 0) 1965172334Smarius v |= GEM_MAC_CC_TX_PAUSE; 1966172334Smarius#endif 1967172334Smarius bus_write_4(sc->sc_res[0], GEM_MAC_CONTROL_CONFIG, v); 1968172334Smarius 1969172334Smarius if ((IFM_OPTIONS(sc->sc_mii->mii_media_active) & IFM_FDX) == 0 && 1970172334Smarius gigabit != 0) 1971172334Smarius bus_write_4(sc->sc_res[0], GEM_MAC_SLOT_TIME, 1972172334Smarius GEM_MAC_SLOT_TIME_CARR_EXTEND); 1973172334Smarius else 1974172334Smarius bus_write_4(sc->sc_res[0], GEM_MAC_SLOT_TIME, 1975172334Smarius GEM_MAC_SLOT_TIME_NORMAL); 1976172334Smarius 197791398Stmm /* XIF Configuration */ 197891398Stmm v = GEM_MAC_XIF_LINK_LED; 197991398Stmm v |= GEM_MAC_XIF_TX_MII_ENA; 1980172334Smarius if ((sc->sc_flags & GEM_SERDES) == 0) { 1981172334Smarius if ((bus_read_4(sc->sc_res[0], GEM_MIF_CONFIG) & 1982172334Smarius GEM_MIF_CONFIG_PHY_SEL) != 0 && 1983174987Smarius (IFM_OPTIONS(sc->sc_mii->mii_media_active) & 1984174987Smarius IFM_FDX) == 0) 1985172334Smarius /* External MII needs echo disable if half duplex. */ 1986174987Smarius v |= GEM_MAC_XIF_ECHO_DISABL; 198799726Sbenno else 1988172334Smarius /* 1989172334Smarius * Internal MII needs buffer enable. 1990172334Smarius * XXX buffer enable makes only sense for an 1991172334Smarius * external PHY. 1992172334Smarius */ 1993172334Smarius v |= GEM_MAC_XIF_MII_BUF_ENA; 1994172334Smarius } 1995172334Smarius if (gigabit != 0) 1996172334Smarius v |= GEM_MAC_XIF_GMII_MODE; 1997172334Smarius if ((IFM_OPTIONS(sc->sc_mii->mii_media_active) & IFM_FDX) != 0) 1998172334Smarius v |= GEM_MAC_XIF_FDPLX_LED; 1999172334Smarius bus_write_4(sc->sc_res[0], GEM_MAC_XIF_CONFIG, v); 200099726Sbenno 2001172334Smarius if ((sc->sc_ifp->if_drv_flags & IFF_DRV_RUNNING) != 0 && 2002172334Smarius (sc->sc_flags & GEM_LINK) != 0) { 2003172334Smarius bus_write_4(sc->sc_res[0], GEM_MAC_TX_CONFIG, 2004172334Smarius txcfg | GEM_MAC_TX_ENABLE); 2005172334Smarius bus_write_4(sc->sc_res[0], GEM_MAC_RX_CONFIG, 2006172334Smarius rxcfg | GEM_MAC_RX_ENABLE); 200791398Stmm } 200891398Stmm} 200991398Stmm 201091398Stmmint 2011174987Smariusgem_mediachange(struct ifnet *ifp) 201291398Stmm{ 201391398Stmm struct gem_softc *sc = ifp->if_softc; 2014150285Smarius int error; 201591398Stmm 2016174987Smarius /* XXX add support for serial media. */ 201791398Stmm 2018150285Smarius GEM_LOCK(sc); 2019150285Smarius error = mii_mediachg(sc->sc_mii); 2020150285Smarius GEM_UNLOCK(sc); 2021150285Smarius return (error); 202291398Stmm} 202391398Stmm 202491398Stmmvoid 2025174987Smariusgem_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr) 202691398Stmm{ 202791398Stmm struct gem_softc *sc = ifp->if_softc; 202891398Stmm 2029148369Smarius GEM_LOCK(sc); 2030148369Smarius if ((ifp->if_flags & IFF_UP) == 0) { 2031148369Smarius GEM_UNLOCK(sc); 203291398Stmm return; 2033148369Smarius } 203491398Stmm 203591398Stmm mii_pollstat(sc->sc_mii); 203691398Stmm ifmr->ifm_active = sc->sc_mii->mii_media_active; 203791398Stmm ifmr->ifm_status = sc->sc_mii->mii_media_status; 2038148369Smarius GEM_UNLOCK(sc); 203991398Stmm} 204091398Stmm 204191398Stmmstatic int 2042174987Smariusgem_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) 204391398Stmm{ 204491398Stmm struct gem_softc *sc = ifp->if_softc; 204591398Stmm struct ifreq *ifr = (struct ifreq *)data; 2046174987Smarius int error; 204791398Stmm 2048174987Smarius error = 0; 204991398Stmm switch (cmd) { 2050150285Smarius case SIOCSIFFLAGS: 2051148369Smarius GEM_LOCK(sc); 2052174987Smarius if ((ifp->if_flags & IFF_UP) != 0) { 2053172334Smarius if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0 && 2054172334Smarius ((ifp->if_flags ^ sc->sc_ifflags) & 2055172334Smarius (IFF_ALLMULTI | IFF_PROMISC)) != 0) 205691398Stmm gem_setladrf(sc); 205791398Stmm else 2058148369Smarius gem_init_locked(sc); 2059174987Smarius } else if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) 2060174987Smarius gem_stop(ifp, 0); 2061170273Syongari if ((ifp->if_flags & IFF_LINK0) != 0) 2062170273Syongari sc->sc_csum_features |= CSUM_UDP; 2063170273Syongari else 2064170273Syongari sc->sc_csum_features &= ~CSUM_UDP; 2065170273Syongari if ((ifp->if_capenable & IFCAP_TXCSUM) != 0) 2066170273Syongari ifp->if_hwassist = sc->sc_csum_features; 206799726Sbenno sc->sc_ifflags = ifp->if_flags; 2068150285Smarius GEM_UNLOCK(sc); 206991398Stmm break; 207091398Stmm case SIOCADDMULTI: 207191398Stmm case SIOCDELMULTI: 2072150285Smarius GEM_LOCK(sc); 207391398Stmm gem_setladrf(sc); 2074150285Smarius GEM_UNLOCK(sc); 207591398Stmm break; 207691398Stmm case SIOCGIFMEDIA: 207791398Stmm case SIOCSIFMEDIA: 207891398Stmm error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii->mii_media, cmd); 207991398Stmm break; 2080170273Syongari case SIOCSIFCAP: 2081170273Syongari GEM_LOCK(sc); 2082170273Syongari ifp->if_capenable = ifr->ifr_reqcap; 2083170273Syongari if ((ifp->if_capenable & IFCAP_TXCSUM) != 0) 2084170273Syongari ifp->if_hwassist = sc->sc_csum_features; 2085170273Syongari else 2086170273Syongari ifp->if_hwassist = 0; 2087170273Syongari GEM_UNLOCK(sc); 2088170273Syongari break; 208991398Stmm default: 2090150285Smarius error = ether_ioctl(ifp, cmd, data); 209191398Stmm break; 209291398Stmm } 209391398Stmm 209491398Stmm return (error); 209591398Stmm} 209691398Stmm 209791398Stmmstatic void 2098174987Smariusgem_setladrf(struct gem_softc *sc) 209991398Stmm{ 2100147256Sbrooks struct ifnet *ifp = sc->sc_ifp; 210191398Stmm struct ifmultiaddr *inm; 210299726Sbenno int i; 2103174987Smarius uint32_t hash[16]; 2104174987Smarius uint32_t crc, v; 210591398Stmm 2106148369Smarius GEM_LOCK_ASSERT(sc, MA_OWNED); 2107148369Smarius 2108174987Smarius /* Get the current RX configuration. */ 2109169269Sphk v = bus_read_4(sc->sc_res[0], GEM_MAC_RX_CONFIG); 211091398Stmm 211199726Sbenno /* 211299726Sbenno * Turn off promiscuous mode, promiscuous group mode (all multicast), 211399726Sbenno * and hash filter. Depending on the case, the right bit will be 211499726Sbenno * enabled. 211599726Sbenno */ 2116174987Smarius v &= ~(GEM_MAC_RX_PROMISCUOUS | GEM_MAC_RX_HASH_FILTER | 211799726Sbenno GEM_MAC_RX_PROMISC_GRP); 211899726Sbenno 2119172334Smarius bus_write_4(sc->sc_res[0], GEM_MAC_RX_CONFIG, v); 2120172334Smarius bus_barrier(sc->sc_res[0], GEM_MAC_RX_CONFIG, 4, 2121172334Smarius BUS_SPACE_BARRIER_WRITE); 2122172334Smarius if (!gem_bitwait(sc, GEM_MAC_RX_CONFIG, GEM_MAC_RX_HASH_FILTER, 0)) 2123172334Smarius device_printf(sc->sc_dev, "cannot disable RX hash filter\n"); 2124172334Smarius 212591398Stmm if ((ifp->if_flags & IFF_PROMISC) != 0) { 212691398Stmm v |= GEM_MAC_RX_PROMISCUOUS; 212791398Stmm goto chipit; 212891398Stmm } 212991398Stmm if ((ifp->if_flags & IFF_ALLMULTI) != 0) { 213099726Sbenno v |= GEM_MAC_RX_PROMISC_GRP; 213191398Stmm goto chipit; 213291398Stmm } 213391398Stmm 213491398Stmm /* 2135174987Smarius * Set up multicast address filter by passing all multicast 2136174987Smarius * addresses through a crc generator, and then using the high 2137174987Smarius * order 8 bits as an index into the 256 bit logical address 2138174987Smarius * filter. The high order 4 bits selects the word, while the 2139174987Smarius * other 4 bits select the bit within the word (where bit 0 2140174987Smarius * is the MSB). 214191398Stmm */ 214291398Stmm 2143174987Smarius /* Clear the hash table. */ 214499726Sbenno memset(hash, 0, sizeof(hash)); 214599726Sbenno 2146148654Srwatson IF_ADDR_LOCK(ifp); 2147147256Sbrooks TAILQ_FOREACH(inm, &ifp->if_multiaddrs, ifma_link) { 214891398Stmm if (inm->ifma_addr->sa_family != AF_LINK) 214991398Stmm continue; 2150130288Smarius crc = ether_crc32_le(LLADDR((struct sockaddr_dl *) 2151130288Smarius inm->ifma_addr), ETHER_ADDR_LEN); 215291398Stmm 2153174987Smarius /* We just want the 8 most significant bits. */ 215491398Stmm crc >>= 24; 215591398Stmm 215691398Stmm /* Set the corresponding bit in the filter. */ 215799726Sbenno hash[crc >> 4] |= 1 << (15 - (crc & 15)); 215891398Stmm } 2159148654Srwatson IF_ADDR_UNLOCK(ifp); 216091398Stmm 216199726Sbenno v |= GEM_MAC_RX_HASH_FILTER; 216299726Sbenno 2163174987Smarius /* Now load the hash table into the chip (if we are using it). */ 2164174987Smarius for (i = 0; i < 16; i++) 2165169269Sphk bus_write_4(sc->sc_res[0], 2166174987Smarius GEM_MAC_HASH0 + i * (GEM_MAC_HASH1 - GEM_MAC_HASH0), 216799726Sbenno hash[i]); 216899726Sbenno 2169174987Smarius chipit: 2170169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_RX_CONFIG, v); 217191398Stmm} 2172