Index: sys/dev/mii/mii_physubr.c =================================================================== --- sys/dev/mii/mii_physubr.c +++ sys/dev/mii/mii_physubr.c @@ -618,11 +618,47 @@ sc->mii_capabilities = PHY_READ(sc, MII_BMSR) & sc->mii_capmask; if (sc->mii_capabilities & BMSR_EXTSTAT) sc->mii_extcapabilities = PHY_READ(sc, MII_EXTSR); + + switch (sc->mii_maxspeed) { + case 100: + /* + * This is a bit tricky. + * If we have a 1G capable PHY, but we don't want to advertise + * 1G capabilities we need to clear the GTCR register before + * doing autonegotiation. + * Clearing the register here is not enough since its value + * can be restored after PHY_RESET is called. + */ + if ((sc->mii_extcapabilities & + (EXTSR_1000THDX | EXTSR_1000TFDX)) != 0) + sc->mii_flags |= MIIF_HAVE_GTCR; + + sc->mii_extcapabilities = 0; + break; + default: + device_printf(dev, + "Ignoring unsupported max speed value of %d\n", + sc->mii_maxspeed); + case 0: + case 1000: + break; + } device_printf(dev, " "); mii_phy_add_media(sc); printf("\n"); MIIBUS_MEDIAINIT(sc->mii_dev); + + /* + * If maxspeed was specified we have to restart autonegotiation. + * PHY might have attempted it and failed due to having mistakenly + * advertising modes that we do not in fact support. + */ + if (sc->mii_maxspeed != 0) { + sc->mii_flags |= MIIF_FORCEANEG; + mii_phy_setmedia(sc); + sc->mii_flags &= ~MIIF_FORCEANEG; + } } /* Index: sys/dev/mii/miivar.h =================================================================== --- sys/dev/mii/miivar.h +++ sys/dev/mii/miivar.h @@ -117,6 +117,7 @@ u_int mii_anegticks; /* ticks before retrying aneg */ u_int mii_media_active; /* last active media */ u_int mii_media_status; /* last active status */ + u_int mii_maxspeed; /* Max speed supported by this PHY */ }; typedef struct mii_softc mii_softc_t;