if_gem.c revision 170273
1119418Sobrien/*- 291398Stmm * Copyright (C) 2001 Eduardo Horvath. 3108832Stmm * Copyright (c) 2001-2003 Thomas Moestl 491398Stmm * All rights reserved. 591398Stmm * 691398Stmm * Redistribution and use in source and binary forms, with or without 791398Stmm * modification, are permitted provided that the following conditions 891398Stmm * are met: 991398Stmm * 1. Redistributions of source code must retain the above copyright 1091398Stmm * notice, this list of conditions and the following disclaimer. 1191398Stmm * 2. Redistributions in binary form must reproduce the above copyright 1291398Stmm * notice, this list of conditions and the following disclaimer in the 1391398Stmm * documentation and/or other materials provided with the distribution. 1491398Stmm * 1591398Stmm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND 1691398Stmm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1791398Stmm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1891398Stmm * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE 1991398Stmm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2091398Stmm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2191398Stmm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2291398Stmm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2391398Stmm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2491398Stmm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2591398Stmm * SUCH DAMAGE. 2691398Stmm * 2799726Sbenno * from: NetBSD: gem.c,v 1.21 2002/06/01 23:50:58 lukem Exp 2891398Stmm */ 2991398Stmm 30119418Sobrien#include <sys/cdefs.h> 31119418Sobrien__FBSDID("$FreeBSD: head/sys/dev/gem/if_gem.c 170273 2007-06-04 06:01:04Z yongari $"); 32119418Sobrien 3391398Stmm/* 3491398Stmm * Driver for Sun GEM ethernet controllers. 3591398Stmm */ 3691398Stmm 37115030Stmm#if 0 3891398Stmm#define GEM_DEBUG 39115030Stmm#endif 4091398Stmm 41148368Smarius#if 0 /* XXX: In case of emergency, re-enable this. */ 42148368Smarius#define GEM_RINT_TIMEOUT 43148368Smarius#endif 44148368Smarius 4591398Stmm#include <sys/param.h> 4691398Stmm#include <sys/systm.h> 4791398Stmm#include <sys/bus.h> 4891398Stmm#include <sys/callout.h> 4995533Smike#include <sys/endian.h> 5091398Stmm#include <sys/mbuf.h> 5191398Stmm#include <sys/malloc.h> 5291398Stmm#include <sys/kernel.h> 53148369Smarius#include <sys/lock.h> 54130026Sphk#include <sys/module.h> 55148369Smarius#include <sys/mutex.h> 5691398Stmm#include <sys/socket.h> 5791398Stmm#include <sys/sockio.h> 58169269Sphk#include <sys/rman.h> 5991398Stmm 60105982Stmm#include <net/bpf.h> 6191398Stmm#include <net/ethernet.h> 6291398Stmm#include <net/if.h> 6391398Stmm#include <net/if_arp.h> 6491398Stmm#include <net/if_dl.h> 6591398Stmm#include <net/if_media.h> 66147256Sbrooks#include <net/if_types.h> 67149552Smarius#include <net/if_vlan_var.h> 6891398Stmm 69170273Syongari#include <netinet/in.h> 70170273Syongari#include <netinet/in_systm.h> 71170273Syongari#include <netinet/ip.h> 72170273Syongari#include <netinet/tcp.h> 73170273Syongari#include <netinet/udp.h> 74170273Syongari 7591398Stmm#include <machine/bus.h> 7691398Stmm 7791398Stmm#include <dev/mii/mii.h> 7891398Stmm#include <dev/mii/miivar.h> 7991398Stmm 80119355Simp#include <dev/gem/if_gemreg.h> 81119355Simp#include <dev/gem/if_gemvar.h> 8291398Stmm 8391398Stmm#define TRIES 10000 84170273Syongari/* 85170273Syongari * The GEM hardware support basic TCP/UDP checksum offloading. However, 86170273Syongari * the hardware doesn't compensate the checksum for UDP datagram which 87170273Syongari * can yield to 0x0. As a safe guard, UDP checksum offload is disabled 88170273Syongari * by default. It can be reactivated by setting special link option 89170273Syongari * link0 with ifconfig(8). 90170273Syongari */ 91170273Syongari#define GEM_CSUM_FEATURES (CSUM_TCP) 9291398Stmm 9392739Salfredstatic void gem_start(struct ifnet *); 94148369Smariusstatic void gem_start_locked(struct ifnet *); 9592739Salfredstatic void gem_stop(struct ifnet *, int); 9692739Salfredstatic int gem_ioctl(struct ifnet *, u_long, caddr_t); 9792739Salfredstatic void gem_cddma_callback(void *, bus_dma_segment_t *, int, int); 98170273Syongaristatic __inline void gem_txcksum(struct gem_softc *, struct mbuf *, uint64_t *); 99170273Syongaristatic __inline void gem_rxcksum(struct mbuf *, uint64_t); 10092739Salfredstatic void gem_tick(void *); 101164931Smariusstatic int gem_watchdog(struct gem_softc *); 10292739Salfredstatic void gem_init(void *); 103164931Smariusstatic void gem_init_locked(struct gem_softc *); 104164931Smariusstatic void gem_init_regs(struct gem_softc *); 10592739Salfredstatic int gem_ringsize(int sz); 10692739Salfredstatic int gem_meminit(struct gem_softc *); 107170273Syongaristatic struct mbuf *gem_defrag(struct mbuf *, int, int); 108170273Syongaristatic int gem_load_txmbuf(struct gem_softc *, struct mbuf **); 10992739Salfredstatic void gem_mifinit(struct gem_softc *); 110164931Smariusstatic int gem_bitwait(struct gem_softc *, bus_addr_t, u_int32_t, 111164931Smarius u_int32_t); 11292739Salfredstatic int gem_reset_rx(struct gem_softc *); 11392739Salfredstatic int gem_reset_tx(struct gem_softc *); 11492739Salfredstatic int gem_disable_rx(struct gem_softc *); 11592739Salfredstatic int gem_disable_tx(struct gem_softc *); 11692739Salfredstatic void gem_rxdrain(struct gem_softc *); 11792739Salfredstatic int gem_add_rxbuf(struct gem_softc *, int); 11892739Salfredstatic void gem_setladrf(struct gem_softc *); 11991398Stmm 12092739Salfredstruct mbuf *gem_get(struct gem_softc *, int, int); 12192739Salfredstatic void gem_eint(struct gem_softc *, u_int); 12292739Salfredstatic void gem_rint(struct gem_softc *); 123148368Smarius#ifdef GEM_RINT_TIMEOUT 12493045Stmmstatic void gem_rint_timeout(void *); 125100587Sjake#endif 12692739Salfredstatic void gem_tint(struct gem_softc *); 12791398Stmm#ifdef notyet 12892739Salfredstatic void gem_power(int, void *); 12991398Stmm#endif 13091398Stmm 13191398Stmmdevclass_t gem_devclass; 13291398StmmDRIVER_MODULE(miibus, gem, miibus_driver, miibus_devclass, 0, 0); 13391398StmmMODULE_DEPEND(gem, miibus, 1, 1, 1); 13491398Stmm 13591398Stmm#ifdef GEM_DEBUG 13691398Stmm#include <sys/ktr.h> 13791398Stmm#define KTR_GEM KTR_CT2 13891398Stmm#endif 13991398Stmm 140115030Stmm#define GEM_NSEGS GEM_NTXDESC 14191398Stmm 14291398Stmm/* 14391398Stmm * gem_attach: 14491398Stmm * 14591398Stmm * Attach a Gem interface to the system. 14691398Stmm */ 14791398Stmmint 14891398Stmmgem_attach(sc) 14991398Stmm struct gem_softc *sc; 15091398Stmm{ 151147256Sbrooks struct ifnet *ifp; 15291398Stmm struct mii_softc *child; 15391398Stmm int i, error; 15499726Sbenno u_int32_t v; 15591398Stmm 156147256Sbrooks ifp = sc->sc_ifp = if_alloc(IFT_ETHER); 157147256Sbrooks if (ifp == NULL) 158147256Sbrooks return (ENOSPC); 159147256Sbrooks 160150285Smarius callout_init_mtx(&sc->sc_tick_ch, &sc->sc_mtx, 0); 161150285Smarius#ifdef GEM_RINT_TIMEOUT 162150285Smarius callout_init_mtx(&sc->sc_rx_ch, &sc->sc_mtx, 0); 163150285Smarius#endif 164150285Smarius 16591398Stmm /* Make sure the chip is stopped. */ 16691398Stmm ifp->if_softc = sc; 167148369Smarius GEM_LOCK(sc); 168150285Smarius gem_stop(ifp, 0); 16991398Stmm gem_reset(sc); 170148369Smarius GEM_UNLOCK(sc); 17191398Stmm 172161928Sjmg error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), 1, 0, 173161928Sjmg BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, 174170273Syongari BUS_SPACE_MAXSIZE_32BIT, 0, BUS_SPACE_MAXSIZE_32BIT, 0, NULL, NULL, 175161928Sjmg &sc->sc_pdmatag); 17691398Stmm if (error) 177147256Sbrooks goto fail_ifnet; 17891398Stmm 17991398Stmm error = bus_dma_tag_create(sc->sc_pdmatag, 1, 0, 180170273Syongari BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, MCLBYTES, 181170273Syongari 1, MCLBYTES, BUS_DMA_ALLOCNOW, NULL, NULL, &sc->sc_rdmatag); 18291398Stmm if (error) 183108832Stmm goto fail_ptag; 18491398Stmm 185108832Stmm error = bus_dma_tag_create(sc->sc_pdmatag, 1, 0, 186170273Syongari BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, 187170273Syongari MCLBYTES * GEM_NTXSEGS, GEM_NTXSEGS, MCLBYTES, 188117126Sscottl BUS_DMA_ALLOCNOW, NULL, NULL, &sc->sc_tdmatag); 189108832Stmm if (error) 190108832Stmm goto fail_rtag; 191108832Stmm 19291398Stmm error = bus_dma_tag_create(sc->sc_pdmatag, PAGE_SIZE, 0, 193170273Syongari BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, 19491398Stmm sizeof(struct gem_control_data), 1, 195170273Syongari sizeof(struct gem_control_data), 0, 196170273Syongari NULL, NULL, &sc->sc_cdmatag); 19791398Stmm if (error) 198108832Stmm goto fail_ttag; 19991398Stmm 20091398Stmm /* 20191398Stmm * Allocate the control data structures, and create and load the 20291398Stmm * DMA map for it. 20391398Stmm */ 20491398Stmm if ((error = bus_dmamem_alloc(sc->sc_cdmatag, 205170273Syongari (void **)&sc->sc_control_data, 206170273Syongari BUS_DMA_WAITOK | BUS_DMA_COHERENT | BUS_DMA_ZERO, 207170273Syongari &sc->sc_cddmamap))) { 20891398Stmm device_printf(sc->sc_dev, "unable to allocate control data," 20991398Stmm " error = %d\n", error); 210108832Stmm goto fail_ctag; 21191398Stmm } 21291398Stmm 21391398Stmm sc->sc_cddma = 0; 21491398Stmm if ((error = bus_dmamap_load(sc->sc_cdmatag, sc->sc_cddmamap, 21591398Stmm sc->sc_control_data, sizeof(struct gem_control_data), 21691398Stmm gem_cddma_callback, sc, 0)) != 0 || sc->sc_cddma == 0) { 21791398Stmm device_printf(sc->sc_dev, "unable to load control data DMA " 21891398Stmm "map, error = %d\n", error); 219108832Stmm goto fail_cmem; 22091398Stmm } 22191398Stmm 22291398Stmm /* 22391398Stmm * Initialize the transmit job descriptors. 22491398Stmm */ 22591398Stmm STAILQ_INIT(&sc->sc_txfreeq); 22691398Stmm STAILQ_INIT(&sc->sc_txdirtyq); 22791398Stmm 22891398Stmm /* 22991398Stmm * Create the transmit buffer DMA maps. 23091398Stmm */ 23191398Stmm error = ENOMEM; 23291398Stmm for (i = 0; i < GEM_TXQUEUELEN; i++) { 23391398Stmm struct gem_txsoft *txs; 23491398Stmm 23591398Stmm txs = &sc->sc_txsoft[i]; 23691398Stmm txs->txs_mbuf = NULL; 23791398Stmm txs->txs_ndescs = 0; 238108832Stmm if ((error = bus_dmamap_create(sc->sc_tdmatag, 0, 23991398Stmm &txs->txs_dmamap)) != 0) { 24091398Stmm device_printf(sc->sc_dev, "unable to create tx DMA map " 24191398Stmm "%d, error = %d\n", i, error); 242108832Stmm goto fail_txd; 24391398Stmm } 24491398Stmm STAILQ_INSERT_TAIL(&sc->sc_txfreeq, txs, txs_q); 24591398Stmm } 24691398Stmm 24791398Stmm /* 24891398Stmm * Create the receive buffer DMA maps. 24991398Stmm */ 25091398Stmm for (i = 0; i < GEM_NRXDESC; i++) { 251108832Stmm if ((error = bus_dmamap_create(sc->sc_rdmatag, 0, 25291398Stmm &sc->sc_rxsoft[i].rxs_dmamap)) != 0) { 25391398Stmm device_printf(sc->sc_dev, "unable to create rx DMA map " 25491398Stmm "%d, error = %d\n", i, error); 255108832Stmm goto fail_rxd; 25691398Stmm } 25791398Stmm sc->sc_rxsoft[i].rxs_mbuf = NULL; 25891398Stmm } 25991398Stmm 26091398Stmm gem_mifinit(sc); 26191398Stmm 26291398Stmm if ((error = mii_phy_probe(sc->sc_dev, &sc->sc_miibus, gem_mediachange, 26391398Stmm gem_mediastatus)) != 0) { 26491398Stmm device_printf(sc->sc_dev, "phy probe failed: %d\n", error); 265108832Stmm goto fail_rxd; 26691398Stmm } 26791398Stmm sc->sc_mii = device_get_softc(sc->sc_miibus); 26891398Stmm 26991398Stmm /* 27091398Stmm * From this point forward, the attachment cannot fail. A failure 27191398Stmm * before this point releases all resources that may have been 27291398Stmm * allocated. 27391398Stmm */ 27491398Stmm 27599726Sbenno /* Get RX FIFO size */ 27699726Sbenno sc->sc_rxfifosize = 64 * 277169269Sphk bus_read_4(sc->sc_res[0], GEM_RX_FIFO_SIZE); 27899726Sbenno 27999726Sbenno /* Get TX FIFO size */ 280169269Sphk v = bus_read_4(sc->sc_res[0], GEM_TX_FIFO_SIZE); 281128588Stmm device_printf(sc->sc_dev, "%ukB RX FIFO, %ukB TX FIFO\n", 282128588Stmm sc->sc_rxfifosize / 1024, v / 16); 28399726Sbenno 284170273Syongari sc->sc_csum_features = GEM_CSUM_FEATURES; 28591398Stmm /* Initialize ifnet structure. */ 28691398Stmm ifp->if_softc = sc; 287121816Sbrooks if_initname(ifp, device_get_name(sc->sc_dev), 288121816Sbrooks device_get_unit(sc->sc_dev)); 289148369Smarius ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 29091398Stmm ifp->if_start = gem_start; 29191398Stmm ifp->if_ioctl = gem_ioctl; 29291398Stmm ifp->if_init = gem_init; 293170273Syongari IFQ_SET_MAXLEN(&ifp->if_snd, GEM_TXQUEUELEN); 294170273Syongari ifp->if_snd.ifq_drv_maxlen = GEM_TXQUEUELEN; 295170273Syongari IFQ_SET_READY(&ifp->if_snd); 29691398Stmm /* 29791398Stmm * Walk along the list of attached MII devices and 29891398Stmm * establish an `MII instance' to `phy number' 29991398Stmm * mapping. We'll use this mapping in media change 30091398Stmm * requests to determine which phy to use to program 30191398Stmm * the MIF configuration register. 30291398Stmm */ 30391398Stmm for (child = LIST_FIRST(&sc->sc_mii->mii_phys); child != NULL; 30491398Stmm child = LIST_NEXT(child, mii_list)) { 30591398Stmm /* 30691398Stmm * Note: we support just two PHYs: the built-in 30791398Stmm * internal device and an external on the MII 30891398Stmm * connector. 30991398Stmm */ 31091398Stmm if (child->mii_phy > 1 || child->mii_inst > 1) { 31191398Stmm device_printf(sc->sc_dev, "cannot accomodate " 31291398Stmm "MII device %s at phy %d, instance %d\n", 31391398Stmm device_get_name(child->mii_dev), 31491398Stmm child->mii_phy, child->mii_inst); 31591398Stmm continue; 31691398Stmm } 31791398Stmm 31891398Stmm sc->sc_phys[child->mii_inst] = child->mii_phy; 31991398Stmm } 32091398Stmm 32191398Stmm /* 32291398Stmm * Now select and activate the PHY we will use. 32391398Stmm * 32491398Stmm * The order of preference is External (MDI1), 32591398Stmm * Internal (MDI0), Serial Link (no MII). 32691398Stmm */ 32791398Stmm if (sc->sc_phys[1]) { 32891398Stmm#ifdef GEM_DEBUG 32991398Stmm printf("using external phy\n"); 33091398Stmm#endif 33191398Stmm sc->sc_mif_config |= GEM_MIF_CONFIG_PHY_SEL; 33291398Stmm } else { 33391398Stmm#ifdef GEM_DEBUG 33491398Stmm printf("using internal phy\n"); 33591398Stmm#endif 33691398Stmm sc->sc_mif_config &= ~GEM_MIF_CONFIG_PHY_SEL; 33791398Stmm } 338169269Sphk bus_write_4(sc->sc_res[0], GEM_MIF_CONFIG, 33991398Stmm sc->sc_mif_config); 34091398Stmm /* Attach the interface. */ 341147256Sbrooks ether_ifattach(ifp, sc->sc_enaddr); 34291398Stmm 343153110Sru#ifdef notyet 34491398Stmm /* 34591398Stmm * Add a suspend hook to make sure we come back up after a 34691398Stmm * resume. 34791398Stmm */ 34891398Stmm sc->sc_powerhook = powerhook_establish(gem_power, sc); 34991398Stmm if (sc->sc_powerhook == NULL) 35091398Stmm device_printf(sc->sc_dev, "WARNING: unable to establish power " 35191398Stmm "hook\n"); 35291398Stmm#endif 35391398Stmm 354149552Smarius /* 355170273Syongari * Tell the upper layer(s) we support long frames/checksum offloads. 356149552Smarius */ 357149552Smarius ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header); 358170273Syongari ifp->if_capabilities |= IFCAP_VLAN_MTU | IFCAP_HWCSUM; 359170273Syongari ifp->if_hwassist |= sc->sc_csum_features; 360170273Syongari ifp->if_capenable |= IFCAP_VLAN_MTU | IFCAP_HWCSUM; 361149552Smarius 36291398Stmm return (0); 36391398Stmm 36491398Stmm /* 36591398Stmm * Free any resources we've allocated during the failed attach 36691398Stmm * attempt. Do this in reverse order and fall through. 36791398Stmm */ 368108832Stmmfail_rxd: 36991398Stmm for (i = 0; i < GEM_NRXDESC; i++) { 37091398Stmm if (sc->sc_rxsoft[i].rxs_dmamap != NULL) 371108832Stmm bus_dmamap_destroy(sc->sc_rdmatag, 37291398Stmm sc->sc_rxsoft[i].rxs_dmamap); 37391398Stmm } 374108832Stmmfail_txd: 37591398Stmm 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); 37991398Stmm } 380108832Stmm bus_dmamap_unload(sc->sc_cdmatag, sc->sc_cddmamap); 381108832Stmmfail_cmem: 38291398Stmm bus_dmamem_free(sc->sc_cdmatag, sc->sc_control_data, 38391398Stmm sc->sc_cddmamap); 384108832Stmmfail_ctag: 38591398Stmm bus_dma_tag_destroy(sc->sc_cdmatag); 386108832Stmmfail_ttag: 387108832Stmm bus_dma_tag_destroy(sc->sc_tdmatag); 388108832Stmmfail_rtag: 389108832Stmm bus_dma_tag_destroy(sc->sc_rdmatag); 390108832Stmmfail_ptag: 39191398Stmm bus_dma_tag_destroy(sc->sc_pdmatag); 392147256Sbrooksfail_ifnet: 393147256Sbrooks if_free(ifp); 39491398Stmm return (error); 39591398Stmm} 39691398Stmm 397108964Stmmvoid 398108964Stmmgem_detach(sc) 399108964Stmm struct gem_softc *sc; 400108964Stmm{ 401147256Sbrooks struct ifnet *ifp = sc->sc_ifp; 402108964Stmm int i; 403108964Stmm 404148369Smarius GEM_LOCK(sc); 405147317Sbrooks gem_stop(ifp, 1); 406148369Smarius GEM_UNLOCK(sc); 407150285Smarius callout_drain(&sc->sc_tick_ch); 408150285Smarius#ifdef GEM_RINT_TIMEOUT 409150285Smarius callout_drain(&sc->sc_rx_ch); 410150285Smarius#endif 411108964Stmm ether_ifdetach(ifp); 412147256Sbrooks if_free(ifp); 413108964Stmm device_delete_child(sc->sc_dev, sc->sc_miibus); 414108964Stmm 415108964Stmm for (i = 0; i < GEM_NRXDESC; i++) { 416108964Stmm if (sc->sc_rxsoft[i].rxs_dmamap != NULL) 417108964Stmm bus_dmamap_destroy(sc->sc_rdmatag, 418108964Stmm sc->sc_rxsoft[i].rxs_dmamap); 419108964Stmm } 420108964Stmm for (i = 0; i < GEM_TXQUEUELEN; i++) { 421108964Stmm if (sc->sc_txsoft[i].txs_dmamap != NULL) 422108964Stmm bus_dmamap_destroy(sc->sc_tdmatag, 423108964Stmm sc->sc_txsoft[i].txs_dmamap); 424108964Stmm } 425109648Stmm GEM_CDSYNC(sc, BUS_DMASYNC_POSTREAD); 426109648Stmm GEM_CDSYNC(sc, BUS_DMASYNC_POSTWRITE); 427108964Stmm bus_dmamap_unload(sc->sc_cdmatag, sc->sc_cddmamap); 428108964Stmm bus_dmamem_free(sc->sc_cdmatag, sc->sc_control_data, 429108964Stmm sc->sc_cddmamap); 430108964Stmm bus_dma_tag_destroy(sc->sc_cdmatag); 431108964Stmm bus_dma_tag_destroy(sc->sc_tdmatag); 432108964Stmm bus_dma_tag_destroy(sc->sc_rdmatag); 433108964Stmm bus_dma_tag_destroy(sc->sc_pdmatag); 434108964Stmm} 435108964Stmm 436108964Stmmvoid 437108964Stmmgem_suspend(sc) 438108964Stmm struct gem_softc *sc; 439108964Stmm{ 440147256Sbrooks struct ifnet *ifp = sc->sc_ifp; 441108964Stmm 442148369Smarius GEM_LOCK(sc); 443108964Stmm gem_stop(ifp, 0); 444148369Smarius GEM_UNLOCK(sc); 445108964Stmm} 446108964Stmm 447108964Stmmvoid 448108964Stmmgem_resume(sc) 449108964Stmm struct gem_softc *sc; 450108964Stmm{ 451147256Sbrooks struct ifnet *ifp = sc->sc_ifp; 452108964Stmm 453148369Smarius GEM_LOCK(sc); 454149552Smarius /* 455149552Smarius * On resume all registers have to be initialized again like 456149552Smarius * after power-on. 457149552Smarius */ 458149552Smarius sc->sc_inited = 0; 459108964Stmm if (ifp->if_flags & IFF_UP) 460148369Smarius gem_init_locked(sc); 461148369Smarius GEM_UNLOCK(sc); 462108964Stmm} 463108964Stmm 464170273Syongaristatic __inline void 465170273Syongarigem_txcksum(struct gem_softc *sc, struct mbuf *m, uint64_t *cflags) 466170273Syongari{ 467170273Syongari struct ip *ip; 468170273Syongari uint64_t offset, offset2; 469170273Syongari char *p; 470170273Syongari 471170273Syongari offset = sizeof(struct ip) + ETHER_HDR_LEN; 472170273Syongari for(; m && m->m_len == 0; m = m->m_next) 473170273Syongari ; 474170273Syongari if (m == NULL || m->m_len < ETHER_HDR_LEN) { 475170273Syongari device_printf(sc->sc_dev, "%s: m_len < ETHER_HDR_LEN\n", 476170273Syongari __func__); 477170273Syongari /* checksum will be corrupted */ 478170273Syongari goto sendit; 479170273Syongari } 480170273Syongari if (m->m_len < ETHER_HDR_LEN + sizeof(uint32_t)) { 481170273Syongari if (m->m_len != ETHER_HDR_LEN) { 482170273Syongari device_printf(sc->sc_dev, 483170273Syongari "%s: m_len != ETHER_HDR_LEN\n", __func__); 484170273Syongari /* checksum will be corrupted */ 485170273Syongari goto sendit; 486170273Syongari } 487170273Syongari for(m = m->m_next; m && m->m_len == 0; m = m->m_next) 488170273Syongari ; 489170273Syongari if (m == NULL) { 490170273Syongari /* checksum will be corrupted */ 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 501170273Syongarisendit: 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; 514170273Syongari int32_t hlen, len, pktlen; 515170273Syongari uint16_t cksum, *opts; 516170273Syongari uint32_t temp32; 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)) 537170273Syongari return; /* can't 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 57191398Stmmgem_cddma_callback(xsc, segs, nsegs, error) 57291398Stmm void *xsc; 57391398Stmm bus_dma_segment_t *segs; 57491398Stmm int nsegs; 57591398Stmm int error; 57691398Stmm{ 57791398Stmm struct gem_softc *sc = (struct gem_softc *)xsc; 57891398Stmm 57991398Stmm if (error != 0) 58091398Stmm return; 58191398Stmm if (nsegs != 1) { 58291398Stmm /* can't happen... */ 58391398Stmm panic("gem_cddma_callback: bad control buffer segment count"); 58491398Stmm } 58591398Stmm sc->sc_cddma = segs[0].ds_addr; 58691398Stmm} 58791398Stmm 58891398Stmmstatic void 589170273Syongarigem_tick(arg) 590170273Syongari void *arg; 59191398Stmm{ 592170273Syongari struct gem_softc *sc = arg; 593170273Syongari struct ifnet *ifp; 59491398Stmm 595170273Syongari GEM_LOCK_ASSERT(sc, MA_OWNED); 596170273Syongari 597170273Syongari ifp = sc->sc_ifp; 598108832Stmm /* 599170273Syongari * Unload collision counters 600108832Stmm */ 601170273Syongari ifp->if_collisions += 602170273Syongari bus_read_4(sc->sc_res[0], GEM_MAC_NORM_COLL_CNT) + 603170273Syongari bus_read_4(sc->sc_res[0], GEM_MAC_FIRST_COLL_CNT) + 604170273Syongari bus_read_4(sc->sc_res[0], GEM_MAC_EXCESS_COLL_CNT) + 605170273Syongari bus_read_4(sc->sc_res[0], GEM_MAC_LATE_COLL_CNT); 60691398Stmm 60791398Stmm /* 608170273Syongari * then clear the hardware counters. 60991398Stmm */ 610170273Syongari bus_write_4(sc->sc_res[0], GEM_MAC_NORM_COLL_CNT, 0); 611170273Syongari bus_write_4(sc->sc_res[0], GEM_MAC_FIRST_COLL_CNT, 0); 612170273Syongari bus_write_4(sc->sc_res[0], GEM_MAC_EXCESS_COLL_CNT, 0); 613170273Syongari bus_write_4(sc->sc_res[0], GEM_MAC_LATE_COLL_CNT, 0); 614108832Stmm 61591398Stmm mii_tick(sc->sc_mii); 61691398Stmm 617164931Smarius if (gem_watchdog(sc) == EJUSTRETURN) 618164931Smarius return; 619164931Smarius 62091398Stmm callout_reset(&sc->sc_tick_ch, hz, gem_tick, sc); 62191398Stmm} 62291398Stmm 62391398Stmmstatic int 62491398Stmmgem_bitwait(sc, r, clr, set) 62591398Stmm struct gem_softc *sc; 62691398Stmm bus_addr_t r; 62791398Stmm u_int32_t clr; 62891398Stmm u_int32_t set; 62991398Stmm{ 63091398Stmm int i; 63191398Stmm u_int32_t reg; 63291398Stmm 63391398Stmm for (i = TRIES; i--; DELAY(100)) { 634169269Sphk reg = bus_read_4(sc->sc_res[0], r); 63591398Stmm if ((r & clr) == 0 && (r & set) == set) 63691398Stmm return (1); 63791398Stmm } 63891398Stmm return (0); 63991398Stmm} 64091398Stmm 64191398Stmmvoid 64291398Stmmgem_reset(sc) 64391398Stmm struct gem_softc *sc; 64491398Stmm{ 64591398Stmm 646115030Stmm#ifdef GEM_DEBUG 647170273Syongari CTR2(KTR_GEM, "%s: %s", device_get_name(sc->sc_dev), __func__); 648115030Stmm#endif 64991398Stmm gem_reset_rx(sc); 65091398Stmm gem_reset_tx(sc); 65191398Stmm 65291398Stmm /* Do a full reset */ 653169269Sphk bus_write_4(sc->sc_res[0], GEM_RESET, GEM_RESET_RX | GEM_RESET_TX); 65491398Stmm if (!gem_bitwait(sc, GEM_RESET, GEM_RESET_RX | GEM_RESET_TX, 0)) 65591398Stmm device_printf(sc->sc_dev, "cannot reset device\n"); 65691398Stmm} 65791398Stmm 65891398Stmm 65991398Stmm/* 66091398Stmm * gem_rxdrain: 66191398Stmm * 66291398Stmm * Drain the receive queue. 66391398Stmm */ 66491398Stmmstatic void 66591398Stmmgem_rxdrain(sc) 66691398Stmm struct gem_softc *sc; 66791398Stmm{ 66891398Stmm struct gem_rxsoft *rxs; 66991398Stmm int i; 67091398Stmm 67191398Stmm for (i = 0; i < GEM_NRXDESC; i++) { 67291398Stmm rxs = &sc->sc_rxsoft[i]; 67391398Stmm if (rxs->rxs_mbuf != NULL) { 674109648Stmm bus_dmamap_sync(sc->sc_rdmatag, rxs->rxs_dmamap, 675109648Stmm BUS_DMASYNC_POSTREAD); 676108832Stmm bus_dmamap_unload(sc->sc_rdmatag, rxs->rxs_dmamap); 67791398Stmm m_freem(rxs->rxs_mbuf); 67891398Stmm rxs->rxs_mbuf = NULL; 67991398Stmm } 68091398Stmm } 68191398Stmm} 68291398Stmm 68391398Stmm/* 68491398Stmm * Reset the whole thing. 68591398Stmm */ 68691398Stmmstatic void 68791398Stmmgem_stop(ifp, disable) 68891398Stmm struct ifnet *ifp; 68991398Stmm int disable; 69091398Stmm{ 69191398Stmm struct gem_softc *sc = (struct gem_softc *)ifp->if_softc; 69291398Stmm struct gem_txsoft *txs; 69391398Stmm 694115030Stmm#ifdef GEM_DEBUG 695170273Syongari CTR2(KTR_GEM, "%s: %s", device_get_name(sc->sc_dev), __func__); 696115030Stmm#endif 69791398Stmm 69891398Stmm callout_stop(&sc->sc_tick_ch); 699150285Smarius#ifdef GEM_RINT_TIMEOUT 700150285Smarius callout_stop(&sc->sc_rx_ch); 701150285Smarius#endif 70291398Stmm 70391398Stmm /* XXX - Should we reset these instead? */ 70491398Stmm gem_disable_tx(sc); 70591398Stmm gem_disable_rx(sc); 70691398Stmm 70791398Stmm /* 70891398Stmm * Release any queued transmit buffers. 70991398Stmm */ 71091398Stmm while ((txs = STAILQ_FIRST(&sc->sc_txdirtyq)) != NULL) { 71191398Stmm STAILQ_REMOVE_HEAD(&sc->sc_txdirtyq, txs_q); 71291398Stmm if (txs->txs_ndescs != 0) { 713109648Stmm bus_dmamap_sync(sc->sc_tdmatag, txs->txs_dmamap, 714109648Stmm BUS_DMASYNC_POSTWRITE); 715108832Stmm bus_dmamap_unload(sc->sc_tdmatag, txs->txs_dmamap); 71691398Stmm if (txs->txs_mbuf != NULL) { 71791398Stmm m_freem(txs->txs_mbuf); 71891398Stmm txs->txs_mbuf = NULL; 71991398Stmm } 72091398Stmm } 72191398Stmm STAILQ_INSERT_TAIL(&sc->sc_txfreeq, txs, txs_q); 72291398Stmm } 72391398Stmm 72491398Stmm if (disable) 72591398Stmm gem_rxdrain(sc); 72691398Stmm 72791398Stmm /* 72891398Stmm * Mark the interface down and cancel the watchdog timer. 72991398Stmm */ 730148887Srwatson ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); 731164931Smarius sc->sc_wdog_timer = 0; 73291398Stmm} 73391398Stmm 73491398Stmm/* 73591398Stmm * Reset the receiver 73691398Stmm */ 73791398Stmmint 73891398Stmmgem_reset_rx(sc) 73991398Stmm struct gem_softc *sc; 74091398Stmm{ 74191398Stmm 74291398Stmm /* 74391398Stmm * Resetting while DMA is in progress can cause a bus hang, so we 74491398Stmm * disable DMA first. 74591398Stmm */ 74691398Stmm gem_disable_rx(sc); 747169269Sphk bus_write_4(sc->sc_res[0], GEM_RX_CONFIG, 0); 74891398Stmm /* Wait till it finishes */ 74991398Stmm if (!gem_bitwait(sc, GEM_RX_CONFIG, 1, 0)) 75091398Stmm device_printf(sc->sc_dev, "cannot disable read dma\n"); 75191398Stmm 75291398Stmm /* Wait 5ms extra. */ 75391398Stmm DELAY(5000); 75491398Stmm 75591398Stmm /* Finally, reset the ERX */ 756169269Sphk bus_write_4(sc->sc_res[0], GEM_RESET, GEM_RESET_RX); 75791398Stmm /* Wait till it finishes */ 75891398Stmm if (!gem_bitwait(sc, GEM_RESET, GEM_RESET_TX, 0)) { 75991398Stmm device_printf(sc->sc_dev, "cannot reset receiver\n"); 76091398Stmm return (1); 76191398Stmm } 76291398Stmm return (0); 76391398Stmm} 76491398Stmm 76591398Stmm 76691398Stmm/* 76791398Stmm * Reset the transmitter 76891398Stmm */ 76991398Stmmstatic int 77091398Stmmgem_reset_tx(sc) 77191398Stmm struct gem_softc *sc; 77291398Stmm{ 77391398Stmm int i; 77491398Stmm 77591398Stmm /* 77691398Stmm * Resetting while DMA is in progress can cause a bus hang, so we 77791398Stmm * disable DMA first. 77891398Stmm */ 77991398Stmm gem_disable_tx(sc); 780169269Sphk bus_write_4(sc->sc_res[0], GEM_TX_CONFIG, 0); 78191398Stmm /* Wait till it finishes */ 78291398Stmm if (!gem_bitwait(sc, GEM_TX_CONFIG, 1, 0)) 78391398Stmm device_printf(sc->sc_dev, "cannot disable read dma\n"); 78491398Stmm 78591398Stmm /* Wait 5ms extra. */ 78691398Stmm DELAY(5000); 78791398Stmm 78891398Stmm /* Finally, reset the ETX */ 789169269Sphk bus_write_4(sc->sc_res[0], GEM_RESET, GEM_RESET_TX); 79091398Stmm /* Wait till it finishes */ 79191398Stmm for (i = TRIES; i--; DELAY(100)) 792169269Sphk if ((bus_read_4(sc->sc_res[0], GEM_RESET) & GEM_RESET_TX) == 0) 79391398Stmm break; 79491398Stmm if (!gem_bitwait(sc, GEM_RESET, GEM_RESET_TX, 0)) { 79591398Stmm device_printf(sc->sc_dev, "cannot reset receiver\n"); 79691398Stmm return (1); 79791398Stmm } 79891398Stmm return (0); 79991398Stmm} 80091398Stmm 80191398Stmm/* 80291398Stmm * disable receiver. 80391398Stmm */ 80491398Stmmstatic int 80591398Stmmgem_disable_rx(sc) 80691398Stmm struct gem_softc *sc; 80791398Stmm{ 80891398Stmm u_int32_t cfg; 80991398Stmm 81091398Stmm /* Flip the enable bit */ 811169269Sphk cfg = bus_read_4(sc->sc_res[0], GEM_MAC_RX_CONFIG); 81291398Stmm cfg &= ~GEM_MAC_RX_ENABLE; 813169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_RX_CONFIG, cfg); 81491398Stmm 81591398Stmm /* Wait for it to finish */ 81691398Stmm return (gem_bitwait(sc, GEM_MAC_RX_CONFIG, GEM_MAC_RX_ENABLE, 0)); 81791398Stmm} 81891398Stmm 81991398Stmm/* 82091398Stmm * disable transmitter. 82191398Stmm */ 82291398Stmmstatic int 82391398Stmmgem_disable_tx(sc) 82491398Stmm struct gem_softc *sc; 82591398Stmm{ 82691398Stmm u_int32_t cfg; 82791398Stmm 82891398Stmm /* Flip the enable bit */ 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); 83291398Stmm 83391398Stmm /* Wait for it to finish */ 83491398Stmm return (gem_bitwait(sc, GEM_MAC_TX_CONFIG, GEM_MAC_TX_ENABLE, 0)); 83591398Stmm} 83691398Stmm 83791398Stmm/* 83891398Stmm * Initialize interface. 83991398Stmm */ 84091398Stmmstatic int 84191398Stmmgem_meminit(sc) 84291398Stmm struct gem_softc *sc; 84391398Stmm{ 84491398Stmm struct gem_rxsoft *rxs; 84591398Stmm int i, error; 84691398Stmm 84791398Stmm /* 84891398Stmm * Initialize the transmit descriptor ring. 84991398Stmm */ 85091398Stmm for (i = 0; i < GEM_NTXDESC; i++) { 85191398Stmm sc->sc_txdescs[i].gd_flags = 0; 85291398Stmm sc->sc_txdescs[i].gd_addr = 0; 85391398Stmm } 854108832Stmm sc->sc_txfree = GEM_MAXTXFREE; 85591398Stmm sc->sc_txnext = 0; 85699726Sbenno sc->sc_txwin = 0; 85791398Stmm 85891398Stmm /* 85991398Stmm * Initialize the receive descriptor and receive job 86091398Stmm * descriptor rings. 86191398Stmm */ 86291398Stmm for (i = 0; i < GEM_NRXDESC; i++) { 86391398Stmm rxs = &sc->sc_rxsoft[i]; 86491398Stmm if (rxs->rxs_mbuf == NULL) { 86591398Stmm if ((error = gem_add_rxbuf(sc, i)) != 0) { 86691398Stmm device_printf(sc->sc_dev, "unable to " 86791398Stmm "allocate or map rx buffer %d, error = " 86891398Stmm "%d\n", i, error); 86991398Stmm /* 87091398Stmm * XXX Should attempt to run with fewer receive 87191398Stmm * XXX buffers instead of just failing. 87291398Stmm */ 87391398Stmm gem_rxdrain(sc); 87491398Stmm return (1); 87591398Stmm } 87691398Stmm } else 87791398Stmm GEM_INIT_RXDESC(sc, i); 87891398Stmm } 87991398Stmm sc->sc_rxptr = 0; 880109648Stmm GEM_CDSYNC(sc, BUS_DMASYNC_PREWRITE); 881109648Stmm GEM_CDSYNC(sc, BUS_DMASYNC_PREREAD); 88291398Stmm 88391398Stmm return (0); 88491398Stmm} 88591398Stmm 88691398Stmmstatic int 88791398Stmmgem_ringsize(sz) 88891398Stmm int sz; 88991398Stmm{ 89091398Stmm int v = 0; 89191398Stmm 89291398Stmm switch (sz) { 89391398Stmm case 32: 89491398Stmm v = GEM_RING_SZ_32; 89591398Stmm break; 89691398Stmm case 64: 89791398Stmm v = GEM_RING_SZ_64; 89891398Stmm break; 89991398Stmm case 128: 90091398Stmm v = GEM_RING_SZ_128; 90191398Stmm break; 90291398Stmm case 256: 90391398Stmm v = GEM_RING_SZ_256; 90491398Stmm break; 90591398Stmm case 512: 90691398Stmm v = GEM_RING_SZ_512; 90791398Stmm break; 90891398Stmm case 1024: 90991398Stmm v = GEM_RING_SZ_1024; 91091398Stmm break; 91191398Stmm case 2048: 91291398Stmm v = GEM_RING_SZ_2048; 91391398Stmm break; 91491398Stmm case 4096: 91591398Stmm v = GEM_RING_SZ_4096; 91691398Stmm break; 91791398Stmm case 8192: 91891398Stmm v = GEM_RING_SZ_8192; 91991398Stmm break; 92091398Stmm default: 92191398Stmm printf("gem: invalid Receive Descriptor ring size\n"); 92291398Stmm break; 92391398Stmm } 92491398Stmm return (v); 92591398Stmm} 92691398Stmm 927148369Smariusstatic void 928148369Smariusgem_init(xsc) 929148369Smarius void *xsc; 930148369Smarius{ 931148369Smarius struct gem_softc *sc = (struct gem_softc *)xsc; 932148369Smarius 933148369Smarius GEM_LOCK(sc); 934148369Smarius gem_init_locked(sc); 935148369Smarius GEM_UNLOCK(sc); 936148369Smarius} 937148369Smarius 93891398Stmm/* 93991398Stmm * Initialization of interface; set up initialization block 94091398Stmm * and transmit/receive descriptor rings. 94191398Stmm */ 94291398Stmmstatic void 943148369Smariusgem_init_locked(sc) 944148369Smarius struct gem_softc *sc; 94591398Stmm{ 946147256Sbrooks struct ifnet *ifp = sc->sc_ifp; 94791398Stmm u_int32_t v; 94891398Stmm 949148369Smarius GEM_LOCK_ASSERT(sc, MA_OWNED); 95091398Stmm 951115030Stmm#ifdef GEM_DEBUG 952170273Syongari CTR2(KTR_GEM, "%s: %s: calling stop", device_get_name(sc->sc_dev), 953170273Syongari __func__); 954115030Stmm#endif 95591398Stmm /* 95691398Stmm * Initialization sequence. The numbered steps below correspond 95791398Stmm * to the sequence outlined in section 6.3.5.1 in the Ethernet 95891398Stmm * Channel Engine manual (part of the PCIO manual). 95991398Stmm * See also the STP2002-STQ document from Sun Microsystems. 96091398Stmm */ 96191398Stmm 96291398Stmm /* step 1 & 2. Reset the Ethernet Channel */ 963147256Sbrooks gem_stop(sc->sc_ifp, 0); 96491398Stmm gem_reset(sc); 965115030Stmm#ifdef GEM_DEBUG 966170273Syongari CTR2(KTR_GEM, "%s: %s: restarting", device_get_name(sc->sc_dev), 967170273Syongari __func__); 968115030Stmm#endif 96991398Stmm 97091398Stmm /* Re-initialize the MIF */ 97191398Stmm gem_mifinit(sc); 97291398Stmm 97391398Stmm /* step 3. Setup data structures in host memory */ 97491398Stmm gem_meminit(sc); 97591398Stmm 97691398Stmm /* step 4. TX MAC registers & counters */ 97791398Stmm gem_init_regs(sc); 97891398Stmm 97991398Stmm /* step 5. RX MAC registers & counters */ 98091398Stmm gem_setladrf(sc); 98191398Stmm 98291398Stmm /* step 6 & 7. Program Descriptor Ring Base Addresses */ 98391398Stmm /* NOTE: we use only 32-bit DMA addresses here. */ 984169269Sphk bus_write_4(sc->sc_res[0], GEM_TX_RING_PTR_HI, 0); 985169269Sphk bus_write_4(sc->sc_res[0], GEM_TX_RING_PTR_LO, GEM_CDTXADDR(sc, 0)); 98691398Stmm 987169269Sphk bus_write_4(sc->sc_res[0], GEM_RX_RING_PTR_HI, 0); 988169269Sphk bus_write_4(sc->sc_res[0], GEM_RX_RING_PTR_LO, GEM_CDRXADDR(sc, 0)); 989115030Stmm#ifdef GEM_DEBUG 99091398Stmm CTR3(KTR_GEM, "loading rx ring %lx, tx ring %lx, cddma %lx", 99191398Stmm GEM_CDRXADDR(sc, 0), GEM_CDTXADDR(sc, 0), sc->sc_cddma); 992115030Stmm#endif 99391398Stmm 99491398Stmm /* step 8. Global Configuration & Interrupt Mask */ 995169269Sphk bus_write_4(sc->sc_res[0], GEM_INTMASK, 99691398Stmm ~(GEM_INTR_TX_INTME| 99791398Stmm GEM_INTR_TX_EMPTY| 99891398Stmm GEM_INTR_RX_DONE|GEM_INTR_RX_NOBUF| 99991398Stmm GEM_INTR_RX_TAG_ERR|GEM_INTR_PCS| 100091398Stmm GEM_INTR_MAC_CONTROL|GEM_INTR_MIF| 100191398Stmm GEM_INTR_BERR)); 1002169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_RX_MASK, 100399726Sbenno GEM_MAC_RX_DONE|GEM_MAC_RX_FRAME_CNT); 1004169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_TX_MASK, 0xffff); /* XXXX */ 1005169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_CONTROL_MASK, 0); /* XXXX */ 100691398Stmm 100791398Stmm /* step 9. ETX Configuration: use mostly default values */ 100891398Stmm 100991398Stmm /* Enable DMA */ 101091398Stmm v = gem_ringsize(GEM_NTXDESC /*XXX*/); 1011169269Sphk bus_write_4(sc->sc_res[0], GEM_TX_CONFIG, 101291398Stmm v|GEM_TX_CONFIG_TXDMA_EN| 101391398Stmm ((0x400<<10)&GEM_TX_CONFIG_TXFIFO_TH)); 101491398Stmm 101591398Stmm /* step 10. ERX Configuration */ 101691398Stmm 101791398Stmm /* Encode Receive Descriptor ring size: four possible values */ 101891398Stmm v = gem_ringsize(GEM_NRXDESC /*XXX*/); 1019170273Syongari /* Rx TCP/UDP checksum offset */ 1020170273Syongari v |= ((ETHER_HDR_LEN + sizeof(struct ip)) << 1021170273Syongari GEM_RX_CONFIG_CXM_START_SHFT); 102291398Stmm 102391398Stmm /* Enable DMA */ 1024169269Sphk bus_write_4(sc->sc_res[0], GEM_RX_CONFIG, 102591398Stmm v|(GEM_THRSH_1024<<GEM_RX_CONFIG_FIFO_THRS_SHIFT)| 1026170273Syongari (2<<GEM_RX_CONFIG_FBOFF_SHFT)|GEM_RX_CONFIG_RXDMA_EN); 102791398Stmm /* 102899726Sbenno * The following value is for an OFF Threshold of about 3/4 full 102999726Sbenno * and an ON Threshold of 1/4 full. 103091398Stmm */ 1031169269Sphk bus_write_4(sc->sc_res[0], GEM_RX_PAUSE_THRESH, 103299726Sbenno (3 * sc->sc_rxfifosize / 256) | 103399726Sbenno ( (sc->sc_rxfifosize / 256) << 12)); 1034169269Sphk bus_write_4(sc->sc_res[0], GEM_RX_BLANKING, (6<<12)|6); 103591398Stmm 103691398Stmm /* step 11. Configure Media */ 103799726Sbenno mii_mediachg(sc->sc_mii); 103891398Stmm 103991398Stmm /* step 12. RX_MAC Configuration Register */ 1040169269Sphk v = bus_read_4(sc->sc_res[0], GEM_MAC_RX_CONFIG); 1041170273Syongari v |= GEM_MAC_RX_ENABLE | GEM_MAC_RX_STRIP_CRC; 1042169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_RX_CONFIG, v); 104391398Stmm 104491398Stmm /* step 14. Issue Transmit Pending command */ 104591398Stmm 104691398Stmm /* step 15. Give the reciever a swift kick */ 1047169269Sphk bus_write_4(sc->sc_res[0], GEM_RX_KICK, GEM_NRXDESC-4); 104891398Stmm 104991398Stmm /* Start the one second timer. */ 1050164931Smarius sc->sc_wdog_timer = 0; 105191398Stmm callout_reset(&sc->sc_tick_ch, hz, gem_tick, sc); 105291398Stmm 1053148887Srwatson ifp->if_drv_flags |= IFF_DRV_RUNNING; 1054148887Srwatson ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 105599726Sbenno sc->sc_ifflags = ifp->if_flags; 105691398Stmm} 105791398Stmm 1058170273Syongari/* 1059170273Syongari * It's copy of ath_defrag(ath(4)). 1060170273Syongari * 1061170273Syongari * Defragment an mbuf chain, returning at most maxfrags separate 1062170273Syongari * mbufs+clusters. If this is not possible NULL is returned and 1063170273Syongari * the original mbuf chain is left in it's present (potentially 1064170273Syongari * modified) state. We use two techniques: collapsing consecutive 1065170273Syongari * mbufs and replacing consecutive mbufs by a cluster. 1066170273Syongari */ 1067170273Syongaristatic struct mbuf * 1068170273Syongarigem_defrag(m0, how, maxfrags) 1069170273Syongari struct mbuf *m0; 1070170273Syongari int how; 1071170273Syongari int maxfrags; 1072170273Syongari{ 1073170273Syongari struct mbuf *m, *n, *n2, **prev; 1074170273Syongari u_int curfrags; 1075170273Syongari 1076170273Syongari /* 1077170273Syongari * Calculate the current number of frags. 1078170273Syongari */ 1079170273Syongari curfrags = 0; 1080170273Syongari for (m = m0; m != NULL; m = m->m_next) 1081170273Syongari curfrags++; 1082170273Syongari /* 1083170273Syongari * First, try to collapse mbufs. Note that we always collapse 1084170273Syongari * towards the front so we don't need to deal with moving the 1085170273Syongari * pkthdr. This may be suboptimal if the first mbuf has much 1086170273Syongari * less data than the following. 1087170273Syongari */ 1088170273Syongari m = m0; 1089170273Syongariagain: 1090170273Syongari for (;;) { 1091170273Syongari n = m->m_next; 1092170273Syongari if (n == NULL) 1093170273Syongari break; 1094170273Syongari if ((m->m_flags & M_RDONLY) == 0 && 1095170273Syongari n->m_len < M_TRAILINGSPACE(m)) { 1096170273Syongari bcopy(mtod(n, void *), mtod(m, char *) + m->m_len, 1097170273Syongari n->m_len); 1098170273Syongari m->m_len += n->m_len; 1099170273Syongari m->m_next = n->m_next; 1100170273Syongari m_free(n); 1101170273Syongari if (--curfrags <= maxfrags) 1102170273Syongari return (m0); 1103170273Syongari } else 1104170273Syongari m = n; 1105170273Syongari } 1106170273Syongari KASSERT(maxfrags > 1, 1107170273Syongari ("maxfrags %u, but normal collapse failed", maxfrags)); 1108170273Syongari /* 1109170273Syongari * Collapse consecutive mbufs to a cluster. 1110170273Syongari */ 1111170273Syongari prev = &m0->m_next; /* NB: not the first mbuf */ 1112170273Syongari while ((n = *prev) != NULL) { 1113170273Syongari if ((n2 = n->m_next) != NULL && 1114170273Syongari n->m_len + n2->m_len < MCLBYTES) { 1115170273Syongari m = m_getcl(how, MT_DATA, 0); 1116170273Syongari if (m == NULL) 1117170273Syongari goto bad; 1118170273Syongari bcopy(mtod(n, void *), mtod(m, void *), n->m_len); 1119170273Syongari bcopy(mtod(n2, void *), mtod(m, char *) + n->m_len, 1120170273Syongari n2->m_len); 1121170273Syongari m->m_len = n->m_len + n2->m_len; 1122170273Syongari m->m_next = n2->m_next; 1123170273Syongari *prev = m; 1124170273Syongari m_free(n); 1125170273Syongari m_free(n2); 1126170273Syongari if (--curfrags <= maxfrags) /* +1 cl -2 mbufs */ 1127170273Syongari return m0; 1128170273Syongari /* 1129170273Syongari * Still not there, try the normal collapse 1130170273Syongari * again before we allocate another cluster. 1131170273Syongari */ 1132170273Syongari goto again; 1133170273Syongari } 1134170273Syongari prev = &n->m_next; 1135170273Syongari } 1136170273Syongari /* 1137170273Syongari * No place where we can collapse to a cluster; punt. 1138170273Syongari * This can occur if, for example, you request 2 frags 1139170273Syongari * but the packet requires that both be clusters (we 1140170273Syongari * never reallocate the first mbuf to avoid moving the 1141170273Syongari * packet header). 1142170273Syongari */ 1143170273Syongaribad: 1144170273Syongari return (NULL); 1145170273Syongari} 1146170273Syongari 114791398Stmmstatic int 1148170273Syongarigem_load_txmbuf(sc, m_head) 114991398Stmm struct gem_softc *sc; 1150170273Syongari struct mbuf **m_head; 115191398Stmm{ 115291398Stmm struct gem_txsoft *txs; 1153170273Syongari bus_dma_segment_t txsegs[GEM_NTXSEGS]; 1154170273Syongari struct mbuf *m; 1155170273Syongari uint64_t flags, cflags; 1156170273Syongari int error, nexttx, nsegs, seg; 115791398Stmm 1158108832Stmm /* Get a work queue entry. */ 1159108832Stmm if ((txs = STAILQ_FIRST(&sc->sc_txfreeq)) == NULL) { 1160108832Stmm /* Ran out of descriptors. */ 1161170273Syongari return (ENOBUFS); 1162108832Stmm } 1163170273Syongari error = bus_dmamap_load_mbuf_sg(sc->sc_tdmatag, txs->txs_dmamap, 1164170273Syongari *m_head, txsegs, &nsegs, BUS_DMA_NOWAIT); 1165170273Syongari if (error == EFBIG) { 1166170273Syongari m = gem_defrag(*m_head, M_DONTWAIT, GEM_NTXSEGS); 1167170273Syongari if (m == NULL) { 1168170273Syongari m_freem(*m_head); 1169170273Syongari *m_head = NULL; 1170170273Syongari return (ENOBUFS); 1171170273Syongari } 1172170273Syongari *m_head = m; 1173170273Syongari error = bus_dmamap_load_mbuf_sg(sc->sc_tdmatag, txs->txs_dmamap, 1174170273Syongari *m_head, txsegs, &nsegs, BUS_DMA_NOWAIT); 1175170273Syongari if (error != 0) { 1176170273Syongari m_freem(*m_head); 1177170273Syongari *m_head = NULL; 1178170273Syongari return (error); 1179170273Syongari } 1180170273Syongari } else if (error != 0) 1181170273Syongari return (error); 1182170273Syongari if (nsegs == 0) { 1183170273Syongari m_freem(*m_head); 1184170273Syongari *m_head = NULL; 1185170273Syongari return (EIO); 1186170273Syongari } 1187170273Syongari 1188170273Syongari /* 1189170273Syongari * Ensure we have enough descriptors free to describe 1190170273Syongari * the packet. Note, we always reserve one descriptor 1191170273Syongari * at the end of the ring as a termination point, to 1192170273Syongari * prevent wrap-around. 1193170273Syongari */ 1194170273Syongari if (nsegs > sc->sc_txfree - 1) { 1195170273Syongari txs->txs_ndescs = 0; 1196170273Syongari bus_dmamap_unload(sc->sc_tdmatag, txs->txs_dmamap); 1197170273Syongari return (ENOBUFS); 1198170273Syongari } 1199170273Syongari 1200170273Syongari flags = cflags = 0; 1201170273Syongari if (((*m_head)->m_pkthdr.csum_flags & sc->sc_csum_features) != 0) 1202170273Syongari gem_txcksum(sc, *m_head, &cflags); 1203170273Syongari 1204170273Syongari txs->txs_ndescs = nsegs; 1205108832Stmm txs->txs_firstdesc = sc->sc_txnext; 1206170273Syongari nexttx = txs->txs_firstdesc; 1207170273Syongari for (seg = 0; seg < nsegs; seg++, nexttx = GEM_NEXTTX(nexttx)) { 1208170273Syongari#ifdef GEM_DEBUG 1209170273Syongari CTR6(KTR_GEM, "%s: mapping seg %d (txd %d), len " 1210170273Syongari "%lx, addr %#lx (%#lx)", __func__, seg, nexttx, 1211170273Syongari txsegs[seg].ds_len, txsegs[seg].ds_addr, 1212170273Syongari GEM_DMA_WRITE(sc, txsegs[seg].ds_addr)); 1213170273Syongari#endif 1214170273Syongari sc->sc_txdescs[nexttx].gd_addr = 1215170273Syongari GEM_DMA_WRITE(sc, txsegs[seg].ds_addr); 1216170273Syongari KASSERT(txsegs[seg].ds_len < GEM_TD_BUFSIZE, 1217170273Syongari ("%s: segment size too large!", __func__)); 1218170273Syongari flags = txsegs[seg].ds_len & GEM_TD_BUFSIZE; 1219170273Syongari sc->sc_txdescs[nexttx].gd_flags = 1220170273Syongari GEM_DMA_WRITE(sc, flags | cflags); 1221170273Syongari txs->txs_lastdesc = nexttx; 122291398Stmm } 122391398Stmm 1224170273Syongari /* set EOP on the last descriptor */ 1225170273Syongari#ifdef GEM_DEBUG 1226170273Syongari CTR3(KTR_GEM, "%s: end of packet at seg %d, tx %d", __func__, seg, 1227170273Syongari nexttx); 1228170273Syongari#endif 1229170273Syongari sc->sc_txdescs[txs->txs_lastdesc].gd_flags |= 1230170273Syongari GEM_DMA_WRITE(sc, GEM_TD_END_OF_PACKET); 1231170273Syongari 1232170273Syongari /* Lastly set SOP on the first descriptor */ 1233170273Syongari#ifdef GEM_DEBUG 1234170273Syongari CTR3(KTR_GEM, "%s: start of packet at seg %d, tx %d", __func__, seg, 1235170273Syongari nexttx); 1236170273Syongari#endif 1237170273Syongari if (++sc->sc_txwin > GEM_NTXSEGS * 2 / 3) { 1238170273Syongari sc->sc_txwin = 0; 1239170273Syongari flags |= GEM_TD_INTERRUPT_ME; 1240170273Syongari sc->sc_txdescs[txs->txs_firstdesc].gd_flags |= 1241170273Syongari GEM_DMA_WRITE(sc, GEM_TD_INTERRUPT_ME | 1242170273Syongari GEM_TD_START_OF_PACKET); 1243170273Syongari } else 1244170273Syongari sc->sc_txdescs[txs->txs_firstdesc].gd_flags |= 1245170273Syongari GEM_DMA_WRITE(sc, GEM_TD_START_OF_PACKET); 1246170273Syongari 1247108832Stmm /* Sync the DMA map. */ 1248170273Syongari bus_dmamap_sync(sc->sc_tdmatag, txs->txs_dmamap, BUS_DMASYNC_PREWRITE); 124991398Stmm 1250115030Stmm#ifdef GEM_DEBUG 1251170273Syongari CTR4(KTR_GEM, "%s: setting firstdesc=%d, lastdesc=%d, ndescs=%d", 1252170273Syongari __func__, txs->txs_firstdesc, txs->txs_lastdesc, txs->txs_ndescs); 1253115030Stmm#endif 1254108832Stmm STAILQ_REMOVE_HEAD(&sc->sc_txfreeq, txs_q); 1255108832Stmm STAILQ_INSERT_TAIL(&sc->sc_txdirtyq, txs, txs_q); 1256170273Syongari txs->txs_mbuf = *m_head; 125791398Stmm 1258108832Stmm sc->sc_txnext = GEM_NEXTTX(txs->txs_lastdesc); 1259108832Stmm sc->sc_txfree -= txs->txs_ndescs; 1260170273Syongari 1261108832Stmm return (0); 126291398Stmm} 126391398Stmm 126491398Stmmstatic void 126591398Stmmgem_init_regs(sc) 126691398Stmm struct gem_softc *sc; 126791398Stmm{ 1268152315Sru const u_char *laddr = IF_LLADDR(sc->sc_ifp); 126999726Sbenno u_int32_t v; 127091398Stmm 127191398Stmm /* These regs are not cleared on reset */ 127291398Stmm if (!sc->sc_inited) { 127391398Stmm 127491398Stmm /* Wooo. Magic values. */ 1275169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_IPG0, 0); 1276169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_IPG1, 8); 1277169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_IPG2, 4); 127891398Stmm 1279169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_MAC_MIN_FRAME, ETHER_MIN_LEN); 128091398Stmm /* Max frame and max burst size */ 1281169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_MAC_MAX_FRAME, 1282149552Smarius (ETHER_MAX_LEN + ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN) | 1283149552Smarius (0x2000 << 16)); 128499726Sbenno 1285169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_PREAMBLE_LEN, 0x7); 1286169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_JAM_SIZE, 0x4); 1287169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_ATTEMPT_LIMIT, 0x10); 128891398Stmm /* Dunno.... */ 1289169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_CONTROL_TYPE, 0x8088); 1290169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_RANDOM_SEED, 129199726Sbenno ((laddr[5]<<8)|laddr[4])&0x3ff); 129299726Sbenno 129391398Stmm /* Secondary MAC addr set to 0:0:0:0:0:0 */ 1294169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_ADDR3, 0); 1295169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_ADDR4, 0); 1296169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_ADDR5, 0); 129799726Sbenno 129899726Sbenno /* MAC control addr set to 01:80:c2:00:00:01 */ 1299169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_ADDR6, 0x0001); 1300169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_ADDR7, 0xc200); 1301169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_ADDR8, 0x0180); 130291398Stmm 130391398Stmm /* MAC filter addr set to 0:0:0:0:0:0 */ 1304169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_ADDR_FILTER0, 0); 1305169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_ADDR_FILTER1, 0); 1306169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_ADDR_FILTER2, 0); 130791398Stmm 1308169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_ADR_FLT_MASK1_2, 0); 1309169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_ADR_FLT_MASK0, 0); 131091398Stmm 131191398Stmm sc->sc_inited = 1; 131291398Stmm } 131391398Stmm 131491398Stmm /* Counters need to be zeroed */ 1315169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_NORM_COLL_CNT, 0); 1316169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_FIRST_COLL_CNT, 0); 1317169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_EXCESS_COLL_CNT, 0); 1318169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_LATE_COLL_CNT, 0); 1319169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_DEFER_TMR_CNT, 0); 1320169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_PEAK_ATTEMPTS, 0); 1321169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_RX_FRAME_COUNT, 0); 1322169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_RX_LEN_ERR_CNT, 0); 1323169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_RX_ALIGN_ERR, 0); 1324169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_RX_CRC_ERR_CNT, 0); 1325169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_RX_CODE_VIOL, 0); 132691398Stmm 132791398Stmm /* Un-pause stuff */ 132891398Stmm#if 0 1329169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_SEND_PAUSE_CMD, 0x1BF0); 133091398Stmm#else 1331169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_SEND_PAUSE_CMD, 0); 133291398Stmm#endif 133391398Stmm 133491398Stmm /* 133591398Stmm * Set the station address. 133691398Stmm */ 1337169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_ADDR0, (laddr[4]<<8)|laddr[5]); 1338169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_ADDR1, (laddr[2]<<8)|laddr[3]); 1339169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_ADDR2, (laddr[0]<<8)|laddr[1]); 134099726Sbenno 134199726Sbenno /* 134299726Sbenno * Enable MII outputs. Enable GMII if there is a gigabit PHY. 134399726Sbenno */ 1344169269Sphk sc->sc_mif_config = bus_read_4(sc->sc_res[0], GEM_MIF_CONFIG); 134599726Sbenno v = GEM_MAC_XIF_TX_MII_ENA; 134699726Sbenno if (sc->sc_mif_config & GEM_MIF_CONFIG_MDI1) { 134799726Sbenno v |= GEM_MAC_XIF_FDPLX_LED; 134899726Sbenno if (sc->sc_flags & GEM_GIGABIT) 134999726Sbenno v |= GEM_MAC_XIF_GMII_MODE; 135099726Sbenno } 1351169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_XIF_CONFIG, v); 135291398Stmm} 135391398Stmm 135491398Stmmstatic void 135591398Stmmgem_start(ifp) 135691398Stmm struct ifnet *ifp; 135791398Stmm{ 135891398Stmm struct gem_softc *sc = (struct gem_softc *)ifp->if_softc; 1359148369Smarius 1360148369Smarius GEM_LOCK(sc); 1361148369Smarius gem_start_locked(ifp); 1362148369Smarius GEM_UNLOCK(sc); 1363148369Smarius} 1364148369Smarius 1365148369Smariusstatic void 1366148369Smariusgem_start_locked(ifp) 1367148369Smarius struct ifnet *ifp; 1368148369Smarius{ 1369148369Smarius struct gem_softc *sc = (struct gem_softc *)ifp->if_softc; 1370170273Syongari struct mbuf *m; 1371170273Syongari int firsttx, ntx = 0, txmfail; 137291398Stmm 1373148887Srwatson if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) != 1374148887Srwatson IFF_DRV_RUNNING) 137591398Stmm return; 137691398Stmm 137791398Stmm firsttx = sc->sc_txnext; 1378115030Stmm#ifdef GEM_DEBUG 1379170273Syongari CTR4(KTR_GEM, "%s: %s: txfree %d, txnext %d", 1380170273Syongari device_get_name(sc->sc_dev), __func__, sc->sc_txfree, firsttx); 1381115030Stmm#endif 1382170273Syongari for (; !IFQ_DRV_IS_EMPTY(&ifp->if_snd) && sc->sc_txfree > 1;) { 1383170273Syongari IFQ_DRV_DEQUEUE(&ifp->if_snd, m); 1384170273Syongari if (m == NULL) 138591398Stmm break; 1386170273Syongari txmfail = gem_load_txmbuf(sc, &m); 1387170273Syongari if (txmfail != 0) { 1388170273Syongari if (m == NULL) 1389170273Syongari break; 1390170273Syongari ifp->if_drv_flags |= IFF_DRV_OACTIVE; 1391170273Syongari IFQ_DRV_PREPEND(&ifp->if_snd, m); 139291398Stmm break; 139391398Stmm } 1394115030Stmm ntx++; 1395108832Stmm /* Kick the transmitter. */ 1396170273Syongari#ifdef GEM_DEBUG 1397170273Syongari CTR3(KTR_GEM, "%s: %s: kicking tx %d", 1398170273Syongari device_get_name(sc->sc_dev), __func__, sc->sc_txnext); 1399115030Stmm#endif 1400169269Sphk bus_write_4(sc->sc_res[0], GEM_TX_KICK, 1401108832Stmm sc->sc_txnext); 1402108832Stmm 1403170273Syongari BPF_MTAP(ifp, m); 140491398Stmm } 140591398Stmm 140691398Stmm if (ntx > 0) { 1407109648Stmm GEM_CDSYNC(sc, BUS_DMASYNC_PREWRITE); 1408109648Stmm 1409115030Stmm#ifdef GEM_DEBUG 1410108832Stmm CTR2(KTR_GEM, "%s: packets enqueued, OWN on %d", 1411108832Stmm device_get_name(sc->sc_dev), firsttx); 1412115030Stmm#endif 141391398Stmm 141491398Stmm /* Set a watchdog timer in case the chip flakes out. */ 1415164931Smarius sc->sc_wdog_timer = 5; 1416115030Stmm#ifdef GEM_DEBUG 1417170273Syongari CTR3(KTR_GEM, "%s: %s: watchdog %d", 1418170273Syongari device_get_name(sc->sc_dev), __func__, sc->sc_wdog_timer); 1419115030Stmm#endif 142091398Stmm } 142191398Stmm} 142291398Stmm 142391398Stmm/* 142491398Stmm * Transmit interrupt. 142591398Stmm */ 142691398Stmmstatic void 142791398Stmmgem_tint(sc) 142891398Stmm struct gem_softc *sc; 142991398Stmm{ 1430147256Sbrooks struct ifnet *ifp = sc->sc_ifp; 143191398Stmm struct gem_txsoft *txs; 143291398Stmm int txlast; 143399726Sbenno int progress = 0; 143491398Stmm 143591398Stmm 1436115030Stmm#ifdef GEM_DEBUG 1437170273Syongari CTR2(KTR_GEM, "%s: %s", device_get_name(sc->sc_dev), __func__); 1438115030Stmm#endif 143991398Stmm 144091398Stmm /* 144191398Stmm * Go through our Tx list and free mbufs for those 144291398Stmm * frames that have been transmitted. 144391398Stmm */ 1444109648Stmm GEM_CDSYNC(sc, BUS_DMASYNC_POSTREAD); 144591398Stmm while ((txs = STAILQ_FIRST(&sc->sc_txdirtyq)) != NULL) { 144691398Stmm 144791398Stmm#ifdef GEM_DEBUG 144891398Stmm if (ifp->if_flags & IFF_DEBUG) { 144991398Stmm int i; 145091398Stmm printf(" txsoft %p transmit chain:\n", txs); 145191398Stmm for (i = txs->txs_firstdesc;; i = GEM_NEXTTX(i)) { 145291398Stmm printf("descriptor %d: ", i); 145391398Stmm printf("gd_flags: 0x%016llx\t", (long long) 145491398Stmm GEM_DMA_READ(sc, sc->sc_txdescs[i].gd_flags)); 145591398Stmm printf("gd_addr: 0x%016llx\n", (long long) 145691398Stmm GEM_DMA_READ(sc, sc->sc_txdescs[i].gd_addr)); 145791398Stmm if (i == txs->txs_lastdesc) 145891398Stmm break; 145991398Stmm } 146091398Stmm } 146191398Stmm#endif 146291398Stmm 146391398Stmm /* 146491398Stmm * In theory, we could harveast some descriptors before 146591398Stmm * the ring is empty, but that's a bit complicated. 146691398Stmm * 146791398Stmm * GEM_TX_COMPLETION points to the last descriptor 146891398Stmm * processed +1. 146991398Stmm */ 1470169269Sphk txlast = bus_read_4(sc->sc_res[0], GEM_TX_COMPLETION); 1471115030Stmm#ifdef GEM_DEBUG 1472170273Syongari CTR4(KTR_GEM, "%s: txs->txs_firstdesc = %d, " 147391398Stmm "txs->txs_lastdesc = %d, txlast = %d", 1474170273Syongari __func__, txs->txs_firstdesc, txs->txs_lastdesc, txlast); 1475115030Stmm#endif 147691398Stmm if (txs->txs_firstdesc <= txs->txs_lastdesc) { 147791398Stmm if ((txlast >= txs->txs_firstdesc) && 147891398Stmm (txlast <= txs->txs_lastdesc)) 147991398Stmm break; 148091398Stmm } else { 148191398Stmm /* Ick -- this command wraps */ 148291398Stmm if ((txlast >= txs->txs_firstdesc) || 148391398Stmm (txlast <= txs->txs_lastdesc)) 148491398Stmm break; 148591398Stmm } 148691398Stmm 1487115030Stmm#ifdef GEM_DEBUG 1488170273Syongari CTR1(KTR_GEM, "%s: releasing a desc", __func__); 1489115030Stmm#endif 149091398Stmm STAILQ_REMOVE_HEAD(&sc->sc_txdirtyq, txs_q); 149191398Stmm 149291398Stmm sc->sc_txfree += txs->txs_ndescs; 149391398Stmm 1494108832Stmm bus_dmamap_sync(sc->sc_tdmatag, txs->txs_dmamap, 149591398Stmm BUS_DMASYNC_POSTWRITE); 1496108832Stmm bus_dmamap_unload(sc->sc_tdmatag, txs->txs_dmamap); 149791398Stmm if (txs->txs_mbuf != NULL) { 149891398Stmm m_freem(txs->txs_mbuf); 149991398Stmm txs->txs_mbuf = NULL; 150091398Stmm } 150191398Stmm 150291398Stmm STAILQ_INSERT_TAIL(&sc->sc_txfreeq, txs, txs_q); 150391398Stmm 150491398Stmm ifp->if_opackets++; 150599726Sbenno progress = 1; 150691398Stmm } 150791398Stmm 1508115030Stmm#ifdef GEM_DEBUG 1509170273Syongari CTR4(KTR_GEM, "%s: GEM_TX_STATE_MACHINE %x " 151091398Stmm "GEM_TX_DATA_PTR %llx " 151191398Stmm "GEM_TX_COMPLETION %x", 1512170273Syongari __func__, 1513170273Syongari bus_space_read_4(sc->sc_res[0], sc->sc_h, GEM_TX_STATE_MACHINE), 1514170273Syongari ((long long) bus_4(sc->sc_res[0], 151591398Stmm GEM_TX_DATA_PTR_HI) << 32) | 1516169269Sphk bus_read_4(sc->sc_res[0], 151791398Stmm GEM_TX_DATA_PTR_LO), 1518169269Sphk bus_read_4(sc->sc_res[0], GEM_TX_COMPLETION)); 1519115030Stmm#endif 152091398Stmm 152199726Sbenno if (progress) { 152299726Sbenno if (sc->sc_txfree == GEM_NTXDESC - 1) 152399726Sbenno sc->sc_txwin = 0; 152491398Stmm 1525148887Srwatson /* Freed some descriptors, so reset IFF_DRV_OACTIVE and restart. */ 1526148887Srwatson ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 1527170273Syongari sc->sc_wdog_timer = STAILQ_EMPTY(&sc->sc_txdirtyq) ? 0 : 5; 152891398Stmm 1529170273Syongari if (ifp->if_drv_flags & IFF_DRV_RUNNING && 1530170273Syongari !IFQ_DRV_IS_EMPTY(&ifp->if_snd)) 1531170273Syongari gem_start_locked(ifp); 153299726Sbenno } 153399726Sbenno 1534115030Stmm#ifdef GEM_DEBUG 1535170273Syongari CTR3(KTR_GEM, "%s: %s: watchdog %d", 1536170273Syongari device_get_name(sc->sc_dev), __func__, sc->sc_wdog_timer); 1537115030Stmm#endif 153891398Stmm} 153991398Stmm 1540148368Smarius#ifdef GEM_RINT_TIMEOUT 154193045Stmmstatic void 154293045Stmmgem_rint_timeout(arg) 154393045Stmm void *arg; 154493045Stmm{ 1545148369Smarius struct gem_softc *sc = (struct gem_softc *)arg; 154693045Stmm 1547150285Smarius GEM_LOCK_ASSERT(sc, MA_OWNED); 1548148369Smarius gem_rint(sc); 154993045Stmm} 1550100587Sjake#endif 155193045Stmm 155291398Stmm/* 155391398Stmm * Receive interrupt. 155491398Stmm */ 155591398Stmmstatic void 155691398Stmmgem_rint(sc) 155791398Stmm struct gem_softc *sc; 155891398Stmm{ 1559147256Sbrooks struct ifnet *ifp = sc->sc_ifp; 156091398Stmm struct gem_rxsoft *rxs; 156191398Stmm struct mbuf *m; 156291398Stmm u_int64_t rxstat; 156399726Sbenno u_int32_t rxcomp; 156499726Sbenno int i, len, progress = 0; 156591398Stmm 1566148368Smarius#ifdef GEM_RINT_TIMEOUT 156793045Stmm callout_stop(&sc->sc_rx_ch); 1568148368Smarius#endif 1569115030Stmm#ifdef GEM_DEBUG 1570170273Syongari CTR2(KTR_GEM, "%s: %s", device_get_name(sc->sc_dev), __func__); 1571115030Stmm#endif 157299726Sbenno 157391398Stmm /* 157499726Sbenno * Read the completion register once. This limits 157599726Sbenno * how long the following loop can execute. 157699726Sbenno */ 1577169269Sphk rxcomp = bus_read_4(sc->sc_res[0], GEM_RX_COMPLETION); 157899726Sbenno 1579115030Stmm#ifdef GEM_DEBUG 1580170273Syongari CTR3(KTR_GEM, "%s: sc->rxptr %d, complete %d", 1581170273Syongari __func__, sc->sc_rxptr, rxcomp); 1582115030Stmm#endif 1583109648Stmm GEM_CDSYNC(sc, BUS_DMASYNC_POSTREAD); 158499726Sbenno for (i = sc->sc_rxptr; i != rxcomp; 158591398Stmm i = GEM_NEXTRX(i)) { 158691398Stmm rxs = &sc->sc_rxsoft[i]; 158791398Stmm 158891398Stmm rxstat = GEM_DMA_READ(sc, sc->sc_rxdescs[i].gd_flags); 158991398Stmm 159091398Stmm if (rxstat & GEM_RD_OWN) { 1591148368Smarius#ifdef GEM_RINT_TIMEOUT 159291398Stmm /* 159393045Stmm * The descriptor is still marked as owned, although 159493045Stmm * it is supposed to have completed. This has been 159593045Stmm * observed on some machines. Just exiting here 159693045Stmm * might leave the packet sitting around until another 159793045Stmm * one arrives to trigger a new interrupt, which is 159893045Stmm * generally undesirable, so set up a timeout. 159991398Stmm */ 160093045Stmm callout_reset(&sc->sc_rx_ch, GEM_RXOWN_TICKS, 160193045Stmm gem_rint_timeout, sc); 160299726Sbenno#endif 160391398Stmm break; 160491398Stmm } 160591398Stmm 160699726Sbenno progress++; 160799726Sbenno ifp->if_ipackets++; 160899726Sbenno 160991398Stmm if (rxstat & GEM_RD_BAD_CRC) { 161099726Sbenno ifp->if_ierrors++; 161191398Stmm device_printf(sc->sc_dev, "receive error: CRC error\n"); 161291398Stmm GEM_INIT_RXDESC(sc, i); 161391398Stmm continue; 161491398Stmm } 161591398Stmm 161691398Stmm#ifdef GEM_DEBUG 161791398Stmm if (ifp->if_flags & IFF_DEBUG) { 161891398Stmm printf(" rxsoft %p descriptor %d: ", rxs, i); 161991398Stmm printf("gd_flags: 0x%016llx\t", (long long) 162091398Stmm GEM_DMA_READ(sc, sc->sc_rxdescs[i].gd_flags)); 162191398Stmm printf("gd_addr: 0x%016llx\n", (long long) 162291398Stmm GEM_DMA_READ(sc, sc->sc_rxdescs[i].gd_addr)); 162391398Stmm } 162491398Stmm#endif 162591398Stmm 162691398Stmm /* 1627170273Syongari * No errors; receive the packet. 162891398Stmm */ 162991398Stmm len = GEM_RD_BUFLEN(rxstat); 163091398Stmm 163191398Stmm /* 163291398Stmm * Allocate a new mbuf cluster. If that fails, we are 163391398Stmm * out of memory, and must drop the packet and recycle 163491398Stmm * the buffer that's already attached to this descriptor. 163591398Stmm */ 163691398Stmm m = rxs->rxs_mbuf; 163791398Stmm if (gem_add_rxbuf(sc, i) != 0) { 163891398Stmm ifp->if_ierrors++; 163991398Stmm GEM_INIT_RXDESC(sc, i); 164091398Stmm continue; 164191398Stmm } 164291398Stmm m->m_data += 2; /* We're already off by two */ 164391398Stmm 164491398Stmm m->m_pkthdr.rcvif = ifp; 1645170273Syongari m->m_pkthdr.len = m->m_len = len; 164691398Stmm 1647170273Syongari if ((ifp->if_capenable & IFCAP_RXCSUM) != 0) 1648170273Syongari gem_rxcksum(m, rxstat); 1649170273Syongari 165091398Stmm /* Pass it on. */ 1651148369Smarius GEM_UNLOCK(sc); 1652106937Ssam (*ifp->if_input)(ifp, m); 1653148369Smarius GEM_LOCK(sc); 165491398Stmm } 165591398Stmm 165699726Sbenno if (progress) { 1657109648Stmm GEM_CDSYNC(sc, BUS_DMASYNC_PREWRITE); 165899726Sbenno /* Update the receive pointer. */ 165999726Sbenno if (i == sc->sc_rxptr) { 166099726Sbenno device_printf(sc->sc_dev, "rint: ring wrap\n"); 166199726Sbenno } 166299726Sbenno sc->sc_rxptr = i; 1663169269Sphk bus_write_4(sc->sc_res[0], GEM_RX_KICK, GEM_PREVRX(i)); 166499726Sbenno } 166591398Stmm 1666115030Stmm#ifdef GEM_DEBUG 1667170273Syongari CTR3(KTR_GEM, "%s: done sc->rxptr %d, complete %d", __func__, 1668169269Sphk sc->sc_rxptr, bus_read_4(sc->sc_res[0], GEM_RX_COMPLETION)); 1669115030Stmm#endif 167091398Stmm} 167191398Stmm 167291398Stmm 167391398Stmm/* 167491398Stmm * gem_add_rxbuf: 167591398Stmm * 167691398Stmm * Add a receive buffer to the indicated descriptor. 167791398Stmm */ 167891398Stmmstatic int 167991398Stmmgem_add_rxbuf(sc, idx) 168091398Stmm struct gem_softc *sc; 168191398Stmm int idx; 168291398Stmm{ 168391398Stmm struct gem_rxsoft *rxs = &sc->sc_rxsoft[idx]; 168491398Stmm struct mbuf *m; 1685148368Smarius bus_dma_segment_t segs[1]; 1686148368Smarius int error, nsegs; 168791398Stmm 1688111119Simp m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); 168991398Stmm if (m == NULL) 169091398Stmm return (ENOBUFS); 1691108832Stmm m->m_len = m->m_pkthdr.len = m->m_ext.ext_size; 169291398Stmm 169391398Stmm#ifdef GEM_DEBUG 169491398Stmm /* bzero the packet to check dma */ 169591398Stmm memset(m->m_ext.ext_buf, 0, m->m_ext.ext_size); 169691398Stmm#endif 169791398Stmm 1698109648Stmm if (rxs->rxs_mbuf != NULL) { 1699109648Stmm bus_dmamap_sync(sc->sc_rdmatag, rxs->rxs_dmamap, 1700109648Stmm BUS_DMASYNC_POSTREAD); 1701108832Stmm bus_dmamap_unload(sc->sc_rdmatag, rxs->rxs_dmamap); 1702109648Stmm } 170391398Stmm 170491398Stmm rxs->rxs_mbuf = m; 170591398Stmm 1706148368Smarius error = bus_dmamap_load_mbuf_sg(sc->sc_rdmatag, rxs->rxs_dmamap, 1707148368Smarius m, segs, &nsegs, BUS_DMA_NOWAIT); 1708148368Smarius /* If nsegs is wrong then the stack is corrupt. */ 1709148368Smarius KASSERT(nsegs == 1, ("Too many segments returned!")); 1710148368Smarius if (error != 0) { 171191398Stmm device_printf(sc->sc_dev, "can't load rx DMA map %d, error = " 171291398Stmm "%d\n", idx, error); 1713148368Smarius m_freem(m); 1714148368Smarius return (ENOBUFS); 171591398Stmm } 1716148368Smarius rxs->rxs_paddr = segs[0].ds_addr; 171791398Stmm 1718108832Stmm bus_dmamap_sync(sc->sc_rdmatag, rxs->rxs_dmamap, BUS_DMASYNC_PREREAD); 171991398Stmm 172091398Stmm GEM_INIT_RXDESC(sc, idx); 172191398Stmm 172291398Stmm return (0); 172391398Stmm} 172491398Stmm 172591398Stmm 172691398Stmmstatic void 172791398Stmmgem_eint(sc, status) 172891398Stmm struct gem_softc *sc; 172991398Stmm u_int status; 173091398Stmm{ 173191398Stmm 173291398Stmm if ((status & GEM_INTR_MIF) != 0) { 173391398Stmm device_printf(sc->sc_dev, "XXXlink status changed\n"); 173491398Stmm return; 173591398Stmm } 173691398Stmm 173791398Stmm device_printf(sc->sc_dev, "status=%x\n", status); 173891398Stmm} 173991398Stmm 174091398Stmm 174191398Stmmvoid 174291398Stmmgem_intr(v) 174391398Stmm void *v; 174491398Stmm{ 174591398Stmm struct gem_softc *sc = (struct gem_softc *)v; 174691398Stmm u_int32_t status; 174791398Stmm 1748148369Smarius GEM_LOCK(sc); 1749169269Sphk status = bus_read_4(sc->sc_res[0], GEM_STATUS); 1750115030Stmm#ifdef GEM_DEBUG 1751170273Syongari CTR4(KTR_GEM, "%s: %s: cplt %x, status %x", 1752170273Syongari device_get_name(sc->sc_dev), __func__, (status>>19), 175391398Stmm (u_int)status); 1754115030Stmm#endif 175591398Stmm 175691398Stmm if ((status & (GEM_INTR_RX_TAG_ERR | GEM_INTR_BERR)) != 0) 175791398Stmm gem_eint(sc, status); 175891398Stmm 175991398Stmm if ((status & (GEM_INTR_TX_EMPTY | GEM_INTR_TX_INTME)) != 0) 176091398Stmm gem_tint(sc); 176191398Stmm 176291398Stmm if ((status & (GEM_INTR_RX_DONE | GEM_INTR_RX_NOBUF)) != 0) 176391398Stmm gem_rint(sc); 176491398Stmm 176591398Stmm /* We should eventually do more than just print out error stats. */ 176691398Stmm if (status & GEM_INTR_TX_MAC) { 1767169269Sphk int txstat = bus_read_4(sc->sc_res[0], GEM_MAC_TX_STATUS); 176891398Stmm if (txstat & ~GEM_MAC_TX_XMIT_DONE) 176999726Sbenno device_printf(sc->sc_dev, "MAC tx fault, status %x\n", 177099726Sbenno txstat); 177197240Stmm if (txstat & (GEM_MAC_TX_UNDERRUN | GEM_MAC_TX_PKT_TOO_LONG)) 1772148369Smarius gem_init_locked(sc); 177391398Stmm } 177491398Stmm if (status & GEM_INTR_RX_MAC) { 1775169269Sphk int rxstat = bus_read_4(sc->sc_res[0], GEM_MAC_RX_STATUS); 1776149552Smarius /* 1777149552Smarius * On some chip revisions GEM_MAC_RX_OVERFLOW happen often 1778149552Smarius * due to a silicon bug so handle them silently. 1779149552Smarius */ 1780149552Smarius if (rxstat & GEM_MAC_RX_OVERFLOW) 1781149552Smarius gem_init_locked(sc); 1782149552Smarius else if (rxstat & ~(GEM_MAC_RX_DONE | GEM_MAC_RX_FRAME_CNT)) 178399726Sbenno device_printf(sc->sc_dev, "MAC rx fault, status %x\n", 178499726Sbenno rxstat); 178591398Stmm } 1786148369Smarius GEM_UNLOCK(sc); 178791398Stmm} 178891398Stmm 1789164931Smariusstatic int 1790164931Smariusgem_watchdog(sc) 1791164931Smarius struct gem_softc *sc; 179291398Stmm{ 179391398Stmm 1794164931Smarius GEM_LOCK_ASSERT(sc, MA_OWNED); 1795164931Smarius 1796115030Stmm#ifdef GEM_DEBUG 1797170273Syongari CTR4(KTR_GEM, "%s: GEM_RX_CONFIG %x GEM_MAC_RX_STATUS %x " 1798170273Syongari "GEM_MAC_RX_CONFIG %x", __func__, 1799169269Sphk bus_read_4(sc->sc_res[0], GEM_RX_CONFIG), 1800169269Sphk bus_read_4(sc->sc_res[0], GEM_MAC_RX_STATUS), 1801169269Sphk bus_read_4(sc->sc_res[0], GEM_MAC_RX_CONFIG)); 1802170273Syongari CTR4(KTR_GEM, "%s: GEM_TX_CONFIG %x GEM_MAC_TX_STATUS %x " 1803170273Syongari "GEM_MAC_TX_CONFIG %x", __func__, 1804169269Sphk bus_read_4(sc->sc_res[0], GEM_TX_CONFIG), 1805169269Sphk bus_read_4(sc->sc_res[0], GEM_MAC_TX_STATUS), 1806169269Sphk bus_read_4(sc->sc_res[0], GEM_MAC_TX_CONFIG)); 1807115030Stmm#endif 180891398Stmm 1809164931Smarius if (sc->sc_wdog_timer == 0 || --sc->sc_wdog_timer != 0) 1810164931Smarius return (0); 1811164931Smarius 181291398Stmm device_printf(sc->sc_dev, "device timeout\n"); 1813164931Smarius ++sc->sc_ifp->if_oerrors; 181491398Stmm 181591398Stmm /* Try to get more packets going. */ 1816148369Smarius gem_init_locked(sc); 1817164931Smarius return (EJUSTRETURN); 181891398Stmm} 181991398Stmm 182091398Stmm/* 182191398Stmm * Initialize the MII Management Interface 182291398Stmm */ 182391398Stmmstatic void 182491398Stmmgem_mifinit(sc) 182591398Stmm struct gem_softc *sc; 182691398Stmm{ 182791398Stmm 182891398Stmm /* Configure the MIF in frame mode */ 1829169269Sphk sc->sc_mif_config = bus_read_4(sc->sc_res[0], GEM_MIF_CONFIG); 183091398Stmm sc->sc_mif_config &= ~GEM_MIF_CONFIG_BB_ENA; 1831169269Sphk bus_write_4(sc->sc_res[0], GEM_MIF_CONFIG, sc->sc_mif_config); 183291398Stmm} 183391398Stmm 183491398Stmm/* 183591398Stmm * MII interface 183691398Stmm * 183791398Stmm * The GEM MII interface supports at least three different operating modes: 183891398Stmm * 183991398Stmm * Bitbang mode is implemented using data, clock and output enable registers. 184091398Stmm * 184191398Stmm * Frame mode is implemented by loading a complete frame into the frame 184291398Stmm * register and polling the valid bit for completion. 184391398Stmm * 184491398Stmm * Polling mode uses the frame register but completion is indicated by 184591398Stmm * an interrupt. 184691398Stmm * 184791398Stmm */ 184891398Stmmint 184991398Stmmgem_mii_readreg(dev, phy, reg) 185091398Stmm device_t dev; 185191398Stmm int phy, reg; 185291398Stmm{ 185391398Stmm struct gem_softc *sc = device_get_softc(dev); 185491398Stmm int n; 185591398Stmm u_int32_t v; 185691398Stmm 185791398Stmm#ifdef GEM_DEBUG_PHY 185891398Stmm printf("gem_mii_readreg: phy %d reg %d\n", phy, reg); 185991398Stmm#endif 186091398Stmm 186191398Stmm#if 0 186291398Stmm /* Select the desired PHY in the MIF configuration register */ 1863169269Sphk v = bus_read_4(sc->sc_res[0], GEM_MIF_CONFIG); 186491398Stmm /* Clear PHY select bit */ 186591398Stmm v &= ~GEM_MIF_CONFIG_PHY_SEL; 186691398Stmm if (phy == GEM_PHYAD_EXTERNAL) 186791398Stmm /* Set PHY select bit to get at external device */ 186891398Stmm v |= GEM_MIF_CONFIG_PHY_SEL; 1869169269Sphk bus_write_4(sc->sc_res[0], GEM_MIF_CONFIG, v); 187091398Stmm#endif 187191398Stmm 187291398Stmm /* Construct the frame command */ 187391398Stmm v = (reg << GEM_MIF_REG_SHIFT) | (phy << GEM_MIF_PHY_SHIFT) | 187491398Stmm GEM_MIF_FRAME_READ; 187591398Stmm 1876169269Sphk bus_write_4(sc->sc_res[0], GEM_MIF_FRAME, v); 187791398Stmm for (n = 0; n < 100; n++) { 187891398Stmm DELAY(1); 1879169269Sphk v = bus_read_4(sc->sc_res[0], GEM_MIF_FRAME); 1880150285Smarius if (v & GEM_MIF_FRAME_TA0) 188191398Stmm return (v & GEM_MIF_FRAME_DATA); 188291398Stmm } 188391398Stmm 188491398Stmm device_printf(sc->sc_dev, "mii_read timeout\n"); 188591398Stmm return (0); 188691398Stmm} 188791398Stmm 188891398Stmmint 188991398Stmmgem_mii_writereg(dev, phy, reg, val) 189091398Stmm device_t dev; 189191398Stmm int phy, reg, val; 189291398Stmm{ 189391398Stmm struct gem_softc *sc = device_get_softc(dev); 189491398Stmm int n; 189591398Stmm u_int32_t v; 189691398Stmm 189791398Stmm#ifdef GEM_DEBUG_PHY 189891398Stmm printf("gem_mii_writereg: phy %d reg %d val %x\n", phy, reg, val); 189991398Stmm#endif 190091398Stmm 190191398Stmm#if 0 190291398Stmm /* Select the desired PHY in the MIF configuration register */ 1903169269Sphk v = bus_read_4(sc->sc_res[0], GEM_MIF_CONFIG); 190491398Stmm /* Clear PHY select bit */ 190591398Stmm v &= ~GEM_MIF_CONFIG_PHY_SEL; 190691398Stmm if (phy == GEM_PHYAD_EXTERNAL) 190791398Stmm /* Set PHY select bit to get at external device */ 190891398Stmm v |= GEM_MIF_CONFIG_PHY_SEL; 1909169269Sphk bus_write_4(sc->sc_res[0], GEM_MIF_CONFIG, v); 191091398Stmm#endif 191191398Stmm /* Construct the frame command */ 191291398Stmm v = GEM_MIF_FRAME_WRITE | 191391398Stmm (phy << GEM_MIF_PHY_SHIFT) | 191491398Stmm (reg << GEM_MIF_REG_SHIFT) | 191591398Stmm (val & GEM_MIF_FRAME_DATA); 191691398Stmm 1917169269Sphk bus_write_4(sc->sc_res[0], GEM_MIF_FRAME, v); 191891398Stmm for (n = 0; n < 100; n++) { 191991398Stmm DELAY(1); 1920169269Sphk v = bus_read_4(sc->sc_res[0], GEM_MIF_FRAME); 1921150285Smarius if (v & GEM_MIF_FRAME_TA0) 192291398Stmm return (1); 192391398Stmm } 192491398Stmm 192591398Stmm device_printf(sc->sc_dev, "mii_write timeout\n"); 192691398Stmm return (0); 192791398Stmm} 192891398Stmm 192991398Stmmvoid 193091398Stmmgem_mii_statchg(dev) 193191398Stmm device_t dev; 193291398Stmm{ 193391398Stmm struct gem_softc *sc = device_get_softc(dev); 193491398Stmm#ifdef GEM_DEBUG 1935148369Smarius int instance; 193691398Stmm#endif 193791398Stmm u_int32_t v; 193891398Stmm 193991398Stmm#ifdef GEM_DEBUG 1940148369Smarius instance = IFM_INST(sc->sc_mii->mii_media.ifm_cur->ifm_media); 194191398Stmm if (sc->sc_debug) 194291398Stmm printf("gem_mii_statchg: status change: phy = %d\n", 194391398Stmm sc->sc_phys[instance]); 194491398Stmm#endif 194591398Stmm 194691398Stmm /* Set tx full duplex options */ 1947169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_TX_CONFIG, 0); 194891398Stmm DELAY(10000); /* reg must be cleared and delay before changing. */ 194991398Stmm v = GEM_MAC_TX_ENA_IPG0|GEM_MAC_TX_NGU|GEM_MAC_TX_NGU_LIMIT| 195091398Stmm GEM_MAC_TX_ENABLE; 195191398Stmm if ((IFM_OPTIONS(sc->sc_mii->mii_media_active) & IFM_FDX) != 0) { 195291398Stmm v |= GEM_MAC_TX_IGN_CARRIER|GEM_MAC_TX_IGN_COLLIS; 195391398Stmm } 1954169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_TX_CONFIG, v); 195591398Stmm 195691398Stmm /* XIF Configuration */ 195791398Stmm v = GEM_MAC_XIF_LINK_LED; 195891398Stmm v |= GEM_MAC_XIF_TX_MII_ENA; 195999726Sbenno 196091398Stmm /* If an external transceiver is connected, enable its MII drivers */ 1961169269Sphk sc->sc_mif_config = bus_read_4(sc->sc_res[0], GEM_MIF_CONFIG); 196291398Stmm if ((sc->sc_mif_config & GEM_MIF_CONFIG_MDI1) != 0) { 196391398Stmm /* External MII needs echo disable if half duplex. */ 196491398Stmm if ((IFM_OPTIONS(sc->sc_mii->mii_media_active) & IFM_FDX) != 0) 196591398Stmm /* turn on full duplex LED */ 196691398Stmm v |= GEM_MAC_XIF_FDPLX_LED; 196799726Sbenno else 196899726Sbenno /* half duplex -- disable echo */ 196999726Sbenno v |= GEM_MAC_XIF_ECHO_DISABL; 197099726Sbenno 197199726Sbenno if (IFM_SUBTYPE(sc->sc_mii->mii_media_active) == IFM_1000_T) 197299726Sbenno v |= GEM_MAC_XIF_GMII_MODE; 197399726Sbenno else 197499726Sbenno v &= ~GEM_MAC_XIF_GMII_MODE; 197591398Stmm } else { 197691398Stmm /* Internal MII needs buf enable */ 197791398Stmm v |= GEM_MAC_XIF_MII_BUF_ENA; 197891398Stmm } 1979169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_XIF_CONFIG, v); 198091398Stmm} 198191398Stmm 198291398Stmmint 198391398Stmmgem_mediachange(ifp) 198491398Stmm struct ifnet *ifp; 198591398Stmm{ 198691398Stmm struct gem_softc *sc = ifp->if_softc; 1987150285Smarius int error; 198891398Stmm 198991398Stmm /* XXX Add support for serial media. */ 199091398Stmm 1991150285Smarius GEM_LOCK(sc); 1992150285Smarius error = mii_mediachg(sc->sc_mii); 1993150285Smarius GEM_UNLOCK(sc); 1994150285Smarius return (error); 199591398Stmm} 199691398Stmm 199791398Stmmvoid 199891398Stmmgem_mediastatus(ifp, ifmr) 199991398Stmm struct ifnet *ifp; 200091398Stmm struct ifmediareq *ifmr; 200191398Stmm{ 200291398Stmm struct gem_softc *sc = ifp->if_softc; 200391398Stmm 2004148369Smarius GEM_LOCK(sc); 2005148369Smarius if ((ifp->if_flags & IFF_UP) == 0) { 2006148369Smarius GEM_UNLOCK(sc); 200791398Stmm return; 2008148369Smarius } 200991398Stmm 201091398Stmm mii_pollstat(sc->sc_mii); 201191398Stmm ifmr->ifm_active = sc->sc_mii->mii_media_active; 201291398Stmm ifmr->ifm_status = sc->sc_mii->mii_media_status; 2013148369Smarius GEM_UNLOCK(sc); 201491398Stmm} 201591398Stmm 201691398Stmm/* 201791398Stmm * Process an ioctl request. 201891398Stmm */ 201991398Stmmstatic int 202091398Stmmgem_ioctl(ifp, cmd, data) 202191398Stmm struct ifnet *ifp; 202291398Stmm u_long cmd; 202391398Stmm caddr_t data; 202491398Stmm{ 202591398Stmm struct gem_softc *sc = ifp->if_softc; 202691398Stmm struct ifreq *ifr = (struct ifreq *)data; 2027148369Smarius int error = 0; 202891398Stmm 202991398Stmm switch (cmd) { 2030150285Smarius case SIOCSIFFLAGS: 2031148369Smarius GEM_LOCK(sc); 203291398Stmm if (ifp->if_flags & IFF_UP) { 203399726Sbenno if ((sc->sc_ifflags ^ ifp->if_flags) == IFF_PROMISC) 203491398Stmm gem_setladrf(sc); 203591398Stmm else 2036148369Smarius gem_init_locked(sc); 203791398Stmm } else { 2038148887Srwatson if (ifp->if_drv_flags & IFF_DRV_RUNNING) 203991398Stmm gem_stop(ifp, 0); 204091398Stmm } 2041170273Syongari if ((ifp->if_flags & IFF_LINK0) != 0) 2042170273Syongari sc->sc_csum_features |= CSUM_UDP; 2043170273Syongari else 2044170273Syongari sc->sc_csum_features &= ~CSUM_UDP; 2045170273Syongari if ((ifp->if_capenable & IFCAP_TXCSUM) != 0) 2046170273Syongari ifp->if_hwassist = sc->sc_csum_features; 204799726Sbenno sc->sc_ifflags = ifp->if_flags; 2048150285Smarius GEM_UNLOCK(sc); 204991398Stmm break; 205091398Stmm case SIOCADDMULTI: 205191398Stmm case SIOCDELMULTI: 2052150285Smarius GEM_LOCK(sc); 205391398Stmm gem_setladrf(sc); 2054150285Smarius GEM_UNLOCK(sc); 205591398Stmm break; 205691398Stmm case SIOCGIFMEDIA: 205791398Stmm case SIOCSIFMEDIA: 205891398Stmm error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii->mii_media, cmd); 205991398Stmm break; 2060170273Syongari case SIOCSIFCAP: 2061170273Syongari GEM_LOCK(sc); 2062170273Syongari ifp->if_capenable = ifr->ifr_reqcap; 2063170273Syongari if ((ifp->if_capenable & IFCAP_TXCSUM) != 0) 2064170273Syongari ifp->if_hwassist = sc->sc_csum_features; 2065170273Syongari else 2066170273Syongari ifp->if_hwassist = 0; 2067170273Syongari GEM_UNLOCK(sc); 2068170273Syongari break; 206991398Stmm default: 2070150285Smarius error = ether_ioctl(ifp, cmd, data); 207191398Stmm break; 207291398Stmm } 207391398Stmm 207491398Stmm return (error); 207591398Stmm} 207691398Stmm 207791398Stmm/* 207891398Stmm * Set up the logical address filter. 207991398Stmm */ 208091398Stmmstatic void 208191398Stmmgem_setladrf(sc) 208291398Stmm struct gem_softc *sc; 208391398Stmm{ 2084147256Sbrooks struct ifnet *ifp = sc->sc_ifp; 208591398Stmm struct ifmultiaddr *inm; 208691398Stmm u_int32_t crc; 208791398Stmm u_int32_t hash[16]; 208891398Stmm u_int32_t v; 208999726Sbenno int i; 209091398Stmm 2091148369Smarius GEM_LOCK_ASSERT(sc, MA_OWNED); 2092148369Smarius 209391398Stmm /* Get current RX configuration */ 2094169269Sphk v = bus_read_4(sc->sc_res[0], GEM_MAC_RX_CONFIG); 209591398Stmm 209699726Sbenno /* 209799726Sbenno * Turn off promiscuous mode, promiscuous group mode (all multicast), 209899726Sbenno * and hash filter. Depending on the case, the right bit will be 209999726Sbenno * enabled. 210099726Sbenno */ 210199726Sbenno v &= ~(GEM_MAC_RX_PROMISCUOUS|GEM_MAC_RX_HASH_FILTER| 210299726Sbenno GEM_MAC_RX_PROMISC_GRP); 210399726Sbenno 210491398Stmm if ((ifp->if_flags & IFF_PROMISC) != 0) { 210599726Sbenno /* Turn on promiscuous mode */ 210691398Stmm v |= GEM_MAC_RX_PROMISCUOUS; 210791398Stmm goto chipit; 210891398Stmm } 210991398Stmm if ((ifp->if_flags & IFF_ALLMULTI) != 0) { 211091398Stmm hash[3] = hash[2] = hash[1] = hash[0] = 0xffff; 211191398Stmm ifp->if_flags |= IFF_ALLMULTI; 211299726Sbenno v |= GEM_MAC_RX_PROMISC_GRP; 211391398Stmm goto chipit; 211491398Stmm } 211591398Stmm 211691398Stmm /* 211791398Stmm * Set up multicast address filter by passing all multicast addresses 211899726Sbenno * through a crc generator, and then using the high order 8 bits as an 211999726Sbenno * index into the 256 bit logical address filter. The high order 4 212099726Sbenno * bits selects the word, while the other 4 bits select the bit within 212199726Sbenno * the word (where bit 0 is the MSB). 212291398Stmm */ 212391398Stmm 212499726Sbenno /* Clear hash table */ 212599726Sbenno memset(hash, 0, sizeof(hash)); 212699726Sbenno 2127148654Srwatson IF_ADDR_LOCK(ifp); 2128147256Sbrooks TAILQ_FOREACH(inm, &ifp->if_multiaddrs, ifma_link) { 212991398Stmm if (inm->ifma_addr->sa_family != AF_LINK) 213091398Stmm continue; 2131130288Smarius crc = ether_crc32_le(LLADDR((struct sockaddr_dl *) 2132130288Smarius inm->ifma_addr), ETHER_ADDR_LEN); 213391398Stmm 213491398Stmm /* Just want the 8 most significant bits. */ 213591398Stmm crc >>= 24; 213691398Stmm 213791398Stmm /* Set the corresponding bit in the filter. */ 213899726Sbenno hash[crc >> 4] |= 1 << (15 - (crc & 15)); 213991398Stmm } 2140148654Srwatson IF_ADDR_UNLOCK(ifp); 214191398Stmm 214299726Sbenno v |= GEM_MAC_RX_HASH_FILTER; 214399726Sbenno ifp->if_flags &= ~IFF_ALLMULTI; 214499726Sbenno 214599726Sbenno /* Now load the hash table into the chip (if we are using it) */ 214699726Sbenno for (i = 0; i < 16; i++) { 2147169269Sphk bus_write_4(sc->sc_res[0], 214899726Sbenno GEM_MAC_HASH0 + i * (GEM_MAC_HASH1-GEM_MAC_HASH0), 214999726Sbenno hash[i]); 215099726Sbenno } 215199726Sbenno 215291398Stmmchipit: 2153169269Sphk bus_write_4(sc->sc_res[0], GEM_MAC_RX_CONFIG, v); 215491398Stmm} 2155