Home | History | Annotate | Line # | Download | only in ic
dwc_gmac.c revision 1.87
      1 /* $NetBSD: dwc_gmac.c,v 1.87 2024/06/16 17:11:11 skrll 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.87 2024/06/16 17:11:11 skrll 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 		if (data->rd_m != NULL)
    670 			m_freem(data->rd_m);
    671 	}
    672 }
    673 
    674 static int
    675 dwc_gmac_alloc_tx_ring(struct dwc_gmac_softc *sc,
    676 	struct dwc_gmac_tx_ring *ring)
    677 {
    678 	int i, error = 0;
    679 
    680 	ring->t_queued = 0;
    681 	ring->t_cur = ring->t_next = 0;
    682 
    683 	memset(ring->t_desc, 0, AWGE_TX_RING_COUNT * sizeof(*ring->t_desc));
    684 	bus_dmamap_sync(sc->sc_dmat, sc->sc_dma_ring_map,
    685 	    TX_DESC_OFFSET(0),
    686 	    AWGE_TX_RING_COUNT * sizeof(struct dwc_gmac_dev_dmadesc),
    687 	    BUS_DMASYNC_POSTWRITE);
    688 
    689 	for (i = 0; i < AWGE_TX_RING_COUNT; i++) {
    690 		error = bus_dmamap_create(sc->sc_dmat, MCLBYTES,
    691 		    AWGE_TX_RING_COUNT, MCLBYTES, 0,
    692 		    BUS_DMA_NOWAIT | BUS_DMA_COHERENT,
    693 		    &ring->t_data[i].td_map);
    694 		if (error != 0) {
    695 			aprint_error_dev(sc->sc_dev,
    696 			    "could not create TX DMA map #%d\n", i);
    697 			ring->t_data[i].td_map = NULL;
    698 			goto fail;
    699 		}
    700 		ring->t_desc[i].ddesc_next = htole32(
    701 		    ring->t_physaddr + sizeof(struct dwc_gmac_dev_dmadesc)
    702 		    * TX_NEXT(i));
    703 	}
    704 
    705 	return 0;
    706 
    707 fail:
    708 	dwc_gmac_free_tx_ring(sc, ring);
    709 	return error;
    710 }
    711 
    712 static void
    713 dwc_gmac_txdesc_sync(struct dwc_gmac_softc *sc, int start, int end, int ops)
    714 {
    715 	/* 'end' is pointing one descriptor beyond the last we want to sync */
    716 	if (end > start) {
    717 		bus_dmamap_sync(sc->sc_dmat, sc->sc_dma_ring_map,
    718 		    TX_DESC_OFFSET(start),
    719 		    TX_DESC_OFFSET(end) - TX_DESC_OFFSET(start),
    720 		    ops);
    721 		return;
    722 	}
    723 	/* sync from 'start' to end of ring */
    724 	bus_dmamap_sync(sc->sc_dmat, sc->sc_dma_ring_map,
    725 	    TX_DESC_OFFSET(start),
    726 	    TX_DESC_OFFSET(AWGE_TX_RING_COUNT) - TX_DESC_OFFSET(start),
    727 	    ops);
    728 	if (TX_DESC_OFFSET(end) - TX_DESC_OFFSET(0) > 0) {
    729 		/* sync from start of ring to 'end' */
    730 		bus_dmamap_sync(sc->sc_dmat, sc->sc_dma_ring_map,
    731 		    TX_DESC_OFFSET(0),
    732 		    TX_DESC_OFFSET(end) - TX_DESC_OFFSET(0),
    733 		    ops);
    734 	}
    735 }
    736 
    737 static void
    738 dwc_gmac_reset_tx_ring(struct dwc_gmac_softc *sc,
    739 	struct dwc_gmac_tx_ring *ring)
    740 {
    741 	int i;
    742 
    743 	mutex_enter(&ring->t_mtx);
    744 	for (i = 0; i < AWGE_TX_RING_COUNT; i++) {
    745 		struct dwc_gmac_tx_data *data = &ring->t_data[i];
    746 
    747 		if (data->td_m != NULL) {
    748 			bus_dmamap_sync(sc->sc_dmat, data->td_active,
    749 			    0, data->td_active->dm_mapsize,
    750 			    BUS_DMASYNC_POSTWRITE);
    751 			bus_dmamap_unload(sc->sc_dmat, data->td_active);
    752 			m_freem(data->td_m);
    753 			data->td_m = NULL;
    754 		}
    755 	}
    756 
    757 	bus_dmamap_sync(sc->sc_dmat, sc->sc_dma_ring_map,
    758 	    TX_DESC_OFFSET(0),
    759 	    AWGE_TX_RING_COUNT * sizeof(struct dwc_gmac_dev_dmadesc),
    760 	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
    761 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_DMA_TX_ADDR,
    762 	    sc->sc_txq.t_physaddr);
    763 
    764 	ring->t_queued = 0;
    765 	ring->t_cur = ring->t_next = 0;
    766 	mutex_exit(&ring->t_mtx);
    767 }
    768 
    769 static void
    770 dwc_gmac_free_tx_ring(struct dwc_gmac_softc *sc,
    771 	struct dwc_gmac_tx_ring *ring)
    772 {
    773 	int i;
    774 
    775 	/* unload the maps */
    776 	for (i = 0; i < AWGE_TX_RING_COUNT; i++) {
    777 		struct dwc_gmac_tx_data *data = &ring->t_data[i];
    778 
    779 		if (data->td_m != NULL) {
    780 			bus_dmamap_sync(sc->sc_dmat, data->td_active,
    781 			    0, data->td_map->dm_mapsize,
    782 			    BUS_DMASYNC_POSTWRITE);
    783 			bus_dmamap_unload(sc->sc_dmat, data->td_active);
    784 			m_freem(data->td_m);
    785 			data->td_m = NULL;
    786 		}
    787 	}
    788 
    789 	/* and actually free them */
    790 	for (i = 0; i < AWGE_TX_RING_COUNT; i++) {
    791 		struct dwc_gmac_tx_data *data = &ring->t_data[i];
    792 
    793 		bus_dmamap_destroy(sc->sc_dmat, data->td_map);
    794 	}
    795 }
    796 
    797 static void
    798 dwc_gmac_miibus_statchg(struct ifnet *ifp)
    799 {
    800 	struct dwc_gmac_softc * const sc = ifp->if_softc;
    801 	struct mii_data * const mii = &sc->sc_mii;
    802 	uint32_t conf, flow;
    803 
    804 	/*
    805 	 * Set MII or GMII interface based on the speed
    806 	 * negotiated by the PHY.
    807 	 */
    808 	conf = bus_space_read_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_MAC_CONF);
    809 	conf &= ~(AWIN_GMAC_MAC_CONF_FES100 | AWIN_GMAC_MAC_CONF_MIISEL
    810 	    | AWIN_GMAC_MAC_CONF_FULLDPLX);
    811 	conf |= AWIN_GMAC_MAC_CONF_FRAMEBURST
    812 	    | AWIN_GMAC_MAC_CONF_DISABLERXOWN
    813 	    | AWIN_GMAC_MAC_CONF_DISABLEJABBER
    814 	    | AWIN_GMAC_MAC_CONF_RXENABLE
    815 	    | AWIN_GMAC_MAC_CONF_TXENABLE;
    816 	switch (IFM_SUBTYPE(mii->mii_media_active)) {
    817 	case IFM_10_T:
    818 		conf |= AWIN_GMAC_MAC_CONF_MIISEL;
    819 		break;
    820 	case IFM_100_TX:
    821 		conf |= AWIN_GMAC_MAC_CONF_FES100 |
    822 			AWIN_GMAC_MAC_CONF_MIISEL;
    823 		break;
    824 	case IFM_1000_T:
    825 		break;
    826 	}
    827 	if (sc->sc_set_speed)
    828 		sc->sc_set_speed(sc, IFM_SUBTYPE(mii->mii_media_active));
    829 
    830 	flow = 0;
    831 	if (IFM_OPTIONS(mii->mii_media_active) & IFM_FDX) {
    832 		conf |= AWIN_GMAC_MAC_CONF_FULLDPLX;
    833 		flow |= __SHIFTIN(0x200, AWIN_GMAC_MAC_FLOWCTRL_PAUSE);
    834 	}
    835 	if (mii->mii_media_active & IFM_ETH_TXPAUSE) {
    836 		flow |= AWIN_GMAC_MAC_FLOWCTRL_TFE;
    837 	}
    838 	if (mii->mii_media_active & IFM_ETH_RXPAUSE) {
    839 		flow |= AWIN_GMAC_MAC_FLOWCTRL_RFE;
    840 	}
    841 	bus_space_write_4(sc->sc_bst, sc->sc_bsh,
    842 	    AWIN_GMAC_MAC_FLOWCTRL, flow);
    843 
    844 #ifdef DWC_GMAC_DEBUG
    845 	aprint_normal_dev(sc->sc_dev,
    846 	    "setting MAC conf register: %08x\n", conf);
    847 #endif
    848 
    849 	bus_space_write_4(sc->sc_bst, sc->sc_bsh,
    850 	    AWIN_GMAC_MAC_CONF, conf);
    851 }
    852 
    853 static int
    854 dwc_gmac_init(struct ifnet *ifp)
    855 {
    856 	struct dwc_gmac_softc *sc = ifp->if_softc;
    857 
    858 	mutex_enter(sc->sc_lock);
    859 	int ret = dwc_gmac_init_locked(ifp);
    860 	mutex_exit(sc->sc_lock);
    861 
    862 	return ret;
    863 }
    864 
    865 static int
    866 dwc_gmac_init_locked(struct ifnet *ifp)
    867 {
    868 	struct dwc_gmac_softc *sc = ifp->if_softc;
    869 	uint32_t ffilt;
    870 
    871 	if (ifp->if_flags & IFF_RUNNING)
    872 		return 0;
    873 
    874 	dwc_gmac_stop_locked(ifp, 0);
    875 
    876 	/*
    877 	 * Configure DMA burst/transfer mode and RX/TX priorities.
    878 	 * XXX - the GMAC_BUSMODE_PRIORXTX bits are undocumented.
    879 	 */
    880 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_DMA_BUSMODE,
    881 	    GMAC_BUSMODE_FIXEDBURST | GMAC_BUSMODE_4PBL |
    882 	    __SHIFTIN(2, GMAC_BUSMODE_RPBL) |
    883 	    __SHIFTIN(2, GMAC_BUSMODE_PBL));
    884 
    885 	/*
    886 	 * Set up address filter
    887 	 */
    888 	ffilt = bus_space_read_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_MAC_FFILT);
    889 	if (ifp->if_flags & IFF_PROMISC) {
    890 		ffilt |= AWIN_GMAC_MAC_FFILT_PR;
    891 	} else {
    892 		ffilt &= ~AWIN_GMAC_MAC_FFILT_PR;
    893 	}
    894 	if (ifp->if_flags & IFF_BROADCAST) {
    895 		ffilt &= ~AWIN_GMAC_MAC_FFILT_DBF;
    896 	} else {
    897 		ffilt |= AWIN_GMAC_MAC_FFILT_DBF;
    898 	}
    899 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_MAC_FFILT, ffilt);
    900 
    901 	/*
    902 	 * Set up multicast filter
    903 	 */
    904 	dwc_gmac_setmulti(sc);
    905 
    906 	/*
    907 	 * Set up dma pointer for RX and TX ring
    908 	 */
    909 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_DMA_RX_ADDR,
    910 	    sc->sc_rxq.r_physaddr);
    911 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_DMA_TX_ADDR,
    912 	    sc->sc_txq.t_physaddr);
    913 
    914 	/*
    915 	 * Start RX/TX part
    916 	 */
    917 	uint32_t opmode = GMAC_DMA_OP_RXSTART | GMAC_DMA_OP_TXSTART;
    918 	if ((sc->sc_flags & DWC_GMAC_FORCE_THRESH_DMA_MODE) == 0) {
    919 		opmode |= GMAC_DMA_OP_RXSTOREFORWARD | GMAC_DMA_OP_TXSTOREFORWARD;
    920 	}
    921 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_DMA_OPMODE, opmode);
    922 
    923 	sc->sc_stopping = false;
    924 
    925 	ifp->if_flags |= IFF_RUNNING;
    926 	sc->sc_txbusy = false;
    927 
    928 	return 0;
    929 }
    930 
    931 static void
    932 dwc_gmac_start(struct ifnet *ifp)
    933 {
    934 	struct dwc_gmac_softc *sc = ifp->if_softc;
    935 #ifdef DWCGMAC_MPSAFE
    936 	KASSERT(if_is_mpsafe(ifp));
    937 #endif
    938 
    939 	mutex_enter(sc->sc_lock);
    940 	if (!sc->sc_stopping) {
    941 		mutex_enter(&sc->sc_txq.t_mtx);
    942 		dwc_gmac_start_locked(ifp);
    943 		mutex_exit(&sc->sc_txq.t_mtx);
    944 	}
    945 	mutex_exit(sc->sc_lock);
    946 }
    947 
    948 static void
    949 dwc_gmac_start_locked(struct ifnet *ifp)
    950 {
    951 	struct dwc_gmac_softc *sc = ifp->if_softc;
    952 	int old = sc->sc_txq.t_queued;
    953 	int start = sc->sc_txq.t_cur;
    954 	struct mbuf *m0;
    955 
    956 	if ((ifp->if_flags & IFF_RUNNING) == 0)
    957 		return;
    958 	if (sc->sc_txbusy)
    959 		return;
    960 
    961 	for (;;) {
    962 		IFQ_POLL(&ifp->if_snd, m0);
    963 		if (m0 == NULL)
    964 			break;
    965 		if (dwc_gmac_queue(sc, m0) != 0) {
    966 			sc->sc_txbusy = true;
    967 			break;
    968 		}
    969 		IFQ_DEQUEUE(&ifp->if_snd, m0);
    970 		bpf_mtap(ifp, m0, BPF_D_OUT);
    971 		if (sc->sc_txq.t_queued == AWGE_TX_RING_COUNT) {
    972 			sc->sc_txbusy = true;
    973 			break;
    974 		}
    975 	}
    976 
    977 	if (sc->sc_txq.t_queued != old) {
    978 		/* packets have been queued, kick it off */
    979 		dwc_gmac_txdesc_sync(sc, start, sc->sc_txq.t_cur,
    980 		    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
    981 
    982 #ifdef DWC_GMAC_DEBUG
    983 		dwc_dump_status(sc);
    984 #endif
    985 		bus_space_write_4(sc->sc_bst, sc->sc_bsh,
    986 		    AWIN_GMAC_DMA_TXPOLL, ~0U);
    987 	}
    988 }
    989 
    990 static void
    991 dwc_gmac_stop(struct ifnet *ifp, int disable)
    992 {
    993 	struct dwc_gmac_softc *sc = ifp->if_softc;
    994 
    995 	mutex_enter(sc->sc_lock);
    996 	dwc_gmac_stop_locked(ifp, disable);
    997 	mutex_exit(sc->sc_lock);
    998 }
    999 
   1000 static void
   1001 dwc_gmac_stop_locked(struct ifnet *ifp, int disable)
   1002 {
   1003 	struct dwc_gmac_softc *sc = ifp->if_softc;
   1004 
   1005 	sc->sc_stopping = true;
   1006 
   1007 	bus_space_write_4(sc->sc_bst, sc->sc_bsh,
   1008 	    AWIN_GMAC_DMA_OPMODE,
   1009 	    bus_space_read_4(sc->sc_bst, sc->sc_bsh,
   1010 		AWIN_GMAC_DMA_OPMODE)
   1011 		& ~(GMAC_DMA_OP_TXSTART | GMAC_DMA_OP_RXSTART));
   1012 	bus_space_write_4(sc->sc_bst, sc->sc_bsh,
   1013 	    AWIN_GMAC_DMA_OPMODE,
   1014 	    bus_space_read_4(sc->sc_bst, sc->sc_bsh,
   1015 		AWIN_GMAC_DMA_OPMODE) | GMAC_DMA_OP_FLUSHTX);
   1016 
   1017 	mii_down(&sc->sc_mii);
   1018 	dwc_gmac_reset_tx_ring(sc, &sc->sc_txq);
   1019 	dwc_gmac_reset_rx_ring(sc, &sc->sc_rxq);
   1020 
   1021 	ifp->if_flags &= ~IFF_RUNNING;
   1022 	sc->sc_txbusy = false;
   1023 }
   1024 
   1025 /*
   1026  * Add m0 to the TX ring
   1027  */
   1028 static int
   1029 dwc_gmac_queue(struct dwc_gmac_softc *sc, struct mbuf *m0)
   1030 {
   1031 	struct dwc_gmac_dev_dmadesc *desc = NULL;
   1032 	struct dwc_gmac_tx_data *data = NULL;
   1033 	bus_dmamap_t map;
   1034 	int error, i, first;
   1035 
   1036 #ifdef DWC_GMAC_DEBUG
   1037 	aprint_normal_dev(sc->sc_dev,
   1038 	    "dwc_gmac_queue: adding mbuf chain %p\n", m0);
   1039 #endif
   1040 
   1041 	first = sc->sc_txq.t_cur;
   1042 	map = sc->sc_txq.t_data[first].td_map;
   1043 
   1044 	error = bus_dmamap_load_mbuf(sc->sc_dmat, map, m0,
   1045 	    BUS_DMA_WRITE | BUS_DMA_NOWAIT);
   1046 	if (error != 0) {
   1047 		aprint_error_dev(sc->sc_dev, "could not map mbuf "
   1048 		    "(len: %d, error %d)\n", m0->m_pkthdr.len, error);
   1049 		return error;
   1050 	}
   1051 
   1052 	if (sc->sc_txq.t_queued + map->dm_nsegs > AWGE_TX_RING_COUNT) {
   1053 		bus_dmamap_unload(sc->sc_dmat, map);
   1054 		return ENOBUFS;
   1055 	}
   1056 
   1057 	for (i = 0; i < map->dm_nsegs; i++) {
   1058 		data = &sc->sc_txq.t_data[sc->sc_txq.t_cur];
   1059 		desc = &sc->sc_txq.t_desc[sc->sc_txq.t_cur];
   1060 
   1061 		desc->ddesc_data = htole32(map->dm_segs[i].ds_addr);
   1062 
   1063 #ifdef DWC_GMAC_DEBUG
   1064 		aprint_normal_dev(sc->sc_dev, "enqueuing desc #%d data %08lx "
   1065 		    "len %lu\n", sc->sc_txq.t_cur,
   1066 		    (unsigned long)map->dm_segs[i].ds_addr,
   1067 		    (unsigned long)map->dm_segs[i].ds_len);
   1068 #endif
   1069 
   1070 		sc->sc_descm->tx_init_flags(desc);
   1071 		sc->sc_descm->tx_set_len(desc, map->dm_segs[i].ds_len);
   1072 
   1073 		if (i == 0)
   1074 			sc->sc_descm->tx_set_first_frag(desc);
   1075 
   1076 		/*
   1077 		 * Defer passing ownership of the first descriptor
   1078 		 * until we are done.
   1079 		 */
   1080 		if (i != 0)
   1081 			sc->sc_descm->tx_set_owned_by_dev(desc);
   1082 
   1083 		sc->sc_txq.t_queued++;
   1084 		sc->sc_txq.t_cur = TX_NEXT(sc->sc_txq.t_cur);
   1085 	}
   1086 
   1087 	sc->sc_descm->tx_set_last_frag(desc);
   1088 
   1089 	data->td_m = m0;
   1090 	data->td_active = map;
   1091 
   1092 	bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize,
   1093 	    BUS_DMASYNC_PREWRITE);
   1094 
   1095 	/* Pass first to device */
   1096 	sc->sc_descm->tx_set_owned_by_dev(&sc->sc_txq.t_desc[first]);
   1097 
   1098 	bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize,
   1099 	    BUS_DMASYNC_PREWRITE);
   1100 
   1101 	return 0;
   1102 }
   1103 
   1104 /*
   1105  * If the interface is up and running, only modify the receive
   1106  * filter when setting promiscuous or debug mode.  Otherwise fall
   1107  * through to ether_ioctl, which will reset the chip.
   1108  */
   1109 static int
   1110 dwc_gmac_ifflags_cb(struct ethercom *ec)
   1111 {
   1112 	struct ifnet *ifp = &ec->ec_if;
   1113 	struct dwc_gmac_softc *sc = ifp->if_softc;
   1114 	int ret = 0;
   1115 
   1116 	mutex_enter(sc->sc_lock);
   1117 	u_short change = ifp->if_flags ^ sc->sc_if_flags;
   1118 	sc->sc_if_flags = ifp->if_flags;
   1119 
   1120 	if ((change & ~(IFF_CANTCHANGE | IFF_DEBUG)) != 0) {
   1121 		ret = ENETRESET;
   1122 		goto out;
   1123 	}
   1124 	if ((change & IFF_PROMISC) != 0) {
   1125 		dwc_gmac_setmulti(sc);
   1126 	}
   1127 out:
   1128 	mutex_exit(sc->sc_lock);
   1129 
   1130 	return ret;
   1131 }
   1132 
   1133 static int
   1134 dwc_gmac_ioctl(struct ifnet *ifp, u_long cmd, void *data)
   1135 {
   1136 	struct dwc_gmac_softc *sc = ifp->if_softc;
   1137 	int error = 0;
   1138 
   1139 	int s = splnet();
   1140 	error = ether_ioctl(ifp, cmd, data);
   1141 
   1142 #ifdef DWCGMAC_MPSAFE
   1143 	splx(s);
   1144 #endif
   1145 
   1146 	if (error == ENETRESET) {
   1147 		error = 0;
   1148 		if (cmd != SIOCADDMULTI && cmd != SIOCDELMULTI)
   1149 			;
   1150 		else if (ifp->if_flags & IFF_RUNNING) {
   1151 			/*
   1152 			 * Multicast list has changed; set the hardware filter
   1153 			 * accordingly.
   1154 			 */
   1155 			mutex_enter(sc->sc_lock);
   1156 			dwc_gmac_setmulti(sc);
   1157 			mutex_exit(sc->sc_lock);
   1158 		}
   1159 	}
   1160 
   1161 	/* Try to get things going again */
   1162 	if (ifp->if_flags & IFF_UP)
   1163 		dwc_gmac_start(ifp);
   1164 	sc->sc_if_flags = sc->sc_ec.ec_if.if_flags;
   1165 
   1166 #ifndef DWCGMAC_MPSAFE
   1167 	splx(s);
   1168 #endif
   1169 
   1170 	return error;
   1171 }
   1172 
   1173 static void
   1174 dwc_gmac_tx_intr(struct dwc_gmac_softc *sc)
   1175 {
   1176 	struct ifnet *ifp = &sc->sc_ec.ec_if;
   1177 	struct dwc_gmac_tx_data *data;
   1178 	struct dwc_gmac_dev_dmadesc *desc;
   1179 	int i, nsegs;
   1180 
   1181 	mutex_enter(&sc->sc_txq.t_mtx);
   1182 
   1183 	for (i = sc->sc_txq.t_next; sc->sc_txq.t_queued > 0; i = TX_NEXT(i)) {
   1184 #ifdef DWC_GMAC_DEBUG
   1185 		aprint_normal_dev(sc->sc_dev,
   1186 		    "dwc_gmac_tx_intr: checking desc #%d (t_queued: %d)\n",
   1187 		    i, sc->sc_txq.t_queued);
   1188 #endif
   1189 
   1190 		/*
   1191 		 * i + 1 does not need to be a valid descriptor,
   1192 		 * this is just a special notion to just sync
   1193 		 * a single tx descriptor (i)
   1194 		 */
   1195 		dwc_gmac_txdesc_sync(sc, i, i + 1,
   1196 		    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
   1197 
   1198 		desc = &sc->sc_txq.t_desc[i];
   1199 		if (sc->sc_descm->tx_is_owned_by_dev(desc))
   1200 			break;
   1201 
   1202 		data = &sc->sc_txq.t_data[i];
   1203 		if (data->td_m == NULL)
   1204 			continue;
   1205 
   1206 		if_statinc(ifp, if_opackets);
   1207 		nsegs = data->td_active->dm_nsegs;
   1208 		bus_dmamap_sync(sc->sc_dmat, data->td_active, 0,
   1209 		    data->td_active->dm_mapsize, BUS_DMASYNC_POSTWRITE);
   1210 		bus_dmamap_unload(sc->sc_dmat, data->td_active);
   1211 
   1212 #ifdef DWC_GMAC_DEBUG
   1213 		aprint_normal_dev(sc->sc_dev,
   1214 		    "dwc_gmac_tx_intr: done with packet at desc #%d, "
   1215 		    "freeing mbuf %p\n", i, data->td_m);
   1216 #endif
   1217 
   1218 		m_freem(data->td_m);
   1219 		data->td_m = NULL;
   1220 
   1221 		sc->sc_txq.t_queued -= nsegs;
   1222 	}
   1223 
   1224 	sc->sc_txq.t_next = i;
   1225 
   1226 	if (sc->sc_txq.t_queued < AWGE_TX_RING_COUNT) {
   1227 		sc->sc_txbusy = false;
   1228 	}
   1229 	mutex_exit(&sc->sc_txq.t_mtx);
   1230 }
   1231 
   1232 static void
   1233 dwc_gmac_rx_intr(struct dwc_gmac_softc *sc)
   1234 {
   1235 	struct ifnet *ifp = &sc->sc_ec.ec_if;
   1236 	struct dwc_gmac_dev_dmadesc *desc;
   1237 	struct dwc_gmac_rx_data *data;
   1238 	bus_addr_t physaddr;
   1239 	struct mbuf *m, *mnew;
   1240 	int i, len, error;
   1241 
   1242 	mutex_enter(&sc->sc_rxq.r_mtx);
   1243 	for (i = sc->sc_rxq.r_cur; ; i = RX_NEXT(i)) {
   1244 		bus_dmamap_sync(sc->sc_dmat, sc->sc_dma_ring_map,
   1245 		    RX_DESC_OFFSET(i), sizeof(*desc),
   1246 		    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
   1247 		desc = &sc->sc_rxq.r_desc[i];
   1248 		data = &sc->sc_rxq.r_data[i];
   1249 
   1250 		if (sc->sc_descm->rx_is_owned_by_dev(desc))
   1251 			break;
   1252 
   1253 		if (sc->sc_descm->rx_has_error(desc)) {
   1254 #ifdef DWC_GMAC_DEBUG
   1255 			aprint_normal_dev(sc->sc_dev,
   1256 			    "RX error: descriptor status %08x, skipping\n",
   1257 			    le32toh(desc->ddesc_status0));
   1258 #endif
   1259 			if_statinc(ifp, if_ierrors);
   1260 			goto skip;
   1261 		}
   1262 
   1263 		len = sc->sc_descm->rx_get_len(desc);
   1264 
   1265 #ifdef DWC_GMAC_DEBUG
   1266 		aprint_normal_dev(sc->sc_dev,
   1267 		    "rx int: device is done with descriptor #%d, len: %d\n",
   1268 		    i, len);
   1269 #endif
   1270 
   1271 		/*
   1272 		 * Try to get a new mbuf before passing this one
   1273 		 * up, if that fails, drop the packet and reuse
   1274 		 * the existing one.
   1275 		 */
   1276 		MGETHDR(mnew, M_DONTWAIT, MT_DATA);
   1277 		if (mnew == NULL) {
   1278 			if_statinc(ifp, if_ierrors);
   1279 			goto skip;
   1280 		}
   1281 		MCLGET(mnew, M_DONTWAIT);
   1282 		if ((mnew->m_flags & M_EXT) == 0) {
   1283 			m_freem(mnew);
   1284 			if_statinc(ifp, if_ierrors);
   1285 			goto skip;
   1286 		}
   1287 		mnew->m_len = mnew->m_pkthdr.len = mnew->m_ext.ext_size;
   1288 		if (mnew->m_len > AWGE_MAX_PACKET) {
   1289 			mnew->m_len = mnew->m_pkthdr.len = AWGE_MAX_PACKET;
   1290 		}
   1291 
   1292 		/* unload old DMA map */
   1293 		bus_dmamap_sync(sc->sc_dmat, data->rd_map, 0,
   1294 		    data->rd_map->dm_mapsize, BUS_DMASYNC_POSTREAD);
   1295 		bus_dmamap_unload(sc->sc_dmat, data->rd_map);
   1296 
   1297 		/* and reload with new mbuf */
   1298 		error = bus_dmamap_load_mbuf(sc->sc_dmat, data->rd_map,
   1299 		    mnew, BUS_DMA_READ | BUS_DMA_NOWAIT);
   1300 		if (error != 0) {
   1301 			m_freem(mnew);
   1302 			/* try to reload old mbuf */
   1303 			error = bus_dmamap_load_mbuf(sc->sc_dmat, data->rd_map,
   1304 			    data->rd_m, BUS_DMA_READ | BUS_DMA_NOWAIT);
   1305 			if (error != 0) {
   1306 				panic("%s: could not load old rx mbuf",
   1307 				    device_xname(sc->sc_dev));
   1308 			}
   1309 			if_statinc(ifp, if_ierrors);
   1310 			goto skip;
   1311 		}
   1312 		physaddr = data->rd_map->dm_segs[0].ds_addr;
   1313 
   1314 		/*
   1315 		 * New mbuf loaded, update RX ring and continue
   1316 		 */
   1317 		m = data->rd_m;
   1318 		data->rd_m = mnew;
   1319 		desc->ddesc_data = htole32(physaddr);
   1320 
   1321 		/* finalize mbuf */
   1322 		m->m_pkthdr.len = m->m_len = len;
   1323 		m_set_rcvif(m, ifp);
   1324 		m->m_flags |= M_HASFCS;
   1325 
   1326 		if_percpuq_enqueue(sc->sc_ipq, m);
   1327 
   1328 skip:
   1329 		bus_dmamap_sync(sc->sc_dmat, data->rd_map, 0,
   1330 		    data->rd_map->dm_mapsize, BUS_DMASYNC_PREREAD);
   1331 
   1332 		sc->sc_descm->rx_init_flags(desc);
   1333 		sc->sc_descm->rx_set_len(desc, data->rd_m->m_len);
   1334 		sc->sc_descm->rx_set_owned_by_dev(desc);
   1335 
   1336 		bus_dmamap_sync(sc->sc_dmat, sc->sc_dma_ring_map,
   1337 		    RX_DESC_OFFSET(i), sizeof(*desc),
   1338 		    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
   1339 	}
   1340 
   1341 	/* update RX pointer */
   1342 	sc->sc_rxq.r_cur = i;
   1343 
   1344 	mutex_exit(&sc->sc_rxq.r_mtx);
   1345 }
   1346 
   1347 static void
   1348 dwc_gmac_setmulti(struct dwc_gmac_softc *sc)
   1349 {
   1350 	struct ifnet * const ifp = &sc->sc_ec.ec_if;
   1351 	struct ether_multi *enm;
   1352 	struct ether_multistep step;
   1353 	struct ethercom *ec = &sc->sc_ec;
   1354 	uint32_t hashes[2] = { 0, 0 };
   1355 	uint32_t ffilt, h;
   1356 	int mcnt;
   1357 
   1358 	KASSERT(mutex_owned(sc->sc_lock));
   1359 
   1360 	ffilt = bus_space_read_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_MAC_FFILT);
   1361 
   1362 	if (ifp->if_flags & IFF_PROMISC) {
   1363 		ffilt |= AWIN_GMAC_MAC_FFILT_PR;
   1364 		goto special_filter;
   1365 	}
   1366 
   1367 	ffilt &= ~(AWIN_GMAC_MAC_FFILT_PM | AWIN_GMAC_MAC_FFILT_PR);
   1368 
   1369 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_MAC_HTLOW, 0);
   1370 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_MAC_HTHIGH, 0);
   1371 
   1372 	ETHER_LOCK(ec);
   1373 	ec->ec_flags &= ~ETHER_F_ALLMULTI;
   1374 	ETHER_FIRST_MULTI(step, ec, enm);
   1375 	mcnt = 0;
   1376 	while (enm != NULL) {
   1377 		if (memcmp(enm->enm_addrlo, enm->enm_addrhi,
   1378 		    ETHER_ADDR_LEN) != 0) {
   1379 			ffilt |= AWIN_GMAC_MAC_FFILT_PM;
   1380 			ec->ec_flags |= ETHER_F_ALLMULTI;
   1381 			ETHER_UNLOCK(ec);
   1382 			goto special_filter;
   1383 		}
   1384 
   1385 		h = ~ether_crc32_be(enm->enm_addrlo, ETHER_ADDR_LEN) >> 26;
   1386 		hashes[h >> 5] |= (1 << (h & 0x1f));
   1387 
   1388 		mcnt++;
   1389 		ETHER_NEXT_MULTI(step, enm);
   1390 	}
   1391 	ETHER_UNLOCK(ec);
   1392 
   1393 	if (mcnt)
   1394 		ffilt |= AWIN_GMAC_MAC_FFILT_HMC;
   1395 	else
   1396 		ffilt &= ~AWIN_GMAC_MAC_FFILT_HMC;
   1397 
   1398 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_MAC_FFILT, ffilt);
   1399 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_MAC_HTLOW,
   1400 	    hashes[0]);
   1401 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_MAC_HTHIGH,
   1402 	    hashes[1]);
   1403 	sc->sc_if_flags = ifp->if_flags;
   1404 
   1405 #ifdef DWC_GMAC_DEBUG
   1406 	dwc_gmac_dump_ffilt(sc, ffilt);
   1407 #endif
   1408 	return;
   1409 
   1410 special_filter:
   1411 #ifdef DWC_GMAC_DEBUG
   1412 	dwc_gmac_dump_ffilt(sc, ffilt);
   1413 #endif
   1414 	/* no MAC hashes, ALLMULTI or PROMISC */
   1415 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_MAC_FFILT,
   1416 	    ffilt);
   1417 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_MAC_HTLOW,
   1418 	    0xffffffff);
   1419 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_MAC_HTHIGH,
   1420 	    0xffffffff);
   1421 	sc->sc_if_flags = sc->sc_ec.ec_if.if_flags;
   1422 }
   1423 
   1424 int
   1425 dwc_gmac_intr(struct dwc_gmac_softc *sc)
   1426 {
   1427 	uint32_t status, dma_status;
   1428 	int rv = 0;
   1429 
   1430 	if (sc->sc_stopping)
   1431 		return 0;
   1432 
   1433 	status = bus_space_read_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_MAC_INTR);
   1434 	if (status & AWIN_GMAC_MII_IRQ) {
   1435 		(void)bus_space_read_4(sc->sc_bst, sc->sc_bsh,
   1436 		    AWIN_GMAC_MII_STATUS);
   1437 		rv = 1;
   1438 		mii_pollstat(&sc->sc_mii);
   1439 	}
   1440 
   1441 	dma_status = bus_space_read_4(sc->sc_bst, sc->sc_bsh,
   1442 	    AWIN_GMAC_DMA_STATUS);
   1443 
   1444 	if (dma_status & (GMAC_DMA_INT_NIE | GMAC_DMA_INT_AIE))
   1445 		rv = 1;
   1446 
   1447 	if (dma_status & GMAC_DMA_INT_TIE)
   1448 		dwc_gmac_tx_intr(sc);
   1449 
   1450 	if (dma_status & GMAC_DMA_INT_RIE)
   1451 		dwc_gmac_rx_intr(sc);
   1452 
   1453 	/*
   1454 	 * Check error conditions
   1455 	 */
   1456 	if (dma_status & GMAC_DMA_INT_ERRORS) {
   1457 		if_statinc(&sc->sc_ec.ec_if, if_oerrors);
   1458 #ifdef DWC_GMAC_DEBUG
   1459 		dwc_dump_and_abort(sc, "interrupt error condition");
   1460 #endif
   1461 	}
   1462 
   1463 	rnd_add_uint32(&sc->rnd_source, dma_status);
   1464 
   1465 	/* ack interrupt */
   1466 	if (dma_status)
   1467 		bus_space_write_4(sc->sc_bst, sc->sc_bsh,
   1468 		    AWIN_GMAC_DMA_STATUS, dma_status & GMAC_DMA_INT_MASK);
   1469 
   1470 	/*
   1471 	 * Get more packets
   1472 	 */
   1473 	if (rv)
   1474 		if_schedule_deferred_start(&sc->sc_ec.ec_if);
   1475 
   1476 	return rv;
   1477 }
   1478 
   1479 static void
   1480 dwc_gmac_desc_set_owned_by_dev(struct dwc_gmac_dev_dmadesc *desc)
   1481 {
   1482 
   1483 	desc->ddesc_status0 |= htole32(DDESC_STATUS_OWNEDBYDEV);
   1484 }
   1485 
   1486 static int
   1487 dwc_gmac_desc_is_owned_by_dev(struct dwc_gmac_dev_dmadesc *desc)
   1488 {
   1489 
   1490 	return !!(le32toh(desc->ddesc_status0) & DDESC_STATUS_OWNEDBYDEV);
   1491 }
   1492 
   1493 static void
   1494 dwc_gmac_desc_std_set_len(struct dwc_gmac_dev_dmadesc *desc, int len)
   1495 {
   1496 	uint32_t cntl = le32toh(desc->ddesc_cntl1);
   1497 
   1498 	desc->ddesc_cntl1 = htole32((cntl & ~DDESC_CNTL_SIZE1MASK) |
   1499 		__SHIFTIN(len, DDESC_CNTL_SIZE1MASK));
   1500 }
   1501 
   1502 static uint32_t
   1503 dwc_gmac_desc_std_get_len(struct dwc_gmac_dev_dmadesc *desc)
   1504 {
   1505 
   1506 	return __SHIFTOUT(le32toh(desc->ddesc_status0), DDESC_STATUS_FRMLENMSK);
   1507 }
   1508 
   1509 static void
   1510 dwc_gmac_desc_std_tx_init_flags(struct dwc_gmac_dev_dmadesc *desc)
   1511 {
   1512 
   1513 	desc->ddesc_status0 = 0;
   1514 	desc->ddesc_cntl1 = htole32(DDESC_CNTL_TXCHAIN);
   1515 }
   1516 
   1517 static void
   1518 dwc_gmac_desc_std_tx_set_first_frag(struct dwc_gmac_dev_dmadesc *desc)
   1519 {
   1520 	uint32_t cntl = le32toh(desc->ddesc_cntl1);
   1521 
   1522 	desc->ddesc_cntl1 = htole32(cntl | DDESC_CNTL_TXFIRST);
   1523 }
   1524 
   1525 static void
   1526 dwc_gmac_desc_std_tx_set_last_frag(struct dwc_gmac_dev_dmadesc *desc)
   1527 {
   1528 	uint32_t cntl = le32toh(desc->ddesc_cntl1);
   1529 
   1530 	desc->ddesc_cntl1 = htole32(cntl |
   1531 		DDESC_CNTL_TXLAST | DDESC_CNTL_TXINT);
   1532 }
   1533 
   1534 static void
   1535 dwc_gmac_desc_std_rx_init_flags(struct dwc_gmac_dev_dmadesc *desc)
   1536 {
   1537 
   1538 	desc->ddesc_status0 = 0;
   1539 	desc->ddesc_cntl1 = htole32(DDESC_CNTL_TXCHAIN);
   1540 }
   1541 
   1542 static int
   1543 dwc_gmac_desc_std_rx_has_error(struct dwc_gmac_dev_dmadesc *desc) {
   1544 	return !!(le32toh(desc->ddesc_status0) &
   1545 		(DDESC_STATUS_RXERROR | DDESC_STATUS_RXTRUNCATED));
   1546 }
   1547 
   1548 static void
   1549 dwc_gmac_desc_enh_set_len(struct dwc_gmac_dev_dmadesc *desc, int len)
   1550 {
   1551 	uint32_t tdes1 = le32toh(desc->ddesc_cntl1);
   1552 
   1553 	desc->ddesc_cntl1 = htole32((tdes1 & ~DDESC_DES1_SIZE1MASK) |
   1554 		__SHIFTIN(len, DDESC_DES1_SIZE1MASK));
   1555 }
   1556 
   1557 static uint32_t
   1558 dwc_gmac_desc_enh_get_len(struct dwc_gmac_dev_dmadesc *desc)
   1559 {
   1560 
   1561 	return __SHIFTOUT(le32toh(desc->ddesc_status0), DDESC_RDES0_FL);
   1562 }
   1563 
   1564 static void
   1565 dwc_gmac_desc_enh_tx_init_flags(struct dwc_gmac_dev_dmadesc *desc)
   1566 {
   1567 
   1568 	desc->ddesc_status0 = htole32(DDESC_TDES0_TCH);
   1569 	desc->ddesc_cntl1 = 0;
   1570 }
   1571 
   1572 static void
   1573 dwc_gmac_desc_enh_tx_set_first_frag(struct dwc_gmac_dev_dmadesc *desc)
   1574 {
   1575 	uint32_t tdes0 = le32toh(desc->ddesc_status0);
   1576 
   1577 	desc->ddesc_status0 = htole32(tdes0 | DDESC_TDES0_FS);
   1578 }
   1579 
   1580 static void
   1581 dwc_gmac_desc_enh_tx_set_last_frag(struct dwc_gmac_dev_dmadesc *desc)
   1582 {
   1583 	uint32_t tdes0 = le32toh(desc->ddesc_status0);
   1584 
   1585 	desc->ddesc_status0 = htole32(tdes0 | DDESC_TDES0_LS | DDESC_TDES0_IC);
   1586 }
   1587 
   1588 static void
   1589 dwc_gmac_desc_enh_rx_init_flags(struct dwc_gmac_dev_dmadesc *desc)
   1590 {
   1591 
   1592 	desc->ddesc_status0 = 0;
   1593 	desc->ddesc_cntl1 = htole32(DDESC_RDES1_RCH);
   1594 }
   1595 
   1596 static int
   1597 dwc_gmac_desc_enh_rx_has_error(struct dwc_gmac_dev_dmadesc *desc)
   1598 {
   1599 
   1600 	return !!(le32toh(desc->ddesc_status0) &
   1601 		(DDESC_RDES0_ES | DDESC_RDES0_LE));
   1602 }
   1603 
   1604 #ifdef DWC_GMAC_DEBUG
   1605 static void
   1606 dwc_gmac_dump_dma(struct dwc_gmac_softc *sc)
   1607 {
   1608 	aprint_normal_dev(sc->sc_dev, "busmode: %08x\n",
   1609 	    bus_space_read_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_DMA_BUSMODE));
   1610 	aprint_normal_dev(sc->sc_dev, "tx poll: %08x\n",
   1611 	    bus_space_read_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_DMA_TXPOLL));
   1612 	aprint_normal_dev(sc->sc_dev, "rx poll: %08x\n",
   1613 	    bus_space_read_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_DMA_RXPOLL));
   1614 	aprint_normal_dev(sc->sc_dev, "rx descriptors: %08x\n",
   1615 	    bus_space_read_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_DMA_RX_ADDR));
   1616 	aprint_normal_dev(sc->sc_dev, "tx descriptors: %08x\n",
   1617 	    bus_space_read_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_DMA_TX_ADDR));
   1618 	aprint_normal_dev(sc->sc_dev, "status: %08x\n",
   1619 	    bus_space_read_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_DMA_STATUS));
   1620 	aprint_normal_dev(sc->sc_dev, "op mode: %08x\n",
   1621 	    bus_space_read_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_DMA_OPMODE));
   1622 	aprint_normal_dev(sc->sc_dev, "int enable: %08x\n",
   1623 	    bus_space_read_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_DMA_INTENABLE));
   1624 	aprint_normal_dev(sc->sc_dev, "cur tx: %08x\n",
   1625 	    bus_space_read_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_DMA_CUR_TX_DESC));
   1626 	aprint_normal_dev(sc->sc_dev, "cur rx: %08x\n",
   1627 	    bus_space_read_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_DMA_CUR_RX_DESC));
   1628 	aprint_normal_dev(sc->sc_dev, "cur tx buffer: %08x\n",
   1629 	    bus_space_read_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_DMA_CUR_TX_BUFADDR));
   1630 	aprint_normal_dev(sc->sc_dev, "cur rx buffer: %08x\n",
   1631 	    bus_space_read_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_DMA_CUR_RX_BUFADDR));
   1632 }
   1633 
   1634 static void
   1635 dwc_gmac_dump_tx_desc(struct dwc_gmac_softc *sc)
   1636 {
   1637 	int i;
   1638 
   1639 	aprint_normal_dev(sc->sc_dev, "TX queue: cur=%d, next=%d, queued=%d\n",
   1640 	    sc->sc_txq.t_cur, sc->sc_txq.t_next, sc->sc_txq.t_queued);
   1641 	aprint_normal_dev(sc->sc_dev, "TX DMA descriptors:\n");
   1642 	for (i = 0; i < AWGE_TX_RING_COUNT; i++) {
   1643 		struct dwc_gmac_dev_dmadesc *desc = &sc->sc_txq.t_desc[i];
   1644 		aprint_normal("#%d (%08lx): status: %08x cntl: %08x "
   1645 		    "data: %08x next: %08x\n",
   1646 		    i, sc->sc_txq.t_physaddr +
   1647 			i * sizeof(struct dwc_gmac_dev_dmadesc),
   1648 		    le32toh(desc->ddesc_status0), le32toh(desc->ddesc_cntl1),
   1649 		    le32toh(desc->ddesc_data), le32toh(desc->ddesc_next));
   1650 	}
   1651 }
   1652 
   1653 static void
   1654 dwc_gmac_dump_rx_desc(struct dwc_gmac_softc *sc)
   1655 {
   1656 	int i;
   1657 
   1658 	aprint_normal_dev(sc->sc_dev, "RX queue: cur=%d, next=%d\n",
   1659 	    sc->sc_rxq.r_cur, sc->sc_rxq.r_next);
   1660 	aprint_normal_dev(sc->sc_dev, "RX DMA descriptors:\n");
   1661 	for (i = 0; i < AWGE_RX_RING_COUNT; i++) {
   1662 		struct dwc_gmac_dev_dmadesc *desc = &sc->sc_rxq.r_desc[i];
   1663 		aprint_normal("#%d (%08lx): status: %08x cntl: %08x "
   1664 		    "data: %08x next: %08x\n",
   1665 		    i, sc->sc_rxq.r_physaddr +
   1666 			i * sizeof(struct dwc_gmac_dev_dmadesc),
   1667 		    le32toh(desc->ddesc_status0), le32toh(desc->ddesc_cntl1),
   1668 		    le32toh(desc->ddesc_data), le32toh(desc->ddesc_next));
   1669 	}
   1670 }
   1671 
   1672 static void
   1673 dwc_dump_status(struct dwc_gmac_softc *sc)
   1674 {
   1675 	uint32_t status = bus_space_read_4(sc->sc_bst, sc->sc_bsh,
   1676 	    AWIN_GMAC_MAC_INTR);
   1677 	uint32_t dma_status = bus_space_read_4(sc->sc_bst, sc->sc_bsh,
   1678 	    AWIN_GMAC_DMA_STATUS);
   1679 	char buf[200];
   1680 
   1681 	/* print interrupt state */
   1682 	snprintb(buf, sizeof(buf), "\177\20"
   1683 	    "b\x10""NI\0"
   1684 	    "b\x0f""AI\0"
   1685 	    "b\x0e""ER\0"
   1686 	    "b\x0d""FB\0"
   1687 	    "b\x0a""ET\0"
   1688 	    "b\x09""RW\0"
   1689 	    "b\x08""RS\0"
   1690 	    "b\x07""RU\0"
   1691 	    "b\x06""RI\0"
   1692 	    "b\x05""UN\0"
   1693 	    "b\x04""OV\0"
   1694 	    "b\x03""TJ\0"
   1695 	    "b\x02""TU\0"
   1696 	    "b\x01""TS\0"
   1697 	    "b\x00""TI\0"
   1698 	    "\0", dma_status);
   1699 	aprint_normal_dev(sc->sc_dev, "INTR status: %08x, DMA status: %s\n",
   1700 	    status, buf);
   1701 }
   1702 
   1703 static void
   1704 dwc_dump_and_abort(struct dwc_gmac_softc *sc, const char *msg)
   1705 {
   1706 	dwc_dump_status(sc);
   1707 	dwc_gmac_dump_ffilt(sc,
   1708 	    bus_space_read_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_MAC_FFILT));
   1709 	dwc_gmac_dump_dma(sc);
   1710 	dwc_gmac_dump_tx_desc(sc);
   1711 	dwc_gmac_dump_rx_desc(sc);
   1712 
   1713 	panic("%s", msg);
   1714 }
   1715 
   1716 static void dwc_gmac_dump_ffilt(struct dwc_gmac_softc *sc, uint32_t ffilt)
   1717 {
   1718 	char buf[200];
   1719 
   1720 	/* print filter setup */
   1721 	snprintb(buf, sizeof(buf), "\177\20"
   1722 	    "b\x1f""RA\0"
   1723 	    "b\x0a""HPF\0"
   1724 	    "b\x09""SAF\0"
   1725 	    "b\x08""SAIF\0"
   1726 	    "b\x05""DBF\0"
   1727 	    "b\x04""PM\0"
   1728 	    "b\x03""DAIF\0"
   1729 	    "b\x02""HMC\0"
   1730 	    "b\x01""HUC\0"
   1731 	    "b\x00""PR\0"
   1732 	    "\0", ffilt);
   1733 	aprint_normal_dev(sc->sc_dev, "FFILT: %s\n", buf);
   1734 }
   1735 #endif
   1736