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