Home | History | Annotate | Line # | Download | only in ic
dwc_gmac.c revision 1.24.2.7
      1 /* $NetBSD: dwc_gmac.c,v 1.24.2.7 2015/02/27 07:19:22 snj 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.24.2.7 2015/02/27 07:19:22 snj Exp $");
     45 
     46 /* #define	DWC_GMAC_DEBUG	1 */
     47 
     48 #include "opt_inet.h"
     49 
     50 #include <sys/param.h>
     51 #include <sys/bus.h>
     52 #include <sys/device.h>
     53 #include <sys/intr.h>
     54 #include <sys/systm.h>
     55 #include <sys/sockio.h>
     56 #include <sys/cprng.h>
     57 
     58 #include <net/if.h>
     59 #include <net/if_ether.h>
     60 #include <net/if_media.h>
     61 #include <net/bpf.h>
     62 #ifdef INET
     63 #include <netinet/if_inarp.h>
     64 #endif
     65 
     66 #include <dev/mii/miivar.h>
     67 
     68 #include <dev/ic/dwc_gmac_reg.h>
     69 #include <dev/ic/dwc_gmac_var.h>
     70 
     71 static int dwc_gmac_miibus_read_reg(device_t, int, int);
     72 static void dwc_gmac_miibus_write_reg(device_t, int, int, int);
     73 static void dwc_gmac_miibus_statchg(struct ifnet *);
     74 
     75 static int dwc_gmac_reset(struct dwc_gmac_softc *sc);
     76 static void dwc_gmac_write_hwaddr(struct dwc_gmac_softc *sc,
     77 			 uint8_t enaddr[ETHER_ADDR_LEN]);
     78 static int dwc_gmac_alloc_dma_rings(struct dwc_gmac_softc *sc);
     79 static void dwc_gmac_free_dma_rings(struct dwc_gmac_softc *sc);
     80 static int dwc_gmac_alloc_rx_ring(struct dwc_gmac_softc *sc, struct dwc_gmac_rx_ring *);
     81 static void dwc_gmac_reset_rx_ring(struct dwc_gmac_softc *sc, struct dwc_gmac_rx_ring *);
     82 static void dwc_gmac_free_rx_ring(struct dwc_gmac_softc *sc, struct dwc_gmac_rx_ring *);
     83 static int dwc_gmac_alloc_tx_ring(struct dwc_gmac_softc *sc, struct dwc_gmac_tx_ring *);
     84 static void dwc_gmac_reset_tx_ring(struct dwc_gmac_softc *sc, struct dwc_gmac_tx_ring *);
     85 static void dwc_gmac_free_tx_ring(struct dwc_gmac_softc *sc, struct dwc_gmac_tx_ring *);
     86 static void dwc_gmac_txdesc_sync(struct dwc_gmac_softc *sc, int start, int end, int ops);
     87 static int dwc_gmac_init(struct ifnet *ifp);
     88 static void dwc_gmac_stop(struct ifnet *ifp, int disable);
     89 static void dwc_gmac_start(struct ifnet *ifp);
     90 static int dwc_gmac_queue(struct dwc_gmac_softc *sc, struct mbuf *m0);
     91 static int dwc_gmac_ioctl(struct ifnet *, u_long, void *);
     92 static void dwc_gmac_tx_intr(struct dwc_gmac_softc *sc);
     93 static void dwc_gmac_rx_intr(struct dwc_gmac_softc *sc);
     94 static void dwc_gmac_setmulti(struct dwc_gmac_softc *sc);
     95 static int dwc_gmac_ifflags_cb(struct ethercom *);
     96 static uint32_t	bitrev32(uint32_t x);
     97 
     98 #define	TX_DESC_OFFSET(N)	((AWGE_RX_RING_COUNT+(N)) \
     99 				    *sizeof(struct dwc_gmac_dev_dmadesc))
    100 #define	TX_NEXT(N)		(((N)+1) & (AWGE_TX_RING_COUNT-1))
    101 
    102 #define RX_DESC_OFFSET(N)	((N)*sizeof(struct dwc_gmac_dev_dmadesc))
    103 #define	RX_NEXT(N)		(((N)+1) & (AWGE_RX_RING_COUNT-1))
    104 
    105 
    106 
    107 #define	GMAC_DEF_DMA_INT_MASK	(GMAC_DMA_INT_TIE|GMAC_DMA_INT_RIE| \
    108 				GMAC_DMA_INT_NIE|GMAC_DMA_INT_AIE| \
    109 				GMAC_DMA_INT_FBE|GMAC_DMA_INT_UNE)
    110 
    111 #define	GMAC_DMA_INT_ERRORS	(GMAC_DMA_INT_AIE|GMAC_DMA_INT_ERE| \
    112 				GMAC_DMA_INT_FBE|	\
    113 				GMAC_DMA_INT_RWE|GMAC_DMA_INT_RUE| \
    114 				GMAC_DMA_INT_UNE|GMAC_DMA_INT_OVE| \
    115 				GMAC_DMA_INT_TJE)
    116 
    117 #define	AWIN_DEF_MAC_INTRMASK	\
    118 	(AWIN_GMAC_MAC_INT_TSI | AWIN_GMAC_MAC_INT_ANEG |	\
    119 	AWIN_GMAC_MAC_INT_LINKCHG | AWIN_GMAC_MAC_INT_RGSMII)
    120 
    121 
    122 #ifdef DWC_GMAC_DEBUG
    123 static void dwc_gmac_dump_dma(struct dwc_gmac_softc *sc);
    124 static void dwc_gmac_dump_tx_desc(struct dwc_gmac_softc *sc);
    125 static void dwc_gmac_dump_rx_desc(struct dwc_gmac_softc *sc);
    126 static void dwc_dump_and_abort(struct dwc_gmac_softc *sc, const char *msg);
    127 static void dwc_dump_status(struct dwc_gmac_softc *sc);
    128 static void dwc_gmac_dump_ffilt(struct dwc_gmac_softc *sc, uint32_t ffilt);
    129 #endif
    130 
    131 void
    132 dwc_gmac_attach(struct dwc_gmac_softc *sc, uint32_t mii_clk)
    133 {
    134 	uint8_t enaddr[ETHER_ADDR_LEN];
    135 	uint32_t maclo, machi;
    136 	struct mii_data * const mii = &sc->sc_mii;
    137 	struct ifnet * const ifp = &sc->sc_ec.ec_if;
    138 	prop_dictionary_t dict;
    139 	int s;
    140 
    141 	mutex_init(&sc->sc_mdio_lock, MUTEX_DEFAULT, IPL_NET);
    142 	sc->sc_mii_clk = mii_clk & 7;
    143 
    144 	dict = device_properties(sc->sc_dev);
    145 	prop_data_t ea = dict ? prop_dictionary_get(dict, "mac-address") : NULL;
    146 	if (ea != NULL) {
    147 		/*
    148 		 * If the MAC address is overriden by a device property,
    149 		 * use that.
    150 		 */
    151 		KASSERT(prop_object_type(ea) == PROP_TYPE_DATA);
    152 		KASSERT(prop_data_size(ea) == ETHER_ADDR_LEN);
    153 		memcpy(enaddr, prop_data_data_nocopy(ea), ETHER_ADDR_LEN);
    154 	} else {
    155 		/*
    156 		 * If we did not get an externaly configure address,
    157 		 * try to read one from the current filter setup,
    158 		 * before resetting the chip.
    159 		 */
    160 		maclo = bus_space_read_4(sc->sc_bst, sc->sc_bsh,
    161 		    AWIN_GMAC_MAC_ADDR0LO);
    162 		machi = bus_space_read_4(sc->sc_bst, sc->sc_bsh,
    163 		    AWIN_GMAC_MAC_ADDR0HI);
    164 
    165 		if (maclo == 0xffffffff && (machi & 0xffff) == 0xffff) {
    166 			/* fake MAC address */
    167 			maclo = 0x00f2 | (cprng_strong32() << 16);
    168 			machi = cprng_strong32();
    169 		}
    170 
    171 		enaddr[0] = maclo & 0x0ff;
    172 		enaddr[1] = (maclo >> 8) & 0x0ff;
    173 		enaddr[2] = (maclo >> 16) & 0x0ff;
    174 		enaddr[3] = (maclo >> 24) & 0x0ff;
    175 		enaddr[4] = machi & 0x0ff;
    176 		enaddr[5] = (machi >> 8) & 0x0ff;
    177 	}
    178 
    179 	/*
    180 	 * Init chip and do initial setup
    181 	 */
    182 	if (dwc_gmac_reset(sc) != 0)
    183 		return;	/* not much to cleanup, haven't attached yet */
    184 	dwc_gmac_write_hwaddr(sc, enaddr);
    185 	aprint_normal_dev(sc->sc_dev, "Ethernet address: %s\n",
    186 	    ether_sprintf(enaddr));
    187 
    188 	/*
    189 	 * Allocate Tx and Rx rings
    190 	 */
    191 	if (dwc_gmac_alloc_dma_rings(sc) != 0) {
    192 		aprint_error_dev(sc->sc_dev, "could not allocate DMA rings\n");
    193 		goto fail;
    194 	}
    195 
    196 	if (dwc_gmac_alloc_tx_ring(sc, &sc->sc_txq) != 0) {
    197 		aprint_error_dev(sc->sc_dev, "could not allocate Tx ring\n");
    198 		goto fail;
    199 	}
    200 
    201 	mutex_init(&sc->sc_rxq.r_mtx, MUTEX_DEFAULT, IPL_NET);
    202 	if (dwc_gmac_alloc_rx_ring(sc, &sc->sc_rxq) != 0) {
    203 		aprint_error_dev(sc->sc_dev, "could not allocate Rx ring\n");
    204 		goto fail;
    205 	}
    206 
    207 	/*
    208 	 * Prepare interface data
    209 	 */
    210 	ifp->if_softc = sc;
    211 	strlcpy(ifp->if_xname, device_xname(sc->sc_dev), IFNAMSIZ);
    212 	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
    213 	ifp->if_ioctl = dwc_gmac_ioctl;
    214 	ifp->if_start = dwc_gmac_start;
    215 	ifp->if_init = dwc_gmac_init;
    216 	ifp->if_stop = dwc_gmac_stop;
    217 	IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
    218 	IFQ_SET_READY(&ifp->if_snd);
    219 
    220 	/*
    221 	 * Attach MII subdevices
    222 	 */
    223 	sc->sc_ec.ec_mii = &sc->sc_mii;
    224 	ifmedia_init(&mii->mii_media, 0, ether_mediachange, ether_mediastatus);
    225         mii->mii_ifp = ifp;
    226         mii->mii_readreg = dwc_gmac_miibus_read_reg;
    227         mii->mii_writereg = dwc_gmac_miibus_write_reg;
    228         mii->mii_statchg = dwc_gmac_miibus_statchg;
    229         mii_attach(sc->sc_dev, mii, 0xffffffff, MII_PHY_ANY, MII_OFFSET_ANY,
    230 	    MIIF_DOPAUSE);
    231 
    232         if (LIST_EMPTY(&mii->mii_phys)) {
    233                 aprint_error_dev(sc->sc_dev, "no PHY found!\n");
    234                 ifmedia_add(&mii->mii_media, IFM_ETHER|IFM_MANUAL, 0, NULL);
    235                 ifmedia_set(&mii->mii_media, IFM_ETHER|IFM_MANUAL);
    236         } else {
    237                 ifmedia_set(&mii->mii_media, IFM_ETHER|IFM_AUTO);
    238         }
    239 
    240 	/*
    241 	 * Ready, attach interface
    242 	 */
    243 	if_attach(ifp);
    244 	ether_ifattach(ifp, enaddr);
    245 	ether_set_ifflags_cb(&sc->sc_ec, dwc_gmac_ifflags_cb);
    246 
    247 	/*
    248 	 * Enable interrupts
    249 	 */
    250 	s = splnet();
    251 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_MAC_INTMASK,
    252 	    AWIN_DEF_MAC_INTRMASK);
    253 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_DMA_INTENABLE,
    254 	    GMAC_DEF_DMA_INT_MASK);
    255 	splx(s);
    256 
    257 	return;
    258 
    259 fail:
    260 	dwc_gmac_free_rx_ring(sc, &sc->sc_rxq);
    261 	dwc_gmac_free_tx_ring(sc, &sc->sc_txq);
    262 }
    263 
    264 
    265 
    266 static int
    267 dwc_gmac_reset(struct dwc_gmac_softc *sc)
    268 {
    269 	size_t cnt;
    270 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_DMA_BUSMODE,
    271 	    bus_space_read_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_DMA_BUSMODE) | GMAC_BUSMODE_RESET);
    272 	for (cnt = 0; cnt < 3000; cnt++) {
    273 		if ((bus_space_read_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_DMA_BUSMODE)
    274 		    & GMAC_BUSMODE_RESET) == 0)
    275 			return 0;
    276 		delay(10);
    277 	}
    278 
    279 	aprint_error_dev(sc->sc_dev, "reset timed out\n");
    280 	return EIO;
    281 }
    282 
    283 static void
    284 dwc_gmac_write_hwaddr(struct dwc_gmac_softc *sc,
    285     uint8_t enaddr[ETHER_ADDR_LEN])
    286 {
    287 	uint32_t lo, hi;
    288 
    289 	lo = enaddr[0] | (enaddr[1] << 8) | (enaddr[2] << 16)
    290 	    | (enaddr[3] << 24);
    291 	hi = enaddr[4] | (enaddr[5] << 8);
    292 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_MAC_ADDR0LO, lo);
    293 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_MAC_ADDR0HI, hi);
    294 }
    295 
    296 static int
    297 dwc_gmac_miibus_read_reg(device_t self, int phy, int reg)
    298 {
    299 	struct dwc_gmac_softc * const sc = device_private(self);
    300 	uint16_t mii;
    301 	size_t cnt;
    302 	int rv = 0;
    303 
    304 	mii = __SHIFTIN(phy,GMAC_MII_PHY_MASK)
    305 	    | __SHIFTIN(reg,GMAC_MII_REG_MASK)
    306 	    | __SHIFTIN(sc->sc_mii_clk,GMAC_MII_CLKMASK)
    307 	    | GMAC_MII_BUSY;
    308 
    309 	mutex_enter(&sc->sc_mdio_lock);
    310 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_MAC_MIIADDR, mii);
    311 
    312 	for (cnt = 0; cnt < 1000; cnt++) {
    313 		if (!(bus_space_read_4(sc->sc_bst, sc->sc_bsh,
    314 		    AWIN_GMAC_MAC_MIIADDR) & GMAC_MII_BUSY)) {
    315 			rv = bus_space_read_4(sc->sc_bst, sc->sc_bsh,
    316 			    AWIN_GMAC_MAC_MIIDATA);
    317 			break;
    318 		}
    319 		delay(10);
    320 	}
    321 
    322 	mutex_exit(&sc->sc_mdio_lock);
    323 
    324 	return rv;
    325 }
    326 
    327 static void
    328 dwc_gmac_miibus_write_reg(device_t self, int phy, int reg, int val)
    329 {
    330 	struct dwc_gmac_softc * const sc = device_private(self);
    331 	uint16_t mii;
    332 	size_t cnt;
    333 
    334 	mii = __SHIFTIN(phy,GMAC_MII_PHY_MASK)
    335 	    | __SHIFTIN(reg,GMAC_MII_REG_MASK)
    336 	    | __SHIFTIN(sc->sc_mii_clk,GMAC_MII_CLKMASK)
    337 	    | GMAC_MII_BUSY | GMAC_MII_WRITE;
    338 
    339 	mutex_enter(&sc->sc_mdio_lock);
    340 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_MAC_MIIDATA, val);
    341 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_MAC_MIIADDR, mii);
    342 
    343 	for (cnt = 0; cnt < 1000; cnt++) {
    344 		if (!(bus_space_read_4(sc->sc_bst, sc->sc_bsh,
    345 		    AWIN_GMAC_MAC_MIIADDR) & GMAC_MII_BUSY))
    346 			break;
    347 		delay(10);
    348 	}
    349 
    350 	mutex_exit(&sc->sc_mdio_lock);
    351 }
    352 
    353 static int
    354 dwc_gmac_alloc_rx_ring(struct dwc_gmac_softc *sc,
    355 	struct dwc_gmac_rx_ring *ring)
    356 {
    357 	struct dwc_gmac_rx_data *data;
    358 	bus_addr_t physaddr;
    359 	const size_t descsize = AWGE_RX_RING_COUNT * sizeof(*ring->r_desc);
    360 	int error, i, next;
    361 
    362 	ring->r_cur = ring->r_next = 0;
    363 	memset(ring->r_desc, 0, descsize);
    364 
    365 	/*
    366 	 * Pre-allocate Rx buffers and populate Rx ring.
    367 	 */
    368 	for (i = 0; i < AWGE_RX_RING_COUNT; i++) {
    369 		struct dwc_gmac_dev_dmadesc *desc;
    370 
    371 		data = &sc->sc_rxq.r_data[i];
    372 
    373 		MGETHDR(data->rd_m, M_DONTWAIT, MT_DATA);
    374 		if (data->rd_m == NULL) {
    375 			aprint_error_dev(sc->sc_dev,
    376 			    "could not allocate rx mbuf #%d\n", i);
    377 			error = ENOMEM;
    378 			goto fail;
    379 		}
    380 		error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1,
    381 		    MCLBYTES, 0, BUS_DMA_NOWAIT, &data->rd_map);
    382 		if (error != 0) {
    383 			aprint_error_dev(sc->sc_dev,
    384 			    "could not create DMA map\n");
    385 			data->rd_map = NULL;
    386 			goto fail;
    387 		}
    388 		MCLGET(data->rd_m, M_DONTWAIT);
    389 		if (!(data->rd_m->m_flags & M_EXT)) {
    390 			aprint_error_dev(sc->sc_dev,
    391 			    "could not allocate mbuf cluster #%d\n", i);
    392 			error = ENOMEM;
    393 			goto fail;
    394 		}
    395 
    396 		error = bus_dmamap_load(sc->sc_dmat, data->rd_map,
    397 		    mtod(data->rd_m, void *), MCLBYTES, NULL,
    398 		    BUS_DMA_READ | BUS_DMA_NOWAIT);
    399 		if (error != 0) {
    400 			aprint_error_dev(sc->sc_dev,
    401 			    "could not load rx buf DMA map #%d", i);
    402 			goto fail;
    403 		}
    404 		physaddr = data->rd_map->dm_segs[0].ds_addr;
    405 
    406 		desc = &sc->sc_rxq.r_desc[i];
    407 		desc->ddesc_data = htole32(physaddr);
    408 		next = RX_NEXT(i);
    409 		desc->ddesc_next = htole32(ring->r_physaddr
    410 		    + next * sizeof(*desc));
    411 		desc->ddesc_cntl = htole32(
    412 		    __SHIFTIN(AWGE_MAX_PACKET,DDESC_CNTL_SIZE1MASK) |
    413 		    DDESC_CNTL_RXCHAIN);
    414 		desc->ddesc_status = htole32(DDESC_STATUS_OWNEDBYDEV);
    415 	}
    416 
    417 	bus_dmamap_sync(sc->sc_dmat, sc->sc_dma_ring_map, 0,
    418 	    AWGE_RX_RING_COUNT*sizeof(struct dwc_gmac_dev_dmadesc),
    419 	    BUS_DMASYNC_PREWRITE|BUS_DMASYNC_PREREAD);
    420 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_DMA_RX_ADDR,
    421 	    ring->r_physaddr);
    422 
    423 	return 0;
    424 
    425 fail:
    426 	dwc_gmac_free_rx_ring(sc, ring);
    427 	return error;
    428 }
    429 
    430 static void
    431 dwc_gmac_reset_rx_ring(struct dwc_gmac_softc *sc,
    432 	struct dwc_gmac_rx_ring *ring)
    433 {
    434 	struct dwc_gmac_dev_dmadesc *desc;
    435 	int i;
    436 
    437 	for (i = 0; i < AWGE_RX_RING_COUNT; i++) {
    438 		desc = &sc->sc_rxq.r_desc[i];
    439 		desc->ddesc_cntl = htole32(
    440 		    __SHIFTIN(AWGE_MAX_PACKET,DDESC_CNTL_SIZE1MASK) |
    441 		    DDESC_CNTL_RXCHAIN);
    442 		desc->ddesc_status = htole32(DDESC_STATUS_OWNEDBYDEV);
    443 	}
    444 
    445 	bus_dmamap_sync(sc->sc_dmat, sc->sc_dma_ring_map, 0,
    446 	    AWGE_RX_RING_COUNT*sizeof(struct dwc_gmac_dev_dmadesc),
    447 	    BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
    448 
    449 	ring->r_cur = ring->r_next = 0;
    450 	/* reset DMA address to start of ring */
    451 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_DMA_RX_ADDR,
    452 	    sc->sc_rxq.r_physaddr);
    453 }
    454 
    455 static int
    456 dwc_gmac_alloc_dma_rings(struct dwc_gmac_softc *sc)
    457 {
    458 	const size_t descsize = AWGE_TOTAL_RING_COUNT *
    459 		sizeof(struct dwc_gmac_dev_dmadesc);
    460 	int error, nsegs;
    461 	void *rings;
    462 
    463 	error = bus_dmamap_create(sc->sc_dmat, descsize, 1, descsize, 0,
    464 	    BUS_DMA_NOWAIT, &sc->sc_dma_ring_map);
    465 	if (error != 0) {
    466 		aprint_error_dev(sc->sc_dev,
    467 		    "could not create desc DMA map\n");
    468 		sc->sc_dma_ring_map = NULL;
    469 		goto fail;
    470 	}
    471 
    472 	error = bus_dmamem_alloc(sc->sc_dmat, descsize, PAGE_SIZE, 0,
    473 	    &sc->sc_dma_ring_seg, 1, &nsegs, BUS_DMA_NOWAIT|BUS_DMA_COHERENT);
    474 	if (error != 0) {
    475 		aprint_error_dev(sc->sc_dev,
    476 		    "could not map DMA memory\n");
    477 		goto fail;
    478 	}
    479 
    480 	error = bus_dmamem_map(sc->sc_dmat, &sc->sc_dma_ring_seg, nsegs,
    481 	    descsize, &rings, BUS_DMA_NOWAIT|BUS_DMA_COHERENT);
    482 	if (error != 0) {
    483 		aprint_error_dev(sc->sc_dev,
    484 		    "could not allocate DMA memory\n");
    485 		goto fail;
    486 	}
    487 
    488 	error = bus_dmamap_load(sc->sc_dmat, sc->sc_dma_ring_map, rings,
    489 	    descsize, NULL, BUS_DMA_NOWAIT|BUS_DMA_COHERENT);
    490 	if (error != 0) {
    491 		aprint_error_dev(sc->sc_dev,
    492 		    "could not load desc DMA map\n");
    493 		goto fail;
    494 	}
    495 
    496 	/* give first AWGE_RX_RING_COUNT to the RX side */
    497 	sc->sc_rxq.r_desc = rings;
    498 	sc->sc_rxq.r_physaddr = sc->sc_dma_ring_map->dm_segs[0].ds_addr;
    499 
    500 	/* and next rings to the TX side */
    501 	sc->sc_txq.t_desc = sc->sc_rxq.r_desc + AWGE_RX_RING_COUNT;
    502 	sc->sc_txq.t_physaddr = sc->sc_rxq.r_physaddr +
    503 	    AWGE_RX_RING_COUNT*sizeof(struct dwc_gmac_dev_dmadesc);
    504 
    505 	return 0;
    506 
    507 fail:
    508 	dwc_gmac_free_dma_rings(sc);
    509 	return error;
    510 }
    511 
    512 static void
    513 dwc_gmac_free_dma_rings(struct dwc_gmac_softc *sc)
    514 {
    515 	bus_dmamap_sync(sc->sc_dmat, sc->sc_dma_ring_map, 0,
    516 	    sc->sc_dma_ring_map->dm_mapsize, BUS_DMASYNC_POSTWRITE);
    517 	bus_dmamap_unload(sc->sc_dmat, sc->sc_dma_ring_map);
    518 	bus_dmamem_unmap(sc->sc_dmat, sc->sc_rxq.r_desc,
    519 	    AWGE_TOTAL_RING_COUNT * sizeof(struct dwc_gmac_dev_dmadesc));
    520 	bus_dmamem_free(sc->sc_dmat, &sc->sc_dma_ring_seg, 1);
    521 }
    522 
    523 static void
    524 dwc_gmac_free_rx_ring(struct dwc_gmac_softc *sc, struct dwc_gmac_rx_ring *ring)
    525 {
    526 	struct dwc_gmac_rx_data *data;
    527 	int i;
    528 
    529 	if (ring->r_desc == NULL)
    530 		return;
    531 
    532 
    533 	for (i = 0; i < AWGE_RX_RING_COUNT; i++) {
    534 		data = &ring->r_data[i];
    535 
    536 		if (data->rd_map != NULL) {
    537 			bus_dmamap_sync(sc->sc_dmat, data->rd_map, 0,
    538 			    AWGE_RX_RING_COUNT
    539 				*sizeof(struct dwc_gmac_dev_dmadesc),
    540 			    BUS_DMASYNC_POSTREAD);
    541 			bus_dmamap_unload(sc->sc_dmat, data->rd_map);
    542 			bus_dmamap_destroy(sc->sc_dmat, data->rd_map);
    543 		}
    544 		if (data->rd_m != NULL)
    545 			m_freem(data->rd_m);
    546 	}
    547 }
    548 
    549 static int
    550 dwc_gmac_alloc_tx_ring(struct dwc_gmac_softc *sc,
    551 	struct dwc_gmac_tx_ring *ring)
    552 {
    553 	int i, error = 0;
    554 
    555 	ring->t_queued = 0;
    556 	ring->t_cur = ring->t_next = 0;
    557 
    558 	memset(ring->t_desc, 0, AWGE_TX_RING_COUNT*sizeof(*ring->t_desc));
    559 	bus_dmamap_sync(sc->sc_dmat, sc->sc_dma_ring_map,
    560 	    TX_DESC_OFFSET(0),
    561 	    AWGE_TX_RING_COUNT*sizeof(struct dwc_gmac_dev_dmadesc),
    562 	    BUS_DMASYNC_POSTWRITE);
    563 
    564 	for (i = 0; i < AWGE_TX_RING_COUNT; i++) {
    565 		error = bus_dmamap_create(sc->sc_dmat, MCLBYTES,
    566 		    AWGE_TX_RING_COUNT, MCLBYTES, 0,
    567 		    BUS_DMA_NOWAIT|BUS_DMA_COHERENT,
    568 		    &ring->t_data[i].td_map);
    569 		if (error != 0) {
    570 			aprint_error_dev(sc->sc_dev,
    571 			    "could not create TX DMA map #%d\n", i);
    572 			ring->t_data[i].td_map = NULL;
    573 			goto fail;
    574 		}
    575 		ring->t_desc[i].ddesc_next = htole32(
    576 		    ring->t_physaddr + sizeof(struct dwc_gmac_dev_dmadesc)
    577 		    *TX_NEXT(i));
    578 	}
    579 
    580 	return 0;
    581 
    582 fail:
    583 	dwc_gmac_free_tx_ring(sc, ring);
    584 	return error;
    585 }
    586 
    587 static void
    588 dwc_gmac_txdesc_sync(struct dwc_gmac_softc *sc, int start, int end, int ops)
    589 {
    590 	/* 'end' is pointing one descriptor beyound the last we want to sync */
    591 	if (end > start) {
    592 		bus_dmamap_sync(sc->sc_dmat, sc->sc_dma_ring_map,
    593 		    TX_DESC_OFFSET(start),
    594 		    TX_DESC_OFFSET(end)-TX_DESC_OFFSET(start),
    595 		    ops);
    596 		return;
    597 	}
    598 	/* sync from 'start' to end of ring */
    599 	bus_dmamap_sync(sc->sc_dmat, sc->sc_dma_ring_map,
    600 	    TX_DESC_OFFSET(start),
    601 	    TX_DESC_OFFSET(AWGE_TX_RING_COUNT)-TX_DESC_OFFSET(start),
    602 	    ops);
    603 	/* sync from start of ring to 'end' */
    604 	bus_dmamap_sync(sc->sc_dmat, sc->sc_dma_ring_map,
    605 	    TX_DESC_OFFSET(0),
    606 	    TX_DESC_OFFSET(end)-TX_DESC_OFFSET(0),
    607 	    ops);
    608 }
    609 
    610 static void
    611 dwc_gmac_reset_tx_ring(struct dwc_gmac_softc *sc,
    612 	struct dwc_gmac_tx_ring *ring)
    613 {
    614 	int i;
    615 
    616 	for (i = 0; i < AWGE_TX_RING_COUNT; i++) {
    617 		struct dwc_gmac_tx_data *data = &ring->t_data[i];
    618 
    619 		if (data->td_m != NULL) {
    620 			bus_dmamap_sync(sc->sc_dmat, data->td_active,
    621 			    0, data->td_active->dm_mapsize,
    622 			    BUS_DMASYNC_POSTWRITE);
    623 			bus_dmamap_unload(sc->sc_dmat, data->td_active);
    624 			m_freem(data->td_m);
    625 			data->td_m = NULL;
    626 		}
    627 	}
    628 
    629 	bus_dmamap_sync(sc->sc_dmat, sc->sc_dma_ring_map,
    630 	    TX_DESC_OFFSET(0),
    631 	    AWGE_TX_RING_COUNT*sizeof(struct dwc_gmac_dev_dmadesc),
    632 	    BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
    633 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_DMA_TX_ADDR,
    634 	    sc->sc_txq.t_physaddr);
    635 
    636 	ring->t_queued = 0;
    637 	ring->t_cur = ring->t_next = 0;
    638 }
    639 
    640 static void
    641 dwc_gmac_free_tx_ring(struct dwc_gmac_softc *sc,
    642 	struct dwc_gmac_tx_ring *ring)
    643 {
    644 	int i;
    645 
    646 	/* unload the maps */
    647 	for (i = 0; i < AWGE_TX_RING_COUNT; i++) {
    648 		struct dwc_gmac_tx_data *data = &ring->t_data[i];
    649 
    650 		if (data->td_m != NULL) {
    651 			bus_dmamap_sync(sc->sc_dmat, data->td_active,
    652 			    0, data->td_map->dm_mapsize,
    653 			    BUS_DMASYNC_POSTWRITE);
    654 			bus_dmamap_unload(sc->sc_dmat, data->td_active);
    655 			m_freem(data->td_m);
    656 			data->td_m = NULL;
    657 		}
    658 	}
    659 
    660 	/* and actually free them */
    661 	for (i = 0; i < AWGE_TX_RING_COUNT; i++) {
    662 		struct dwc_gmac_tx_data *data = &ring->t_data[i];
    663 
    664 		bus_dmamap_destroy(sc->sc_dmat, data->td_map);
    665 	}
    666 }
    667 
    668 static void
    669 dwc_gmac_miibus_statchg(struct ifnet *ifp)
    670 {
    671 	struct dwc_gmac_softc * const sc = ifp->if_softc;
    672 	struct mii_data * const mii = &sc->sc_mii;
    673 	uint32_t conf, flow;
    674 
    675 	/*
    676 	 * Set MII or GMII interface based on the speed
    677 	 * negotiated by the PHY.
    678 	 */
    679 	conf = bus_space_read_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_MAC_CONF);
    680 	conf &= ~(AWIN_GMAC_MAC_CONF_FES100|AWIN_GMAC_MAC_CONF_MIISEL
    681 	    |AWIN_GMAC_MAC_CONF_FULLDPLX);
    682 	conf |= AWIN_GMAC_MAC_CONF_FRAMEBURST
    683 	    | AWIN_GMAC_MAC_CONF_DISABLERXOWN
    684 	    | AWIN_GMAC_MAC_CONF_DISABLEJABBER
    685 	    | AWIN_GMAC_MAC_CONF_ACS
    686 	    | AWIN_GMAC_MAC_CONF_RXENABLE
    687 	    | AWIN_GMAC_MAC_CONF_TXENABLE;
    688 	switch (IFM_SUBTYPE(mii->mii_media_active)) {
    689 	case IFM_10_T:
    690 		conf |= AWIN_GMAC_MAC_CONF_MIISEL;
    691 		break;
    692 	case IFM_100_TX:
    693 		conf |= AWIN_GMAC_MAC_CONF_FES100 |
    694 			AWIN_GMAC_MAC_CONF_MIISEL;
    695 		break;
    696 	case IFM_1000_T:
    697 		break;
    698 	}
    699 
    700 	flow = 0;
    701 	if (IFM_OPTIONS(mii->mii_media_active) & IFM_FDX) {
    702 		conf |= AWIN_GMAC_MAC_CONF_FULLDPLX;
    703 		flow |= __SHIFTIN(0x200, AWIN_GMAC_MAC_FLOWCTRL_PAUSE);
    704 	}
    705 	if (mii->mii_media_active & IFM_ETH_TXPAUSE) {
    706 		flow |= AWIN_GMAC_MAC_FLOWCTRL_TFE;
    707 	}
    708 	if (mii->mii_media_active & IFM_ETH_RXPAUSE) {
    709 		flow |= AWIN_GMAC_MAC_FLOWCTRL_RFE;
    710 	}
    711 	bus_space_write_4(sc->sc_bst, sc->sc_bsh,
    712 	    AWIN_GMAC_MAC_FLOWCTRL, flow);
    713 
    714 #ifdef DWC_GMAC_DEBUG
    715 	aprint_normal_dev(sc->sc_dev,
    716 	    "setting MAC conf register: %08x\n", conf);
    717 #endif
    718 
    719 	bus_space_write_4(sc->sc_bst, sc->sc_bsh,
    720 	    AWIN_GMAC_MAC_CONF, conf);
    721 }
    722 
    723 static int
    724 dwc_gmac_init(struct ifnet *ifp)
    725 {
    726 	struct dwc_gmac_softc *sc = ifp->if_softc;
    727 	uint32_t ffilt;
    728 
    729 	if (ifp->if_flags & IFF_RUNNING)
    730 		return 0;
    731 
    732 	dwc_gmac_stop(ifp, 0);
    733 
    734 	/*
    735 	 * Configure DMA burst/transfer mode and RX/TX priorities.
    736 	 * XXX - the GMAC_BUSMODE_PRIORXTX bits are undocumented.
    737 	 */
    738 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_DMA_BUSMODE,
    739 	    GMAC_BUSMODE_FIXEDBURST | GMAC_BUSMODE_4PBL |
    740 	    __SHIFTIN(2, GMAC_BUSMODE_RPBL) |
    741 	    __SHIFTIN(2, GMAC_BUSMODE_PBL));
    742 
    743 	/*
    744 	 * Set up address filter
    745 	 */
    746 	ffilt = bus_space_read_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_MAC_FFILT);
    747 	if (ifp->if_flags & IFF_PROMISC) {
    748 		ffilt |= AWIN_GMAC_MAC_FFILT_PR;
    749 	} else {
    750 		ffilt &= ~AWIN_GMAC_MAC_FFILT_PR;
    751 	}
    752 	if (ifp->if_flags & IFF_BROADCAST) {
    753 		ffilt &= ~AWIN_GMAC_MAC_FFILT_DBF;
    754 	} else {
    755 		ffilt |= AWIN_GMAC_MAC_FFILT_DBF;
    756 	}
    757 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_MAC_FFILT, ffilt);
    758 
    759 	/*
    760 	 * Set up multicast filter
    761 	 */
    762 	dwc_gmac_setmulti(sc);
    763 
    764 	/*
    765 	 * Set up dma pointer for RX and TX ring
    766 	 */
    767 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_DMA_RX_ADDR,
    768 	    sc->sc_rxq.r_physaddr);
    769 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_DMA_TX_ADDR,
    770 	    sc->sc_txq.t_physaddr);
    771 
    772 	/*
    773 	 * Start RX/TX part
    774 	 */
    775 	bus_space_write_4(sc->sc_bst, sc->sc_bsh,
    776 	    AWIN_GMAC_DMA_OPMODE, GMAC_DMA_OP_RXSTART | GMAC_DMA_OP_TXSTART |
    777 	    GMAC_DMA_OP_RXSTOREFORWARD | GMAC_DMA_OP_TXSTOREFORWARD);
    778 
    779 	ifp->if_flags |= IFF_RUNNING;
    780 	ifp->if_flags &= ~IFF_OACTIVE;
    781 
    782 	return 0;
    783 }
    784 
    785 static void
    786 dwc_gmac_start(struct ifnet *ifp)
    787 {
    788 	struct dwc_gmac_softc *sc = ifp->if_softc;
    789 	int old = sc->sc_txq.t_queued;
    790 	int start = sc->sc_txq.t_cur;
    791 	struct mbuf *m0;
    792 
    793 	if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
    794 		return;
    795 
    796 	for (;;) {
    797 		IFQ_POLL(&ifp->if_snd, m0);
    798 		if (m0 == NULL)
    799 			break;
    800 		if (dwc_gmac_queue(sc, m0) != 0) {
    801 			ifp->if_flags |= IFF_OACTIVE;
    802 			break;
    803 		}
    804 		IFQ_DEQUEUE(&ifp->if_snd, m0);
    805 		bpf_mtap(ifp, m0);
    806 		if (sc->sc_txq.t_queued == AWGE_TX_RING_COUNT) {
    807 			ifp->if_flags |= IFF_OACTIVE;
    808 			break;
    809 		}
    810 	}
    811 
    812 	if (sc->sc_txq.t_queued != old) {
    813 		/* packets have been queued, kick it off */
    814 		dwc_gmac_txdesc_sync(sc, start, sc->sc_txq.t_cur,
    815 		    BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
    816 
    817 		bus_space_write_4(sc->sc_bst, sc->sc_bsh,
    818 		    AWIN_GMAC_DMA_TXPOLL, ~0U);
    819 #ifdef DWC_GMAC_DEBUG
    820 		dwc_dump_status(sc);
    821 #endif
    822 	}
    823 }
    824 
    825 static void
    826 dwc_gmac_stop(struct ifnet *ifp, int disable)
    827 {
    828 	struct dwc_gmac_softc *sc = ifp->if_softc;
    829 
    830 	bus_space_write_4(sc->sc_bst, sc->sc_bsh,
    831 	    AWIN_GMAC_DMA_OPMODE,
    832 	    bus_space_read_4(sc->sc_bst, sc->sc_bsh,
    833 	        AWIN_GMAC_DMA_OPMODE)
    834 		& ~(GMAC_DMA_OP_TXSTART|GMAC_DMA_OP_RXSTART));
    835 	bus_space_write_4(sc->sc_bst, sc->sc_bsh,
    836 	    AWIN_GMAC_DMA_OPMODE,
    837 	    bus_space_read_4(sc->sc_bst, sc->sc_bsh,
    838 	        AWIN_GMAC_DMA_OPMODE) | GMAC_DMA_OP_FLUSHTX);
    839 
    840 	mii_down(&sc->sc_mii);
    841 	dwc_gmac_reset_tx_ring(sc, &sc->sc_txq);
    842 	dwc_gmac_reset_rx_ring(sc, &sc->sc_rxq);
    843 }
    844 
    845 /*
    846  * Add m0 to the TX ring
    847  */
    848 static int
    849 dwc_gmac_queue(struct dwc_gmac_softc *sc, struct mbuf *m0)
    850 {
    851 	struct dwc_gmac_dev_dmadesc *desc = NULL;
    852 	struct dwc_gmac_tx_data *data = NULL;
    853 	bus_dmamap_t map;
    854 	uint32_t flags, len, status;
    855 	int error, i, first;
    856 
    857 #ifdef DWC_GMAC_DEBUG
    858 	aprint_normal_dev(sc->sc_dev,
    859 	    "dwc_gmac_queue: adding mbuf chain %p\n", m0);
    860 #endif
    861 
    862 	first = sc->sc_txq.t_cur;
    863 	map = sc->sc_txq.t_data[first].td_map;
    864 
    865 	error = bus_dmamap_load_mbuf(sc->sc_dmat, map, m0,
    866 	    BUS_DMA_WRITE|BUS_DMA_NOWAIT);
    867 	if (error != 0) {
    868 		aprint_error_dev(sc->sc_dev, "could not map mbuf "
    869 		    "(len: %d, error %d)\n", m0->m_pkthdr.len, error);
    870 		return error;
    871 	}
    872 
    873 	if (sc->sc_txq.t_queued + map->dm_nsegs > AWGE_TX_RING_COUNT) {
    874 		bus_dmamap_unload(sc->sc_dmat, map);
    875 		return ENOBUFS;
    876 	}
    877 
    878 	flags = DDESC_CNTL_TXFIRST|DDESC_CNTL_TXCHAIN;
    879 	status = 0;
    880 	for (i = 0; i < map->dm_nsegs; i++) {
    881 		data = &sc->sc_txq.t_data[sc->sc_txq.t_cur];
    882 		desc = &sc->sc_txq.t_desc[sc->sc_txq.t_cur];
    883 
    884 		desc->ddesc_data = htole32(map->dm_segs[i].ds_addr);
    885 		len = __SHIFTIN(map->dm_segs[i].ds_len, DDESC_CNTL_SIZE1MASK);
    886 
    887 #ifdef DWC_GMAC_DEBUG
    888 		aprint_normal_dev(sc->sc_dev, "enqueing desc #%d data %08lx "
    889 		    "len %lu (flags: %08x, len: %08x)\n", sc->sc_txq.t_cur,
    890 		    (unsigned long)map->dm_segs[i].ds_addr,
    891 		    (unsigned long)map->dm_segs[i].ds_len,
    892 		    flags, len);
    893 #endif
    894 
    895 		desc->ddesc_cntl = htole32(len|flags);
    896 		flags &= ~DDESC_CNTL_TXFIRST;
    897 
    898 		/*
    899 		 * Defer passing ownership of the first descriptor
    900 		 * until we are done.
    901 		 */
    902 		desc->ddesc_status = htole32(status);
    903 		status |= DDESC_STATUS_OWNEDBYDEV;
    904 
    905 		sc->sc_txq.t_queued++;
    906 		sc->sc_txq.t_cur = TX_NEXT(sc->sc_txq.t_cur);
    907 	}
    908 
    909 	desc->ddesc_cntl |= htole32(DDESC_CNTL_TXLAST|DDESC_CNTL_TXINT);
    910 
    911 	data->td_m = m0;
    912 	data->td_active = map;
    913 
    914 	bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize,
    915 	    BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
    916 
    917 	/* Pass first to device */
    918 	sc->sc_txq.t_desc[first].ddesc_status =
    919 	    htole32(DDESC_STATUS_OWNEDBYDEV);
    920 
    921 	return 0;
    922 }
    923 
    924 /*
    925  * If the interface is up and running, only modify the receive
    926  * filter when setting promiscuous or debug mode.  Otherwise fall
    927  * through to ether_ioctl, which will reset the chip.
    928  */
    929 static int
    930 dwc_gmac_ifflags_cb(struct ethercom *ec)
    931 {
    932 	struct ifnet *ifp = &ec->ec_if;
    933 	struct dwc_gmac_softc *sc = ifp->if_softc;
    934 	int change = ifp->if_flags ^ sc->sc_if_flags;
    935 
    936 	if ((change & ~(IFF_CANTCHANGE|IFF_DEBUG)) != 0)
    937 		return ENETRESET;
    938 	if ((change & IFF_PROMISC) != 0)
    939 		dwc_gmac_setmulti(sc);
    940 	return 0;
    941 }
    942 
    943 static int
    944 dwc_gmac_ioctl(struct ifnet *ifp, u_long cmd, void *data)
    945 {
    946 	struct dwc_gmac_softc *sc = ifp->if_softc;
    947 	int s, error = 0;
    948 
    949 	s = splnet();
    950 
    951 	if ((error = ether_ioctl(ifp, cmd, data)) == ENETRESET) {
    952 		error = 0;
    953 		if (cmd != SIOCADDMULTI && cmd != SIOCDELMULTI)
    954 			;
    955 		else if (ifp->if_flags & IFF_RUNNING) {
    956 			/*
    957 			 * Multicast list has changed; set the hardware filter
    958 			 * accordingly.
    959 			 */
    960 			dwc_gmac_setmulti(sc);
    961 		}
    962 	}
    963 
    964 	/* Try to get things going again */
    965 	if (ifp->if_flags & IFF_UP)
    966 		dwc_gmac_start(ifp);
    967 	sc->sc_if_flags = sc->sc_ec.ec_if.if_flags;
    968 	splx(s);
    969 	return error;
    970 }
    971 
    972 static void
    973 dwc_gmac_tx_intr(struct dwc_gmac_softc *sc)
    974 {
    975 	struct ifnet *ifp = &sc->sc_ec.ec_if;
    976 	struct dwc_gmac_tx_data *data;
    977 	struct dwc_gmac_dev_dmadesc *desc;
    978 	uint32_t status;
    979 	int i, nsegs;
    980 
    981 	for (i = sc->sc_txq.t_next; sc->sc_txq.t_queued > 0; i = TX_NEXT(i)) {
    982 #ifdef DWC_GMAC_DEBUG
    983 		aprint_normal_dev(sc->sc_dev,
    984 		    "dwc_gmac_tx_intr: checking desc #%d (t_queued: %d)\n",
    985 		    i, sc->sc_txq.t_queued);
    986 #endif
    987 
    988 		/*
    989 		 * i+1 does not need to be a valid descriptor,
    990 		 * this is just a special notion to just sync
    991 		 * a single tx descriptor (i)
    992 		 */
    993 		dwc_gmac_txdesc_sync(sc, i, i+1,
    994 		    BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
    995 
    996 		desc = &sc->sc_txq.t_desc[i];
    997 		status = le32toh(desc->ddesc_status);
    998 		if (status & DDESC_STATUS_OWNEDBYDEV)
    999 			break;
   1000 
   1001 		data = &sc->sc_txq.t_data[i];
   1002 		if (data->td_m == NULL)
   1003 			continue;
   1004 
   1005 		ifp->if_opackets++;
   1006 		nsegs = data->td_active->dm_nsegs;
   1007 		bus_dmamap_sync(sc->sc_dmat, data->td_active, 0,
   1008 		    data->td_active->dm_mapsize, BUS_DMASYNC_POSTWRITE);
   1009 		bus_dmamap_unload(sc->sc_dmat, data->td_active);
   1010 
   1011 #ifdef DWC_GMAC_DEBUG
   1012 		aprint_normal_dev(sc->sc_dev,
   1013 		    "dwc_gmac_tx_intr: done with packet at desc #%d, "
   1014 		    "freeing mbuf %p\n", i, data->td_m);
   1015 #endif
   1016 
   1017 		m_freem(data->td_m);
   1018 		data->td_m = NULL;
   1019 
   1020 		sc->sc_txq.t_queued -= nsegs;
   1021 	}
   1022 
   1023 	sc->sc_txq.t_next = i;
   1024 
   1025 	if (sc->sc_txq.t_queued < AWGE_TX_RING_COUNT) {
   1026 		ifp->if_flags &= ~IFF_OACTIVE;
   1027 	}
   1028 }
   1029 
   1030 static void
   1031 dwc_gmac_rx_intr(struct dwc_gmac_softc *sc)
   1032 {
   1033 	struct ifnet *ifp = &sc->sc_ec.ec_if;
   1034 	struct dwc_gmac_dev_dmadesc *desc;
   1035 	struct dwc_gmac_rx_data *data;
   1036 	bus_addr_t physaddr;
   1037 	uint32_t status;
   1038 	struct mbuf *m, *mnew;
   1039 	int i, len, error;
   1040 
   1041 	for (i = sc->sc_rxq.r_cur; ; i = RX_NEXT(i)) {
   1042 		bus_dmamap_sync(sc->sc_dmat, sc->sc_dma_ring_map,
   1043 		    RX_DESC_OFFSET(i), sizeof(*desc),
   1044 		    BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
   1045 		desc = &sc->sc_rxq.r_desc[i];
   1046 		data = &sc->sc_rxq.r_data[i];
   1047 
   1048 		status = le32toh(desc->ddesc_status);
   1049 		if (status & DDESC_STATUS_OWNEDBYDEV)
   1050 			break;
   1051 
   1052 		if (status & (DDESC_STATUS_RXERROR|DDESC_STATUS_RXTRUNCATED)) {
   1053 #ifdef DWC_GMAC_DEBUG
   1054 			aprint_normal_dev(sc->sc_dev,
   1055 			    "RX error: descriptor status %08x, skipping\n",
   1056 			    status);
   1057 #endif
   1058 			ifp->if_ierrors++;
   1059 			goto skip;
   1060 		}
   1061 
   1062 		len = __SHIFTOUT(status, DDESC_STATUS_FRMLENMSK);
   1063 
   1064 #ifdef DWC_GMAC_DEBUG
   1065 		aprint_normal_dev(sc->sc_dev,
   1066 		    "rx int: device is done with descriptor #%d, len: %d\n",
   1067 		    i, len);
   1068 #endif
   1069 
   1070 		/*
   1071 		 * Try to get a new mbuf before passing this one
   1072 		 * up, if that fails, drop the packet and reuse
   1073 		 * the existing one.
   1074 		 */
   1075 		MGETHDR(mnew, M_DONTWAIT, MT_DATA);
   1076 		if (mnew == NULL) {
   1077 			ifp->if_ierrors++;
   1078 			goto skip;
   1079 		}
   1080 		MCLGET(mnew, M_DONTWAIT);
   1081 		if ((mnew->m_flags & M_EXT) == 0) {
   1082 			m_freem(mnew);
   1083 			ifp->if_ierrors++;
   1084 			goto skip;
   1085 		}
   1086 
   1087 		/* unload old DMA map */
   1088 		bus_dmamap_sync(sc->sc_dmat, data->rd_map, 0,
   1089 		    data->rd_map->dm_mapsize, BUS_DMASYNC_POSTREAD);
   1090 		bus_dmamap_unload(sc->sc_dmat, data->rd_map);
   1091 
   1092 		/* and reload with new mbuf */
   1093 		error = bus_dmamap_load(sc->sc_dmat, data->rd_map,
   1094 		    mtod(mnew, void*), MCLBYTES, NULL,
   1095 		    BUS_DMA_READ | BUS_DMA_NOWAIT);
   1096 		if (error != 0) {
   1097 			m_freem(mnew);
   1098 			/* try to reload old mbuf */
   1099 			error = bus_dmamap_load(sc->sc_dmat, data->rd_map,
   1100 			    mtod(data->rd_m, void*), MCLBYTES, NULL,
   1101 			    BUS_DMA_READ | BUS_DMA_NOWAIT);
   1102 			if (error != 0) {
   1103 				panic("%s: could not load old rx mbuf",
   1104 				    device_xname(sc->sc_dev));
   1105 			}
   1106 			ifp->if_ierrors++;
   1107 			goto skip;
   1108 		}
   1109 		physaddr = data->rd_map->dm_segs[0].ds_addr;
   1110 
   1111 		/*
   1112 		 * New mbuf loaded, update RX ring and continue
   1113 		 */
   1114 		m = data->rd_m;
   1115 		data->rd_m = mnew;
   1116 		desc->ddesc_data = htole32(physaddr);
   1117 
   1118 		/* finalize mbuf */
   1119 		m->m_pkthdr.len = m->m_len = len;
   1120 		m->m_pkthdr.rcvif = ifp;
   1121 		m->m_flags |= M_HASFCS;
   1122 
   1123 		bpf_mtap(ifp, m);
   1124 		ifp->if_ipackets++;
   1125 		(*ifp->if_input)(ifp, m);
   1126 
   1127 skip:
   1128 		bus_dmamap_sync(sc->sc_dmat, data->rd_map, 0,
   1129 		    data->rd_map->dm_mapsize, BUS_DMASYNC_PREREAD);
   1130 		desc->ddesc_cntl = htole32(
   1131 		    __SHIFTIN(AWGE_MAX_PACKET,DDESC_CNTL_SIZE1MASK) |
   1132 		    DDESC_CNTL_RXCHAIN);
   1133 		desc->ddesc_status = htole32(DDESC_STATUS_OWNEDBYDEV);
   1134 		bus_dmamap_sync(sc->sc_dmat, sc->sc_dma_ring_map,
   1135 		    RX_DESC_OFFSET(i), sizeof(*desc),
   1136 		    BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
   1137 	}
   1138 
   1139 	/* update RX pointer */
   1140 	sc->sc_rxq.r_cur = i;
   1141 
   1142 }
   1143 
   1144 /*
   1145  * Reverse order of bits - http://aggregate.org/MAGIC/#Bit%20Reversal
   1146  */
   1147 static uint32_t
   1148 bitrev32(uint32_t x)
   1149 {
   1150 	x = (((x & 0xaaaaaaaa) >> 1) | ((x & 0x55555555) << 1));
   1151 	x = (((x & 0xcccccccc) >> 2) | ((x & 0x33333333) << 2));
   1152 	x = (((x & 0xf0f0f0f0) >> 4) | ((x & 0x0f0f0f0f) << 4));
   1153 	x = (((x & 0xff00ff00) >> 8) | ((x & 0x00ff00ff) << 8));
   1154 
   1155 	return (x >> 16) | (x << 16);
   1156 }
   1157 
   1158 static void
   1159 dwc_gmac_setmulti(struct dwc_gmac_softc *sc)
   1160 {
   1161 	struct ifnet * const ifp = &sc->sc_ec.ec_if;
   1162 	struct ether_multi *enm;
   1163 	struct ether_multistep step;
   1164 	uint32_t hashes[2] = { 0, 0 };
   1165 	uint32_t ffilt, h;
   1166 	int mcnt, s;
   1167 
   1168 	s = splnet();
   1169 
   1170 	ffilt = bus_space_read_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_MAC_FFILT);
   1171 
   1172 	if (ifp->if_flags & IFF_PROMISC) {
   1173 		ffilt |= AWIN_GMAC_MAC_FFILT_PR;
   1174 		goto special_filter;
   1175 	}
   1176 
   1177 	ifp->if_flags &= ~IFF_ALLMULTI;
   1178 	ffilt &= ~(AWIN_GMAC_MAC_FFILT_PM|AWIN_GMAC_MAC_FFILT_PR);
   1179 
   1180 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_MAC_HTLOW, 0);
   1181 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_MAC_HTHIGH, 0);
   1182 
   1183 	ETHER_FIRST_MULTI(step, &sc->sc_ec, enm);
   1184 	mcnt = 0;
   1185 	while (enm != NULL) {
   1186 		if (memcmp(enm->enm_addrlo, enm->enm_addrhi,
   1187 		    ETHER_ADDR_LEN) != 0) {
   1188 			ffilt |= AWIN_GMAC_MAC_FFILT_PM;
   1189 			ifp->if_flags |= IFF_ALLMULTI;
   1190 			goto special_filter;
   1191 		}
   1192 
   1193 		h = bitrev32(
   1194 			~ether_crc32_le(enm->enm_addrlo, ETHER_ADDR_LEN)
   1195 		    ) >> 26;
   1196 		hashes[h >> 5] |= (1 << (h & 0x1f));
   1197 
   1198 		mcnt++;
   1199 		ETHER_NEXT_MULTI(step, enm);
   1200 	}
   1201 
   1202 	if (mcnt)
   1203 		ffilt |= AWIN_GMAC_MAC_FFILT_HMC;
   1204 	else
   1205 		ffilt &= ~AWIN_GMAC_MAC_FFILT_HMC;
   1206 
   1207 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_MAC_FFILT, ffilt);
   1208 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_MAC_HTLOW,
   1209 	    hashes[0]);
   1210 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_MAC_HTHIGH,
   1211 	    hashes[1]);
   1212 	sc->sc_if_flags = sc->sc_ec.ec_if.if_flags;
   1213 
   1214 	splx(s);
   1215 
   1216 #ifdef DWC_GMAC_DEBUG
   1217 	dwc_gmac_dump_ffilt(sc, ffilt);
   1218 #endif
   1219 	return;
   1220 
   1221 special_filter:
   1222 #ifdef DWC_GMAC_DEBUG
   1223 	dwc_gmac_dump_ffilt(sc, ffilt);
   1224 #endif
   1225 	/* no MAC hashes, ALLMULTI or PROMISC */
   1226 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_MAC_FFILT,
   1227 	    ffilt);
   1228 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_MAC_HTLOW,
   1229 	    0xffffffff);
   1230 	bus_space_write_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_MAC_HTHIGH,
   1231 	    0xffffffff);
   1232 	sc->sc_if_flags = sc->sc_ec.ec_if.if_flags;
   1233 	splx(s);
   1234 }
   1235 
   1236 int
   1237 dwc_gmac_intr(struct dwc_gmac_softc *sc)
   1238 {
   1239 	uint32_t status, dma_status;
   1240 	int rv = 0;
   1241 
   1242 	status = bus_space_read_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_MAC_INTR);
   1243 	if (status & AWIN_GMAC_MII_IRQ) {
   1244 		(void)bus_space_read_4(sc->sc_bst, sc->sc_bsh,
   1245 		    AWIN_GMAC_MII_STATUS);
   1246 		rv = 1;
   1247 		mii_pollstat(&sc->sc_mii);
   1248 	}
   1249 
   1250 	dma_status = bus_space_read_4(sc->sc_bst, sc->sc_bsh,
   1251 	    AWIN_GMAC_DMA_STATUS);
   1252 
   1253 	if (dma_status & (GMAC_DMA_INT_NIE|GMAC_DMA_INT_AIE))
   1254 		rv = 1;
   1255 
   1256 	if (dma_status & GMAC_DMA_INT_TIE)
   1257 		dwc_gmac_tx_intr(sc);
   1258 
   1259 	if (dma_status & GMAC_DMA_INT_RIE)
   1260 		dwc_gmac_rx_intr(sc);
   1261 
   1262 	/*
   1263 	 * Check error conditions
   1264 	 */
   1265 	if (dma_status & GMAC_DMA_INT_ERRORS) {
   1266 		sc->sc_ec.ec_if.if_oerrors++;
   1267 #ifdef DWC_GMAC_DEBUG
   1268 		dwc_dump_and_abort(sc, "interrupt error condition");
   1269 #endif
   1270 	}
   1271 
   1272 	/* ack interrupt */
   1273 	if (dma_status)
   1274 		bus_space_write_4(sc->sc_bst, sc->sc_bsh,
   1275 		    AWIN_GMAC_DMA_STATUS, dma_status & GMAC_DMA_INT_MASK);
   1276 
   1277 	/*
   1278 	 * Get more packets
   1279 	 */
   1280 	if (rv)
   1281 		sc->sc_ec.ec_if.if_start(&sc->sc_ec.ec_if);
   1282 
   1283 	return rv;
   1284 }
   1285 
   1286 #ifdef DWC_GMAC_DEBUG
   1287 static void
   1288 dwc_gmac_dump_dma(struct dwc_gmac_softc *sc)
   1289 {
   1290 	aprint_normal_dev(sc->sc_dev, "busmode: %08x\n",
   1291 	    bus_space_read_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_DMA_BUSMODE));
   1292 	aprint_normal_dev(sc->sc_dev, "tx poll: %08x\n",
   1293 	    bus_space_read_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_DMA_TXPOLL));
   1294 	aprint_normal_dev(sc->sc_dev, "rx poll: %08x\n",
   1295 	    bus_space_read_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_DMA_RXPOLL));
   1296 	aprint_normal_dev(sc->sc_dev, "rx descriptors: %08x\n",
   1297 	    bus_space_read_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_DMA_RX_ADDR));
   1298 	aprint_normal_dev(sc->sc_dev, "tx descriptors: %08x\n",
   1299 	    bus_space_read_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_DMA_TX_ADDR));
   1300 	aprint_normal_dev(sc->sc_dev, "status: %08x\n",
   1301 	    bus_space_read_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_DMA_STATUS));
   1302 	aprint_normal_dev(sc->sc_dev, "op mode: %08x\n",
   1303 	    bus_space_read_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_DMA_OPMODE));
   1304 	aprint_normal_dev(sc->sc_dev, "int enable: %08x\n",
   1305 	    bus_space_read_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_DMA_INTENABLE));
   1306 	aprint_normal_dev(sc->sc_dev, "cur tx: %08x\n",
   1307 	    bus_space_read_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_DMA_CUR_TX_DESC));
   1308 	aprint_normal_dev(sc->sc_dev, "cur rx: %08x\n",
   1309 	    bus_space_read_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_DMA_CUR_RX_DESC));
   1310 	aprint_normal_dev(sc->sc_dev, "cur tx buffer: %08x\n",
   1311 	    bus_space_read_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_DMA_CUR_TX_BUFADDR));
   1312 	aprint_normal_dev(sc->sc_dev, "cur rx buffer: %08x\n",
   1313 	    bus_space_read_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_DMA_CUR_RX_BUFADDR));
   1314 }
   1315 
   1316 static void
   1317 dwc_gmac_dump_tx_desc(struct dwc_gmac_softc *sc)
   1318 {
   1319 	int i;
   1320 
   1321 	aprint_normal_dev(sc->sc_dev, "TX queue: cur=%d, next=%d, queued=%d\n",
   1322 	    sc->sc_txq.t_cur, sc->sc_txq.t_next, sc->sc_txq.t_queued);
   1323 	aprint_normal_dev(sc->sc_dev, "TX DMA descriptors:\n");
   1324 	for (i = 0; i < AWGE_TX_RING_COUNT; i++) {
   1325 		struct dwc_gmac_dev_dmadesc *desc = &sc->sc_txq.t_desc[i];
   1326 		aprint_normal("#%d (%08lx): status: %08x cntl: %08x "
   1327 		    "data: %08x next: %08x\n",
   1328 		    i, sc->sc_txq.t_physaddr +
   1329 			i*sizeof(struct dwc_gmac_dev_dmadesc),
   1330 		    le32toh(desc->ddesc_status), le32toh(desc->ddesc_cntl),
   1331 		    le32toh(desc->ddesc_data), le32toh(desc->ddesc_next));
   1332 	}
   1333 }
   1334 
   1335 static void
   1336 dwc_gmac_dump_rx_desc(struct dwc_gmac_softc *sc)
   1337 {
   1338 	int i;
   1339 
   1340 	aprint_normal_dev(sc->sc_dev, "RX queue: cur=%d, next=%d\n",
   1341 	    sc->sc_rxq.r_cur, sc->sc_rxq.r_next);
   1342 	aprint_normal_dev(sc->sc_dev, "RX DMA descriptors:\n");
   1343 	for (i = 0; i < AWGE_RX_RING_COUNT; i++) {
   1344 		struct dwc_gmac_dev_dmadesc *desc = &sc->sc_rxq.r_desc[i];
   1345 		aprint_normal("#%d (%08lx): status: %08x cntl: %08x "
   1346 		    "data: %08x next: %08x\n",
   1347 		    i, sc->sc_rxq.r_physaddr +
   1348 			i*sizeof(struct dwc_gmac_dev_dmadesc),
   1349 		    le32toh(desc->ddesc_status), le32toh(desc->ddesc_cntl),
   1350 		    le32toh(desc->ddesc_data), le32toh(desc->ddesc_next));
   1351 	}
   1352 }
   1353 
   1354 static void
   1355 dwc_dump_status(struct dwc_gmac_softc *sc)
   1356 {
   1357 	uint32_t status = bus_space_read_4(sc->sc_bst, sc->sc_bsh,
   1358 	     AWIN_GMAC_MAC_INTR);
   1359 	uint32_t dma_status = bus_space_read_4(sc->sc_bst, sc->sc_bsh,
   1360 	     AWIN_GMAC_DMA_STATUS);
   1361 	char buf[200];
   1362 
   1363 	/* print interrupt state */
   1364 	snprintb(buf, sizeof(buf), "\177\20"
   1365 	    "b\x10""NI\0"
   1366 	    "b\x0f""AI\0"
   1367 	    "b\x0e""ER\0"
   1368 	    "b\x0d""FB\0"
   1369 	    "b\x0a""ET\0"
   1370 	    "b\x09""RW\0"
   1371 	    "b\x08""RS\0"
   1372 	    "b\x07""RU\0"
   1373 	    "b\x06""RI\0"
   1374 	    "b\x05""UN\0"
   1375 	    "b\x04""OV\0"
   1376 	    "b\x03""TJ\0"
   1377 	    "b\x02""TU\0"
   1378 	    "b\x01""TS\0"
   1379 	    "b\x00""TI\0"
   1380 	    "\0", dma_status);
   1381 	aprint_normal_dev(sc->sc_dev, "INTR status: %08x, DMA status: %s\n",
   1382 	    status, buf);
   1383 }
   1384 
   1385 static void
   1386 dwc_dump_and_abort(struct dwc_gmac_softc *sc, const char *msg)
   1387 {
   1388 	dwc_dump_status(sc);
   1389 	dwc_gmac_dump_ffilt(sc,
   1390 	    bus_space_read_4(sc->sc_bst, sc->sc_bsh, AWIN_GMAC_MAC_FFILT));
   1391 	dwc_gmac_dump_dma(sc);
   1392 	dwc_gmac_dump_tx_desc(sc);
   1393 	dwc_gmac_dump_rx_desc(sc);
   1394 
   1395 	panic("%s", msg);
   1396 }
   1397 
   1398 static void dwc_gmac_dump_ffilt(struct dwc_gmac_softc *sc, uint32_t ffilt)
   1399 {
   1400 	char buf[200];
   1401 
   1402 	/* print filter setup */
   1403 	snprintb(buf, sizeof(buf), "\177\20"
   1404 	    "b\x1f""RA\0"
   1405 	    "b\x0a""HPF\0"
   1406 	    "b\x09""SAF\0"
   1407 	    "b\x08""SAIF\0"
   1408 	    "b\x05""DBF\0"
   1409 	    "b\x04""PM\0"
   1410 	    "b\x03""DAIF\0"
   1411 	    "b\x02""HMC\0"
   1412 	    "b\x01""HUC\0"
   1413 	    "b\x00""PR\0"
   1414 	    "\0", ffilt);
   1415 	aprint_normal_dev(sc->sc_dev, "FFILT: %s\n", buf);
   1416 }
   1417 #endif
   1418