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