int mii_phy_auto(struct mii_softc *sc, int waitfor) { int bmsr, i; if ((sc->mii_flags & MIIF_DOINGAUTO) == 0) { /* * Check for 1000BASE-X. Autonegotiation is a bit * different on such devices. */ if (sc->mii_flags & MIIF_IS_1000X) { uint16_t anar = 0; if (sc->mii_extcapabilities & EXTSR_1000XFDX) anar |= ANAR_X_FD; if (sc->mii_extcapabilities & EXTSR_1000XHDX) anar |= ANAR_X_HD; if (sc->mii_flags & MIIF_DOPAUSE && sc->mii_extcapabilities & EXTSR_1000XFDX) anar |= ANAR_X_PAUSE_TOWARDS; PHY_WRITE(sc, MII_ANAR, anar); } else { uint16_t anar; anar = BMSR_MEDIA_TO_ANAR(sc->mii_capabilities) | ANAR_CSMA; /* * Most 100baseTX PHY's only support symmetric * PAUSE, so we don't advertise asymmetric * PAUSE unless we also have 1000baseT capability. */ if (sc->mii_flags & MIIF_DOPAUSE) { if (sc->mii_capabilities & BMSR_100TXFDX) anar |= ANAR_FC; if (sc->mii_extcapabilities & EXTSR_1000TFDX) anar |= ANAR_PAUSE_TOWARDS; } PHY_WRITE(sc, MII_ANAR, anar); if (sc->mii_flags & MIIF_HAVE_GTCR) { uint16_t gtcr = 0; if (sc->mii_extcapabilities & EXTSR_1000TFDX) gtcr |= GTCR_ADV_1000TFDX; if (sc->mii_extcapabilities & EXTSR_1000THDX) gtcr |= GTCR_ADV_1000THDX; PHY_WRITE(sc, MII_100T2CR, gtcr); } } PHY_WRITE(sc, MII_BMCR, BMCR_AUTOEN | BMCR_STARTNEG); } if (waitfor) { /* Wait 500ms for it to complete. */ for (i = 0; i < 500; i++) { if ((bmsr = PHY_READ(sc, MII_BMSR)) & BMSR_ACOMP) return (0); delay(1000); } /* * Don't need to worry about clearing MIIF_DOINGAUTO. * If that's set, a timeout is pending, and it will * clear the flag. */ return (EIO); } /* * Just let it finish asynchronously. This is for the benefit of * the tick handler driving autonegotiation. Don't want 500ms * delays all the time while the system is running! */ if (sc->mii_flags & MIIF_AUTOTSLEEP) { sc->mii_flags |= MIIF_DOINGAUTO; tsleep(&sc->mii_flags, PZERO, "miiaut", hz >> 1); mii_phy_auto_timeout(sc); } else if ((sc->mii_flags & MIIF_DOINGAUTO) == 0) {
int mii_phy_auto(struct mii_softc *sc, int waitfor) { int i; struct mii_data *mii = sc->mii_pdata; struct ifmedia_entry *ife = mii->mii_media.ifm_cur; sc->mii_ticks = 0; if ((sc->mii_flags & MIIF_DOINGAUTO) == 0) { /* * Check for 1000BASE-X. Autonegotiation is a bit * different on such devices. */ if (sc->mii_flags & MIIF_IS_1000X) { uint16_t anar = 0; if (sc->mii_extcapabilities & EXTSR_1000XFDX) anar |= ANAR_X_FD; if (sc->mii_extcapabilities & EXTSR_1000XHDX) anar |= ANAR_X_HD; if (sc->mii_flags & MIIF_DOPAUSE) { /* XXX Asymmetric vs. symmetric? */ anar |= ANLPAR_X_PAUSE_TOWARDS; } PHY_WRITE(sc, MII_ANAR, anar); } else { uint16_t anar; anar = BMSR_MEDIA_TO_ANAR(sc->mii_capabilities) | ANAR_CSMA; if (sc->mii_flags & MIIF_DOPAUSE) { anar |= ANAR_FC; /* XXX Only 1000BASE-T has PAUSE_ASYM? */ if ((sc->mii_flags & MIIF_HAVE_GTCR) && (sc->mii_extcapabilities & (EXTSR_1000THDX | EXTSR_1000TFDX))) anar |= ANAR_PAUSE_ASYM; } /* *for 1000-base-T, autonegotiation mus be enabled, but *if we're not set to auto, only advertise *1000-base-T with the link partner. */ if (IFM_SUBTYPE(ife->ifm_media) == IFM_1000_T) { anar &= ~(ANAR_T4|ANAR_TX_FD|ANAR_TX|ANAR_10_FD|ANAR_10); } PHY_WRITE(sc, MII_ANAR, anar); if (sc->mii_flags & MIIF_HAVE_GTCR) { uint16_t gtcr = 0; if (sc->mii_extcapabilities & EXTSR_1000TFDX) gtcr |= GTCR_ADV_1000TFDX; if (sc->mii_extcapabilities & EXTSR_1000THDX) gtcr |= GTCR_ADV_1000THDX; PHY_WRITE(sc, MII_100T2CR, gtcr); } } PHY_WRITE(sc, MII_BMCR, BMCR_AUTOEN | BMCR_STARTNEG); } if (waitfor) { /* Wait 500ms for it to complete. */ for (i = 0; i < 500; i++) { if (PHY_READ(sc, MII_BMSR) & BMSR_ACOMP) return (0); delay(1000); } /* * Don't need to worry about clearing MIIF_DOINGAUTO. * If that's set, a timeout is pending, and it will * clear the flag. */ return (EIO); } /* * Just let it finish asynchronously. This is for the benefit of * the tick handler driving autonegotiation. Don't want 500ms * delays all the time while the system is running! */ if (sc->mii_flags & MIIF_AUTOTSLEEP) { sc->mii_flags |= MIIF_DOINGAUTO; tsleep(&sc->mii_flags, PZERO, "miiaut", hz >> 1); mii_phy_auto_timeout(sc); } else if ((sc->mii_flags & MIIF_DOINGAUTO) == 0) {