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