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