1 /* $NetBSD: mii_physubr.c,v 1.49 2006/03/29 07:05:24 thorpej 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 * 3. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgement: 21 * This product includes software developed by the NetBSD 22 * Foundation, Inc. and its contributors. 23 * 4. Neither the name of The NetBSD Foundation nor the names of its 24 * contributors may be used to endorse or promote products derived 25 * from this software without specific prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 37 * POSSIBILITY OF SUCH DAMAGE. 38 * 39 * $FreeBSD: src/sys/dev/mii/mii_physubr.c,v 1.2.2.1 2000/12/12 19:29:14 wpaul Exp $ 40 */ 41 42 /* 43 * Subroutines common to all PHYs. 44 */ 45 46 #include <sys/param.h> 47 #include <sys/systm.h> 48 #include <sys/kernel.h> 49 #include <sys/socket.h> 50 #include <sys/errno.h> 51 #include <sys/module.h> 52 #include <sys/bus.h> 53 #include <sys/thread2.h> 54 55 #include <net/if.h> 56 #include <net/if_var.h> 57 #include <net/if_media.h> 58 59 #include "mii.h" 60 #include "miivar.h" 61 62 #include "miibus_if.h" 63 64 const struct mii_media mii_media_table[MII_NMEDIA] = { 65 [MII_MEDIA_NONE] = { .mm_bmcr = BMCR_ISO, 66 .mm_anar = ANAR_CSMA, 67 .mm_gtcr = 0 }, 68 69 [MII_MEDIA_10_T] = { .mm_bmcr = BMCR_S10, 70 .mm_anar = ANAR_CSMA | ANAR_10, 71 .mm_gtcr = 0 }, 72 73 [MII_MEDIA_10_T_FDX] = { .mm_bmcr = BMCR_S10 | BMCR_FDX, 74 .mm_anar = ANAR_CSMA | ANAR_10_FD, 75 .mm_gtcr = 0 }, 76 77 [MII_MEDIA_100_T4] = { .mm_bmcr = BMCR_S100, 78 .mm_anar = ANAR_CSMA | ANAR_T4, 79 .mm_gtcr = 0 }, 80 81 [MII_MEDIA_100_TX] = { .mm_bmcr = BMCR_S100, 82 .mm_anar = ANAR_CSMA | ANAR_TX, 83 .mm_gtcr = 0 }, 84 85 [MII_MEDIA_100_TX_FDX] = { .mm_bmcr = BMCR_S100 | BMCR_FDX, 86 .mm_anar = ANAR_CSMA | ANAR_TX_FD, 87 .mm_gtcr = 0 }, 88 89 [MII_MEDIA_1000_X] = { .mm_bmcr = BMCR_S1000, 90 .mm_anar = ANAR_CSMA, 91 .mm_gtcr = 0 }, 92 93 [MII_MEDIA_1000_X_FDX] = { .mm_bmcr = BMCR_S1000 | BMCR_FDX, 94 .mm_anar = ANAR_CSMA, 95 .mm_gtcr = 0 }, 96 97 [MII_MEDIA_1000_T] = { .mm_bmcr = BMCR_S1000, 98 .mm_anar = ANAR_CSMA, 99 .mm_gtcr = GTCR_ADV_1000THDX }, 100 101 [MII_MEDIA_1000_T_FDX] = { .mm_bmcr = BMCR_S1000, 102 .mm_anar = ANAR_CSMA, 103 .mm_gtcr = GTCR_ADV_1000TFDX } 104 }; 105 106 void 107 mii_softc_init(struct mii_softc *mii, struct mii_attach_args *ma) 108 { 109 mii->mii_phy = ma->mii_phyno; 110 mii->mii_flags |= ma->mii_flags; 111 mii->mii_model = MII_MODEL(ma->mii_id2); 112 mii->mii_rev = MII_REV(ma->mii_id2); 113 mii->mii_privtag = ma->mii_privtag; 114 mii->mii_priv = ma->mii_priv; 115 116 if (mii->mii_reset == NULL) 117 mii->mii_reset = mii_phy_reset; 118 if (mii->mii_anegticks == 0) 119 mii->mii_anegticks = MII_ANEGTICKS; 120 } 121 122 int 123 mii_phy_auto(struct mii_softc *sc, int waitfor) 124 { 125 uint16_t anar; 126 127 /* 128 * Check for 1000BASE-X. Autonegotiation is a bit 129 * different on such devices. 130 */ 131 if (sc->mii_flags & MIIF_IS_1000X) { 132 anar = 0; 133 if (sc->mii_extcapabilities & EXTSR_1000XFDX) 134 anar |= ANAR_X_FD; 135 if (sc->mii_extcapabilities & EXTSR_1000XHDX) 136 anar |= ANAR_X_HD; 137 138 if (sc->mii_flags & MIIF_DOPAUSE) { 139 /* XXX Asymmetric vs. symmetric? */ 140 anar |= ANLPAR_X_PAUSE_TOWARDS; 141 } 142 PHY_WRITE(sc, MII_ANAR, anar); 143 } else { 144 anar = BMSR_MEDIA_TO_ANAR(sc->mii_capabilities) | 145 ANAR_CSMA; 146 if (sc->mii_flags & MIIF_DOPAUSE) { 147 anar |= ANAR_FC; 148 /* XXX Only 1000BASE-T has PAUSE_ASYM? */ 149 if ((sc->mii_flags & MIIF_HAVE_GTCR) && 150 (sc->mii_extcapabilities & 151 (EXTSR_1000THDX|EXTSR_1000TFDX))) 152 anar |= ANAR_X_PAUSE_ASYM; 153 } 154 PHY_WRITE(sc, MII_ANAR, anar); 155 if (sc->mii_flags & MIIF_HAVE_GTCR) { 156 uint16_t gtcr = 0; 157 158 if (sc->mii_extcapabilities & EXTSR_1000TFDX) 159 gtcr |= GTCR_ADV_1000TFDX; 160 if (sc->mii_extcapabilities & EXTSR_1000THDX) 161 gtcr |= GTCR_ADV_1000THDX; 162 163 PHY_WRITE(sc, MII_100T2CR, gtcr); 164 } 165 } 166 PHY_WRITE(sc, MII_BMCR, BMCR_AUTOEN | BMCR_STARTNEG); 167 168 if (waitfor) { 169 int i; 170 171 /* Wait 500ms for it to complete. */ 172 for (i = 0; i < 500; i++) { 173 if (PHY_READ(sc, MII_BMSR) & BMSR_ACOMP) 174 return (0); 175 DELAY(1000); 176 } 177 return (EIO); 178 } 179 return (EJUSTRETURN); 180 } 181 182 void 183 mii_phy_reset(struct mii_softc *sc) 184 { 185 int reg, i; 186 187 if (sc->mii_flags & MIIF_NOISOLATE) 188 reg = BMCR_RESET; 189 else 190 reg = BMCR_RESET | BMCR_ISO; 191 PHY_WRITE(sc, MII_BMCR, reg); 192 193 /* 194 * It is best to allow a little time for the reset to settle 195 * in before we start polling the BMCR again. Notably, the 196 * DP83840A manual states that there should be a 500us delay 197 * between asserting software reset and attempting MII serial 198 * operations. Also, a DP83815 can get into a bad state on 199 * cable removal and reinsertion if we do not delay here. 200 */ 201 DELAY(500); 202 203 /* Wait 100ms for it to complete. */ 204 for (i = 0; i < 100; i++) { 205 reg = PHY_READ(sc, MII_BMCR); 206 if ((reg & BMCR_RESET) == 0) 207 break; 208 DELAY(1000); 209 } 210 211 if (sc->mii_inst != 0 && ((sc->mii_flags & MIIF_NOISOLATE) == 0)) 212 PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO); 213 } 214 215 /* 216 * Initialize generic PHY media based on BMSR, called when a PHY is 217 * attached. We expect to be set up to print a comma-separated list 218 * of media names. Does not print a newline. 219 */ 220 void 221 mii_phy_add_media(struct mii_softc *sc) 222 { 223 struct mii_data *mii = sc->mii_pdata; 224 const char *sep = ""; 225 int fdx = 0; 226 227 #define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL) 228 #define PRINT(s) kprintf("%s%s", sep, s); sep = ", " 229 230 if ((sc->mii_flags & MIIF_NOISOLATE) == 0) 231 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, sc->mii_inst), 232 MII_MEDIA_NONE); 233 234 /* 235 * There are different interpretations for the bits in 236 * HomePNA PHYs. And there is really only one media type 237 * that is supported. 238 */ 239 if (sc->mii_flags & MIIF_IS_HPNA) { 240 if (sc->mii_capabilities & BMSR_10THDX) { 241 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_HPNA_1, 0, 242 sc->mii_inst), 243 MII_MEDIA_10_T); 244 PRINT("HomePNA1"); 245 } 246 return; 247 } 248 249 if (sc->mii_capabilities & BMSR_10THDX) { 250 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, 0, sc->mii_inst), 251 MII_MEDIA_10_T); 252 PRINT("10baseT"); 253 } 254 if (sc->mii_capabilities & BMSR_10TFDX) { 255 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, IFM_FDX, sc->mii_inst), 256 MII_MEDIA_10_T_FDX); 257 PRINT("10baseT-FDX"); 258 fdx = 1; 259 } 260 if (sc->mii_capabilities & BMSR_100TXHDX) { 261 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, 0, sc->mii_inst), 262 MII_MEDIA_100_TX); 263 PRINT("100baseTX"); 264 } 265 if (sc->mii_capabilities & BMSR_100TXFDX) { 266 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_FDX, sc->mii_inst), 267 MII_MEDIA_100_TX_FDX); 268 PRINT("100baseTX-FDX"); 269 fdx = 1; 270 } 271 if (sc->mii_capabilities & BMSR_100T4) { 272 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_T4, 0, sc->mii_inst), 273 MII_MEDIA_100_T4); 274 PRINT("100baseT4"); 275 } 276 277 if (sc->mii_extcapabilities & EXTSR_MEDIAMASK) { 278 /* 279 * XXX Right now only handle 1000SX and 1000TX. Need 280 * XXX to handle 1000LX and 1000CX some how. 281 * 282 * Note since it can take 5 seconds to auto-negotiate 283 * a gigabit link, we make anegticks 10 seconds for 284 * all the gigabit media types. 285 */ 286 if (sc->mii_extcapabilities & EXTSR_1000XHDX) { 287 sc->mii_anegticks = MII_ANEGTICKS_GIGE; 288 sc->mii_flags |= MIIF_IS_1000X; 289 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_SX, 0, 290 sc->mii_inst), MII_MEDIA_1000_X); 291 PRINT("1000baseSX"); 292 } 293 if (sc->mii_extcapabilities & EXTSR_1000XFDX) { 294 sc->mii_anegticks = MII_ANEGTICKS_GIGE; 295 sc->mii_flags |= MIIF_IS_1000X; 296 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_SX, IFM_FDX, 297 sc->mii_inst), MII_MEDIA_1000_X_FDX); 298 PRINT("1000baseSX-FDX"); 299 fdx = 1; 300 } 301 302 /* 303 * 1000baseT media needs to be able to manipulate 304 * master/slave mode. We set IFM_ETH_MASTER in 305 * the "don't care mask" and filter it out when 306 * the media is set. 307 * 308 * All 1000baseT PHYs have a 1000baseT control register. 309 */ 310 if (sc->mii_extcapabilities & EXTSR_1000THDX) { 311 sc->mii_anegticks = MII_ANEGTICKS_GIGE; 312 sc->mii_flags |= MIIF_HAVE_GTCR; 313 mii->mii_media.ifm_mask |= IFM_ETH_MASTER; 314 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T, 0, 315 sc->mii_inst), MII_MEDIA_1000_T); 316 PRINT("1000baseT"); 317 } 318 if (sc->mii_extcapabilities & EXTSR_1000TFDX) { 319 sc->mii_anegticks = MII_ANEGTICKS_GIGE; 320 sc->mii_flags |= MIIF_HAVE_GTCR; 321 mii->mii_media.ifm_mask |= IFM_ETH_MASTER; 322 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T, IFM_FDX, 323 sc->mii_inst), MII_MEDIA_1000_T_FDX); 324 PRINT("1000baseT-FDX"); 325 fdx = 1; 326 } 327 } 328 329 if (sc->mii_capabilities & BMSR_ANEG) { 330 ADD(IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, 0, sc->mii_inst), 331 MII_NMEDIA); /* intentionally invalid index */ 332 PRINT("auto"); 333 } 334 #undef ADD 335 #undef PRINT 336 if (fdx != 0 && (sc->mii_flags & MIIF_DOPAUSE)) 337 mii->mii_media.ifm_mask |= IFM_ETH_FMASK; 338 } 339 340 void 341 mii_phy_set_media(struct mii_softc *sc) 342 { 343 struct mii_data *mii = sc->mii_pdata; 344 struct ifmedia_entry *ife = mii->mii_media.ifm_cur; 345 int bmcr, anar, gtcr; 346 347 if (IFM_SUBTYPE(ife->ifm_media) == IFM_AUTO) { 348 /* 349 * Force renegotiation if MIIF_DOPAUSE. 350 * 351 * XXX This is only necessary because many NICs don't 352 * XXX advertise PAUSE capabilities at boot time. Maybe 353 * XXX we should force this only once? 354 */ 355 if ((PHY_READ(sc, MII_BMCR) & BMCR_AUTOEN) == 0 || 356 (sc->mii_flags & (MIIF_FORCEANEG | MIIF_DOPAUSE))) 357 mii_phy_auto(sc, 1); 358 return; 359 } 360 361 /* 362 * Table index is stored in the media entry. 363 */ 364 365 KASSERT(ife->ifm_data >= 0 && ife->ifm_data < MII_NMEDIA, 366 ("bogus ife->ifm_data (%d)", ife->ifm_data)); 367 368 anar = mii_media_table[ife->ifm_data].mm_anar; 369 bmcr = mii_media_table[ife->ifm_data].mm_bmcr; 370 gtcr = mii_media_table[ife->ifm_data].mm_gtcr; 371 372 if (mii->mii_media.ifm_media & IFM_ETH_MASTER) { 373 switch (IFM_SUBTYPE(ife->ifm_media)) { 374 case IFM_1000_T: 375 gtcr |= GTCR_MAN_MS|GTCR_ADV_MS; 376 break; 377 378 default: 379 panic("mii_phy_setmedia: MASTER on wrong media"); 380 } 381 } 382 383 if (mii->mii_media.ifm_media & IFM_FLOW) { 384 if (sc->mii_flags & MIIF_IS_1000X) { 385 anar |= ANAR_X_PAUSE_SYM | ANAR_X_PAUSE_ASYM; 386 } else { 387 anar |= ANAR_FC; 388 /* XXX Only 1000BASE-T has PAUSE_ASYM? */ 389 if ((sc->mii_flags & MIIF_HAVE_GTCR) && 390 (sc->mii_extcapabilities & 391 (EXTSR_1000THDX | EXTSR_1000TFDX))) 392 anar |= ANAR_X_PAUSE_ASYM; 393 } 394 } 395 396 if (ife->ifm_media & IFM_LOOP) 397 bmcr |= BMCR_LOOP; 398 399 PHY_WRITE(sc, MII_ANAR, anar); 400 PHY_WRITE(sc, MII_BMCR, bmcr); 401 if (sc->mii_flags & MIIF_HAVE_GTCR) 402 PHY_WRITE(sc, MII_100T2CR, gtcr); 403 } 404 405 int 406 mii_phy_tick(struct mii_softc *sc) 407 { 408 struct mii_data *mii = sc->mii_pdata; 409 struct ifmedia_entry *ife = mii->mii_media.ifm_cur; 410 int reg; 411 412 /* Just bail now if the interface is down. */ 413 if ((mii->mii_ifp->if_flags & IFF_UP) == 0) 414 return (EJUSTRETURN); 415 416 /* 417 * If we're not doing autonegotiation, we don't need to do 418 * any extra work here. However, we need to check the link 419 * status so we can generate an announcement if the status 420 * changes. 421 */ 422 if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) 423 return (0); 424 425 /* Read the status register twice; BMSR_LINK is latch-low. */ 426 reg = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR); 427 if (reg & BMSR_LINK) { 428 /* 429 * See above. 430 */ 431 432 /* Reset autonegotiation timer. */ 433 sc->mii_ticks = 0; 434 return (0); 435 } 436 437 /* 438 * Only retry autonegotiation every N seconds. 439 */ 440 KKASSERT(sc->mii_anegticks > 0); 441 if (++sc->mii_ticks <= sc->mii_anegticks) 442 return (EJUSTRETURN); 443 444 sc->mii_ticks = 0; 445 sc->mii_reset(sc); /* Reset PHY */ 446 mii_phy_auto(sc, 0); /* Ignore EJUSTRETURN */ 447 return (0); 448 } 449 450 static int 451 mii_phy_statusmsg(struct mii_softc *sc) 452 { 453 struct mii_data *mii = sc->mii_pdata; 454 struct ifnet *ifp = mii->mii_ifp; 455 int baudrate, link_state, announce = 0; 456 457 if (mii->mii_media_status & IFM_AVALID) { 458 if (mii->mii_media_status & IFM_ACTIVE) 459 link_state = LINK_STATE_UP; 460 else 461 link_state = LINK_STATE_DOWN; 462 } else 463 link_state = LINK_STATE_UNKNOWN; 464 465 baudrate = ifmedia_baudrate(mii->mii_media_active); 466 467 if (link_state != ifp->if_link_state) { 468 ifp->if_link_state = link_state; 469 /* 470 * XXX Right here we'd like to notify protocols 471 * XXX that the link status has changed, so that 472 * XXX e.g. Duplicate Address Detection can restart. 473 */ 474 announce = 1; 475 } 476 477 if (baudrate != ifp->if_baudrate) { 478 ifp->if_baudrate = baudrate; 479 announce = 1; 480 } 481 482 return (announce); 483 } 484 485 void 486 mii_phy_update(struct mii_softc *sc, int cmd) 487 { 488 struct mii_data *mii = sc->mii_pdata; 489 struct ifnet *ifp = mii->mii_ifp; 490 int announce; 491 492 if (sc->mii_media_active != mii->mii_media_active || 493 sc->mii_media_status != mii->mii_media_status || 494 cmd == MII_MEDIACHG) { 495 announce = mii_phy_statusmsg(sc); 496 MIIBUS_STATCHG(sc->mii_dev); 497 sc->mii_media_active = mii->mii_media_active; 498 sc->mii_media_status = mii->mii_media_status; 499 500 if (announce) { 501 crit_enter(); 502 if_link_state_change(ifp); 503 crit_exit(); 504 } 505 } 506 } 507 508 /* 509 * Return the flow control status flag from MII_ANAR & MII_ANLPAR. 510 */ 511 int 512 mii_phy_flowstatus(struct mii_softc *sc) 513 { 514 int anar, anlpar; 515 516 if ((sc->mii_flags & MIIF_DOPAUSE) == 0) 517 return (0); 518 519 anar = PHY_READ(sc, MII_ANAR); 520 anlpar = PHY_READ(sc, MII_ANLPAR); 521 522 if ((anar & ANAR_X_PAUSE_SYM) & (anlpar & ANLPAR_X_PAUSE_SYM)) 523 return (IFM_FLOW | IFM_ETH_TXPAUSE | IFM_ETH_RXPAUSE); 524 525 if ((anar & ANAR_X_PAUSE_SYM) == 0) { 526 if ((anar & ANAR_X_PAUSE_ASYM) && 527 ((anlpar & ANLPAR_X_PAUSE_TOWARDS) == 528 ANLPAR_X_PAUSE_TOWARDS)) 529 return (IFM_FLOW | IFM_ETH_TXPAUSE); 530 else 531 return (0); 532 } 533 534 if ((anar & ANAR_X_PAUSE_ASYM) == 0) { 535 if (anlpar & ANLPAR_X_PAUSE_SYM) 536 return (IFM_FLOW | IFM_ETH_TXPAUSE | IFM_ETH_RXPAUSE); 537 else 538 return (0); 539 } 540 541 switch (anlpar & ANLPAR_X_PAUSE_TOWARDS) { 542 case ANLPAR_X_PAUSE_NONE: 543 return (0); 544 545 case ANLPAR_X_PAUSE_ASYM: 546 return (IFM_FLOW | IFM_ETH_RXPAUSE); 547 548 default: 549 return (IFM_FLOW | IFM_ETH_RXPAUSE | IFM_ETH_TXPAUSE); 550 } 551 /* NOTREACHED */ 552 } 553 554 const struct mii_phydesc * 555 mii_phy_match(const struct mii_attach_args *ma, const struct mii_phydesc *mpd) 556 { 557 for (; mpd->mpd_name != NULL; mpd++) { 558 if (MII_OUI(ma->mii_id1, ma->mii_id2) == mpd->mpd_oui && 559 MII_MODEL(ma->mii_id2) == mpd->mpd_model) 560 return (mpd); 561 } 562 return (NULL); 563 } 564