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