1 /* $NetBSD: mii_physubr.c,v 1.94 2020/08/27 10:10:23 kardel Exp $ */ 2 3 /*- 4 * Copyright (c) 1998, 1999, 2000, 2001 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 9 * NASA Ames Research Center. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 /* 34 * Subroutines common to all PHYs. 35 */ 36 37 #include <sys/cdefs.h> 38 __KERNEL_RCSID(0, "$NetBSD: mii_physubr.c,v 1.94 2020/08/27 10:10:23 kardel Exp $"); 39 40 #include <sys/param.h> 41 #include <sys/device.h> 42 #include <sys/systm.h> 43 #include <sys/kernel.h> 44 #include <sys/socket.h> 45 #include <sys/errno.h> 46 #include <sys/module.h> 47 #include <sys/proc.h> 48 49 #include <net/if.h> 50 #include <net/if_media.h> 51 #include <net/route.h> 52 53 #include <dev/mii/mii.h> 54 #include <dev/mii/miivar.h> 55 56 const char *(*mii_get_descr)(int, int) = mii_get_descr_stub; 57 58 int mii_verbose_loaded = 0; 59 60 const char * 61 mii_get_descr_stub(int oui, int model) 62 { 63 mii_load_verbose(); 64 if (mii_verbose_loaded) 65 return mii_get_descr(oui, model); 66 else 67 return NULL; 68 } 69 70 /* 71 * Routine to load the miiverbose kernel module as needed 72 */ 73 void 74 mii_load_verbose(void) 75 { 76 if (mii_verbose_loaded == 0) 77 module_autoload("miiverbose", MODULE_CLASS_MISC); 78 } 79 80 static void mii_phy_statusmsg(struct mii_softc *); 81 82 /* 83 * Media to register setting conversion table. Order matters. 84 */ 85 static const struct mii_media mii_media_table[MII_NMEDIA] = { 86 /* None */ 87 { BMCR_ISO, ANAR_CSMA, 88 0, }, 89 90 /* 10baseT */ 91 { BMCR_S10, ANAR_CSMA | ANAR_10, 92 0, }, 93 94 /* 10baseT-FDX */ 95 { BMCR_S10|BMCR_FDX, ANAR_CSMA | ANAR_10_FD, 96 0, }, 97 98 /* 100baseT4 */ 99 { BMCR_S100, ANAR_CSMA | ANAR_T4, 100 0, }, 101 102 /* 100baseTX */ 103 { BMCR_S100, ANAR_CSMA | ANAR_TX, 104 0, }, 105 106 /* 100baseTX-FDX */ 107 { BMCR_S100|BMCR_FDX, ANAR_CSMA | ANAR_TX_FD, 108 0, }, 109 110 /* 1000baseX */ 111 { BMCR_S1000, ANAR_CSMA, 112 0, }, 113 114 /* 1000baseX-FDX */ 115 { BMCR_S1000|BMCR_FDX, ANAR_CSMA, 116 0, }, 117 118 /* 1000baseT */ 119 { BMCR_S1000, ANAR_CSMA, 120 GTCR_ADV_1000THDX }, 121 122 /* 1000baseT-FDX */ 123 { BMCR_S1000, ANAR_CSMA, 124 GTCR_ADV_1000TFDX }, 125 }; 126 127 static void mii_phy_auto_timeout(void *); 128 static void mii_phy_auto_timeout_locked(struct mii_softc *); 129 130 void 131 mii_phy_setmedia(struct mii_softc *sc) 132 { 133 struct mii_data *mii = sc->mii_pdata; 134 struct ifmedia_entry *ife = mii->mii_media.ifm_cur; 135 uint16_t bmcr, anar, gtcr; 136 137 KASSERT(mii_locked(mii)); 138 139 if (IFM_SUBTYPE(ife->ifm_media) == IFM_AUTO) { 140 /* 141 * Force renegotiation if MIIF_DOPAUSE. 142 * 143 * XXX This is only necessary because many NICs don't 144 * XXX advertise PAUSE capabilities at boot time. Maybe 145 * XXX we should force this only once? 146 */ 147 PHY_READ(sc, MII_BMCR, &bmcr); 148 if ((bmcr & BMCR_AUTOEN) == 0 || 149 (sc->mii_flags & (MIIF_FORCEANEG | MIIF_DOPAUSE))) 150 (void) mii_phy_auto(sc); 151 return; 152 } 153 154 /* Table index is stored in the media entry. */ 155 156 #ifdef DIAGNOSTIC 157 if (/* ife->ifm_data < 0 || */ ife->ifm_data >= MII_NMEDIA) 158 panic("mii_phy_setmedia"); 159 #endif 160 161 anar = mii_media_table[ife->ifm_data].mm_anar; 162 bmcr = mii_media_table[ife->ifm_data].mm_bmcr; 163 gtcr = mii_media_table[ife->ifm_data].mm_gtcr; 164 165 if (mii->mii_media.ifm_media & IFM_ETH_MASTER) { 166 switch (IFM_SUBTYPE(ife->ifm_media)) { 167 case IFM_1000_T: 168 gtcr |= GTCR_MAN_MS | GTCR_ADV_MS; 169 break; 170 171 default: 172 panic("mii_phy_setmedia: MASTER on wrong media"); 173 } 174 } 175 176 if (mii->mii_media.ifm_media & IFM_FLOW) { 177 if (sc->mii_flags & MIIF_IS_1000X) 178 anar |= ANAR_X_PAUSE_SYM | ANAR_X_PAUSE_ASYM; 179 else { 180 anar |= ANAR_FC; 181 /* XXX Only 1000BASE-T has PAUSE_ASYM? */ 182 if ((sc->mii_flags & MIIF_HAVE_GTCR) && 183 (sc->mii_extcapabilities & 184 (EXTSR_1000THDX | EXTSR_1000TFDX))) 185 anar |= ANAR_PAUSE_ASYM; 186 } 187 } 188 189 if (ife->ifm_media & IFM_LOOP) 190 bmcr |= BMCR_LOOP; 191 192 PHY_WRITE(sc, MII_ANAR, anar); 193 if (sc->mii_flags & MIIF_HAVE_GTCR) 194 PHY_WRITE(sc, MII_100T2CR, gtcr); 195 if (IFM_SUBTYPE(ife->ifm_media) == IFM_1000_T) 196 mii_phy_auto(sc); 197 else 198 PHY_WRITE(sc, MII_BMCR, bmcr); 199 } 200 201 /* Setup autonegotiation and start it. */ 202 int 203 mii_phy_auto(struct mii_softc *sc) 204 { 205 struct mii_data *mii = sc->mii_pdata; 206 struct ifmedia_entry *ife = mii->mii_media.ifm_cur; 207 208 KASSERT(mii_locked(mii)); 209 210 sc->mii_ticks = 0; 211 if ((sc->mii_flags & MIIF_DOINGAUTO) == 0) { 212 /* 213 * Check for 1000BASE-X. Autonegotiation is a bit 214 * different on such devices. 215 */ 216 if (sc->mii_flags & MIIF_IS_1000X) { 217 uint16_t anar = 0; 218 219 if (sc->mii_extcapabilities & EXTSR_1000XFDX) 220 anar |= ANAR_X_FD; 221 if (sc->mii_extcapabilities & EXTSR_1000XHDX) 222 anar |= ANAR_X_HD; 223 224 if (sc->mii_flags & MIIF_DOPAUSE) { 225 /* XXX Asymmetric vs. symmetric? */ 226 anar |= ANLPAR_X_PAUSE_TOWARDS; 227 } 228 229 PHY_WRITE(sc, MII_ANAR, anar); 230 } else { 231 uint16_t anar; 232 233 anar = BMSR_MEDIA_TO_ANAR(sc->mii_capabilities) | 234 ANAR_CSMA; 235 if (sc->mii_flags & MIIF_DOPAUSE) { 236 anar |= ANAR_FC; 237 /* XXX Only 1000BASE-T has PAUSE_ASYM? */ 238 if ((sc->mii_flags & MIIF_HAVE_GTCR) && 239 (sc->mii_extcapabilities & 240 (EXTSR_1000THDX | EXTSR_1000TFDX))) 241 anar |= ANAR_PAUSE_ASYM; 242 } 243 244 /* 245 * For 1000-base-T, autonegotiation must be enabled, 246 * but if we're not set to auto, only advertise 247 * 1000-base-T with the link partner. 248 */ 249 if (IFM_SUBTYPE(ife->ifm_media) == IFM_1000_T) { 250 anar &= ~(ANAR_T4 | ANAR_TX_FD | ANAR_TX | 251 ANAR_10_FD | ANAR_10); 252 } 253 254 PHY_WRITE(sc, MII_ANAR, anar); 255 if (sc->mii_flags & MIIF_HAVE_GTCR) { 256 uint16_t gtcr = 0; 257 258 if (sc->mii_extcapabilities & EXTSR_1000TFDX) 259 gtcr |= GTCR_ADV_1000TFDX; 260 if (sc->mii_extcapabilities & EXTSR_1000THDX) 261 gtcr |= GTCR_ADV_1000THDX; 262 263 PHY_WRITE(sc, MII_100T2CR, gtcr); 264 } 265 } 266 PHY_WRITE(sc, MII_BMCR, BMCR_AUTOEN | BMCR_STARTNEG); 267 } 268 269 /* 270 * Just let it finish asynchronously. This is for the benefit of 271 * the tick handler driving autonegotiation. Don't want 500ms 272 * delays all the time while the system is running! 273 */ 274 if (sc->mii_flags & MIIF_AUTOTSLEEP) { 275 ASSERT_SLEEPABLE(); 276 sc->mii_flags |= MIIF_DOINGAUTO; 277 kpause("miiaut", false, hz >> 1, mii->mii_media.ifm_lock); 278 mii_phy_auto_timeout_locked(sc); 279 } else if ((sc->mii_flags & MIIF_DOINGAUTO) == 0) { 280 sc->mii_flags |= MIIF_DOINGAUTO; 281 callout_reset(&sc->mii_nway_ch, hz >> 1, 282 mii_phy_auto_timeout, sc); 283 } 284 return EJUSTRETURN; 285 } 286 287 /* Just restart autonegotiation without changing any setting */ 288 int 289 mii_phy_auto_restart(struct mii_softc *sc) 290 { 291 uint16_t reg; 292 293 PHY_READ(sc, MII_BMCR, ®); 294 reg |= BMCR_STARTNEG; 295 PHY_WRITE(sc, MII_BMCR, reg); 296 sc->mii_ticks = 0; 297 298 return EJUSTRETURN; 299 } 300 301 static void 302 mii_phy_auto_timeout_locked(struct mii_softc *sc) 303 { 304 305 if (!device_is_active(sc->mii_dev)) 306 return; 307 308 sc->mii_flags &= ~MIIF_DOINGAUTO; 309 310 /* Update the media status. */ 311 (void) PHY_SERVICE(sc, sc->mii_pdata, MII_POLLSTAT); 312 } 313 314 static void 315 mii_phy_auto_timeout(void *arg) 316 { 317 struct mii_softc *sc = arg; 318 319 if (!device_is_active(sc->mii_dev)) 320 return; 321 322 mii_lock(sc->mii_pdata); 323 mii_phy_auto_timeout_locked(sc); 324 mii_unlock(sc->mii_pdata); 325 } 326 327 int 328 mii_phy_tick(struct mii_softc *sc) 329 { 330 struct mii_data *mii = sc->mii_pdata; 331 struct ifmedia_entry *ife = mii->mii_media.ifm_cur; 332 uint16_t reg; 333 334 KASSERT(mii_locked(mii)); 335 336 /* Just bail now if the interface is down. */ 337 if ((mii->mii_ifp->if_flags & IFF_UP) == 0) 338 return EJUSTRETURN; 339 340 /* 341 * If we're not doing autonegotiation, we don't need to do any extra 342 * work here. However, we need to check the link status so we can 343 * generate an announcement by returning with 0 if the status changes. 344 */ 345 if ((IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) && 346 (IFM_SUBTYPE(ife->ifm_media) != IFM_1000_T)) { 347 /* 348 * Reset autonegotiation timer to 0 just to make sure 349 * the future autonegotiation start with 0. 350 */ 351 sc->mii_ticks = 0; 352 return 0; 353 } 354 355 /* Read the status register twice; BMSR_LINK is latch-low. */ 356 PHY_READ(sc, MII_BMSR, ®); 357 PHY_READ(sc, MII_BMSR, ®); 358 if (reg & BMSR_LINK) { 359 /* 360 * Reset autonegotiation timer to 0 in case the link 361 * goes down in the next tick. 362 */ 363 sc->mii_ticks = 0; 364 /* See above. */ 365 return 0; 366 } 367 368 /* 369 * mii_ticks == 0 means it's the first tick after changing the media or 370 * the link became down since the last tick (see above), so return with 371 * 0 to update the status. 372 */ 373 if (sc->mii_ticks++ == 0) 374 return 0; 375 376 /* 377 * Only retry autonegotiation every N seconds. 378 */ 379 KASSERT(sc->mii_anegticks != 0); 380 if (sc->mii_ticks <= sc->mii_anegticks) 381 return EJUSTRETURN; 382 383 if (mii_phy_auto_restart(sc) == EJUSTRETURN) 384 return EJUSTRETURN; 385 386 /* 387 * Might need to generate a status message if autonegotiation 388 * failed. 389 */ 390 return 0; 391 } 392 393 void 394 mii_phy_reset(struct mii_softc *sc) 395 { 396 int i; 397 uint16_t reg; 398 399 KASSERT(mii_locked(sc->mii_pdata)); 400 401 if (sc->mii_flags & MIIF_NOISOLATE) 402 reg = BMCR_RESET; 403 else 404 reg = BMCR_RESET | BMCR_ISO; 405 PHY_WRITE(sc, MII_BMCR, reg); 406 407 /* Wait another 500ms for it to complete. */ 408 for (i = 0; i < 500; i++) { 409 PHY_READ(sc, MII_BMCR, ®); 410 if ((reg & BMCR_RESET) == 0) 411 break; 412 delay(1000); 413 } 414 415 if (sc->mii_inst != 0 && ((sc->mii_flags & MIIF_NOISOLATE) == 0)) 416 PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO); 417 } 418 419 void 420 mii_phy_down(struct mii_softc *sc) 421 { 422 423 KASSERT(mii_locked(sc->mii_pdata)); 424 425 if (sc->mii_flags & MIIF_DOINGAUTO) { 426 sc->mii_flags &= ~MIIF_DOINGAUTO; 427 callout_stop(&sc->mii_nway_ch); 428 } 429 } 430 431 void 432 mii_phy_status(struct mii_softc *sc) 433 { 434 435 KASSERT(mii_locked(sc->mii_pdata)); 436 PHY_STATUS(sc); 437 } 438 439 void 440 mii_phy_update(struct mii_softc *sc, int cmd) 441 { 442 struct mii_data *mii = sc->mii_pdata; 443 u_int mii_media_active; 444 int mii_media_status; 445 446 KASSERT(mii_locked(mii)); 447 448 mii_media_active = mii->mii_media_active; 449 mii_media_status = mii->mii_media_status; 450 451 if (sc->mii_media_active != mii_media_active || 452 sc->mii_media_status != mii_media_status || 453 cmd == MII_MEDIACHG) { 454 mii_phy_statusmsg(sc); 455 (*mii->mii_statchg)(mii->mii_ifp); 456 sc->mii_media_active = mii_media_active; 457 sc->mii_media_status = mii_media_status; 458 } 459 } 460 461 static void 462 mii_phy_statusmsg(struct mii_softc *sc) 463 { 464 struct mii_data *mii = sc->mii_pdata; 465 struct ifnet *ifp = mii->mii_ifp; 466 467 KASSERT(mii_locked(mii)); 468 469 if (mii->mii_media_status & IFM_AVALID) { 470 if (mii->mii_media_status & IFM_ACTIVE) 471 if_link_state_change(ifp, LINK_STATE_UP); 472 else 473 if_link_state_change(ifp, LINK_STATE_DOWN); 474 } else 475 if_link_state_change(ifp, LINK_STATE_UNKNOWN); 476 477 /* XXX NET_MPSAFE */ 478 ifp->if_baudrate = ifmedia_baudrate(mii->mii_media_active); 479 } 480 481 /* 482 * Initialize generic PHY media based on BMSR, called when a PHY is 483 * attached. We expect to be set up to print a comma-separated list 484 * of media names. Does not print a newline. 485 */ 486 void 487 mii_phy_add_media(struct mii_softc *sc) 488 { 489 struct mii_data *mii = sc->mii_pdata; 490 device_t self = sc->mii_dev; 491 const char *sep = ""; 492 int fdx = 0; 493 494 aprint_normal_dev(self, ""); 495 if ((sc->mii_capabilities & BMSR_MEDIAMASK) == 0 && 496 (sc->mii_extcapabilities & EXTSR_MEDIAMASK) == 0) { 497 aprint_error("no media present\n"); 498 goto out; 499 } 500 501 /* 502 * Set the autonegotiation timer for 10/100 media. Gigabit media is 503 * handled below. 504 */ 505 mii_lock(mii); 506 sc->mii_anegticks = MII_ANEGTICKS; 507 mii_unlock(mii); 508 509 #define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL) 510 #define PRINT(n) aprint_normal("%s%s", sep, (n)); sep = ", " 511 512 /* This flag is static; no need to lock. */ 513 if ((sc->mii_flags & MIIF_NOISOLATE) == 0) 514 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, sc->mii_inst), 515 MII_MEDIA_NONE); 516 517 /* 518 * There are different interpretations for the bits in 519 * HomePNA PHYs. And there is really only one media type 520 * that is supported. This flag is also static, and so 521 * no need to lock. 522 */ 523 if (sc->mii_flags & MIIF_IS_HPNA) { 524 if (sc->mii_capabilities & BMSR_10THDX) { 525 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_HPNA_1, 0, 526 sc->mii_inst), 527 MII_MEDIA_10_T); 528 PRINT("HomePNA1"); 529 } 530 goto out; 531 } 532 533 if (sc->mii_capabilities & BMSR_10THDX) { 534 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, 0, sc->mii_inst), 535 MII_MEDIA_10_T); 536 PRINT("10baseT"); 537 } 538 if (sc->mii_capabilities & BMSR_10TFDX) { 539 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, IFM_FDX, sc->mii_inst), 540 MII_MEDIA_10_T_FDX); 541 PRINT("10baseT-FDX"); 542 fdx = 1; 543 } 544 if (sc->mii_capabilities & BMSR_100TXHDX) { 545 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, 0, sc->mii_inst), 546 MII_MEDIA_100_TX); 547 PRINT("100baseTX"); 548 } 549 if (sc->mii_capabilities & BMSR_100TXFDX) { 550 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_FDX, sc->mii_inst), 551 MII_MEDIA_100_TX_FDX); 552 PRINT("100baseTX-FDX"); 553 fdx = 1; 554 } 555 if (sc->mii_capabilities & BMSR_100T4) { 556 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_T4, 0, sc->mii_inst), 557 MII_MEDIA_100_T4); 558 PRINT("100baseT4"); 559 } 560 561 if (sc->mii_extcapabilities & EXTSR_MEDIAMASK) { 562 /* 563 * XXX Right now only handle 1000SX and 1000TX. Need 564 * XXX to handle 1000LX and 1000CX some how. 565 * 566 * Note since it can take 5 seconds to auto-negotiate 567 * a gigabit link, we make anegticks 10 seconds for 568 * all the gigabit media types. 569 */ 570 if (sc->mii_extcapabilities & EXTSR_1000XHDX) { 571 mii_lock(mii); 572 sc->mii_anegticks = MII_ANEGTICKS_GIGE; 573 sc->mii_flags |= MIIF_IS_1000X; 574 mii_unlock(mii); 575 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_SX, 0, 576 sc->mii_inst), MII_MEDIA_1000_X); 577 PRINT("1000baseSX"); 578 } 579 if (sc->mii_extcapabilities & EXTSR_1000XFDX) { 580 mii_lock(mii); 581 sc->mii_anegticks = MII_ANEGTICKS_GIGE; 582 sc->mii_flags |= MIIF_IS_1000X; 583 mii_unlock(mii); 584 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_SX, IFM_FDX, 585 sc->mii_inst), MII_MEDIA_1000_X_FDX); 586 PRINT("1000baseSX-FDX"); 587 fdx = 1; 588 } 589 590 /* 591 * 1000baseT media needs to be able to manipulate 592 * master/slave mode. We set IFM_ETH_MASTER in 593 * the "don't care mask" and filter it out when 594 * the media is set. 595 * 596 * All 1000baseT PHYs have a 1000baseT control register. 597 */ 598 if (sc->mii_extcapabilities & EXTSR_1000THDX) { 599 mii_lock(mii); 600 sc->mii_anegticks = MII_ANEGTICKS_GIGE; 601 sc->mii_flags |= MIIF_HAVE_GTCR; 602 mii->mii_media.ifm_mask |= IFM_ETH_MASTER; 603 mii_unlock(mii); 604 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T, 0, 605 sc->mii_inst), MII_MEDIA_1000_T); 606 PRINT("1000baseT"); 607 } 608 if (sc->mii_extcapabilities & EXTSR_1000TFDX) { 609 mii_lock(mii); 610 sc->mii_anegticks = MII_ANEGTICKS_GIGE; 611 sc->mii_flags |= MIIF_HAVE_GTCR; 612 mii->mii_media.ifm_mask |= IFM_ETH_MASTER; 613 mii_unlock(mii); 614 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T, IFM_FDX, 615 sc->mii_inst), MII_MEDIA_1000_T_FDX); 616 PRINT("1000baseT-FDX"); 617 fdx = 1; 618 } 619 } 620 621 if (sc->mii_capabilities & BMSR_ANEG) { 622 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, 0, sc->mii_inst), 623 MII_NMEDIA); /* intentionally invalid index */ 624 PRINT("auto"); 625 } 626 #undef ADD 627 #undef PRINT 628 /* This flag is static; no need to lock. */ 629 if (fdx != 0 && (sc->mii_flags & MIIF_DOPAUSE)) { 630 mii_lock(mii); 631 mii->mii_media.ifm_mask |= IFM_ETH_FMASK; 632 mii_unlock(mii); 633 } 634 out: 635 aprint_normal("\n"); 636 if (!pmf_device_register(self, NULL, mii_phy_resume)) { 637 aprint_error_dev(self, "couldn't establish power handler\n"); 638 } 639 } 640 641 void 642 mii_phy_delete_media(struct mii_softc *sc) 643 { 644 struct mii_data *mii = sc->mii_pdata; 645 646 ifmedia_delete_instance(&mii->mii_media, sc->mii_inst); 647 } 648 649 int 650 mii_phy_activate(device_t self, enum devact act) 651 { 652 653 switch (act) { 654 case DVACT_DEACTIVATE: 655 /* XXX Invalidate parent's media setting? */ 656 return 0; 657 default: 658 return EOPNOTSUPP; 659 } 660 } 661 662 /* ARGSUSED1 */ 663 int 664 mii_phy_detach(device_t self, int flags) 665 { 666 struct mii_softc *sc = device_private(self); 667 668 mii_lock(sc->mii_pdata); 669 if (sc->mii_flags & MIIF_DOINGAUTO) { 670 callout_halt(&sc->mii_nway_ch, 671 sc->mii_pdata->mii_media.ifm_lock); 672 } 673 mii_unlock(sc->mii_pdata); 674 675 callout_destroy(&sc->mii_nway_ch); 676 677 mii_phy_delete_media(sc); 678 679 return 0; 680 } 681 682 const struct mii_phydesc * 683 mii_phy_match(const struct mii_attach_args *ma, const struct mii_phydesc *mpd) 684 { 685 686 for (; mpd->mpd_name != NULL; mpd++) { 687 if (MII_OUI(ma->mii_id1, ma->mii_id2) == mpd->mpd_oui && 688 MII_MODEL(ma->mii_id2) == mpd->mpd_model) 689 return mpd; 690 } 691 return NULL; 692 } 693 694 /* 695 * Return the flow control status flag from MII_ANAR & MII_ANLPAR. 696 */ 697 u_int 698 mii_phy_flowstatus(struct mii_softc *sc) 699 { 700 uint16_t anar, anlpar; 701 702 KASSERT(mii_locked(sc->mii_pdata)); 703 704 if ((sc->mii_flags & MIIF_DOPAUSE) == 0) 705 return 0; 706 707 PHY_READ(sc, MII_ANAR, &anar); 708 PHY_READ(sc, MII_ANLPAR, &anlpar); 709 710 /* For 1000baseX, the bits are in a different location. */ 711 if (sc->mii_flags & MIIF_IS_1000X) { 712 anar <<= 3; 713 anlpar <<= 3; 714 } 715 716 if ((anar & ANAR_PAUSE_SYM) & (anlpar & ANLPAR_PAUSE_SYM)) 717 return (IFM_FLOW | IFM_ETH_TXPAUSE | IFM_ETH_RXPAUSE); 718 719 if ((anar & ANAR_PAUSE_SYM) == 0) { 720 if ((anar & ANAR_PAUSE_ASYM) && 721 ((anlpar & ANLPAR_PAUSE_TOWARDS) == ANLPAR_PAUSE_TOWARDS)) 722 return (IFM_FLOW | IFM_ETH_TXPAUSE); 723 else 724 return 0; 725 } 726 727 if ((anar & ANAR_PAUSE_ASYM) == 0) { 728 if (anlpar & ANLPAR_PAUSE_SYM) 729 return (IFM_FLOW | IFM_ETH_TXPAUSE | IFM_ETH_RXPAUSE); 730 else 731 return 0; 732 } 733 734 switch ((anlpar & ANLPAR_PAUSE_TOWARDS)) { 735 case ANLPAR_PAUSE_NONE: 736 return 0; 737 738 case ANLPAR_PAUSE_ASYM: 739 return (IFM_FLOW | IFM_ETH_RXPAUSE); 740 741 default: 742 return (IFM_FLOW | IFM_ETH_RXPAUSE | IFM_ETH_TXPAUSE); 743 } 744 /* NOTREACHED */ 745 } 746 747 bool 748 mii_phy_resume(device_t dv, const pmf_qual_t *qual) 749 { 750 struct mii_softc *sc = device_private(dv); 751 752 mii_lock(sc->mii_pdata); 753 PHY_RESET(sc); 754 bool rv = PHY_SERVICE(sc, sc->mii_pdata, MII_MEDIACHG) == 0; 755 mii_unlock(sc->mii_pdata); 756 757 return rv; 758 } 759 760 761 /* 762 * Given an ifmedia_entry, return the corresponding ANAR value. 763 */ 764 uint16_t 765 mii_anar(struct ifmedia_entry *ife) 766 { 767 768 #ifdef DIAGNOSTIC 769 if (ife->ifm_data >= MII_NMEDIA) 770 panic("mii_anar"); 771 #endif 772 773 return mii_media_table[ife->ifm_data].mm_anar; 774 } 775