if_gem.c revision 130026
119370Spst/*- 219370Spst * Copyright (C) 2001 Eduardo Horvath. 3130803Smarcel * Copyright (c) 2001-2003 Thomas Moestl 4130803Smarcel * All rights reserved. 5130803Smarcel * 6130803Smarcel * Redistribution and use in source and binary forms, with or without 798944Sobrien * modification, are permitted provided that the following conditions 819370Spst * are met: 998944Sobrien * 1. Redistributions of source code must retain the above copyright 1098944Sobrien * notice, this list of conditions and the following disclaimer. 1198944Sobrien * 2. Redistributions in binary form must reproduce the above copyright 1298944Sobrien * notice, this list of conditions and the following disclaimer in the 1319370Spst * documentation and/or other materials provided with the distribution. 1498944Sobrien * 1598944Sobrien * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND 1698944Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1798944Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1819370Spst * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE 1998944Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2098944Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2198944Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2298944Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2319370Spst * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2419370Spst * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2519370Spst * SUCH DAMAGE. 2619370Spst * 2719370Spst * from: NetBSD: gem.c,v 1.21 2002/06/01 23:50:58 lukem Exp 2819370Spst */ 2919370Spst 3019370Spst#include <sys/cdefs.h> 3119370Spst__FBSDID("$FreeBSD: head/sys/dev/gem/if_gem.c 130026 2004-06-03 06:10:02Z phk $"); 3219370Spst 3319370Spst/* 3446283Sdfr * Driver for Sun GEM ethernet controllers. 3598944Sobrien */ 3698944Sobrien 3719370Spst#if 0 3819370Spst#define GEM_DEBUG 3919370Spst#endif 4019370Spst 4119370Spst#include <sys/param.h> 4298944Sobrien#include <sys/systm.h> 4398944Sobrien#include <sys/bus.h> 4419370Spst#include <sys/callout.h> 4598944Sobrien#include <sys/endian.h> 4619370Spst#include <sys/mbuf.h> 4798944Sobrien#include <sys/malloc.h> 4819370Spst#include <sys/kernel.h> 4998944Sobrien#include <sys/module.h> 5019370Spst#include <sys/socket.h> 5198944Sobrien#include <sys/sockio.h> 5219370Spst 5398944Sobrien#include <net/bpf.h> 5419370Spst#include <net/ethernet.h> 5598944Sobrien#include <net/if.h> 5619370Spst#include <net/if_arp.h> 5798944Sobrien#include <net/if_dl.h> 5819370Spst#include <net/if_media.h> 5998944Sobrien 6046283Sdfr#include <machine/bus.h> 6198944Sobrien 6298944Sobrien#include <dev/mii/mii.h> 6319370Spst#include <dev/mii/miivar.h> 6419370Spst 6519370Spst#include <dev/gem/if_gemreg.h> 6619370Spst#include <dev/gem/if_gemvar.h> 6719370Spst 6819370Spst#define TRIES 10000 6919370Spst 7019370Spststatic void gem_start(struct ifnet *); 7119370Spststatic void gem_stop(struct ifnet *, int); 7219370Spststatic int gem_ioctl(struct ifnet *, u_long, caddr_t); 7319370Spststatic void gem_cddma_callback(void *, bus_dma_segment_t *, int, int); 7419370Spststatic void gem_rxdma_callback(void *, bus_dma_segment_t *, int, 7519370Spst bus_size_t, int); 7619370Spststatic void gem_txdma_callback(void *, bus_dma_segment_t *, int, 7719370Spst bus_size_t, int); 7819370Spststatic void gem_tick(void *); 7919370Spststatic void gem_watchdog(struct ifnet *); 8019370Spststatic void gem_init(void *); 8119370Spststatic void gem_init_regs(struct gem_softc *sc); 8219370Spststatic int gem_ringsize(int sz); 8319370Spststatic int gem_meminit(struct gem_softc *); 8419370Spststatic int gem_load_txmbuf(struct gem_softc *, struct mbuf *); 8519370Spststatic void gem_mifinit(struct gem_softc *); 8619370Spststatic int gem_bitwait(struct gem_softc *sc, bus_addr_t r, 8719370Spst u_int32_t clr, u_int32_t set); 8819370Spststatic int gem_reset_rx(struct gem_softc *); 8919370Spststatic int gem_reset_tx(struct gem_softc *); 9019370Spststatic int gem_disable_rx(struct gem_softc *); 9119370Spststatic int gem_disable_tx(struct gem_softc *); 9219370Spststatic void gem_rxdrain(struct gem_softc *); 9319370Spststatic int gem_add_rxbuf(struct gem_softc *, int); 9419370Spststatic void gem_setladrf(struct gem_softc *); 9519370Spst 9619370Spststruct mbuf *gem_get(struct gem_softc *, int, int); 9719370Spststatic void gem_eint(struct gem_softc *, u_int); 9819370Spststatic void gem_rint(struct gem_softc *); 9919370Spst#if 0 10019370Spststatic void gem_rint_timeout(void *); 10119370Spst#endif 10219370Spststatic void gem_tint(struct gem_softc *); 10398944Sobrien#ifdef notyet 10419370Spststatic void gem_power(int, void *); 10519370Spst#endif 10619370Spst 10719370Spstdevclass_t gem_devclass; 10819370SpstDRIVER_MODULE(miibus, gem, miibus_driver, miibus_devclass, 0, 0); 10919370SpstMODULE_DEPEND(gem, miibus, 1, 1, 1); 11019370Spst 11119370Spst#ifdef GEM_DEBUG 11219370Spst#include <sys/ktr.h> 11319370Spst#define KTR_GEM KTR_CT2 11419370Spst#endif 11519370Spst 11619370Spst#define GEM_NSEGS GEM_NTXDESC 11719370Spst 11819370Spst/* 11919370Spst * gem_attach: 12019370Spst * 12119370Spst * Attach a Gem interface to the system. 12219370Spst */ 12319370Spstint 12419370Spstgem_attach(sc) 12519370Spst struct gem_softc *sc; 12698944Sobrien{ 12798944Sobrien struct ifnet *ifp = &sc->sc_arpcom.ac_if; 12898944Sobrien struct mii_softc *child; 12919370Spst int i, error; 13019370Spst u_int32_t v; 13119370Spst 13219370Spst /* Make sure the chip is stopped. */ 13319370Spst ifp->if_softc = sc; 13419370Spst gem_reset(sc); 13598944Sobrien 13619370Spst error = bus_dma_tag_create(NULL, 1, 0, BUS_SPACE_MAXADDR_32BIT, 13719370Spst BUS_SPACE_MAXADDR, NULL, NULL, MCLBYTES, GEM_NSEGS, 13819370Spst BUS_SPACE_MAXSIZE_32BIT, 0, NULL, NULL, &sc->sc_pdmatag); 13919370Spst if (error) 14019370Spst return (error); 14119370Spst 14298944Sobrien error = bus_dma_tag_create(sc->sc_pdmatag, 1, 0, 14319370Spst BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, MAXBSIZE, 14419370Spst 1, BUS_SPACE_MAXSIZE_32BIT, BUS_DMA_ALLOCNOW, NULL, NULL, 14519370Spst &sc->sc_rdmatag); 14619370Spst if (error) 14719370Spst goto fail_ptag; 14898944Sobrien 14946283Sdfr error = bus_dma_tag_create(sc->sc_pdmatag, 1, 0, 15098944Sobrien BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, 15119370Spst GEM_TD_BUFSIZE, GEM_NTXDESC, BUS_SPACE_MAXSIZE_32BIT, 15219370Spst BUS_DMA_ALLOCNOW, NULL, NULL, &sc->sc_tdmatag); 153242936Semaste if (error) 154242936Semaste goto fail_rtag; 155242936Semaste 15619370Spst error = bus_dma_tag_create(sc->sc_pdmatag, PAGE_SIZE, 0, 157242936Semaste BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, 158242936Semaste sizeof(struct gem_control_data), 1, 15919370Spst sizeof(struct gem_control_data), BUS_DMA_ALLOCNOW, 16019370Spst busdma_lock_mutex, &Giant, &sc->sc_cdmatag); 16119370Spst if (error) 162242936Semaste goto fail_ttag; 16319370Spst 16419370Spst /* 165242936Semaste * Allocate the control data structures, and create and load the 16619370Spst * DMA map for it. 16719370Spst */ 168242936Semaste if ((error = bus_dmamem_alloc(sc->sc_cdmatag, 16919370Spst (void **)&sc->sc_control_data, 0, &sc->sc_cddmamap))) { 17019370Spst device_printf(sc->sc_dev, "unable to allocate control data," 171242936Semaste " error = %d\n", error); 172242936Semaste goto fail_ctag; 173242936Semaste } 174242936Semaste 175242936Semaste sc->sc_cddma = 0; 176242936Semaste if ((error = bus_dmamap_load(sc->sc_cdmatag, sc->sc_cddmamap, 177242936Semaste sc->sc_control_data, sizeof(struct gem_control_data), 178242936Semaste gem_cddma_callback, sc, 0)) != 0 || sc->sc_cddma == 0) { 179242936Semaste device_printf(sc->sc_dev, "unable to load control data DMA " 180242936Semaste "map, error = %d\n", error); 181242936Semaste goto fail_cmem; 182242936Semaste } 183242936Semaste 184242936Semaste /* 185242936Semaste * Initialize the transmit job descriptors. 186242936Semaste */ 187242936Semaste STAILQ_INIT(&sc->sc_txfreeq); 188242936Semaste STAILQ_INIT(&sc->sc_txdirtyq); 189242936Semaste 190242936Semaste /* 191242936Semaste * Create the transmit buffer DMA maps. 192242936Semaste */ 193242936Semaste error = ENOMEM; 194242936Semaste for (i = 0; i < GEM_TXQUEUELEN; i++) { 195242936Semaste struct gem_txsoft *txs; 196242936Semaste 197242936Semaste txs = &sc->sc_txsoft[i]; 198242936Semaste txs->txs_mbuf = NULL; 199242936Semaste txs->txs_ndescs = 0; 200242936Semaste if ((error = bus_dmamap_create(sc->sc_tdmatag, 0, 201242936Semaste &txs->txs_dmamap)) != 0) { 202242936Semaste device_printf(sc->sc_dev, "unable to create tx DMA map " 203242936Semaste "%d, error = %d\n", i, error); 204242936Semaste goto fail_txd; 205242936Semaste } 206242936Semaste STAILQ_INSERT_TAIL(&sc->sc_txfreeq, txs, txs_q); 207242936Semaste } 208242936Semaste 209242936Semaste /* 210242936Semaste * Create the receive buffer DMA maps. 211242936Semaste */ 212242936Semaste for (i = 0; i < GEM_NRXDESC; i++) { 21319370Spst if ((error = bus_dmamap_create(sc->sc_rdmatag, 0, 21419370Spst &sc->sc_rxsoft[i].rxs_dmamap)) != 0) { 21519370Spst device_printf(sc->sc_dev, "unable to create rx DMA map " 21619370Spst "%d, error = %d\n", i, error); 21719370Spst goto fail_rxd; 21819370Spst } 21919370Spst sc->sc_rxsoft[i].rxs_mbuf = NULL; 22019370Spst } 22198944Sobrien 22298944Sobrien 22319370Spst gem_mifinit(sc); 22419370Spst 22519370Spst if ((error = mii_phy_probe(sc->sc_dev, &sc->sc_miibus, gem_mediachange, 22619370Spst gem_mediastatus)) != 0) { 22719370Spst device_printf(sc->sc_dev, "phy probe failed: %d\n", error); 22819370Spst goto fail_rxd; 22919370Spst } 23019370Spst sc->sc_mii = device_get_softc(sc->sc_miibus); 23119370Spst 23219370Spst /* 23319370Spst * From this point forward, the attachment cannot fail. A failure 23419370Spst * before this point releases all resources that may have been 23519370Spst * allocated. 23619370Spst */ 23719370Spst 23819370Spst /* Get RX FIFO size */ 23919370Spst sc->sc_rxfifosize = 64 * 24019370Spst bus_space_read_4(sc->sc_bustag, sc->sc_h, GEM_RX_FIFO_SIZE); 24119370Spst 24219370Spst /* Get TX FIFO size */ 24319370Spst v = bus_space_read_4(sc->sc_bustag, sc->sc_h, GEM_TX_FIFO_SIZE); 24419370Spst device_printf(sc->sc_dev, "%ukB RX FIFO, %ukB TX FIFO\n", 24519370Spst sc->sc_rxfifosize / 1024, v / 16); 24619370Spst 24719370Spst /* Initialize ifnet structure. */ 24819370Spst ifp->if_softc = sc; 24919370Spst if_initname(ifp, device_get_name(sc->sc_dev), 25019370Spst device_get_unit(sc->sc_dev)); 25119370Spst ifp->if_mtu = ETHERMTU; 25246283Sdfr ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 25346283Sdfr ifp->if_start = gem_start; 25446283Sdfr ifp->if_ioctl = gem_ioctl; 25546283Sdfr ifp->if_watchdog = gem_watchdog; 25646283Sdfr ifp->if_init = gem_init; 25746283Sdfr ifp->if_snd.ifq_maxlen = GEM_TXQUEUELEN; 25819370Spst /* 25946283Sdfr * Walk along the list of attached MII devices and 26046283Sdfr * establish an `MII instance' to `phy number' 26146283Sdfr * mapping. We'll use this mapping in media change 26246283Sdfr * requests to determine which phy to use to program 26398944Sobrien * the MIF configuration register. 26446283Sdfr */ 26546283Sdfr for (child = LIST_FIRST(&sc->sc_mii->mii_phys); child != NULL; 26698944Sobrien child = LIST_NEXT(child, mii_list)) { 26798944Sobrien /* 26846283Sdfr * Note: we support just two PHYs: the built-in 26998944Sobrien * internal device and an external on the MII 27098944Sobrien * connector. 27146283Sdfr */ 27246283Sdfr if (child->mii_phy > 1 || child->mii_inst > 1) { 27346283Sdfr device_printf(sc->sc_dev, "cannot accomodate " 27446283Sdfr "MII device %s at phy %d, instance %d\n", 27546283Sdfr device_get_name(child->mii_dev), 27646283Sdfr child->mii_phy, child->mii_inst); 27746283Sdfr continue; 27846283Sdfr } 27946283Sdfr 28046283Sdfr sc->sc_phys[child->mii_inst] = child->mii_phy; 28146283Sdfr } 28246283Sdfr 28346283Sdfr /* 28446283Sdfr * Now select and activate the PHY we will use. 28546283Sdfr * 28646283Sdfr * The order of preference is External (MDI1), 28746283Sdfr * Internal (MDI0), Serial Link (no MII). 28846283Sdfr */ 28946283Sdfr if (sc->sc_phys[1]) { 29046283Sdfr#ifdef GEM_DEBUG 29146283Sdfr printf("using external phy\n"); 29246283Sdfr#endif 29346283Sdfr sc->sc_mif_config |= GEM_MIF_CONFIG_PHY_SEL; 29446283Sdfr } else { 29546283Sdfr#ifdef GEM_DEBUG 29698944Sobrien printf("using internal phy\n"); 29746283Sdfr#endif 29846283Sdfr sc->sc_mif_config &= ~GEM_MIF_CONFIG_PHY_SEL; 29946283Sdfr } 30046283Sdfr bus_space_write_4(sc->sc_bustag, sc->sc_h, GEM_MIF_CONFIG, 30146283Sdfr sc->sc_mif_config); 30219370Spst /* Attach the interface. */ 30398944Sobrien ether_ifattach(ifp, sc->sc_arpcom.ac_enaddr); 30498944Sobrien 30519370Spst#if notyet 30619370Spst /* 30746283Sdfr * Add a suspend hook to make sure we come back up after a 30819370Spst * resume. 30946283Sdfr */ 31046283Sdfr sc->sc_powerhook = powerhook_establish(gem_power, sc); 31146283Sdfr if (sc->sc_powerhook == NULL) 31246283Sdfr device_printf(sc->sc_dev, "WARNING: unable to establish power " 31346283Sdfr "hook\n"); 31446283Sdfr#endif 31546283Sdfr 31646283Sdfr callout_init(&sc->sc_tick_ch, 0); 31746283Sdfr callout_init(&sc->sc_rx_ch, 0); 31846283Sdfr return (0); 31946283Sdfr 32046283Sdfr /* 32146283Sdfr * Free any resources we've allocated during the failed attach 32246283Sdfr * attempt. Do this in reverse order and fall through. 32346283Sdfr */ 32446283Sdfrfail_rxd: 32546283Sdfr for (i = 0; i < GEM_NRXDESC; i++) { 32646283Sdfr if (sc->sc_rxsoft[i].rxs_dmamap != NULL) 32746283Sdfr bus_dmamap_destroy(sc->sc_rdmatag, 32846283Sdfr sc->sc_rxsoft[i].rxs_dmamap); 32946283Sdfr } 33046283Sdfrfail_txd: 33146283Sdfr for (i = 0; i < GEM_TXQUEUELEN; i++) { 33246283Sdfr if (sc->sc_txsoft[i].txs_dmamap != NULL) 33346283Sdfr bus_dmamap_destroy(sc->sc_tdmatag, 33446283Sdfr sc->sc_txsoft[i].txs_dmamap); 33546283Sdfr } 33646283Sdfr bus_dmamap_unload(sc->sc_cdmatag, sc->sc_cddmamap); 33746283Sdfrfail_cmem: 33846283Sdfr bus_dmamem_free(sc->sc_cdmatag, sc->sc_control_data, 33946283Sdfr sc->sc_cddmamap); 34046283Sdfrfail_ctag: 34146283Sdfr bus_dma_tag_destroy(sc->sc_cdmatag); 34246283Sdfrfail_ttag: 34346283Sdfr bus_dma_tag_destroy(sc->sc_tdmatag); 34446283Sdfrfail_rtag: 34546283Sdfr bus_dma_tag_destroy(sc->sc_rdmatag); 34646283Sdfrfail_ptag: 34746283Sdfr bus_dma_tag_destroy(sc->sc_pdmatag); 34846283Sdfr return (error); 34946283Sdfr} 35046283Sdfr 35146283Sdfrvoid 35246283Sdfrgem_detach(sc) 35346283Sdfr struct gem_softc *sc; 35446283Sdfr{ 35546283Sdfr struct ifnet *ifp = &sc->sc_arpcom.ac_if; 35646283Sdfr int i; 35746283Sdfr 35846283Sdfr ether_ifdetach(ifp); 35919370Spst gem_stop(ifp, 1); 36019370Spst device_delete_child(sc->sc_dev, sc->sc_miibus); 36119370Spst 36246283Sdfr for (i = 0; i < GEM_NRXDESC; i++) { 36319370Spst if (sc->sc_rxsoft[i].rxs_dmamap != NULL) 36419370Spst bus_dmamap_destroy(sc->sc_rdmatag, 36519370Spst sc->sc_rxsoft[i].rxs_dmamap); 36619370Spst } 36719370Spst for (i = 0; i < GEM_TXQUEUELEN; i++) { 36898944Sobrien if (sc->sc_txsoft[i].txs_dmamap != NULL) 369130803Smarcel bus_dmamap_destroy(sc->sc_tdmatag, 37019370Spst sc->sc_txsoft[i].txs_dmamap); 37119370Spst } 372130803Smarcel GEM_CDSYNC(sc, BUS_DMASYNC_POSTREAD); 37319370Spst GEM_CDSYNC(sc, BUS_DMASYNC_POSTWRITE); 37419370Spst bus_dmamap_unload(sc->sc_cdmatag, sc->sc_cddmamap); 37519370Spst bus_dmamem_free(sc->sc_cdmatag, sc->sc_control_data, 37619370Spst sc->sc_cddmamap); 37798944Sobrien bus_dma_tag_destroy(sc->sc_cdmatag); 378130803Smarcel bus_dma_tag_destroy(sc->sc_tdmatag); 37919370Spst bus_dma_tag_destroy(sc->sc_rdmatag); 38019370Spst bus_dma_tag_destroy(sc->sc_pdmatag); 38119370Spst} 38219370Spst 38398944Sobrienvoid 384130803Smarcelgem_suspend(sc) 38519370Spst struct gem_softc *sc; 38619370Spst{ 38719370Spst struct ifnet *ifp = &sc->sc_arpcom.ac_if; 38819370Spst 38919370Spst gem_stop(ifp, 0); 39019370Spst} 39119370Spst 39219370Spstvoid 39319370Spstgem_resume(sc) 39419370Spst struct gem_softc *sc; 39519370Spst{ 39619370Spst struct ifnet *ifp = &sc->sc_arpcom.ac_if; 39719370Spst 39819370Spst if (ifp->if_flags & IFF_UP) 39998944Sobrien gem_init(ifp); 40019370Spst} 40198944Sobrien 40219370Spststatic void 40319370Spstgem_cddma_callback(xsc, segs, nsegs, error) 40419370Spst void *xsc; 40519370Spst bus_dma_segment_t *segs; 40619370Spst int nsegs; 40719370Spst int error; 40819370Spst{ 40919370Spst struct gem_softc *sc = (struct gem_softc *)xsc; 41019370Spst 41198944Sobrien if (error != 0) 41219370Spst return; 41319370Spst if (nsegs != 1) { 41419370Spst /* can't happen... */ 41519370Spst panic("gem_cddma_callback: bad control buffer segment count"); 41619370Spst } 41719370Spst sc->sc_cddma = segs[0].ds_addr; 41819370Spst} 41919370Spst 42098944Sobrienstatic void 42146283Sdfrgem_rxdma_callback(xsc, segs, nsegs, totsz, error) 42219370Spst void *xsc; 42319370Spst bus_dma_segment_t *segs; 42419370Spst int nsegs; 42519370Spst bus_size_t totsz; 42698944Sobrien int error; 42746283Sdfr{ 42819370Spst struct gem_rxsoft *rxs = (struct gem_rxsoft *)xsc; 42919370Spst 43019370Spst if (error != 0) 43146283Sdfr return; 43219370Spst KASSERT(nsegs == 1, ("gem_rxdma_callback: bad dma segment count")); 43319370Spst rxs->rxs_paddr = segs[0].ds_addr; 43419370Spst} 43546283Sdfr 43619370Spststatic void 43719370Spstgem_txdma_callback(xsc, segs, nsegs, totsz, error) 43819370Spst void *xsc; 43946283Sdfr bus_dma_segment_t *segs; 44019370Spst int nsegs; 44119370Spst bus_size_t totsz; 44219370Spst int error; 44346283Sdfr{ 44419370Spst struct gem_txdma *txd = (struct gem_txdma *)xsc; 44519370Spst struct gem_softc *sc = txd->txd_sc; 44698944Sobrien struct gem_txsoft *txs = txd->txd_txs; 44719370Spst bus_size_t len = 0; 44846283Sdfr uint64_t flags = 0; 44946283Sdfr int seg, nexttx; 45046283Sdfr 45119370Spst if (error != 0) 45219370Spst return; 45319370Spst /* 45419370Spst * Ensure we have enough descriptors free to describe 45519370Spst * the packet. Note, we always reserve one descriptor 45619370Spst * at the end of the ring as a termination point, to 45719370Spst * prevent wrap-around. 45898944Sobrien */ 45919370Spst if (nsegs > sc->sc_txfree - 1) { 46046283Sdfr txs->txs_ndescs = -1; 46146283Sdfr return; 46219370Spst } 46346283Sdfr txs->txs_ndescs = nsegs; 46446283Sdfr 46546283Sdfr nexttx = txs->txs_firstdesc; 46646283Sdfr /* 46746283Sdfr * Initialize the transmit descriptors. 46846283Sdfr */ 46946283Sdfr for (seg = 0; seg < nsegs; 47046283Sdfr seg++, nexttx = GEM_NEXTTX(nexttx)) { 47146283Sdfr#ifdef GEM_DEBUG 47219370Spst CTR5(KTR_GEM, "txdma_cb: mapping seg %d (txd %d), len " 47319370Spst "%lx, addr %#lx (%#lx)", seg, nexttx, 47498944Sobrien segs[seg].ds_len, segs[seg].ds_addr, 47598944Sobrien GEM_DMA_WRITE(sc, segs[seg].ds_addr)); 47619370Spst#endif 47719370Spst 47898944Sobrien if (segs[seg].ds_len == 0) 47919370Spst continue; 48019370Spst sc->sc_txdescs[nexttx].gd_addr = 48119370Spst GEM_DMA_WRITE(sc, segs[seg].ds_addr); 48298944Sobrien KASSERT(segs[seg].ds_len < GEM_TD_BUFSIZE, 48319370Spst ("gem_txdma_callback: segment size too large!")); 48419370Spst flags = segs[seg].ds_len & GEM_TD_BUFSIZE; 48598944Sobrien if (len == 0) { 48698944Sobrien#ifdef GEM_DEBUG 48798944Sobrien CTR2(KTR_GEM, "txdma_cb: start of packet at seg %d, " 48898944Sobrien "tx %d", seg, nexttx); 48998944Sobrien#endif 49098944Sobrien flags |= GEM_TD_START_OF_PACKET; 49198944Sobrien if (++sc->sc_txwin > GEM_NTXSEGS * 2 / 3) { 49298944Sobrien sc->sc_txwin = 0; 493130803Smarcel flags |= GEM_TD_INTERRUPT_ME; 494130803Smarcel } 495130803Smarcel } 49698944Sobrien if (len + segs[seg].ds_len == totsz) { 49798944Sobrien#ifdef GEM_DEBUG 49898944Sobrien CTR2(KTR_GEM, "txdma_cb: end of packet at seg %d, " 49919370Spst "tx %d", seg, nexttx); 50098944Sobrien#endif 50198944Sobrien flags |= GEM_TD_END_OF_PACKET; 50298944Sobrien } 50398944Sobrien sc->sc_txdescs[nexttx].gd_flags = GEM_DMA_WRITE(sc, flags); 50498944Sobrien txs->txs_lastdesc = nexttx; 50598944Sobrien len += segs[seg].ds_len; 50698944Sobrien } 50798944Sobrien KASSERT((flags & GEM_TD_END_OF_PACKET) != 0, 50819370Spst ("gem_txdma_callback: missed end of packet!")); 50919370Spst} 51019370Spst 51119370Spststatic void 51219370Spstgem_tick(arg) 51319370Spst void *arg; 51419370Spst{ 51519370Spst struct gem_softc *sc = arg; 51698944Sobrien int s; 51798944Sobrien 51898944Sobrien s = splnet(); 51998944Sobrien mii_tick(sc->sc_mii); 52098944Sobrien splx(s); 52198944Sobrien 52298944Sobrien callout_reset(&sc->sc_tick_ch, hz, gem_tick, sc); 52398944Sobrien} 52419370Spst 52598944Sobrienstatic int 52619370Spstgem_bitwait(sc, r, clr, set) 52798944Sobrien struct gem_softc *sc; 52819370Spst bus_addr_t r; 52919370Spst u_int32_t clr; 53019370Spst u_int32_t set; 53119370Spst{ 53298944Sobrien int i; 53398944Sobrien u_int32_t reg; 53419370Spst 53519370Spst for (i = TRIES; i--; DELAY(100)) { 53619370Spst reg = bus_space_read_4(sc->sc_bustag, sc->sc_h, r); 53719370Spst if ((r & clr) == 0 && (r & set) == set) 53898944Sobrien return (1); 53998944Sobrien } 54098944Sobrien return (0); 54146283Sdfr} 54246283Sdfr 54346283Sdfrvoid 54446283Sdfrgem_reset(sc) 54546283Sdfr struct gem_softc *sc; 54698944Sobrien{ 54798944Sobrien bus_space_tag_t t = sc->sc_bustag; 54846283Sdfr bus_space_handle_t h = sc->sc_h; 54946283Sdfr int s; 55046283Sdfr 55146283Sdfr s = splnet(); 55298944Sobrien#ifdef GEM_DEBUG 55346283Sdfr CTR1(KTR_GEM, "%s: gem_reset", device_get_name(sc->sc_dev)); 55446283Sdfr#endif 55546283Sdfr gem_reset_rx(sc); 556130803Smarcel gem_reset_tx(sc); 55798944Sobrien 55846283Sdfr /* Do a full reset */ 55946283Sdfr bus_space_write_4(t, h, GEM_RESET, GEM_RESET_RX | GEM_RESET_TX); 56046283Sdfr if (!gem_bitwait(sc, GEM_RESET, GEM_RESET_RX | GEM_RESET_TX, 0)) 56146283Sdfr device_printf(sc->sc_dev, "cannot reset device\n"); 56246283Sdfr splx(s); 56398944Sobrien} 56498944Sobrien 56598944Sobrien 56698944Sobrien/* 56798944Sobrien * gem_rxdrain: 56898944Sobrien * 56998944Sobrien * Drain the receive queue. 57098944Sobrien */ 57198944Sobrienstatic void 57246283Sdfrgem_rxdrain(sc) 57398944Sobrien struct gem_softc *sc; 57498944Sobrien{ 57546283Sdfr struct gem_rxsoft *rxs; 57646283Sdfr int i; 57746283Sdfr 57846283Sdfr for (i = 0; i < GEM_NRXDESC; i++) { 57946283Sdfr rxs = &sc->sc_rxsoft[i]; 58046283Sdfr if (rxs->rxs_mbuf != NULL) { 58146283Sdfr bus_dmamap_sync(sc->sc_rdmatag, rxs->rxs_dmamap, 58246283Sdfr BUS_DMASYNC_POSTREAD); 58398944Sobrien bus_dmamap_unload(sc->sc_rdmatag, rxs->rxs_dmamap); 58498944Sobrien m_freem(rxs->rxs_mbuf); 58598944Sobrien rxs->rxs_mbuf = NULL; 58698944Sobrien } 58798944Sobrien } 58898944Sobrien} 58946283Sdfr 59098944Sobrien/* 59198944Sobrien * Reset the whole thing. 59246283Sdfr */ 59346283Sdfrstatic void 594130803Smarcelgem_stop(ifp, disable) 59546283Sdfr struct ifnet *ifp; 59646283Sdfr int disable; 59746283Sdfr{ 59846283Sdfr struct gem_softc *sc = (struct gem_softc *)ifp->if_softc; 59946283Sdfr struct gem_txsoft *txs; 60046283Sdfr 60198944Sobrien#ifdef GEM_DEBUG 60246283Sdfr CTR1(KTR_GEM, "%s: gem_stop", device_get_name(sc->sc_dev)); 60346283Sdfr#endif 60446283Sdfr 60598944Sobrien callout_stop(&sc->sc_tick_ch); 60698944Sobrien 60746283Sdfr /* XXX - Should we reset these instead? */ 60846283Sdfr gem_disable_tx(sc); 60946283Sdfr gem_disable_rx(sc); 61046283Sdfr 61146283Sdfr /* 61246283Sdfr * Release any queued transmit buffers. 61346283Sdfr */ 61446283Sdfr while ((txs = STAILQ_FIRST(&sc->sc_txdirtyq)) != NULL) { 61546283Sdfr STAILQ_REMOVE_HEAD(&sc->sc_txdirtyq, txs_q); 61646283Sdfr if (txs->txs_ndescs != 0) { 61746283Sdfr bus_dmamap_sync(sc->sc_tdmatag, txs->txs_dmamap, 61846283Sdfr BUS_DMASYNC_POSTWRITE); 61946283Sdfr bus_dmamap_unload(sc->sc_tdmatag, txs->txs_dmamap); 62046283Sdfr if (txs->txs_mbuf != NULL) { 62146283Sdfr m_freem(txs->txs_mbuf); 62246283Sdfr txs->txs_mbuf = NULL; 62346283Sdfr } 62446283Sdfr } 62546283Sdfr STAILQ_INSERT_TAIL(&sc->sc_txfreeq, txs, txs_q); 62646283Sdfr } 62746283Sdfr 62846283Sdfr if (disable) 62946283Sdfr gem_rxdrain(sc); 63046283Sdfr 63146283Sdfr /* 63246283Sdfr * Mark the interface down and cancel the watchdog timer. 63346283Sdfr */ 63446283Sdfr ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); 63546283Sdfr ifp->if_timer = 0; 63646283Sdfr} 63746283Sdfr 63846283Sdfr/* 63946283Sdfr * Reset the receiver 64046283Sdfr */ 64146283Sdfrint 64298944Sobriengem_reset_rx(sc) 643130803Smarcel struct gem_softc *sc; 64498944Sobrien{ 64546283Sdfr bus_space_tag_t t = sc->sc_bustag; 64646283Sdfr bus_space_handle_t h = sc->sc_h; 64746283Sdfr 64846283Sdfr /* 64946283Sdfr * Resetting while DMA is in progress can cause a bus hang, so we 65098944Sobrien * disable DMA first. 65198944Sobrien */ 65298944Sobrien gem_disable_rx(sc); 65398944Sobrien bus_space_write_4(t, h, GEM_RX_CONFIG, 0); 65498944Sobrien /* Wait till it finishes */ 65598944Sobrien if (!gem_bitwait(sc, GEM_RX_CONFIG, 1, 0)) 65698944Sobrien device_printf(sc->sc_dev, "cannot disable read dma\n"); 65798944Sobrien 65898944Sobrien /* Wait 5ms extra. */ 65998944Sobrien DELAY(5000); 66098944Sobrien 66146283Sdfr /* Finally, reset the ERX */ 66298944Sobrien bus_space_write_4(t, h, GEM_RESET, GEM_RESET_RX); 66398944Sobrien /* Wait till it finishes */ 66498944Sobrien if (!gem_bitwait(sc, GEM_RESET, GEM_RESET_TX, 0)) { 66598944Sobrien device_printf(sc->sc_dev, "cannot reset receiver\n"); 66698944Sobrien return (1); 66798944Sobrien } 66898944Sobrien return (0); 66998944Sobrien} 67098944Sobrien 67198944Sobrien 67298944Sobrien/* 67346283Sdfr * Reset the transmitter 67498944Sobrien */ 67598944Sobrienstatic int 67698944Sobriengem_reset_tx(sc) 67798944Sobrien struct gem_softc *sc; 67898944Sobrien{ 67998944Sobrien bus_space_tag_t t = sc->sc_bustag; 68098944Sobrien bus_space_handle_t h = sc->sc_h; 68198944Sobrien int i; 68298944Sobrien 68398944Sobrien /* 68498944Sobrien * Resetting while DMA is in progress can cause a bus hang, so we 68546283Sdfr * disable DMA first. 68698944Sobrien */ 68798944Sobrien gem_disable_tx(sc); 68898944Sobrien bus_space_write_4(t, h, GEM_TX_CONFIG, 0); 68998944Sobrien /* Wait till it finishes */ 69098944Sobrien if (!gem_bitwait(sc, GEM_TX_CONFIG, 1, 0)) 69198944Sobrien device_printf(sc->sc_dev, "cannot disable read dma\n"); 69246283Sdfr 69346283Sdfr /* Wait 5ms extra. */ 69446283Sdfr DELAY(5000); 69546283Sdfr 69646283Sdfr /* Finally, reset the ETX */ 69746283Sdfr bus_space_write_4(t, h, GEM_RESET, GEM_RESET_TX); 69846283Sdfr /* Wait till it finishes */ 69946283Sdfr for (i = TRIES; i--; DELAY(100)) 70098944Sobrien if ((bus_space_read_4(t, h, GEM_RESET) & GEM_RESET_TX) == 0) 70198944Sobrien break; 70298944Sobrien if (!gem_bitwait(sc, GEM_RESET, GEM_RESET_TX, 0)) { 70398944Sobrien device_printf(sc->sc_dev, "cannot reset receiver\n"); 70498944Sobrien return (1); 70598944Sobrien } 70698944Sobrien return (0); 70798944Sobrien} 70898944Sobrien 70998944Sobrien/* 71046283Sdfr * disable receiver. 71198944Sobrien */ 71298944Sobrienstatic int 71398944Sobriengem_disable_rx(sc) 71498944Sobrien struct gem_softc *sc; 71598944Sobrien{ 71698944Sobrien bus_space_tag_t t = sc->sc_bustag; 71798944Sobrien bus_space_handle_t h = sc->sc_h; 71898944Sobrien u_int32_t cfg; 71998944Sobrien 72098944Sobrien /* Flip the enable bit */ 72146283Sdfr cfg = bus_space_read_4(t, h, GEM_MAC_RX_CONFIG); 72298944Sobrien cfg &= ~GEM_MAC_RX_ENABLE; 72398944Sobrien bus_space_write_4(t, h, GEM_MAC_RX_CONFIG, cfg); 72498944Sobrien 72598944Sobrien /* Wait for it to finish */ 72698944Sobrien return (gem_bitwait(sc, GEM_MAC_RX_CONFIG, GEM_MAC_RX_ENABLE, 0)); 72798944Sobrien} 72898944Sobrien 72998944Sobrien/* 73098944Sobrien * disable transmitter. 73198944Sobrien */ 73246283Sdfrstatic int 73398944Sobriengem_disable_tx(sc) 73498944Sobrien struct gem_softc *sc; 73598944Sobrien{ 73698944Sobrien bus_space_tag_t t = sc->sc_bustag; 73798944Sobrien bus_space_handle_t h = sc->sc_h; 73898944Sobrien u_int32_t cfg; 73946283Sdfr 74046283Sdfr /* Flip the enable bit */ 74146283Sdfr cfg = bus_space_read_4(t, h, GEM_MAC_TX_CONFIG); 742130803Smarcel cfg &= ~GEM_MAC_TX_ENABLE; 74346283Sdfr bus_space_write_4(t, h, GEM_MAC_TX_CONFIG, cfg); 74446283Sdfr 74546283Sdfr /* Wait for it to finish */ 74646283Sdfr return (gem_bitwait(sc, GEM_MAC_TX_CONFIG, GEM_MAC_TX_ENABLE, 0)); 74746283Sdfr} 74846283Sdfr 74998944Sobrien/* 75098944Sobrien * Initialize interface. 75146283Sdfr */ 75246283Sdfrstatic int 75346283Sdfrgem_meminit(sc) 75498944Sobrien struct gem_softc *sc; 75546283Sdfr{ 75646283Sdfr struct gem_rxsoft *rxs; 75746283Sdfr int i, error; 75898944Sobrien 75946283Sdfr /* 76098944Sobrien * Initialize the transmit descriptor ring. 76146283Sdfr */ 76298944Sobrien memset((void *)sc->sc_txdescs, 0, sizeof(sc->sc_txdescs)); 76346283Sdfr for (i = 0; i < GEM_NTXDESC; i++) { 76446283Sdfr sc->sc_txdescs[i].gd_flags = 0; 76546283Sdfr sc->sc_txdescs[i].gd_addr = 0; 76646283Sdfr } 76746283Sdfr sc->sc_txfree = GEM_MAXTXFREE; 76898944Sobrien sc->sc_txnext = 0; 76998944Sobrien sc->sc_txwin = 0; 77098944Sobrien 77198944Sobrien /* 77298944Sobrien * Initialize the receive descriptor and receive job 77398944Sobrien * descriptor rings. 77446283Sdfr */ 77546283Sdfr for (i = 0; i < GEM_NRXDESC; i++) { 77646283Sdfr rxs = &sc->sc_rxsoft[i]; 77746283Sdfr if (rxs->rxs_mbuf == NULL) { 77898944Sobrien if ((error = gem_add_rxbuf(sc, i)) != 0) { 77946283Sdfr device_printf(sc->sc_dev, "unable to " 78098944Sobrien "allocate or map rx buffer %d, error = " 78198944Sobrien "%d\n", i, error); 78246283Sdfr /* 78398944Sobrien * XXX Should attempt to run with fewer receive 78446283Sdfr * XXX buffers instead of just failing. 785130803Smarcel */ 78646283Sdfr gem_rxdrain(sc); 78746283Sdfr return (1); 78846283Sdfr } 78946283Sdfr } else 79046283Sdfr GEM_INIT_RXDESC(sc, i); 79146283Sdfr } 79246283Sdfr sc->sc_rxptr = 0; 79346283Sdfr GEM_CDSYNC(sc, BUS_DMASYNC_PREWRITE); 79446283Sdfr GEM_CDSYNC(sc, BUS_DMASYNC_PREREAD); 79546283Sdfr 79646283Sdfr return (0); 79746283Sdfr} 79846283Sdfr 79946283Sdfrstatic int 80098944Sobriengem_ringsize(sz) 80146283Sdfr int sz; 80246283Sdfr{ 80398944Sobrien int v = 0; 80498944Sobrien 80546283Sdfr switch (sz) { 80646283Sdfr case 32: 80746283Sdfr v = GEM_RING_SZ_32; 80846283Sdfr break; 80946283Sdfr case 64: 81098944Sobrien v = GEM_RING_SZ_64; 81198944Sobrien break; 81298944Sobrien case 128: 81398944Sobrien v = GEM_RING_SZ_128; 81498944Sobrien break; 81546283Sdfr case 256: 81646283Sdfr v = GEM_RING_SZ_256; 81746283Sdfr break; 81846283Sdfr case 512: 81946283Sdfr v = GEM_RING_SZ_512; 82046283Sdfr break; 82198944Sobrien case 1024: 82298944Sobrien v = GEM_RING_SZ_1024; 82398944Sobrien break; 82498944Sobrien case 2048: 82598944Sobrien v = GEM_RING_SZ_2048; 82698944Sobrien break; 82798944Sobrien case 4096: 82898944Sobrien v = GEM_RING_SZ_4096; 82998944Sobrien break; 83098944Sobrien case 8192: 83198944Sobrien v = GEM_RING_SZ_8192; 83298944Sobrien break; 83398944Sobrien default: 83498944Sobrien printf("gem: invalid Receive Descriptor ring size\n"); 83598944Sobrien break; 83646283Sdfr } 83746283Sdfr return (v); 83846283Sdfr} 83946283Sdfr 84046283Sdfr/* 84146283Sdfr * Initialization of interface; set up initialization block 84246283Sdfr * and transmit/receive descriptor rings. 84346283Sdfr */ 84446283Sdfrstatic void 84546283Sdfrgem_init(xsc) 84698944Sobrien void *xsc; 84798944Sobrien{ 84898944Sobrien struct gem_softc *sc = (struct gem_softc *)xsc; 84946283Sdfr struct ifnet *ifp = &sc->sc_arpcom.ac_if; 85098944Sobrien bus_space_tag_t t = sc->sc_bustag; 85198944Sobrien bus_space_handle_t h = sc->sc_h; 85298944Sobrien int s; 85398944Sobrien u_int32_t v; 85498944Sobrien 85598944Sobrien s = splnet(); 85698944Sobrien 85746283Sdfr#ifdef GEM_DEBUG 85898944Sobrien CTR1(KTR_GEM, "%s: gem_init: calling stop", device_get_name(sc->sc_dev)); 85998944Sobrien#endif 86098944Sobrien /* 86198944Sobrien * Initialization sequence. The numbered steps below correspond 86298944Sobrien * to the sequence outlined in section 6.3.5.1 in the Ethernet 86398944Sobrien * Channel Engine manual (part of the PCIO manual). 86498944Sobrien * See also the STP2002-STQ document from Sun Microsystems. 86598944Sobrien */ 86698944Sobrien 86798944Sobrien /* step 1 & 2. Reset the Ethernet Channel */ 86898944Sobrien gem_stop(&sc->sc_arpcom.ac_if, 0); 86998944Sobrien gem_reset(sc); 87098944Sobrien#ifdef GEM_DEBUG 87198944Sobrien CTR1(KTR_GEM, "%s: gem_init: restarting", device_get_name(sc->sc_dev)); 87246283Sdfr#endif 87346283Sdfr 87446283Sdfr /* Re-initialize the MIF */ 87546283Sdfr gem_mifinit(sc); 87698944Sobrien 87798944Sobrien /* step 3. Setup data structures in host memory */ 87898944Sobrien gem_meminit(sc); 87998944Sobrien 88098944Sobrien /* step 4. TX MAC registers & counters */ 88198944Sobrien gem_init_regs(sc); 882130803Smarcel /* XXX: VLAN code from NetBSD temporarily removed. */ 88346283Sdfr bus_space_write_4(t, h, GEM_MAC_MAC_MAX_FRAME, 88446283Sdfr (ETHER_MAX_LEN + sizeof(struct ether_header)) | (0x2000<<16)); 88519370Spst 88619370Spst /* step 5. RX MAC registers & counters */ 887130803Smarcel gem_setladrf(sc); 88898944Sobrien 88919370Spst /* step 6 & 7. Program Descriptor Ring Base Addresses */ 89019370Spst /* NOTE: we use only 32-bit DMA addresses here. */ 89119370Spst bus_space_write_4(t, h, GEM_TX_RING_PTR_HI, 0); 89219370Spst bus_space_write_4(t, h, GEM_TX_RING_PTR_LO, GEM_CDTXADDR(sc, 0)); 89319370Spst 894130803Smarcel bus_space_write_4(t, h, GEM_RX_RING_PTR_HI, 0); 89598944Sobrien bus_space_write_4(t, h, GEM_RX_RING_PTR_LO, GEM_CDRXADDR(sc, 0)); 89619370Spst#ifdef GEM_DEBUG 89719370Spst CTR3(KTR_GEM, "loading rx ring %lx, tx ring %lx, cddma %lx", 89819370Spst GEM_CDRXADDR(sc, 0), GEM_CDTXADDR(sc, 0), sc->sc_cddma); 89919370Spst#endif 90019370Spst 90119370Spst /* step 8. Global Configuration & Interrupt Mask */ 90219370Spst bus_space_write_4(t, h, GEM_INTMASK, 90319370Spst ~(GEM_INTR_TX_INTME| 90419370Spst GEM_INTR_TX_EMPTY| 90519370Spst GEM_INTR_RX_DONE|GEM_INTR_RX_NOBUF| 90619370Spst GEM_INTR_RX_TAG_ERR|GEM_INTR_PCS| 90719370Spst GEM_INTR_MAC_CONTROL|GEM_INTR_MIF| 90819370Spst GEM_INTR_BERR)); 90919370Spst bus_space_write_4(t, h, GEM_MAC_RX_MASK, 91019370Spst GEM_MAC_RX_DONE|GEM_MAC_RX_FRAME_CNT); 91119370Spst bus_space_write_4(t, h, GEM_MAC_TX_MASK, 0xffff); /* XXXX */ 91219370Spst bus_space_write_4(t, h, GEM_MAC_CONTROL_MASK, 0); /* XXXX */ 913130803Smarcel 91419370Spst /* step 9. ETX Configuration: use mostly default values */ 91519370Spst 916130803Smarcel /* Enable DMA */ 917130803Smarcel v = gem_ringsize(GEM_NTXDESC /*XXX*/); 918130803Smarcel bus_space_write_4(t, h, GEM_TX_CONFIG, 919130803Smarcel v|GEM_TX_CONFIG_TXDMA_EN| 920130803Smarcel ((0x400<<10)&GEM_TX_CONFIG_TXFIFO_TH)); 921130803Smarcel 922130803Smarcel /* step 10. ERX Configuration */ 923130803Smarcel 924130803Smarcel /* Encode Receive Descriptor ring size: four possible values */ 925130803Smarcel v = gem_ringsize(GEM_NRXDESC /*XXX*/); 926130803Smarcel 927130803Smarcel /* Enable DMA */ 928130803Smarcel bus_space_write_4(t, h, GEM_RX_CONFIG, 929130803Smarcel v|(GEM_THRSH_1024<<GEM_RX_CONFIG_FIFO_THRS_SHIFT)| 930130803Smarcel (2<<GEM_RX_CONFIG_FBOFF_SHFT)|GEM_RX_CONFIG_RXDMA_EN| 931130803Smarcel (0<<GEM_RX_CONFIG_CXM_START_SHFT)); 932130803Smarcel /* 933130803Smarcel * The following value is for an OFF Threshold of about 3/4 full 934130803Smarcel * and an ON Threshold of 1/4 full. 935130803Smarcel */ 936130803Smarcel bus_space_write_4(t, h, GEM_RX_PAUSE_THRESH, 937130803Smarcel (3 * sc->sc_rxfifosize / 256) | 938130803Smarcel ( (sc->sc_rxfifosize / 256) << 12)); 939130803Smarcel bus_space_write_4(t, h, GEM_RX_BLANKING, (6<<12)|6); 940130803Smarcel 941130803Smarcel /* step 11. Configure Media */ 942130803Smarcel mii_mediachg(sc->sc_mii); 943130803Smarcel 944130803Smarcel /* step 12. RX_MAC Configuration Register */ 945130803Smarcel v = bus_space_read_4(t, h, GEM_MAC_RX_CONFIG); 946130803Smarcel v |= GEM_MAC_RX_ENABLE; 947130803Smarcel bus_space_write_4(t, h, GEM_MAC_RX_CONFIG, v); 948130803Smarcel 949130803Smarcel /* step 14. Issue Transmit Pending command */ 95019370Spst 95198944Sobrien /* step 15. Give the reciever a swift kick */ 95219370Spst bus_space_write_4(t, h, GEM_RX_KICK, GEM_NRXDESC-4); 95398944Sobrien 95498944Sobrien /* Start the one second timer. */ 95598944Sobrien callout_reset(&sc->sc_tick_ch, hz, gem_tick, sc); 95698944Sobrien 95798944Sobrien ifp->if_flags |= IFF_RUNNING; 95819370Spst ifp->if_flags &= ~IFF_OACTIVE; 95919370Spst ifp->if_timer = 0; 96098944Sobrien sc->sc_ifflags = ifp->if_flags; 96198944Sobrien splx(s); 96298944Sobrien} 96398944Sobrien 96419370Spststatic int 96519370Spstgem_load_txmbuf(sc, m0) 96619370Spst struct gem_softc *sc; 96719370Spst struct mbuf *m0; 96819370Spst{ 96919370Spst struct gem_txdma txd; 97019370Spst struct gem_txsoft *txs; 97119370Spst int error; 97219370Spst 97319370Spst /* Get a work queue entry. */ 97498944Sobrien if ((txs = STAILQ_FIRST(&sc->sc_txfreeq)) == NULL) { 97519370Spst /* Ran out of descriptors. */ 97619370Spst return (-1); 97719370Spst } 97819370Spst txd.txd_sc = sc; 97919370Spst txd.txd_txs = txs; 98019370Spst txs->txs_mbuf = m0; 98119370Spst txs->txs_firstdesc = sc->sc_txnext; 98219370Spst error = bus_dmamap_load_mbuf(sc->sc_tdmatag, txs->txs_dmamap, m0, 98319370Spst gem_txdma_callback, &txd, BUS_DMA_NOWAIT); 98419370Spst if (error != 0) 98519370Spst goto fail; 98619370Spst if (txs->txs_ndescs == -1) { 98719370Spst error = -1; 98819370Spst goto fail; 98919370Spst } 99019370Spst 99119370Spst /* Sync the DMA map. */ 99219370Spst bus_dmamap_sync(sc->sc_tdmatag, txs->txs_dmamap, 99319370Spst BUS_DMASYNC_PREWRITE); 99419370Spst 99519370Spst#ifdef GEM_DEBUG 99619370Spst CTR3(KTR_GEM, "load_mbuf: setting firstdesc=%d, lastdesc=%d, " 99719370Spst "ndescs=%d", txs->txs_firstdesc, txs->txs_lastdesc, 99819370Spst txs->txs_ndescs); 99998944Sobrien#endif 100019370Spst STAILQ_REMOVE_HEAD(&sc->sc_txfreeq, txs_q); 100119370Spst STAILQ_INSERT_TAIL(&sc->sc_txdirtyq, txs, txs_q); 100219370Spst 100319370Spst sc->sc_txnext = GEM_NEXTTX(txs->txs_lastdesc); 100419370Spst sc->sc_txfree -= txs->txs_ndescs; 100519370Spst return (0); 100619370Spst 100719370Spstfail: 100846283Sdfr#ifdef GEM_DEBUG 100919370Spst CTR1(KTR_GEM, "gem_load_txmbuf failed (%d)", error); 101019370Spst#endif 101119370Spst bus_dmamap_unload(sc->sc_tdmatag, txs->txs_dmamap); 101219370Spst return (error); 101319370Spst} 101419370Spst 101519370Spststatic void 101619370Spstgem_init_regs(sc) 101719370Spst struct gem_softc *sc; 101819370Spst{ 101946283Sdfr bus_space_tag_t t = sc->sc_bustag; 102019370Spst bus_space_handle_t h = sc->sc_h; 102119370Spst const u_char *laddr = sc->sc_arpcom.ac_enaddr; 102219370Spst u_int32_t v; 102319370Spst 102419370Spst /* These regs are not cleared on reset */ 102519370Spst if (!sc->sc_inited) { 102619370Spst 102719370Spst /* Wooo. Magic values. */ 102819370Spst bus_space_write_4(t, h, GEM_MAC_IPG0, 0); 102919370Spst bus_space_write_4(t, h, GEM_MAC_IPG1, 8); 103019370Spst bus_space_write_4(t, h, GEM_MAC_IPG2, 4); 103119370Spst 103298944Sobrien bus_space_write_4(t, h, GEM_MAC_MAC_MIN_FRAME, ETHER_MIN_LEN); 103398944Sobrien /* Max frame and max burst size */ 103498944Sobrien bus_space_write_4(t, h, GEM_MAC_MAC_MAX_FRAME, 103598944Sobrien ETHER_MAX_LEN | (0x2000<<16)); 103698944Sobrien 103798944Sobrien bus_space_write_4(t, h, GEM_MAC_PREAMBLE_LEN, 0x7); 103898944Sobrien bus_space_write_4(t, h, GEM_MAC_JAM_SIZE, 0x4); 103998944Sobrien bus_space_write_4(t, h, GEM_MAC_ATTEMPT_LIMIT, 0x10); 104098944Sobrien /* Dunno.... */ 104198944Sobrien bus_space_write_4(t, h, GEM_MAC_CONTROL_TYPE, 0x8088); 104298944Sobrien bus_space_write_4(t, h, GEM_MAC_RANDOM_SEED, 104398944Sobrien ((laddr[5]<<8)|laddr[4])&0x3ff); 104498944Sobrien 104598944Sobrien /* Secondary MAC addr set to 0:0:0:0:0:0 */ 104698944Sobrien bus_space_write_4(t, h, GEM_MAC_ADDR3, 0); 104798944Sobrien bus_space_write_4(t, h, GEM_MAC_ADDR4, 0); 104898944Sobrien bus_space_write_4(t, h, GEM_MAC_ADDR5, 0); 104998944Sobrien 105098944Sobrien /* MAC control addr set to 01:80:c2:00:00:01 */ 105198944Sobrien bus_space_write_4(t, h, GEM_MAC_ADDR6, 0x0001); 105298944Sobrien bus_space_write_4(t, h, GEM_MAC_ADDR7, 0xc200); 105398944Sobrien bus_space_write_4(t, h, GEM_MAC_ADDR8, 0x0180); 105498944Sobrien 105598944Sobrien /* MAC filter addr set to 0:0:0:0:0:0 */ 105698944Sobrien bus_space_write_4(t, h, GEM_MAC_ADDR_FILTER0, 0); 105798944Sobrien bus_space_write_4(t, h, GEM_MAC_ADDR_FILTER1, 0); 105898944Sobrien bus_space_write_4(t, h, GEM_MAC_ADDR_FILTER2, 0); 105998944Sobrien 106098944Sobrien bus_space_write_4(t, h, GEM_MAC_ADR_FLT_MASK1_2, 0); 106198944Sobrien bus_space_write_4(t, h, GEM_MAC_ADR_FLT_MASK0, 0); 106298944Sobrien 106398944Sobrien sc->sc_inited = 1; 106498944Sobrien } 106598944Sobrien 106698944Sobrien /* Counters need to be zeroed */ 106798944Sobrien bus_space_write_4(t, h, GEM_MAC_NORM_COLL_CNT, 0); 106898944Sobrien bus_space_write_4(t, h, GEM_MAC_FIRST_COLL_CNT, 0); 106998944Sobrien bus_space_write_4(t, h, GEM_MAC_EXCESS_COLL_CNT, 0); 107098944Sobrien bus_space_write_4(t, h, GEM_MAC_LATE_COLL_CNT, 0); 107198944Sobrien bus_space_write_4(t, h, GEM_MAC_DEFER_TMR_CNT, 0); 107298944Sobrien bus_space_write_4(t, h, GEM_MAC_PEAK_ATTEMPTS, 0); 107319370Spst bus_space_write_4(t, h, GEM_MAC_RX_FRAME_COUNT, 0); 107498944Sobrien bus_space_write_4(t, h, GEM_MAC_RX_LEN_ERR_CNT, 0); 107598944Sobrien bus_space_write_4(t, h, GEM_MAC_RX_ALIGN_ERR, 0); 107698944Sobrien bus_space_write_4(t, h, GEM_MAC_RX_CRC_ERR_CNT, 0); 107798944Sobrien bus_space_write_4(t, h, GEM_MAC_RX_CODE_VIOL, 0); 107819370Spst 107946283Sdfr /* Un-pause stuff */ 108019370Spst#if 0 108119370Spst bus_space_write_4(t, h, GEM_MAC_SEND_PAUSE_CMD, 0x1BF0); 108298944Sobrien#else 108319370Spst bus_space_write_4(t, h, GEM_MAC_SEND_PAUSE_CMD, 0); 108419370Spst#endif 108519370Spst 108646283Sdfr /* 108746283Sdfr * Set the station address. 108846283Sdfr */ 108919370Spst bus_space_write_4(t, h, GEM_MAC_ADDR0, (laddr[4]<<8)|laddr[5]); 109019370Spst bus_space_write_4(t, h, GEM_MAC_ADDR1, (laddr[2]<<8)|laddr[3]); 109119370Spst bus_space_write_4(t, h, GEM_MAC_ADDR2, (laddr[0]<<8)|laddr[1]); 109298944Sobrien 109346283Sdfr /* 109419370Spst * Enable MII outputs. Enable GMII if there is a gigabit PHY. 109519370Spst */ 109619370Spst sc->sc_mif_config = bus_space_read_4(t, h, GEM_MIF_CONFIG); 109746283Sdfr v = GEM_MAC_XIF_TX_MII_ENA; 109846283Sdfr if (sc->sc_mif_config & GEM_MIF_CONFIG_MDI1) { 109919370Spst v |= GEM_MAC_XIF_FDPLX_LED; 110019370Spst if (sc->sc_flags & GEM_GIGABIT) 110119370Spst v |= GEM_MAC_XIF_GMII_MODE; 110219370Spst } 110346283Sdfr bus_space_write_4(t, h, GEM_MAC_XIF_CONFIG, v); 110419370Spst} 110519370Spst 110646283Sdfrstatic void 110746283Sdfrgem_start(ifp) 110819370Spst struct ifnet *ifp; 110919370Spst{ 111019370Spst struct gem_softc *sc = (struct gem_softc *)ifp->if_softc; 111119370Spst struct mbuf *m0 = NULL; 111219370Spst int firsttx, ntx = 0, ofree, txmfail; 111319370Spst 111446283Sdfr if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING) 111519370Spst return; 111619370Spst 111719370Spst /* 111819370Spst * Remember the previous number of free descriptors and 111946283Sdfr * the first descriptor we'll use. 112046283Sdfr */ 112119370Spst ofree = sc->sc_txfree; 112246283Sdfr firsttx = sc->sc_txnext; 112346283Sdfr 112446283Sdfr#ifdef GEM_DEBUG 112546283Sdfr CTR3(KTR_GEM, "%s: gem_start: txfree %d, txnext %d", 112698944Sobrien device_get_name(sc->sc_dev), ofree, firsttx); 112719370Spst#endif 112898944Sobrien 112946283Sdfr /* 113046283Sdfr * Loop through the send queue, setting up transmit descriptors 113146283Sdfr * until we drain the queue, or use up all available transmit 113246283Sdfr * descriptors. 113346283Sdfr */ 113446283Sdfr txmfail = 0; 113546283Sdfr do { 113646283Sdfr /* 113746283Sdfr * Grab a packet off the queue. 113846283Sdfr */ 113946283Sdfr IF_DEQUEUE(&ifp->if_snd, m0); 114046283Sdfr if (m0 == NULL) 114146283Sdfr break; 114246283Sdfr 114346283Sdfr txmfail = gem_load_txmbuf(sc, m0); 114446283Sdfr if (txmfail > 0) { 114546283Sdfr /* Drop the mbuf and complain. */ 114646283Sdfr printf("gem_start: error %d while loading mbuf dma " 114746283Sdfr "map\n", txmfail); 114846283Sdfr continue; 114998944Sobrien } 115046283Sdfr /* Not enough descriptors. */ 115146283Sdfr if (txmfail == -1) { 115246283Sdfr if (sc->sc_txfree == GEM_MAXTXFREE) 115346283Sdfr panic("gem_start: mbuf chain too long!"); 115498944Sobrien IF_PREPEND(&ifp->if_snd, m0); 115598944Sobrien break; 115646283Sdfr } 115746283Sdfr 115846283Sdfr ntx++; 115946283Sdfr /* Kick the transmitter. */ 116046283Sdfr#ifdef GEM_DEBUG 116146283Sdfr CTR2(KTR_GEM, "%s: gem_start: kicking tx %d", 116246283Sdfr device_get_name(sc->sc_dev), sc->sc_txnext); 116346283Sdfr#endif 116446283Sdfr bus_space_write_4(sc->sc_bustag, sc->sc_h, GEM_TX_KICK, 116546283Sdfr sc->sc_txnext); 116646283Sdfr 116746283Sdfr if (ifp->if_bpf != NULL) 116846283Sdfr bpf_mtap(ifp->if_bpf, m0); 116946283Sdfr } while (1); 117046283Sdfr 117146283Sdfr if (txmfail == -1 || sc->sc_txfree == 0) { 117246283Sdfr /* No more slots left; notify upper layer. */ 117346283Sdfr ifp->if_flags |= IFF_OACTIVE; 117446283Sdfr } 117546283Sdfr 117646283Sdfr if (ntx > 0) { 117746283Sdfr GEM_CDSYNC(sc, BUS_DMASYNC_PREWRITE); 117846283Sdfr 117946283Sdfr#ifdef GEM_DEBUG 118046283Sdfr CTR2(KTR_GEM, "%s: packets enqueued, OWN on %d", 118198944Sobrien device_get_name(sc->sc_dev), firsttx); 118298944Sobrien#endif 118398944Sobrien 118446283Sdfr /* Set a watchdog timer in case the chip flakes out. */ 118546283Sdfr ifp->if_timer = 5; 118646283Sdfr#ifdef GEM_DEBUG 118746283Sdfr CTR2(KTR_GEM, "%s: gem_start: watchdog %d", 118846283Sdfr device_get_name(sc->sc_dev), ifp->if_timer); 118946283Sdfr#endif 119046283Sdfr } 119119370Spst} 119219370Spst 119319370Spst/* 119419370Spst * Transmit interrupt. 119546283Sdfr */ 119619370Spststatic void 119746283Sdfrgem_tint(sc) 119819370Spst struct gem_softc *sc; 119946283Sdfr{ 120046283Sdfr struct ifnet *ifp = &sc->sc_arpcom.ac_if; 120119370Spst bus_space_tag_t t = sc->sc_bustag; 120298944Sobrien bus_space_handle_t mac = sc->sc_h; 120398944Sobrien struct gem_txsoft *txs; 120446283Sdfr int txlast; 120546283Sdfr int progress = 0; 120646283Sdfr 120746283Sdfr 120846283Sdfr#ifdef GEM_DEBUG 120946283Sdfr CTR1(KTR_GEM, "%s: gem_tint", device_get_name(sc->sc_dev)); 121019370Spst#endif 121198944Sobrien 121219370Spst /* 121319370Spst * Unload collision counters 121498944Sobrien */ 121598944Sobrien ifp->if_collisions += 121619370Spst bus_space_read_4(t, mac, GEM_MAC_NORM_COLL_CNT) + 121719370Spst bus_space_read_4(t, mac, GEM_MAC_FIRST_COLL_CNT) + 121819370Spst bus_space_read_4(t, mac, GEM_MAC_EXCESS_COLL_CNT) + 121919370Spst bus_space_read_4(t, mac, GEM_MAC_LATE_COLL_CNT); 122019370Spst 122119370Spst /* 122219370Spst * then clear the hardware counters. 122319370Spst */ 122419370Spst bus_space_write_4(t, mac, GEM_MAC_NORM_COLL_CNT, 0); 122519370Spst bus_space_write_4(t, mac, GEM_MAC_FIRST_COLL_CNT, 0); 122619370Spst bus_space_write_4(t, mac, GEM_MAC_EXCESS_COLL_CNT, 0); 122719370Spst bus_space_write_4(t, mac, GEM_MAC_LATE_COLL_CNT, 0); 122819370Spst 122919370Spst /* 123098944Sobrien * Go through our Tx list and free mbufs for those 123119370Spst * frames that have been transmitted. 123219370Spst */ 123319370Spst GEM_CDSYNC(sc, BUS_DMASYNC_POSTREAD); 123419370Spst while ((txs = STAILQ_FIRST(&sc->sc_txdirtyq)) != NULL) { 123519370Spst 123619370Spst#ifdef GEM_DEBUG 123719370Spst if (ifp->if_flags & IFF_DEBUG) { 123819370Spst int i; 123919370Spst printf(" txsoft %p transmit chain:\n", txs); 124019370Spst for (i = txs->txs_firstdesc;; i = GEM_NEXTTX(i)) { 124119370Spst printf("descriptor %d: ", i); 124219370Spst printf("gd_flags: 0x%016llx\t", (long long) 124319370Spst GEM_DMA_READ(sc, sc->sc_txdescs[i].gd_flags)); 124419370Spst printf("gd_addr: 0x%016llx\n", (long long) 124519370Spst GEM_DMA_READ(sc, sc->sc_txdescs[i].gd_addr)); 124619370Spst if (i == txs->txs_lastdesc) 124719370Spst break; 124819370Spst } 124919370Spst } 125098944Sobrien#endif 125119370Spst 125298944Sobrien /* 125319370Spst * In theory, we could harveast some descriptors before 125419370Spst * the ring is empty, but that's a bit complicated. 125519370Spst * 125619370Spst * GEM_TX_COMPLETION points to the last descriptor 125719370Spst * processed +1. 125819370Spst */ 125998944Sobrien txlast = bus_space_read_4(t, mac, GEM_TX_COMPLETION); 126019370Spst#ifdef GEM_DEBUG 1261130803Smarcel CTR3(KTR_GEM, "gem_tint: txs->txs_firstdesc = %d, " 126219370Spst "txs->txs_lastdesc = %d, txlast = %d", 126319370Spst txs->txs_firstdesc, txs->txs_lastdesc, txlast); 126419370Spst#endif 126598944Sobrien if (txs->txs_firstdesc <= txs->txs_lastdesc) { 126619370Spst if ((txlast >= txs->txs_firstdesc) && 126719370Spst (txlast <= txs->txs_lastdesc)) 126819370Spst break; 126919370Spst } else { 127019370Spst /* Ick -- this command wraps */ 127119370Spst if ((txlast >= txs->txs_firstdesc) || 127219370Spst (txlast <= txs->txs_lastdesc)) 127319370Spst break; 127419370Spst } 127519370Spst 1276130803Smarcel#ifdef GEM_DEBUG 1277130803Smarcel CTR0(KTR_GEM, "gem_tint: releasing a desc"); 127819370Spst#endif 127919370Spst STAILQ_REMOVE_HEAD(&sc->sc_txdirtyq, txs_q); 128019370Spst 128119370Spst sc->sc_txfree += txs->txs_ndescs; 128219370Spst 128319370Spst bus_dmamap_sync(sc->sc_tdmatag, txs->txs_dmamap, 128419370Spst BUS_DMASYNC_POSTWRITE); 128519370Spst bus_dmamap_unload(sc->sc_tdmatag, txs->txs_dmamap); 128619370Spst if (txs->txs_mbuf != NULL) { 128719370Spst m_freem(txs->txs_mbuf); 128819370Spst txs->txs_mbuf = NULL; 128919370Spst } 129098944Sobrien 129119370Spst STAILQ_INSERT_TAIL(&sc->sc_txfreeq, txs, txs_q); 1292130803Smarcel 129319370Spst ifp->if_opackets++; 129419370Spst progress = 1; 129519370Spst } 129698944Sobrien 129719370Spst#ifdef GEM_DEBUG 129819370Spst CTR3(KTR_GEM, "gem_tint: GEM_TX_STATE_MACHINE %x " 129919370Spst "GEM_TX_DATA_PTR %llx " 130019370Spst "GEM_TX_COMPLETION %x", 130119370Spst bus_space_read_4(sc->sc_bustag, sc->sc_h, GEM_TX_STATE_MACHINE), 130219370Spst ((long long) bus_space_read_4(sc->sc_bustag, sc->sc_h, 130398944Sobrien GEM_TX_DATA_PTR_HI) << 32) | 130419370Spst bus_space_read_4(sc->sc_bustag, sc->sc_h, 130519370Spst GEM_TX_DATA_PTR_LO), 130698944Sobrien bus_space_read_4(sc->sc_bustag, sc->sc_h, GEM_TX_COMPLETION)); 130719370Spst#endif 130819370Spst 130998944Sobrien if (progress) { 131019370Spst if (sc->sc_txfree == GEM_NTXDESC - 1) 131119370Spst sc->sc_txwin = 0; 1312130803Smarcel 1313130803Smarcel /* Freed some descriptors, so reset IFF_OACTIVE and restart. */ 131419370Spst ifp->if_flags &= ~IFF_OACTIVE; 131519370Spst gem_start(ifp); 131619370Spst 131719370Spst if (STAILQ_EMPTY(&sc->sc_txdirtyq)) 131819370Spst ifp->if_timer = 0; 131919370Spst } 132019370Spst 132119370Spst#ifdef GEM_DEBUG 132219370Spst CTR2(KTR_GEM, "%s: gem_tint: watchdog %d", 132319370Spst device_get_name(sc->sc_dev), ifp->if_timer); 132419370Spst#endif 132519370Spst} 132619370Spst 132719370Spst#if 0 132819370Spststatic void 132919370Spstgem_rint_timeout(arg) 133019370Spst void *arg; 133119370Spst{ 133219370Spst 133319370Spst gem_rint((struct gem_softc *)arg); 133498944Sobrien} 133519370Spst#endif 133619370Spst 133719370Spst/* 133898944Sobrien * Receive interrupt. 133919370Spst */ 134019370Spststatic void 134119370Spstgem_rint(sc) 134219370Spst struct gem_softc *sc; 134319370Spst{ 134419370Spst struct ifnet *ifp = &sc->sc_arpcom.ac_if; 134519370Spst bus_space_tag_t t = sc->sc_bustag; 134619370Spst bus_space_handle_t h = sc->sc_h; 134719370Spst struct gem_rxsoft *rxs; 134819370Spst struct mbuf *m; 134919370Spst u_int64_t rxstat; 135019370Spst u_int32_t rxcomp; 135198944Sobrien int i, len, progress = 0; 135219370Spst 135319370Spst callout_stop(&sc->sc_rx_ch); 135419370Spst#ifdef GEM_DEBUG 135519370Spst CTR1(KTR_GEM, "%s: gem_rint", device_get_name(sc->sc_dev)); 135619370Spst#endif 135719370Spst 135819370Spst /* 135919370Spst * Read the completion register once. This limits 136019370Spst * how long the following loop can execute. 136119370Spst */ 136219370Spst rxcomp = bus_space_read_4(t, h, GEM_RX_COMPLETION); 136319370Spst 136419370Spst#ifdef GEM_DEBUG 136519370Spst CTR2(KTR_GEM, "gem_rint: sc->rxptr %d, complete %d", 136619370Spst sc->sc_rxptr, rxcomp); 136719370Spst#endif 136819370Spst GEM_CDSYNC(sc, BUS_DMASYNC_POSTREAD); 136998944Sobrien for (i = sc->sc_rxptr; i != rxcomp; 137019370Spst i = GEM_NEXTRX(i)) { 137119370Spst rxs = &sc->sc_rxsoft[i]; 137298944Sobrien 137319370Spst rxstat = GEM_DMA_READ(sc, sc->sc_rxdescs[i].gd_flags); 137419370Spst 137598944Sobrien if (rxstat & GEM_RD_OWN) { 137619370Spst#if 0 /* XXX: In case of emergency, re-enable this. */ 137719370Spst /* 137819370Spst * The descriptor is still marked as owned, although 137919370Spst * it is supposed to have completed. This has been 138098944Sobrien * observed on some machines. Just exiting here 138119370Spst * might leave the packet sitting around until another 138219370Spst * one arrives to trigger a new interrupt, which is 138319370Spst * generally undesirable, so set up a timeout. 138419370Spst */ 138519370Spst callout_reset(&sc->sc_rx_ch, GEM_RXOWN_TICKS, 138698944Sobrien gem_rint_timeout, sc); 138719370Spst#endif 138819370Spst break; 138919370Spst } 139019370Spst 139119370Spst progress++; 139219370Spst ifp->if_ipackets++; 139398944Sobrien 139498944Sobrien if (rxstat & GEM_RD_BAD_CRC) { 139519370Spst ifp->if_ierrors++; 139619370Spst device_printf(sc->sc_dev, "receive error: CRC error\n"); 139719370Spst GEM_INIT_RXDESC(sc, i); 139819370Spst continue; 139919370Spst } 140098944Sobrien 140198944Sobrien#ifdef GEM_DEBUG 140219370Spst if (ifp->if_flags & IFF_DEBUG) { 140319370Spst printf(" rxsoft %p descriptor %d: ", rxs, i); 140498944Sobrien printf("gd_flags: 0x%016llx\t", (long long) 140519370Spst GEM_DMA_READ(sc, sc->sc_rxdescs[i].gd_flags)); 140619370Spst printf("gd_addr: 0x%016llx\n", (long long) 140719370Spst GEM_DMA_READ(sc, sc->sc_rxdescs[i].gd_addr)); 140819370Spst } 140919370Spst#endif 141019370Spst 141119370Spst /* 141298944Sobrien * No errors; receive the packet. Note the Gem 141319370Spst * includes the CRC with every packet. 141419370Spst */ 141519370Spst len = GEM_RD_BUFLEN(rxstat); 141619370Spst 141719370Spst /* 141819370Spst * Allocate a new mbuf cluster. If that fails, we are 141998944Sobrien * out of memory, and must drop the packet and recycle 142019370Spst * the buffer that's already attached to this descriptor. 142119370Spst */ 142219370Spst m = rxs->rxs_mbuf; 142319370Spst if (gem_add_rxbuf(sc, i) != 0) { 142419370Spst ifp->if_ierrors++; 142519370Spst GEM_INIT_RXDESC(sc, i); 142619370Spst continue; 142798944Sobrien } 142819370Spst m->m_data += 2; /* We're already off by two */ 142919370Spst 143019370Spst m->m_pkthdr.rcvif = ifp; 143119370Spst m->m_pkthdr.len = m->m_len = len - ETHER_CRC_LEN; 143219370Spst 143398944Sobrien /* Pass it on. */ 143419370Spst (*ifp->if_input)(ifp, m); 143519370Spst } 143619370Spst 143798944Sobrien if (progress) { 143819370Spst GEM_CDSYNC(sc, BUS_DMASYNC_PREWRITE); 143919370Spst /* Update the receive pointer. */ 144098944Sobrien if (i == sc->sc_rxptr) { 144119370Spst device_printf(sc->sc_dev, "rint: ring wrap\n"); 144219370Spst } 144319370Spst sc->sc_rxptr = i; 144419370Spst bus_space_write_4(t, h, GEM_RX_KICK, GEM_PREVRX(i)); 144519370Spst } 144698944Sobrien 144719370Spst#ifdef GEM_DEBUG 144819370Spst CTR2(KTR_GEM, "gem_rint: done sc->rxptr %d, complete %d", 144919370Spst sc->sc_rxptr, bus_space_read_4(t, h, GEM_RX_COMPLETION)); 145019370Spst#endif 145119370Spst} 145298944Sobrien 145398944Sobrien 145498944Sobrien/* 145519370Spst * gem_add_rxbuf: 145698944Sobrien * 145719370Spst * Add a receive buffer to the indicated descriptor. 145819370Spst */ 145998944Sobrienstatic int 146098944Sobriengem_add_rxbuf(sc, idx) 146198944Sobrien struct gem_softc *sc; 146219370Spst int idx; 146398944Sobrien{ 146419370Spst struct gem_rxsoft *rxs = &sc->sc_rxsoft[idx]; 146519370Spst struct mbuf *m; 146619370Spst int error; 146719370Spst 146819370Spst m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); 146919370Spst if (m == NULL) 147019370Spst return (ENOBUFS); 147119370Spst m->m_len = m->m_pkthdr.len = m->m_ext.ext_size; 147219370Spst 147319370Spst#ifdef GEM_DEBUG 147419370Spst /* bzero the packet to check dma */ 147519370Spst memset(m->m_ext.ext_buf, 0, m->m_ext.ext_size); 147619370Spst#endif 147719370Spst 147819370Spst if (rxs->rxs_mbuf != NULL) { 147919370Spst bus_dmamap_sync(sc->sc_rdmatag, rxs->rxs_dmamap, 148019370Spst BUS_DMASYNC_POSTREAD); 148119370Spst bus_dmamap_unload(sc->sc_rdmatag, rxs->rxs_dmamap); 148219370Spst } 148319370Spst 148419370Spst rxs->rxs_mbuf = m; 148519370Spst 148619370Spst error = bus_dmamap_load_mbuf(sc->sc_rdmatag, rxs->rxs_dmamap, 1487 m, gem_rxdma_callback, rxs, BUS_DMA_NOWAIT); 1488 if (error != 0 || rxs->rxs_paddr == 0) { 1489 device_printf(sc->sc_dev, "can't load rx DMA map %d, error = " 1490 "%d\n", idx, error); 1491 panic("gem_add_rxbuf"); /* XXX */ 1492 } 1493 1494 bus_dmamap_sync(sc->sc_rdmatag, rxs->rxs_dmamap, BUS_DMASYNC_PREREAD); 1495 1496 GEM_INIT_RXDESC(sc, idx); 1497 1498 return (0); 1499} 1500 1501 1502static void 1503gem_eint(sc, status) 1504 struct gem_softc *sc; 1505 u_int status; 1506{ 1507 1508 if ((status & GEM_INTR_MIF) != 0) { 1509 device_printf(sc->sc_dev, "XXXlink status changed\n"); 1510 return; 1511 } 1512 1513 device_printf(sc->sc_dev, "status=%x\n", status); 1514} 1515 1516 1517void 1518gem_intr(v) 1519 void *v; 1520{ 1521 struct gem_softc *sc = (struct gem_softc *)v; 1522 bus_space_tag_t t = sc->sc_bustag; 1523 bus_space_handle_t seb = sc->sc_h; 1524 u_int32_t status; 1525 1526 status = bus_space_read_4(t, seb, GEM_STATUS); 1527#ifdef GEM_DEBUG 1528 CTR3(KTR_GEM, "%s: gem_intr: cplt %x, status %x", 1529 device_get_name(sc->sc_dev), (status>>19), 1530 (u_int)status); 1531#endif 1532 1533 if ((status & (GEM_INTR_RX_TAG_ERR | GEM_INTR_BERR)) != 0) 1534 gem_eint(sc, status); 1535 1536 if ((status & (GEM_INTR_TX_EMPTY | GEM_INTR_TX_INTME)) != 0) 1537 gem_tint(sc); 1538 1539 if ((status & (GEM_INTR_RX_DONE | GEM_INTR_RX_NOBUF)) != 0) 1540 gem_rint(sc); 1541 1542 /* We should eventually do more than just print out error stats. */ 1543 if (status & GEM_INTR_TX_MAC) { 1544 int txstat = bus_space_read_4(t, seb, GEM_MAC_TX_STATUS); 1545 if (txstat & ~GEM_MAC_TX_XMIT_DONE) 1546 device_printf(sc->sc_dev, "MAC tx fault, status %x\n", 1547 txstat); 1548 if (txstat & (GEM_MAC_TX_UNDERRUN | GEM_MAC_TX_PKT_TOO_LONG)) 1549 gem_init(sc); 1550 } 1551 if (status & GEM_INTR_RX_MAC) { 1552 int rxstat = bus_space_read_4(t, seb, GEM_MAC_RX_STATUS); 1553 if (rxstat & ~(GEM_MAC_RX_DONE | GEM_MAC_RX_FRAME_CNT)) 1554 device_printf(sc->sc_dev, "MAC rx fault, status %x\n", 1555 rxstat); 1556 if ((rxstat & GEM_MAC_RX_OVERFLOW) != 0) 1557 gem_init(sc); 1558 } 1559} 1560 1561 1562static void 1563gem_watchdog(ifp) 1564 struct ifnet *ifp; 1565{ 1566 struct gem_softc *sc = ifp->if_softc; 1567 1568#ifdef GEM_DEBUG 1569 CTR3(KTR_GEM, "gem_watchdog: GEM_RX_CONFIG %x GEM_MAC_RX_STATUS %x " 1570 "GEM_MAC_RX_CONFIG %x", 1571 bus_space_read_4(sc->sc_bustag, sc->sc_h, GEM_RX_CONFIG), 1572 bus_space_read_4(sc->sc_bustag, sc->sc_h, GEM_MAC_RX_STATUS), 1573 bus_space_read_4(sc->sc_bustag, sc->sc_h, GEM_MAC_RX_CONFIG)); 1574 CTR3(KTR_GEM, "gem_watchdog: GEM_TX_CONFIG %x GEM_MAC_TX_STATUS %x " 1575 "GEM_MAC_TX_CONFIG %x", 1576 bus_space_read_4(sc->sc_bustag, sc->sc_h, GEM_TX_CONFIG), 1577 bus_space_read_4(sc->sc_bustag, sc->sc_h, GEM_MAC_TX_STATUS), 1578 bus_space_read_4(sc->sc_bustag, sc->sc_h, GEM_MAC_TX_CONFIG)); 1579#endif 1580 1581 device_printf(sc->sc_dev, "device timeout\n"); 1582 ++ifp->if_oerrors; 1583 1584 /* Try to get more packets going. */ 1585 gem_start(ifp); 1586} 1587 1588/* 1589 * Initialize the MII Management Interface 1590 */ 1591static void 1592gem_mifinit(sc) 1593 struct gem_softc *sc; 1594{ 1595 bus_space_tag_t t = sc->sc_bustag; 1596 bus_space_handle_t mif = sc->sc_h; 1597 1598 /* Configure the MIF in frame mode */ 1599 sc->sc_mif_config = bus_space_read_4(t, mif, GEM_MIF_CONFIG); 1600 sc->sc_mif_config &= ~GEM_MIF_CONFIG_BB_ENA; 1601 bus_space_write_4(t, mif, GEM_MIF_CONFIG, sc->sc_mif_config); 1602} 1603 1604/* 1605 * MII interface 1606 * 1607 * The GEM MII interface supports at least three different operating modes: 1608 * 1609 * Bitbang mode is implemented using data, clock and output enable registers. 1610 * 1611 * Frame mode is implemented by loading a complete frame into the frame 1612 * register and polling the valid bit for completion. 1613 * 1614 * Polling mode uses the frame register but completion is indicated by 1615 * an interrupt. 1616 * 1617 */ 1618int 1619gem_mii_readreg(dev, phy, reg) 1620 device_t dev; 1621 int phy, reg; 1622{ 1623 struct gem_softc *sc = device_get_softc(dev); 1624 bus_space_tag_t t = sc->sc_bustag; 1625 bus_space_handle_t mif = sc->sc_h; 1626 int n; 1627 u_int32_t v; 1628 1629#ifdef GEM_DEBUG_PHY 1630 printf("gem_mii_readreg: phy %d reg %d\n", phy, reg); 1631#endif 1632 1633#if 0 1634 /* Select the desired PHY in the MIF configuration register */ 1635 v = bus_space_read_4(t, mif, GEM_MIF_CONFIG); 1636 /* Clear PHY select bit */ 1637 v &= ~GEM_MIF_CONFIG_PHY_SEL; 1638 if (phy == GEM_PHYAD_EXTERNAL) 1639 /* Set PHY select bit to get at external device */ 1640 v |= GEM_MIF_CONFIG_PHY_SEL; 1641 bus_space_write_4(t, mif, GEM_MIF_CONFIG, v); 1642#endif 1643 1644 /* Construct the frame command */ 1645 v = (reg << GEM_MIF_REG_SHIFT) | (phy << GEM_MIF_PHY_SHIFT) | 1646 GEM_MIF_FRAME_READ; 1647 1648 bus_space_write_4(t, mif, GEM_MIF_FRAME, v); 1649 for (n = 0; n < 100; n++) { 1650 DELAY(1); 1651 v = bus_space_read_4(t, mif, GEM_MIF_FRAME); 1652 if (v & GEM_MIF_FRAME_TA0) 1653 return (v & GEM_MIF_FRAME_DATA); 1654 } 1655 1656 device_printf(sc->sc_dev, "mii_read timeout\n"); 1657 return (0); 1658} 1659 1660int 1661gem_mii_writereg(dev, phy, reg, val) 1662 device_t dev; 1663 int phy, reg, val; 1664{ 1665 struct gem_softc *sc = device_get_softc(dev); 1666 bus_space_tag_t t = sc->sc_bustag; 1667 bus_space_handle_t mif = sc->sc_h; 1668 int n; 1669 u_int32_t v; 1670 1671#ifdef GEM_DEBUG_PHY 1672 printf("gem_mii_writereg: phy %d reg %d val %x\n", phy, reg, val); 1673#endif 1674 1675#if 0 1676 /* Select the desired PHY in the MIF configuration register */ 1677 v = bus_space_read_4(t, mif, GEM_MIF_CONFIG); 1678 /* Clear PHY select bit */ 1679 v &= ~GEM_MIF_CONFIG_PHY_SEL; 1680 if (phy == GEM_PHYAD_EXTERNAL) 1681 /* Set PHY select bit to get at external device */ 1682 v |= GEM_MIF_CONFIG_PHY_SEL; 1683 bus_space_write_4(t, mif, GEM_MIF_CONFIG, v); 1684#endif 1685 /* Construct the frame command */ 1686 v = GEM_MIF_FRAME_WRITE | 1687 (phy << GEM_MIF_PHY_SHIFT) | 1688 (reg << GEM_MIF_REG_SHIFT) | 1689 (val & GEM_MIF_FRAME_DATA); 1690 1691 bus_space_write_4(t, mif, GEM_MIF_FRAME, v); 1692 for (n = 0; n < 100; n++) { 1693 DELAY(1); 1694 v = bus_space_read_4(t, mif, GEM_MIF_FRAME); 1695 if (v & GEM_MIF_FRAME_TA0) 1696 return (1); 1697 } 1698 1699 device_printf(sc->sc_dev, "mii_write timeout\n"); 1700 return (0); 1701} 1702 1703void 1704gem_mii_statchg(dev) 1705 device_t dev; 1706{ 1707 struct gem_softc *sc = device_get_softc(dev); 1708#ifdef GEM_DEBUG 1709 int instance = IFM_INST(sc->sc_mii->mii_media.ifm_cur->ifm_media); 1710#endif 1711 bus_space_tag_t t = sc->sc_bustag; 1712 bus_space_handle_t mac = sc->sc_h; 1713 u_int32_t v; 1714 1715#ifdef GEM_DEBUG 1716 if (sc->sc_debug) 1717 printf("gem_mii_statchg: status change: phy = %d\n", 1718 sc->sc_phys[instance]); 1719#endif 1720 1721 /* Set tx full duplex options */ 1722 bus_space_write_4(t, mac, GEM_MAC_TX_CONFIG, 0); 1723 DELAY(10000); /* reg must be cleared and delay before changing. */ 1724 v = GEM_MAC_TX_ENA_IPG0|GEM_MAC_TX_NGU|GEM_MAC_TX_NGU_LIMIT| 1725 GEM_MAC_TX_ENABLE; 1726 if ((IFM_OPTIONS(sc->sc_mii->mii_media_active) & IFM_FDX) != 0) { 1727 v |= GEM_MAC_TX_IGN_CARRIER|GEM_MAC_TX_IGN_COLLIS; 1728 } 1729 bus_space_write_4(t, mac, GEM_MAC_TX_CONFIG, v); 1730 1731 /* XIF Configuration */ 1732 /* We should really calculate all this rather than rely on defaults */ 1733 v = bus_space_read_4(t, mac, GEM_MAC_XIF_CONFIG); 1734 v = GEM_MAC_XIF_LINK_LED; 1735 v |= GEM_MAC_XIF_TX_MII_ENA; 1736 1737 /* If an external transceiver is connected, enable its MII drivers */ 1738 sc->sc_mif_config = bus_space_read_4(t, mac, GEM_MIF_CONFIG); 1739 if ((sc->sc_mif_config & GEM_MIF_CONFIG_MDI1) != 0) { 1740 /* External MII needs echo disable if half duplex. */ 1741 if ((IFM_OPTIONS(sc->sc_mii->mii_media_active) & IFM_FDX) != 0) 1742 /* turn on full duplex LED */ 1743 v |= GEM_MAC_XIF_FDPLX_LED; 1744 else 1745 /* half duplex -- disable echo */ 1746 v |= GEM_MAC_XIF_ECHO_DISABL; 1747 1748 if (IFM_SUBTYPE(sc->sc_mii->mii_media_active) == IFM_1000_T) 1749 v |= GEM_MAC_XIF_GMII_MODE; 1750 else 1751 v &= ~GEM_MAC_XIF_GMII_MODE; 1752 } else { 1753 /* Internal MII needs buf enable */ 1754 v |= GEM_MAC_XIF_MII_BUF_ENA; 1755 } 1756 bus_space_write_4(t, mac, GEM_MAC_XIF_CONFIG, v); 1757} 1758 1759int 1760gem_mediachange(ifp) 1761 struct ifnet *ifp; 1762{ 1763 struct gem_softc *sc = ifp->if_softc; 1764 1765 /* XXX Add support for serial media. */ 1766 1767 return (mii_mediachg(sc->sc_mii)); 1768} 1769 1770void 1771gem_mediastatus(ifp, ifmr) 1772 struct ifnet *ifp; 1773 struct ifmediareq *ifmr; 1774{ 1775 struct gem_softc *sc = ifp->if_softc; 1776 1777 if ((ifp->if_flags & IFF_UP) == 0) 1778 return; 1779 1780 mii_pollstat(sc->sc_mii); 1781 ifmr->ifm_active = sc->sc_mii->mii_media_active; 1782 ifmr->ifm_status = sc->sc_mii->mii_media_status; 1783} 1784 1785/* 1786 * Process an ioctl request. 1787 */ 1788static int 1789gem_ioctl(ifp, cmd, data) 1790 struct ifnet *ifp; 1791 u_long cmd; 1792 caddr_t data; 1793{ 1794 struct gem_softc *sc = ifp->if_softc; 1795 struct ifreq *ifr = (struct ifreq *)data; 1796 int s, error = 0; 1797 1798 switch (cmd) { 1799 case SIOCSIFADDR: 1800 case SIOCGIFADDR: 1801 case SIOCSIFMTU: 1802 error = ether_ioctl(ifp, cmd, data); 1803 break; 1804 case SIOCSIFFLAGS: 1805 if (ifp->if_flags & IFF_UP) { 1806 if ((sc->sc_ifflags ^ ifp->if_flags) == IFF_PROMISC) 1807 gem_setladrf(sc); 1808 else 1809 gem_init(sc); 1810 } else { 1811 if (ifp->if_flags & IFF_RUNNING) 1812 gem_stop(ifp, 0); 1813 } 1814 sc->sc_ifflags = ifp->if_flags; 1815 error = 0; 1816 break; 1817 case SIOCADDMULTI: 1818 case SIOCDELMULTI: 1819 gem_setladrf(sc); 1820 error = 0; 1821 break; 1822 case SIOCGIFMEDIA: 1823 case SIOCSIFMEDIA: 1824 error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii->mii_media, cmd); 1825 break; 1826 default: 1827 error = ENOTTY; 1828 break; 1829 } 1830 1831 /* Try to get things going again */ 1832 if (ifp->if_flags & IFF_UP) 1833 gem_start(ifp); 1834 splx(s); 1835 return (error); 1836} 1837 1838/* 1839 * Set up the logical address filter. 1840 */ 1841static void 1842gem_setladrf(sc) 1843 struct gem_softc *sc; 1844{ 1845 struct ifnet *ifp = &sc->sc_arpcom.ac_if; 1846 struct ifmultiaddr *inm; 1847 struct sockaddr_dl *sdl; 1848 bus_space_tag_t t = sc->sc_bustag; 1849 bus_space_handle_t h = sc->sc_h; 1850 u_char *cp; 1851 u_int32_t crc; 1852 u_int32_t hash[16]; 1853 u_int32_t v; 1854 int len; 1855 int i; 1856 1857 /* Get current RX configuration */ 1858 v = bus_space_read_4(t, h, GEM_MAC_RX_CONFIG); 1859 1860 /* 1861 * Turn off promiscuous mode, promiscuous group mode (all multicast), 1862 * and hash filter. Depending on the case, the right bit will be 1863 * enabled. 1864 */ 1865 v &= ~(GEM_MAC_RX_PROMISCUOUS|GEM_MAC_RX_HASH_FILTER| 1866 GEM_MAC_RX_PROMISC_GRP); 1867 1868 if ((ifp->if_flags & IFF_PROMISC) != 0) { 1869 /* Turn on promiscuous mode */ 1870 v |= GEM_MAC_RX_PROMISCUOUS; 1871 goto chipit; 1872 } 1873 if ((ifp->if_flags & IFF_ALLMULTI) != 0) { 1874 hash[3] = hash[2] = hash[1] = hash[0] = 0xffff; 1875 ifp->if_flags |= IFF_ALLMULTI; 1876 v |= GEM_MAC_RX_PROMISC_GRP; 1877 goto chipit; 1878 } 1879 1880 /* 1881 * Set up multicast address filter by passing all multicast addresses 1882 * through a crc generator, and then using the high order 8 bits as an 1883 * index into the 256 bit logical address filter. The high order 4 1884 * bits selects the word, while the other 4 bits select the bit within 1885 * the word (where bit 0 is the MSB). 1886 */ 1887 1888 /* Clear hash table */ 1889 memset(hash, 0, sizeof(hash)); 1890 1891 TAILQ_FOREACH(inm, &sc->sc_arpcom.ac_if.if_multiaddrs, ifma_link) { 1892 if (inm->ifma_addr->sa_family != AF_LINK) 1893 continue; 1894 sdl = (struct sockaddr_dl *)inm->ifma_addr; 1895 cp = LLADDR(sdl); 1896 crc = 0xffffffff; 1897 for (len = sdl->sdl_alen; --len >= 0;) { 1898 int octet = *cp++; 1899 int i; 1900 1901#define MC_POLY_LE 0xedb88320UL /* mcast crc, little endian */ 1902 for (i = 0; i < 8; i++) { 1903 if ((crc & 1) ^ (octet & 1)) { 1904 crc >>= 1; 1905 crc ^= MC_POLY_LE; 1906 } else { 1907 crc >>= 1; 1908 } 1909 octet >>= 1; 1910 } 1911 } 1912 /* Just want the 8 most significant bits. */ 1913 crc >>= 24; 1914 1915 /* Set the corresponding bit in the filter. */ 1916 hash[crc >> 4] |= 1 << (15 - (crc & 15)); 1917 } 1918 1919 v |= GEM_MAC_RX_HASH_FILTER; 1920 ifp->if_flags &= ~IFF_ALLMULTI; 1921 1922 /* Now load the hash table into the chip (if we are using it) */ 1923 for (i = 0; i < 16; i++) { 1924 bus_space_write_4(t, h, 1925 GEM_MAC_HASH0 + i * (GEM_MAC_HASH1-GEM_MAC_HASH0), 1926 hash[i]); 1927 } 1928 1929chipit: 1930 bus_space_write_4(t, h, GEM_MAC_RX_CONFIG, v); 1931} 1932