Beispiel #1
0
static void
rgephy_disable_eee(struct mii_softc *sc)
{
	uint16_t anar;

	PHY_WRITE(sc, RGEPHY_F_EPAGSR, 0x0000);
	PHY_WRITE(sc, MII_MMDACR, MMDACR_FN_ADDRESS |
	    (MMDACR_DADDRMASK & RGEPHY_F_MMD_DEV_7));
	PHY_WRITE(sc, MII_MMDAADR, RGEPHY_F_MMD_EEEAR);
	PHY_WRITE(sc, MII_MMDACR, MMDACR_FN_DATANPI |
	    (MMDACR_DADDRMASK & RGEPHY_F_MMD_DEV_7));
	PHY_WRITE(sc, MII_MMDAADR, 0x0000);
	PHY_WRITE(sc, MII_MMDACR, 0x0000);
	/*
	 * XXX
	 * Restart auto-negotiation to take changes effect.
	 * This may result in link establishment.
	 */
	anar = BMSR_MEDIA_TO_ANAR(sc->mii_capabilities) | ANAR_CSMA;
	PHY_WRITE(sc, RGEPHY_MII_ANAR, anar);
	PHY_WRITE(sc, RGEPHY_MII_1000CTL, RGEPHY_1000CTL_AHD |
	    RGEPHY_1000CTL_AFD);
	PHY_WRITE(sc, RGEPHY_MII_BMCR, RGEPHY_BMCR_RESET |
	    RGEPHY_BMCR_AUTOEN | RGEPHY_BMCR_STARTNEG);
}
Beispiel #2
0
int
brgphy_mii_phy_auto(struct mii_softc *sc)
{
	int anar, ktcr = 0;

	PHY_RESET(sc);

	if (sc->mii_flags & MIIF_HAVEFIBER) {
		anar = BRGPHY_SERDES_ANAR_FDX | BRGPHY_SERDES_ANAR_HDX;
		if (sc->mii_flags & MIIF_DOPAUSE)
			anar |= BRGPHY_SERDES_ANAR_BOTH_PAUSE;
		PHY_WRITE(sc, BRGPHY_SERDES_ANAR, anar);
	} else {
		anar = BMSR_MEDIA_TO_ANAR(sc->mii_capabilities) | ANAR_CSMA;
		if (sc->mii_flags & MIIF_DOPAUSE)
			anar |= BRGPHY_ANAR_ASP | BRGPHY_ANAR_PC;
		PHY_WRITE(sc, BRGPHY_MII_ANAR, anar);
	}

	/* Enable speed in the 1000baseT control register */
	ktcr = BRGPHY_1000CTL_AFD | BRGPHY_1000CTL_AHD;
	if (sc->mii_model == MII_MODEL_xxBROADCOM_BCM5701)
		ktcr |= BRGPHY_1000CTL_MSE | BRGPHY_1000CTL_MSC;
	PHY_WRITE(sc, BRGPHY_MII_1000CTL, ktcr);
	ktcr = PHY_READ(sc, BRGPHY_MII_1000CTL);

	/* Start autonegotiation */
	PHY_WRITE(sc, BRGPHY_MII_BMCR,
	    BRGPHY_BMCR_AUTOEN | BRGPHY_BMCR_STARTNEG);
	PHY_WRITE(sc, BRGPHY_MII_IMR, 0xFF00);

	return (EJUSTRETURN);
}
Beispiel #3
0
static void
atphy_auto(struct mii_softc *sc)
{
	uint16_t anar;

	anar = BMSR_MEDIA_TO_ANAR(sc->mii_capabilities);
	PHY_WRITE(sc, MII_ANAR, anar | (3 << 10) | ANAR_CSMA);

	if (sc->mii_extcapabilities & (EXTSR_1000TFDX | EXTSR_1000THDX)) {
		PHY_WRITE(sc, MII_100T2CR, GTCR_ADV_1000TFDX |
		    GTCR_ADV_1000THDX);
	} else if (sc->mii_model == MII_MODEL_ATHEROS_F1) {
		/*
		 * AR8132 has 10/100 PHY and the PHY uses the same
		 * model number of F1 gigabit PHY. The PHY has no
		 * ability to establish gigabit link so explicitly
		 * disable 1000baseT configuration for the PHY.
		 * Otherwise, there is a case that atphy(4) could
		 * not establish a link against gigabit link partner
		 * unless the link partner supports down-shifting.
		 */
		PHY_WRITE(sc, MII_100T2CR, 0); 
	}
	PHY_WRITE(sc, MII_BMCR, BMCR_RESET | BMCR_AUTOEN | BMCR_STARTNEG);
}
static void
brgphy_mii_phy_auto(struct mii_softc *sc)
{
	struct brgphy_softc *bsc = (struct brgphy_softc *)sc;
	int ktcr = 0;

	brgphy_reset(sc);

	/* Enable flow control in the advertisement register. */
	if ((sc->mii_flags & MIIF_HAVEFIBER) == 0) {
		/* Pause capability advertisement (pause capable & asymmetric) */
		PHY_WRITE(sc, BRGPHY_MII_ANAR,
	    	BMSR_MEDIA_TO_ANAR(sc->mii_capabilities) | ANAR_CSMA |
	    	BRGPHY_ANAR_ASP | BRGPHY_ANAR_PC);
	} else {
		PHY_WRITE(sc, BRGPHY_SERDES_ANAR, BRGPHY_SERDES_ANAR_FDX |
			BRGPHY_SERDES_ANAR_HDX | BRGPHY_SERDES_ANAR_BOTH_PAUSE);
	}

	/* Enable speed in the 1000baseT control register */
	ktcr = BRGPHY_1000CTL_AFD | BRGPHY_1000CTL_AHD;
	if (bsc->mii_model == MII_MODEL_xxBROADCOM_BCM5701)
		ktcr |= BRGPHY_1000CTL_MSE | BRGPHY_1000CTL_MSC;
	PHY_WRITE(sc, BRGPHY_MII_1000CTL, ktcr);
	ktcr = PHY_READ(sc, BRGPHY_MII_1000CTL);

	/* Start autonegotiation */
	PHY_WRITE(sc, BRGPHY_MII_BMCR,BRGPHY_BMCR_AUTOEN | BRGPHY_BMCR_STARTNEG);
	PHY_WRITE(sc, BRGPHY_MII_IMR, 0xFF00);

}
Beispiel #5
0
static int
atphy_setmedia(struct mii_softc *sc, int media)
{
	uint16_t anar;

	anar = BMSR_MEDIA_TO_ANAR(sc->mii_capabilities) | ANAR_CSMA;
	if ((IFM_SUBTYPE(media) == IFM_AUTO || (media & IFM_FDX) != 0) &&
	    ((media & IFM_FLOW) != 0 ||
	    (sc->mii_flags & MIIF_FORCEPAUSE) != 0))
		anar |= ANAR_PAUSE_TOWARDS;
	PHY_WRITE(sc, MII_ANAR, anar);
	if ((sc->mii_extcapabilities &
	     (EXTSR_1000TFDX | EXTSR_1000THDX)) != 0)
		PHY_WRITE(sc, MII_100T2CR, GTCR_ADV_1000TFDX |
		    GTCR_ADV_1000THDX);
	else if (sc->mii_mpd_model == MII_MODEL_xxATHEROS_F1) {
		/*
		 * AR8132 has 10/100 PHY and the PHY uses the same
		 * model number of F1 gigabit PHY.  The PHY has no
		 * ability to establish gigabit link so explicitly
		 * disable 1000baseT configuration for the PHY.
		 * Otherwise, there is a case that atphy(4) could
		 * not establish a link against gigabit link partner
		 * unless the link partner supports down-shifting.
		 */
		PHY_WRITE(sc, MII_100T2CR, 0);
	}
	PHY_WRITE(sc, MII_BMCR, BMCR_RESET | BMCR_AUTOEN | BMCR_STARTNEG);

	return (EJUSTRETURN);
}
Beispiel #6
0
static void
brgphy_mii_phy_auto(struct mii_softc *sc, int media)
{
	int anar, ktcr = 0;

	PHY_RESET(sc);

	if ((sc->mii_flags & MIIF_HAVEFIBER) == 0) {
		anar = BMSR_MEDIA_TO_ANAR(sc->mii_capabilities) | ANAR_CSMA;
		if ((media & IFM_FLOW) != 0 ||
		    (sc->mii_flags & MIIF_FORCEPAUSE) != 0)
			anar |= BRGPHY_ANAR_PC | BRGPHY_ANAR_ASP;
		PHY_WRITE(sc, BRGPHY_MII_ANAR, anar);
		ktcr = BRGPHY_1000CTL_AFD | BRGPHY_1000CTL_AHD;
		if (sc->mii_mpd_model == MII_MODEL_BROADCOM_BCM5701)
			ktcr |= BRGPHY_1000CTL_MSE | BRGPHY_1000CTL_MSC;
		PHY_WRITE(sc, BRGPHY_MII_1000CTL, ktcr);
		PHY_READ(sc, BRGPHY_MII_1000CTL);
	} else {
		anar = BRGPHY_SERDES_ANAR_FDX | BRGPHY_SERDES_ANAR_HDX;
		if ((media & IFM_FLOW) != 0 ||
		    (sc->mii_flags & MIIF_FORCEPAUSE) != 0)
			anar |= BRGPHY_SERDES_ANAR_BOTH_PAUSE;
		PHY_WRITE(sc, BRGPHY_SERDES_ANAR, anar);
	}

	PHY_WRITE(sc, BRGPHY_MII_BMCR, BRGPHY_BMCR_AUTOEN |
	    BRGPHY_BMCR_STARTNEG);
	PHY_WRITE(sc, BRGPHY_MII_IMR, 0xFF00);
}
Beispiel #7
0
static void
nsphy_reset(struct mii_softc *sc)
{
	int anar;

	mii_phy_reset(sc);
	anar = PHY_READ(sc, MII_ANAR);
	anar |= BMSR_MEDIA_TO_ANAR(PHY_READ(sc, MII_BMSR));
	PHY_WRITE(sc, MII_ANAR, anar);
}
Beispiel #8
0
static void
smcphy_auto(struct mii_softc *sc, int media)
{
	uint16_t	anar;

	anar = BMSR_MEDIA_TO_ANAR(sc->mii_capabilities) | ANAR_CSMA;
	if ((media & IFM_FLOW) != 0 || (sc->mii_flags & MIIF_FORCEPAUSE) != 0)
		anar |= ANAR_FC;
	PHY_WRITE(sc, MII_ANAR, anar);
	/* Apparently this helps. */
	anar = PHY_READ(sc, MII_ANAR);
	PHY_WRITE(sc, MII_BMCR, BMCR_AUTOEN | BMCR_STARTNEG);
}
Beispiel #9
0
static int
atphy_auto(struct mii_softc *sc)
{
	uint16_t anar;

	anar = BMSR_MEDIA_TO_ANAR(sc->mii_capabilities);
	PHY_WRITE(sc, MII_ANAR, anar | (3 << 10) | ANAR_CSMA);
	if ((sc->mii_extcapabilities & (EXTSR_1000TFDX | EXTSR_1000THDX)) != 0)
		PHY_WRITE(sc, MII_100T2CR, GTCR_ADV_1000TFDX |
		    GTCR_ADV_1000THDX);
	PHY_WRITE(sc, MII_BMCR, BMCR_RESET | BMCR_AUTOEN | BMCR_STARTNEG);

	return (EJUSTRETURN);
}
Beispiel #10
0
int
mii_phy_auto(struct mii_softc *sc)
{
	struct ifmedia_entry *ife = sc->mii_pdata->mii_media.ifm_cur;
	int anar, gtcr;

	/*
	 * Check for 1000BASE-X.  Autonegotiation is a bit
	 * different on such devices.
	 */
	if ((sc->mii_flags & MIIF_IS_1000X) != 0) {
		anar = 0;
		if ((sc->mii_extcapabilities & EXTSR_1000XFDX) != 0)
			anar |= ANAR_X_FD;
		if ((sc->mii_extcapabilities & EXTSR_1000XHDX) != 0)
			anar |= ANAR_X_HD;

		if ((ife->ifm_media & IFM_FLOW) != 0 ||
		    (sc->mii_flags & MIIF_FORCEPAUSE) != 0)
			anar |= ANAR_X_PAUSE_TOWARDS;
		PHY_WRITE(sc, MII_ANAR, anar);
	} else {
		anar = BMSR_MEDIA_TO_ANAR(sc->mii_capabilities) |
		    ANAR_CSMA;
		if ((ife->ifm_media & IFM_FLOW) != 0 ||
		    (sc->mii_flags & MIIF_FORCEPAUSE) != 0) {
			if ((sc->mii_capabilities &
			    (BMSR_10TFDX | BMSR_100TXFDX)) != 0)
				anar |= ANAR_FC;
			/* XXX Only 1000BASE-T has PAUSE_ASYM? */
			if (((sc->mii_flags & MIIF_HAVE_GTCR) != 0) &&
			    (sc->mii_extcapabilities &
			    (EXTSR_1000THDX | EXTSR_1000TFDX)) != 0)
				anar |= ANAR_X_PAUSE_ASYM;
		}
		PHY_WRITE(sc, MII_ANAR, anar);
		if ((sc->mii_flags & MIIF_HAVE_GTCR) != 0) {
			gtcr = 0;
			if ((sc->mii_extcapabilities & EXTSR_1000TFDX) != 0)
				gtcr |= GTCR_ADV_1000TFDX;
			if ((sc->mii_extcapabilities & EXTSR_1000THDX) != 0)
				gtcr |= GTCR_ADV_1000THDX;
			PHY_WRITE(sc, MII_100T2CR, gtcr);
		}
	}
	PHY_WRITE(sc, MII_BMCR, BMCR_AUTOEN | BMCR_STARTNEG);
	return (EJUSTRETURN);
}
Beispiel #11
0
int
atphy_mii_phy_auto(struct mii_softc *sc)
{
	uint16_t anar;

	anar = BMSR_MEDIA_TO_ANAR(sc->mii_capabilities) | ANAR_CSMA;
	if (sc->mii_flags & MIIF_DOPAUSE)
		anar |= ANAR_PAUSE_TOWARDS;
	PHY_WRITE(sc, MII_ANAR, anar);
	if (sc->mii_extcapabilities & (EXTSR_1000TFDX | EXTSR_1000THDX))
		PHY_WRITE(sc, MII_100T2CR, GTCR_ADV_1000TFDX |
		    GTCR_ADV_1000THDX);
	PHY_WRITE(sc, MII_BMCR, BMCR_RESET | BMCR_AUTOEN | BMCR_STARTNEG);

	return (EJUSTRETURN);
}
Beispiel #12
0
int
mii_phy_auto(struct mii_softc *sc)
{

	/*
	 * 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;
		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);
	return (EJUSTRETURN);
}
Beispiel #13
0
static int
rgephy_mii_phy_auto(struct mii_softc *mii)
{

	rgephy_loop(mii);
	rgephy_reset(mii);

	PHY_WRITE(mii, RGEPHY_MII_ANAR,
	    BMSR_MEDIA_TO_ANAR(mii->mii_capabilities) | ANAR_CSMA);
	DELAY(1000);
	PHY_WRITE(mii, RGEPHY_MII_1000CTL,
            RGEPHY_1000CTL_AHD|RGEPHY_1000CTL_AFD);
	DELAY(1000);
	PHY_WRITE(mii, RGEPHY_MII_BMCR,
	    RGEPHY_BMCR_AUTOEN | RGEPHY_BMCR_STARTNEG);
	DELAY(100);

	return (EJUSTRETURN);
}
Beispiel #14
0
static void
brgphy_mii_phy_auto(struct mii_softc *sc)
{
	int ktcr;

	brgphy_reset(sc);

	PHY_WRITE(sc, BRGPHY_MII_ANAR,
	    BMSR_MEDIA_TO_ANAR(sc->mii_capabilities) | ANAR_CSMA);
	DELAY(1000);

	ktcr = BRGPHY_1000CTL_AFD|BRGPHY_1000CTL_AHD;
	if (sc->mii_model == MII_MODEL_xxBROADCOM_BCM5701)
		ktcr |= BRGPHY_1000CTL_MSE|BRGPHY_1000CTL_MSC;
	PHY_WRITE(sc, BRGPHY_MII_1000CTL, ktcr);
	ktcr = PHY_READ(sc, BRGPHY_MII_1000CTL);
	DELAY(1000);

	PHY_WRITE(sc, BRGPHY_MII_BMCR,
	    BRGPHY_BMCR_AUTOEN | BRGPHY_BMCR_STARTNEG);
	PHY_WRITE(sc, BRGPHY_MII_IMR, 0xFF00);
}
Beispiel #15
0
static int
rgephy_mii_phy_auto(struct mii_softc *sc, int media)
{
	int anar;

	rgephy_loop(sc);
	PHY_RESET(sc);

	anar = BMSR_MEDIA_TO_ANAR(sc->mii_capabilities) | ANAR_CSMA;
	if ((media & IFM_FLOW) != 0 || (sc->mii_flags & MIIF_FORCEPAUSE) != 0)
		anar |= RGEPHY_ANAR_PC | RGEPHY_ANAR_ASP;
	PHY_WRITE(sc, RGEPHY_MII_ANAR, anar);
	DELAY(1000);
	PHY_WRITE(sc, RGEPHY_MII_1000CTL,
	    RGEPHY_1000CTL_AHD | RGEPHY_1000CTL_AFD);
	DELAY(1000);
	PHY_WRITE(sc, RGEPHY_MII_BMCR,
	    RGEPHY_BMCR_AUTOEN | RGEPHY_BMCR_STARTNEG);
	DELAY(100);

	return (EJUSTRETURN);
}
Beispiel #16
0
int
brgphy_mii_phy_auto(struct mii_softc *sc)
{
	int anar, ktcr = 0;

	sc->mii_ticks = 0;
	brgphy_loop(sc);
	PHY_RESET(sc);

	ktcr = GTCR_ADV_1000TFDX | GTCR_ADV_1000THDX;
	if ((sc->mii_mpd_oui == MII_OUI_BROADCOM)
	    && (sc->mii_mpd_model == MII_MODEL_BROADCOM_BCM5701))
		ktcr |= GTCR_MAN_MS | GTCR_ADV_MS;
	PHY_WRITE(sc, MII_100T2CR, ktcr);
	ktcr = PHY_READ(sc, MII_100T2CR);
	DELAY(1000);

	if (sc->mii_flags & MIIF_HAVEFIBER) {
		anar = ANAR_X_FD | ANAR_X_HD;
		if (sc->mii_flags & MIIF_DOPAUSE)
			anar |= BRGPHY_SERDES_ANAR_BOTH_PAUSE;
	} else {
		anar = BMSR_MEDIA_TO_ANAR(sc->mii_capabilities) | ANAR_CSMA;
		if (sc->mii_flags & MIIF_DOPAUSE)
			anar |= ANAR_FC | ANAR_PAUSE_ASYM;
	}
	PHY_WRITE(sc, MII_ANAR, anar);
	DELAY(1000);

	/* Start autonegotiation */
	PHY_WRITE(sc, MII_BMCR,
	    BMCR_AUTOEN | BMCR_STARTNEG);
	PHY_WRITE(sc, BRGPHY_MII_IMR, 0xFF00);

	return (EJUSTRETURN);
}
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) {