e1000phy.c revision 84145
175353Smjacob/* $FreeBSD: head/sys/dev/mii/e1000phy.c 84145 2001-09-29 19:18:52Z jlemon $ */
275353Smjacob/*
375353Smjacob * Principal Author: Parag Patel
475353Smjacob * Copyright (c) 2001
575353Smjacob * All rights reserved.
675353Smjacob *
775353Smjacob * Redistribution and use in source and binary forms, with or without
875353Smjacob * modification, are permitted provided that the following conditions
975353Smjacob * are met:
1075353Smjacob * 1. Redistributions of source code must retain the above copyright
1175353Smjacob *    notice unmodified, this list of conditions, and the following
1275353Smjacob *    disclaimer.
1375353Smjacob * 2. Redistributions in binary form must reproduce the above copyright
1475353Smjacob *    notice, this list of conditions and the following disclaimer in the
1575353Smjacob *    documentation and/or other materials provided with the distribution.
1675353Smjacob *
1775353Smjacob * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1875353Smjacob * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1975353Smjacob * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2075353Smjacob * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2175353Smjacob * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2275353Smjacob * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2375353Smjacob * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2475353Smjacob * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2575353Smjacob * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2675353Smjacob * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2775353Smjacob * SUCH DAMAGE.
2875353Smjacob *
2975353Smjacob * Additonal Copyright (c) 2001 by Traakan Software under same licence.
3075353Smjacob * Secondary Author: Matthew Jacob
3175353Smjacob */
3275353Smjacob
3375353Smjacob/*
3475353Smjacob * driver for the Marvell 88E1000 series external 1000/100/10-BT PHY.
3575353Smjacob */
3675353Smjacob
3775353Smjacob#include <sys/param.h>
3875353Smjacob#include <sys/systm.h>
3975353Smjacob#include <sys/kernel.h>
4075353Smjacob#include <sys/malloc.h>
4175353Smjacob#include <sys/socket.h>
4275353Smjacob#include <sys/bus.h>
4375353Smjacob
4475353Smjacob#include <machine/clock.h>
4575353Smjacob
4675353Smjacob#include <net/if.h>
4775353Smjacob#include <net/if_media.h>
4875353Smjacob
4975353Smjacob#include <dev/mii/mii.h>
5075353Smjacob#include <dev/mii/miivar.h>
5175353Smjacob#include <dev/mii/miidevs.h>
5275353Smjacob
5375353Smjacob#include <dev/mii/e1000phyreg.h>
5475353Smjacob
5575353Smjacob#include "miibus_if.h"
5675353Smjacob
5775353Smjacobstatic int e1000phy_probe(device_t);
5875353Smjacobstatic int e1000phy_attach(device_t);
5975353Smjacobstatic int e1000phy_detach(device_t);
6075353Smjacob
6175353Smjacobstatic device_method_t e1000phy_methods[] = {
6275353Smjacob	/* device interface */
6375353Smjacob	DEVMETHOD(device_probe,		e1000phy_probe),
6475353Smjacob	DEVMETHOD(device_attach,	e1000phy_attach),
6575353Smjacob	DEVMETHOD(device_detach,	e1000phy_detach),
6675353Smjacob	DEVMETHOD(device_shutdown,	bus_generic_shutdown),
6775353Smjacob	{ 0, 0 }
6875353Smjacob};
6975353Smjacob
7075353Smjacobstatic devclass_t e1000phy_devclass;
7175353Smjacobstatic driver_t e1000phy_driver = {
7275353Smjacob	"e1000phy", e1000phy_methods, sizeof (struct mii_softc)
7375353Smjacob};
7475353SmjacobDRIVER_MODULE(e1000phy, miibus, e1000phy_driver, e1000phy_devclass, 0, 0);
7575353Smjacob
7684145Sjlemonstatic int	e1000phy_service(struct mii_softc *, struct mii_data *, int);
7784145Sjlemonstatic void	e1000phy_status(struct mii_softc *);
7884145Sjlemonstatic void	e1000phy_reset(struct mii_softc *);
7984145Sjlemonstatic int	e1000phy_mii_phy_auto(struct mii_softc *, int);
8075353Smjacob
8175353Smjacobextern void	mii_phy_auto_timeout(void *);
8275353Smjacob
8375353Smjacobstatic int e1000phy_debug = 0;
8475353Smjacob
8575353Smjacobstatic int
8675353Smjacobe1000phy_probe(device_t	dev)
8775353Smjacob{
8875353Smjacob	struct mii_attach_args *ma;
8975353Smjacob	u_int32_t id;
9075353Smjacob
9175353Smjacob	ma = device_get_ivars(dev);
9275353Smjacob	id = ((ma->mii_id1 << 16) | ma->mii_id2) & E1000_ID_MASK;
9375353Smjacob
9475353Smjacob	if (id != E1000_ID_88E1000 && id != E1000_ID_88E1000S) {
9575353Smjacob		return ENXIO;
9675353Smjacob	}
9775353Smjacob
9875353Smjacob	device_set_desc(dev, MII_STR_MARVELL_E1000);
9975353Smjacob	return 0;
10075353Smjacob}
10175353Smjacob
10275353Smjacobstatic int
10375353Smjacobe1000phy_attach(device_t dev)
10475353Smjacob{
10575353Smjacob	struct mii_softc *sc;
10675353Smjacob	struct mii_attach_args *ma;
10775353Smjacob	struct mii_data *mii;
10875353Smjacob
10975353Smjacob	getenv_int("e1000phy_debug", &e1000phy_debug);
11075353Smjacob
11175353Smjacob	sc = device_get_softc(dev);
11275353Smjacob	ma = device_get_ivars(dev);
11375353Smjacob	sc->mii_dev = device_get_parent(dev);
11475353Smjacob	mii = device_get_softc(sc->mii_dev);
11575353Smjacob	LIST_INSERT_HEAD(&mii->mii_phys, sc, mii_list);
11675353Smjacob
11775353Smjacob	sc->mii_inst = mii->mii_instance;
11875353Smjacob	sc->mii_phy = ma->mii_phyno;
11975353Smjacob	sc->mii_service = e1000phy_service;
12075353Smjacob	sc->mii_pdata = mii;
12175353Smjacob
12275353Smjacob	sc->mii_flags |= MIIF_NOISOLATE;
12375353Smjacob	mii->mii_instance++;
12475353Smjacob	e1000phy_reset(sc);
12575353Smjacob
12684144Sjlemon	device_printf(dev, " ");
12784144Sjlemon
12875353Smjacob#define	ADD(m, c)	ifmedia_add(&mii->mii_media, (m), (c), NULL)
12984144Sjlemon/*
13075353Smjacob	ADD(IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, sc->mii_inst),
13175353Smjacob	    E1000_CR_ISOLATE);
13284144Sjlemon*/
13384144Sjlemon	ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, 0, sc->mii_inst),
13484144Sjlemon	    E1000_CR_SPEED_10);
13584144Sjlemon	printf("10baseT, ");
13684144Sjlemon	ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, IFM_FDX, sc->mii_inst),
13784144Sjlemon	    E1000_CR_SPEED_10 | E1000_CR_FULL_DUPLEX);
13884144Sjlemon	printf("10baseT-FDX, ");
13984144Sjlemon	ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, 0, sc->mii_inst),
14084144Sjlemon	    E1000_CR_SPEED_100);
14184144Sjlemon	printf("100baseTX, ");
14284144Sjlemon	ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_FDX, sc->mii_inst),
14384144Sjlemon	    E1000_CR_SPEED_100 | E1000_CR_FULL_DUPLEX);
14484144Sjlemon	printf("100baseTX-FDX, ");
14575353Smjacob	/*
14684144Sjlemon	 * 1000BT-simplex not supported; driver must ignore this entry,
14784144Sjlemon	 * but it must be present in order to manually set full-duplex.
14884144Sjlemon	 */
14975353Smjacob	ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_TX, 0, sc->mii_inst),
15084144Sjlemon	    E1000_CR_SPEED_1000);
15184144Sjlemon	ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_TX, IFM_FDX, sc->mii_inst),
15284144Sjlemon	    E1000_CR_SPEED_1000 | E1000_CR_FULL_DUPLEX);
15384144Sjlemon	printf("1000baseTX-FDX, ");
15475353Smjacob	ADD(IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, 0, sc->mii_inst), 0);
15584144Sjlemon	printf("auto\n");
15675353Smjacob#undef ADD
15775353Smjacob
15875353Smjacob	MIIBUS_MEDIAINIT(sc->mii_dev);
15975353Smjacob	return(0);
16075353Smjacob}
16175353Smjacob
16275353Smjacobstatic int
16375353Smjacobe1000phy_detach(device_t dev)
16475353Smjacob{
16575353Smjacob	struct mii_softc *sc;
16675353Smjacob	struct mii_data *mii;
16775353Smjacob
16875353Smjacob	sc = device_get_softc(dev);
16975353Smjacob	mii = device_get_softc(device_get_parent(dev));
17075353Smjacob
17175353Smjacob	if (sc->mii_flags & MIIF_DOINGAUTO)
17275353Smjacob		untimeout(mii_phy_auto_timeout, sc, sc->mii_auto_ch);
17375353Smjacob
17475353Smjacob	sc->mii_dev = NULL;
17575353Smjacob	LIST_REMOVE(sc, mii_list);
17675353Smjacob
17775353Smjacob	return 0;
17875353Smjacob}
17975353Smjacob
18075353Smjacobstatic void
18175353Smjacobe1000phy_reset(struct mii_softc *sc)
18275353Smjacob{
18375353Smjacob	u_int32_t reg;
18475353Smjacob	int i;
18575353Smjacob
18675353Smjacob	/* initialize custom E1000 registers to magic values */
18775353Smjacob	reg = PHY_READ(sc, E1000_SCR);
18875353Smjacob	reg &= ~E1000_SCR_AUTO_X_MODE;
18975353Smjacob	PHY_WRITE(sc, E1000_SCR, reg);
19075353Smjacob
19175353Smjacob	/* normal PHY reset */
19275353Smjacob	/*mii_phy_reset(sc);*/
19375353Smjacob	reg = PHY_READ(sc, E1000_CR);
19475353Smjacob	reg |= E1000_CR_RESET;
19575353Smjacob	PHY_WRITE(sc, E1000_CR, reg);
19675353Smjacob
19775353Smjacob	for (i = 0; i < 500; i++) {
19875353Smjacob		DELAY(1);
19975353Smjacob		reg = PHY_READ(sc, E1000_CR);
20075353Smjacob		if (!(reg & E1000_CR_RESET))
20175353Smjacob			break;
20275353Smjacob	}
20375353Smjacob
20475353Smjacob	/* set more custom E1000 registers to magic values */
20575353Smjacob	reg = PHY_READ(sc, E1000_SCR);
20675353Smjacob	reg |= E1000_SCR_ASSERT_CRS_ON_TX;
20775353Smjacob	PHY_WRITE(sc, E1000_SCR, reg);
20875353Smjacob
20975353Smjacob	reg = PHY_READ(sc, E1000_ESCR);
21075353Smjacob	reg |= E1000_ESCR_TX_CLK_25;
21175353Smjacob	PHY_WRITE(sc, E1000_ESCR, reg);
21275353Smjacob
21375353Smjacob	/* even more magic to reset DSP? */
21475353Smjacob	PHY_WRITE(sc, 29, 0x1d);
21575353Smjacob	PHY_WRITE(sc, 30, 0xc1);
21675353Smjacob	PHY_WRITE(sc, 30, 0x00);
21775353Smjacob}
21875353Smjacob
21984145Sjlemonstatic int
22075353Smjacobe1000phy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
22175353Smjacob{
22275353Smjacob	struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
22375353Smjacob	int reg;
22475353Smjacob
22575353Smjacob	switch (cmd) {
22675353Smjacob	case MII_POLLSTAT:
22775353Smjacob		/*
22875353Smjacob		 * If we're not polling our PHY instance, just return.
22975353Smjacob		 */
23075353Smjacob		if (IFM_INST(ife->ifm_media) != sc->mii_inst)
23175353Smjacob			return (0);
23275353Smjacob		break;
23375353Smjacob
23475353Smjacob	case MII_MEDIACHG:
23575353Smjacob		/*
23675353Smjacob		 * If the media indicates a different PHY instance,
23775353Smjacob		 * isolate ourselves.
23875353Smjacob		 */
23975353Smjacob		if (IFM_INST(ife->ifm_media) != sc->mii_inst) {
24075353Smjacob			reg = PHY_READ(sc, E1000_CR);
24175353Smjacob			PHY_WRITE(sc, E1000_CR, reg | E1000_CR_ISOLATE);
24275353Smjacob			return (0);
24375353Smjacob		}
24475353Smjacob
24575353Smjacob		/*
24675353Smjacob		 * If the interface is not up, don't do anything.
24775353Smjacob		 */
24875353Smjacob		if ((mii->mii_ifp->if_flags & IFF_UP) == 0) {
24975353Smjacob			break;
25075353Smjacob		}
25175353Smjacob
25275353Smjacob		switch (IFM_SUBTYPE(ife->ifm_media)) {
25375353Smjacob		case IFM_AUTO:
25475353Smjacob			/*
25575353Smjacob			 * If we're already in auto mode, just return.
25675353Smjacob			 */
25775353Smjacob			if (sc->mii_flags & MIIF_DOINGAUTO) {
25875353Smjacob				return (0);
25975353Smjacob			}
26075353Smjacob			e1000phy_reset(sc);
26175353Smjacob			(void)e1000phy_mii_phy_auto(sc, 1);
26275353Smjacob			break;
26375353Smjacob
26475353Smjacob		case IFM_1000_TX:
26575353Smjacob			if (sc->mii_flags & MIIF_DOINGAUTO)
26675353Smjacob				return (0);
26775353Smjacob
26875353Smjacob			e1000phy_reset(sc);
26975353Smjacob
27075353Smjacob			/* TODO - any other way to force 1000BT? */
27175353Smjacob			(void)e1000phy_mii_phy_auto(sc, 1);
27275353Smjacob			break;
27375353Smjacob
27475353Smjacob		case IFM_100_TX:
27575353Smjacob			e1000phy_reset(sc);
27675353Smjacob
27775353Smjacob			if ((ife->ifm_media & IFM_GMASK) == IFM_FDX) {
27875353Smjacob				PHY_WRITE(sc, E1000_CR,
27975353Smjacob				    E1000_CR_FULL_DUPLEX | E1000_CR_SPEED_100);
28075353Smjacob				PHY_WRITE(sc, E1000_AR, E1000_AR_100TX_FD);
28175353Smjacob			} else {
28275353Smjacob				PHY_WRITE(sc, E1000_CR, E1000_CR_SPEED_100);
28375353Smjacob				PHY_WRITE(sc, E1000_AR, E1000_AR_100TX);
28475353Smjacob			}
28575353Smjacob			break;
28675353Smjacob
28775353Smjacob		case IFM_10_T:
28875353Smjacob			e1000phy_reset(sc);
28975353Smjacob
29075353Smjacob			if ((ife->ifm_media & IFM_GMASK) == IFM_FDX) {
29175353Smjacob				PHY_WRITE(sc, E1000_CR,
29275353Smjacob				    E1000_CR_FULL_DUPLEX | E1000_CR_SPEED_10);
29375353Smjacob				PHY_WRITE(sc, E1000_AR, E1000_AR_10T_FD);
29475353Smjacob			} else {
29575353Smjacob				PHY_WRITE(sc, E1000_CR, E1000_CR_SPEED_10);
29675353Smjacob				PHY_WRITE(sc, E1000_AR, E1000_AR_10T);
29775353Smjacob			}
29875353Smjacob
29975353Smjacob			break;
30075353Smjacob
30175353Smjacob		default:
30275353Smjacob			return (EINVAL);
30375353Smjacob		}
30475353Smjacob
30575353Smjacob		break;
30675353Smjacob
30775353Smjacob	case MII_TICK:
30875353Smjacob		/*
30975353Smjacob		 * If we're not currently selected, just return.
31075353Smjacob		 */
31175353Smjacob		if (IFM_INST(ife->ifm_media) != sc->mii_inst) {
31275353Smjacob			return (0);
31375353Smjacob		}
31475353Smjacob
31575353Smjacob		/*
31684145Sjlemon		 * Is the interface even up?
31775353Smjacob		 */
31884145Sjlemon		if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
31975353Smjacob			return (0);
32075353Smjacob
32175353Smjacob		/*
32284145Sjlemon		 * Only used for autonegotiation.
32375353Smjacob		 */
32484145Sjlemon		if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO)
32584145Sjlemon			break;
32675353Smjacob
32775353Smjacob		/*
32884145Sjlemon		 * check for link.
32984145Sjlemon		 * Read the status register twice; BMSR_LINK is latch-low.
33075353Smjacob		 */
33184145Sjlemon		reg = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR);
33284145Sjlemon		if (reg & BMSR_LINK)
33384145Sjlemon			break;
33475353Smjacob
33575353Smjacob		/*
33684145Sjlemon		 * Only retry autonegotiation every 5 seconds.
33775353Smjacob		 */
33884145Sjlemon		if (++sc->mii_ticks != 5)
33984145Sjlemon			return (0);
34075353Smjacob
34184145Sjlemon		sc->mii_ticks = 0;
34275353Smjacob		e1000phy_reset(sc);
34384145Sjlemon		if (e1000phy_mii_phy_auto(sc, 0) == EJUSTRETURN)
34484145Sjlemon			return (0);
34575353Smjacob		break;
34675353Smjacob	}
34775353Smjacob
34875353Smjacob	/* Update the media status. */
34975353Smjacob	e1000phy_status(sc);
35075353Smjacob
35175353Smjacob	/* Callback if something changed. */
35284145Sjlemon	mii_phy_update(sc, cmd);
35375353Smjacob	return (0);
35475353Smjacob}
35575353Smjacob
35684145Sjlemonstatic void
35775353Smjacobe1000phy_status(struct mii_softc *sc)
35875353Smjacob{
35975353Smjacob	struct mii_data *mii = sc->mii_pdata;
36075353Smjacob	int bmsr, bmcr, esr, ssr, isr, ar, lpar;
36175353Smjacob
36275353Smjacob	mii->mii_media_status = IFM_AVALID;
36375353Smjacob	mii->mii_media_active = IFM_ETHER;
36475353Smjacob
36575353Smjacob	bmsr = PHY_READ(sc, E1000_SR) | PHY_READ(sc, E1000_SR);
36675353Smjacob	esr = PHY_READ(sc, E1000_ESR);
36775353Smjacob	bmcr = PHY_READ(sc, E1000_CR);
36875353Smjacob	ssr = PHY_READ(sc, E1000_SSR);
36975353Smjacob	isr = PHY_READ(sc, E1000_ISR);
37075353Smjacob	ar = PHY_READ(sc, E1000_AR);
37175353Smjacob	lpar = PHY_READ(sc, E1000_LPAR);
37275353Smjacob
37375353Smjacob	if (bmsr & E1000_SR_LINK_STATUS)
37475353Smjacob		mii->mii_media_status |= IFM_ACTIVE;
37575353Smjacob
37675353Smjacob	if (bmcr & E1000_CR_LOOPBACK)
37775353Smjacob		mii->mii_media_active |= IFM_LOOP;
37875353Smjacob
37975353Smjacob	if ((sc->mii_flags & MIIF_DOINGAUTO) &&
38075353Smjacob	    (!(bmsr & E1000_SR_AUTO_NEG_COMPLETE) || !(ssr & E1000_SSR_LINK) ||
38175353Smjacob	    !(ssr & E1000_SSR_SPD_DPLX_RESOLVED))) {
38275353Smjacob		/* Erg, still trying, I guess... */
38375353Smjacob		mii->mii_media_active |= IFM_NONE;
38475353Smjacob		return;
38575353Smjacob	}
38675353Smjacob
38775353Smjacob	if (ssr & E1000_SSR_1000MBS)
38875353Smjacob		mii->mii_media_active |= IFM_1000_TX;
38975353Smjacob	else if (ssr & E1000_SSR_100MBS)
39075353Smjacob		mii->mii_media_active |= IFM_100_TX;
39175353Smjacob	else
39275353Smjacob		mii->mii_media_active |= IFM_10_T;
39375353Smjacob
39475353Smjacob	if (ssr & E1000_SSR_DUPLEX)
39575353Smjacob		mii->mii_media_active |= IFM_FDX;
39675353Smjacob	else
39775353Smjacob		mii->mii_media_active |= IFM_HDX;
39875353Smjacob
39975353Smjacob	/* FLAG0==rx-flow-control FLAG1==tx-flow-control */
40075353Smjacob	if ((ar & E1000_AR_PAUSE) && (lpar & E1000_LPAR_PAUSE)) {
40175353Smjacob		mii->mii_media_active |= IFM_FLAG0 | IFM_FLAG1;
40275353Smjacob	} else if (!(ar & E1000_AR_PAUSE) && (ar & E1000_AR_ASM_DIR) &&
40375353Smjacob	    (lpar & E1000_LPAR_PAUSE) && (lpar & E1000_LPAR_ASM_DIR)) {
40475353Smjacob		mii->mii_media_active |= IFM_FLAG1;
40575353Smjacob	} else if ((ar & E1000_AR_PAUSE) && (ar & E1000_AR_ASM_DIR) &&
40675353Smjacob	    !(lpar & E1000_LPAR_PAUSE) && (lpar & E1000_LPAR_ASM_DIR)) {
40775353Smjacob		mii->mii_media_active |= IFM_FLAG0;
40875353Smjacob	}
40975353Smjacob}
41075353Smjacob
41175353Smjacobstatic int
41275353Smjacobe1000phy_mii_phy_auto(struct mii_softc *mii, int waitfor)
41375353Smjacob{
41475353Smjacob	int bmsr, i;
41575353Smjacob
41675353Smjacob	if ((mii->mii_flags & MIIF_DOINGAUTO) == 0) {
41775353Smjacob		PHY_WRITE(mii, E1000_AR, E1000_AR_10T | E1000_AR_10T_FD |
41875353Smjacob		    E1000_AR_100TX | E1000_AR_100TX_FD |
41975353Smjacob		    E1000_AR_PAUSE | E1000_AR_ASM_DIR);
42075353Smjacob		PHY_WRITE(mii, E1000_1GCR, E1000_1GCR_1000T_FD);
42175353Smjacob		PHY_WRITE(mii, E1000_CR,
42275353Smjacob		    E1000_CR_AUTO_NEG_ENABLE | E1000_CR_RESTART_AUTO_NEG);
42375353Smjacob	}
42475353Smjacob
42575353Smjacob	if (waitfor) {
42675353Smjacob		/* Wait 500ms for it to complete. */
42775353Smjacob		for (i = 0; i < 500; i++) {
42875353Smjacob			bmsr =
42975353Smjacob			    PHY_READ(mii, E1000_SR) | PHY_READ(mii, E1000_SR);
43075353Smjacob
43175353Smjacob			if (bmsr & E1000_SR_AUTO_NEG_COMPLETE) {
43275353Smjacob				return (0);
43375353Smjacob			}
43475353Smjacob			DELAY(1000);
43575353Smjacob		}
43675353Smjacob
43775353Smjacob		/*
43875353Smjacob		 * Don't need to worry about clearing MIIF_DOINGAUTO.
43975353Smjacob		 * If that's set, a timeout is pending, and it will
44075353Smjacob		 * clear the flag. [do it anyway]
44175353Smjacob		 */
44275353Smjacob	}
44375353Smjacob
44475353Smjacob	/*
44575353Smjacob	 * Just let it finish asynchronously.  This is for the benefit of
44675353Smjacob	 * the tick handler driving autonegotiation.  Don't want 500ms
44775353Smjacob	 * delays all the time while the system is running!
44875353Smjacob	 */
44975353Smjacob	if ((mii->mii_flags & MIIF_DOINGAUTO) == 0) {
45075353Smjacob		mii->mii_flags |= MIIF_DOINGAUTO;
45175353Smjacob		mii->mii_ticks = 0;
45275353Smjacob		mii->mii_auto_ch = timeout(mii_phy_auto_timeout, mii, hz >> 1);
45375353Smjacob	}
45475353Smjacob	return (EJUSTRETURN);
45575353Smjacob}
456