Home | History | Annotate | Line # | Download | only in ic
dwc_gmac.c revision 1.88
      1 /* $NetBSD: dwc_gmac.c,v 1.88 2024/07/05 04:31:51 rin Exp $ */
      2 
      3 /*-
      4  * Copyright (c) 2013, 2014 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Matt Thomas of 3am Software Foundry and Martin Husemann.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29  * POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 
     32 /*
     33  * This driver supports the Synopsis Designware GMAC core, as found
     34  * on Allwinner A20 cores and others.
     35  *
     36  * Real documentation seems to not be available, the marketing product
     37  * documents could be found here:
     38  *
     39  *  http://www.synopsys.com/dw/ipdir.php?ds=dwc_ether_mac10_100_1000_unive
     40  */
     41 
     42 #include <sys/cdefs.h>
     43 
     44 __KERNEL_RCSID(1, "$NetBSD: dwc_gmac.c,v 1.88 2024/07/05 04:31:51 rin Exp $");
     45 
     46 /* #define	DWC_GMAC_DEBUG	1 */
     47 
     48 #ifdef _KERNEL_OPT
     49 #include "opt_inet.h"
     50 #endif
     51 
     52 #include <sys/param.h>
     53 #include <sys/bus.h>
     54 #include <sys/device.h>
     55 #include <sys/intr.h>
     56 #include <sys/systm.h>
     57 #include <sys/sockio.h>
     58 #include <sys/cprng.h>
     59 #include <sys/rndsource.h>
     60 
     61 #include <net/if.h>
     62 #include <net/if_ether.h>
     63 #include <net/if_media.h>
     64 #include <net/bpf.h>
     65 #ifdef INET
     66 #include <netinet/if_inarp.h>
     67 #endif
     68 
     69 #include <dev/mii/miivar.h>
     70 
     71 #include <dev/ic/dwc_gmac_reg.h>
     72 #include <dev/ic/dwc_gmac_var.h>
     73 
     74 static int dwc_gmac_miibus_read_reg(device_t, int, int, uint16_t *);
     75 static int dwc_gmac_miibus_write_reg(device_t, int, int, uint16_t);
     76 static void dwc_gmac_miibus_statchg(struct ifnet *);
     77 
     78 static int dwc_gmac_reset(struct dwc_gmac_softc *);
     79 static void dwc_gmac_write_hwaddr(struct dwc_gmac_softc *, uint8_t[ETHER_ADDR_LEN]);
     80 static int dwc_gmac_alloc_dma_rings(struct dwc_gmac_softc *);
     81 static void dwc_gmac_free_dma_rings(struct dwc_gmac_softc *);
     82 static int dwc_gmac_alloc_rx_ring(struct dwc_gmac_softc *, struct dwc_gmac_rx_ring *);
     83 static void dwc_gmac_reset_rx_ring(struct dwc_gmac_softc *, struct dwc_gmac_rx_ring *);
     84 static void dwc_gmac_free_rx_ring(struct dwc_gmac_softc *, struct dwc_gmac_rx_ring *);
     85 static int dwc_gmac_alloc_tx_ring(struct dwc_gmac_softc *, struct dwc_gmac_tx_ring *);
     86 static void dwc_gmac_reset_tx_ring(struct dwc_gmac_softc *, struct dwc_gmac_tx_ring *);
     87 static void dwc_gmac_free_tx_ring(struct dwc_gmac_softc *, struct dwc_gmac_tx_ring *);
     88 static void dwc_gmac_txdesc_sync(struct dwc_gmac_softc *, int, int, int);
     89 static int dwc_gmac_init(struct ifnet *);
     90 static int dwc_gmac_init_locked(struct ifnet *);
     91 static void dwc_gmac_stop(struct ifnet *, int);
     92 static void dwc_gmac_stop_locked(struct ifnet *, int);
     93 static void dwc_gmac_start(struct ifnet *);
     94 static void dwc_gmac_start_locked(struct ifnet *);
     95 static int dwc_gmac_queue(struct dwc_gmac_softc *, struct mbuf *);
     96 static int dwc_gmac_ioctl(struct ifnet *, u_long, void *);
     97 static void dwc_gmac_tx_intr(struct dwc_gmac_softc *);
     98 static void dwc_gmac_rx_intr(struct dwc_gmac_softc *);
     99 static void dwc_gmac_setmulti(struct dwc_gmac_softc *);
    100 static int dwc_gmac_ifflags_cb(struct ethercom *);
    101 static void dwc_gmac_desc_set_owned_by_dev(struct dwc_gmac_dev_dmadesc *);
    102 static int  dwc_gmac_desc_is_owned_by_dev(struct dwc_gmac_dev_dmadesc *);
    103 static void dwc_gmac_desc_std_set_len(struct dwc_gmac_dev_dmadesc *, int);
    104 static uint32_t dwc_gmac_desc_std_get_len(struct dwc_gmac_dev_dmadesc *);
    105 static void dwc_gmac_desc_std_tx_init_flags(struct dwc_gmac_dev_dmadesc *);
    106 static void dwc_gmac_desc_std_tx_set_first_frag(struct dwc_gmac_dev_dmadesc *);
    107 static void dwc_gmac_desc_std_tx_set_last_frag(struct dwc_gmac_dev_dmadesc *);
    108 static void dwc_gmac_desc_std_rx_init_flags(struct dwc_gmac_dev_dmadesc *);
    109 static int  dwc_gmac_desc_std_rx_has_error(struct dwc_gmac_dev_dmadesc *);
    110 static void dwc_gmac_desc_enh_set_len(struct dwc_gmac_dev_dmadesc *, int);
    111 static uint32_t dwc_gmac_desc_enh_get_len(struct dwc_gmac_dev_dmadesc *);
    112 static void dwc_gmac_desc_enh_tx_init_flags(struct dwc_gmac_dev_dmadesc *);
    113 static void dwc_gmac_desc_enh_tx_set_first_frag(struct dwc_gmac_dev_dmadesc *);
    114 static void dwc_gmac_desc_enh_tx_set_last_frag(struct dwc_gmac_dev_dmadesc *);
    115 static void dwc_gmac_desc_enh_rx_init_flags(struct dwc_gmac_dev_dmadesc *);
    116 static int  dwc_gmac_desc_enh_rx_has_error(struct dwc_gmac_dev_dmadesc *);
    117 
    118 static const struct dwc_gmac_desc_methods desc_methods_standard = {
    119 	.tx_init_flags = dwc_gmac_desc_std_tx_init_flags,
    120 	.tx_set_owned_by_dev = dwc_gmac_desc_set_owned_by_dev,
    121 	.tx_is_owned_by_dev = dwc_gmac_desc_is_owned_by_dev,
    122 	.tx_set_len = dwc_gmac_desc_std_set_len,
    123 	.tx_set_first_frag = dwc_gmac_desc_std_tx_set_first_frag,
    124 	.tx_set_last_frag = dwc_gmac_desc_std_tx_set_last_frag,
    125 	.rx_init_flags = dwc_gmac_desc_std_rx_init_flags,
    126 	.rx_set_owned_by_dev = dwc_gmac_desc_set_owned_by_dev,
    127 	.rx_is_owned_by_dev = dwc_gmac_desc_is_owned_by_dev,
    128 	.rx_set_len = dwc_gmac_desc_std_set_len,
    129 	.rx_get_len = dwc_gmac_desc_std_get_len,
    130 	.rx_has_error = dwc_gmac_desc_std_rx_has_error
    131 };
    132 
    133 static const struct dwc_gmac_desc_methods desc_methods_enhanced = {
    134 	.tx_init_flags = dwc_gmac_desc_enh_tx_init_flags,
    135 	.tx_set_owned_by_dev = dwc_gmac_desc_set_owned_by_dev,
    136 	.tx_is_owned_by_dev = dwc_gmac_desc_is_owned_by_dev,
    137 	.tx_set_len = dwc_gmac_desc_enh_set_len,
    138 	.tx_set_first_frag = dwc_gmac_desc_enh_tx_set_first_frag,
    139 	.tx_set_last_frag = dwc_gmac_desc_enh_tx_set_last_frag,
    140 	.rx_init_flags = dwc_gmac_desc_enh_rx_init_flags,
    141 	.rx_set_owned_by_dev = dwc_gmac_desc_set_owned_by_dev,
    142 	.rx_is_owned_by_dev = dwc_gmac_desc_is_owned_by_dev,
    143 	.rx_set_len = dwc_gmac_desc_enh_set_len,
    144 	.rx_get_len = dwc_gmac_desc_enh_get_len,
    145 	.rx_has_error = dwc_gmac_desc_enh_rx_has_error
    146 };
    147 
    148 
    149 #define	TX_DESC_OFFSET(N)	((AWGE_RX_RING_COUNT + (N)) \
    150 				    * sizeof(struct dwc_gmac_dev_dmadesc))
    151 #define	TX_NEXT(N)		(((N) + 1) & (AWGE_TX_RING_COUNT - 1))
    152 
    153 #define RX_DESC_OFFSET(N)	((N) * sizeof(struct dwc_gmac_dev_dmadesc))
    154 #define	RX_NEXT(N)		(((N) + 1) & (AWGE_RX_RING_COUNT - 1))
    155 
    156 
    157 
    158 #define	GMAC_DEF_DMA_INT_MASK	(GMAC_DMA_INT_TIE | GMAC_DMA_INT_RIE | \
    159 				GMAC_DMA_INT_NIE | GMAC_DMA_INT_AIE | \
    160 				GMAC_DMA_INT_FBE | GMAC_DMA_INT_UNE)
    161 
    162 #define	GMAC_DMA_INT_ERRORS	(GMAC_DMA_INT_AIE | GMAC_DMA_INT_ERE | \
    163 				GMAC_DMA_INT_FBE |	\
    164 				GMAC_DMA_INT_RWE | GMAC_DMA_INT_RUE | \
    165 				GMAC_DMA_INT_UNE | GMAC_DMA_INT_OVE | \
    166 				GMAC_DMA_INT_TJE)
    167 
    168 #define	AWIN_DEF_MAC_INTRMASK	\
    169 	(AWIN_GMAC_MAC_INT_TSI | AWIN_GMAC_MAC_INT_ANEG |	\
    170 	AWIN_GMAC_MAC_INT_LINKCHG)
    171 
    172 #ifdef DWC_GMAC_DEBUG
    173 static void dwc_gmac_dump_dma(struct dwc_gmac_softc *);
    174 static void dwc_gmac_dump_tx_desc(struct dwc_gmac_softc *);
    175 static void dwc_gmac_dump_rx_desc(struct dwc_gmac_softc *);
    176 static void dwc_dump_and_abort(struct dwc_gmac_softc *, const char *);
    177 static void dwc_dump_status(struct dwc_gmac_softc *);
    178 static void dwc_gmac_dump_ffilt(struct dwc_gmac_softc *, uint32_t);
    179 #endif
    180 
    181 int
    182 dwc_gmac_attach(struct dwc_gmac_softc *sc, int phy_id, uint32_t mii_clk)
    183 {
    184 	uint8_t enaddr[ETHER_ADDR_LEN];
    185 	uint32_t maclo, machi, ver, hwft;
    186 	struct mii_data * const mii = &sc->sc_mii;
    187 	struct ifnet * const ifp = &sc->sc_ec.ec_if;
    188 	prop_dictionary_t dict;
    189 
    190 	mutex_init(&sc->sc_mdio_lock, MUTEX_DEFAULT, IPL_NET);
    191 	sc->sc_mii_clk = mii_clk & 7;
    192 
    193 	dict = device_properties(sc->sc_dev);
    194 	prop_data_t ea = dict ? prop_dictionary_get(dict, "mac-address") : NULL;
    195 	if (ea != NULL) {
    196 		/*
    197 		 * If the MAC address is overridden by a device property,
    198 		 * use that.
    199 		 */
    200 		KASSERT(prop_object_type(ea) == PROP_TYPE_DATA);
    201 		KASSERT(prop_data_size(ea) == ETHER_ADDR_LEN);
    202 		memcpy(enaddr, prop_data_value(ea), ETHER_ADDR_LEN);
    203 	} else {
    204 		/*
    205 		 * If we did not get an externaly configure address,
    206 		 * try to read one from the current filter setup,
    207 		 * before resetting the chip.
    208 		 */
    209 		maclo = bus_space_read_4(sc->sc_bst, sc->sc_bsh,
    210 		    AWIN_GMAC_MAC_ADDR0LO);
    211 		machi = bus_space_read_4(sc->sc_bst, sc->sc_bsh,
    212 		    AWIN_GMAC_MAC_ADDR0HI);
    213 
    214 		if (maclo == 0xffffffff && (machi & 0xffff) == 0xffff) {
    215 			/* fake MAC address */
    216 			maclo = 0x00f2 | (cprng_strong32() << 16);
    217 			machi = cprng_strong32();
    218 		}
    219 
    220 		enaddr[0] = maclo & 0x0ff;
    221 		enaddr[1] = (maclo >> 8) & 0x0ff;
    222 		enaddr[2] = (maclo >> 16) & 0x0ff;
    223 		enaddr[3] = (maclo >> 24) & 0x0ff;
    224 		enaddr[4] = machi & 0x0ff;
    225 		enaddr[5] = (machi >> 8) & 0x0ff;
    226 	}
    227 
    228 	ver = bus_space_read_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_MAC_VERSION);
    229 	aprint_normal_dev(sc->sc_dev, "Core version: %08x\n", ver);
    230 
    231 	/*
    232 	 * Init chip and do initial setup
    233 	 */
    234 	if (dwc_gmac_reset(sc) != 0)
    235 		return ENXIO;	/* not much to cleanup, haven't attached yet */
    236 	dwc_gmac_write_hwaddr(sc, enaddr);
    237 	aprint_normal_dev(sc->sc_dev, "Ethernet address %s\n",
    238 	    ether_sprintf(enaddr));
    239 
    240 	hwft = 0;
    241 	if (ver >= 0x35) {
    242 		hwft = bus_space_read_4(sc->sc_bst, sc->sc_bsh,
    243 		    AWIN_GMAC_DMA_HWFEATURES);
    244 		aprint_normal_dev(sc->sc_dev,
    245 		    "HW feature mask: %x\n", hwft);
    246 	}
    247 
    248 	if (sizeof(bus_addr_t) > 4) {
    249 		int error = bus_dmatag_subregion(sc->sc_dmat, 0, __MASK(32),
    250 		    &sc->sc_dmat, BUS_DMA_WAITOK);
    251 		if (error != 0) {
    252 			aprint_error_dev(sc->sc_dev,
    253 			    "failed to create DMA subregion\n");
    254 			return ENOMEM;
    255 		}
    256 	}
    257 
    258 	if (hwft & GMAC_DMA_FEAT_ENHANCED_DESC) {
    259 		aprint_normal_dev(sc->sc_dev,
    260 		    "Using enhanced descriptor format\n");
    261 		sc->sc_descm = &desc_methods_enhanced;
    262 	} else {
    263 		sc->sc_descm = &desc_methods_standard;
    264 	}
    265 	if (hwft & GMAC_DMA_FEAT_RMON) {
    266 		uint32_t val;
    267 
    268 		/* Mask all MMC interrupts */
    269 		val = 0xffffffff;
    270 		bus_space_write_4(sc->sc_bst, sc->sc_bsh,
    271 		    GMAC_MMC_RX_INT_MSK, val);
    272 		bus_space_write_4(sc->sc_bst, sc->sc_bsh,
    273 		    GMAC_MMC_TX_INT_MSK, val);
    274 	}
    275 
    276 	/*
    277 	 * Allocate Tx and Rx rings
    278 	 */
    279 	if (dwc_gmac_alloc_dma_rings(sc) != 0) {
    280 		aprint_error_dev(sc->sc_dev, "could not allocate DMA rings\n");
    281 		goto fail;
    282 	}
    283 
    284 	if (dwc_gmac_alloc_tx_ring(sc, &sc->sc_txq) != 0) {
    285 		aprint_error_dev(sc->sc_dev, "could not allocate Tx ring\n");
    286 		goto fail;
    287 	}
    288 
    289 	if (dwc_gmac_alloc_rx_ring(sc, &sc->sc_rxq) != 0) {
    290 		aprint_error_dev(sc->sc_dev, "could not allocate Rx ring\n");
    291 		goto fail;
    292 	}
    293 
    294 	sc->sc_lock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_NET);
    295 	mutex_init(&sc->sc_txq.t_mtx, MUTEX_DEFAULT, IPL_NET);
    296 	mutex_init(&sc->sc_rxq.r_mtx, MUTEX_DEFAULT, IPL_NET);
    297 
    298 	/*
    299 	 * Prepare interface data
    300 	 */
    301 	ifp->if_softc = sc;
    302 	strlcpy(ifp->if_xname, device_xname(sc->sc_dev), IFNAMSIZ);
    303 	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
    304 #ifdef DWCGMAC_MPSAFE
    305 	ifp->if_extflags = IFEF_MPSAFE;
    306 #endif
    307 	ifp->if_ioctl = dwc_gmac_ioctl;
    308 	ifp->if_start = dwc_gmac_start;
    309 	ifp->if_init = dwc_gmac_init;
    310 	ifp->if_stop = dwc_gmac_stop;
    311 	IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
    312 	IFQ_SET_READY(&ifp->if_snd);
    313 
    314 	/*
    315 	 * Attach MII subdevices
    316 	 */
    317 	sc->sc_ec.ec_mii = &sc->sc_mii;
    318 	ifmedia_init(&mii->mii_media, 0, ether_mediachange, ether_mediastatus);
    319 	mii->mii_ifp = ifp;
    320 	mii->mii_readreg = dwc_gmac_miibus_read_reg;
    321 	mii->mii_writereg = dwc_gmac_miibus_write_reg;
    322 	mii->mii_statchg = dwc_gmac_miibus_statchg;
    323 	mii_attach(sc->sc_dev, mii, 0xffffffff, phy_id, MII_OFFSET_ANY,
    324 	    MIIF_DOPAUSE);
    325 
    326 	if (LIST_EMPTY(&mii->mii_phys)) {
    327 		aprint_error_dev(sc->sc_dev, "no PHY found!\n");
    328 		ifmedia_add(&mii->mii_media, IFM_ETHER | IFM_MANUAL, 0, NULL);
    329 		ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_MANUAL);
    330 	} else {
    331 		ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_AUTO);
    332 	}
    333 
    334 	/*
    335 	 * We can support 802.1Q VLAN-sized frames.
    336 	 */
    337 	sc->sc_ec.ec_capabilities |= ETHERCAP_VLAN_MTU;
    338 
    339 	/*
    340 	 * Ready, attach interface
    341 	 */
    342 	/* Attach the interface. */
    343 	if_initialize(ifp);
    344 	sc->sc_ipq = if_percpuq_create(&sc->sc_ec.ec_if);
    345 	if_deferred_start_init(ifp, NULL);
    346 	ether_ifattach(ifp, enaddr);
    347 	ether_set_ifflags_cb(&sc->sc_ec, dwc_gmac_ifflags_cb);
    348 	if_register(ifp);
    349 	rnd_attach_source(&sc->rnd_source, device_xname(sc->sc_dev),
    350 	    RND_TYPE_NET, RND_FLAG_DEFAULT);
    351 
    352 	/*
    353 	 * Enable interrupts
    354 	 */
    355 	mutex_enter(sc->sc_lock);
    356 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_MAC_INTMASK,
    357 	    AWIN_DEF_MAC_INTRMASK);
    358 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_DMA_INTENABLE,
    359 	    GMAC_DEF_DMA_INT_MASK);
    360 	mutex_exit(sc->sc_lock);
    361 
    362 	return 0;
    363 
    364 fail:
    365 	dwc_gmac_free_rx_ring(sc, &sc->sc_rxq);
    366 	dwc_gmac_free_tx_ring(sc, &sc->sc_txq);
    367 	dwc_gmac_free_dma_rings(sc);
    368 	mutex_destroy(&sc->sc_mdio_lock);
    369 
    370 	return ENXIO;
    371 }
    372 
    373 
    374 
    375 static int
    376 dwc_gmac_reset(struct dwc_gmac_softc *sc)
    377 {
    378 	size_t cnt;
    379 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_DMA_BUSMODE,
    380 	    bus_space_read_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_DMA_BUSMODE)
    381 	    | GMAC_BUSMODE_RESET);
    382 	for (cnt = 0; cnt < 30000; cnt++) {
    383 		if ((bus_space_read_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_DMA_BUSMODE)
    384 		    & GMAC_BUSMODE_RESET) == 0)
    385 			return 0;
    386 		delay(10);
    387 	}
    388 
    389 	aprint_error_dev(sc->sc_dev, "reset timed out\n");
    390 	return EIO;
    391 }
    392 
    393 static void
    394 dwc_gmac_write_hwaddr(struct dwc_gmac_softc *sc,
    395     uint8_t enaddr[ETHER_ADDR_LEN])
    396 {
    397 	uint32_t hi, lo;
    398 
    399 	hi = enaddr[4] | (enaddr[5] << 8);
    400 	lo = enaddr[0] | (enaddr[1] << 8) | (enaddr[2] << 16)
    401 	    | ((uint32_t)enaddr[3] << 24);
    402 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_MAC_ADDR0HI, hi);
    403 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_MAC_ADDR0LO, lo);
    404 }
    405 
    406 static int
    407 dwc_gmac_miibus_read_reg(device_t self, int phy, int reg, uint16_t *val)
    408 {
    409 	struct dwc_gmac_softc * const sc = device_private(self);
    410 	uint16_t mii;
    411 	size_t cnt;
    412 
    413 	mii = __SHIFTIN(phy, GMAC_MII_PHY_MASK)
    414 	    | __SHIFTIN(reg, GMAC_MII_REG_MASK)
    415 	    | __SHIFTIN(sc->sc_mii_clk, GMAC_MII_CLKMASK)
    416 	    | GMAC_MII_BUSY;
    417 
    418 	mutex_enter(&sc->sc_mdio_lock);
    419 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_MAC_MIIADDR, mii);
    420 
    421 	for (cnt = 0; cnt < 1000; cnt++) {
    422 		if (!(bus_space_read_4(sc->sc_bst, sc->sc_bsh,
    423 		    AWIN_GMAC_MAC_MIIADDR) & GMAC_MII_BUSY)) {
    424 			*val = bus_space_read_4(sc->sc_bst, sc->sc_bsh,
    425 			    AWIN_GMAC_MAC_MIIDATA);
    426 			break;
    427 		}
    428 		delay(10);
    429 	}
    430 
    431 	mutex_exit(&sc->sc_mdio_lock);
    432 
    433 	if (cnt >= 1000)
    434 		return ETIMEDOUT;
    435 
    436 	return 0;
    437 }
    438 
    439 static int
    440 dwc_gmac_miibus_write_reg(device_t self, int phy, int reg, uint16_t val)
    441 {
    442 	struct dwc_gmac_softc * const sc = device_private(self);
    443 	uint16_t mii;
    444 	size_t cnt;
    445 
    446 	mii = __SHIFTIN(phy, GMAC_MII_PHY_MASK)
    447 	    | __SHIFTIN(reg, GMAC_MII_REG_MASK)
    448 	    | __SHIFTIN(sc->sc_mii_clk, GMAC_MII_CLKMASK)
    449 	    | GMAC_MII_BUSY | GMAC_MII_WRITE;
    450 
    451 	mutex_enter(&sc->sc_mdio_lock);
    452 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_MAC_MIIDATA, val);
    453 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_MAC_MIIADDR, mii);
    454 
    455 	for (cnt = 0; cnt < 1000; cnt++) {
    456 		if (!(bus_space_read_4(sc->sc_bst, sc->sc_bsh,
    457 		    AWIN_GMAC_MAC_MIIADDR) & GMAC_MII_BUSY))
    458 			break;
    459 		delay(10);
    460 	}
    461 
    462 	mutex_exit(&sc->sc_mdio_lock);
    463 
    464 	if (cnt >= 1000)
    465 		return ETIMEDOUT;
    466 
    467 	return 0;
    468 }
    469 
    470 static int
    471 dwc_gmac_alloc_rx_ring(struct dwc_gmac_softc *sc,
    472 	struct dwc_gmac_rx_ring *ring)
    473 {
    474 	struct dwc_gmac_rx_data *data;
    475 	bus_addr_t physaddr;
    476 	const size_t descsize = AWGE_RX_RING_COUNT * sizeof(*ring->r_desc);
    477 	int error, i, next;
    478 
    479 	ring->r_cur = ring->r_next = 0;
    480 	memset(ring->r_desc, 0, descsize);
    481 
    482 	/*
    483 	 * Pre-allocate Rx buffers and populate Rx ring.
    484 	 */
    485 	for (i = 0; i < AWGE_RX_RING_COUNT; i++) {
    486 		struct dwc_gmac_dev_dmadesc *desc;
    487 
    488 		data = &sc->sc_rxq.r_data[i];
    489 
    490 		MGETHDR(data->rd_m, M_DONTWAIT, MT_DATA);
    491 		if (data->rd_m == NULL) {
    492 			aprint_error_dev(sc->sc_dev,
    493 			    "could not allocate rx mbuf #%d\n", i);
    494 			error = ENOMEM;
    495 			goto fail;
    496 		}
    497 		error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1,
    498 		    MCLBYTES, 0, BUS_DMA_NOWAIT, &data->rd_map);
    499 		if (error != 0) {
    500 			aprint_error_dev(sc->sc_dev,
    501 			    "could not create DMA map\n");
    502 			data->rd_map = NULL;
    503 			goto fail;
    504 		}
    505 		MCLGET(data->rd_m, M_DONTWAIT);
    506 		if (!(data->rd_m->m_flags & M_EXT)) {
    507 			aprint_error_dev(sc->sc_dev,
    508 			    "could not allocate mbuf cluster #%d\n", i);
    509 			error = ENOMEM;
    510 			goto fail;
    511 		}
    512 		data->rd_m->m_len = data->rd_m->m_pkthdr.len
    513 		    = data->rd_m->m_ext.ext_size;
    514 		if (data->rd_m->m_len > AWGE_MAX_PACKET) {
    515 			data->rd_m->m_len = data->rd_m->m_pkthdr.len
    516 			    = AWGE_MAX_PACKET;
    517 		}
    518 
    519 		error = bus_dmamap_load_mbuf(sc->sc_dmat, data->rd_map,
    520 		    data->rd_m, BUS_DMA_READ | BUS_DMA_NOWAIT);
    521 		if (error != 0) {
    522 			aprint_error_dev(sc->sc_dev,
    523 			    "could not load rx buf DMA map #%d", i);
    524 			goto fail;
    525 		}
    526 		bus_dmamap_sync(sc->sc_dmat, data->rd_map, 0,
    527 		    data->rd_map->dm_mapsize, BUS_DMASYNC_PREREAD);
    528 		physaddr = data->rd_map->dm_segs[0].ds_addr;
    529 
    530 		desc = &sc->sc_rxq.r_desc[i];
    531 		desc->ddesc_data = htole32(physaddr);
    532 		next = RX_NEXT(i);
    533 		desc->ddesc_next = htole32(ring->r_physaddr
    534 		    + next * sizeof(*desc));
    535 		sc->sc_descm->rx_init_flags(desc);
    536 		sc->sc_descm->rx_set_len(desc, data->rd_m->m_len);
    537 		sc->sc_descm->rx_set_owned_by_dev(desc);
    538 	}
    539 
    540 	bus_dmamap_sync(sc->sc_dmat, sc->sc_dma_ring_map, 0,
    541 	    AWGE_RX_RING_COUNT * sizeof(struct dwc_gmac_dev_dmadesc),
    542 	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
    543 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_DMA_RX_ADDR,
    544 	    ring->r_physaddr);
    545 
    546 	return 0;
    547 
    548 fail:
    549 	dwc_gmac_free_rx_ring(sc, ring);
    550 	return error;
    551 }
    552 
    553 static void
    554 dwc_gmac_reset_rx_ring(struct dwc_gmac_softc *sc,
    555 	struct dwc_gmac_rx_ring *ring)
    556 {
    557 	struct dwc_gmac_dev_dmadesc *desc;
    558 	struct dwc_gmac_rx_data *data;
    559 	int i;
    560 
    561 	mutex_enter(&ring->r_mtx);
    562 	for (i = 0; i < AWGE_RX_RING_COUNT; i++) {
    563 		desc = &sc->sc_rxq.r_desc[i];
    564 		data = &sc->sc_rxq.r_data[i];
    565 		sc->sc_descm->rx_init_flags(desc);
    566 		sc->sc_descm->rx_set_len(desc, data->rd_m->m_len);
    567 		sc->sc_descm->rx_set_owned_by_dev(desc);
    568 	}
    569 
    570 	bus_dmamap_sync(sc->sc_dmat, sc->sc_dma_ring_map, 0,
    571 	    AWGE_RX_RING_COUNT * sizeof(struct dwc_gmac_dev_dmadesc),
    572 	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
    573 
    574 	ring->r_cur = ring->r_next = 0;
    575 	/* reset DMA address to start of ring */
    576 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_DMA_RX_ADDR,
    577 	    sc->sc_rxq.r_physaddr);
    578 	mutex_exit(&ring->r_mtx);
    579 }
    580 
    581 static int
    582 dwc_gmac_alloc_dma_rings(struct dwc_gmac_softc *sc)
    583 {
    584 	const size_t descsize = AWGE_TOTAL_RING_COUNT *
    585 		sizeof(struct dwc_gmac_dev_dmadesc);
    586 	int error, nsegs;
    587 	void *rings;
    588 
    589 	error = bus_dmamap_create(sc->sc_dmat, descsize, 1, descsize, 0,
    590 	    BUS_DMA_NOWAIT, &sc->sc_dma_ring_map);
    591 	if (error != 0) {
    592 		aprint_error_dev(sc->sc_dev,
    593 		    "could not create desc DMA map\n");
    594 		sc->sc_dma_ring_map = NULL;
    595 		goto fail;
    596 	}
    597 
    598 	error = bus_dmamem_alloc(sc->sc_dmat, descsize, PAGE_SIZE, 0,
    599 	    &sc->sc_dma_ring_seg, 1, &nsegs, BUS_DMA_NOWAIT |BUS_DMA_COHERENT);
    600 	if (error != 0) {
    601 		aprint_error_dev(sc->sc_dev,
    602 		    "could not map DMA memory\n");
    603 		goto fail;
    604 	}
    605 
    606 	error = bus_dmamem_map(sc->sc_dmat, &sc->sc_dma_ring_seg, nsegs,
    607 	    descsize, &rings, BUS_DMA_NOWAIT | BUS_DMA_COHERENT);
    608 	if (error != 0) {
    609 		aprint_error_dev(sc->sc_dev,
    610 		    "could not allocate DMA memory\n");
    611 		goto fail;
    612 	}
    613 
    614 	error = bus_dmamap_load(sc->sc_dmat, sc->sc_dma_ring_map, rings,
    615 	    descsize, NULL, BUS_DMA_NOWAIT | BUS_DMA_COHERENT);
    616 	if (error != 0) {
    617 		aprint_error_dev(sc->sc_dev,
    618 		    "could not load desc DMA map\n");
    619 		goto fail;
    620 	}
    621 
    622 	/* give first AWGE_RX_RING_COUNT to the RX side */
    623 	sc->sc_rxq.r_desc = rings;
    624 	sc->sc_rxq.r_physaddr = sc->sc_dma_ring_map->dm_segs[0].ds_addr;
    625 
    626 	/* and next rings to the TX side */
    627 	sc->sc_txq.t_desc = sc->sc_rxq.r_desc + AWGE_RX_RING_COUNT;
    628 	sc->sc_txq.t_physaddr = sc->sc_rxq.r_physaddr +
    629 	    AWGE_RX_RING_COUNT * sizeof(struct dwc_gmac_dev_dmadesc);
    630 
    631 	return 0;
    632 
    633 fail:
    634 	dwc_gmac_free_dma_rings(sc);
    635 	return error;
    636 }
    637 
    638 static void
    639 dwc_gmac_free_dma_rings(struct dwc_gmac_softc *sc)
    640 {
    641 	bus_dmamap_sync(sc->sc_dmat, sc->sc_dma_ring_map, 0,
    642 	    sc->sc_dma_ring_map->dm_mapsize, BUS_DMASYNC_POSTWRITE);
    643 	bus_dmamap_unload(sc->sc_dmat, sc->sc_dma_ring_map);
    644 	bus_dmamem_unmap(sc->sc_dmat, sc->sc_rxq.r_desc,
    645 	    AWGE_TOTAL_RING_COUNT * sizeof(struct dwc_gmac_dev_dmadesc));
    646 	bus_dmamem_free(sc->sc_dmat, &sc->sc_dma_ring_seg, 1);
    647 }
    648 
    649 static void
    650 dwc_gmac_free_rx_ring(struct dwc_gmac_softc *sc, struct dwc_gmac_rx_ring *ring)
    651 {
    652 	struct dwc_gmac_rx_data *data;
    653 	int i;
    654 
    655 	if (ring->r_desc == NULL)
    656 		return;
    657 
    658 	for (i = 0; i < AWGE_RX_RING_COUNT; i++) {
    659 		data = &ring->r_data[i];
    660 
    661 		if (data->rd_map != NULL) {
    662 			bus_dmamap_sync(sc->sc_dmat, data->rd_map, 0,
    663 			    AWGE_RX_RING_COUNT
    664 				* sizeof(struct dwc_gmac_dev_dmadesc),
    665 			    BUS_DMASYNC_POSTREAD);
    666 			bus_dmamap_unload(sc->sc_dmat, data->rd_map);
    667 			bus_dmamap_destroy(sc->sc_dmat, data->rd_map);
    668 		}
    669 		m_freem(data->rd_m);
    670 	}
    671 }
    672 
    673 static int
    674 dwc_gmac_alloc_tx_ring(struct dwc_gmac_softc *sc,
    675 	struct dwc_gmac_tx_ring *ring)
    676 {
    677 	int i, error = 0;
    678 
    679 	ring->t_queued = 0;
    680 	ring->t_cur = ring->t_next = 0;
    681 
    682 	memset(ring->t_desc, 0, AWGE_TX_RING_COUNT * sizeof(*ring->t_desc));
    683 	bus_dmamap_sync(sc->sc_dmat, sc->sc_dma_ring_map,
    684 	    TX_DESC_OFFSET(0),
    685 	    AWGE_TX_RING_COUNT * sizeof(struct dwc_gmac_dev_dmadesc),
    686 	    BUS_DMASYNC_POSTWRITE);
    687 
    688 	for (i = 0; i < AWGE_TX_RING_COUNT; i++) {
    689 		error = bus_dmamap_create(sc->sc_dmat, MCLBYTES,
    690 		    AWGE_TX_RING_COUNT, MCLBYTES, 0,
    691 		    BUS_DMA_NOWAIT | BUS_DMA_COHERENT,
    692 		    &ring->t_data[i].td_map);
    693 		if (error != 0) {
    694 			aprint_error_dev(sc->sc_dev,
    695 			    "could not create TX DMA map #%d\n", i);
    696 			ring->t_data[i].td_map = NULL;
    697 			goto fail;
    698 		}
    699 		ring->t_desc[i].ddesc_next = htole32(
    700 		    ring->t_physaddr + sizeof(struct dwc_gmac_dev_dmadesc)
    701 		    * TX_NEXT(i));
    702 	}
    703 
    704 	return 0;
    705 
    706 fail:
    707 	dwc_gmac_free_tx_ring(sc, ring);
    708 	return error;
    709 }
    710 
    711 static void
    712 dwc_gmac_txdesc_sync(struct dwc_gmac_softc *sc, int start, int end, int ops)
    713 {
    714 	/* 'end' is pointing one descriptor beyond the last we want to sync */
    715 	if (end > start) {
    716 		bus_dmamap_sync(sc->sc_dmat, sc->sc_dma_ring_map,
    717 		    TX_DESC_OFFSET(start),
    718 		    TX_DESC_OFFSET(end) - TX_DESC_OFFSET(start),
    719 		    ops);
    720 		return;
    721 	}
    722 	/* sync from 'start' to end of ring */
    723 	bus_dmamap_sync(sc->sc_dmat, sc->sc_dma_ring_map,
    724 	    TX_DESC_OFFSET(start),
    725 	    TX_DESC_OFFSET(AWGE_TX_RING_COUNT) - TX_DESC_OFFSET(start),
    726 	    ops);
    727 	if (TX_DESC_OFFSET(end) - TX_DESC_OFFSET(0) > 0) {
    728 		/* sync from start of ring to 'end' */
    729 		bus_dmamap_sync(sc->sc_dmat, sc->sc_dma_ring_map,
    730 		    TX_DESC_OFFSET(0),
    731 		    TX_DESC_OFFSET(end) - TX_DESC_OFFSET(0),
    732 		    ops);
    733 	}
    734 }
    735 
    736 static void
    737 dwc_gmac_reset_tx_ring(struct dwc_gmac_softc *sc,
    738 	struct dwc_gmac_tx_ring *ring)
    739 {
    740 	int i;
    741 
    742 	mutex_enter(&ring->t_mtx);
    743 	for (i = 0; i < AWGE_TX_RING_COUNT; i++) {
    744 		struct dwc_gmac_tx_data *data = &ring->t_data[i];
    745 
    746 		if (data->td_m != NULL) {
    747 			bus_dmamap_sync(sc->sc_dmat, data->td_active,
    748 			    0, data->td_active->dm_mapsize,
    749 			    BUS_DMASYNC_POSTWRITE);
    750 			bus_dmamap_unload(sc->sc_dmat, data->td_active);
    751 			m_freem(data->td_m);
    752 			data->td_m = NULL;
    753 		}
    754 	}
    755 
    756 	bus_dmamap_sync(sc->sc_dmat, sc->sc_dma_ring_map,
    757 	    TX_DESC_OFFSET(0),
    758 	    AWGE_TX_RING_COUNT * sizeof(struct dwc_gmac_dev_dmadesc),
    759 	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
    760 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_DMA_TX_ADDR,
    761 	    sc->sc_txq.t_physaddr);
    762 
    763 	ring->t_queued = 0;
    764 	ring->t_cur = ring->t_next = 0;
    765 	mutex_exit(&ring->t_mtx);
    766 }
    767 
    768 static void
    769 dwc_gmac_free_tx_ring(struct dwc_gmac_softc *sc,
    770 	struct dwc_gmac_tx_ring *ring)
    771 {
    772 	int i;
    773 
    774 	/* unload the maps */
    775 	for (i = 0; i < AWGE_TX_RING_COUNT; i++) {
    776 		struct dwc_gmac_tx_data *data = &ring->t_data[i];
    777 
    778 		if (data->td_m != NULL) {
    779 			bus_dmamap_sync(sc->sc_dmat, data->td_active,
    780 			    0, data->td_map->dm_mapsize,
    781 			    BUS_DMASYNC_POSTWRITE);
    782 			bus_dmamap_unload(sc->sc_dmat, data->td_active);
    783 			m_freem(data->td_m);
    784 			data->td_m = NULL;
    785 		}
    786 	}
    787 
    788 	/* and actually free them */
    789 	for (i = 0; i < AWGE_TX_RING_COUNT; i++) {
    790 		struct dwc_gmac_tx_data *data = &ring->t_data[i];
    791 
    792 		bus_dmamap_destroy(sc->sc_dmat, data->td_map);
    793 	}
    794 }
    795 
    796 static void
    797 dwc_gmac_miibus_statchg(struct ifnet *ifp)
    798 {
    799 	struct dwc_gmac_softc * const sc = ifp->if_softc;
    800 	struct mii_data * const mii = &sc->sc_mii;
    801 	uint32_t conf, flow;
    802 
    803 	/*
    804 	 * Set MII or GMII interface based on the speed
    805 	 * negotiated by the PHY.
    806 	 */
    807 	conf = bus_space_read_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_MAC_CONF);
    808 	conf &= ~(AWIN_GMAC_MAC_CONF_FES100 | AWIN_GMAC_MAC_CONF_MIISEL
    809 	    | AWIN_GMAC_MAC_CONF_FULLDPLX);
    810 	conf |= AWIN_GMAC_MAC_CONF_FRAMEBURST
    811 	    | AWIN_GMAC_MAC_CONF_DISABLERXOWN
    812 	    | AWIN_GMAC_MAC_CONF_DISABLEJABBER
    813 	    | AWIN_GMAC_MAC_CONF_RXENABLE
    814 	    | AWIN_GMAC_MAC_CONF_TXENABLE;
    815 	switch (IFM_SUBTYPE(mii->mii_media_active)) {
    816 	case IFM_10_T:
    817 		conf |= AWIN_GMAC_MAC_CONF_MIISEL;
    818 		break;
    819 	case IFM_100_TX:
    820 		conf |= AWIN_GMAC_MAC_CONF_FES100 |
    821 			AWIN_GMAC_MAC_CONF_MIISEL;
    822 		break;
    823 	case IFM_1000_T:
    824 		break;
    825 	}
    826 	if (sc->sc_set_speed)
    827 		sc->sc_set_speed(sc, IFM_SUBTYPE(mii->mii_media_active));
    828 
    829 	flow = 0;
    830 	if (IFM_OPTIONS(mii->mii_media_active) & IFM_FDX) {
    831 		conf |= AWIN_GMAC_MAC_CONF_FULLDPLX;
    832 		flow |= __SHIFTIN(0x200, AWIN_GMAC_MAC_FLOWCTRL_PAUSE);
    833 	}
    834 	if (mii->mii_media_active & IFM_ETH_TXPAUSE) {
    835 		flow |= AWIN_GMAC_MAC_FLOWCTRL_TFE;
    836 	}
    837 	if (mii->mii_media_active & IFM_ETH_RXPAUSE) {
    838 		flow |= AWIN_GMAC_MAC_FLOWCTRL_RFE;
    839 	}
    840 	bus_space_write_4(sc->sc_bst, sc->sc_bsh,
    841 	    AWIN_GMAC_MAC_FLOWCTRL, flow);
    842 
    843 #ifdef DWC_GMAC_DEBUG
    844 	aprint_normal_dev(sc->sc_dev,
    845 	    "setting MAC conf register: %08x\n", conf);
    846 #endif
    847 
    848 	bus_space_write_4(sc->sc_bst, sc->sc_bsh,
    849 	    AWIN_GMAC_MAC_CONF, conf);
    850 }
    851 
    852 static int
    853 dwc_gmac_init(struct ifnet *ifp)
    854 {
    855 	struct dwc_gmac_softc *sc = ifp->if_softc;
    856 
    857 	mutex_enter(sc->sc_lock);
    858 	int ret = dwc_gmac_init_locked(ifp);
    859 	mutex_exit(sc->sc_lock);
    860 
    861 	return ret;
    862 }
    863 
    864 static int
    865 dwc_gmac_init_locked(struct ifnet *ifp)
    866 {
    867 	struct dwc_gmac_softc *sc = ifp->if_softc;
    868 	uint32_t ffilt;
    869 
    870 	if (ifp->if_flags & IFF_RUNNING)
    871 		return 0;
    872 
    873 	dwc_gmac_stop_locked(ifp, 0);
    874 
    875 	/*
    876 	 * Configure DMA burst/transfer mode and RX/TX priorities.
    877 	 * XXX - the GMAC_BUSMODE_PRIORXTX bits are undocumented.
    878 	 */
    879 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_DMA_BUSMODE,
    880 	    GMAC_BUSMODE_FIXEDBURST | GMAC_BUSMODE_4PBL |
    881 	    __SHIFTIN(2, GMAC_BUSMODE_RPBL) |
    882 	    __SHIFTIN(2, GMAC_BUSMODE_PBL));
    883 
    884 	/*
    885 	 * Set up address filter
    886 	 */
    887 	ffilt = bus_space_read_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_MAC_FFILT);
    888 	if (ifp->if_flags & IFF_PROMISC) {
    889 		ffilt |= AWIN_GMAC_MAC_FFILT_PR;
    890 	} else {
    891 		ffilt &= ~AWIN_GMAC_MAC_FFILT_PR;
    892 	}
    893 	if (ifp->if_flags & IFF_BROADCAST) {
    894 		ffilt &= ~AWIN_GMAC_MAC_FFILT_DBF;
    895 	} else {
    896 		ffilt |= AWIN_GMAC_MAC_FFILT_DBF;
    897 	}
    898 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_MAC_FFILT, ffilt);
    899 
    900 	/*
    901 	 * Set up multicast filter
    902 	 */
    903 	dwc_gmac_setmulti(sc);
    904 
    905 	/*
    906 	 * Set up dma pointer for RX and TX ring
    907 	 */
    908 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_DMA_RX_ADDR,
    909 	    sc->sc_rxq.r_physaddr);
    910 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_DMA_TX_ADDR,
    911 	    sc->sc_txq.t_physaddr);
    912 
    913 	/*
    914 	 * Start RX/TX part
    915 	 */
    916 	uint32_t opmode = GMAC_DMA_OP_RXSTART | GMAC_DMA_OP_TXSTART;
    917 	if ((sc->sc_flags & DWC_GMAC_FORCE_THRESH_DMA_MODE) == 0) {
    918 		opmode |= GMAC_DMA_OP_RXSTOREFORWARD | GMAC_DMA_OP_TXSTOREFORWARD;
    919 	}
    920 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_DMA_OPMODE, opmode);
    921 
    922 	sc->sc_stopping = false;
    923 
    924 	ifp->if_flags |= IFF_RUNNING;
    925 	sc->sc_txbusy = false;
    926 
    927 	return 0;
    928 }
    929 
    930 static void
    931 dwc_gmac_start(struct ifnet *ifp)
    932 {
    933 	struct dwc_gmac_softc *sc = ifp->if_softc;
    934 #ifdef DWCGMAC_MPSAFE
    935 	KASSERT(if_is_mpsafe(ifp));
    936 #endif
    937 
    938 	mutex_enter(sc->sc_lock);
    939 	if (!sc->sc_stopping) {
    940 		mutex_enter(&sc->sc_txq.t_mtx);
    941 		dwc_gmac_start_locked(ifp);
    942 		mutex_exit(&sc->sc_txq.t_mtx);
    943 	}
    944 	mutex_exit(sc->sc_lock);
    945 }
    946 
    947 static void
    948 dwc_gmac_start_locked(struct ifnet *ifp)
    949 {
    950 	struct dwc_gmac_softc *sc = ifp->if_softc;
    951 	int old = sc->sc_txq.t_queued;
    952 	int start = sc->sc_txq.t_cur;
    953 	struct mbuf *m0;
    954 
    955 	if ((ifp->if_flags & IFF_RUNNING) == 0)
    956 		return;
    957 	if (sc->sc_txbusy)
    958 		return;
    959 
    960 	for (;;) {
    961 		IFQ_POLL(&ifp->if_snd, m0);
    962 		if (m0 == NULL)
    963 			break;
    964 		if (dwc_gmac_queue(sc, m0) != 0) {
    965 			sc->sc_txbusy = true;
    966 			break;
    967 		}
    968 		IFQ_DEQUEUE(&ifp->if_snd, m0);
    969 		bpf_mtap(ifp, m0, BPF_D_OUT);
    970 		if (sc->sc_txq.t_queued == AWGE_TX_RING_COUNT) {
    971 			sc->sc_txbusy = true;
    972 			break;
    973 		}
    974 	}
    975 
    976 	if (sc->sc_txq.t_queued != old) {
    977 		/* packets have been queued, kick it off */
    978 		dwc_gmac_txdesc_sync(sc, start, sc->sc_txq.t_cur,
    979 		    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
    980 
    981 #ifdef DWC_GMAC_DEBUG
    982 		dwc_dump_status(sc);
    983 #endif
    984 		bus_space_write_4(sc->sc_bst, sc->sc_bsh,
    985 		    AWIN_GMAC_DMA_TXPOLL, ~0U);
    986 	}
    987 }
    988 
    989 static void
    990 dwc_gmac_stop(struct ifnet *ifp, int disable)
    991 {
    992 	struct dwc_gmac_softc *sc = ifp->if_softc;
    993 
    994 	mutex_enter(sc->sc_lock);
    995 	dwc_gmac_stop_locked(ifp, disable);
    996 	mutex_exit(sc->sc_lock);
    997 }
    998 
    999 static void
   1000 dwc_gmac_stop_locked(struct ifnet *ifp, int disable)
   1001 {
   1002 	struct dwc_gmac_softc *sc = ifp->if_softc;
   1003 
   1004 	sc->sc_stopping = true;
   1005 
   1006 	bus_space_write_4(sc->sc_bst, sc->sc_bsh,
   1007 	    AWIN_GMAC_DMA_OPMODE,
   1008 	    bus_space_read_4(sc->sc_bst, sc->sc_bsh,
   1009 		AWIN_GMAC_DMA_OPMODE)
   1010 		& ~(GMAC_DMA_OP_TXSTART | GMAC_DMA_OP_RXSTART));
   1011 	bus_space_write_4(sc->sc_bst, sc->sc_bsh,
   1012 	    AWIN_GMAC_DMA_OPMODE,
   1013 	    bus_space_read_4(sc->sc_bst, sc->sc_bsh,
   1014 		AWIN_GMAC_DMA_OPMODE) | GMAC_DMA_OP_FLUSHTX);
   1015 
   1016 	mii_down(&sc->sc_mii);
   1017 	dwc_gmac_reset_tx_ring(sc, &sc->sc_txq);
   1018 	dwc_gmac_reset_rx_ring(sc, &sc->sc_rxq);
   1019 
   1020 	ifp->if_flags &= ~IFF_RUNNING;
   1021 	sc->sc_txbusy = false;
   1022 }
   1023 
   1024 /*
   1025  * Add m0 to the TX ring
   1026  */
   1027 static int
   1028 dwc_gmac_queue(struct dwc_gmac_softc *sc, struct mbuf *m0)
   1029 {
   1030 	struct dwc_gmac_dev_dmadesc *desc = NULL;
   1031 	struct dwc_gmac_tx_data *data = NULL;
   1032 	bus_dmamap_t map;
   1033 	int error, i, first;
   1034 
   1035 #ifdef DWC_GMAC_DEBUG
   1036 	aprint_normal_dev(sc->sc_dev,
   1037 	    "dwc_gmac_queue: adding mbuf chain %p\n", m0);
   1038 #endif
   1039 
   1040 	first = sc->sc_txq.t_cur;
   1041 	map = sc->sc_txq.t_data[first].td_map;
   1042 
   1043 	error = bus_dmamap_load_mbuf(sc->sc_dmat, map, m0,
   1044 	    BUS_DMA_WRITE | BUS_DMA_NOWAIT);
   1045 	if (error != 0) {
   1046 		aprint_error_dev(sc->sc_dev, "could not map mbuf "
   1047 		    "(len: %d, error %d)\n", m0->m_pkthdr.len, error);
   1048 		return error;
   1049 	}
   1050 
   1051 	if (sc->sc_txq.t_queued + map->dm_nsegs > AWGE_TX_RING_COUNT) {
   1052 		bus_dmamap_unload(sc->sc_dmat, map);
   1053 		return ENOBUFS;
   1054 	}
   1055 
   1056 	for (i = 0; i < map->dm_nsegs; i++) {
   1057 		data = &sc->sc_txq.t_data[sc->sc_txq.t_cur];
   1058 		desc = &sc->sc_txq.t_desc[sc->sc_txq.t_cur];
   1059 
   1060 		desc->ddesc_data = htole32(map->dm_segs[i].ds_addr);
   1061 
   1062 #ifdef DWC_GMAC_DEBUG
   1063 		aprint_normal_dev(sc->sc_dev, "enqueuing desc #%d data %08lx "
   1064 		    "len %lu\n", sc->sc_txq.t_cur,
   1065 		    (unsigned long)map->dm_segs[i].ds_addr,
   1066 		    (unsigned long)map->dm_segs[i].ds_len);
   1067 #endif
   1068 
   1069 		sc->sc_descm->tx_init_flags(desc);
   1070 		sc->sc_descm->tx_set_len(desc, map->dm_segs[i].ds_len);
   1071 
   1072 		if (i == 0)
   1073 			sc->sc_descm->tx_set_first_frag(desc);
   1074 
   1075 		/*
   1076 		 * Defer passing ownership of the first descriptor
   1077 		 * until we are done.
   1078 		 */
   1079 		if (i != 0)
   1080 			sc->sc_descm->tx_set_owned_by_dev(desc);
   1081 
   1082 		sc->sc_txq.t_queued++;
   1083 		sc->sc_txq.t_cur = TX_NEXT(sc->sc_txq.t_cur);
   1084 	}
   1085 
   1086 	sc->sc_descm->tx_set_last_frag(desc);
   1087 
   1088 	data->td_m = m0;
   1089 	data->td_active = map;
   1090 
   1091 	bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize,
   1092 	    BUS_DMASYNC_PREWRITE);
   1093 
   1094 	/* Pass first to device */
   1095 	sc->sc_descm->tx_set_owned_by_dev(&sc->sc_txq.t_desc[first]);
   1096 
   1097 	bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize,
   1098 	    BUS_DMASYNC_PREWRITE);
   1099 
   1100 	return 0;
   1101 }
   1102 
   1103 /*
   1104  * If the interface is up and running, only modify the receive
   1105  * filter when setting promiscuous or debug mode.  Otherwise fall
   1106  * through to ether_ioctl, which will reset the chip.
   1107  */
   1108 static int
   1109 dwc_gmac_ifflags_cb(struct ethercom *ec)
   1110 {
   1111 	struct ifnet *ifp = &ec->ec_if;
   1112 	struct dwc_gmac_softc *sc = ifp->if_softc;
   1113 	int ret = 0;
   1114 
   1115 	mutex_enter(sc->sc_lock);
   1116 	u_short change = ifp->if_flags ^ sc->sc_if_flags;
   1117 	sc->sc_if_flags = ifp->if_flags;
   1118 
   1119 	if ((change & ~(IFF_CANTCHANGE | IFF_DEBUG)) != 0) {
   1120 		ret = ENETRESET;
   1121 		goto out;
   1122 	}
   1123 	if ((change & IFF_PROMISC) != 0) {
   1124 		dwc_gmac_setmulti(sc);
   1125 	}
   1126 out:
   1127 	mutex_exit(sc->sc_lock);
   1128 
   1129 	return ret;
   1130 }
   1131 
   1132 static int
   1133 dwc_gmac_ioctl(struct ifnet *ifp, u_long cmd, void *data)
   1134 {
   1135 	struct dwc_gmac_softc *sc = ifp->if_softc;
   1136 	int error = 0;
   1137 
   1138 	int s = splnet();
   1139 	error = ether_ioctl(ifp, cmd, data);
   1140 
   1141 #ifdef DWCGMAC_MPSAFE
   1142 	splx(s);
   1143 #endif
   1144 
   1145 	if (error == ENETRESET) {
   1146 		error = 0;
   1147 		if (cmd != SIOCADDMULTI && cmd != SIOCDELMULTI)
   1148 			;
   1149 		else if (ifp->if_flags & IFF_RUNNING) {
   1150 			/*
   1151 			 * Multicast list has changed; set the hardware filter
   1152 			 * accordingly.
   1153 			 */
   1154 			mutex_enter(sc->sc_lock);
   1155 			dwc_gmac_setmulti(sc);
   1156 			mutex_exit(sc->sc_lock);
   1157 		}
   1158 	}
   1159 
   1160 	/* Try to get things going again */
   1161 	if (ifp->if_flags & IFF_UP)
   1162 		dwc_gmac_start(ifp);
   1163 	sc->sc_if_flags = sc->sc_ec.ec_if.if_flags;
   1164 
   1165 #ifndef DWCGMAC_MPSAFE
   1166 	splx(s);
   1167 #endif
   1168 
   1169 	return error;
   1170 }
   1171 
   1172 static void
   1173 dwc_gmac_tx_intr(struct dwc_gmac_softc *sc)
   1174 {
   1175 	struct ifnet *ifp = &sc->sc_ec.ec_if;
   1176 	struct dwc_gmac_tx_data *data;
   1177 	struct dwc_gmac_dev_dmadesc *desc;
   1178 	int i, nsegs;
   1179 
   1180 	mutex_enter(&sc->sc_txq.t_mtx);
   1181 
   1182 	for (i = sc->sc_txq.t_next; sc->sc_txq.t_queued > 0; i = TX_NEXT(i)) {
   1183 #ifdef DWC_GMAC_DEBUG
   1184 		aprint_normal_dev(sc->sc_dev,
   1185 		    "dwc_gmac_tx_intr: checking desc #%d (t_queued: %d)\n",
   1186 		    i, sc->sc_txq.t_queued);
   1187 #endif
   1188 
   1189 		/*
   1190 		 * i + 1 does not need to be a valid descriptor,
   1191 		 * this is just a special notion to just sync
   1192 		 * a single tx descriptor (i)
   1193 		 */
   1194 		dwc_gmac_txdesc_sync(sc, i, i + 1,
   1195 		    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
   1196 
   1197 		desc = &sc->sc_txq.t_desc[i];
   1198 		if (sc->sc_descm->tx_is_owned_by_dev(desc))
   1199 			break;
   1200 
   1201 		data = &sc->sc_txq.t_data[i];
   1202 		if (data->td_m == NULL)
   1203 			continue;
   1204 
   1205 		if_statinc(ifp, if_opackets);
   1206 		nsegs = data->td_active->dm_nsegs;
   1207 		bus_dmamap_sync(sc->sc_dmat, data->td_active, 0,
   1208 		    data->td_active->dm_mapsize, BUS_DMASYNC_POSTWRITE);
   1209 		bus_dmamap_unload(sc->sc_dmat, data->td_active);
   1210 
   1211 #ifdef DWC_GMAC_DEBUG
   1212 		aprint_normal_dev(sc->sc_dev,
   1213 		    "dwc_gmac_tx_intr: done with packet at desc #%d, "
   1214 		    "freeing mbuf %p\n", i, data->td_m);
   1215 #endif
   1216 
   1217 		m_freem(data->td_m);
   1218 		data->td_m = NULL;
   1219 
   1220 		sc->sc_txq.t_queued -= nsegs;
   1221 	}
   1222 
   1223 	sc->sc_txq.t_next = i;
   1224 
   1225 	if (sc->sc_txq.t_queued < AWGE_TX_RING_COUNT) {
   1226 		sc->sc_txbusy = false;
   1227 	}
   1228 	mutex_exit(&sc->sc_txq.t_mtx);
   1229 }
   1230 
   1231 static void
   1232 dwc_gmac_rx_intr(struct dwc_gmac_softc *sc)
   1233 {
   1234 	struct ifnet *ifp = &sc->sc_ec.ec_if;
   1235 	struct dwc_gmac_dev_dmadesc *desc;
   1236 	struct dwc_gmac_rx_data *data;
   1237 	bus_addr_t physaddr;
   1238 	struct mbuf *m, *mnew;
   1239 	int i, len, error;
   1240 
   1241 	mutex_enter(&sc->sc_rxq.r_mtx);
   1242 	for (i = sc->sc_rxq.r_cur; ; i = RX_NEXT(i)) {
   1243 		bus_dmamap_sync(sc->sc_dmat, sc->sc_dma_ring_map,
   1244 		    RX_DESC_OFFSET(i), sizeof(*desc),
   1245 		    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
   1246 		desc = &sc->sc_rxq.r_desc[i];
   1247 		data = &sc->sc_rxq.r_data[i];
   1248 
   1249 		if (sc->sc_descm->rx_is_owned_by_dev(desc))
   1250 			break;
   1251 
   1252 		if (sc->sc_descm->rx_has_error(desc)) {
   1253 #ifdef DWC_GMAC_DEBUG
   1254 			aprint_normal_dev(sc->sc_dev,
   1255 			    "RX error: descriptor status %08x, skipping\n",
   1256 			    le32toh(desc->ddesc_status0));
   1257 #endif
   1258 			if_statinc(ifp, if_ierrors);
   1259 			goto skip;
   1260 		}
   1261 
   1262 		len = sc->sc_descm->rx_get_len(desc);
   1263 
   1264 #ifdef DWC_GMAC_DEBUG
   1265 		aprint_normal_dev(sc->sc_dev,
   1266 		    "rx int: device is done with descriptor #%d, len: %d\n",
   1267 		    i, len);
   1268 #endif
   1269 
   1270 		/*
   1271 		 * Try to get a new mbuf before passing this one
   1272 		 * up, if that fails, drop the packet and reuse
   1273 		 * the existing one.
   1274 		 */
   1275 		MGETHDR(mnew, M_DONTWAIT, MT_DATA);
   1276 		if (mnew == NULL) {
   1277 			if_statinc(ifp, if_ierrors);
   1278 			goto skip;
   1279 		}
   1280 		MCLGET(mnew, M_DONTWAIT);
   1281 		if ((mnew->m_flags & M_EXT) == 0) {
   1282 			m_freem(mnew);
   1283 			if_statinc(ifp, if_ierrors);
   1284 			goto skip;
   1285 		}
   1286 		mnew->m_len = mnew->m_pkthdr.len = mnew->m_ext.ext_size;
   1287 		if (mnew->m_len > AWGE_MAX_PACKET) {
   1288 			mnew->m_len = mnew->m_pkthdr.len = AWGE_MAX_PACKET;
   1289 		}
   1290 
   1291 		/* unload old DMA map */
   1292 		bus_dmamap_sync(sc->sc_dmat, data->rd_map, 0,
   1293 		    data->rd_map->dm_mapsize, BUS_DMASYNC_POSTREAD);
   1294 		bus_dmamap_unload(sc->sc_dmat, data->rd_map);
   1295 
   1296 		/* and reload with new mbuf */
   1297 		error = bus_dmamap_load_mbuf(sc->sc_dmat, data->rd_map,
   1298 		    mnew, BUS_DMA_READ | BUS_DMA_NOWAIT);
   1299 		if (error != 0) {
   1300 			m_freem(mnew);
   1301 			/* try to reload old mbuf */
   1302 			error = bus_dmamap_load_mbuf(sc->sc_dmat, data->rd_map,
   1303 			    data->rd_m, BUS_DMA_READ | BUS_DMA_NOWAIT);
   1304 			if (error != 0) {
   1305 				panic("%s: could not load old rx mbuf",
   1306 				    device_xname(sc->sc_dev));
   1307 			}
   1308 			if_statinc(ifp, if_ierrors);
   1309 			goto skip;
   1310 		}
   1311 		physaddr = data->rd_map->dm_segs[0].ds_addr;
   1312 
   1313 		/*
   1314 		 * New mbuf loaded, update RX ring and continue
   1315 		 */
   1316 		m = data->rd_m;
   1317 		data->rd_m = mnew;
   1318 		desc->ddesc_data = htole32(physaddr);
   1319 
   1320 		/* finalize mbuf */
   1321 		m->m_pkthdr.len = m->m_len = len;
   1322 		m_set_rcvif(m, ifp);
   1323 		m->m_flags |= M_HASFCS;
   1324 
   1325 		if_percpuq_enqueue(sc->sc_ipq, m);
   1326 
   1327 skip:
   1328 		bus_dmamap_sync(sc->sc_dmat, data->rd_map, 0,
   1329 		    data->rd_map->dm_mapsize, BUS_DMASYNC_PREREAD);
   1330 
   1331 		sc->sc_descm->rx_init_flags(desc);
   1332 		sc->sc_descm->rx_set_len(desc, data->rd_m->m_len);
   1333 		sc->sc_descm->rx_set_owned_by_dev(desc);
   1334 
   1335 		bus_dmamap_sync(sc->sc_dmat, sc->sc_dma_ring_map,
   1336 		    RX_DESC_OFFSET(i), sizeof(*desc),
   1337 		    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
   1338 	}
   1339 
   1340 	/* update RX pointer */
   1341 	sc->sc_rxq.r_cur = i;
   1342 
   1343 	mutex_exit(&sc->sc_rxq.r_mtx);
   1344 }
   1345 
   1346 static void
   1347 dwc_gmac_setmulti(struct dwc_gmac_softc *sc)
   1348 {
   1349 	struct ifnet * const ifp = &sc->sc_ec.ec_if;
   1350 	struct ether_multi *enm;
   1351 	struct ether_multistep step;
   1352 	struct ethercom *ec = &sc->sc_ec;
   1353 	uint32_t hashes[2] = { 0, 0 };
   1354 	uint32_t ffilt, h;
   1355 	int mcnt;
   1356 
   1357 	KASSERT(mutex_owned(sc->sc_lock));
   1358 
   1359 	ffilt = bus_space_read_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_MAC_FFILT);
   1360 
   1361 	if (ifp->if_flags & IFF_PROMISC) {
   1362 		ffilt |= AWIN_GMAC_MAC_FFILT_PR;
   1363 		goto special_filter;
   1364 	}
   1365 
   1366 	ffilt &= ~(AWIN_GMAC_MAC_FFILT_PM | AWIN_GMAC_MAC_FFILT_PR);
   1367 
   1368 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_MAC_HTLOW, 0);
   1369 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_MAC_HTHIGH, 0);
   1370 
   1371 	ETHER_LOCK(ec);
   1372 	ec->ec_flags &= ~ETHER_F_ALLMULTI;
   1373 	ETHER_FIRST_MULTI(step, ec, enm);
   1374 	mcnt = 0;
   1375 	while (enm != NULL) {
   1376 		if (memcmp(enm->enm_addrlo, enm->enm_addrhi,
   1377 		    ETHER_ADDR_LEN) != 0) {
   1378 			ffilt |= AWIN_GMAC_MAC_FFILT_PM;
   1379 			ec->ec_flags |= ETHER_F_ALLMULTI;
   1380 			ETHER_UNLOCK(ec);
   1381 			goto special_filter;
   1382 		}
   1383 
   1384 		h = ~ether_crc32_be(enm->enm_addrlo, ETHER_ADDR_LEN) >> 26;
   1385 		hashes[h >> 5] |= (1 << (h & 0x1f));
   1386 
   1387 		mcnt++;
   1388 		ETHER_NEXT_MULTI(step, enm);
   1389 	}
   1390 	ETHER_UNLOCK(ec);
   1391 
   1392 	if (mcnt)
   1393 		ffilt |= AWIN_GMAC_MAC_FFILT_HMC;
   1394 	else
   1395 		ffilt &= ~AWIN_GMAC_MAC_FFILT_HMC;
   1396 
   1397 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_MAC_FFILT, ffilt);
   1398 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_MAC_HTLOW,
   1399 	    hashes[0]);
   1400 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_MAC_HTHIGH,
   1401 	    hashes[1]);
   1402 	sc->sc_if_flags = ifp->if_flags;
   1403 
   1404 #ifdef DWC_GMAC_DEBUG
   1405 	dwc_gmac_dump_ffilt(sc, ffilt);
   1406 #endif
   1407 	return;
   1408 
   1409 special_filter:
   1410 #ifdef DWC_GMAC_DEBUG
   1411 	dwc_gmac_dump_ffilt(sc, ffilt);
   1412 #endif
   1413 	/* no MAC hashes, ALLMULTI or PROMISC */
   1414 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_MAC_FFILT,
   1415 	    ffilt);
   1416 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_MAC_HTLOW,
   1417 	    0xffffffff);
   1418 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_MAC_HTHIGH,
   1419 	    0xffffffff);
   1420 	sc->sc_if_flags = sc->sc_ec.ec_if.if_flags;
   1421 }
   1422 
   1423 int
   1424 dwc_gmac_intr(struct dwc_gmac_softc *sc)
   1425 {
   1426 	uint32_t status, dma_status;
   1427 	int rv = 0;
   1428 
   1429 	if (sc->sc_stopping)
   1430 		return 0;
   1431 
   1432 	status = bus_space_read_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_MAC_INTR);
   1433 	if (status & AWIN_GMAC_MII_IRQ) {
   1434 		(void)bus_space_read_4(sc->sc_bst, sc->sc_bsh,
   1435 		    AWIN_GMAC_MII_STATUS);
   1436 		rv = 1;
   1437 		mii_pollstat(&sc->sc_mii);
   1438 	}
   1439 
   1440 	dma_status = bus_space_read_4(sc->sc_bst, sc->sc_bsh,
   1441 	    AWIN_GMAC_DMA_STATUS);
   1442 
   1443 	if (dma_status & (GMAC_DMA_INT_NIE | GMAC_DMA_INT_AIE))
   1444 		rv = 1;
   1445 
   1446 	if (dma_status & GMAC_DMA_INT_TIE)
   1447 		dwc_gmac_tx_intr(sc);
   1448 
   1449 	if (dma_status & GMAC_DMA_INT_RIE)
   1450 		dwc_gmac_rx_intr(sc);
   1451 
   1452 	/*
   1453 	 * Check error conditions
   1454 	 */
   1455 	if (dma_status & GMAC_DMA_INT_ERRORS) {
   1456 		if_statinc(&sc->sc_ec.ec_if, if_oerrors);
   1457 #ifdef DWC_GMAC_DEBUG
   1458 		dwc_dump_and_abort(sc, "interrupt error condition");
   1459 #endif
   1460 	}
   1461 
   1462 	rnd_add_uint32(&sc->rnd_source, dma_status);
   1463 
   1464 	/* ack interrupt */
   1465 	if (dma_status)
   1466 		bus_space_write_4(sc->sc_bst, sc->sc_bsh,
   1467 		    AWIN_GMAC_DMA_STATUS, dma_status & GMAC_DMA_INT_MASK);
   1468 
   1469 	/*
   1470 	 * Get more packets
   1471 	 */
   1472 	if (rv)
   1473 		if_schedule_deferred_start(&sc->sc_ec.ec_if);
   1474 
   1475 	return rv;
   1476 }
   1477 
   1478 static void
   1479 dwc_gmac_desc_set_owned_by_dev(struct dwc_gmac_dev_dmadesc *desc)
   1480 {
   1481 
   1482 	desc->ddesc_status0 |= htole32(DDESC_STATUS_OWNEDBYDEV);
   1483 }
   1484 
   1485 static int
   1486 dwc_gmac_desc_is_owned_by_dev(struct dwc_gmac_dev_dmadesc *desc)
   1487 {
   1488 
   1489 	return !!(le32toh(desc->ddesc_status0) & DDESC_STATUS_OWNEDBYDEV);
   1490 }
   1491 
   1492 static void
   1493 dwc_gmac_desc_std_set_len(struct dwc_gmac_dev_dmadesc *desc, int len)
   1494 {
   1495 	uint32_t cntl = le32toh(desc->ddesc_cntl1);
   1496 
   1497 	desc->ddesc_cntl1 = htole32((cntl & ~DDESC_CNTL_SIZE1MASK) |
   1498 		__SHIFTIN(len, DDESC_CNTL_SIZE1MASK));
   1499 }
   1500 
   1501 static uint32_t
   1502 dwc_gmac_desc_std_get_len(struct dwc_gmac_dev_dmadesc *desc)
   1503 {
   1504 
   1505 	return __SHIFTOUT(le32toh(desc->ddesc_status0), DDESC_STATUS_FRMLENMSK);
   1506 }
   1507 
   1508 static void
   1509 dwc_gmac_desc_std_tx_init_flags(struct dwc_gmac_dev_dmadesc *desc)
   1510 {
   1511 
   1512 	desc->ddesc_status0 = 0;
   1513 	desc->ddesc_cntl1 = htole32(DDESC_CNTL_TXCHAIN);
   1514 }
   1515 
   1516 static void
   1517 dwc_gmac_desc_std_tx_set_first_frag(struct dwc_gmac_dev_dmadesc *desc)
   1518 {
   1519 	uint32_t cntl = le32toh(desc->ddesc_cntl1);
   1520 
   1521 	desc->ddesc_cntl1 = htole32(cntl | DDESC_CNTL_TXFIRST);
   1522 }
   1523 
   1524 static void
   1525 dwc_gmac_desc_std_tx_set_last_frag(struct dwc_gmac_dev_dmadesc *desc)
   1526 {
   1527 	uint32_t cntl = le32toh(desc->ddesc_cntl1);
   1528 
   1529 	desc->ddesc_cntl1 = htole32(cntl |
   1530 		DDESC_CNTL_TXLAST | DDESC_CNTL_TXINT);
   1531 }
   1532 
   1533 static void
   1534 dwc_gmac_desc_std_rx_init_flags(struct dwc_gmac_dev_dmadesc *desc)
   1535 {
   1536 
   1537 	desc->ddesc_status0 = 0;
   1538 	desc->ddesc_cntl1 = htole32(DDESC_CNTL_TXCHAIN);
   1539 }
   1540 
   1541 static int
   1542 dwc_gmac_desc_std_rx_has_error(struct dwc_gmac_dev_dmadesc *desc) {
   1543 	return !!(le32toh(desc->ddesc_status0) &
   1544 		(DDESC_STATUS_RXERROR | DDESC_STATUS_RXTRUNCATED));
   1545 }
   1546 
   1547 static void
   1548 dwc_gmac_desc_enh_set_len(struct dwc_gmac_dev_dmadesc *desc, int len)
   1549 {
   1550 	uint32_t tdes1 = le32toh(desc->ddesc_cntl1);
   1551 
   1552 	desc->ddesc_cntl1 = htole32((tdes1 & ~DDESC_DES1_SIZE1MASK) |
   1553 		__SHIFTIN(len, DDESC_DES1_SIZE1MASK));
   1554 }
   1555 
   1556 static uint32_t
   1557 dwc_gmac_desc_enh_get_len(struct dwc_gmac_dev_dmadesc *desc)
   1558 {
   1559 
   1560 	return __SHIFTOUT(le32toh(desc->ddesc_status0), DDESC_RDES0_FL);
   1561 }
   1562 
   1563 static void
   1564 dwc_gmac_desc_enh_tx_init_flags(struct dwc_gmac_dev_dmadesc *desc)
   1565 {
   1566 
   1567 	desc->ddesc_status0 = htole32(DDESC_TDES0_TCH);
   1568 	desc->ddesc_cntl1 = 0;
   1569 }
   1570 
   1571 static void
   1572 dwc_gmac_desc_enh_tx_set_first_frag(struct dwc_gmac_dev_dmadesc *desc)
   1573 {
   1574 	uint32_t tdes0 = le32toh(desc->ddesc_status0);
   1575 
   1576 	desc->ddesc_status0 = htole32(tdes0 | DDESC_TDES0_FS);
   1577 }
   1578 
   1579 static void
   1580 dwc_gmac_desc_enh_tx_set_last_frag(struct dwc_gmac_dev_dmadesc *desc)
   1581 {
   1582 	uint32_t tdes0 = le32toh(desc->ddesc_status0);
   1583 
   1584 	desc->ddesc_status0 = htole32(tdes0 | DDESC_TDES0_LS | DDESC_TDES0_IC);
   1585 }
   1586 
   1587 static void
   1588 dwc_gmac_desc_enh_rx_init_flags(struct dwc_gmac_dev_dmadesc *desc)
   1589 {
   1590 
   1591 	desc->ddesc_status0 = 0;
   1592 	desc->ddesc_cntl1 = htole32(DDESC_RDES1_RCH);
   1593 }
   1594 
   1595 static int
   1596 dwc_gmac_desc_enh_rx_has_error(struct dwc_gmac_dev_dmadesc *desc)
   1597 {
   1598 
   1599 	return !!(le32toh(desc->ddesc_status0) &
   1600 		(DDESC_RDES0_ES | DDESC_RDES0_LE));
   1601 }
   1602 
   1603 #ifdef DWC_GMAC_DEBUG
   1604 static void
   1605 dwc_gmac_dump_dma(struct dwc_gmac_softc *sc)
   1606 {
   1607 	aprint_normal_dev(sc->sc_dev, "busmode: %08x\n",
   1608 	    bus_space_read_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_DMA_BUSMODE));
   1609 	aprint_normal_dev(sc->sc_dev, "tx poll: %08x\n",
   1610 	    bus_space_read_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_DMA_TXPOLL));
   1611 	aprint_normal_dev(sc->sc_dev, "rx poll: %08x\n",
   1612 	    bus_space_read_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_DMA_RXPOLL));
   1613 	aprint_normal_dev(sc->sc_dev, "rx descriptors: %08x\n",
   1614 	    bus_space_read_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_DMA_RX_ADDR));
   1615 	aprint_normal_dev(sc->sc_dev, "tx descriptors: %08x\n",
   1616 	    bus_space_read_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_DMA_TX_ADDR));
   1617 	aprint_normal_dev(sc->sc_dev, "status: %08x\n",
   1618 	    bus_space_read_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_DMA_STATUS));
   1619 	aprint_normal_dev(sc->sc_dev, "op mode: %08x\n",
   1620 	    bus_space_read_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_DMA_OPMODE));
   1621 	aprint_normal_dev(sc->sc_dev, "int enable: %08x\n",
   1622 	    bus_space_read_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_DMA_INTENABLE));
   1623 	aprint_normal_dev(sc->sc_dev, "cur tx: %08x\n",
   1624 	    bus_space_read_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_DMA_CUR_TX_DESC));
   1625 	aprint_normal_dev(sc->sc_dev, "cur rx: %08x\n",
   1626 	    bus_space_read_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_DMA_CUR_RX_DESC));
   1627 	aprint_normal_dev(sc->sc_dev, "cur tx buffer: %08x\n",
   1628 	    bus_space_read_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_DMA_CUR_TX_BUFADDR));
   1629 	aprint_normal_dev(sc->sc_dev, "cur rx buffer: %08x\n",
   1630 	    bus_space_read_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_DMA_CUR_RX_BUFADDR));
   1631 }
   1632 
   1633 static void
   1634 dwc_gmac_dump_tx_desc(struct dwc_gmac_softc *sc)
   1635 {
   1636 	int i;
   1637 
   1638 	aprint_normal_dev(sc->sc_dev, "TX queue: cur=%d, next=%d, queued=%d\n",
   1639 	    sc->sc_txq.t_cur, sc->sc_txq.t_next, sc->sc_txq.t_queued);
   1640 	aprint_normal_dev(sc->sc_dev, "TX DMA descriptors:\n");
   1641 	for (i = 0; i < AWGE_TX_RING_COUNT; i++) {
   1642 		struct dwc_gmac_dev_dmadesc *desc = &sc->sc_txq.t_desc[i];
   1643 		aprint_normal("#%d (%08lx): status: %08x cntl: %08x "
   1644 		    "data: %08x next: %08x\n",
   1645 		    i, sc->sc_txq.t_physaddr +
   1646 			i * sizeof(struct dwc_gmac_dev_dmadesc),
   1647 		    le32toh(desc->ddesc_status0), le32toh(desc->ddesc_cntl1),
   1648 		    le32toh(desc->ddesc_data), le32toh(desc->ddesc_next));
   1649 	}
   1650 }
   1651 
   1652 static void
   1653 dwc_gmac_dump_rx_desc(struct dwc_gmac_softc *sc)
   1654 {
   1655 	int i;
   1656 
   1657 	aprint_normal_dev(sc->sc_dev, "RX queue: cur=%d, next=%d\n",
   1658 	    sc->sc_rxq.r_cur, sc->sc_rxq.r_next);
   1659 	aprint_normal_dev(sc->sc_dev, "RX DMA descriptors:\n");
   1660 	for (i = 0; i < AWGE_RX_RING_COUNT; i++) {
   1661 		struct dwc_gmac_dev_dmadesc *desc = &sc->sc_rxq.r_desc[i];
   1662 		aprint_normal("#%d (%08lx): status: %08x cntl: %08x "
   1663 		    "data: %08x next: %08x\n",
   1664 		    i, sc->sc_rxq.r_physaddr +
   1665 			i * sizeof(struct dwc_gmac_dev_dmadesc),
   1666 		    le32toh(desc->ddesc_status0), le32toh(desc->ddesc_cntl1),
   1667 		    le32toh(desc->ddesc_data), le32toh(desc->ddesc_next));
   1668 	}
   1669 }
   1670 
   1671 static void
   1672 dwc_dump_status(struct dwc_gmac_softc *sc)
   1673 {
   1674 	uint32_t status = bus_space_read_4(sc->sc_bst, sc->sc_bsh,
   1675 	    AWIN_GMAC_MAC_INTR);
   1676 	uint32_t dma_status = bus_space_read_4(sc->sc_bst, sc->sc_bsh,
   1677 	    AWIN_GMAC_DMA_STATUS);
   1678 	char buf[200];
   1679 
   1680 	/* print interrupt state */
   1681 	snprintb(buf, sizeof(buf), "\177\20"
   1682 	    "b\x10""NI\0"
   1683 	    "b\x0f""AI\0"
   1684 	    "b\x0e""ER\0"
   1685 	    "b\x0d""FB\0"
   1686 	    "b\x0a""ET\0"
   1687 	    "b\x09""RW\0"
   1688 	    "b\x08""RS\0"
   1689 	    "b\x07""RU\0"
   1690 	    "b\x06""RI\0"
   1691 	    "b\x05""UN\0"
   1692 	    "b\x04""OV\0"
   1693 	    "b\x03""TJ\0"
   1694 	    "b\x02""TU\0"
   1695 	    "b\x01""TS\0"
   1696 	    "b\x00""TI\0"
   1697 	    "\0", dma_status);
   1698 	aprint_normal_dev(sc->sc_dev, "INTR status: %08x, DMA status: %s\n",
   1699 	    status, buf);
   1700 }
   1701 
   1702 static void
   1703 dwc_dump_and_abort(struct dwc_gmac_softc *sc, const char *msg)
   1704 {
   1705 	dwc_dump_status(sc);
   1706 	dwc_gmac_dump_ffilt(sc,
   1707 	    bus_space_read_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_MAC_FFILT));
   1708 	dwc_gmac_dump_dma(sc);
   1709 	dwc_gmac_dump_tx_desc(sc);
   1710 	dwc_gmac_dump_rx_desc(sc);
   1711 
   1712 	panic("%s", msg);
   1713 }
   1714 
   1715 static void dwc_gmac_dump_ffilt(struct dwc_gmac_softc *sc, uint32_t ffilt)
   1716 {
   1717 	char buf[200];
   1718 
   1719 	/* print filter setup */
   1720 	snprintb(buf, sizeof(buf), "\177\20"
   1721 	    "b\x1f""RA\0"
   1722 	    "b\x0a""HPF\0"
   1723 	    "b\x09""SAF\0"
   1724 	    "b\x08""SAIF\0"
   1725 	    "b\x05""DBF\0"
   1726 	    "b\x04""PM\0"
   1727 	    "b\x03""DAIF\0"
   1728 	    "b\x02""HMC\0"
   1729 	    "b\x01""HUC\0"
   1730 	    "b\x00""PR\0"
   1731 	    "\0", ffilt);
   1732 	aprint_normal_dev(sc->sc_dev, "FFILT: %s\n", buf);
   1733 }
   1734 #endif
   1735