if_gem.c revision 130288
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 130288 2004-06-10 00:04:16Z marius $"); 32119418Sobrien 3391398Stmm/* 3491398Stmm * Driver for Sun GEM ethernet controllers. 3591398Stmm */ 3691398Stmm 37115030Stmm#if 0 3891398Stmm#define GEM_DEBUG 39115030Stmm#endif 4091398Stmm 4191398Stmm#include <sys/param.h> 4291398Stmm#include <sys/systm.h> 4391398Stmm#include <sys/bus.h> 4491398Stmm#include <sys/callout.h> 4595533Smike#include <sys/endian.h> 4691398Stmm#include <sys/mbuf.h> 4791398Stmm#include <sys/malloc.h> 4891398Stmm#include <sys/kernel.h> 49130026Sphk#include <sys/module.h> 5091398Stmm#include <sys/socket.h> 5191398Stmm#include <sys/sockio.h> 5291398Stmm 53105982Stmm#include <net/bpf.h> 5491398Stmm#include <net/ethernet.h> 5591398Stmm#include <net/if.h> 5691398Stmm#include <net/if_arp.h> 5791398Stmm#include <net/if_dl.h> 5891398Stmm#include <net/if_media.h> 5991398Stmm 6091398Stmm#include <machine/bus.h> 6191398Stmm 6291398Stmm#include <dev/mii/mii.h> 6391398Stmm#include <dev/mii/miivar.h> 6491398Stmm 65119355Simp#include <dev/gem/if_gemreg.h> 66119355Simp#include <dev/gem/if_gemvar.h> 6791398Stmm 6891398Stmm#define TRIES 10000 6991398Stmm 7092739Salfredstatic void gem_start(struct ifnet *); 7192739Salfredstatic void gem_stop(struct ifnet *, int); 7292739Salfredstatic int gem_ioctl(struct ifnet *, u_long, caddr_t); 7392739Salfredstatic void gem_cddma_callback(void *, bus_dma_segment_t *, int, int); 74108832Stmmstatic void gem_rxdma_callback(void *, bus_dma_segment_t *, int, 75108832Stmm bus_size_t, int); 76108832Stmmstatic void gem_txdma_callback(void *, bus_dma_segment_t *, int, 77108832Stmm bus_size_t, int); 7892739Salfredstatic void gem_tick(void *); 7992739Salfredstatic void gem_watchdog(struct ifnet *); 8092739Salfredstatic void gem_init(void *); 8192739Salfredstatic void gem_init_regs(struct gem_softc *sc); 8292739Salfredstatic int gem_ringsize(int sz); 8392739Salfredstatic int gem_meminit(struct gem_softc *); 84108832Stmmstatic int gem_load_txmbuf(struct gem_softc *, struct mbuf *); 8592739Salfredstatic void gem_mifinit(struct gem_softc *); 8692739Salfredstatic int gem_bitwait(struct gem_softc *sc, bus_addr_t r, 8792739Salfred u_int32_t clr, u_int32_t set); 8892739Salfredstatic int gem_reset_rx(struct gem_softc *); 8992739Salfredstatic int gem_reset_tx(struct gem_softc *); 9092739Salfredstatic int gem_disable_rx(struct gem_softc *); 9192739Salfredstatic int gem_disable_tx(struct gem_softc *); 9292739Salfredstatic void gem_rxdrain(struct gem_softc *); 9392739Salfredstatic int gem_add_rxbuf(struct gem_softc *, int); 9492739Salfredstatic void gem_setladrf(struct gem_softc *); 9591398Stmm 9692739Salfredstruct mbuf *gem_get(struct gem_softc *, int, int); 9792739Salfredstatic void gem_eint(struct gem_softc *, u_int); 9892739Salfredstatic void gem_rint(struct gem_softc *); 99100587Sjake#if 0 10093045Stmmstatic void gem_rint_timeout(void *); 101100587Sjake#endif 10292739Salfredstatic void gem_tint(struct gem_softc *); 10391398Stmm#ifdef notyet 10492739Salfredstatic void gem_power(int, void *); 10591398Stmm#endif 10691398Stmm 10791398Stmmdevclass_t gem_devclass; 10891398StmmDRIVER_MODULE(miibus, gem, miibus_driver, miibus_devclass, 0, 0); 10991398StmmMODULE_DEPEND(gem, miibus, 1, 1, 1); 11091398Stmm 11191398Stmm#ifdef GEM_DEBUG 11291398Stmm#include <sys/ktr.h> 11391398Stmm#define KTR_GEM KTR_CT2 11491398Stmm#endif 11591398Stmm 116115030Stmm#define GEM_NSEGS GEM_NTXDESC 11791398Stmm 11891398Stmm/* 11991398Stmm * gem_attach: 12091398Stmm * 12191398Stmm * Attach a Gem interface to the system. 12291398Stmm */ 12391398Stmmint 12491398Stmmgem_attach(sc) 12591398Stmm struct gem_softc *sc; 12691398Stmm{ 12791398Stmm struct ifnet *ifp = &sc->sc_arpcom.ac_if; 12891398Stmm struct mii_softc *child; 12991398Stmm int i, error; 13099726Sbenno u_int32_t v; 13191398Stmm 13291398Stmm /* Make sure the chip is stopped. */ 13391398Stmm ifp->if_softc = sc; 13491398Stmm gem_reset(sc); 13591398Stmm 13691398Stmm error = bus_dma_tag_create(NULL, 1, 0, BUS_SPACE_MAXADDR_32BIT, 13791398Stmm BUS_SPACE_MAXADDR, NULL, NULL, MCLBYTES, GEM_NSEGS, 138117126Sscottl BUS_SPACE_MAXSIZE_32BIT, 0, NULL, NULL, &sc->sc_pdmatag); 13991398Stmm if (error) 14091398Stmm return (error); 14191398Stmm 14291398Stmm error = bus_dma_tag_create(sc->sc_pdmatag, 1, 0, 14391398Stmm BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, MAXBSIZE, 144117126Sscottl 1, BUS_SPACE_MAXSIZE_32BIT, BUS_DMA_ALLOCNOW, NULL, NULL, 145108832Stmm &sc->sc_rdmatag); 14691398Stmm if (error) 147108832Stmm goto fail_ptag; 14891398Stmm 149108832Stmm error = bus_dma_tag_create(sc->sc_pdmatag, 1, 0, 150108832Stmm BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, 151115030Stmm GEM_TD_BUFSIZE, GEM_NTXDESC, BUS_SPACE_MAXSIZE_32BIT, 152117126Sscottl BUS_DMA_ALLOCNOW, NULL, NULL, &sc->sc_tdmatag); 153108832Stmm if (error) 154108832Stmm goto fail_rtag; 155108832Stmm 15691398Stmm error = bus_dma_tag_create(sc->sc_pdmatag, PAGE_SIZE, 0, 15791398Stmm BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, 15891398Stmm sizeof(struct gem_control_data), 1, 15991398Stmm sizeof(struct gem_control_data), BUS_DMA_ALLOCNOW, 160117126Sscottl busdma_lock_mutex, &Giant, &sc->sc_cdmatag); 16191398Stmm if (error) 162108832Stmm goto fail_ttag; 16391398Stmm 16491398Stmm /* 16591398Stmm * Allocate the control data structures, and create and load the 16691398Stmm * DMA map for it. 16791398Stmm */ 16891398Stmm if ((error = bus_dmamem_alloc(sc->sc_cdmatag, 16991398Stmm (void **)&sc->sc_control_data, 0, &sc->sc_cddmamap))) { 17091398Stmm device_printf(sc->sc_dev, "unable to allocate control data," 17191398Stmm " error = %d\n", error); 172108832Stmm goto fail_ctag; 17391398Stmm } 17491398Stmm 17591398Stmm sc->sc_cddma = 0; 17691398Stmm if ((error = bus_dmamap_load(sc->sc_cdmatag, sc->sc_cddmamap, 17791398Stmm sc->sc_control_data, sizeof(struct gem_control_data), 17891398Stmm gem_cddma_callback, sc, 0)) != 0 || sc->sc_cddma == 0) { 17991398Stmm device_printf(sc->sc_dev, "unable to load control data DMA " 18091398Stmm "map, error = %d\n", error); 181108832Stmm goto fail_cmem; 18291398Stmm } 18391398Stmm 18491398Stmm /* 18591398Stmm * Initialize the transmit job descriptors. 18691398Stmm */ 18791398Stmm STAILQ_INIT(&sc->sc_txfreeq); 18891398Stmm STAILQ_INIT(&sc->sc_txdirtyq); 18991398Stmm 19091398Stmm /* 19191398Stmm * Create the transmit buffer DMA maps. 19291398Stmm */ 19391398Stmm error = ENOMEM; 19491398Stmm for (i = 0; i < GEM_TXQUEUELEN; i++) { 19591398Stmm struct gem_txsoft *txs; 19691398Stmm 19791398Stmm txs = &sc->sc_txsoft[i]; 19891398Stmm txs->txs_mbuf = NULL; 19991398Stmm txs->txs_ndescs = 0; 200108832Stmm if ((error = bus_dmamap_create(sc->sc_tdmatag, 0, 20191398Stmm &txs->txs_dmamap)) != 0) { 20291398Stmm device_printf(sc->sc_dev, "unable to create tx DMA map " 20391398Stmm "%d, error = %d\n", i, error); 204108832Stmm goto fail_txd; 20591398Stmm } 20691398Stmm STAILQ_INSERT_TAIL(&sc->sc_txfreeq, txs, txs_q); 20791398Stmm } 20891398Stmm 20991398Stmm /* 21091398Stmm * Create the receive buffer DMA maps. 21191398Stmm */ 21291398Stmm for (i = 0; i < GEM_NRXDESC; i++) { 213108832Stmm if ((error = bus_dmamap_create(sc->sc_rdmatag, 0, 21491398Stmm &sc->sc_rxsoft[i].rxs_dmamap)) != 0) { 21591398Stmm device_printf(sc->sc_dev, "unable to create rx DMA map " 21691398Stmm "%d, error = %d\n", i, error); 217108832Stmm goto fail_rxd; 21891398Stmm } 21991398Stmm sc->sc_rxsoft[i].rxs_mbuf = NULL; 22091398Stmm } 22191398Stmm 22291398Stmm 22391398Stmm gem_mifinit(sc); 22491398Stmm 22591398Stmm if ((error = mii_phy_probe(sc->sc_dev, &sc->sc_miibus, gem_mediachange, 22691398Stmm gem_mediastatus)) != 0) { 22791398Stmm device_printf(sc->sc_dev, "phy probe failed: %d\n", error); 228108832Stmm goto fail_rxd; 22991398Stmm } 23091398Stmm sc->sc_mii = device_get_softc(sc->sc_miibus); 23191398Stmm 23291398Stmm /* 23391398Stmm * From this point forward, the attachment cannot fail. A failure 23491398Stmm * before this point releases all resources that may have been 23591398Stmm * allocated. 23691398Stmm */ 23791398Stmm 23899726Sbenno /* Get RX FIFO size */ 23999726Sbenno sc->sc_rxfifosize = 64 * 24099726Sbenno bus_space_read_4(sc->sc_bustag, sc->sc_h, GEM_RX_FIFO_SIZE); 24199726Sbenno 24299726Sbenno /* Get TX FIFO size */ 24399726Sbenno v = bus_space_read_4(sc->sc_bustag, sc->sc_h, GEM_TX_FIFO_SIZE); 244128588Stmm device_printf(sc->sc_dev, "%ukB RX FIFO, %ukB TX FIFO\n", 245128588Stmm sc->sc_rxfifosize / 1024, v / 16); 24699726Sbenno 24791398Stmm /* Initialize ifnet structure. */ 24891398Stmm ifp->if_softc = sc; 249121816Sbrooks if_initname(ifp, device_get_name(sc->sc_dev), 250121816Sbrooks device_get_unit(sc->sc_dev)); 25191398Stmm ifp->if_mtu = ETHERMTU; 25291398Stmm ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 25391398Stmm ifp->if_start = gem_start; 25491398Stmm ifp->if_ioctl = gem_ioctl; 25591398Stmm ifp->if_watchdog = gem_watchdog; 25691398Stmm ifp->if_init = gem_init; 25791398Stmm ifp->if_snd.ifq_maxlen = GEM_TXQUEUELEN; 25891398Stmm /* 25991398Stmm * Walk along the list of attached MII devices and 26091398Stmm * establish an `MII instance' to `phy number' 26191398Stmm * mapping. We'll use this mapping in media change 26291398Stmm * requests to determine which phy to use to program 26391398Stmm * the MIF configuration register. 26491398Stmm */ 26591398Stmm for (child = LIST_FIRST(&sc->sc_mii->mii_phys); child != NULL; 26691398Stmm child = LIST_NEXT(child, mii_list)) { 26791398Stmm /* 26891398Stmm * Note: we support just two PHYs: the built-in 26991398Stmm * internal device and an external on the MII 27091398Stmm * connector. 27191398Stmm */ 27291398Stmm if (child->mii_phy > 1 || child->mii_inst > 1) { 27391398Stmm device_printf(sc->sc_dev, "cannot accomodate " 27491398Stmm "MII device %s at phy %d, instance %d\n", 27591398Stmm device_get_name(child->mii_dev), 27691398Stmm child->mii_phy, child->mii_inst); 27791398Stmm continue; 27891398Stmm } 27991398Stmm 28091398Stmm sc->sc_phys[child->mii_inst] = child->mii_phy; 28191398Stmm } 28291398Stmm 28391398Stmm /* 28491398Stmm * Now select and activate the PHY we will use. 28591398Stmm * 28691398Stmm * The order of preference is External (MDI1), 28791398Stmm * Internal (MDI0), Serial Link (no MII). 28891398Stmm */ 28991398Stmm if (sc->sc_phys[1]) { 29091398Stmm#ifdef GEM_DEBUG 29191398Stmm printf("using external phy\n"); 29291398Stmm#endif 29391398Stmm sc->sc_mif_config |= GEM_MIF_CONFIG_PHY_SEL; 29491398Stmm } else { 29591398Stmm#ifdef GEM_DEBUG 29691398Stmm printf("using internal phy\n"); 29791398Stmm#endif 29891398Stmm sc->sc_mif_config &= ~GEM_MIF_CONFIG_PHY_SEL; 29991398Stmm } 30091398Stmm bus_space_write_4(sc->sc_bustag, sc->sc_h, GEM_MIF_CONFIG, 30191398Stmm sc->sc_mif_config); 30291398Stmm /* Attach the interface. */ 303106937Ssam ether_ifattach(ifp, sc->sc_arpcom.ac_enaddr); 30491398Stmm 30591398Stmm#if notyet 30691398Stmm /* 30791398Stmm * Add a suspend hook to make sure we come back up after a 30891398Stmm * resume. 30991398Stmm */ 31091398Stmm sc->sc_powerhook = powerhook_establish(gem_power, sc); 31191398Stmm if (sc->sc_powerhook == NULL) 31291398Stmm device_printf(sc->sc_dev, "WARNING: unable to establish power " 31391398Stmm "hook\n"); 31491398Stmm#endif 31591398Stmm 31691398Stmm callout_init(&sc->sc_tick_ch, 0); 31793045Stmm callout_init(&sc->sc_rx_ch, 0); 31891398Stmm return (0); 31991398Stmm 32091398Stmm /* 32191398Stmm * Free any resources we've allocated during the failed attach 32291398Stmm * attempt. Do this in reverse order and fall through. 32391398Stmm */ 324108832Stmmfail_rxd: 32591398Stmm for (i = 0; i < GEM_NRXDESC; i++) { 32691398Stmm if (sc->sc_rxsoft[i].rxs_dmamap != NULL) 327108832Stmm bus_dmamap_destroy(sc->sc_rdmatag, 32891398Stmm sc->sc_rxsoft[i].rxs_dmamap); 32991398Stmm } 330108832Stmmfail_txd: 33191398Stmm for (i = 0; i < GEM_TXQUEUELEN; i++) { 33291398Stmm if (sc->sc_txsoft[i].txs_dmamap != NULL) 333108832Stmm bus_dmamap_destroy(sc->sc_tdmatag, 33491398Stmm sc->sc_txsoft[i].txs_dmamap); 33591398Stmm } 336108832Stmm bus_dmamap_unload(sc->sc_cdmatag, sc->sc_cddmamap); 337108832Stmmfail_cmem: 33891398Stmm bus_dmamem_free(sc->sc_cdmatag, sc->sc_control_data, 33991398Stmm sc->sc_cddmamap); 340108832Stmmfail_ctag: 34191398Stmm bus_dma_tag_destroy(sc->sc_cdmatag); 342108832Stmmfail_ttag: 343108832Stmm bus_dma_tag_destroy(sc->sc_tdmatag); 344108832Stmmfail_rtag: 345108832Stmm bus_dma_tag_destroy(sc->sc_rdmatag); 346108832Stmmfail_ptag: 34791398Stmm bus_dma_tag_destroy(sc->sc_pdmatag); 34891398Stmm return (error); 34991398Stmm} 35091398Stmm 351108964Stmmvoid 352108964Stmmgem_detach(sc) 353108964Stmm struct gem_softc *sc; 354108964Stmm{ 355108964Stmm struct ifnet *ifp = &sc->sc_arpcom.ac_if; 356108964Stmm int i; 357108964Stmm 358108964Stmm ether_ifdetach(ifp); 359108964Stmm gem_stop(ifp, 1); 360108964Stmm device_delete_child(sc->sc_dev, sc->sc_miibus); 361108964Stmm 362108964Stmm for (i = 0; i < GEM_NRXDESC; i++) { 363108964Stmm if (sc->sc_rxsoft[i].rxs_dmamap != NULL) 364108964Stmm bus_dmamap_destroy(sc->sc_rdmatag, 365108964Stmm sc->sc_rxsoft[i].rxs_dmamap); 366108964Stmm } 367108964Stmm for (i = 0; i < GEM_TXQUEUELEN; i++) { 368108964Stmm if (sc->sc_txsoft[i].txs_dmamap != NULL) 369108964Stmm bus_dmamap_destroy(sc->sc_tdmatag, 370108964Stmm sc->sc_txsoft[i].txs_dmamap); 371108964Stmm } 372109648Stmm GEM_CDSYNC(sc, BUS_DMASYNC_POSTREAD); 373109648Stmm GEM_CDSYNC(sc, BUS_DMASYNC_POSTWRITE); 374108964Stmm bus_dmamap_unload(sc->sc_cdmatag, sc->sc_cddmamap); 375108964Stmm bus_dmamem_free(sc->sc_cdmatag, sc->sc_control_data, 376108964Stmm sc->sc_cddmamap); 377108964Stmm bus_dma_tag_destroy(sc->sc_cdmatag); 378108964Stmm bus_dma_tag_destroy(sc->sc_tdmatag); 379108964Stmm bus_dma_tag_destroy(sc->sc_rdmatag); 380108964Stmm bus_dma_tag_destroy(sc->sc_pdmatag); 381108964Stmm} 382108964Stmm 383108964Stmmvoid 384108964Stmmgem_suspend(sc) 385108964Stmm struct gem_softc *sc; 386108964Stmm{ 387108964Stmm struct ifnet *ifp = &sc->sc_arpcom.ac_if; 388108964Stmm 389108964Stmm gem_stop(ifp, 0); 390108964Stmm} 391108964Stmm 392108964Stmmvoid 393108964Stmmgem_resume(sc) 394108964Stmm struct gem_softc *sc; 395108964Stmm{ 396108964Stmm struct ifnet *ifp = &sc->sc_arpcom.ac_if; 397108964Stmm 398108964Stmm if (ifp->if_flags & IFF_UP) 399108964Stmm gem_init(ifp); 400108964Stmm} 401108964Stmm 40291398Stmmstatic void 40391398Stmmgem_cddma_callback(xsc, segs, nsegs, error) 40491398Stmm void *xsc; 40591398Stmm bus_dma_segment_t *segs; 40691398Stmm int nsegs; 40791398Stmm int error; 40891398Stmm{ 40991398Stmm struct gem_softc *sc = (struct gem_softc *)xsc; 41091398Stmm 41191398Stmm if (error != 0) 41291398Stmm return; 41391398Stmm if (nsegs != 1) { 41491398Stmm /* can't happen... */ 41591398Stmm panic("gem_cddma_callback: bad control buffer segment count"); 41691398Stmm } 41791398Stmm sc->sc_cddma = segs[0].ds_addr; 41891398Stmm} 41991398Stmm 42091398Stmmstatic void 421108832Stmmgem_rxdma_callback(xsc, segs, nsegs, totsz, error) 42291398Stmm void *xsc; 42391398Stmm bus_dma_segment_t *segs; 42491398Stmm int nsegs; 425108832Stmm bus_size_t totsz; 42691398Stmm int error; 42791398Stmm{ 42891398Stmm struct gem_rxsoft *rxs = (struct gem_rxsoft *)xsc; 42991398Stmm 43091398Stmm if (error != 0) 43191398Stmm return; 432108832Stmm KASSERT(nsegs == 1, ("gem_rxdma_callback: bad dma segment count")); 43391398Stmm rxs->rxs_paddr = segs[0].ds_addr; 43491398Stmm} 43591398Stmm 43691398Stmmstatic void 437108832Stmmgem_txdma_callback(xsc, segs, nsegs, totsz, error) 43891398Stmm void *xsc; 43991398Stmm bus_dma_segment_t *segs; 44091398Stmm int nsegs; 441108832Stmm bus_size_t totsz; 44291398Stmm int error; 44391398Stmm{ 444108832Stmm struct gem_txdma *txd = (struct gem_txdma *)xsc; 445108832Stmm struct gem_softc *sc = txd->txd_sc; 446108832Stmm struct gem_txsoft *txs = txd->txd_txs; 447108832Stmm bus_size_t len = 0; 448108832Stmm uint64_t flags = 0; 449108832Stmm int seg, nexttx; 45091398Stmm 45191398Stmm if (error != 0) 45291398Stmm return; 453108832Stmm /* 454108832Stmm * Ensure we have enough descriptors free to describe 455108832Stmm * the packet. Note, we always reserve one descriptor 456108832Stmm * at the end of the ring as a termination point, to 457108832Stmm * prevent wrap-around. 458108832Stmm */ 459108832Stmm if (nsegs > sc->sc_txfree - 1) { 460108832Stmm txs->txs_ndescs = -1; 461108832Stmm return; 462108832Stmm } 463108832Stmm txs->txs_ndescs = nsegs; 46491398Stmm 465108832Stmm nexttx = txs->txs_firstdesc; 46691398Stmm /* 46791398Stmm * Initialize the transmit descriptors. 46891398Stmm */ 46991398Stmm for (seg = 0; seg < nsegs; 470108832Stmm seg++, nexttx = GEM_NEXTTX(nexttx)) { 471115030Stmm#ifdef GEM_DEBUG 47291398Stmm CTR5(KTR_GEM, "txdma_cb: mapping seg %d (txd %d), len " 473108832Stmm "%lx, addr %#lx (%#lx)", seg, nexttx, 47491398Stmm segs[seg].ds_len, segs[seg].ds_addr, 475108832Stmm GEM_DMA_WRITE(sc, segs[seg].ds_addr)); 476115030Stmm#endif 477108832Stmm 478108832Stmm if (segs[seg].ds_len == 0) 479108832Stmm continue; 480108832Stmm sc->sc_txdescs[nexttx].gd_addr = 481108832Stmm GEM_DMA_WRITE(sc, segs[seg].ds_addr); 482108832Stmm KASSERT(segs[seg].ds_len < GEM_TD_BUFSIZE, 483108832Stmm ("gem_txdma_callback: segment size too large!")); 48491398Stmm flags = segs[seg].ds_len & GEM_TD_BUFSIZE; 485108832Stmm if (len == 0) { 486115030Stmm#ifdef GEM_DEBUG 48791398Stmm CTR2(KTR_GEM, "txdma_cb: start of packet at seg %d, " 488108832Stmm "tx %d", seg, nexttx); 489115030Stmm#endif 49091398Stmm flags |= GEM_TD_START_OF_PACKET; 491108832Stmm if (++sc->sc_txwin > GEM_NTXSEGS * 2 / 3) { 492108832Stmm sc->sc_txwin = 0; 49399726Sbenno flags |= GEM_TD_INTERRUPT_ME; 49499726Sbenno } 49591398Stmm } 496108832Stmm if (len + segs[seg].ds_len == totsz) { 497115030Stmm#ifdef GEM_DEBUG 49891398Stmm CTR2(KTR_GEM, "txdma_cb: end of packet at seg %d, " 499108832Stmm "tx %d", seg, nexttx); 500115030Stmm#endif 50191398Stmm flags |= GEM_TD_END_OF_PACKET; 50291398Stmm } 503108832Stmm sc->sc_txdescs[nexttx].gd_flags = GEM_DMA_WRITE(sc, flags); 504108832Stmm txs->txs_lastdesc = nexttx; 505108832Stmm len += segs[seg].ds_len; 50691398Stmm } 507108832Stmm KASSERT((flags & GEM_TD_END_OF_PACKET) != 0, 508108832Stmm ("gem_txdma_callback: missed end of packet!")); 50991398Stmm} 51091398Stmm 51191398Stmmstatic void 51291398Stmmgem_tick(arg) 51391398Stmm void *arg; 51491398Stmm{ 51591398Stmm struct gem_softc *sc = arg; 51691398Stmm int s; 51791398Stmm 51891398Stmm s = splnet(); 51991398Stmm mii_tick(sc->sc_mii); 52091398Stmm splx(s); 52191398Stmm 52291398Stmm callout_reset(&sc->sc_tick_ch, hz, gem_tick, sc); 52391398Stmm} 52491398Stmm 52591398Stmmstatic int 52691398Stmmgem_bitwait(sc, r, clr, set) 52791398Stmm struct gem_softc *sc; 52891398Stmm bus_addr_t r; 52991398Stmm u_int32_t clr; 53091398Stmm u_int32_t set; 53191398Stmm{ 53291398Stmm int i; 53391398Stmm u_int32_t reg; 53491398Stmm 53591398Stmm for (i = TRIES; i--; DELAY(100)) { 53691398Stmm reg = bus_space_read_4(sc->sc_bustag, sc->sc_h, r); 53791398Stmm if ((r & clr) == 0 && (r & set) == set) 53891398Stmm return (1); 53991398Stmm } 54091398Stmm return (0); 54191398Stmm} 54291398Stmm 54391398Stmmvoid 54491398Stmmgem_reset(sc) 54591398Stmm struct gem_softc *sc; 54691398Stmm{ 54791398Stmm bus_space_tag_t t = sc->sc_bustag; 54891398Stmm bus_space_handle_t h = sc->sc_h; 54991398Stmm int s; 55091398Stmm 55191398Stmm s = splnet(); 552115030Stmm#ifdef GEM_DEBUG 55391398Stmm CTR1(KTR_GEM, "%s: gem_reset", device_get_name(sc->sc_dev)); 554115030Stmm#endif 55591398Stmm gem_reset_rx(sc); 55691398Stmm gem_reset_tx(sc); 55791398Stmm 55891398Stmm /* Do a full reset */ 55991398Stmm bus_space_write_4(t, h, GEM_RESET, GEM_RESET_RX | GEM_RESET_TX); 56091398Stmm if (!gem_bitwait(sc, GEM_RESET, GEM_RESET_RX | GEM_RESET_TX, 0)) 56191398Stmm device_printf(sc->sc_dev, "cannot reset device\n"); 56291398Stmm splx(s); 56391398Stmm} 56491398Stmm 56591398Stmm 56691398Stmm/* 56791398Stmm * gem_rxdrain: 56891398Stmm * 56991398Stmm * Drain the receive queue. 57091398Stmm */ 57191398Stmmstatic void 57291398Stmmgem_rxdrain(sc) 57391398Stmm struct gem_softc *sc; 57491398Stmm{ 57591398Stmm struct gem_rxsoft *rxs; 57691398Stmm int i; 57791398Stmm 57891398Stmm for (i = 0; i < GEM_NRXDESC; i++) { 57991398Stmm rxs = &sc->sc_rxsoft[i]; 58091398Stmm if (rxs->rxs_mbuf != NULL) { 581109648Stmm bus_dmamap_sync(sc->sc_rdmatag, rxs->rxs_dmamap, 582109648Stmm BUS_DMASYNC_POSTREAD); 583108832Stmm bus_dmamap_unload(sc->sc_rdmatag, rxs->rxs_dmamap); 58491398Stmm m_freem(rxs->rxs_mbuf); 58591398Stmm rxs->rxs_mbuf = NULL; 58691398Stmm } 58791398Stmm } 58891398Stmm} 58991398Stmm 59091398Stmm/* 59191398Stmm * Reset the whole thing. 59291398Stmm */ 59391398Stmmstatic void 59491398Stmmgem_stop(ifp, disable) 59591398Stmm struct ifnet *ifp; 59691398Stmm int disable; 59791398Stmm{ 59891398Stmm struct gem_softc *sc = (struct gem_softc *)ifp->if_softc; 59991398Stmm struct gem_txsoft *txs; 60091398Stmm 601115030Stmm#ifdef GEM_DEBUG 60291398Stmm CTR1(KTR_GEM, "%s: gem_stop", device_get_name(sc->sc_dev)); 603115030Stmm#endif 60491398Stmm 60591398Stmm callout_stop(&sc->sc_tick_ch); 60691398Stmm 60791398Stmm /* XXX - Should we reset these instead? */ 60891398Stmm gem_disable_tx(sc); 60991398Stmm gem_disable_rx(sc); 61091398Stmm 61191398Stmm /* 61291398Stmm * Release any queued transmit buffers. 61391398Stmm */ 61491398Stmm while ((txs = STAILQ_FIRST(&sc->sc_txdirtyq)) != NULL) { 61591398Stmm STAILQ_REMOVE_HEAD(&sc->sc_txdirtyq, txs_q); 61691398Stmm if (txs->txs_ndescs != 0) { 617109648Stmm bus_dmamap_sync(sc->sc_tdmatag, txs->txs_dmamap, 618109648Stmm BUS_DMASYNC_POSTWRITE); 619108832Stmm bus_dmamap_unload(sc->sc_tdmatag, txs->txs_dmamap); 62091398Stmm if (txs->txs_mbuf != NULL) { 62191398Stmm m_freem(txs->txs_mbuf); 62291398Stmm txs->txs_mbuf = NULL; 62391398Stmm } 62491398Stmm } 62591398Stmm STAILQ_INSERT_TAIL(&sc->sc_txfreeq, txs, txs_q); 62691398Stmm } 62791398Stmm 62891398Stmm if (disable) 62991398Stmm gem_rxdrain(sc); 63091398Stmm 63191398Stmm /* 63291398Stmm * Mark the interface down and cancel the watchdog timer. 63391398Stmm */ 63491398Stmm ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); 63591398Stmm ifp->if_timer = 0; 63691398Stmm} 63791398Stmm 63891398Stmm/* 63991398Stmm * Reset the receiver 64091398Stmm */ 64191398Stmmint 64291398Stmmgem_reset_rx(sc) 64391398Stmm struct gem_softc *sc; 64491398Stmm{ 64591398Stmm bus_space_tag_t t = sc->sc_bustag; 64691398Stmm bus_space_handle_t h = sc->sc_h; 64791398Stmm 64891398Stmm /* 64991398Stmm * Resetting while DMA is in progress can cause a bus hang, so we 65091398Stmm * disable DMA first. 65191398Stmm */ 65291398Stmm gem_disable_rx(sc); 65391398Stmm bus_space_write_4(t, h, GEM_RX_CONFIG, 0); 65491398Stmm /* Wait till it finishes */ 65591398Stmm if (!gem_bitwait(sc, GEM_RX_CONFIG, 1, 0)) 65691398Stmm device_printf(sc->sc_dev, "cannot disable read dma\n"); 65791398Stmm 65891398Stmm /* Wait 5ms extra. */ 65991398Stmm DELAY(5000); 66091398Stmm 66191398Stmm /* Finally, reset the ERX */ 66291398Stmm bus_space_write_4(t, h, GEM_RESET, GEM_RESET_RX); 66391398Stmm /* Wait till it finishes */ 66491398Stmm if (!gem_bitwait(sc, GEM_RESET, GEM_RESET_TX, 0)) { 66591398Stmm device_printf(sc->sc_dev, "cannot reset receiver\n"); 66691398Stmm return (1); 66791398Stmm } 66891398Stmm return (0); 66991398Stmm} 67091398Stmm 67191398Stmm 67291398Stmm/* 67391398Stmm * Reset the transmitter 67491398Stmm */ 67591398Stmmstatic int 67691398Stmmgem_reset_tx(sc) 67791398Stmm struct gem_softc *sc; 67891398Stmm{ 67991398Stmm bus_space_tag_t t = sc->sc_bustag; 68091398Stmm bus_space_handle_t h = sc->sc_h; 68191398Stmm int i; 68291398Stmm 68391398Stmm /* 68491398Stmm * Resetting while DMA is in progress can cause a bus hang, so we 68591398Stmm * disable DMA first. 68691398Stmm */ 68791398Stmm gem_disable_tx(sc); 68891398Stmm bus_space_write_4(t, h, GEM_TX_CONFIG, 0); 68991398Stmm /* Wait till it finishes */ 69091398Stmm if (!gem_bitwait(sc, GEM_TX_CONFIG, 1, 0)) 69191398Stmm device_printf(sc->sc_dev, "cannot disable read dma\n"); 69291398Stmm 69391398Stmm /* Wait 5ms extra. */ 69491398Stmm DELAY(5000); 69591398Stmm 69691398Stmm /* Finally, reset the ETX */ 69791398Stmm bus_space_write_4(t, h, GEM_RESET, GEM_RESET_TX); 69891398Stmm /* Wait till it finishes */ 69991398Stmm for (i = TRIES; i--; DELAY(100)) 70091398Stmm if ((bus_space_read_4(t, h, GEM_RESET) & GEM_RESET_TX) == 0) 70191398Stmm break; 70291398Stmm if (!gem_bitwait(sc, GEM_RESET, GEM_RESET_TX, 0)) { 70391398Stmm device_printf(sc->sc_dev, "cannot reset receiver\n"); 70491398Stmm return (1); 70591398Stmm } 70691398Stmm return (0); 70791398Stmm} 70891398Stmm 70991398Stmm/* 71091398Stmm * disable receiver. 71191398Stmm */ 71291398Stmmstatic int 71391398Stmmgem_disable_rx(sc) 71491398Stmm struct gem_softc *sc; 71591398Stmm{ 71691398Stmm bus_space_tag_t t = sc->sc_bustag; 71791398Stmm bus_space_handle_t h = sc->sc_h; 71891398Stmm u_int32_t cfg; 71991398Stmm 72091398Stmm /* Flip the enable bit */ 72191398Stmm cfg = bus_space_read_4(t, h, GEM_MAC_RX_CONFIG); 72291398Stmm cfg &= ~GEM_MAC_RX_ENABLE; 72391398Stmm bus_space_write_4(t, h, GEM_MAC_RX_CONFIG, cfg); 72491398Stmm 72591398Stmm /* Wait for it to finish */ 72691398Stmm return (gem_bitwait(sc, GEM_MAC_RX_CONFIG, GEM_MAC_RX_ENABLE, 0)); 72791398Stmm} 72891398Stmm 72991398Stmm/* 73091398Stmm * disable transmitter. 73191398Stmm */ 73291398Stmmstatic int 73391398Stmmgem_disable_tx(sc) 73491398Stmm struct gem_softc *sc; 73591398Stmm{ 73691398Stmm bus_space_tag_t t = sc->sc_bustag; 73791398Stmm bus_space_handle_t h = sc->sc_h; 73891398Stmm u_int32_t cfg; 73991398Stmm 74091398Stmm /* Flip the enable bit */ 74191398Stmm cfg = bus_space_read_4(t, h, GEM_MAC_TX_CONFIG); 74291398Stmm cfg &= ~GEM_MAC_TX_ENABLE; 74391398Stmm bus_space_write_4(t, h, GEM_MAC_TX_CONFIG, cfg); 74491398Stmm 74591398Stmm /* Wait for it to finish */ 74691398Stmm return (gem_bitwait(sc, GEM_MAC_TX_CONFIG, GEM_MAC_TX_ENABLE, 0)); 74791398Stmm} 74891398Stmm 74991398Stmm/* 75091398Stmm * Initialize interface. 75191398Stmm */ 75291398Stmmstatic int 75391398Stmmgem_meminit(sc) 75491398Stmm struct gem_softc *sc; 75591398Stmm{ 75691398Stmm struct gem_rxsoft *rxs; 75791398Stmm int i, error; 75891398Stmm 75991398Stmm /* 76091398Stmm * Initialize the transmit descriptor ring. 76191398Stmm */ 76291398Stmm memset((void *)sc->sc_txdescs, 0, sizeof(sc->sc_txdescs)); 76391398Stmm for (i = 0; i < GEM_NTXDESC; i++) { 76491398Stmm sc->sc_txdescs[i].gd_flags = 0; 76591398Stmm sc->sc_txdescs[i].gd_addr = 0; 76691398Stmm } 767108832Stmm sc->sc_txfree = GEM_MAXTXFREE; 76891398Stmm sc->sc_txnext = 0; 76999726Sbenno sc->sc_txwin = 0; 77091398Stmm 77191398Stmm /* 77291398Stmm * Initialize the receive descriptor and receive job 77391398Stmm * descriptor rings. 77491398Stmm */ 77591398Stmm for (i = 0; i < GEM_NRXDESC; i++) { 77691398Stmm rxs = &sc->sc_rxsoft[i]; 77791398Stmm if (rxs->rxs_mbuf == NULL) { 77891398Stmm if ((error = gem_add_rxbuf(sc, i)) != 0) { 77991398Stmm device_printf(sc->sc_dev, "unable to " 78091398Stmm "allocate or map rx buffer %d, error = " 78191398Stmm "%d\n", i, error); 78291398Stmm /* 78391398Stmm * XXX Should attempt to run with fewer receive 78491398Stmm * XXX buffers instead of just failing. 78591398Stmm */ 78691398Stmm gem_rxdrain(sc); 78791398Stmm return (1); 78891398Stmm } 78991398Stmm } else 79091398Stmm GEM_INIT_RXDESC(sc, i); 79191398Stmm } 79291398Stmm sc->sc_rxptr = 0; 793109648Stmm GEM_CDSYNC(sc, BUS_DMASYNC_PREWRITE); 794109648Stmm GEM_CDSYNC(sc, BUS_DMASYNC_PREREAD); 79591398Stmm 79691398Stmm return (0); 79791398Stmm} 79891398Stmm 79991398Stmmstatic int 80091398Stmmgem_ringsize(sz) 80191398Stmm int sz; 80291398Stmm{ 80391398Stmm int v = 0; 80491398Stmm 80591398Stmm switch (sz) { 80691398Stmm case 32: 80791398Stmm v = GEM_RING_SZ_32; 80891398Stmm break; 80991398Stmm case 64: 81091398Stmm v = GEM_RING_SZ_64; 81191398Stmm break; 81291398Stmm case 128: 81391398Stmm v = GEM_RING_SZ_128; 81491398Stmm break; 81591398Stmm case 256: 81691398Stmm v = GEM_RING_SZ_256; 81791398Stmm break; 81891398Stmm case 512: 81991398Stmm v = GEM_RING_SZ_512; 82091398Stmm break; 82191398Stmm case 1024: 82291398Stmm v = GEM_RING_SZ_1024; 82391398Stmm break; 82491398Stmm case 2048: 82591398Stmm v = GEM_RING_SZ_2048; 82691398Stmm break; 82791398Stmm case 4096: 82891398Stmm v = GEM_RING_SZ_4096; 82991398Stmm break; 83091398Stmm case 8192: 83191398Stmm v = GEM_RING_SZ_8192; 83291398Stmm break; 83391398Stmm default: 83491398Stmm printf("gem: invalid Receive Descriptor ring size\n"); 83591398Stmm break; 83691398Stmm } 83791398Stmm return (v); 83891398Stmm} 83991398Stmm 84091398Stmm/* 84191398Stmm * Initialization of interface; set up initialization block 84291398Stmm * and transmit/receive descriptor rings. 84391398Stmm */ 84491398Stmmstatic void 84591398Stmmgem_init(xsc) 84691398Stmm void *xsc; 84791398Stmm{ 84891398Stmm struct gem_softc *sc = (struct gem_softc *)xsc; 84991398Stmm struct ifnet *ifp = &sc->sc_arpcom.ac_if; 85091398Stmm bus_space_tag_t t = sc->sc_bustag; 85191398Stmm bus_space_handle_t h = sc->sc_h; 85291398Stmm int s; 85391398Stmm u_int32_t v; 85491398Stmm 85591398Stmm s = splnet(); 85691398Stmm 857115030Stmm#ifdef GEM_DEBUG 85891398Stmm CTR1(KTR_GEM, "%s: gem_init: calling stop", device_get_name(sc->sc_dev)); 859115030Stmm#endif 86091398Stmm /* 86191398Stmm * Initialization sequence. The numbered steps below correspond 86291398Stmm * to the sequence outlined in section 6.3.5.1 in the Ethernet 86391398Stmm * Channel Engine manual (part of the PCIO manual). 86491398Stmm * See also the STP2002-STQ document from Sun Microsystems. 86591398Stmm */ 86691398Stmm 86791398Stmm /* step 1 & 2. Reset the Ethernet Channel */ 86891398Stmm gem_stop(&sc->sc_arpcom.ac_if, 0); 86991398Stmm gem_reset(sc); 870115030Stmm#ifdef GEM_DEBUG 87191398Stmm CTR1(KTR_GEM, "%s: gem_init: restarting", device_get_name(sc->sc_dev)); 872115030Stmm#endif 87391398Stmm 87491398Stmm /* Re-initialize the MIF */ 87591398Stmm gem_mifinit(sc); 87691398Stmm 87791398Stmm /* step 3. Setup data structures in host memory */ 87891398Stmm gem_meminit(sc); 87991398Stmm 88091398Stmm /* step 4. TX MAC registers & counters */ 88191398Stmm gem_init_regs(sc); 88291398Stmm /* XXX: VLAN code from NetBSD temporarily removed. */ 88391398Stmm bus_space_write_4(t, h, GEM_MAC_MAC_MAX_FRAME, 88491398Stmm (ETHER_MAX_LEN + sizeof(struct ether_header)) | (0x2000<<16)); 88591398Stmm 88691398Stmm /* step 5. RX MAC registers & counters */ 88791398Stmm gem_setladrf(sc); 88891398Stmm 88991398Stmm /* step 6 & 7. Program Descriptor Ring Base Addresses */ 89091398Stmm /* NOTE: we use only 32-bit DMA addresses here. */ 89191398Stmm bus_space_write_4(t, h, GEM_TX_RING_PTR_HI, 0); 89291398Stmm bus_space_write_4(t, h, GEM_TX_RING_PTR_LO, GEM_CDTXADDR(sc, 0)); 89391398Stmm 89491398Stmm bus_space_write_4(t, h, GEM_RX_RING_PTR_HI, 0); 89591398Stmm bus_space_write_4(t, h, GEM_RX_RING_PTR_LO, GEM_CDRXADDR(sc, 0)); 896115030Stmm#ifdef GEM_DEBUG 89791398Stmm CTR3(KTR_GEM, "loading rx ring %lx, tx ring %lx, cddma %lx", 89891398Stmm GEM_CDRXADDR(sc, 0), GEM_CDTXADDR(sc, 0), sc->sc_cddma); 899115030Stmm#endif 90091398Stmm 90191398Stmm /* step 8. Global Configuration & Interrupt Mask */ 90291398Stmm bus_space_write_4(t, h, GEM_INTMASK, 90391398Stmm ~(GEM_INTR_TX_INTME| 90491398Stmm GEM_INTR_TX_EMPTY| 90591398Stmm GEM_INTR_RX_DONE|GEM_INTR_RX_NOBUF| 90691398Stmm GEM_INTR_RX_TAG_ERR|GEM_INTR_PCS| 90791398Stmm GEM_INTR_MAC_CONTROL|GEM_INTR_MIF| 90891398Stmm GEM_INTR_BERR)); 90999726Sbenno bus_space_write_4(t, h, GEM_MAC_RX_MASK, 91099726Sbenno GEM_MAC_RX_DONE|GEM_MAC_RX_FRAME_CNT); 91191398Stmm bus_space_write_4(t, h, GEM_MAC_TX_MASK, 0xffff); /* XXXX */ 91291398Stmm bus_space_write_4(t, h, GEM_MAC_CONTROL_MASK, 0); /* XXXX */ 91391398Stmm 91491398Stmm /* step 9. ETX Configuration: use mostly default values */ 91591398Stmm 91691398Stmm /* Enable DMA */ 91791398Stmm v = gem_ringsize(GEM_NTXDESC /*XXX*/); 91891398Stmm bus_space_write_4(t, h, GEM_TX_CONFIG, 91991398Stmm v|GEM_TX_CONFIG_TXDMA_EN| 92091398Stmm ((0x400<<10)&GEM_TX_CONFIG_TXFIFO_TH)); 92191398Stmm 92291398Stmm /* step 10. ERX Configuration */ 92391398Stmm 92491398Stmm /* Encode Receive Descriptor ring size: four possible values */ 92591398Stmm v = gem_ringsize(GEM_NRXDESC /*XXX*/); 92691398Stmm 92791398Stmm /* Enable DMA */ 92891398Stmm bus_space_write_4(t, h, GEM_RX_CONFIG, 92991398Stmm v|(GEM_THRSH_1024<<GEM_RX_CONFIG_FIFO_THRS_SHIFT)| 93091398Stmm (2<<GEM_RX_CONFIG_FBOFF_SHFT)|GEM_RX_CONFIG_RXDMA_EN| 93191398Stmm (0<<GEM_RX_CONFIG_CXM_START_SHFT)); 93291398Stmm /* 93399726Sbenno * The following value is for an OFF Threshold of about 3/4 full 93499726Sbenno * and an ON Threshold of 1/4 full. 93591398Stmm */ 93699726Sbenno bus_space_write_4(t, h, GEM_RX_PAUSE_THRESH, 93799726Sbenno (3 * sc->sc_rxfifosize / 256) | 93899726Sbenno ( (sc->sc_rxfifosize / 256) << 12)); 93999726Sbenno bus_space_write_4(t, h, GEM_RX_BLANKING, (6<<12)|6); 94091398Stmm 94191398Stmm /* step 11. Configure Media */ 94299726Sbenno mii_mediachg(sc->sc_mii); 94391398Stmm 94491398Stmm /* step 12. RX_MAC Configuration Register */ 94591398Stmm v = bus_space_read_4(t, h, GEM_MAC_RX_CONFIG); 94691398Stmm v |= GEM_MAC_RX_ENABLE; 94791398Stmm bus_space_write_4(t, h, GEM_MAC_RX_CONFIG, v); 94891398Stmm 94991398Stmm /* step 14. Issue Transmit Pending command */ 95091398Stmm 95191398Stmm /* step 15. Give the reciever a swift kick */ 95291398Stmm bus_space_write_4(t, h, GEM_RX_KICK, GEM_NRXDESC-4); 95391398Stmm 95491398Stmm /* Start the one second timer. */ 95591398Stmm callout_reset(&sc->sc_tick_ch, hz, gem_tick, sc); 95691398Stmm 95791398Stmm ifp->if_flags |= IFF_RUNNING; 95891398Stmm ifp->if_flags &= ~IFF_OACTIVE; 95991398Stmm ifp->if_timer = 0; 96099726Sbenno sc->sc_ifflags = ifp->if_flags; 96191398Stmm splx(s); 96291398Stmm} 96391398Stmm 96491398Stmmstatic int 965108832Stmmgem_load_txmbuf(sc, m0) 96691398Stmm struct gem_softc *sc; 96791398Stmm struct mbuf *m0; 96891398Stmm{ 96991398Stmm struct gem_txdma txd; 97091398Stmm struct gem_txsoft *txs; 971108832Stmm int error; 97291398Stmm 973108832Stmm /* Get a work queue entry. */ 974108832Stmm if ((txs = STAILQ_FIRST(&sc->sc_txfreeq)) == NULL) { 975108832Stmm /* Ran out of descriptors. */ 976108832Stmm return (-1); 977108832Stmm } 97891398Stmm txd.txd_sc = sc; 979108832Stmm txd.txd_txs = txs; 980108832Stmm txs->txs_mbuf = m0; 981108832Stmm txs->txs_firstdesc = sc->sc_txnext; 982108832Stmm error = bus_dmamap_load_mbuf(sc->sc_tdmatag, txs->txs_dmamap, m0, 983108832Stmm gem_txdma_callback, &txd, BUS_DMA_NOWAIT); 984108832Stmm if (error != 0) 985108832Stmm goto fail; 986108832Stmm if (txs->txs_ndescs == -1) { 987108832Stmm error = -1; 988108832Stmm goto fail; 98991398Stmm } 99091398Stmm 991108832Stmm /* Sync the DMA map. */ 992108832Stmm bus_dmamap_sync(sc->sc_tdmatag, txs->txs_dmamap, 993108832Stmm BUS_DMASYNC_PREWRITE); 99491398Stmm 995115030Stmm#ifdef GEM_DEBUG 996108832Stmm CTR3(KTR_GEM, "load_mbuf: setting firstdesc=%d, lastdesc=%d, " 997108832Stmm "ndescs=%d", txs->txs_firstdesc, txs->txs_lastdesc, 998108832Stmm txs->txs_ndescs); 999115030Stmm#endif 1000108832Stmm STAILQ_REMOVE_HEAD(&sc->sc_txfreeq, txs_q); 1001108832Stmm STAILQ_INSERT_TAIL(&sc->sc_txdirtyq, txs, txs_q); 100291398Stmm 1003108832Stmm sc->sc_txnext = GEM_NEXTTX(txs->txs_lastdesc); 1004108832Stmm sc->sc_txfree -= txs->txs_ndescs; 1005108832Stmm return (0); 100691398Stmm 1007108832Stmmfail: 1008115030Stmm#ifdef GEM_DEBUG 1009108832Stmm CTR1(KTR_GEM, "gem_load_txmbuf failed (%d)", error); 1010115030Stmm#endif 1011108832Stmm bus_dmamap_unload(sc->sc_tdmatag, txs->txs_dmamap); 1012108832Stmm return (error); 101391398Stmm} 101491398Stmm 101591398Stmmstatic void 101691398Stmmgem_init_regs(sc) 101791398Stmm struct gem_softc *sc; 101891398Stmm{ 101991398Stmm bus_space_tag_t t = sc->sc_bustag; 102091398Stmm bus_space_handle_t h = sc->sc_h; 102199726Sbenno const u_char *laddr = sc->sc_arpcom.ac_enaddr; 102299726Sbenno u_int32_t v; 102391398Stmm 102491398Stmm /* These regs are not cleared on reset */ 102591398Stmm if (!sc->sc_inited) { 102691398Stmm 102791398Stmm /* Wooo. Magic values. */ 102891398Stmm bus_space_write_4(t, h, GEM_MAC_IPG0, 0); 102991398Stmm bus_space_write_4(t, h, GEM_MAC_IPG1, 8); 103091398Stmm bus_space_write_4(t, h, GEM_MAC_IPG2, 4); 103191398Stmm 103291398Stmm bus_space_write_4(t, h, GEM_MAC_MAC_MIN_FRAME, ETHER_MIN_LEN); 103391398Stmm /* Max frame and max burst size */ 103491398Stmm bus_space_write_4(t, h, GEM_MAC_MAC_MAX_FRAME, 103599726Sbenno ETHER_MAX_LEN | (0x2000<<16)); 103699726Sbenno 103791398Stmm bus_space_write_4(t, h, GEM_MAC_PREAMBLE_LEN, 0x7); 103891398Stmm bus_space_write_4(t, h, GEM_MAC_JAM_SIZE, 0x4); 103991398Stmm bus_space_write_4(t, h, GEM_MAC_ATTEMPT_LIMIT, 0x10); 104091398Stmm /* Dunno.... */ 104191398Stmm bus_space_write_4(t, h, GEM_MAC_CONTROL_TYPE, 0x8088); 104291398Stmm bus_space_write_4(t, h, GEM_MAC_RANDOM_SEED, 104399726Sbenno ((laddr[5]<<8)|laddr[4])&0x3ff); 104499726Sbenno 104591398Stmm /* Secondary MAC addr set to 0:0:0:0:0:0 */ 104691398Stmm bus_space_write_4(t, h, GEM_MAC_ADDR3, 0); 104791398Stmm bus_space_write_4(t, h, GEM_MAC_ADDR4, 0); 104891398Stmm bus_space_write_4(t, h, GEM_MAC_ADDR5, 0); 104999726Sbenno 105099726Sbenno /* MAC control addr set to 01:80:c2:00:00:01 */ 105191398Stmm bus_space_write_4(t, h, GEM_MAC_ADDR6, 0x0001); 105291398Stmm bus_space_write_4(t, h, GEM_MAC_ADDR7, 0xc200); 105391398Stmm bus_space_write_4(t, h, GEM_MAC_ADDR8, 0x0180); 105491398Stmm 105591398Stmm /* MAC filter addr set to 0:0:0:0:0:0 */ 105691398Stmm bus_space_write_4(t, h, GEM_MAC_ADDR_FILTER0, 0); 105791398Stmm bus_space_write_4(t, h, GEM_MAC_ADDR_FILTER1, 0); 105891398Stmm bus_space_write_4(t, h, GEM_MAC_ADDR_FILTER2, 0); 105991398Stmm 106091398Stmm bus_space_write_4(t, h, GEM_MAC_ADR_FLT_MASK1_2, 0); 106191398Stmm bus_space_write_4(t, h, GEM_MAC_ADR_FLT_MASK0, 0); 106291398Stmm 106391398Stmm sc->sc_inited = 1; 106491398Stmm } 106591398Stmm 106691398Stmm /* Counters need to be zeroed */ 106791398Stmm bus_space_write_4(t, h, GEM_MAC_NORM_COLL_CNT, 0); 106891398Stmm bus_space_write_4(t, h, GEM_MAC_FIRST_COLL_CNT, 0); 106991398Stmm bus_space_write_4(t, h, GEM_MAC_EXCESS_COLL_CNT, 0); 107091398Stmm bus_space_write_4(t, h, GEM_MAC_LATE_COLL_CNT, 0); 107191398Stmm bus_space_write_4(t, h, GEM_MAC_DEFER_TMR_CNT, 0); 107291398Stmm bus_space_write_4(t, h, GEM_MAC_PEAK_ATTEMPTS, 0); 107391398Stmm bus_space_write_4(t, h, GEM_MAC_RX_FRAME_COUNT, 0); 107491398Stmm bus_space_write_4(t, h, GEM_MAC_RX_LEN_ERR_CNT, 0); 107591398Stmm bus_space_write_4(t, h, GEM_MAC_RX_ALIGN_ERR, 0); 107691398Stmm bus_space_write_4(t, h, GEM_MAC_RX_CRC_ERR_CNT, 0); 107791398Stmm bus_space_write_4(t, h, GEM_MAC_RX_CODE_VIOL, 0); 107891398Stmm 107991398Stmm /* Un-pause stuff */ 108091398Stmm#if 0 108191398Stmm bus_space_write_4(t, h, GEM_MAC_SEND_PAUSE_CMD, 0x1BF0); 108291398Stmm#else 108391398Stmm bus_space_write_4(t, h, GEM_MAC_SEND_PAUSE_CMD, 0); 108491398Stmm#endif 108591398Stmm 108691398Stmm /* 108791398Stmm * Set the station address. 108891398Stmm */ 108999726Sbenno bus_space_write_4(t, h, GEM_MAC_ADDR0, (laddr[4]<<8)|laddr[5]); 109099726Sbenno bus_space_write_4(t, h, GEM_MAC_ADDR1, (laddr[2]<<8)|laddr[3]); 109199726Sbenno bus_space_write_4(t, h, GEM_MAC_ADDR2, (laddr[0]<<8)|laddr[1]); 109299726Sbenno 109399726Sbenno /* 109499726Sbenno * Enable MII outputs. Enable GMII if there is a gigabit PHY. 109599726Sbenno */ 109699726Sbenno sc->sc_mif_config = bus_space_read_4(t, h, GEM_MIF_CONFIG); 109799726Sbenno v = GEM_MAC_XIF_TX_MII_ENA; 109899726Sbenno if (sc->sc_mif_config & GEM_MIF_CONFIG_MDI1) { 109999726Sbenno v |= GEM_MAC_XIF_FDPLX_LED; 110099726Sbenno if (sc->sc_flags & GEM_GIGABIT) 110199726Sbenno v |= GEM_MAC_XIF_GMII_MODE; 110299726Sbenno } 110399726Sbenno bus_space_write_4(t, h, GEM_MAC_XIF_CONFIG, v); 110491398Stmm} 110591398Stmm 110691398Stmmstatic void 110791398Stmmgem_start(ifp) 110891398Stmm struct ifnet *ifp; 110991398Stmm{ 111091398Stmm struct gem_softc *sc = (struct gem_softc *)ifp->if_softc; 1111108832Stmm struct mbuf *m0 = NULL; 1112115030Stmm int firsttx, ntx = 0, ofree, txmfail; 111391398Stmm 111491398Stmm if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING) 111591398Stmm return; 111691398Stmm 111791398Stmm /* 111891398Stmm * Remember the previous number of free descriptors and 111991398Stmm * the first descriptor we'll use. 112091398Stmm */ 112191398Stmm ofree = sc->sc_txfree; 112291398Stmm firsttx = sc->sc_txnext; 112391398Stmm 1124115030Stmm#ifdef GEM_DEBUG 112591398Stmm CTR3(KTR_GEM, "%s: gem_start: txfree %d, txnext %d", 112691398Stmm device_get_name(sc->sc_dev), ofree, firsttx); 1127115030Stmm#endif 112891398Stmm 112991398Stmm /* 113091398Stmm * Loop through the send queue, setting up transmit descriptors 113191398Stmm * until we drain the queue, or use up all available transmit 113291398Stmm * descriptors. 113391398Stmm */ 113491398Stmm txmfail = 0; 1135115030Stmm do { 113691398Stmm /* 113791398Stmm * Grab a packet off the queue. 113891398Stmm */ 113991398Stmm IF_DEQUEUE(&ifp->if_snd, m0); 114091398Stmm if (m0 == NULL) 114191398Stmm break; 114291398Stmm 1143108832Stmm txmfail = gem_load_txmbuf(sc, m0); 114491398Stmm if (txmfail > 0) { 1145108832Stmm /* Drop the mbuf and complain. */ 1146108832Stmm printf("gem_start: error %d while loading mbuf dma " 1147108832Stmm "map\n", txmfail); 1148108832Stmm continue; 114991398Stmm } 1150108832Stmm /* Not enough descriptors. */ 1151108832Stmm if (txmfail == -1) { 1152108832Stmm if (sc->sc_txfree == GEM_MAXTXFREE) 1153108832Stmm panic("gem_start: mbuf chain too long!"); 115491398Stmm IF_PREPEND(&ifp->if_snd, m0); 115591398Stmm break; 115691398Stmm } 115791398Stmm 1158115030Stmm ntx++; 1159108832Stmm /* Kick the transmitter. */ 1160115030Stmm#ifdef GEM_DEBUG 1161108832Stmm CTR2(KTR_GEM, "%s: gem_start: kicking tx %d", 1162108832Stmm device_get_name(sc->sc_dev), sc->sc_txnext); 1163115030Stmm#endif 1164108832Stmm bus_space_write_4(sc->sc_bustag, sc->sc_h, GEM_TX_KICK, 1165108832Stmm sc->sc_txnext); 1166108832Stmm 1167105982Stmm if (ifp->if_bpf != NULL) 1168106950Smux bpf_mtap(ifp->if_bpf, m0); 1169115030Stmm } while (1); 117091398Stmm 117191398Stmm if (txmfail == -1 || sc->sc_txfree == 0) { 1172108832Stmm /* No more slots left; notify upper layer. */ 117391398Stmm ifp->if_flags |= IFF_OACTIVE; 117491398Stmm } 117591398Stmm 117691398Stmm if (ntx > 0) { 1177109648Stmm GEM_CDSYNC(sc, BUS_DMASYNC_PREWRITE); 1178109648Stmm 1179115030Stmm#ifdef GEM_DEBUG 1180108832Stmm CTR2(KTR_GEM, "%s: packets enqueued, OWN on %d", 1181108832Stmm device_get_name(sc->sc_dev), firsttx); 1182115030Stmm#endif 118391398Stmm 118491398Stmm /* Set a watchdog timer in case the chip flakes out. */ 118591398Stmm ifp->if_timer = 5; 1186115030Stmm#ifdef GEM_DEBUG 118791398Stmm CTR2(KTR_GEM, "%s: gem_start: watchdog %d", 118891398Stmm device_get_name(sc->sc_dev), ifp->if_timer); 1189115030Stmm#endif 119091398Stmm } 119191398Stmm} 119291398Stmm 119391398Stmm/* 119491398Stmm * Transmit interrupt. 119591398Stmm */ 119691398Stmmstatic void 119791398Stmmgem_tint(sc) 119891398Stmm struct gem_softc *sc; 119991398Stmm{ 120091398Stmm struct ifnet *ifp = &sc->sc_arpcom.ac_if; 120191398Stmm bus_space_tag_t t = sc->sc_bustag; 120291398Stmm bus_space_handle_t mac = sc->sc_h; 120391398Stmm struct gem_txsoft *txs; 120491398Stmm int txlast; 120599726Sbenno int progress = 0; 120691398Stmm 120791398Stmm 1208115030Stmm#ifdef GEM_DEBUG 120991398Stmm CTR1(KTR_GEM, "%s: gem_tint", device_get_name(sc->sc_dev)); 1210115030Stmm#endif 121191398Stmm 121291398Stmm /* 121391398Stmm * Unload collision counters 121491398Stmm */ 121591398Stmm ifp->if_collisions += 121691398Stmm bus_space_read_4(t, mac, GEM_MAC_NORM_COLL_CNT) + 121791398Stmm bus_space_read_4(t, mac, GEM_MAC_FIRST_COLL_CNT) + 121891398Stmm bus_space_read_4(t, mac, GEM_MAC_EXCESS_COLL_CNT) + 121991398Stmm bus_space_read_4(t, mac, GEM_MAC_LATE_COLL_CNT); 122091398Stmm 122191398Stmm /* 122291398Stmm * then clear the hardware counters. 122391398Stmm */ 122491398Stmm bus_space_write_4(t, mac, GEM_MAC_NORM_COLL_CNT, 0); 122591398Stmm bus_space_write_4(t, mac, GEM_MAC_FIRST_COLL_CNT, 0); 122691398Stmm bus_space_write_4(t, mac, GEM_MAC_EXCESS_COLL_CNT, 0); 122791398Stmm bus_space_write_4(t, mac, GEM_MAC_LATE_COLL_CNT, 0); 122891398Stmm 122991398Stmm /* 123091398Stmm * Go through our Tx list and free mbufs for those 123191398Stmm * frames that have been transmitted. 123291398Stmm */ 1233109648Stmm GEM_CDSYNC(sc, BUS_DMASYNC_POSTREAD); 123491398Stmm while ((txs = STAILQ_FIRST(&sc->sc_txdirtyq)) != NULL) { 123591398Stmm 123691398Stmm#ifdef GEM_DEBUG 123791398Stmm if (ifp->if_flags & IFF_DEBUG) { 123891398Stmm int i; 123991398Stmm printf(" txsoft %p transmit chain:\n", txs); 124091398Stmm for (i = txs->txs_firstdesc;; i = GEM_NEXTTX(i)) { 124191398Stmm printf("descriptor %d: ", i); 124291398Stmm printf("gd_flags: 0x%016llx\t", (long long) 124391398Stmm GEM_DMA_READ(sc, sc->sc_txdescs[i].gd_flags)); 124491398Stmm printf("gd_addr: 0x%016llx\n", (long long) 124591398Stmm GEM_DMA_READ(sc, sc->sc_txdescs[i].gd_addr)); 124691398Stmm if (i == txs->txs_lastdesc) 124791398Stmm break; 124891398Stmm } 124991398Stmm } 125091398Stmm#endif 125191398Stmm 125291398Stmm /* 125391398Stmm * In theory, we could harveast some descriptors before 125491398Stmm * the ring is empty, but that's a bit complicated. 125591398Stmm * 125691398Stmm * GEM_TX_COMPLETION points to the last descriptor 125791398Stmm * processed +1. 125891398Stmm */ 125991398Stmm txlast = bus_space_read_4(t, mac, GEM_TX_COMPLETION); 1260115030Stmm#ifdef GEM_DEBUG 126191398Stmm CTR3(KTR_GEM, "gem_tint: txs->txs_firstdesc = %d, " 126291398Stmm "txs->txs_lastdesc = %d, txlast = %d", 126391398Stmm txs->txs_firstdesc, txs->txs_lastdesc, txlast); 1264115030Stmm#endif 126591398Stmm if (txs->txs_firstdesc <= txs->txs_lastdesc) { 126691398Stmm if ((txlast >= txs->txs_firstdesc) && 126791398Stmm (txlast <= txs->txs_lastdesc)) 126891398Stmm break; 126991398Stmm } else { 127091398Stmm /* Ick -- this command wraps */ 127191398Stmm if ((txlast >= txs->txs_firstdesc) || 127291398Stmm (txlast <= txs->txs_lastdesc)) 127391398Stmm break; 127491398Stmm } 127591398Stmm 1276115030Stmm#ifdef GEM_DEBUG 127791398Stmm CTR0(KTR_GEM, "gem_tint: releasing a desc"); 1278115030Stmm#endif 127991398Stmm STAILQ_REMOVE_HEAD(&sc->sc_txdirtyq, txs_q); 128091398Stmm 128191398Stmm sc->sc_txfree += txs->txs_ndescs; 128291398Stmm 1283108832Stmm bus_dmamap_sync(sc->sc_tdmatag, txs->txs_dmamap, 128491398Stmm BUS_DMASYNC_POSTWRITE); 1285108832Stmm bus_dmamap_unload(sc->sc_tdmatag, txs->txs_dmamap); 128691398Stmm if (txs->txs_mbuf != NULL) { 128791398Stmm m_freem(txs->txs_mbuf); 128891398Stmm txs->txs_mbuf = NULL; 128991398Stmm } 129091398Stmm 129191398Stmm STAILQ_INSERT_TAIL(&sc->sc_txfreeq, txs, txs_q); 129291398Stmm 129391398Stmm ifp->if_opackets++; 129499726Sbenno progress = 1; 129591398Stmm } 129691398Stmm 1297115030Stmm#ifdef GEM_DEBUG 129891398Stmm CTR3(KTR_GEM, "gem_tint: GEM_TX_STATE_MACHINE %x " 129991398Stmm "GEM_TX_DATA_PTR %llx " 130091398Stmm "GEM_TX_COMPLETION %x", 130191398Stmm bus_space_read_4(sc->sc_bustag, sc->sc_h, GEM_TX_STATE_MACHINE), 130291398Stmm ((long long) bus_space_read_4(sc->sc_bustag, sc->sc_h, 130391398Stmm GEM_TX_DATA_PTR_HI) << 32) | 130491398Stmm bus_space_read_4(sc->sc_bustag, sc->sc_h, 130591398Stmm GEM_TX_DATA_PTR_LO), 130691398Stmm bus_space_read_4(sc->sc_bustag, sc->sc_h, GEM_TX_COMPLETION)); 1307115030Stmm#endif 130891398Stmm 130999726Sbenno if (progress) { 131099726Sbenno if (sc->sc_txfree == GEM_NTXDESC - 1) 131199726Sbenno sc->sc_txwin = 0; 131291398Stmm 131399726Sbenno /* Freed some descriptors, so reset IFF_OACTIVE and restart. */ 131499726Sbenno ifp->if_flags &= ~IFF_OACTIVE; 131599726Sbenno gem_start(ifp); 131691398Stmm 131799726Sbenno if (STAILQ_EMPTY(&sc->sc_txdirtyq)) 131899726Sbenno ifp->if_timer = 0; 131999726Sbenno } 132099726Sbenno 1321115030Stmm#ifdef GEM_DEBUG 132291398Stmm CTR2(KTR_GEM, "%s: gem_tint: watchdog %d", 132391398Stmm device_get_name(sc->sc_dev), ifp->if_timer); 1324115030Stmm#endif 132591398Stmm} 132691398Stmm 1327100587Sjake#if 0 132893045Stmmstatic void 132993045Stmmgem_rint_timeout(arg) 133093045Stmm void *arg; 133193045Stmm{ 133293045Stmm 133393045Stmm gem_rint((struct gem_softc *)arg); 133493045Stmm} 1335100587Sjake#endif 133693045Stmm 133791398Stmm/* 133891398Stmm * Receive interrupt. 133991398Stmm */ 134091398Stmmstatic void 134191398Stmmgem_rint(sc) 134291398Stmm struct gem_softc *sc; 134391398Stmm{ 134491398Stmm struct ifnet *ifp = &sc->sc_arpcom.ac_if; 134591398Stmm bus_space_tag_t t = sc->sc_bustag; 134691398Stmm bus_space_handle_t h = sc->sc_h; 134791398Stmm struct gem_rxsoft *rxs; 134891398Stmm struct mbuf *m; 134991398Stmm u_int64_t rxstat; 135099726Sbenno u_int32_t rxcomp; 135199726Sbenno int i, len, progress = 0; 135291398Stmm 135393045Stmm callout_stop(&sc->sc_rx_ch); 1354115030Stmm#ifdef GEM_DEBUG 135591398Stmm CTR1(KTR_GEM, "%s: gem_rint", device_get_name(sc->sc_dev)); 1356115030Stmm#endif 135799726Sbenno 135891398Stmm /* 135999726Sbenno * Read the completion register once. This limits 136099726Sbenno * how long the following loop can execute. 136199726Sbenno */ 136299726Sbenno rxcomp = bus_space_read_4(t, h, GEM_RX_COMPLETION); 136399726Sbenno 1364115030Stmm#ifdef GEM_DEBUG 136591398Stmm CTR2(KTR_GEM, "gem_rint: sc->rxptr %d, complete %d", 136699726Sbenno sc->sc_rxptr, rxcomp); 1367115030Stmm#endif 1368109648Stmm GEM_CDSYNC(sc, BUS_DMASYNC_POSTREAD); 136999726Sbenno for (i = sc->sc_rxptr; i != rxcomp; 137091398Stmm i = GEM_NEXTRX(i)) { 137191398Stmm rxs = &sc->sc_rxsoft[i]; 137291398Stmm 137391398Stmm rxstat = GEM_DMA_READ(sc, sc->sc_rxdescs[i].gd_flags); 137491398Stmm 137591398Stmm if (rxstat & GEM_RD_OWN) { 137699726Sbenno#if 0 /* XXX: In case of emergency, re-enable this. */ 137791398Stmm /* 137893045Stmm * The descriptor is still marked as owned, although 137993045Stmm * it is supposed to have completed. This has been 138093045Stmm * observed on some machines. Just exiting here 138193045Stmm * might leave the packet sitting around until another 138293045Stmm * one arrives to trigger a new interrupt, which is 138393045Stmm * generally undesirable, so set up a timeout. 138491398Stmm */ 138593045Stmm callout_reset(&sc->sc_rx_ch, GEM_RXOWN_TICKS, 138693045Stmm gem_rint_timeout, sc); 138799726Sbenno#endif 138891398Stmm break; 138991398Stmm } 139091398Stmm 139199726Sbenno progress++; 139299726Sbenno ifp->if_ipackets++; 139399726Sbenno 139491398Stmm if (rxstat & GEM_RD_BAD_CRC) { 139599726Sbenno ifp->if_ierrors++; 139691398Stmm device_printf(sc->sc_dev, "receive error: CRC error\n"); 139791398Stmm GEM_INIT_RXDESC(sc, i); 139891398Stmm continue; 139991398Stmm } 140091398Stmm 140191398Stmm#ifdef GEM_DEBUG 140291398Stmm if (ifp->if_flags & IFF_DEBUG) { 140391398Stmm printf(" rxsoft %p descriptor %d: ", rxs, i); 140491398Stmm printf("gd_flags: 0x%016llx\t", (long long) 140591398Stmm GEM_DMA_READ(sc, sc->sc_rxdescs[i].gd_flags)); 140691398Stmm printf("gd_addr: 0x%016llx\n", (long long) 140791398Stmm GEM_DMA_READ(sc, sc->sc_rxdescs[i].gd_addr)); 140891398Stmm } 140991398Stmm#endif 141091398Stmm 141191398Stmm /* 141291398Stmm * No errors; receive the packet. Note the Gem 141391398Stmm * includes the CRC with every packet. 141491398Stmm */ 141591398Stmm len = GEM_RD_BUFLEN(rxstat); 141691398Stmm 141791398Stmm /* 141891398Stmm * Allocate a new mbuf cluster. If that fails, we are 141991398Stmm * out of memory, and must drop the packet and recycle 142091398Stmm * the buffer that's already attached to this descriptor. 142191398Stmm */ 142291398Stmm m = rxs->rxs_mbuf; 142391398Stmm if (gem_add_rxbuf(sc, i) != 0) { 142491398Stmm ifp->if_ierrors++; 142591398Stmm GEM_INIT_RXDESC(sc, i); 142691398Stmm continue; 142791398Stmm } 142891398Stmm m->m_data += 2; /* We're already off by two */ 142991398Stmm 143091398Stmm m->m_pkthdr.rcvif = ifp; 143191398Stmm m->m_pkthdr.len = m->m_len = len - ETHER_CRC_LEN; 143291398Stmm 143391398Stmm /* Pass it on. */ 1434106937Ssam (*ifp->if_input)(ifp, m); 143591398Stmm } 143691398Stmm 143799726Sbenno if (progress) { 1438109648Stmm GEM_CDSYNC(sc, BUS_DMASYNC_PREWRITE); 143999726Sbenno /* Update the receive pointer. */ 144099726Sbenno if (i == sc->sc_rxptr) { 144199726Sbenno device_printf(sc->sc_dev, "rint: ring wrap\n"); 144299726Sbenno } 144399726Sbenno sc->sc_rxptr = i; 144499726Sbenno bus_space_write_4(t, h, GEM_RX_KICK, GEM_PREVRX(i)); 144599726Sbenno } 144691398Stmm 1447115030Stmm#ifdef GEM_DEBUG 144891398Stmm CTR2(KTR_GEM, "gem_rint: done sc->rxptr %d, complete %d", 144991398Stmm sc->sc_rxptr, bus_space_read_4(t, h, GEM_RX_COMPLETION)); 1450115030Stmm#endif 145191398Stmm} 145291398Stmm 145391398Stmm 145491398Stmm/* 145591398Stmm * gem_add_rxbuf: 145691398Stmm * 145791398Stmm * Add a receive buffer to the indicated descriptor. 145891398Stmm */ 145991398Stmmstatic int 146091398Stmmgem_add_rxbuf(sc, idx) 146191398Stmm struct gem_softc *sc; 146291398Stmm int idx; 146391398Stmm{ 146491398Stmm struct gem_rxsoft *rxs = &sc->sc_rxsoft[idx]; 146591398Stmm struct mbuf *m; 146691398Stmm int error; 146791398Stmm 1468111119Simp m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); 146991398Stmm if (m == NULL) 147091398Stmm return (ENOBUFS); 1471108832Stmm m->m_len = m->m_pkthdr.len = m->m_ext.ext_size; 147291398Stmm 147391398Stmm#ifdef GEM_DEBUG 147491398Stmm /* bzero the packet to check dma */ 147591398Stmm memset(m->m_ext.ext_buf, 0, m->m_ext.ext_size); 147691398Stmm#endif 147791398Stmm 1478109648Stmm if (rxs->rxs_mbuf != NULL) { 1479109648Stmm bus_dmamap_sync(sc->sc_rdmatag, rxs->rxs_dmamap, 1480109648Stmm BUS_DMASYNC_POSTREAD); 1481108832Stmm bus_dmamap_unload(sc->sc_rdmatag, rxs->rxs_dmamap); 1482109648Stmm } 148391398Stmm 148491398Stmm rxs->rxs_mbuf = m; 148591398Stmm 1486108832Stmm error = bus_dmamap_load_mbuf(sc->sc_rdmatag, rxs->rxs_dmamap, 1487108832Stmm m, gem_rxdma_callback, rxs, BUS_DMA_NOWAIT); 148891398Stmm if (error != 0 || rxs->rxs_paddr == 0) { 148991398Stmm device_printf(sc->sc_dev, "can't load rx DMA map %d, error = " 149091398Stmm "%d\n", idx, error); 149191398Stmm panic("gem_add_rxbuf"); /* XXX */ 149291398Stmm } 149391398Stmm 1494108832Stmm bus_dmamap_sync(sc->sc_rdmatag, rxs->rxs_dmamap, BUS_DMASYNC_PREREAD); 149591398Stmm 149691398Stmm GEM_INIT_RXDESC(sc, idx); 149791398Stmm 149891398Stmm return (0); 149991398Stmm} 150091398Stmm 150191398Stmm 150291398Stmmstatic void 150391398Stmmgem_eint(sc, status) 150491398Stmm struct gem_softc *sc; 150591398Stmm u_int status; 150691398Stmm{ 150791398Stmm 150891398Stmm if ((status & GEM_INTR_MIF) != 0) { 150991398Stmm device_printf(sc->sc_dev, "XXXlink status changed\n"); 151091398Stmm return; 151191398Stmm } 151291398Stmm 151391398Stmm device_printf(sc->sc_dev, "status=%x\n", status); 151491398Stmm} 151591398Stmm 151691398Stmm 151791398Stmmvoid 151891398Stmmgem_intr(v) 151991398Stmm void *v; 152091398Stmm{ 152191398Stmm struct gem_softc *sc = (struct gem_softc *)v; 152291398Stmm bus_space_tag_t t = sc->sc_bustag; 152391398Stmm bus_space_handle_t seb = sc->sc_h; 152491398Stmm u_int32_t status; 152591398Stmm 152691398Stmm status = bus_space_read_4(t, seb, GEM_STATUS); 1527115030Stmm#ifdef GEM_DEBUG 152891398Stmm CTR3(KTR_GEM, "%s: gem_intr: cplt %x, status %x", 152991398Stmm device_get_name(sc->sc_dev), (status>>19), 153091398Stmm (u_int)status); 1531115030Stmm#endif 153291398Stmm 153391398Stmm if ((status & (GEM_INTR_RX_TAG_ERR | GEM_INTR_BERR)) != 0) 153491398Stmm gem_eint(sc, status); 153591398Stmm 153691398Stmm if ((status & (GEM_INTR_TX_EMPTY | GEM_INTR_TX_INTME)) != 0) 153791398Stmm gem_tint(sc); 153891398Stmm 153991398Stmm if ((status & (GEM_INTR_RX_DONE | GEM_INTR_RX_NOBUF)) != 0) 154091398Stmm gem_rint(sc); 154191398Stmm 154291398Stmm /* We should eventually do more than just print out error stats. */ 154391398Stmm if (status & GEM_INTR_TX_MAC) { 154491398Stmm int txstat = bus_space_read_4(t, seb, GEM_MAC_TX_STATUS); 154591398Stmm if (txstat & ~GEM_MAC_TX_XMIT_DONE) 154699726Sbenno device_printf(sc->sc_dev, "MAC tx fault, status %x\n", 154799726Sbenno txstat); 154897240Stmm if (txstat & (GEM_MAC_TX_UNDERRUN | GEM_MAC_TX_PKT_TOO_LONG)) 154997240Stmm gem_init(sc); 155091398Stmm } 155191398Stmm if (status & GEM_INTR_RX_MAC) { 155291398Stmm int rxstat = bus_space_read_4(t, seb, GEM_MAC_RX_STATUS); 155391398Stmm if (rxstat & ~(GEM_MAC_RX_DONE | GEM_MAC_RX_FRAME_CNT)) 155499726Sbenno device_printf(sc->sc_dev, "MAC rx fault, status %x\n", 155599726Sbenno rxstat); 155697240Stmm if ((rxstat & GEM_MAC_RX_OVERFLOW) != 0) 155797240Stmm gem_init(sc); 155891398Stmm } 155991398Stmm} 156091398Stmm 156191398Stmm 156291398Stmmstatic void 156391398Stmmgem_watchdog(ifp) 156491398Stmm struct ifnet *ifp; 156591398Stmm{ 156691398Stmm struct gem_softc *sc = ifp->if_softc; 156791398Stmm 1568115030Stmm#ifdef GEM_DEBUG 156991398Stmm CTR3(KTR_GEM, "gem_watchdog: GEM_RX_CONFIG %x GEM_MAC_RX_STATUS %x " 157091398Stmm "GEM_MAC_RX_CONFIG %x", 157191398Stmm bus_space_read_4(sc->sc_bustag, sc->sc_h, GEM_RX_CONFIG), 157291398Stmm bus_space_read_4(sc->sc_bustag, sc->sc_h, GEM_MAC_RX_STATUS), 157391398Stmm bus_space_read_4(sc->sc_bustag, sc->sc_h, GEM_MAC_RX_CONFIG)); 157491398Stmm CTR3(KTR_GEM, "gem_watchdog: GEM_TX_CONFIG %x GEM_MAC_TX_STATUS %x " 157591398Stmm "GEM_MAC_TX_CONFIG %x", 157691398Stmm bus_space_read_4(sc->sc_bustag, sc->sc_h, GEM_TX_CONFIG), 157791398Stmm bus_space_read_4(sc->sc_bustag, sc->sc_h, GEM_MAC_TX_STATUS), 157891398Stmm bus_space_read_4(sc->sc_bustag, sc->sc_h, GEM_MAC_TX_CONFIG)); 1579115030Stmm#endif 158091398Stmm 158191398Stmm device_printf(sc->sc_dev, "device timeout\n"); 158291398Stmm ++ifp->if_oerrors; 158391398Stmm 158491398Stmm /* Try to get more packets going. */ 158591398Stmm gem_start(ifp); 158691398Stmm} 158791398Stmm 158891398Stmm/* 158991398Stmm * Initialize the MII Management Interface 159091398Stmm */ 159191398Stmmstatic void 159291398Stmmgem_mifinit(sc) 159391398Stmm struct gem_softc *sc; 159491398Stmm{ 159591398Stmm bus_space_tag_t t = sc->sc_bustag; 159691398Stmm bus_space_handle_t mif = sc->sc_h; 159791398Stmm 159891398Stmm /* Configure the MIF in frame mode */ 159991398Stmm sc->sc_mif_config = bus_space_read_4(t, mif, GEM_MIF_CONFIG); 160091398Stmm sc->sc_mif_config &= ~GEM_MIF_CONFIG_BB_ENA; 160191398Stmm bus_space_write_4(t, mif, GEM_MIF_CONFIG, sc->sc_mif_config); 160291398Stmm} 160391398Stmm 160491398Stmm/* 160591398Stmm * MII interface 160691398Stmm * 160791398Stmm * The GEM MII interface supports at least three different operating modes: 160891398Stmm * 160991398Stmm * Bitbang mode is implemented using data, clock and output enable registers. 161091398Stmm * 161191398Stmm * Frame mode is implemented by loading a complete frame into the frame 161291398Stmm * register and polling the valid bit for completion. 161391398Stmm * 161491398Stmm * Polling mode uses the frame register but completion is indicated by 161591398Stmm * an interrupt. 161691398Stmm * 161791398Stmm */ 161891398Stmmint 161991398Stmmgem_mii_readreg(dev, phy, reg) 162091398Stmm device_t dev; 162191398Stmm int phy, reg; 162291398Stmm{ 162391398Stmm struct gem_softc *sc = device_get_softc(dev); 162491398Stmm bus_space_tag_t t = sc->sc_bustag; 162591398Stmm bus_space_handle_t mif = sc->sc_h; 162691398Stmm int n; 162791398Stmm u_int32_t v; 162891398Stmm 162991398Stmm#ifdef GEM_DEBUG_PHY 163091398Stmm printf("gem_mii_readreg: phy %d reg %d\n", phy, reg); 163191398Stmm#endif 163291398Stmm 163391398Stmm#if 0 163491398Stmm /* Select the desired PHY in the MIF configuration register */ 163591398Stmm v = bus_space_read_4(t, mif, GEM_MIF_CONFIG); 163691398Stmm /* Clear PHY select bit */ 163791398Stmm v &= ~GEM_MIF_CONFIG_PHY_SEL; 163891398Stmm if (phy == GEM_PHYAD_EXTERNAL) 163991398Stmm /* Set PHY select bit to get at external device */ 164091398Stmm v |= GEM_MIF_CONFIG_PHY_SEL; 164191398Stmm bus_space_write_4(t, mif, GEM_MIF_CONFIG, v); 164291398Stmm#endif 164391398Stmm 164491398Stmm /* Construct the frame command */ 164591398Stmm v = (reg << GEM_MIF_REG_SHIFT) | (phy << GEM_MIF_PHY_SHIFT) | 164691398Stmm GEM_MIF_FRAME_READ; 164791398Stmm 164891398Stmm bus_space_write_4(t, mif, GEM_MIF_FRAME, v); 164991398Stmm for (n = 0; n < 100; n++) { 165091398Stmm DELAY(1); 165191398Stmm v = bus_space_read_4(t, mif, GEM_MIF_FRAME); 165291398Stmm if (v & GEM_MIF_FRAME_TA0) 165391398Stmm return (v & GEM_MIF_FRAME_DATA); 165491398Stmm } 165591398Stmm 165691398Stmm device_printf(sc->sc_dev, "mii_read timeout\n"); 165791398Stmm return (0); 165891398Stmm} 165991398Stmm 166091398Stmmint 166191398Stmmgem_mii_writereg(dev, phy, reg, val) 166291398Stmm device_t dev; 166391398Stmm int phy, reg, val; 166491398Stmm{ 166591398Stmm struct gem_softc *sc = device_get_softc(dev); 166691398Stmm bus_space_tag_t t = sc->sc_bustag; 166791398Stmm bus_space_handle_t mif = sc->sc_h; 166891398Stmm int n; 166991398Stmm u_int32_t v; 167091398Stmm 167191398Stmm#ifdef GEM_DEBUG_PHY 167291398Stmm printf("gem_mii_writereg: phy %d reg %d val %x\n", phy, reg, val); 167391398Stmm#endif 167491398Stmm 167591398Stmm#if 0 167691398Stmm /* Select the desired PHY in the MIF configuration register */ 167791398Stmm v = bus_space_read_4(t, mif, GEM_MIF_CONFIG); 167891398Stmm /* Clear PHY select bit */ 167991398Stmm v &= ~GEM_MIF_CONFIG_PHY_SEL; 168091398Stmm if (phy == GEM_PHYAD_EXTERNAL) 168191398Stmm /* Set PHY select bit to get at external device */ 168291398Stmm v |= GEM_MIF_CONFIG_PHY_SEL; 168391398Stmm bus_space_write_4(t, mif, GEM_MIF_CONFIG, v); 168491398Stmm#endif 168591398Stmm /* Construct the frame command */ 168691398Stmm v = GEM_MIF_FRAME_WRITE | 168791398Stmm (phy << GEM_MIF_PHY_SHIFT) | 168891398Stmm (reg << GEM_MIF_REG_SHIFT) | 168991398Stmm (val & GEM_MIF_FRAME_DATA); 169091398Stmm 169191398Stmm bus_space_write_4(t, mif, GEM_MIF_FRAME, v); 169291398Stmm for (n = 0; n < 100; n++) { 169391398Stmm DELAY(1); 169491398Stmm v = bus_space_read_4(t, mif, GEM_MIF_FRAME); 169591398Stmm if (v & GEM_MIF_FRAME_TA0) 169691398Stmm return (1); 169791398Stmm } 169891398Stmm 169991398Stmm device_printf(sc->sc_dev, "mii_write timeout\n"); 170091398Stmm return (0); 170191398Stmm} 170291398Stmm 170391398Stmmvoid 170491398Stmmgem_mii_statchg(dev) 170591398Stmm device_t dev; 170691398Stmm{ 170791398Stmm struct gem_softc *sc = device_get_softc(dev); 170891398Stmm#ifdef GEM_DEBUG 170991398Stmm int instance = IFM_INST(sc->sc_mii->mii_media.ifm_cur->ifm_media); 171091398Stmm#endif 171191398Stmm bus_space_tag_t t = sc->sc_bustag; 171291398Stmm bus_space_handle_t mac = sc->sc_h; 171391398Stmm u_int32_t v; 171491398Stmm 171591398Stmm#ifdef GEM_DEBUG 171691398Stmm if (sc->sc_debug) 171791398Stmm printf("gem_mii_statchg: status change: phy = %d\n", 171891398Stmm sc->sc_phys[instance]); 171991398Stmm#endif 172091398Stmm 172191398Stmm /* Set tx full duplex options */ 172291398Stmm bus_space_write_4(t, mac, GEM_MAC_TX_CONFIG, 0); 172391398Stmm DELAY(10000); /* reg must be cleared and delay before changing. */ 172491398Stmm v = GEM_MAC_TX_ENA_IPG0|GEM_MAC_TX_NGU|GEM_MAC_TX_NGU_LIMIT| 172591398Stmm GEM_MAC_TX_ENABLE; 172691398Stmm if ((IFM_OPTIONS(sc->sc_mii->mii_media_active) & IFM_FDX) != 0) { 172791398Stmm v |= GEM_MAC_TX_IGN_CARRIER|GEM_MAC_TX_IGN_COLLIS; 172891398Stmm } 172991398Stmm bus_space_write_4(t, mac, GEM_MAC_TX_CONFIG, v); 173091398Stmm 173191398Stmm /* XIF Configuration */ 173291398Stmm /* We should really calculate all this rather than rely on defaults */ 173391398Stmm v = bus_space_read_4(t, mac, GEM_MAC_XIF_CONFIG); 173491398Stmm v = GEM_MAC_XIF_LINK_LED; 173591398Stmm v |= GEM_MAC_XIF_TX_MII_ENA; 173699726Sbenno 173791398Stmm /* If an external transceiver is connected, enable its MII drivers */ 173891398Stmm sc->sc_mif_config = bus_space_read_4(t, mac, GEM_MIF_CONFIG); 173991398Stmm if ((sc->sc_mif_config & GEM_MIF_CONFIG_MDI1) != 0) { 174091398Stmm /* External MII needs echo disable if half duplex. */ 174191398Stmm if ((IFM_OPTIONS(sc->sc_mii->mii_media_active) & IFM_FDX) != 0) 174291398Stmm /* turn on full duplex LED */ 174391398Stmm v |= GEM_MAC_XIF_FDPLX_LED; 174499726Sbenno else 174599726Sbenno /* half duplex -- disable echo */ 174699726Sbenno v |= GEM_MAC_XIF_ECHO_DISABL; 174799726Sbenno 174899726Sbenno if (IFM_SUBTYPE(sc->sc_mii->mii_media_active) == IFM_1000_T) 174999726Sbenno v |= GEM_MAC_XIF_GMII_MODE; 175099726Sbenno else 175199726Sbenno v &= ~GEM_MAC_XIF_GMII_MODE; 175291398Stmm } else { 175391398Stmm /* Internal MII needs buf enable */ 175491398Stmm v |= GEM_MAC_XIF_MII_BUF_ENA; 175591398Stmm } 175691398Stmm bus_space_write_4(t, mac, GEM_MAC_XIF_CONFIG, v); 175791398Stmm} 175891398Stmm 175991398Stmmint 176091398Stmmgem_mediachange(ifp) 176191398Stmm struct ifnet *ifp; 176291398Stmm{ 176391398Stmm struct gem_softc *sc = ifp->if_softc; 176491398Stmm 176591398Stmm /* XXX Add support for serial media. */ 176691398Stmm 176791398Stmm return (mii_mediachg(sc->sc_mii)); 176891398Stmm} 176991398Stmm 177091398Stmmvoid 177191398Stmmgem_mediastatus(ifp, ifmr) 177291398Stmm struct ifnet *ifp; 177391398Stmm struct ifmediareq *ifmr; 177491398Stmm{ 177591398Stmm struct gem_softc *sc = ifp->if_softc; 177691398Stmm 177791398Stmm if ((ifp->if_flags & IFF_UP) == 0) 177891398Stmm return; 177991398Stmm 178091398Stmm mii_pollstat(sc->sc_mii); 178191398Stmm ifmr->ifm_active = sc->sc_mii->mii_media_active; 178291398Stmm ifmr->ifm_status = sc->sc_mii->mii_media_status; 178391398Stmm} 178491398Stmm 178591398Stmm/* 178691398Stmm * Process an ioctl request. 178791398Stmm */ 178891398Stmmstatic int 178991398Stmmgem_ioctl(ifp, cmd, data) 179091398Stmm struct ifnet *ifp; 179191398Stmm u_long cmd; 179291398Stmm caddr_t data; 179391398Stmm{ 179491398Stmm struct gem_softc *sc = ifp->if_softc; 179591398Stmm struct ifreq *ifr = (struct ifreq *)data; 179691398Stmm int s, error = 0; 179791398Stmm 179891398Stmm switch (cmd) { 179991398Stmm case SIOCSIFADDR: 180091398Stmm case SIOCGIFADDR: 180191398Stmm case SIOCSIFMTU: 180291398Stmm error = ether_ioctl(ifp, cmd, data); 180391398Stmm break; 180491398Stmm case SIOCSIFFLAGS: 180591398Stmm if (ifp->if_flags & IFF_UP) { 180699726Sbenno if ((sc->sc_ifflags ^ ifp->if_flags) == IFF_PROMISC) 180791398Stmm gem_setladrf(sc); 180891398Stmm else 180991398Stmm gem_init(sc); 181091398Stmm } else { 181191398Stmm if (ifp->if_flags & IFF_RUNNING) 181291398Stmm gem_stop(ifp, 0); 181391398Stmm } 181499726Sbenno sc->sc_ifflags = ifp->if_flags; 181591398Stmm error = 0; 181691398Stmm break; 181791398Stmm case SIOCADDMULTI: 181891398Stmm case SIOCDELMULTI: 181991398Stmm gem_setladrf(sc); 182091398Stmm error = 0; 182191398Stmm break; 182291398Stmm case SIOCGIFMEDIA: 182391398Stmm case SIOCSIFMEDIA: 182491398Stmm error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii->mii_media, cmd); 182591398Stmm break; 182691398Stmm default: 1827108832Stmm error = ENOTTY; 182891398Stmm break; 182991398Stmm } 183091398Stmm 183191398Stmm /* Try to get things going again */ 183291398Stmm if (ifp->if_flags & IFF_UP) 183391398Stmm gem_start(ifp); 183491398Stmm splx(s); 183591398Stmm return (error); 183691398Stmm} 183791398Stmm 183891398Stmm/* 183991398Stmm * Set up the logical address filter. 184091398Stmm */ 184191398Stmmstatic void 184291398Stmmgem_setladrf(sc) 184391398Stmm struct gem_softc *sc; 184491398Stmm{ 184591398Stmm struct ifnet *ifp = &sc->sc_arpcom.ac_if; 184691398Stmm struct ifmultiaddr *inm; 184791398Stmm bus_space_tag_t t = sc->sc_bustag; 184891398Stmm bus_space_handle_t h = sc->sc_h; 184991398Stmm u_int32_t crc; 185091398Stmm u_int32_t hash[16]; 185191398Stmm u_int32_t v; 185299726Sbenno int i; 185391398Stmm 185491398Stmm /* Get current RX configuration */ 185591398Stmm v = bus_space_read_4(t, h, GEM_MAC_RX_CONFIG); 185691398Stmm 185799726Sbenno /* 185899726Sbenno * Turn off promiscuous mode, promiscuous group mode (all multicast), 185999726Sbenno * and hash filter. Depending on the case, the right bit will be 186099726Sbenno * enabled. 186199726Sbenno */ 186299726Sbenno v &= ~(GEM_MAC_RX_PROMISCUOUS|GEM_MAC_RX_HASH_FILTER| 186399726Sbenno GEM_MAC_RX_PROMISC_GRP); 186499726Sbenno 186591398Stmm if ((ifp->if_flags & IFF_PROMISC) != 0) { 186699726Sbenno /* Turn on promiscuous mode */ 186791398Stmm v |= GEM_MAC_RX_PROMISCUOUS; 186891398Stmm goto chipit; 186991398Stmm } 187091398Stmm if ((ifp->if_flags & IFF_ALLMULTI) != 0) { 187191398Stmm hash[3] = hash[2] = hash[1] = hash[0] = 0xffff; 187291398Stmm ifp->if_flags |= IFF_ALLMULTI; 187399726Sbenno v |= GEM_MAC_RX_PROMISC_GRP; 187491398Stmm goto chipit; 187591398Stmm } 187691398Stmm 187791398Stmm /* 187891398Stmm * Set up multicast address filter by passing all multicast addresses 187999726Sbenno * through a crc generator, and then using the high order 8 bits as an 188099726Sbenno * index into the 256 bit logical address filter. The high order 4 188199726Sbenno * bits selects the word, while the other 4 bits select the bit within 188299726Sbenno * the word (where bit 0 is the MSB). 188391398Stmm */ 188491398Stmm 188599726Sbenno /* Clear hash table */ 188699726Sbenno memset(hash, 0, sizeof(hash)); 188799726Sbenno 188891398Stmm TAILQ_FOREACH(inm, &sc->sc_arpcom.ac_if.if_multiaddrs, ifma_link) { 188991398Stmm if (inm->ifma_addr->sa_family != AF_LINK) 189091398Stmm continue; 1891130288Smarius crc = ether_crc32_le(LLADDR((struct sockaddr_dl *) 1892130288Smarius inm->ifma_addr), ETHER_ADDR_LEN); 189391398Stmm 189491398Stmm /* Just want the 8 most significant bits. */ 189591398Stmm crc >>= 24; 189691398Stmm 189791398Stmm /* Set the corresponding bit in the filter. */ 189899726Sbenno hash[crc >> 4] |= 1 << (15 - (crc & 15)); 189991398Stmm } 190091398Stmm 190199726Sbenno v |= GEM_MAC_RX_HASH_FILTER; 190299726Sbenno ifp->if_flags &= ~IFF_ALLMULTI; 190399726Sbenno 190499726Sbenno /* Now load the hash table into the chip (if we are using it) */ 190599726Sbenno for (i = 0; i < 16; i++) { 190699726Sbenno bus_space_write_4(t, h, 190799726Sbenno GEM_MAC_HASH0 + i * (GEM_MAC_HASH1-GEM_MAC_HASH0), 190899726Sbenno hash[i]); 190999726Sbenno } 191099726Sbenno 191191398Stmmchipit: 191291398Stmm bus_space_write_4(t, h, GEM_MAC_RX_CONFIG, v); 191391398Stmm} 1914