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