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