1 /* $NetBSD: fec.c,v 1.2 2026/06/30 21:31:31 rkujawa Exp $ */ 2 3 /*- 4 * Copyright (c) 2008, 2026 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Radoslaw Kujawa and Robert Swindells. 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 * Driver for the MPC5200B Fast Ethernet Controller (FEC). 34 */ 35 36 #include <sys/cdefs.h> 37 __KERNEL_RCSID(0, "$NetBSD: fec.c,v 1.2 2026/06/30 21:31:31 rkujawa Exp $"); 38 39 #include <sys/param.h> 40 #include <sys/systm.h> 41 #include <sys/device.h> 42 #include <sys/callout.h> 43 #include <sys/mbuf.h> 44 #include <sys/bus.h> 45 46 #include <net/if.h> 47 #include <net/if_dl.h> 48 #include <net/if_ether.h> 49 #include <net/if_media.h> 50 #include <net/bpf.h> 51 52 #include <dev/mii/mii.h> 53 #include <dev/mii/miivar.h> 54 55 #include <dev/ofw/openfirm.h> 56 57 #include <machine/autoconf.h> 58 59 #include <powerpc/mpc5200/obiovar.h> 60 #include <powerpc/mpc5200/mpc5200reg.h> 61 #include <powerpc/mpc5200/fecreg.h> 62 #include <powerpc/mpc5200/fecvar.h> 63 #include <powerpc/mpc5200/cdmvar.h> 64 #include <powerpc/mpc5200/bestcommvar.h> 65 66 #define FEC_READ(sc, r) bus_space_read_4((sc)->sc_iot, (sc)->sc_ioh, (r)) 67 #define FEC_WRITE(sc, r, v) bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (r), (v)) 68 69 #define FEC_RX_TASK 3 /* TASK_FEC_RX image slot */ 70 #define FEC_TX_TASK 2 /* TASK_FEC_TX image slot */ 71 #define FEC_RX_INITIATOR 3 /* INITIATOR_FEC_RX */ 72 #define FEC_TX_INITIATOR 4 /* INITIATOR_FEC_TX */ 73 74 static const struct bestcomm_bd_layout fec_rx_layout = BESTCOMM_LAYOUT_FEC_RX; 75 static const struct bestcomm_bd_layout fec_tx_layout = BESTCOMM_LAYOUT_FEC_TX; 76 77 static int fec_match(device_t, cfdata_t, void *); 78 static void fec_attach(device_t, device_t, void *); 79 80 static int fec_miibus_readreg(device_t, int, int, uint16_t *); 81 static int fec_miibus_writereg(device_t, int, int, uint16_t); 82 static void fec_miibus_statchg(struct ifnet *); 83 84 static int fec_ioctl(struct ifnet *, u_long, void *); 85 static int fec_init(struct ifnet *); 86 static void fec_stop(struct ifnet *, int); 87 static void fec_start(struct ifnet *); 88 static void fec_tick(void *); 89 90 static void fec_reset(struct fec_softc *); 91 static void fec_mac_setup(struct fec_softc *); 92 static void fec_set_filter(struct fec_softc *); 93 static void fec_mib_sync(struct fec_softc *, bool); 94 static int fec_newbuf(struct fec_softc *, u_int); 95 static int fec_intr(void *); 96 static int fec_rxintr(void *); 97 static int fec_txintr(void *); 98 99 CFATTACH_DECL_NEW(fec, sizeof(struct fec_softc), 100 fec_match, fec_attach, NULL, NULL); 101 102 static int 103 fec_match(device_t parent, cfdata_t cf, void *aux) 104 { 105 struct obio_attach_args *oba = aux; 106 char compat[40]; 107 int len; 108 109 if (strcmp(oba->obio_name, "ethernet") == 0) 110 return 1; 111 112 len = OF_getprop(oba->obio_node, "compatible", compat, sizeof(compat)); 113 if (len > 0 && 114 (strcmp(compat, "mpc5200-fec") == 0 || 115 strcmp(compat, "mpc5200b-fec") == 0)) 116 return 1; 117 118 return 0; 119 } 120 121 static void 122 fec_attach(device_t parent, device_t self, void *aux) 123 { 124 struct fec_softc *sc = device_private(self); 125 struct obio_attach_args *oba = aux; 126 struct ifnet *ifp = &sc->sc_if; 127 struct mii_data *mii = &sc->sc_mii; 128 uint8_t enaddr[ETHER_ADDR_LEN]; 129 bus_size_t size; 130 int ist; 131 132 sc->sc_dev = self; 133 sc->sc_iot = oba->obio_bst; 134 sc->sc_dmat = oba->obio_dmat; 135 sc->sc_pa = oba->obio_addr; 136 callout_init(&sc->sc_tick_ch, 0); 137 callout_setfunc(&sc->sc_tick_ch, fec_tick, sc); 138 139 size = oba->obio_size != 0 ? oba->obio_size : FEC_REG_SIZE; 140 if (bus_space_map(sc->sc_iot, oba->obio_addr, size, 0, 141 &sc->sc_ioh) != 0) { 142 aprint_error(": can't map registers\n"); 143 return; 144 } 145 146 if (OF_getprop(oba->obio_node, "local-mac-address", enaddr, 147 sizeof(enaddr)) != sizeof(enaddr) && 148 OF_getprop(oba->obio_node, "mac-address", enaddr, 149 sizeof(enaddr)) != sizeof(enaddr)) { 150 aprint_error(": no MAC address\n"); 151 return; 152 } 153 memcpy(sc->sc_enaddr, enaddr, ETHER_ADDR_LEN); 154 155 if (obio_decode_interrupt(oba->obio_node, 0, &sc->sc_irq, &ist)) 156 sc->sc_ih = intr_establish(sc->sc_irq, ist, IPL_NET, 157 fec_intr, sc); 158 159 aprint_normal(": MPC5200 FEC, address %s\n", 160 ether_sprintf(sc->sc_enaddr)); 161 162 /* Reset the controller and program the MII management clock. */ 163 sc->sc_ipb_freq = mpc5200_cdm_get_ipb_freq(); 164 fec_reset(sc); 165 166 /* MII / PHY. */ 167 mii->mii_ifp = ifp; 168 mii->mii_readreg = fec_miibus_readreg; 169 mii->mii_writereg = fec_miibus_writereg; 170 mii->mii_statchg = fec_miibus_statchg; 171 sc->sc_ec.ec_mii = mii; 172 ifmedia_init(&mii->mii_media, 0, ether_mediachange, ether_mediastatus); 173 /* MIIF_DOPAUSE: advertise 802.3 PAUSE so we can honour rx flow control. */ 174 mii_attach(self, mii, 0xffffffff, MII_PHY_ANY, MII_OFFSET_ANY, 175 MIIF_DOPAUSE); 176 if (LIST_FIRST(&mii->mii_phys) == NULL) { 177 aprint_error_dev(self, "no PHY found\n"); 178 ifmedia_add(&mii->mii_media, IFM_ETHER | IFM_MANUAL, 0, NULL); 179 ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_MANUAL); 180 } else 181 ifmedia_set(&mii->mii_media, IFM_ETHER | IFM_AUTO); 182 183 /* The controller accepts VLAN-sized frames (see fec_mac_setup()). */ 184 sc->sc_ec.ec_capabilities |= ETHERCAP_VLAN_MTU; 185 186 strlcpy(ifp->if_xname, device_xname(self), IFNAMSIZ); 187 ifp->if_softc = sc; 188 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 189 ifp->if_init = fec_init; 190 ifp->if_stop = fec_stop; 191 ifp->if_start = fec_start; 192 ifp->if_ioctl = fec_ioctl; 193 IFQ_SET_READY(&ifp->if_snd); 194 195 if_attach(ifp); 196 if_deferred_start_init(ifp, NULL); 197 ether_ifattach(ifp, sc->sc_enaddr); 198 } 199 200 /* 201 * Soft-reset the controller and set the MII management clock divider so MDC 202 * stays at or below 2.5 MHz, derived from the IPB clock. 203 */ 204 static void 205 fec_reset(struct fec_softc *sc) 206 { 207 uint32_t div; 208 int i; 209 210 FEC_WRITE(sc, FEC_ECNTRL, FEC_ECNTRL_RESET); 211 for (i = 0; i < 1000; i++) { 212 if ((FEC_READ(sc, FEC_ECNTRL) & FEC_ECNTRL_RESET) == 0) 213 break; 214 DELAY(10); 215 } 216 FEC_WRITE(sc, FEC_IMASK, 0); /* mask all events */ 217 FEC_WRITE(sc, FEC_IEVENT, 0xffffffff); /* clear events */ 218 219 div = howmany(sc->sc_ipb_freq, 2 * FEC_MII_MAX_CLK); 220 if (div > 0x3f) 221 div = 0x3f; 222 FEC_WRITE(sc, FEC_MII_SPEED, FEC_MII_SPEED_DIV(div)); 223 } 224 225 static int 226 fec_mii_wait(struct fec_softc *sc) 227 { 228 int i; 229 230 for (i = 0; i < FEC_PHY_TIMEOUT; i++) { 231 if (FEC_READ(sc, FEC_IEVENT) & FEC_INT_MII) { 232 FEC_WRITE(sc, FEC_IEVENT, FEC_INT_MII); 233 return 0; 234 } 235 DELAY(10); 236 } 237 return ETIMEDOUT; 238 } 239 240 static int 241 fec_miibus_readreg(device_t self, int phy, int reg, uint16_t *val) 242 { 243 struct fec_softc *sc = device_private(self); 244 245 FEC_WRITE(sc, FEC_IEVENT, FEC_INT_MII); 246 FEC_WRITE(sc, FEC_MII_DATA, FEC_MII_READ(phy, reg)); 247 if (fec_mii_wait(sc) != 0) 248 return ETIMEDOUT; 249 250 *val = FEC_READ(sc, FEC_MII_DATA) & FEC_MII_DATA_MASK; 251 return 0; 252 } 253 254 static int 255 fec_miibus_writereg(device_t self, int phy, int reg, uint16_t val) 256 { 257 struct fec_softc *sc = device_private(self); 258 259 FEC_WRITE(sc, FEC_IEVENT, FEC_INT_MII); 260 FEC_WRITE(sc, FEC_MII_DATA, FEC_MII_WRITE(phy, reg, val)); 261 return fec_mii_wait(sc); 262 } 263 264 static void 265 fec_miibus_statchg(struct ifnet *ifp) 266 { 267 struct fec_softc *sc = ifp->if_softc; 268 uint32_t xcr, rcr; 269 270 xcr = FEC_READ(sc, FEC_X_CNTRL); 271 if (sc->sc_mii.mii_media_active & IFM_FDX) 272 xcr |= FEC_X_CNTRL_FDEN; 273 else 274 xcr &= ~FEC_X_CNTRL_FDEN; 275 FEC_WRITE(sc, FEC_X_CNTRL, xcr); 276 277 rcr = FEC_READ(sc, FEC_R_CNTRL); 278 if (sc->sc_mii.mii_media_active & IFM_ETH_RXPAUSE) 279 rcr |= FEC_R_CNTRL_FCE; 280 else 281 rcr &= ~FEC_R_CNTRL_FCE; 282 FEC_WRITE(sc, FEC_R_CNTRL, rcr); 283 } 284 285 static void 286 fec_tick(void *arg) 287 { 288 struct fec_softc *sc = arg; 289 int s; 290 291 s = splnet(); 292 mii_tick(&sc->sc_mii); 293 if (sc->sc_if.if_flags & IFF_RUNNING) 294 fec_mib_sync(sc, false); /* fold hw counters into if_stats */ 295 splx(s); 296 297 /* 298 * Meh. Under load the receive FIFO can overrun, work it around. 299 */ 300 if ((sc->sc_if.if_flags & IFF_RUNNING) && 301 (FEC_READ(sc, FEC_ECNTRL) & FEC_ECNTRL_ETHER_EN) == 0) { 302 if_statinc(&sc->sc_if, if_ierrors); 303 aprint_error_dev(sc->sc_dev, 304 "ETHER_EN cleared, resetting\n"); 305 s = splnet(); 306 (void)fec_init(&sc->sc_if); /* reschedules the callout */ 307 splx(s); 308 return; 309 } 310 311 callout_schedule(&sc->sc_tick_ch, hz); 312 } 313 314 /* Program the station address and receive/transmit MAC control. */ 315 static void 316 fec_mac_setup(struct fec_softc *sc) 317 { 318 FEC_WRITE(sc, FEC_PADDR1, 319 (sc->sc_enaddr[0] << 24) | (sc->sc_enaddr[1] << 16) | 320 (sc->sc_enaddr[2] << 8) | sc->sc_enaddr[3]); 321 FEC_WRITE(sc, FEC_PADDR2, 322 (sc->sc_enaddr[4] << 24) | (sc->sc_enaddr[5] << 16) | 0x8808); 323 FEC_WRITE(sc, FEC_IADDR1, 0); 324 FEC_WRITE(sc, FEC_IADDR2, 0); 325 /* 326 * Allow VLAN-tagged frames (ETHERCAP_VLAN_MTU) 327 */ 328 FEC_WRITE(sc, FEC_R_CNTRL, 329 FEC_R_CNTRL_MAX_FL(ETHER_MAX_LEN + ETHER_VLAN_ENCAP_LEN) | 330 FEC_R_CNTRL_MII_MODE); 331 FEC_WRITE(sc, FEC_X_CNTRL, FEC_X_CNTRL_FDEN); 332 333 /* 334 * Enable frame mode on both FIFOs 335 */ 336 FEC_WRITE(sc, FEC_RESET_CNTRL, FEC_RESET_CNTRL_FIFO_EN); 337 338 FEC_WRITE(sc, FEC_RFIFO_CONTROL, FEC_FIFO_CTRL_INIT); 339 FEC_WRITE(sc, FEC_TFIFO_CONTROL, FEC_FIFO_CTRL_INIT); 340 341 /* 342 * The transmit FIFO requests data from BestComm only while it holds 343 * fewer than "alarm" bytes! 344 */ 345 FEC_WRITE(sc, FEC_TFIFO_ALARM, 0x80); 346 } 347 348 /* 349 * Program the receive address filter 350 */ 351 static void 352 fec_set_filter(struct fec_softc *sc) 353 { 354 struct ethercom *ec = &sc->sc_ec; 355 struct ifnet *ifp = &sc->sc_if; 356 struct ether_multi *enm; 357 struct ether_multistep step; 358 uint32_t gaddr[2] = { 0, 0 }; 359 uint32_t rcr; 360 u_int h; 361 362 rcr = FEC_READ(sc, FEC_R_CNTRL) & ~FEC_R_CNTRL_PROM; 363 364 if (ifp->if_flags & IFF_PROMISC) { 365 rcr |= FEC_R_CNTRL_PROM; 366 gaddr[0] = gaddr[1] = 0xffffffff; 367 goto done; 368 } 369 370 ETHER_LOCK(ec); 371 ec->ec_flags &= ~ETHER_F_ALLMULTI; 372 ETHER_FIRST_MULTI(step, ec, enm); 373 while (enm != NULL) { 374 if (memcmp(enm->enm_addrlo, enm->enm_addrhi, 375 ETHER_ADDR_LEN) != 0) { 376 /* 377 * A range of addresses 378 */ 379 ec->ec_flags |= ETHER_F_ALLMULTI; 380 gaddr[0] = gaddr[1] = 0xffffffff; 381 break; 382 } 383 h = ether_crc32_le(enm->enm_addrlo, ETHER_ADDR_LEN) >> 26; 384 gaddr[h >> 5] |= 1U << (h & 0x1f); 385 ETHER_NEXT_MULTI(step, enm); 386 } 387 ETHER_UNLOCK(ec); 388 389 done: 390 FEC_WRITE(sc, FEC_GADDR1, gaddr[1]); /* buckets 32..63 */ 391 FEC_WRITE(sc, FEC_GADDR2, gaddr[0]); /* buckets 0..31 */ 392 FEC_WRITE(sc, FEC_R_CNTRL, rcr); 393 } 394 395 /* 396 * On-chip counters we dump into the interface stats. 397 */ 398 static const struct fec_mibcnt { 399 bus_size_t reg; 400 if_stat_t stat; 401 } fec_mibtab[] = { 402 { FEC_RMON_T_COL, if_collisions }, 403 { FEC_IEEE_T_LCOL, if_oerrors }, 404 { FEC_IEEE_T_EXCOL, if_oerrors }, 405 { FEC_IEEE_T_MACERR, if_oerrors }, /* Tx FIFO underrun */ 406 { FEC_IEEE_R_DROP, if_iqdrops }, 407 { FEC_IEEE_R_CRC, if_ierrors }, 408 { FEC_IEEE_R_ALIGN, if_ierrors }, 409 { FEC_IEEE_R_MACERR, if_iqdrops }, /* Rx FIFO overflow */ 410 }; 411 __CTASSERT(__arraycount(fec_mibtab) == FEC_NMIB); 412 413 /* 414 * Harvest the on-chip MIB counters. 415 */ 416 static void 417 fec_mib_sync(struct fec_softc *sc, bool prime) 418 { 419 struct ifnet *ifp = &sc->sc_if; 420 net_stat_ref_t nsr; 421 u_int i; 422 423 if (prime) { 424 for (i = 0; i < FEC_NMIB; i++) 425 sc->sc_mib_prev[i] = FEC_READ(sc, fec_mibtab[i].reg); 426 return; 427 } 428 429 nsr = IF_STAT_GETREF(ifp); 430 for (i = 0; i < FEC_NMIB; i++) { 431 uint32_t cur = FEC_READ(sc, fec_mibtab[i].reg); 432 uint32_t delta = cur - sc->sc_mib_prev[i]; /* wraps mod 2^32 */ 433 434 if (delta != 0) 435 if_statadd_ref(ifp, nsr, fec_mibtab[i].stat, delta); 436 sc->sc_mib_prev[i] = cur; 437 } 438 IF_STAT_PUTREF(ifp); 439 } 440 441 /* Allocate a cluster for receive descriptor idx and hand it to the engine. */ 442 static int 443 fec_newbuf(struct fec_softc *sc, u_int idx) 444 { 445 struct mbuf *m; 446 int error; 447 448 MGETHDR(m, M_DONTWAIT, MT_DATA); 449 if (m == NULL) 450 return ENOBUFS; 451 MCLGET(m, M_DONTWAIT); 452 if ((m->m_flags & M_EXT) == 0) { 453 m_freem(m); 454 return ENOBUFS; 455 } 456 m->m_len = m->m_pkthdr.len = MCLBYTES; 457 error = bus_dmamap_load_mbuf(sc->sc_dmat, sc->sc_rxmap[idx], m, 458 BUS_DMA_NOWAIT | BUS_DMA_READ); 459 if (error) { 460 m_freem(m); 461 return error; 462 } 463 bus_dmamap_sync(sc->sc_dmat, sc->sc_rxmap[idx], 0, MCLBYTES, 464 BUS_DMASYNC_PREREAD); 465 sc->sc_rxmbuf[idx] = m; 466 bestcomm_bd_post(&sc->sc_rxring, idx, 467 sc->sc_rxmap[idx]->dm_segs[0].ds_addr, MCLBYTES, 0); 468 return 0; 469 } 470 471 static int 472 fec_init(struct ifnet *ifp) 473 { 474 struct fec_softc *sc = ifp->if_softc; 475 u_int i; 476 int error; 477 bool link_up; 478 479 link_up = (sc->sc_mii.mii_media_status & IFM_ACTIVE) != 0; 480 481 fec_stop(ifp, 0); 482 483 if (!bestcomm_available()) { 484 aprint_error_ifnet(ifp, "BestComm SDMA not available\n"); 485 return ENXIO; 486 } 487 488 fec_reset(sc); 489 fec_mac_setup(sc); 490 fec_set_filter(sc); 491 492 /* 493 * Enable the on-chip MIB counter block 494 */ 495 FEC_WRITE(sc, FEC_MIB_CONTROL, 0); 496 fec_mib_sync(sc, true); 497 498 if (bestcomm_bd_setup(&sc->sc_rxring, FEC_RX_TASK, &fec_rx_layout, 499 sc->sc_pa + FEC_RFIFO_DATA, FEC_NRXDESC, MCLBYTES, 4, 500 FEC_RX_INITIATOR, 6) != 0 || 501 bestcomm_bd_setup(&sc->sc_txring, FEC_TX_TASK, &fec_tx_layout, 502 sc->sc_pa + FEC_TFIFO_DATA, FEC_NTXDESC, MCLBYTES, 4, 503 FEC_TX_INITIATOR, 5) != 0) { 504 aprint_error_ifnet(ifp, "cannot set up SDMA rings\n"); 505 error = ENOMEM; 506 goto fail; 507 } 508 509 for (i = 0; i < FEC_NRXDESC; i++) { 510 if (sc->sc_rxmap[i] == NULL && 511 bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES, 0, 512 BUS_DMA_NOWAIT, &sc->sc_rxmap[i]) != 0) { 513 error = ENOMEM; 514 goto fail; 515 } 516 if ((error = fec_newbuf(sc, i)) != 0) 517 goto fail; 518 } 519 for (i = 0; i < FEC_NTXDESC; i++) { 520 if (sc->sc_txmap[i] == NULL && 521 bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES, 0, 522 BUS_DMA_NOWAIT, &sc->sc_txmap[i]) != 0) { 523 error = ENOMEM; 524 goto fail; 525 } 526 } 527 sc->sc_rxptr = 0; 528 sc->sc_txnext = sc->sc_txdirty = sc->sc_txbusy = 0; 529 530 /* Hook the BestComm task-completion interrupts (via the SIU cascade). */ 531 sc->sc_rxih = intr_establish(bestcomm_task_irq(FEC_RX_TASK), IST_LEVEL, 532 IPL_NET, fec_rxintr, sc); 533 sc->sc_txih = intr_establish(bestcomm_task_irq(FEC_TX_TASK), IST_LEVEL, 534 IPL_NET, fec_txintr, sc); 535 536 /* 537 * Bring the link up before enabling the controller. 538 */ 539 mii_mediachg(&sc->sc_mii); 540 if (!link_up) { 541 for (i = 0; i < 500; i++) { 542 mii_pollstat(&sc->sc_mii); 543 if (sc->sc_mii.mii_media_status & IFM_ACTIVE) 544 break; 545 DELAY(10000); 546 } 547 } 548 549 FEC_WRITE(sc, FEC_ECNTRL, FEC_ECNTRL_ETHER_EN); 550 bestcomm_task_start(FEC_RX_TASK); 551 bestcomm_task_start(FEC_TX_TASK); 552 553 ifp->if_flags |= IFF_RUNNING; 554 ifp->if_flags &= ~IFF_OACTIVE; 555 556 callout_schedule(&sc->sc_tick_ch, hz); 557 return 0; 558 559 fail: 560 /* Unwind any partial setup so we leave a clean, fully-stopped state. */ 561 fec_stop(ifp, 1); 562 return error; 563 } 564 565 static void 566 fec_stop(struct ifnet *ifp, int disable) 567 { 568 struct fec_softc *sc = ifp->if_softc; 569 u_int i; 570 571 callout_stop(&sc->sc_tick_ch); 572 573 /* 574 * Stop the SDMA tasks and release their buffer-descriptor rings back 575 * to the on-chip SRAM pool. 576 */ 577 bestcomm_bd_teardown(&sc->sc_rxring); 578 bestcomm_bd_teardown(&sc->sc_txring); 579 580 FEC_WRITE(sc, FEC_ECNTRL, 0); 581 582 if (sc->sc_rxih != NULL) { 583 intr_disestablish(sc->sc_rxih); 584 sc->sc_rxih = NULL; 585 } 586 if (sc->sc_txih != NULL) { 587 intr_disestablish(sc->sc_txih); 588 sc->sc_txih = NULL; 589 } 590 591 mii_down(&sc->sc_mii); 592 593 for (i = 0; i < FEC_NRXDESC; i++) { 594 if (sc->sc_rxmbuf[i] != NULL) { 595 bus_dmamap_unload(sc->sc_dmat, sc->sc_rxmap[i]); 596 m_freem(sc->sc_rxmbuf[i]); 597 sc->sc_rxmbuf[i] = NULL; 598 } 599 } 600 for (i = 0; i < FEC_NTXDESC; i++) { 601 if (sc->sc_txmbuf[i] != NULL) { 602 bus_dmamap_unload(sc->sc_dmat, sc->sc_txmap[i]); 603 m_freem(sc->sc_txmbuf[i]); 604 sc->sc_txmbuf[i] = NULL; 605 } 606 } 607 ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); 608 } 609 610 static void 611 fec_start(struct ifnet *ifp) 612 { 613 struct fec_softc *sc = ifp->if_softc; 614 struct mbuf *m, *mn; 615 u_int idx; 616 int error, posted = 0; 617 618 if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING) 619 return; 620 621 while (sc->sc_txbusy < FEC_NTXDESC) { 622 IFQ_POLL(&ifp->if_snd, m); 623 if (m == NULL) 624 break; 625 idx = sc->sc_txnext; 626 627 error = bus_dmamap_load_mbuf(sc->sc_dmat, sc->sc_txmap[idx], m, 628 BUS_DMA_NOWAIT | BUS_DMA_WRITE); 629 if (error == EFBIG) { 630 /* The buffer descriptor holds one segment; collapse. */ 631 mn = m_defrag(m, M_DONTWAIT); 632 if (mn != NULL) { 633 m = mn; 634 error = bus_dmamap_load_mbuf(sc->sc_dmat, 635 sc->sc_txmap[idx], m, 636 BUS_DMA_NOWAIT | BUS_DMA_WRITE); 637 } 638 } 639 IFQ_DEQUEUE(&ifp->if_snd, m); 640 if (error) { 641 m_freem(m); 642 if_statinc(ifp, if_oerrors); 643 continue; 644 } 645 646 bus_dmamap_sync(sc->sc_dmat, sc->sc_txmap[idx], 0, 647 m->m_pkthdr.len, BUS_DMASYNC_PREWRITE); 648 bpf_mtap(ifp, m, BPF_D_OUT); 649 sc->sc_txmbuf[idx] = m; 650 bestcomm_bd_post(&sc->sc_txring, idx, 651 sc->sc_txmap[idx]->dm_segs[0].ds_addr, m->m_pkthdr.len, 652 BESTCOMM_BD_FLAG_LAST | BESTCOMM_BD_FLAG_INT); 653 sc->sc_txnext = (idx + 1) % FEC_NTXDESC; 654 sc->sc_txbusy++; 655 posted = 1; 656 } 657 658 /* 659 * (Re-)enable the transmit task. 660 */ 661 if (posted) 662 bestcomm_task_start(FEC_TX_TASK); 663 664 if (sc->sc_txbusy == FEC_NTXDESC) 665 ifp->if_flags |= IFF_OACTIVE; 666 } 667 668 /* BestComm FEC_RX task completion: hand received frames up, refill the ring. */ 669 static int 670 fec_rxintr(void *arg) 671 { 672 struct fec_softc *sc = arg; 673 struct ifnet *ifp = &sc->sc_if; 674 struct mbuf *m; 675 uint32_t st; 676 u_int idx; 677 int len, handled = 0; 678 679 for (;;) { 680 idx = sc->sc_rxptr; 681 st = bestcomm_bd_status(&sc->sc_rxring, idx); 682 if (st & BESTCOMM_BD_READY) 683 break; 684 handled = 1; 685 686 bus_dmamap_sync(sc->sc_dmat, sc->sc_rxmap[idx], 0, MCLBYTES, 687 BUS_DMASYNC_POSTREAD); 688 bus_dmamap_unload(sc->sc_dmat, sc->sc_rxmap[idx]); 689 m = sc->sc_rxmbuf[idx]; 690 sc->sc_rxmbuf[idx] = NULL; 691 692 len = st & BESTCOMM_BD_LEN_MASK; 693 if (len > ETHER_CRC_LEN) 694 len -= ETHER_CRC_LEN; /* strip FCS */ 695 696 if (fec_newbuf(sc, idx) != 0) { 697 /* No replacement: recycle this buffer, drop the frame. */ 698 sc->sc_rxmbuf[idx] = m; 699 (void)bus_dmamap_load_mbuf(sc->sc_dmat, 700 sc->sc_rxmap[idx], m, BUS_DMA_NOWAIT | BUS_DMA_READ); 701 bus_dmamap_sync(sc->sc_dmat, sc->sc_rxmap[idx], 0, 702 MCLBYTES, BUS_DMASYNC_PREREAD); 703 bestcomm_bd_post(&sc->sc_rxring, idx, 704 sc->sc_rxmap[idx]->dm_segs[0].ds_addr, MCLBYTES, 0); 705 if_statinc(ifp, if_ierrors); 706 } else { 707 m_set_rcvif(m, ifp); 708 m->m_pkthdr.len = m->m_len = len; 709 if_percpuq_enqueue(ifp->if_percpuq, m); 710 } 711 sc->sc_rxptr = (idx + 1) % FEC_NRXDESC; 712 } 713 714 return handled; 715 } 716 717 /* BestComm FEC_TX task completion: reap transmitted frames. */ 718 static int 719 fec_txintr(void *arg) 720 { 721 struct fec_softc *sc = arg; 722 struct ifnet *ifp = &sc->sc_if; 723 uint32_t st; 724 u_int idx; 725 int handled = 0; 726 727 while (sc->sc_txbusy > 0) { 728 idx = sc->sc_txdirty; 729 st = bestcomm_bd_status(&sc->sc_txring, idx); 730 if (st & BESTCOMM_BD_READY) 731 break; 732 handled = 1; 733 734 bus_dmamap_sync(sc->sc_dmat, sc->sc_txmap[idx], 0, 735 sc->sc_txmbuf[idx]->m_pkthdr.len, BUS_DMASYNC_POSTWRITE); 736 bus_dmamap_unload(sc->sc_dmat, sc->sc_txmap[idx]); 737 m_freem(sc->sc_txmbuf[idx]); 738 sc->sc_txmbuf[idx] = NULL; 739 if_statinc(ifp, if_opackets); 740 741 sc->sc_txdirty = (idx + 1) % FEC_NTXDESC; 742 sc->sc_txbusy--; 743 } 744 if (handled) { 745 ifp->if_flags &= ~IFF_OACTIVE; 746 if_schedule_deferred_start(ifp); 747 } 748 return handled; 749 } 750 751 static int 752 fec_ioctl(struct ifnet *ifp, u_long cmd, void *data) 753 { 754 struct fec_softc *sc = ifp->if_softc; 755 int s, error; 756 757 s = splnet(); 758 error = ether_ioctl(ifp, cmd, data); 759 if (error == ENETRESET) { 760 /* 761 * The multicast list or the promiscuous flag changed. 762 */ 763 if (ifp->if_flags & IFF_RUNNING) 764 fec_set_filter(sc); 765 error = 0; 766 } 767 splx(s); 768 return error; 769 } 770 771 static int 772 fec_intr(void *arg) 773 { 774 struct fec_softc *sc = arg; 775 uint32_t ievent; 776 777 ievent = FEC_READ(sc, FEC_IEVENT); 778 FEC_WRITE(sc, FEC_IEVENT, ievent); /* acknowledge */ 779 /* Frame rx/tx is serviced by the BestComm task-completion handlers. */ 780 return ievent != 0; 781 } 782