if_gem.c revision 119418
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 119418 2003-08-24 17:55:58Z obrien $"); 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> 4991398Stmm#include <sys/socket.h> 5091398Stmm#include <sys/sockio.h> 5191398Stmm 52105982Stmm#include <net/bpf.h> 5391398Stmm#include <net/ethernet.h> 5491398Stmm#include <net/if.h> 5591398Stmm#include <net/if_arp.h> 5691398Stmm#include <net/if_dl.h> 5791398Stmm#include <net/if_media.h> 5891398Stmm 5991398Stmm#include <machine/bus.h> 6091398Stmm 6191398Stmm#include <dev/mii/mii.h> 6291398Stmm#include <dev/mii/miivar.h> 6391398Stmm 64119355Simp#include <dev/gem/if_gemreg.h> 65119355Simp#include <dev/gem/if_gemvar.h> 6691398Stmm 6791398Stmm#define TRIES 10000 6891398Stmm 6992739Salfredstatic void gem_start(struct ifnet *); 7092739Salfredstatic void gem_stop(struct ifnet *, int); 7192739Salfredstatic int gem_ioctl(struct ifnet *, u_long, caddr_t); 7292739Salfredstatic void gem_cddma_callback(void *, bus_dma_segment_t *, int, int); 73108832Stmmstatic void gem_rxdma_callback(void *, bus_dma_segment_t *, int, 74108832Stmm bus_size_t, int); 75108832Stmmstatic void gem_txdma_callback(void *, bus_dma_segment_t *, int, 76108832Stmm bus_size_t, int); 7792739Salfredstatic void gem_tick(void *); 7892739Salfredstatic void gem_watchdog(struct ifnet *); 7992739Salfredstatic void gem_init(void *); 8092739Salfredstatic void gem_init_regs(struct gem_softc *sc); 8192739Salfredstatic int gem_ringsize(int sz); 8292739Salfredstatic int gem_meminit(struct gem_softc *); 83108832Stmmstatic int gem_load_txmbuf(struct gem_softc *, struct mbuf *); 8492739Salfredstatic void gem_mifinit(struct gem_softc *); 8592739Salfredstatic int gem_bitwait(struct gem_softc *sc, bus_addr_t r, 8692739Salfred u_int32_t clr, u_int32_t set); 8792739Salfredstatic int gem_reset_rx(struct gem_softc *); 8892739Salfredstatic int gem_reset_tx(struct gem_softc *); 8992739Salfredstatic int gem_disable_rx(struct gem_softc *); 9092739Salfredstatic int gem_disable_tx(struct gem_softc *); 9192739Salfredstatic void gem_rxdrain(struct gem_softc *); 9292739Salfredstatic int gem_add_rxbuf(struct gem_softc *, int); 9392739Salfredstatic void gem_setladrf(struct gem_softc *); 9491398Stmm 9592739Salfredstruct mbuf *gem_get(struct gem_softc *, int, int); 9692739Salfredstatic void gem_eint(struct gem_softc *, u_int); 9792739Salfredstatic void gem_rint(struct gem_softc *); 98100587Sjake#if 0 9993045Stmmstatic void gem_rint_timeout(void *); 100100587Sjake#endif 10192739Salfredstatic void gem_tint(struct gem_softc *); 10291398Stmm#ifdef notyet 10392739Salfredstatic void gem_power(int, void *); 10491398Stmm#endif 10591398Stmm 10691398Stmmdevclass_t gem_devclass; 10791398StmmDRIVER_MODULE(miibus, gem, miibus_driver, miibus_devclass, 0, 0); 10891398StmmMODULE_DEPEND(gem, miibus, 1, 1, 1); 10991398Stmm 11091398Stmm#ifdef GEM_DEBUG 11191398Stmm#include <sys/ktr.h> 11291398Stmm#define KTR_GEM KTR_CT2 11391398Stmm#endif 11491398Stmm 115115030Stmm#define GEM_NSEGS GEM_NTXDESC 11691398Stmm 11791398Stmm/* 11891398Stmm * gem_attach: 11991398Stmm * 12091398Stmm * Attach a Gem interface to the system. 12191398Stmm */ 12291398Stmmint 12391398Stmmgem_attach(sc) 12491398Stmm struct gem_softc *sc; 12591398Stmm{ 12691398Stmm struct ifnet *ifp = &sc->sc_arpcom.ac_if; 12791398Stmm struct mii_softc *child; 12891398Stmm int i, error; 12999726Sbenno u_int32_t v; 13091398Stmm 13191398Stmm /* Make sure the chip is stopped. */ 13291398Stmm ifp->if_softc = sc; 13391398Stmm gem_reset(sc); 13491398Stmm 13591398Stmm error = bus_dma_tag_create(NULL, 1, 0, BUS_SPACE_MAXADDR_32BIT, 13691398Stmm BUS_SPACE_MAXADDR, NULL, NULL, MCLBYTES, GEM_NSEGS, 137117126Sscottl BUS_SPACE_MAXSIZE_32BIT, 0, NULL, NULL, &sc->sc_pdmatag); 13891398Stmm if (error) 13991398Stmm return (error); 14091398Stmm 14191398Stmm error = bus_dma_tag_create(sc->sc_pdmatag, 1, 0, 14291398Stmm BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, MAXBSIZE, 143117126Sscottl 1, BUS_SPACE_MAXSIZE_32BIT, BUS_DMA_ALLOCNOW, NULL, NULL, 144108832Stmm &sc->sc_rdmatag); 14591398Stmm if (error) 146108832Stmm goto fail_ptag; 14791398Stmm 148108832Stmm error = bus_dma_tag_create(sc->sc_pdmatag, 1, 0, 149108832Stmm BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, 150115030Stmm GEM_TD_BUFSIZE, GEM_NTXDESC, BUS_SPACE_MAXSIZE_32BIT, 151117126Sscottl BUS_DMA_ALLOCNOW, NULL, NULL, &sc->sc_tdmatag); 152108832Stmm if (error) 153108832Stmm goto fail_rtag; 154108832Stmm 15591398Stmm error = bus_dma_tag_create(sc->sc_pdmatag, PAGE_SIZE, 0, 15691398Stmm BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, 15791398Stmm sizeof(struct gem_control_data), 1, 15891398Stmm sizeof(struct gem_control_data), BUS_DMA_ALLOCNOW, 159117126Sscottl busdma_lock_mutex, &Giant, &sc->sc_cdmatag); 16091398Stmm if (error) 161108832Stmm goto fail_ttag; 16291398Stmm 16391398Stmm /* 16491398Stmm * Allocate the control data structures, and create and load the 16591398Stmm * DMA map for it. 16691398Stmm */ 16791398Stmm if ((error = bus_dmamem_alloc(sc->sc_cdmatag, 16891398Stmm (void **)&sc->sc_control_data, 0, &sc->sc_cddmamap))) { 16991398Stmm device_printf(sc->sc_dev, "unable to allocate control data," 17091398Stmm " error = %d\n", error); 171108832Stmm goto fail_ctag; 17291398Stmm } 17391398Stmm 17491398Stmm sc->sc_cddma = 0; 17591398Stmm if ((error = bus_dmamap_load(sc->sc_cdmatag, sc->sc_cddmamap, 17691398Stmm sc->sc_control_data, sizeof(struct gem_control_data), 17791398Stmm gem_cddma_callback, sc, 0)) != 0 || sc->sc_cddma == 0) { 17891398Stmm device_printf(sc->sc_dev, "unable to load control data DMA " 17991398Stmm "map, error = %d\n", error); 180108832Stmm goto fail_cmem; 18191398Stmm } 18291398Stmm 18391398Stmm /* 18491398Stmm * Initialize the transmit job descriptors. 18591398Stmm */ 18691398Stmm STAILQ_INIT(&sc->sc_txfreeq); 18791398Stmm STAILQ_INIT(&sc->sc_txdirtyq); 18891398Stmm 18991398Stmm /* 19091398Stmm * Create the transmit buffer DMA maps. 19191398Stmm */ 19291398Stmm error = ENOMEM; 19391398Stmm for (i = 0; i < GEM_TXQUEUELEN; i++) { 19491398Stmm struct gem_txsoft *txs; 19591398Stmm 19691398Stmm txs = &sc->sc_txsoft[i]; 19791398Stmm txs->txs_mbuf = NULL; 19891398Stmm txs->txs_ndescs = 0; 199108832Stmm if ((error = bus_dmamap_create(sc->sc_tdmatag, 0, 20091398Stmm &txs->txs_dmamap)) != 0) { 20191398Stmm device_printf(sc->sc_dev, "unable to create tx DMA map " 20291398Stmm "%d, error = %d\n", i, error); 203108832Stmm goto fail_txd; 20491398Stmm } 20591398Stmm STAILQ_INSERT_TAIL(&sc->sc_txfreeq, txs, txs_q); 20691398Stmm } 20791398Stmm 20891398Stmm /* 20991398Stmm * Create the receive buffer DMA maps. 21091398Stmm */ 21191398Stmm for (i = 0; i < GEM_NRXDESC; i++) { 212108832Stmm if ((error = bus_dmamap_create(sc->sc_rdmatag, 0, 21391398Stmm &sc->sc_rxsoft[i].rxs_dmamap)) != 0) { 21491398Stmm device_printf(sc->sc_dev, "unable to create rx DMA map " 21591398Stmm "%d, error = %d\n", i, error); 216108832Stmm goto fail_rxd; 21791398Stmm } 21891398Stmm sc->sc_rxsoft[i].rxs_mbuf = NULL; 21991398Stmm } 22091398Stmm 22191398Stmm 22291398Stmm gem_mifinit(sc); 22391398Stmm 22491398Stmm if ((error = mii_phy_probe(sc->sc_dev, &sc->sc_miibus, gem_mediachange, 22591398Stmm gem_mediastatus)) != 0) { 22691398Stmm device_printf(sc->sc_dev, "phy probe failed: %d\n", error); 227108832Stmm goto fail_rxd; 22891398Stmm } 22991398Stmm sc->sc_mii = device_get_softc(sc->sc_miibus); 23091398Stmm 23191398Stmm /* 23291398Stmm * From this point forward, the attachment cannot fail. A failure 23391398Stmm * before this point releases all resources that may have been 23491398Stmm * allocated. 23591398Stmm */ 23691398Stmm 23791398Stmm /* Announce ourselves. */ 23891398Stmm device_printf(sc->sc_dev, "Ethernet address:"); 23991398Stmm for (i = 0; i < 6; i++) 24091398Stmm printf("%c%02x", i > 0 ? ':' : ' ', sc->sc_arpcom.ac_enaddr[i]); 24191398Stmm 24299726Sbenno /* Get RX FIFO size */ 24399726Sbenno sc->sc_rxfifosize = 64 * 24499726Sbenno bus_space_read_4(sc->sc_bustag, sc->sc_h, GEM_RX_FIFO_SIZE); 24599726Sbenno printf(", %uKB RX fifo", sc->sc_rxfifosize / 1024); 24699726Sbenno 24799726Sbenno /* Get TX FIFO size */ 24899726Sbenno v = bus_space_read_4(sc->sc_bustag, sc->sc_h, GEM_TX_FIFO_SIZE); 24999726Sbenno printf(", %uKB TX fifo\n", v / 16); 25099726Sbenno 25191398Stmm /* Initialize ifnet structure. */ 25291398Stmm ifp->if_softc = sc; 25391398Stmm ifp->if_unit = device_get_unit(sc->sc_dev); 25491398Stmm ifp->if_name = "gem"; 25591398Stmm ifp->if_mtu = ETHERMTU; 25691398Stmm ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 25791398Stmm ifp->if_start = gem_start; 25891398Stmm ifp->if_ioctl = gem_ioctl; 25991398Stmm ifp->if_watchdog = gem_watchdog; 26091398Stmm ifp->if_init = gem_init; 26191398Stmm ifp->if_output = ether_output; 26291398Stmm ifp->if_snd.ifq_maxlen = GEM_TXQUEUELEN; 26391398Stmm /* 26491398Stmm * Walk along the list of attached MII devices and 26591398Stmm * establish an `MII instance' to `phy number' 26691398Stmm * mapping. We'll use this mapping in media change 26791398Stmm * requests to determine which phy to use to program 26891398Stmm * the MIF configuration register. 26991398Stmm */ 27091398Stmm for (child = LIST_FIRST(&sc->sc_mii->mii_phys); child != NULL; 27191398Stmm child = LIST_NEXT(child, mii_list)) { 27291398Stmm /* 27391398Stmm * Note: we support just two PHYs: the built-in 27491398Stmm * internal device and an external on the MII 27591398Stmm * connector. 27691398Stmm */ 27791398Stmm if (child->mii_phy > 1 || child->mii_inst > 1) { 27891398Stmm device_printf(sc->sc_dev, "cannot accomodate " 27991398Stmm "MII device %s at phy %d, instance %d\n", 28091398Stmm device_get_name(child->mii_dev), 28191398Stmm child->mii_phy, child->mii_inst); 28291398Stmm continue; 28391398Stmm } 28491398Stmm 28591398Stmm sc->sc_phys[child->mii_inst] = child->mii_phy; 28691398Stmm } 28791398Stmm 28891398Stmm /* 28991398Stmm * Now select and activate the PHY we will use. 29091398Stmm * 29191398Stmm * The order of preference is External (MDI1), 29291398Stmm * Internal (MDI0), Serial Link (no MII). 29391398Stmm */ 29491398Stmm if (sc->sc_phys[1]) { 29591398Stmm#ifdef GEM_DEBUG 29691398Stmm printf("using external phy\n"); 29791398Stmm#endif 29891398Stmm sc->sc_mif_config |= GEM_MIF_CONFIG_PHY_SEL; 29991398Stmm } else { 30091398Stmm#ifdef GEM_DEBUG 30191398Stmm printf("using internal phy\n"); 30291398Stmm#endif 30391398Stmm sc->sc_mif_config &= ~GEM_MIF_CONFIG_PHY_SEL; 30491398Stmm } 30591398Stmm bus_space_write_4(sc->sc_bustag, sc->sc_h, GEM_MIF_CONFIG, 30691398Stmm sc->sc_mif_config); 30791398Stmm /* Attach the interface. */ 308106937Ssam ether_ifattach(ifp, sc->sc_arpcom.ac_enaddr); 30991398Stmm 31091398Stmm#if notyet 31191398Stmm /* 31291398Stmm * Add a suspend hook to make sure we come back up after a 31391398Stmm * resume. 31491398Stmm */ 31591398Stmm sc->sc_powerhook = powerhook_establish(gem_power, sc); 31691398Stmm if (sc->sc_powerhook == NULL) 31791398Stmm device_printf(sc->sc_dev, "WARNING: unable to establish power " 31891398Stmm "hook\n"); 31991398Stmm#endif 32091398Stmm 32191398Stmm callout_init(&sc->sc_tick_ch, 0); 32293045Stmm callout_init(&sc->sc_rx_ch, 0); 32391398Stmm return (0); 32491398Stmm 32591398Stmm /* 32691398Stmm * Free any resources we've allocated during the failed attach 32791398Stmm * attempt. Do this in reverse order and fall through. 32891398Stmm */ 329108832Stmmfail_rxd: 33091398Stmm for (i = 0; i < GEM_NRXDESC; i++) { 33191398Stmm if (sc->sc_rxsoft[i].rxs_dmamap != NULL) 332108832Stmm bus_dmamap_destroy(sc->sc_rdmatag, 33391398Stmm sc->sc_rxsoft[i].rxs_dmamap); 33491398Stmm } 335108832Stmmfail_txd: 33691398Stmm for (i = 0; i < GEM_TXQUEUELEN; i++) { 33791398Stmm if (sc->sc_txsoft[i].txs_dmamap != NULL) 338108832Stmm bus_dmamap_destroy(sc->sc_tdmatag, 33991398Stmm sc->sc_txsoft[i].txs_dmamap); 34091398Stmm } 341108832Stmm bus_dmamap_unload(sc->sc_cdmatag, sc->sc_cddmamap); 342108832Stmmfail_cmem: 34391398Stmm bus_dmamem_free(sc->sc_cdmatag, sc->sc_control_data, 34491398Stmm sc->sc_cddmamap); 345108832Stmmfail_ctag: 34691398Stmm bus_dma_tag_destroy(sc->sc_cdmatag); 347108832Stmmfail_ttag: 348108832Stmm bus_dma_tag_destroy(sc->sc_tdmatag); 349108832Stmmfail_rtag: 350108832Stmm bus_dma_tag_destroy(sc->sc_rdmatag); 351108832Stmmfail_ptag: 35291398Stmm bus_dma_tag_destroy(sc->sc_pdmatag); 35391398Stmm return (error); 35491398Stmm} 35591398Stmm 356108964Stmmvoid 357108964Stmmgem_detach(sc) 358108964Stmm struct gem_softc *sc; 359108964Stmm{ 360108964Stmm struct ifnet *ifp = &sc->sc_arpcom.ac_if; 361108964Stmm int i; 362108964Stmm 363108964Stmm ether_ifdetach(ifp); 364108964Stmm gem_stop(ifp, 1); 365108964Stmm device_delete_child(sc->sc_dev, sc->sc_miibus); 366108964Stmm 367108964Stmm for (i = 0; i < GEM_NRXDESC; i++) { 368108964Stmm if (sc->sc_rxsoft[i].rxs_dmamap != NULL) 369108964Stmm bus_dmamap_destroy(sc->sc_rdmatag, 370108964Stmm sc->sc_rxsoft[i].rxs_dmamap); 371108964Stmm } 372108964Stmm for (i = 0; i < GEM_TXQUEUELEN; i++) { 373108964Stmm if (sc->sc_txsoft[i].txs_dmamap != NULL) 374108964Stmm bus_dmamap_destroy(sc->sc_tdmatag, 375108964Stmm sc->sc_txsoft[i].txs_dmamap); 376108964Stmm } 377109648Stmm GEM_CDSYNC(sc, BUS_DMASYNC_POSTREAD); 378109648Stmm GEM_CDSYNC(sc, BUS_DMASYNC_POSTWRITE); 379108964Stmm bus_dmamap_unload(sc->sc_cdmatag, sc->sc_cddmamap); 380108964Stmm bus_dmamem_free(sc->sc_cdmatag, sc->sc_control_data, 381108964Stmm sc->sc_cddmamap); 382108964Stmm bus_dma_tag_destroy(sc->sc_cdmatag); 383108964Stmm bus_dma_tag_destroy(sc->sc_tdmatag); 384108964Stmm bus_dma_tag_destroy(sc->sc_rdmatag); 385108964Stmm bus_dma_tag_destroy(sc->sc_pdmatag); 386108964Stmm} 387108964Stmm 388108964Stmmvoid 389108964Stmmgem_suspend(sc) 390108964Stmm struct gem_softc *sc; 391108964Stmm{ 392108964Stmm struct ifnet *ifp = &sc->sc_arpcom.ac_if; 393108964Stmm 394108964Stmm gem_stop(ifp, 0); 395108964Stmm} 396108964Stmm 397108964Stmmvoid 398108964Stmmgem_resume(sc) 399108964Stmm struct gem_softc *sc; 400108964Stmm{ 401108964Stmm struct ifnet *ifp = &sc->sc_arpcom.ac_if; 402108964Stmm 403108964Stmm if (ifp->if_flags & IFF_UP) 404108964Stmm gem_init(ifp); 405108964Stmm} 406108964Stmm 40791398Stmmstatic void 40891398Stmmgem_cddma_callback(xsc, segs, nsegs, error) 40991398Stmm void *xsc; 41091398Stmm bus_dma_segment_t *segs; 41191398Stmm int nsegs; 41291398Stmm int error; 41391398Stmm{ 41491398Stmm struct gem_softc *sc = (struct gem_softc *)xsc; 41591398Stmm 41691398Stmm if (error != 0) 41791398Stmm return; 41891398Stmm if (nsegs != 1) { 41991398Stmm /* can't happen... */ 42091398Stmm panic("gem_cddma_callback: bad control buffer segment count"); 42191398Stmm } 42291398Stmm sc->sc_cddma = segs[0].ds_addr; 42391398Stmm} 42491398Stmm 42591398Stmmstatic void 426108832Stmmgem_rxdma_callback(xsc, segs, nsegs, totsz, error) 42791398Stmm void *xsc; 42891398Stmm bus_dma_segment_t *segs; 42991398Stmm int nsegs; 430108832Stmm bus_size_t totsz; 43191398Stmm int error; 43291398Stmm{ 43391398Stmm struct gem_rxsoft *rxs = (struct gem_rxsoft *)xsc; 43491398Stmm 43591398Stmm if (error != 0) 43691398Stmm return; 437108832Stmm KASSERT(nsegs == 1, ("gem_rxdma_callback: bad dma segment count")); 43891398Stmm rxs->rxs_paddr = segs[0].ds_addr; 43991398Stmm} 44091398Stmm 44191398Stmmstatic void 442108832Stmmgem_txdma_callback(xsc, segs, nsegs, totsz, error) 44391398Stmm void *xsc; 44491398Stmm bus_dma_segment_t *segs; 44591398Stmm int nsegs; 446108832Stmm bus_size_t totsz; 44791398Stmm int error; 44891398Stmm{ 449108832Stmm struct gem_txdma *txd = (struct gem_txdma *)xsc; 450108832Stmm struct gem_softc *sc = txd->txd_sc; 451108832Stmm struct gem_txsoft *txs = txd->txd_txs; 452108832Stmm bus_size_t len = 0; 453108832Stmm uint64_t flags = 0; 454108832Stmm int seg, nexttx; 45591398Stmm 45691398Stmm if (error != 0) 45791398Stmm return; 458108832Stmm /* 459108832Stmm * Ensure we have enough descriptors free to describe 460108832Stmm * the packet. Note, we always reserve one descriptor 461108832Stmm * at the end of the ring as a termination point, to 462108832Stmm * prevent wrap-around. 463108832Stmm */ 464108832Stmm if (nsegs > sc->sc_txfree - 1) { 465108832Stmm txs->txs_ndescs = -1; 466108832Stmm return; 467108832Stmm } 468108832Stmm txs->txs_ndescs = nsegs; 46991398Stmm 470108832Stmm nexttx = txs->txs_firstdesc; 47191398Stmm /* 47291398Stmm * Initialize the transmit descriptors. 47391398Stmm */ 47491398Stmm for (seg = 0; seg < nsegs; 475108832Stmm seg++, nexttx = GEM_NEXTTX(nexttx)) { 476115030Stmm#ifdef GEM_DEBUG 47791398Stmm CTR5(KTR_GEM, "txdma_cb: mapping seg %d (txd %d), len " 478108832Stmm "%lx, addr %#lx (%#lx)", seg, nexttx, 47991398Stmm segs[seg].ds_len, segs[seg].ds_addr, 480108832Stmm GEM_DMA_WRITE(sc, segs[seg].ds_addr)); 481115030Stmm#endif 482108832Stmm 483108832Stmm if (segs[seg].ds_len == 0) 484108832Stmm continue; 485108832Stmm sc->sc_txdescs[nexttx].gd_addr = 486108832Stmm GEM_DMA_WRITE(sc, segs[seg].ds_addr); 487108832Stmm KASSERT(segs[seg].ds_len < GEM_TD_BUFSIZE, 488108832Stmm ("gem_txdma_callback: segment size too large!")); 48991398Stmm flags = segs[seg].ds_len & GEM_TD_BUFSIZE; 490108832Stmm if (len == 0) { 491115030Stmm#ifdef GEM_DEBUG 49291398Stmm CTR2(KTR_GEM, "txdma_cb: start of packet at seg %d, " 493108832Stmm "tx %d", seg, nexttx); 494115030Stmm#endif 49591398Stmm flags |= GEM_TD_START_OF_PACKET; 496108832Stmm if (++sc->sc_txwin > GEM_NTXSEGS * 2 / 3) { 497108832Stmm sc->sc_txwin = 0; 49899726Sbenno flags |= GEM_TD_INTERRUPT_ME; 49999726Sbenno } 50091398Stmm } 501108832Stmm if (len + segs[seg].ds_len == totsz) { 502115030Stmm#ifdef GEM_DEBUG 50391398Stmm CTR2(KTR_GEM, "txdma_cb: end of packet at seg %d, " 504108832Stmm "tx %d", seg, nexttx); 505115030Stmm#endif 50691398Stmm flags |= GEM_TD_END_OF_PACKET; 50791398Stmm } 508108832Stmm sc->sc_txdescs[nexttx].gd_flags = GEM_DMA_WRITE(sc, flags); 509108832Stmm txs->txs_lastdesc = nexttx; 510108832Stmm len += segs[seg].ds_len; 51191398Stmm } 512108832Stmm KASSERT((flags & GEM_TD_END_OF_PACKET) != 0, 513108832Stmm ("gem_txdma_callback: missed end of packet!")); 51491398Stmm} 51591398Stmm 51691398Stmmstatic void 51791398Stmmgem_tick(arg) 51891398Stmm void *arg; 51991398Stmm{ 52091398Stmm struct gem_softc *sc = arg; 52191398Stmm int s; 52291398Stmm 52391398Stmm s = splnet(); 52491398Stmm mii_tick(sc->sc_mii); 52591398Stmm splx(s); 52691398Stmm 52791398Stmm callout_reset(&sc->sc_tick_ch, hz, gem_tick, sc); 52891398Stmm} 52991398Stmm 53091398Stmmstatic int 53191398Stmmgem_bitwait(sc, r, clr, set) 53291398Stmm struct gem_softc *sc; 53391398Stmm bus_addr_t r; 53491398Stmm u_int32_t clr; 53591398Stmm u_int32_t set; 53691398Stmm{ 53791398Stmm int i; 53891398Stmm u_int32_t reg; 53991398Stmm 54091398Stmm for (i = TRIES; i--; DELAY(100)) { 54191398Stmm reg = bus_space_read_4(sc->sc_bustag, sc->sc_h, r); 54291398Stmm if ((r & clr) == 0 && (r & set) == set) 54391398Stmm return (1); 54491398Stmm } 54591398Stmm return (0); 54691398Stmm} 54791398Stmm 54891398Stmmvoid 54991398Stmmgem_reset(sc) 55091398Stmm struct gem_softc *sc; 55191398Stmm{ 55291398Stmm bus_space_tag_t t = sc->sc_bustag; 55391398Stmm bus_space_handle_t h = sc->sc_h; 55491398Stmm int s; 55591398Stmm 55691398Stmm s = splnet(); 557115030Stmm#ifdef GEM_DEBUG 55891398Stmm CTR1(KTR_GEM, "%s: gem_reset", device_get_name(sc->sc_dev)); 559115030Stmm#endif 56091398Stmm gem_reset_rx(sc); 56191398Stmm gem_reset_tx(sc); 56291398Stmm 56391398Stmm /* Do a full reset */ 56491398Stmm bus_space_write_4(t, h, GEM_RESET, GEM_RESET_RX | GEM_RESET_TX); 56591398Stmm if (!gem_bitwait(sc, GEM_RESET, GEM_RESET_RX | GEM_RESET_TX, 0)) 56691398Stmm device_printf(sc->sc_dev, "cannot reset device\n"); 56791398Stmm splx(s); 56891398Stmm} 56991398Stmm 57091398Stmm 57191398Stmm/* 57291398Stmm * gem_rxdrain: 57391398Stmm * 57491398Stmm * Drain the receive queue. 57591398Stmm */ 57691398Stmmstatic void 57791398Stmmgem_rxdrain(sc) 57891398Stmm struct gem_softc *sc; 57991398Stmm{ 58091398Stmm struct gem_rxsoft *rxs; 58191398Stmm int i; 58291398Stmm 58391398Stmm for (i = 0; i < GEM_NRXDESC; i++) { 58491398Stmm rxs = &sc->sc_rxsoft[i]; 58591398Stmm if (rxs->rxs_mbuf != NULL) { 586109648Stmm bus_dmamap_sync(sc->sc_rdmatag, rxs->rxs_dmamap, 587109648Stmm BUS_DMASYNC_POSTREAD); 588108832Stmm bus_dmamap_unload(sc->sc_rdmatag, rxs->rxs_dmamap); 58991398Stmm m_freem(rxs->rxs_mbuf); 59091398Stmm rxs->rxs_mbuf = NULL; 59191398Stmm } 59291398Stmm } 59391398Stmm} 59491398Stmm 59591398Stmm/* 59691398Stmm * Reset the whole thing. 59791398Stmm */ 59891398Stmmstatic void 59991398Stmmgem_stop(ifp, disable) 60091398Stmm struct ifnet *ifp; 60191398Stmm int disable; 60291398Stmm{ 60391398Stmm struct gem_softc *sc = (struct gem_softc *)ifp->if_softc; 60491398Stmm struct gem_txsoft *txs; 60591398Stmm 606115030Stmm#ifdef GEM_DEBUG 60791398Stmm CTR1(KTR_GEM, "%s: gem_stop", device_get_name(sc->sc_dev)); 608115030Stmm#endif 60991398Stmm 61091398Stmm callout_stop(&sc->sc_tick_ch); 61191398Stmm 61291398Stmm /* XXX - Should we reset these instead? */ 61391398Stmm gem_disable_tx(sc); 61491398Stmm gem_disable_rx(sc); 61591398Stmm 61691398Stmm /* 61791398Stmm * Release any queued transmit buffers. 61891398Stmm */ 61991398Stmm while ((txs = STAILQ_FIRST(&sc->sc_txdirtyq)) != NULL) { 62091398Stmm STAILQ_REMOVE_HEAD(&sc->sc_txdirtyq, txs_q); 62191398Stmm if (txs->txs_ndescs != 0) { 622109648Stmm bus_dmamap_sync(sc->sc_tdmatag, txs->txs_dmamap, 623109648Stmm BUS_DMASYNC_POSTWRITE); 624108832Stmm bus_dmamap_unload(sc->sc_tdmatag, txs->txs_dmamap); 62591398Stmm if (txs->txs_mbuf != NULL) { 62691398Stmm m_freem(txs->txs_mbuf); 62791398Stmm txs->txs_mbuf = NULL; 62891398Stmm } 62991398Stmm } 63091398Stmm STAILQ_INSERT_TAIL(&sc->sc_txfreeq, txs, txs_q); 63191398Stmm } 63291398Stmm 63391398Stmm if (disable) 63491398Stmm gem_rxdrain(sc); 63591398Stmm 63691398Stmm /* 63791398Stmm * Mark the interface down and cancel the watchdog timer. 63891398Stmm */ 63991398Stmm ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); 64091398Stmm ifp->if_timer = 0; 64191398Stmm} 64291398Stmm 64391398Stmm/* 64491398Stmm * Reset the receiver 64591398Stmm */ 64691398Stmmint 64791398Stmmgem_reset_rx(sc) 64891398Stmm struct gem_softc *sc; 64991398Stmm{ 65091398Stmm bus_space_tag_t t = sc->sc_bustag; 65191398Stmm bus_space_handle_t h = sc->sc_h; 65291398Stmm 65391398Stmm /* 65491398Stmm * Resetting while DMA is in progress can cause a bus hang, so we 65591398Stmm * disable DMA first. 65691398Stmm */ 65791398Stmm gem_disable_rx(sc); 65891398Stmm bus_space_write_4(t, h, GEM_RX_CONFIG, 0); 65991398Stmm /* Wait till it finishes */ 66091398Stmm if (!gem_bitwait(sc, GEM_RX_CONFIG, 1, 0)) 66191398Stmm device_printf(sc->sc_dev, "cannot disable read dma\n"); 66291398Stmm 66391398Stmm /* Wait 5ms extra. */ 66491398Stmm DELAY(5000); 66591398Stmm 66691398Stmm /* Finally, reset the ERX */ 66791398Stmm bus_space_write_4(t, h, GEM_RESET, GEM_RESET_RX); 66891398Stmm /* Wait till it finishes */ 66991398Stmm if (!gem_bitwait(sc, GEM_RESET, GEM_RESET_TX, 0)) { 67091398Stmm device_printf(sc->sc_dev, "cannot reset receiver\n"); 67191398Stmm return (1); 67291398Stmm } 67391398Stmm return (0); 67491398Stmm} 67591398Stmm 67691398Stmm 67791398Stmm/* 67891398Stmm * Reset the transmitter 67991398Stmm */ 68091398Stmmstatic int 68191398Stmmgem_reset_tx(sc) 68291398Stmm struct gem_softc *sc; 68391398Stmm{ 68491398Stmm bus_space_tag_t t = sc->sc_bustag; 68591398Stmm bus_space_handle_t h = sc->sc_h; 68691398Stmm int i; 68791398Stmm 68891398Stmm /* 68991398Stmm * Resetting while DMA is in progress can cause a bus hang, so we 69091398Stmm * disable DMA first. 69191398Stmm */ 69291398Stmm gem_disable_tx(sc); 69391398Stmm bus_space_write_4(t, h, GEM_TX_CONFIG, 0); 69491398Stmm /* Wait till it finishes */ 69591398Stmm if (!gem_bitwait(sc, GEM_TX_CONFIG, 1, 0)) 69691398Stmm device_printf(sc->sc_dev, "cannot disable read dma\n"); 69791398Stmm 69891398Stmm /* Wait 5ms extra. */ 69991398Stmm DELAY(5000); 70091398Stmm 70191398Stmm /* Finally, reset the ETX */ 70291398Stmm bus_space_write_4(t, h, GEM_RESET, GEM_RESET_TX); 70391398Stmm /* Wait till it finishes */ 70491398Stmm for (i = TRIES; i--; DELAY(100)) 70591398Stmm if ((bus_space_read_4(t, h, GEM_RESET) & GEM_RESET_TX) == 0) 70691398Stmm break; 70791398Stmm if (!gem_bitwait(sc, GEM_RESET, GEM_RESET_TX, 0)) { 70891398Stmm device_printf(sc->sc_dev, "cannot reset receiver\n"); 70991398Stmm return (1); 71091398Stmm } 71191398Stmm return (0); 71291398Stmm} 71391398Stmm 71491398Stmm/* 71591398Stmm * disable receiver. 71691398Stmm */ 71791398Stmmstatic int 71891398Stmmgem_disable_rx(sc) 71991398Stmm struct gem_softc *sc; 72091398Stmm{ 72191398Stmm bus_space_tag_t t = sc->sc_bustag; 72291398Stmm bus_space_handle_t h = sc->sc_h; 72391398Stmm u_int32_t cfg; 72491398Stmm 72591398Stmm /* Flip the enable bit */ 72691398Stmm cfg = bus_space_read_4(t, h, GEM_MAC_RX_CONFIG); 72791398Stmm cfg &= ~GEM_MAC_RX_ENABLE; 72891398Stmm bus_space_write_4(t, h, GEM_MAC_RX_CONFIG, cfg); 72991398Stmm 73091398Stmm /* Wait for it to finish */ 73191398Stmm return (gem_bitwait(sc, GEM_MAC_RX_CONFIG, GEM_MAC_RX_ENABLE, 0)); 73291398Stmm} 73391398Stmm 73491398Stmm/* 73591398Stmm * disable transmitter. 73691398Stmm */ 73791398Stmmstatic int 73891398Stmmgem_disable_tx(sc) 73991398Stmm struct gem_softc *sc; 74091398Stmm{ 74191398Stmm bus_space_tag_t t = sc->sc_bustag; 74291398Stmm bus_space_handle_t h = sc->sc_h; 74391398Stmm u_int32_t cfg; 74491398Stmm 74591398Stmm /* Flip the enable bit */ 74691398Stmm cfg = bus_space_read_4(t, h, GEM_MAC_TX_CONFIG); 74791398Stmm cfg &= ~GEM_MAC_TX_ENABLE; 74891398Stmm bus_space_write_4(t, h, GEM_MAC_TX_CONFIG, cfg); 74991398Stmm 75091398Stmm /* Wait for it to finish */ 75191398Stmm return (gem_bitwait(sc, GEM_MAC_TX_CONFIG, GEM_MAC_TX_ENABLE, 0)); 75291398Stmm} 75391398Stmm 75491398Stmm/* 75591398Stmm * Initialize interface. 75691398Stmm */ 75791398Stmmstatic int 75891398Stmmgem_meminit(sc) 75991398Stmm struct gem_softc *sc; 76091398Stmm{ 76191398Stmm struct gem_rxsoft *rxs; 76291398Stmm int i, error; 76391398Stmm 76491398Stmm /* 76591398Stmm * Initialize the transmit descriptor ring. 76691398Stmm */ 76791398Stmm memset((void *)sc->sc_txdescs, 0, sizeof(sc->sc_txdescs)); 76891398Stmm for (i = 0; i < GEM_NTXDESC; i++) { 76991398Stmm sc->sc_txdescs[i].gd_flags = 0; 77091398Stmm sc->sc_txdescs[i].gd_addr = 0; 77191398Stmm } 772108832Stmm sc->sc_txfree = GEM_MAXTXFREE; 77391398Stmm sc->sc_txnext = 0; 77499726Sbenno sc->sc_txwin = 0; 77591398Stmm 77691398Stmm /* 77791398Stmm * Initialize the receive descriptor and receive job 77891398Stmm * descriptor rings. 77991398Stmm */ 78091398Stmm for (i = 0; i < GEM_NRXDESC; i++) { 78191398Stmm rxs = &sc->sc_rxsoft[i]; 78291398Stmm if (rxs->rxs_mbuf == NULL) { 78391398Stmm if ((error = gem_add_rxbuf(sc, i)) != 0) { 78491398Stmm device_printf(sc->sc_dev, "unable to " 78591398Stmm "allocate or map rx buffer %d, error = " 78691398Stmm "%d\n", i, error); 78791398Stmm /* 78891398Stmm * XXX Should attempt to run with fewer receive 78991398Stmm * XXX buffers instead of just failing. 79091398Stmm */ 79191398Stmm gem_rxdrain(sc); 79291398Stmm return (1); 79391398Stmm } 79491398Stmm } else 79591398Stmm GEM_INIT_RXDESC(sc, i); 79691398Stmm } 79791398Stmm sc->sc_rxptr = 0; 798109648Stmm GEM_CDSYNC(sc, BUS_DMASYNC_PREWRITE); 799109648Stmm GEM_CDSYNC(sc, BUS_DMASYNC_PREREAD); 80091398Stmm 80191398Stmm return (0); 80291398Stmm} 80391398Stmm 80491398Stmmstatic int 80591398Stmmgem_ringsize(sz) 80691398Stmm int sz; 80791398Stmm{ 80891398Stmm int v = 0; 80991398Stmm 81091398Stmm switch (sz) { 81191398Stmm case 32: 81291398Stmm v = GEM_RING_SZ_32; 81391398Stmm break; 81491398Stmm case 64: 81591398Stmm v = GEM_RING_SZ_64; 81691398Stmm break; 81791398Stmm case 128: 81891398Stmm v = GEM_RING_SZ_128; 81991398Stmm break; 82091398Stmm case 256: 82191398Stmm v = GEM_RING_SZ_256; 82291398Stmm break; 82391398Stmm case 512: 82491398Stmm v = GEM_RING_SZ_512; 82591398Stmm break; 82691398Stmm case 1024: 82791398Stmm v = GEM_RING_SZ_1024; 82891398Stmm break; 82991398Stmm case 2048: 83091398Stmm v = GEM_RING_SZ_2048; 83191398Stmm break; 83291398Stmm case 4096: 83391398Stmm v = GEM_RING_SZ_4096; 83491398Stmm break; 83591398Stmm case 8192: 83691398Stmm v = GEM_RING_SZ_8192; 83791398Stmm break; 83891398Stmm default: 83991398Stmm printf("gem: invalid Receive Descriptor ring size\n"); 84091398Stmm break; 84191398Stmm } 84291398Stmm return (v); 84391398Stmm} 84491398Stmm 84591398Stmm/* 84691398Stmm * Initialization of interface; set up initialization block 84791398Stmm * and transmit/receive descriptor rings. 84891398Stmm */ 84991398Stmmstatic void 85091398Stmmgem_init(xsc) 85191398Stmm void *xsc; 85291398Stmm{ 85391398Stmm struct gem_softc *sc = (struct gem_softc *)xsc; 85491398Stmm struct ifnet *ifp = &sc->sc_arpcom.ac_if; 85591398Stmm bus_space_tag_t t = sc->sc_bustag; 85691398Stmm bus_space_handle_t h = sc->sc_h; 85791398Stmm int s; 85891398Stmm u_int32_t v; 85991398Stmm 86091398Stmm s = splnet(); 86191398Stmm 862115030Stmm#ifdef GEM_DEBUG 86391398Stmm CTR1(KTR_GEM, "%s: gem_init: calling stop", device_get_name(sc->sc_dev)); 864115030Stmm#endif 86591398Stmm /* 86691398Stmm * Initialization sequence. The numbered steps below correspond 86791398Stmm * to the sequence outlined in section 6.3.5.1 in the Ethernet 86891398Stmm * Channel Engine manual (part of the PCIO manual). 86991398Stmm * See also the STP2002-STQ document from Sun Microsystems. 87091398Stmm */ 87191398Stmm 87291398Stmm /* step 1 & 2. Reset the Ethernet Channel */ 87391398Stmm gem_stop(&sc->sc_arpcom.ac_if, 0); 87491398Stmm gem_reset(sc); 875115030Stmm#ifdef GEM_DEBUG 87691398Stmm CTR1(KTR_GEM, "%s: gem_init: restarting", device_get_name(sc->sc_dev)); 877115030Stmm#endif 87891398Stmm 87991398Stmm /* Re-initialize the MIF */ 88091398Stmm gem_mifinit(sc); 88191398Stmm 88291398Stmm /* step 3. Setup data structures in host memory */ 88391398Stmm gem_meminit(sc); 88491398Stmm 88591398Stmm /* step 4. TX MAC registers & counters */ 88691398Stmm gem_init_regs(sc); 88791398Stmm /* XXX: VLAN code from NetBSD temporarily removed. */ 88891398Stmm bus_space_write_4(t, h, GEM_MAC_MAC_MAX_FRAME, 88991398Stmm (ETHER_MAX_LEN + sizeof(struct ether_header)) | (0x2000<<16)); 89091398Stmm 89191398Stmm /* step 5. RX MAC registers & counters */ 89291398Stmm gem_setladrf(sc); 89391398Stmm 89491398Stmm /* step 6 & 7. Program Descriptor Ring Base Addresses */ 89591398Stmm /* NOTE: we use only 32-bit DMA addresses here. */ 89691398Stmm bus_space_write_4(t, h, GEM_TX_RING_PTR_HI, 0); 89791398Stmm bus_space_write_4(t, h, GEM_TX_RING_PTR_LO, GEM_CDTXADDR(sc, 0)); 89891398Stmm 89991398Stmm bus_space_write_4(t, h, GEM_RX_RING_PTR_HI, 0); 90091398Stmm bus_space_write_4(t, h, GEM_RX_RING_PTR_LO, GEM_CDRXADDR(sc, 0)); 901115030Stmm#ifdef GEM_DEBUG 90291398Stmm CTR3(KTR_GEM, "loading rx ring %lx, tx ring %lx, cddma %lx", 90391398Stmm GEM_CDRXADDR(sc, 0), GEM_CDTXADDR(sc, 0), sc->sc_cddma); 904115030Stmm#endif 90591398Stmm 90691398Stmm /* step 8. Global Configuration & Interrupt Mask */ 90791398Stmm bus_space_write_4(t, h, GEM_INTMASK, 90891398Stmm ~(GEM_INTR_TX_INTME| 90991398Stmm GEM_INTR_TX_EMPTY| 91091398Stmm GEM_INTR_RX_DONE|GEM_INTR_RX_NOBUF| 91191398Stmm GEM_INTR_RX_TAG_ERR|GEM_INTR_PCS| 91291398Stmm GEM_INTR_MAC_CONTROL|GEM_INTR_MIF| 91391398Stmm GEM_INTR_BERR)); 91499726Sbenno bus_space_write_4(t, h, GEM_MAC_RX_MASK, 91599726Sbenno GEM_MAC_RX_DONE|GEM_MAC_RX_FRAME_CNT); 91691398Stmm bus_space_write_4(t, h, GEM_MAC_TX_MASK, 0xffff); /* XXXX */ 91791398Stmm bus_space_write_4(t, h, GEM_MAC_CONTROL_MASK, 0); /* XXXX */ 91891398Stmm 91991398Stmm /* step 9. ETX Configuration: use mostly default values */ 92091398Stmm 92191398Stmm /* Enable DMA */ 92291398Stmm v = gem_ringsize(GEM_NTXDESC /*XXX*/); 92391398Stmm bus_space_write_4(t, h, GEM_TX_CONFIG, 92491398Stmm v|GEM_TX_CONFIG_TXDMA_EN| 92591398Stmm ((0x400<<10)&GEM_TX_CONFIG_TXFIFO_TH)); 92691398Stmm 92791398Stmm /* step 10. ERX Configuration */ 92891398Stmm 92991398Stmm /* Encode Receive Descriptor ring size: four possible values */ 93091398Stmm v = gem_ringsize(GEM_NRXDESC /*XXX*/); 93191398Stmm 93291398Stmm /* Enable DMA */ 93391398Stmm bus_space_write_4(t, h, GEM_RX_CONFIG, 93491398Stmm v|(GEM_THRSH_1024<<GEM_RX_CONFIG_FIFO_THRS_SHIFT)| 93591398Stmm (2<<GEM_RX_CONFIG_FBOFF_SHFT)|GEM_RX_CONFIG_RXDMA_EN| 93691398Stmm (0<<GEM_RX_CONFIG_CXM_START_SHFT)); 93791398Stmm /* 93899726Sbenno * The following value is for an OFF Threshold of about 3/4 full 93999726Sbenno * and an ON Threshold of 1/4 full. 94091398Stmm */ 94199726Sbenno bus_space_write_4(t, h, GEM_RX_PAUSE_THRESH, 94299726Sbenno (3 * sc->sc_rxfifosize / 256) | 94399726Sbenno ( (sc->sc_rxfifosize / 256) << 12)); 94499726Sbenno bus_space_write_4(t, h, GEM_RX_BLANKING, (6<<12)|6); 94591398Stmm 94691398Stmm /* step 11. Configure Media */ 94799726Sbenno mii_mediachg(sc->sc_mii); 94891398Stmm 94991398Stmm /* step 12. RX_MAC Configuration Register */ 95091398Stmm v = bus_space_read_4(t, h, GEM_MAC_RX_CONFIG); 95191398Stmm v |= GEM_MAC_RX_ENABLE; 95291398Stmm bus_space_write_4(t, h, GEM_MAC_RX_CONFIG, v); 95391398Stmm 95491398Stmm /* step 14. Issue Transmit Pending command */ 95591398Stmm 95691398Stmm /* step 15. Give the reciever a swift kick */ 95791398Stmm bus_space_write_4(t, h, GEM_RX_KICK, GEM_NRXDESC-4); 95891398Stmm 95991398Stmm /* Start the one second timer. */ 96091398Stmm callout_reset(&sc->sc_tick_ch, hz, gem_tick, sc); 96191398Stmm 96291398Stmm ifp->if_flags |= IFF_RUNNING; 96391398Stmm ifp->if_flags &= ~IFF_OACTIVE; 96491398Stmm ifp->if_timer = 0; 96599726Sbenno sc->sc_ifflags = ifp->if_flags; 96691398Stmm splx(s); 96791398Stmm} 96891398Stmm 96991398Stmmstatic int 970108832Stmmgem_load_txmbuf(sc, m0) 97191398Stmm struct gem_softc *sc; 97291398Stmm struct mbuf *m0; 97391398Stmm{ 97491398Stmm struct gem_txdma txd; 97591398Stmm struct gem_txsoft *txs; 976108832Stmm int error; 97791398Stmm 978108832Stmm /* Get a work queue entry. */ 979108832Stmm if ((txs = STAILQ_FIRST(&sc->sc_txfreeq)) == NULL) { 980108832Stmm /* Ran out of descriptors. */ 981108832Stmm return (-1); 982108832Stmm } 98391398Stmm txd.txd_sc = sc; 984108832Stmm txd.txd_txs = txs; 985108832Stmm txs->txs_mbuf = m0; 986108832Stmm txs->txs_firstdesc = sc->sc_txnext; 987108832Stmm error = bus_dmamap_load_mbuf(sc->sc_tdmatag, txs->txs_dmamap, m0, 988108832Stmm gem_txdma_callback, &txd, BUS_DMA_NOWAIT); 989108832Stmm if (error != 0) 990108832Stmm goto fail; 991108832Stmm if (txs->txs_ndescs == -1) { 992108832Stmm error = -1; 993108832Stmm goto fail; 99491398Stmm } 99591398Stmm 996108832Stmm /* Sync the DMA map. */ 997108832Stmm bus_dmamap_sync(sc->sc_tdmatag, txs->txs_dmamap, 998108832Stmm BUS_DMASYNC_PREWRITE); 99991398Stmm 1000115030Stmm#ifdef GEM_DEBUG 1001108832Stmm CTR3(KTR_GEM, "load_mbuf: setting firstdesc=%d, lastdesc=%d, " 1002108832Stmm "ndescs=%d", txs->txs_firstdesc, txs->txs_lastdesc, 1003108832Stmm txs->txs_ndescs); 1004115030Stmm#endif 1005108832Stmm STAILQ_REMOVE_HEAD(&sc->sc_txfreeq, txs_q); 1006108832Stmm STAILQ_INSERT_TAIL(&sc->sc_txdirtyq, txs, txs_q); 100791398Stmm 1008108832Stmm sc->sc_txnext = GEM_NEXTTX(txs->txs_lastdesc); 1009108832Stmm sc->sc_txfree -= txs->txs_ndescs; 1010108832Stmm return (0); 101191398Stmm 1012108832Stmmfail: 1013115030Stmm#ifdef GEM_DEBUG 1014108832Stmm CTR1(KTR_GEM, "gem_load_txmbuf failed (%d)", error); 1015115030Stmm#endif 1016108832Stmm bus_dmamap_unload(sc->sc_tdmatag, txs->txs_dmamap); 1017108832Stmm return (error); 101891398Stmm} 101991398Stmm 102091398Stmmstatic void 102191398Stmmgem_init_regs(sc) 102291398Stmm struct gem_softc *sc; 102391398Stmm{ 102491398Stmm bus_space_tag_t t = sc->sc_bustag; 102591398Stmm bus_space_handle_t h = sc->sc_h; 102699726Sbenno const u_char *laddr = sc->sc_arpcom.ac_enaddr; 102799726Sbenno u_int32_t v; 102891398Stmm 102991398Stmm /* These regs are not cleared on reset */ 103091398Stmm if (!sc->sc_inited) { 103191398Stmm 103291398Stmm /* Wooo. Magic values. */ 103391398Stmm bus_space_write_4(t, h, GEM_MAC_IPG0, 0); 103491398Stmm bus_space_write_4(t, h, GEM_MAC_IPG1, 8); 103591398Stmm bus_space_write_4(t, h, GEM_MAC_IPG2, 4); 103691398Stmm 103791398Stmm bus_space_write_4(t, h, GEM_MAC_MAC_MIN_FRAME, ETHER_MIN_LEN); 103891398Stmm /* Max frame and max burst size */ 103991398Stmm bus_space_write_4(t, h, GEM_MAC_MAC_MAX_FRAME, 104099726Sbenno ETHER_MAX_LEN | (0x2000<<16)); 104199726Sbenno 104291398Stmm bus_space_write_4(t, h, GEM_MAC_PREAMBLE_LEN, 0x7); 104391398Stmm bus_space_write_4(t, h, GEM_MAC_JAM_SIZE, 0x4); 104491398Stmm bus_space_write_4(t, h, GEM_MAC_ATTEMPT_LIMIT, 0x10); 104591398Stmm /* Dunno.... */ 104691398Stmm bus_space_write_4(t, h, GEM_MAC_CONTROL_TYPE, 0x8088); 104791398Stmm bus_space_write_4(t, h, GEM_MAC_RANDOM_SEED, 104899726Sbenno ((laddr[5]<<8)|laddr[4])&0x3ff); 104999726Sbenno 105091398Stmm /* Secondary MAC addr set to 0:0:0:0:0:0 */ 105191398Stmm bus_space_write_4(t, h, GEM_MAC_ADDR3, 0); 105291398Stmm bus_space_write_4(t, h, GEM_MAC_ADDR4, 0); 105391398Stmm bus_space_write_4(t, h, GEM_MAC_ADDR5, 0); 105499726Sbenno 105599726Sbenno /* MAC control addr set to 01:80:c2:00:00:01 */ 105691398Stmm bus_space_write_4(t, h, GEM_MAC_ADDR6, 0x0001); 105791398Stmm bus_space_write_4(t, h, GEM_MAC_ADDR7, 0xc200); 105891398Stmm bus_space_write_4(t, h, GEM_MAC_ADDR8, 0x0180); 105991398Stmm 106091398Stmm /* MAC filter addr set to 0:0:0:0:0:0 */ 106191398Stmm bus_space_write_4(t, h, GEM_MAC_ADDR_FILTER0, 0); 106291398Stmm bus_space_write_4(t, h, GEM_MAC_ADDR_FILTER1, 0); 106391398Stmm bus_space_write_4(t, h, GEM_MAC_ADDR_FILTER2, 0); 106491398Stmm 106591398Stmm bus_space_write_4(t, h, GEM_MAC_ADR_FLT_MASK1_2, 0); 106691398Stmm bus_space_write_4(t, h, GEM_MAC_ADR_FLT_MASK0, 0); 106791398Stmm 106891398Stmm sc->sc_inited = 1; 106991398Stmm } 107091398Stmm 107191398Stmm /* Counters need to be zeroed */ 107291398Stmm bus_space_write_4(t, h, GEM_MAC_NORM_COLL_CNT, 0); 107391398Stmm bus_space_write_4(t, h, GEM_MAC_FIRST_COLL_CNT, 0); 107491398Stmm bus_space_write_4(t, h, GEM_MAC_EXCESS_COLL_CNT, 0); 107591398Stmm bus_space_write_4(t, h, GEM_MAC_LATE_COLL_CNT, 0); 107691398Stmm bus_space_write_4(t, h, GEM_MAC_DEFER_TMR_CNT, 0); 107791398Stmm bus_space_write_4(t, h, GEM_MAC_PEAK_ATTEMPTS, 0); 107891398Stmm bus_space_write_4(t, h, GEM_MAC_RX_FRAME_COUNT, 0); 107991398Stmm bus_space_write_4(t, h, GEM_MAC_RX_LEN_ERR_CNT, 0); 108091398Stmm bus_space_write_4(t, h, GEM_MAC_RX_ALIGN_ERR, 0); 108191398Stmm bus_space_write_4(t, h, GEM_MAC_RX_CRC_ERR_CNT, 0); 108291398Stmm bus_space_write_4(t, h, GEM_MAC_RX_CODE_VIOL, 0); 108391398Stmm 108491398Stmm /* Un-pause stuff */ 108591398Stmm#if 0 108691398Stmm bus_space_write_4(t, h, GEM_MAC_SEND_PAUSE_CMD, 0x1BF0); 108791398Stmm#else 108891398Stmm bus_space_write_4(t, h, GEM_MAC_SEND_PAUSE_CMD, 0); 108991398Stmm#endif 109091398Stmm 109191398Stmm /* 109291398Stmm * Set the station address. 109391398Stmm */ 109499726Sbenno bus_space_write_4(t, h, GEM_MAC_ADDR0, (laddr[4]<<8)|laddr[5]); 109599726Sbenno bus_space_write_4(t, h, GEM_MAC_ADDR1, (laddr[2]<<8)|laddr[3]); 109699726Sbenno bus_space_write_4(t, h, GEM_MAC_ADDR2, (laddr[0]<<8)|laddr[1]); 109799726Sbenno 109899726Sbenno /* 109999726Sbenno * Enable MII outputs. Enable GMII if there is a gigabit PHY. 110099726Sbenno */ 110199726Sbenno sc->sc_mif_config = bus_space_read_4(t, h, GEM_MIF_CONFIG); 110299726Sbenno v = GEM_MAC_XIF_TX_MII_ENA; 110399726Sbenno if (sc->sc_mif_config & GEM_MIF_CONFIG_MDI1) { 110499726Sbenno v |= GEM_MAC_XIF_FDPLX_LED; 110599726Sbenno if (sc->sc_flags & GEM_GIGABIT) 110699726Sbenno v |= GEM_MAC_XIF_GMII_MODE; 110799726Sbenno } 110899726Sbenno bus_space_write_4(t, h, GEM_MAC_XIF_CONFIG, v); 110991398Stmm} 111091398Stmm 111191398Stmmstatic void 111291398Stmmgem_start(ifp) 111391398Stmm struct ifnet *ifp; 111491398Stmm{ 111591398Stmm struct gem_softc *sc = (struct gem_softc *)ifp->if_softc; 1116108832Stmm struct mbuf *m0 = NULL; 1117115030Stmm int firsttx, ntx = 0, ofree, txmfail; 111891398Stmm 111991398Stmm if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING) 112091398Stmm return; 112191398Stmm 112291398Stmm /* 112391398Stmm * Remember the previous number of free descriptors and 112491398Stmm * the first descriptor we'll use. 112591398Stmm */ 112691398Stmm ofree = sc->sc_txfree; 112791398Stmm firsttx = sc->sc_txnext; 112891398Stmm 1129115030Stmm#ifdef GEM_DEBUG 113091398Stmm CTR3(KTR_GEM, "%s: gem_start: txfree %d, txnext %d", 113191398Stmm device_get_name(sc->sc_dev), ofree, firsttx); 1132115030Stmm#endif 113391398Stmm 113491398Stmm /* 113591398Stmm * Loop through the send queue, setting up transmit descriptors 113691398Stmm * until we drain the queue, or use up all available transmit 113791398Stmm * descriptors. 113891398Stmm */ 113991398Stmm txmfail = 0; 1140115030Stmm do { 114191398Stmm /* 114291398Stmm * Grab a packet off the queue. 114391398Stmm */ 114491398Stmm IF_DEQUEUE(&ifp->if_snd, m0); 114591398Stmm if (m0 == NULL) 114691398Stmm break; 114791398Stmm 1148108832Stmm txmfail = gem_load_txmbuf(sc, m0); 114991398Stmm if (txmfail > 0) { 1150108832Stmm /* Drop the mbuf and complain. */ 1151108832Stmm printf("gem_start: error %d while loading mbuf dma " 1152108832Stmm "map\n", txmfail); 1153108832Stmm continue; 115491398Stmm } 1155108832Stmm /* Not enough descriptors. */ 1156108832Stmm if (txmfail == -1) { 1157108832Stmm if (sc->sc_txfree == GEM_MAXTXFREE) 1158108832Stmm panic("gem_start: mbuf chain too long!"); 115991398Stmm IF_PREPEND(&ifp->if_snd, m0); 116091398Stmm break; 116191398Stmm } 116291398Stmm 1163115030Stmm ntx++; 1164108832Stmm /* Kick the transmitter. */ 1165115030Stmm#ifdef GEM_DEBUG 1166108832Stmm CTR2(KTR_GEM, "%s: gem_start: kicking tx %d", 1167108832Stmm device_get_name(sc->sc_dev), sc->sc_txnext); 1168115030Stmm#endif 1169108832Stmm bus_space_write_4(sc->sc_bustag, sc->sc_h, GEM_TX_KICK, 1170108832Stmm sc->sc_txnext); 1171108832Stmm 1172105982Stmm if (ifp->if_bpf != NULL) 1173106950Smux bpf_mtap(ifp->if_bpf, m0); 1174115030Stmm } while (1); 117591398Stmm 117691398Stmm if (txmfail == -1 || sc->sc_txfree == 0) { 1177108832Stmm /* No more slots left; notify upper layer. */ 117891398Stmm ifp->if_flags |= IFF_OACTIVE; 117991398Stmm } 118091398Stmm 118191398Stmm if (ntx > 0) { 1182109648Stmm GEM_CDSYNC(sc, BUS_DMASYNC_PREWRITE); 1183109648Stmm 1184115030Stmm#ifdef GEM_DEBUG 1185108832Stmm CTR2(KTR_GEM, "%s: packets enqueued, OWN on %d", 1186108832Stmm device_get_name(sc->sc_dev), firsttx); 1187115030Stmm#endif 118891398Stmm 118991398Stmm /* Set a watchdog timer in case the chip flakes out. */ 119091398Stmm ifp->if_timer = 5; 1191115030Stmm#ifdef GEM_DEBUG 119291398Stmm CTR2(KTR_GEM, "%s: gem_start: watchdog %d", 119391398Stmm device_get_name(sc->sc_dev), ifp->if_timer); 1194115030Stmm#endif 119591398Stmm } 119691398Stmm} 119791398Stmm 119891398Stmm/* 119991398Stmm * Transmit interrupt. 120091398Stmm */ 120191398Stmmstatic void 120291398Stmmgem_tint(sc) 120391398Stmm struct gem_softc *sc; 120491398Stmm{ 120591398Stmm struct ifnet *ifp = &sc->sc_arpcom.ac_if; 120691398Stmm bus_space_tag_t t = sc->sc_bustag; 120791398Stmm bus_space_handle_t mac = sc->sc_h; 120891398Stmm struct gem_txsoft *txs; 120991398Stmm int txlast; 121099726Sbenno int progress = 0; 121191398Stmm 121291398Stmm 1213115030Stmm#ifdef GEM_DEBUG 121491398Stmm CTR1(KTR_GEM, "%s: gem_tint", device_get_name(sc->sc_dev)); 1215115030Stmm#endif 121691398Stmm 121791398Stmm /* 121891398Stmm * Unload collision counters 121991398Stmm */ 122091398Stmm ifp->if_collisions += 122191398Stmm bus_space_read_4(t, mac, GEM_MAC_NORM_COLL_CNT) + 122291398Stmm bus_space_read_4(t, mac, GEM_MAC_FIRST_COLL_CNT) + 122391398Stmm bus_space_read_4(t, mac, GEM_MAC_EXCESS_COLL_CNT) + 122491398Stmm bus_space_read_4(t, mac, GEM_MAC_LATE_COLL_CNT); 122591398Stmm 122691398Stmm /* 122791398Stmm * then clear the hardware counters. 122891398Stmm */ 122991398Stmm bus_space_write_4(t, mac, GEM_MAC_NORM_COLL_CNT, 0); 123091398Stmm bus_space_write_4(t, mac, GEM_MAC_FIRST_COLL_CNT, 0); 123191398Stmm bus_space_write_4(t, mac, GEM_MAC_EXCESS_COLL_CNT, 0); 123291398Stmm bus_space_write_4(t, mac, GEM_MAC_LATE_COLL_CNT, 0); 123391398Stmm 123491398Stmm /* 123591398Stmm * Go through our Tx list and free mbufs for those 123691398Stmm * frames that have been transmitted. 123791398Stmm */ 1238109648Stmm GEM_CDSYNC(sc, BUS_DMASYNC_POSTREAD); 123991398Stmm while ((txs = STAILQ_FIRST(&sc->sc_txdirtyq)) != NULL) { 124091398Stmm 124191398Stmm#ifdef GEM_DEBUG 124291398Stmm if (ifp->if_flags & IFF_DEBUG) { 124391398Stmm int i; 124491398Stmm printf(" txsoft %p transmit chain:\n", txs); 124591398Stmm for (i = txs->txs_firstdesc;; i = GEM_NEXTTX(i)) { 124691398Stmm printf("descriptor %d: ", i); 124791398Stmm printf("gd_flags: 0x%016llx\t", (long long) 124891398Stmm GEM_DMA_READ(sc, sc->sc_txdescs[i].gd_flags)); 124991398Stmm printf("gd_addr: 0x%016llx\n", (long long) 125091398Stmm GEM_DMA_READ(sc, sc->sc_txdescs[i].gd_addr)); 125191398Stmm if (i == txs->txs_lastdesc) 125291398Stmm break; 125391398Stmm } 125491398Stmm } 125591398Stmm#endif 125691398Stmm 125791398Stmm /* 125891398Stmm * In theory, we could harveast some descriptors before 125991398Stmm * the ring is empty, but that's a bit complicated. 126091398Stmm * 126191398Stmm * GEM_TX_COMPLETION points to the last descriptor 126291398Stmm * processed +1. 126391398Stmm */ 126491398Stmm txlast = bus_space_read_4(t, mac, GEM_TX_COMPLETION); 1265115030Stmm#ifdef GEM_DEBUG 126691398Stmm CTR3(KTR_GEM, "gem_tint: txs->txs_firstdesc = %d, " 126791398Stmm "txs->txs_lastdesc = %d, txlast = %d", 126891398Stmm txs->txs_firstdesc, txs->txs_lastdesc, txlast); 1269115030Stmm#endif 127091398Stmm if (txs->txs_firstdesc <= txs->txs_lastdesc) { 127191398Stmm if ((txlast >= txs->txs_firstdesc) && 127291398Stmm (txlast <= txs->txs_lastdesc)) 127391398Stmm break; 127491398Stmm } else { 127591398Stmm /* Ick -- this command wraps */ 127691398Stmm if ((txlast >= txs->txs_firstdesc) || 127791398Stmm (txlast <= txs->txs_lastdesc)) 127891398Stmm break; 127991398Stmm } 128091398Stmm 1281115030Stmm#ifdef GEM_DEBUG 128291398Stmm CTR0(KTR_GEM, "gem_tint: releasing a desc"); 1283115030Stmm#endif 128491398Stmm STAILQ_REMOVE_HEAD(&sc->sc_txdirtyq, txs_q); 128591398Stmm 128691398Stmm sc->sc_txfree += txs->txs_ndescs; 128791398Stmm 1288108832Stmm bus_dmamap_sync(sc->sc_tdmatag, txs->txs_dmamap, 128991398Stmm BUS_DMASYNC_POSTWRITE); 1290108832Stmm bus_dmamap_unload(sc->sc_tdmatag, txs->txs_dmamap); 129191398Stmm if (txs->txs_mbuf != NULL) { 129291398Stmm m_freem(txs->txs_mbuf); 129391398Stmm txs->txs_mbuf = NULL; 129491398Stmm } 129591398Stmm 129691398Stmm STAILQ_INSERT_TAIL(&sc->sc_txfreeq, txs, txs_q); 129791398Stmm 129891398Stmm ifp->if_opackets++; 129999726Sbenno progress = 1; 130091398Stmm } 130191398Stmm 1302115030Stmm#ifdef GEM_DEBUG 130391398Stmm CTR3(KTR_GEM, "gem_tint: GEM_TX_STATE_MACHINE %x " 130491398Stmm "GEM_TX_DATA_PTR %llx " 130591398Stmm "GEM_TX_COMPLETION %x", 130691398Stmm bus_space_read_4(sc->sc_bustag, sc->sc_h, GEM_TX_STATE_MACHINE), 130791398Stmm ((long long) bus_space_read_4(sc->sc_bustag, sc->sc_h, 130891398Stmm GEM_TX_DATA_PTR_HI) << 32) | 130991398Stmm bus_space_read_4(sc->sc_bustag, sc->sc_h, 131091398Stmm GEM_TX_DATA_PTR_LO), 131191398Stmm bus_space_read_4(sc->sc_bustag, sc->sc_h, GEM_TX_COMPLETION)); 1312115030Stmm#endif 131391398Stmm 131499726Sbenno if (progress) { 131599726Sbenno if (sc->sc_txfree == GEM_NTXDESC - 1) 131699726Sbenno sc->sc_txwin = 0; 131791398Stmm 131899726Sbenno /* Freed some descriptors, so reset IFF_OACTIVE and restart. */ 131999726Sbenno ifp->if_flags &= ~IFF_OACTIVE; 132099726Sbenno gem_start(ifp); 132191398Stmm 132299726Sbenno if (STAILQ_EMPTY(&sc->sc_txdirtyq)) 132399726Sbenno ifp->if_timer = 0; 132499726Sbenno } 132599726Sbenno 1326115030Stmm#ifdef GEM_DEBUG 132791398Stmm CTR2(KTR_GEM, "%s: gem_tint: watchdog %d", 132891398Stmm device_get_name(sc->sc_dev), ifp->if_timer); 1329115030Stmm#endif 133091398Stmm} 133191398Stmm 1332100587Sjake#if 0 133393045Stmmstatic void 133493045Stmmgem_rint_timeout(arg) 133593045Stmm void *arg; 133693045Stmm{ 133793045Stmm 133893045Stmm gem_rint((struct gem_softc *)arg); 133993045Stmm} 1340100587Sjake#endif 134193045Stmm 134291398Stmm/* 134391398Stmm * Receive interrupt. 134491398Stmm */ 134591398Stmmstatic void 134691398Stmmgem_rint(sc) 134791398Stmm struct gem_softc *sc; 134891398Stmm{ 134991398Stmm struct ifnet *ifp = &sc->sc_arpcom.ac_if; 135091398Stmm bus_space_tag_t t = sc->sc_bustag; 135191398Stmm bus_space_handle_t h = sc->sc_h; 135291398Stmm struct gem_rxsoft *rxs; 135391398Stmm struct mbuf *m; 135491398Stmm u_int64_t rxstat; 135599726Sbenno u_int32_t rxcomp; 135699726Sbenno int i, len, progress = 0; 135791398Stmm 135893045Stmm callout_stop(&sc->sc_rx_ch); 1359115030Stmm#ifdef GEM_DEBUG 136091398Stmm CTR1(KTR_GEM, "%s: gem_rint", device_get_name(sc->sc_dev)); 1361115030Stmm#endif 136299726Sbenno 136391398Stmm /* 136499726Sbenno * Read the completion register once. This limits 136599726Sbenno * how long the following loop can execute. 136699726Sbenno */ 136799726Sbenno rxcomp = bus_space_read_4(t, h, GEM_RX_COMPLETION); 136899726Sbenno 1369115030Stmm#ifdef GEM_DEBUG 137091398Stmm CTR2(KTR_GEM, "gem_rint: sc->rxptr %d, complete %d", 137199726Sbenno sc->sc_rxptr, rxcomp); 1372115030Stmm#endif 1373109648Stmm GEM_CDSYNC(sc, BUS_DMASYNC_POSTREAD); 137499726Sbenno for (i = sc->sc_rxptr; i != rxcomp; 137591398Stmm i = GEM_NEXTRX(i)) { 137691398Stmm rxs = &sc->sc_rxsoft[i]; 137791398Stmm 137891398Stmm rxstat = GEM_DMA_READ(sc, sc->sc_rxdescs[i].gd_flags); 137991398Stmm 138091398Stmm if (rxstat & GEM_RD_OWN) { 138199726Sbenno#if 0 /* XXX: In case of emergency, re-enable this. */ 138291398Stmm /* 138393045Stmm * The descriptor is still marked as owned, although 138493045Stmm * it is supposed to have completed. This has been 138593045Stmm * observed on some machines. Just exiting here 138693045Stmm * might leave the packet sitting around until another 138793045Stmm * one arrives to trigger a new interrupt, which is 138893045Stmm * generally undesirable, so set up a timeout. 138991398Stmm */ 139093045Stmm callout_reset(&sc->sc_rx_ch, GEM_RXOWN_TICKS, 139193045Stmm gem_rint_timeout, sc); 139299726Sbenno#endif 139391398Stmm break; 139491398Stmm } 139591398Stmm 139699726Sbenno progress++; 139799726Sbenno ifp->if_ipackets++; 139899726Sbenno 139991398Stmm if (rxstat & GEM_RD_BAD_CRC) { 140099726Sbenno ifp->if_ierrors++; 140191398Stmm device_printf(sc->sc_dev, "receive error: CRC error\n"); 140291398Stmm GEM_INIT_RXDESC(sc, i); 140391398Stmm continue; 140491398Stmm } 140591398Stmm 140691398Stmm#ifdef GEM_DEBUG 140791398Stmm if (ifp->if_flags & IFF_DEBUG) { 140891398Stmm printf(" rxsoft %p descriptor %d: ", rxs, i); 140991398Stmm printf("gd_flags: 0x%016llx\t", (long long) 141091398Stmm GEM_DMA_READ(sc, sc->sc_rxdescs[i].gd_flags)); 141191398Stmm printf("gd_addr: 0x%016llx\n", (long long) 141291398Stmm GEM_DMA_READ(sc, sc->sc_rxdescs[i].gd_addr)); 141391398Stmm } 141491398Stmm#endif 141591398Stmm 141691398Stmm /* 141791398Stmm * No errors; receive the packet. Note the Gem 141891398Stmm * includes the CRC with every packet. 141991398Stmm */ 142091398Stmm len = GEM_RD_BUFLEN(rxstat); 142191398Stmm 142291398Stmm /* 142391398Stmm * Allocate a new mbuf cluster. If that fails, we are 142491398Stmm * out of memory, and must drop the packet and recycle 142591398Stmm * the buffer that's already attached to this descriptor. 142691398Stmm */ 142791398Stmm m = rxs->rxs_mbuf; 142891398Stmm if (gem_add_rxbuf(sc, i) != 0) { 142991398Stmm ifp->if_ierrors++; 143091398Stmm GEM_INIT_RXDESC(sc, i); 143191398Stmm continue; 143291398Stmm } 143391398Stmm m->m_data += 2; /* We're already off by two */ 143491398Stmm 143591398Stmm m->m_pkthdr.rcvif = ifp; 143691398Stmm m->m_pkthdr.len = m->m_len = len - ETHER_CRC_LEN; 143791398Stmm 143891398Stmm /* Pass it on. */ 1439106937Ssam (*ifp->if_input)(ifp, m); 144091398Stmm } 144191398Stmm 144299726Sbenno if (progress) { 1443109648Stmm GEM_CDSYNC(sc, BUS_DMASYNC_PREWRITE); 144499726Sbenno /* Update the receive pointer. */ 144599726Sbenno if (i == sc->sc_rxptr) { 144699726Sbenno device_printf(sc->sc_dev, "rint: ring wrap\n"); 144799726Sbenno } 144899726Sbenno sc->sc_rxptr = i; 144999726Sbenno bus_space_write_4(t, h, GEM_RX_KICK, GEM_PREVRX(i)); 145099726Sbenno } 145191398Stmm 1452115030Stmm#ifdef GEM_DEBUG 145391398Stmm CTR2(KTR_GEM, "gem_rint: done sc->rxptr %d, complete %d", 145491398Stmm sc->sc_rxptr, bus_space_read_4(t, h, GEM_RX_COMPLETION)); 1455115030Stmm#endif 145691398Stmm} 145791398Stmm 145891398Stmm 145991398Stmm/* 146091398Stmm * gem_add_rxbuf: 146191398Stmm * 146291398Stmm * Add a receive buffer to the indicated descriptor. 146391398Stmm */ 146491398Stmmstatic int 146591398Stmmgem_add_rxbuf(sc, idx) 146691398Stmm struct gem_softc *sc; 146791398Stmm int idx; 146891398Stmm{ 146991398Stmm struct gem_rxsoft *rxs = &sc->sc_rxsoft[idx]; 147091398Stmm struct mbuf *m; 147191398Stmm int error; 147291398Stmm 1473111119Simp m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); 147491398Stmm if (m == NULL) 147591398Stmm return (ENOBUFS); 1476108832Stmm m->m_len = m->m_pkthdr.len = m->m_ext.ext_size; 147791398Stmm 147891398Stmm#ifdef GEM_DEBUG 147991398Stmm /* bzero the packet to check dma */ 148091398Stmm memset(m->m_ext.ext_buf, 0, m->m_ext.ext_size); 148191398Stmm#endif 148291398Stmm 1483109648Stmm if (rxs->rxs_mbuf != NULL) { 1484109648Stmm bus_dmamap_sync(sc->sc_rdmatag, rxs->rxs_dmamap, 1485109648Stmm BUS_DMASYNC_POSTREAD); 1486108832Stmm bus_dmamap_unload(sc->sc_rdmatag, rxs->rxs_dmamap); 1487109648Stmm } 148891398Stmm 148991398Stmm rxs->rxs_mbuf = m; 149091398Stmm 1491108832Stmm error = bus_dmamap_load_mbuf(sc->sc_rdmatag, rxs->rxs_dmamap, 1492108832Stmm m, gem_rxdma_callback, rxs, BUS_DMA_NOWAIT); 149391398Stmm if (error != 0 || rxs->rxs_paddr == 0) { 149491398Stmm device_printf(sc->sc_dev, "can't load rx DMA map %d, error = " 149591398Stmm "%d\n", idx, error); 149691398Stmm panic("gem_add_rxbuf"); /* XXX */ 149791398Stmm } 149891398Stmm 1499108832Stmm bus_dmamap_sync(sc->sc_rdmatag, rxs->rxs_dmamap, BUS_DMASYNC_PREREAD); 150091398Stmm 150191398Stmm GEM_INIT_RXDESC(sc, idx); 150291398Stmm 150391398Stmm return (0); 150491398Stmm} 150591398Stmm 150691398Stmm 150791398Stmmstatic void 150891398Stmmgem_eint(sc, status) 150991398Stmm struct gem_softc *sc; 151091398Stmm u_int status; 151191398Stmm{ 151291398Stmm 151391398Stmm if ((status & GEM_INTR_MIF) != 0) { 151491398Stmm device_printf(sc->sc_dev, "XXXlink status changed\n"); 151591398Stmm return; 151691398Stmm } 151791398Stmm 151891398Stmm device_printf(sc->sc_dev, "status=%x\n", status); 151991398Stmm} 152091398Stmm 152191398Stmm 152291398Stmmvoid 152391398Stmmgem_intr(v) 152491398Stmm void *v; 152591398Stmm{ 152691398Stmm struct gem_softc *sc = (struct gem_softc *)v; 152791398Stmm bus_space_tag_t t = sc->sc_bustag; 152891398Stmm bus_space_handle_t seb = sc->sc_h; 152991398Stmm u_int32_t status; 153091398Stmm 153191398Stmm status = bus_space_read_4(t, seb, GEM_STATUS); 1532115030Stmm#ifdef GEM_DEBUG 153391398Stmm CTR3(KTR_GEM, "%s: gem_intr: cplt %x, status %x", 153491398Stmm device_get_name(sc->sc_dev), (status>>19), 153591398Stmm (u_int)status); 1536115030Stmm#endif 153791398Stmm 153891398Stmm if ((status & (GEM_INTR_RX_TAG_ERR | GEM_INTR_BERR)) != 0) 153991398Stmm gem_eint(sc, status); 154091398Stmm 154191398Stmm if ((status & (GEM_INTR_TX_EMPTY | GEM_INTR_TX_INTME)) != 0) 154291398Stmm gem_tint(sc); 154391398Stmm 154491398Stmm if ((status & (GEM_INTR_RX_DONE | GEM_INTR_RX_NOBUF)) != 0) 154591398Stmm gem_rint(sc); 154691398Stmm 154791398Stmm /* We should eventually do more than just print out error stats. */ 154891398Stmm if (status & GEM_INTR_TX_MAC) { 154991398Stmm int txstat = bus_space_read_4(t, seb, GEM_MAC_TX_STATUS); 155091398Stmm if (txstat & ~GEM_MAC_TX_XMIT_DONE) 155199726Sbenno device_printf(sc->sc_dev, "MAC tx fault, status %x\n", 155299726Sbenno txstat); 155397240Stmm if (txstat & (GEM_MAC_TX_UNDERRUN | GEM_MAC_TX_PKT_TOO_LONG)) 155497240Stmm gem_init(sc); 155591398Stmm } 155691398Stmm if (status & GEM_INTR_RX_MAC) { 155791398Stmm int rxstat = bus_space_read_4(t, seb, GEM_MAC_RX_STATUS); 155891398Stmm if (rxstat & ~(GEM_MAC_RX_DONE | GEM_MAC_RX_FRAME_CNT)) 155999726Sbenno device_printf(sc->sc_dev, "MAC rx fault, status %x\n", 156099726Sbenno rxstat); 156197240Stmm if ((rxstat & GEM_MAC_RX_OVERFLOW) != 0) 156297240Stmm gem_init(sc); 156391398Stmm } 156491398Stmm} 156591398Stmm 156691398Stmm 156791398Stmmstatic void 156891398Stmmgem_watchdog(ifp) 156991398Stmm struct ifnet *ifp; 157091398Stmm{ 157191398Stmm struct gem_softc *sc = ifp->if_softc; 157291398Stmm 1573115030Stmm#ifdef GEM_DEBUG 157491398Stmm CTR3(KTR_GEM, "gem_watchdog: GEM_RX_CONFIG %x GEM_MAC_RX_STATUS %x " 157591398Stmm "GEM_MAC_RX_CONFIG %x", 157691398Stmm bus_space_read_4(sc->sc_bustag, sc->sc_h, GEM_RX_CONFIG), 157791398Stmm bus_space_read_4(sc->sc_bustag, sc->sc_h, GEM_MAC_RX_STATUS), 157891398Stmm bus_space_read_4(sc->sc_bustag, sc->sc_h, GEM_MAC_RX_CONFIG)); 157991398Stmm CTR3(KTR_GEM, "gem_watchdog: GEM_TX_CONFIG %x GEM_MAC_TX_STATUS %x " 158091398Stmm "GEM_MAC_TX_CONFIG %x", 158191398Stmm bus_space_read_4(sc->sc_bustag, sc->sc_h, GEM_TX_CONFIG), 158291398Stmm bus_space_read_4(sc->sc_bustag, sc->sc_h, GEM_MAC_TX_STATUS), 158391398Stmm bus_space_read_4(sc->sc_bustag, sc->sc_h, GEM_MAC_TX_CONFIG)); 1584115030Stmm#endif 158591398Stmm 158691398Stmm device_printf(sc->sc_dev, "device timeout\n"); 158791398Stmm ++ifp->if_oerrors; 158891398Stmm 158991398Stmm /* Try to get more packets going. */ 159091398Stmm gem_start(ifp); 159191398Stmm} 159291398Stmm 159391398Stmm/* 159491398Stmm * Initialize the MII Management Interface 159591398Stmm */ 159691398Stmmstatic void 159791398Stmmgem_mifinit(sc) 159891398Stmm struct gem_softc *sc; 159991398Stmm{ 160091398Stmm bus_space_tag_t t = sc->sc_bustag; 160191398Stmm bus_space_handle_t mif = sc->sc_h; 160291398Stmm 160391398Stmm /* Configure the MIF in frame mode */ 160491398Stmm sc->sc_mif_config = bus_space_read_4(t, mif, GEM_MIF_CONFIG); 160591398Stmm sc->sc_mif_config &= ~GEM_MIF_CONFIG_BB_ENA; 160691398Stmm bus_space_write_4(t, mif, GEM_MIF_CONFIG, sc->sc_mif_config); 160791398Stmm} 160891398Stmm 160991398Stmm/* 161091398Stmm * MII interface 161191398Stmm * 161291398Stmm * The GEM MII interface supports at least three different operating modes: 161391398Stmm * 161491398Stmm * Bitbang mode is implemented using data, clock and output enable registers. 161591398Stmm * 161691398Stmm * Frame mode is implemented by loading a complete frame into the frame 161791398Stmm * register and polling the valid bit for completion. 161891398Stmm * 161991398Stmm * Polling mode uses the frame register but completion is indicated by 162091398Stmm * an interrupt. 162191398Stmm * 162291398Stmm */ 162391398Stmmint 162491398Stmmgem_mii_readreg(dev, phy, reg) 162591398Stmm device_t dev; 162691398Stmm int phy, reg; 162791398Stmm{ 162891398Stmm struct gem_softc *sc = device_get_softc(dev); 162991398Stmm bus_space_tag_t t = sc->sc_bustag; 163091398Stmm bus_space_handle_t mif = sc->sc_h; 163191398Stmm int n; 163291398Stmm u_int32_t v; 163391398Stmm 163491398Stmm#ifdef GEM_DEBUG_PHY 163591398Stmm printf("gem_mii_readreg: phy %d reg %d\n", phy, reg); 163691398Stmm#endif 163791398Stmm 163891398Stmm#if 0 163991398Stmm /* Select the desired PHY in the MIF configuration register */ 164091398Stmm v = bus_space_read_4(t, mif, GEM_MIF_CONFIG); 164191398Stmm /* Clear PHY select bit */ 164291398Stmm v &= ~GEM_MIF_CONFIG_PHY_SEL; 164391398Stmm if (phy == GEM_PHYAD_EXTERNAL) 164491398Stmm /* Set PHY select bit to get at external device */ 164591398Stmm v |= GEM_MIF_CONFIG_PHY_SEL; 164691398Stmm bus_space_write_4(t, mif, GEM_MIF_CONFIG, v); 164791398Stmm#endif 164891398Stmm 164991398Stmm /* Construct the frame command */ 165091398Stmm v = (reg << GEM_MIF_REG_SHIFT) | (phy << GEM_MIF_PHY_SHIFT) | 165191398Stmm GEM_MIF_FRAME_READ; 165291398Stmm 165391398Stmm bus_space_write_4(t, mif, GEM_MIF_FRAME, v); 165491398Stmm for (n = 0; n < 100; n++) { 165591398Stmm DELAY(1); 165691398Stmm v = bus_space_read_4(t, mif, GEM_MIF_FRAME); 165791398Stmm if (v & GEM_MIF_FRAME_TA0) 165891398Stmm return (v & GEM_MIF_FRAME_DATA); 165991398Stmm } 166091398Stmm 166191398Stmm device_printf(sc->sc_dev, "mii_read timeout\n"); 166291398Stmm return (0); 166391398Stmm} 166491398Stmm 166591398Stmmint 166691398Stmmgem_mii_writereg(dev, phy, reg, val) 166791398Stmm device_t dev; 166891398Stmm int phy, reg, val; 166991398Stmm{ 167091398Stmm struct gem_softc *sc = device_get_softc(dev); 167191398Stmm bus_space_tag_t t = sc->sc_bustag; 167291398Stmm bus_space_handle_t mif = sc->sc_h; 167391398Stmm int n; 167491398Stmm u_int32_t v; 167591398Stmm 167691398Stmm#ifdef GEM_DEBUG_PHY 167791398Stmm printf("gem_mii_writereg: phy %d reg %d val %x\n", phy, reg, val); 167891398Stmm#endif 167991398Stmm 168091398Stmm#if 0 168191398Stmm /* Select the desired PHY in the MIF configuration register */ 168291398Stmm v = bus_space_read_4(t, mif, GEM_MIF_CONFIG); 168391398Stmm /* Clear PHY select bit */ 168491398Stmm v &= ~GEM_MIF_CONFIG_PHY_SEL; 168591398Stmm if (phy == GEM_PHYAD_EXTERNAL) 168691398Stmm /* Set PHY select bit to get at external device */ 168791398Stmm v |= GEM_MIF_CONFIG_PHY_SEL; 168891398Stmm bus_space_write_4(t, mif, GEM_MIF_CONFIG, v); 168991398Stmm#endif 169091398Stmm /* Construct the frame command */ 169191398Stmm v = GEM_MIF_FRAME_WRITE | 169291398Stmm (phy << GEM_MIF_PHY_SHIFT) | 169391398Stmm (reg << GEM_MIF_REG_SHIFT) | 169491398Stmm (val & GEM_MIF_FRAME_DATA); 169591398Stmm 169691398Stmm bus_space_write_4(t, mif, GEM_MIF_FRAME, v); 169791398Stmm for (n = 0; n < 100; n++) { 169891398Stmm DELAY(1); 169991398Stmm v = bus_space_read_4(t, mif, GEM_MIF_FRAME); 170091398Stmm if (v & GEM_MIF_FRAME_TA0) 170191398Stmm return (1); 170291398Stmm } 170391398Stmm 170491398Stmm device_printf(sc->sc_dev, "mii_write timeout\n"); 170591398Stmm return (0); 170691398Stmm} 170791398Stmm 170891398Stmmvoid 170991398Stmmgem_mii_statchg(dev) 171091398Stmm device_t dev; 171191398Stmm{ 171291398Stmm struct gem_softc *sc = device_get_softc(dev); 171391398Stmm#ifdef GEM_DEBUG 171491398Stmm int instance = IFM_INST(sc->sc_mii->mii_media.ifm_cur->ifm_media); 171591398Stmm#endif 171691398Stmm bus_space_tag_t t = sc->sc_bustag; 171791398Stmm bus_space_handle_t mac = sc->sc_h; 171891398Stmm u_int32_t v; 171991398Stmm 172091398Stmm#ifdef GEM_DEBUG 172191398Stmm if (sc->sc_debug) 172291398Stmm printf("gem_mii_statchg: status change: phy = %d\n", 172391398Stmm sc->sc_phys[instance]); 172491398Stmm#endif 172591398Stmm 172691398Stmm /* Set tx full duplex options */ 172791398Stmm bus_space_write_4(t, mac, GEM_MAC_TX_CONFIG, 0); 172891398Stmm DELAY(10000); /* reg must be cleared and delay before changing. */ 172991398Stmm v = GEM_MAC_TX_ENA_IPG0|GEM_MAC_TX_NGU|GEM_MAC_TX_NGU_LIMIT| 173091398Stmm GEM_MAC_TX_ENABLE; 173191398Stmm if ((IFM_OPTIONS(sc->sc_mii->mii_media_active) & IFM_FDX) != 0) { 173291398Stmm v |= GEM_MAC_TX_IGN_CARRIER|GEM_MAC_TX_IGN_COLLIS; 173391398Stmm } 173491398Stmm bus_space_write_4(t, mac, GEM_MAC_TX_CONFIG, v); 173591398Stmm 173691398Stmm /* XIF Configuration */ 173791398Stmm /* We should really calculate all this rather than rely on defaults */ 173891398Stmm v = bus_space_read_4(t, mac, GEM_MAC_XIF_CONFIG); 173991398Stmm v = GEM_MAC_XIF_LINK_LED; 174091398Stmm v |= GEM_MAC_XIF_TX_MII_ENA; 174199726Sbenno 174291398Stmm /* If an external transceiver is connected, enable its MII drivers */ 174391398Stmm sc->sc_mif_config = bus_space_read_4(t, mac, GEM_MIF_CONFIG); 174491398Stmm if ((sc->sc_mif_config & GEM_MIF_CONFIG_MDI1) != 0) { 174591398Stmm /* External MII needs echo disable if half duplex. */ 174691398Stmm if ((IFM_OPTIONS(sc->sc_mii->mii_media_active) & IFM_FDX) != 0) 174791398Stmm /* turn on full duplex LED */ 174891398Stmm v |= GEM_MAC_XIF_FDPLX_LED; 174999726Sbenno else 175099726Sbenno /* half duplex -- disable echo */ 175199726Sbenno v |= GEM_MAC_XIF_ECHO_DISABL; 175299726Sbenno 175399726Sbenno if (IFM_SUBTYPE(sc->sc_mii->mii_media_active) == IFM_1000_T) 175499726Sbenno v |= GEM_MAC_XIF_GMII_MODE; 175599726Sbenno else 175699726Sbenno v &= ~GEM_MAC_XIF_GMII_MODE; 175791398Stmm } else { 175891398Stmm /* Internal MII needs buf enable */ 175991398Stmm v |= GEM_MAC_XIF_MII_BUF_ENA; 176091398Stmm } 176191398Stmm bus_space_write_4(t, mac, GEM_MAC_XIF_CONFIG, v); 176291398Stmm} 176391398Stmm 176491398Stmmint 176591398Stmmgem_mediachange(ifp) 176691398Stmm struct ifnet *ifp; 176791398Stmm{ 176891398Stmm struct gem_softc *sc = ifp->if_softc; 176991398Stmm 177091398Stmm /* XXX Add support for serial media. */ 177191398Stmm 177291398Stmm return (mii_mediachg(sc->sc_mii)); 177391398Stmm} 177491398Stmm 177591398Stmmvoid 177691398Stmmgem_mediastatus(ifp, ifmr) 177791398Stmm struct ifnet *ifp; 177891398Stmm struct ifmediareq *ifmr; 177991398Stmm{ 178091398Stmm struct gem_softc *sc = ifp->if_softc; 178191398Stmm 178291398Stmm if ((ifp->if_flags & IFF_UP) == 0) 178391398Stmm return; 178491398Stmm 178591398Stmm mii_pollstat(sc->sc_mii); 178691398Stmm ifmr->ifm_active = sc->sc_mii->mii_media_active; 178791398Stmm ifmr->ifm_status = sc->sc_mii->mii_media_status; 178891398Stmm} 178991398Stmm 179091398Stmm/* 179191398Stmm * Process an ioctl request. 179291398Stmm */ 179391398Stmmstatic int 179491398Stmmgem_ioctl(ifp, cmd, data) 179591398Stmm struct ifnet *ifp; 179691398Stmm u_long cmd; 179791398Stmm caddr_t data; 179891398Stmm{ 179991398Stmm struct gem_softc *sc = ifp->if_softc; 180091398Stmm struct ifreq *ifr = (struct ifreq *)data; 180191398Stmm int s, error = 0; 180291398Stmm 180391398Stmm switch (cmd) { 180491398Stmm case SIOCSIFADDR: 180591398Stmm case SIOCGIFADDR: 180691398Stmm case SIOCSIFMTU: 180791398Stmm error = ether_ioctl(ifp, cmd, data); 180891398Stmm break; 180991398Stmm case SIOCSIFFLAGS: 181091398Stmm if (ifp->if_flags & IFF_UP) { 181199726Sbenno if ((sc->sc_ifflags ^ ifp->if_flags) == IFF_PROMISC) 181291398Stmm gem_setladrf(sc); 181391398Stmm else 181491398Stmm gem_init(sc); 181591398Stmm } else { 181691398Stmm if (ifp->if_flags & IFF_RUNNING) 181791398Stmm gem_stop(ifp, 0); 181891398Stmm } 181999726Sbenno sc->sc_ifflags = ifp->if_flags; 182091398Stmm error = 0; 182191398Stmm break; 182291398Stmm case SIOCADDMULTI: 182391398Stmm case SIOCDELMULTI: 182491398Stmm gem_setladrf(sc); 182591398Stmm error = 0; 182691398Stmm break; 182791398Stmm case SIOCGIFMEDIA: 182891398Stmm case SIOCSIFMEDIA: 182991398Stmm error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii->mii_media, cmd); 183091398Stmm break; 183191398Stmm default: 1832108832Stmm error = ENOTTY; 183391398Stmm break; 183491398Stmm } 183591398Stmm 183691398Stmm /* Try to get things going again */ 183791398Stmm if (ifp->if_flags & IFF_UP) 183891398Stmm gem_start(ifp); 183991398Stmm splx(s); 184091398Stmm return (error); 184191398Stmm} 184291398Stmm 184391398Stmm/* 184491398Stmm * Set up the logical address filter. 184591398Stmm */ 184691398Stmmstatic void 184791398Stmmgem_setladrf(sc) 184891398Stmm struct gem_softc *sc; 184991398Stmm{ 185091398Stmm struct ifnet *ifp = &sc->sc_arpcom.ac_if; 185191398Stmm struct ifmultiaddr *inm; 185291398Stmm struct sockaddr_dl *sdl; 185391398Stmm bus_space_tag_t t = sc->sc_bustag; 185491398Stmm bus_space_handle_t h = sc->sc_h; 185591398Stmm u_char *cp; 185691398Stmm u_int32_t crc; 185791398Stmm u_int32_t hash[16]; 185891398Stmm u_int32_t v; 185991398Stmm int len; 186099726Sbenno int i; 186191398Stmm 186291398Stmm /* Get current RX configuration */ 186391398Stmm v = bus_space_read_4(t, h, GEM_MAC_RX_CONFIG); 186491398Stmm 186599726Sbenno /* 186699726Sbenno * Turn off promiscuous mode, promiscuous group mode (all multicast), 186799726Sbenno * and hash filter. Depending on the case, the right bit will be 186899726Sbenno * enabled. 186999726Sbenno */ 187099726Sbenno v &= ~(GEM_MAC_RX_PROMISCUOUS|GEM_MAC_RX_HASH_FILTER| 187199726Sbenno GEM_MAC_RX_PROMISC_GRP); 187299726Sbenno 187391398Stmm if ((ifp->if_flags & IFF_PROMISC) != 0) { 187499726Sbenno /* Turn on promiscuous mode */ 187591398Stmm v |= GEM_MAC_RX_PROMISCUOUS; 187691398Stmm goto chipit; 187791398Stmm } 187891398Stmm if ((ifp->if_flags & IFF_ALLMULTI) != 0) { 187991398Stmm hash[3] = hash[2] = hash[1] = hash[0] = 0xffff; 188091398Stmm ifp->if_flags |= IFF_ALLMULTI; 188199726Sbenno v |= GEM_MAC_RX_PROMISC_GRP; 188291398Stmm goto chipit; 188391398Stmm } 188491398Stmm 188591398Stmm /* 188691398Stmm * Set up multicast address filter by passing all multicast addresses 188799726Sbenno * through a crc generator, and then using the high order 8 bits as an 188899726Sbenno * index into the 256 bit logical address filter. The high order 4 188999726Sbenno * bits selects the word, while the other 4 bits select the bit within 189099726Sbenno * the word (where bit 0 is the MSB). 189191398Stmm */ 189291398Stmm 189399726Sbenno /* Clear hash table */ 189499726Sbenno memset(hash, 0, sizeof(hash)); 189599726Sbenno 189691398Stmm TAILQ_FOREACH(inm, &sc->sc_arpcom.ac_if.if_multiaddrs, ifma_link) { 189791398Stmm if (inm->ifma_addr->sa_family != AF_LINK) 189891398Stmm continue; 189991398Stmm sdl = (struct sockaddr_dl *)inm->ifma_addr; 190091398Stmm cp = LLADDR(sdl); 190191398Stmm crc = 0xffffffff; 190291398Stmm for (len = sdl->sdl_alen; --len >= 0;) { 190391398Stmm int octet = *cp++; 190491398Stmm int i; 190591398Stmm 190691398Stmm#define MC_POLY_LE 0xedb88320UL /* mcast crc, little endian */ 190791398Stmm for (i = 0; i < 8; i++) { 190891398Stmm if ((crc & 1) ^ (octet & 1)) { 190991398Stmm crc >>= 1; 191091398Stmm crc ^= MC_POLY_LE; 191191398Stmm } else { 191291398Stmm crc >>= 1; 191391398Stmm } 191491398Stmm octet >>= 1; 191591398Stmm } 191691398Stmm } 191791398Stmm /* Just want the 8 most significant bits. */ 191891398Stmm crc >>= 24; 191991398Stmm 192091398Stmm /* Set the corresponding bit in the filter. */ 192199726Sbenno hash[crc >> 4] |= 1 << (15 - (crc & 15)); 192291398Stmm } 192391398Stmm 192499726Sbenno v |= GEM_MAC_RX_HASH_FILTER; 192599726Sbenno ifp->if_flags &= ~IFF_ALLMULTI; 192699726Sbenno 192799726Sbenno /* Now load the hash table into the chip (if we are using it) */ 192899726Sbenno for (i = 0; i < 16; i++) { 192999726Sbenno bus_space_write_4(t, h, 193099726Sbenno GEM_MAC_HASH0 + i * (GEM_MAC_HASH1-GEM_MAC_HASH0), 193199726Sbenno hash[i]); 193299726Sbenno } 193399726Sbenno 193491398Stmmchipit: 193591398Stmm bus_space_write_4(t, h, GEM_MAC_RX_CONFIG, v); 193691398Stmm} 1937