1 /*- 2 * Copyright (c) 2011-2012 Semihalf. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27 #include <sys/cdefs.h> 28 __FBSDID("$FreeBSD$"); 29 30 #include <sys/param.h> 31 #include <sys/systm.h> 32 #include <sys/kernel.h> 33 #include <sys/module.h> 34 #include <sys/bus.h> 35 #include <sys/rman.h> 36 #include <sys/malloc.h> 37 #include <sys/mbuf.h> 38 #include <sys/socket.h> 39 #include <sys/sysctl.h> 40 #include <sys/sockio.h> 41 42 #include <machine/bus.h> 43 #include <machine/resource.h> 44 45 #include <net/ethernet.h> 46 #include <net/if.h> 47 #include <net/if_dl.h> 48 #include <net/if_media.h> 49 #include <net/if_types.h> 50 #include <net/if_arp.h> 51 52 #include <dev/mii/mii.h> 53 #include <dev/mii/miivar.h> 54 #include <dev/ofw/ofw_bus.h> 55 #include <dev/ofw/ofw_bus_subr.h> 56 #include <dev/ofw/openfirm.h> 57 58 #include "miibus_if.h" 59 60 #include <contrib/ncsw/inc/integrations/dpaa_integration_ext.h> 61 #include <contrib/ncsw/inc/Peripherals/fm_mac_ext.h> 62 #include <contrib/ncsw/inc/Peripherals/fm_port_ext.h> 63 #include <contrib/ncsw/inc/xx_ext.h> 64 65 #include "fman.h" 66 #include "if_dtsec.h" 67 #include "if_dtsec_im.h" 68 #include "if_dtsec_rm.h" 69 70 71 /** 72 * @group dTSEC private defines. 73 * @{ 74 */ 75 /** 76 * dTSEC FMan MAC exceptions info struct. 77 */ 78 struct dtsec_fm_mac_ex_str { 79 const int num; 80 const char *str; 81 }; 82 /** @} */ 83 84 85 /** 86 * @group FMan MAC routines. 87 * @{ 88 */ 89 #define DTSEC_MAC_EXCEPTIONS_END (-1) 90 91 /** 92 * FMan MAC exceptions. 93 */ 94 static const struct dtsec_fm_mac_ex_str dtsec_fm_mac_exceptions[] = { 95 { e_FM_MAC_EX_10G_MDIO_SCAN_EVENTMDIO, "MDIO scan event" }, 96 { e_FM_MAC_EX_10G_MDIO_CMD_CMPL, "MDIO command completion" }, 97 { e_FM_MAC_EX_10G_REM_FAULT, "Remote fault" }, 98 { e_FM_MAC_EX_10G_LOC_FAULT, "Local fault" }, 99 { e_FM_MAC_EX_10G_1TX_ECC_ER, "Transmit frame ECC error" }, 100 { e_FM_MAC_EX_10G_TX_FIFO_UNFL, "Transmit FIFO underflow" }, 101 { e_FM_MAC_EX_10G_TX_FIFO_OVFL, "Receive FIFO overflow" }, 102 { e_FM_MAC_EX_10G_TX_ER, "Transmit frame error" }, 103 { e_FM_MAC_EX_10G_RX_FIFO_OVFL, "Receive FIFO overflow" }, 104 { e_FM_MAC_EX_10G_RX_ECC_ER, "Receive frame ECC error" }, 105 { e_FM_MAC_EX_10G_RX_JAB_FRM, "Receive jabber frame" }, 106 { e_FM_MAC_EX_10G_RX_OVRSZ_FRM, "Receive oversized frame" }, 107 { e_FM_MAC_EX_10G_RX_RUNT_FRM, "Receive runt frame" }, 108 { e_FM_MAC_EX_10G_RX_FRAG_FRM, "Receive fragment frame" }, 109 { e_FM_MAC_EX_10G_RX_LEN_ER, "Receive payload length error" }, 110 { e_FM_MAC_EX_10G_RX_CRC_ER, "Receive CRC error" }, 111 { e_FM_MAC_EX_10G_RX_ALIGN_ER, "Receive alignment error" }, 112 { e_FM_MAC_EX_1G_BAB_RX, "Babbling receive error" }, 113 { e_FM_MAC_EX_1G_RX_CTL, "Receive control (pause frame) interrupt" }, 114 { e_FM_MAC_EX_1G_GRATEFUL_TX_STP_COMPLET, "Graceful transmit stop " 115 "complete" }, 116 { e_FM_MAC_EX_1G_BAB_TX, "Babbling transmit error" }, 117 { e_FM_MAC_EX_1G_TX_CTL, "Transmit control (pause frame) interrupt" }, 118 { e_FM_MAC_EX_1G_TX_ERR, "Transmit error" }, 119 { e_FM_MAC_EX_1G_LATE_COL, "Late collision" }, 120 { e_FM_MAC_EX_1G_COL_RET_LMT, "Collision retry limit" }, 121 { e_FM_MAC_EX_1G_TX_FIFO_UNDRN, "Transmit FIFO underrun" }, 122 { e_FM_MAC_EX_1G_MAG_PCKT, "Magic Packet detected when dTSEC is in " 123 "Magic Packet detection mode" }, 124 { e_FM_MAC_EX_1G_MII_MNG_RD_COMPLET, "MII management read completion" }, 125 { e_FM_MAC_EX_1G_MII_MNG_WR_COMPLET, "MII management write completion" }, 126 { e_FM_MAC_EX_1G_GRATEFUL_RX_STP_COMPLET, "Graceful receive stop " 127 "complete" }, 128 { e_FM_MAC_EX_1G_TX_DATA_ERR, "Internal data error on transmit" }, 129 { e_FM_MAC_EX_1G_RX_DATA_ERR, "Internal data error on receive" }, 130 { e_FM_MAC_EX_1G_1588_TS_RX_ERR, "Time-Stamp Receive Error" }, 131 { e_FM_MAC_EX_1G_RX_MIB_CNT_OVFL, "MIB counter overflow" }, 132 { DTSEC_MAC_EXCEPTIONS_END, "" } 133 }; 134 135 static const char * 136 dtsec_fm_mac_ex_to_str(e_FmMacExceptions exception) 137 { 138 int i; 139 140 for (i = 0; dtsec_fm_mac_exceptions[i].num != exception && 141 dtsec_fm_mac_exceptions[i].num != DTSEC_MAC_EXCEPTIONS_END; ++i) 142 ; 143 144 if (dtsec_fm_mac_exceptions[i].num == DTSEC_MAC_EXCEPTIONS_END) 145 return ("<Unknown Exception>"); 146 147 return (dtsec_fm_mac_exceptions[i].str); 148 } 149 150 static void 151 dtsec_fm_mac_mdio_event_callback(t_Handle h_App, 152 e_FmMacExceptions exception) 153 { 154 struct dtsec_softc *sc; 155 156 sc = h_App; 157 device_printf(sc->sc_dev, "MDIO event %i: %s.\n", exception, 158 dtsec_fm_mac_ex_to_str(exception)); 159 } 160 161 static void 162 dtsec_fm_mac_exception_callback(t_Handle app, e_FmMacExceptions exception) 163 { 164 struct dtsec_softc *sc; 165 166 sc = app; 167 device_printf(sc->sc_dev, "MAC exception %i: %s.\n", exception, 168 dtsec_fm_mac_ex_to_str(exception)); 169 } 170 171 static void 172 dtsec_fm_mac_free(struct dtsec_softc *sc) 173 { 174 if (sc->sc_mach == NULL) 175 return; 176 177 FM_MAC_Disable(sc->sc_mach, e_COMM_MODE_RX_AND_TX); 178 FM_MAC_Free(sc->sc_mach); 179 sc->sc_mach = NULL; 180 } 181 182 static int 183 dtsec_fm_mac_init(struct dtsec_softc *sc, uint8_t *mac) 184 { 185 t_FmMacParams params; 186 t_Error error; 187 188 memset(¶ms, 0, sizeof(params)); 189 memcpy(¶ms.addr, mac, sizeof(params.addr)); 190 191 params.baseAddr = rman_get_bushandle(sc->sc_mem); 192 params.enetMode = sc->sc_mac_enet_mode; 193 params.macId = sc->sc_eth_id; 194 params.mdioIrq = sc->sc_mac_mdio_irq; 195 params.f_Event = dtsec_fm_mac_mdio_event_callback; 196 params.f_Exception = dtsec_fm_mac_exception_callback; 197 params.h_App = sc; 198 params.h_Fm = sc->sc_fmh; 199 200 sc->sc_mach = FM_MAC_Config(¶ms); 201 if (sc->sc_mach == NULL) { 202 device_printf(sc->sc_dev, "couldn't configure FM_MAC module.\n" 203 ); 204 return (ENXIO); 205 } 206 207 error = FM_MAC_ConfigResetOnInit(sc->sc_mach, TRUE); 208 if (error != E_OK) { 209 device_printf(sc->sc_dev, "couldn't enable reset on init " 210 "feature.\n"); 211 dtsec_fm_mac_free(sc); 212 return (ENXIO); 213 } 214 215 /* Do not inform about pause frames */ 216 error = FM_MAC_ConfigException(sc->sc_mach, e_FM_MAC_EX_1G_RX_CTL, 217 FALSE); 218 if (error != E_OK) { 219 device_printf(sc->sc_dev, "couldn't disable pause frames " 220 "exception.\n"); 221 dtsec_fm_mac_free(sc); 222 return (ENXIO); 223 } 224 225 error = FM_MAC_Init(sc->sc_mach); 226 if (error != E_OK) { 227 device_printf(sc->sc_dev, "couldn't initialize FM_MAC module." 228 "\n"); 229 dtsec_fm_mac_free(sc); 230 return (ENXIO); 231 } 232 233 return (0); 234 } 235 /** @} */ 236 237 238 /** 239 * @group FMan PORT routines. 240 * @{ 241 */ 242 static const char * 243 dtsec_fm_port_ex_to_str(e_FmPortExceptions exception) 244 { 245 246 switch (exception) { 247 case e_FM_PORT_EXCEPTION_IM_BUSY: 248 return ("IM: RX busy"); 249 default: 250 return ("<Unknown Exception>"); 251 } 252 } 253 254 void 255 dtsec_fm_port_rx_exception_callback(t_Handle app, 256 e_FmPortExceptions exception) 257 { 258 struct dtsec_softc *sc; 259 260 sc = app; 261 device_printf(sc->sc_dev, "RX exception: %i: %s.\n", exception, 262 dtsec_fm_port_ex_to_str(exception)); 263 } 264 265 void 266 dtsec_fm_port_tx_exception_callback(t_Handle app, 267 e_FmPortExceptions exception) 268 { 269 struct dtsec_softc *sc; 270 271 sc = app; 272 device_printf(sc->sc_dev, "TX exception: %i: %s.\n", exception, 273 dtsec_fm_port_ex_to_str(exception)); 274 } 275 276 e_FmPortType 277 dtsec_fm_port_rx_type(enum eth_dev_type type) 278 { 279 switch (type) { 280 case ETH_DTSEC: 281 return (e_FM_PORT_TYPE_RX); 282 case ETH_10GSEC: 283 return (e_FM_PORT_TYPE_RX_10G); 284 default: 285 return (e_FM_PORT_TYPE_DUMMY); 286 } 287 } 288 289 e_FmPortType 290 dtsec_fm_port_tx_type(enum eth_dev_type type) 291 { 292 293 switch (type) { 294 case ETH_DTSEC: 295 return (e_FM_PORT_TYPE_TX); 296 case ETH_10GSEC: 297 return (e_FM_PORT_TYPE_TX_10G); 298 default: 299 return (e_FM_PORT_TYPE_DUMMY); 300 } 301 } 302 303 static void 304 dtsec_fm_port_free_both(struct dtsec_softc *sc) 305 { 306 if (sc->sc_rxph) { 307 FM_PORT_Free(sc->sc_rxph); 308 sc->sc_rxph = NULL; 309 } 310 311 if (sc->sc_txph) { 312 FM_PORT_Free(sc->sc_txph); 313 sc->sc_txph = NULL; 314 } 315 } 316 /** @} */ 317 318 319 /** 320 * @group IFnet routines. 321 * @{ 322 */ 323 static int 324 dtsec_if_enable_locked(struct dtsec_softc *sc) 325 { 326 int error; 327 328 DTSEC_LOCK_ASSERT(sc); 329 330 error = FM_MAC_Enable(sc->sc_mach, e_COMM_MODE_RX_AND_TX); 331 if (error != E_OK) 332 return (EIO); 333 334 error = FM_PORT_Enable(sc->sc_rxph); 335 if (error != E_OK) 336 return (EIO); 337 338 error = FM_PORT_Enable(sc->sc_txph); 339 if (error != E_OK) 340 return (EIO); 341 342 sc->sc_ifnet->if_drv_flags |= IFF_DRV_RUNNING; 343 344 /* Refresh link state */ 345 dtsec_miibus_statchg(sc->sc_dev); 346 347 return (0); 348 } 349 350 static int 351 dtsec_if_disable_locked(struct dtsec_softc *sc) 352 { 353 int error; 354 355 DTSEC_LOCK_ASSERT(sc); 356 357 error = FM_MAC_Disable(sc->sc_mach, e_COMM_MODE_RX_AND_TX); 358 if (error != E_OK) 359 return (EIO); 360 361 error = FM_PORT_Disable(sc->sc_rxph); 362 if (error != E_OK) 363 return (EIO); 364 365 error = FM_PORT_Disable(sc->sc_txph); 366 if (error != E_OK) 367 return (EIO); 368 369 sc->sc_ifnet->if_drv_flags &= ~IFF_DRV_RUNNING; 370 371 return (0); 372 } 373 374 static int 375 dtsec_if_ioctl(struct ifnet *ifp, u_long command, caddr_t data) 376 { 377 struct dtsec_softc *sc; 378 struct ifreq *ifr; 379 int error; 380 381 sc = ifp->if_softc; 382 ifr = (struct ifreq *)data; 383 error = 0; 384 385 /* Basic functionality to achieve media status reports */ 386 switch (command) { 387 case SIOCSIFFLAGS: 388 DTSEC_LOCK(sc); 389 390 if (sc->sc_ifnet->if_flags & IFF_UP) 391 error = dtsec_if_enable_locked(sc); 392 else 393 error = dtsec_if_disable_locked(sc); 394 395 DTSEC_UNLOCK(sc); 396 break; 397 398 case SIOCGIFMEDIA: 399 case SIOCSIFMEDIA: 400 error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii->mii_media, 401 command); 402 break; 403 404 default: 405 error = ether_ioctl(ifp, command, data); 406 } 407 408 return (error); 409 } 410 411 static void 412 dtsec_if_tick(void *arg) 413 { 414 struct dtsec_softc *sc; 415 416 sc = arg; 417 418 /* TODO */ 419 DTSEC_LOCK(sc); 420 421 mii_tick(sc->sc_mii); 422 callout_reset(&sc->sc_tick_callout, hz, dtsec_if_tick, sc); 423 424 DTSEC_UNLOCK(sc); 425 } 426 427 static void 428 dtsec_if_deinit_locked(struct dtsec_softc *sc) 429 { 430 431 DTSEC_LOCK_ASSERT(sc); 432 433 DTSEC_UNLOCK(sc); 434 callout_drain(&sc->sc_tick_callout); 435 DTSEC_LOCK(sc); 436 } 437 438 static void 439 dtsec_if_init_locked(struct dtsec_softc *sc) 440 { 441 int error; 442 443 DTSEC_LOCK_ASSERT(sc); 444 445 /* Set MAC address */ 446 error = FM_MAC_ModifyMacAddr(sc->sc_mach, 447 (t_EnetAddr *)IF_LLADDR(sc->sc_ifnet)); 448 if (error != E_OK) { 449 device_printf(sc->sc_dev, "couldn't set MAC address.\n"); 450 goto err; 451 } 452 453 /* Start MII polling */ 454 if (sc->sc_mii) 455 callout_reset(&sc->sc_tick_callout, hz, dtsec_if_tick, sc); 456 457 if (sc->sc_ifnet->if_flags & IFF_UP) { 458 error = dtsec_if_enable_locked(sc); 459 if (error != 0) 460 goto err; 461 } else { 462 error = dtsec_if_disable_locked(sc); 463 if (error != 0) 464 goto err; 465 } 466 467 return; 468 469 err: 470 dtsec_if_deinit_locked(sc); 471 device_printf(sc->sc_dev, "initialization error.\n"); 472 return; 473 } 474 475 static void 476 dtsec_if_init(void *data) 477 { 478 struct dtsec_softc *sc; 479 480 sc = data; 481 482 DTSEC_LOCK(sc); 483 dtsec_if_init_locked(sc); 484 DTSEC_UNLOCK(sc); 485 } 486 487 static void 488 dtsec_if_start(struct ifnet *ifp) 489 { 490 struct dtsec_softc *sc; 491 492 sc = ifp->if_softc; 493 DTSEC_LOCK(sc); 494 sc->sc_start_locked(sc); 495 DTSEC_UNLOCK(sc); 496 } 497 498 static void 499 dtsec_if_watchdog(struct ifnet *ifp) 500 { 501 /* TODO */ 502 } 503 /** @} */ 504 505 506 /** 507 * @group IFmedia routines. 508 * @{ 509 */ 510 static int 511 dtsec_ifmedia_upd(struct ifnet *ifp) 512 { 513 struct dtsec_softc *sc = ifp->if_softc; 514 515 DTSEC_LOCK(sc); 516 mii_mediachg(sc->sc_mii); 517 DTSEC_UNLOCK(sc); 518 519 return (0); 520 } 521 522 static void 523 dtsec_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr) 524 { 525 struct dtsec_softc *sc = ifp->if_softc; 526 527 DTSEC_LOCK(sc); 528 529 mii_pollstat(sc->sc_mii); 530 531 ifmr->ifm_active = sc->sc_mii->mii_media_active; 532 ifmr->ifm_status = sc->sc_mii->mii_media_status; 533 534 DTSEC_UNLOCK(sc); 535 } 536 /** @} */ 537 538 539 /** 540 * @group dTSEC bus interface. 541 * @{ 542 */ 543 static void 544 dtsec_configure_mode(struct dtsec_softc *sc) 545 { 546 char tunable[64]; 547 548 snprintf(tunable, sizeof(tunable), "%s.independent_mode", 549 device_get_nameunit(sc->sc_dev)); 550 551 sc->sc_mode = DTSEC_MODE_REGULAR; 552 TUNABLE_INT_FETCH(tunable, &sc->sc_mode); 553 554 if (sc->sc_mode == DTSEC_MODE_REGULAR) { 555 sc->sc_port_rx_init = dtsec_rm_fm_port_rx_init; 556 sc->sc_port_tx_init = dtsec_rm_fm_port_tx_init; 557 sc->sc_start_locked = dtsec_rm_if_start_locked; 558 } else { 559 sc->sc_port_rx_init = dtsec_im_fm_port_rx_init; 560 sc->sc_port_tx_init = dtsec_im_fm_port_tx_init; 561 sc->sc_start_locked = dtsec_im_if_start_locked; 562 } 563 564 device_printf(sc->sc_dev, "Configured for %s mode.\n", 565 (sc->sc_mode == DTSEC_MODE_REGULAR) ? "regular" : "independent"); 566 } 567 568 int 569 dtsec_attach(device_t dev) 570 { 571 struct dtsec_softc *sc; 572 device_t parent; 573 int error; 574 struct ifnet *ifp; 575 576 sc = device_get_softc(dev); 577 578 parent = device_get_parent(dev); 579 sc->sc_dev = dev; 580 sc->sc_mac_mdio_irq = NO_IRQ; 581 582 /* Check if MallocSmart allocator is ready */ 583 if (XX_MallocSmartInit() != E_OK) 584 return (ENXIO); 585 586 /* Init locks */ 587 mtx_init(&sc->sc_lock, device_get_nameunit(dev), 588 "DTSEC Global Lock", MTX_DEF); 589 590 mtx_init(&sc->sc_mii_lock, device_get_nameunit(dev), 591 "DTSEC MII Lock", MTX_DEF); 592 593 /* Init callouts */ 594 callout_init(&sc->sc_tick_callout, CALLOUT_MPSAFE); 595 596 /* Read configuraton */ 597 if ((error = fman_get_handle(parent, &sc->sc_fmh)) != 0) 598 return (error); 599 600 if ((error = fman_get_muram_handle(parent, &sc->sc_muramh)) != 0) 601 return (error); 602 603 if ((error = fman_get_bushandle(parent, &sc->sc_fm_base)) != 0) 604 return (error); 605 606 /* Configure working mode */ 607 dtsec_configure_mode(sc); 608 609 /* If we are working in regular mode configure BMAN and QMAN */ 610 if (sc->sc_mode == DTSEC_MODE_REGULAR) { 611 /* Create RX buffer pool */ 612 error = dtsec_rm_pool_rx_init(sc); 613 if (error != 0) 614 return (EIO); 615 616 /* Create RX frame queue range */ 617 error = dtsec_rm_fqr_rx_init(sc); 618 if (error != 0) 619 return (EIO); 620 621 /* Create frame info pool */ 622 error = dtsec_rm_fi_pool_init(sc); 623 if (error != 0) 624 return (EIO); 625 626 /* Create TX frame queue range */ 627 error = dtsec_rm_fqr_tx_init(sc); 628 if (error != 0) 629 return (EIO); 630 } 631 632 /* Init FMan MAC module. */ 633 error = dtsec_fm_mac_init(sc, sc->sc_mac_addr); 634 if (error != 0) { 635 dtsec_detach(dev); 636 return (ENXIO); 637 } 638 639 /* Init FMan TX port */ 640 error = sc->sc_port_tx_init(sc, device_get_unit(sc->sc_dev)); 641 if (error != 0) { 642 dtsec_detach(dev); 643 return (ENXIO); 644 } 645 646 /* Init FMan RX port */ 647 error = sc->sc_port_rx_init(sc, device_get_unit(sc->sc_dev)); 648 if (error != 0) { 649 dtsec_detach(dev); 650 return (ENXIO); 651 } 652 653 /* Create network interface for upper layers */ 654 ifp = sc->sc_ifnet = if_alloc(IFT_ETHER); 655 if (ifp == NULL) { 656 device_printf(sc->sc_dev, "if_alloc() failed.\n"); 657 dtsec_detach(dev); 658 return (ENOMEM); 659 } 660 661 ifp->if_softc = sc; 662 ifp->if_mtu = ETHERMTU; /* TODO: Configure */ 663 ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST; 664 ifp->if_init = dtsec_if_init; 665 ifp->if_start = dtsec_if_start; 666 ifp->if_ioctl = dtsec_if_ioctl; 667 ifp->if_snd.ifq_maxlen = IFQ_MAXLEN; 668 669 if (sc->sc_phy_addr >= 0) 670 if_initname(ifp, device_get_name(sc->sc_dev), 671 device_get_unit(sc->sc_dev)); 672 else 673 if_initname(ifp, "dtsec_phy", device_get_unit(sc->sc_dev)); 674 675 /* TODO */ 676 #if 0 677 IFQ_SET_MAXLEN(&ifp->if_snd, TSEC_TX_NUM_DESC - 1); 678 ifp->if_snd.ifq_drv_maxlen = TSEC_TX_NUM_DESC - 1; 679 IFQ_SET_READY(&ifp->if_snd); 680 #endif 681 ifp->if_capabilities = 0; /* TODO: Check */ 682 ifp->if_capenable = ifp->if_capabilities; 683 684 /* Attach PHY(s) */ 685 error = mii_attach(sc->sc_dev, &sc->sc_mii_dev, ifp, dtsec_ifmedia_upd, 686 dtsec_ifmedia_sts, BMSR_DEFCAPMASK, sc->sc_phy_addr, 687 MII_OFFSET_ANY, 0); 688 if (error) { 689 device_printf(sc->sc_dev, "attaching PHYs failed: %d\n", error); 690 dtsec_detach(sc->sc_dev); 691 return (error); 692 } 693 sc->sc_mii = device_get_softc(sc->sc_mii_dev); 694 695 /* Attach to stack */ 696 ether_ifattach(ifp, sc->sc_mac_addr); 697 698 return (0); 699 } 700 701 int 702 dtsec_detach(device_t dev) 703 { 704 struct dtsec_softc *sc; 705 if_t ifp; 706 707 sc = device_get_softc(dev); 708 ifp = sc->sc_ifnet; 709 710 if (device_is_attached(dev)) { 711 ether_ifdetach(ifp); 712 /* Shutdown interface */ 713 DTSEC_LOCK(sc); 714 dtsec_if_deinit_locked(sc); 715 DTSEC_UNLOCK(sc); 716 } 717 718 if (sc->sc_ifnet) { 719 if_free(sc->sc_ifnet); 720 sc->sc_ifnet = NULL; 721 } 722 723 if (sc->sc_mode == DTSEC_MODE_REGULAR) { 724 /* Free RX/TX FQRs */ 725 dtsec_rm_fqr_rx_free(sc); 726 dtsec_rm_fqr_tx_free(sc); 727 728 /* Free frame info pool */ 729 dtsec_rm_fi_pool_free(sc); 730 731 /* Free RX buffer pool */ 732 dtsec_rm_pool_rx_free(sc); 733 } 734 735 dtsec_fm_mac_free(sc); 736 dtsec_fm_port_free_both(sc); 737 738 /* Destroy lock */ 739 mtx_destroy(&sc->sc_lock); 740 741 return (0); 742 } 743 744 int 745 dtsec_suspend(device_t dev) 746 { 747 748 return (0); 749 } 750 751 int 752 dtsec_resume(device_t dev) 753 { 754 755 return (0); 756 } 757 758 int 759 dtsec_shutdown(device_t dev) 760 { 761 762 return (0); 763 } 764 /** @} */ 765 766 767 /** 768 * @group MII bus interface. 769 * @{ 770 */ 771 int 772 dtsec_miibus_readreg(device_t dev, int phy, int reg) 773 { 774 struct dtsec_softc *sc; 775 776 sc = device_get_softc(dev); 777 778 return (MIIBUS_READREG(sc->sc_mdio, phy, reg)); 779 } 780 781 int 782 dtsec_miibus_writereg(device_t dev, int phy, int reg, int value) 783 { 784 785 struct dtsec_softc *sc; 786 787 sc = device_get_softc(dev); 788 789 return (MIIBUS_WRITEREG(sc->sc_mdio, phy, reg, value)); 790 } 791 792 void 793 dtsec_miibus_statchg(device_t dev) 794 { 795 struct dtsec_softc *sc; 796 e_EnetSpeed speed; 797 bool duplex; 798 int error; 799 800 sc = device_get_softc(dev); 801 802 DTSEC_LOCK_ASSERT(sc); 803 804 duplex = ((sc->sc_mii->mii_media_active & IFM_GMASK) == IFM_FDX); 805 806 switch (IFM_SUBTYPE(sc->sc_mii->mii_media_active)) { 807 case IFM_1000_T: 808 case IFM_1000_SX: 809 speed = e_ENET_SPEED_1000; 810 break; 811 812 case IFM_100_TX: 813 speed = e_ENET_SPEED_100; 814 break; 815 816 case IFM_10_T: 817 speed = e_ENET_SPEED_10; 818 break; 819 820 default: 821 speed = e_ENET_SPEED_10; 822 } 823 824 error = FM_MAC_AdjustLink(sc->sc_mach, speed, duplex); 825 if (error != E_OK) 826 device_printf(sc->sc_dev, "error while adjusting MAC speed.\n"); 827 } 828 /** @} */ 829