e1000phy.c revision 120281
175353Smjacob/*
2119418Sobrien
3119418Sobrien#include <sys/cdefs.h>
4119418Sobrien__FBSDID("$FreeBSD: head/sys/dev/mii/e1000phy.c 120281 2003-09-20 10:53:08Z wilko $");
575353Smjacob * Principal Author: Parag Patel
675353Smjacob * Copyright (c) 2001
775353Smjacob * All rights reserved.
875353Smjacob *
975353Smjacob * Redistribution and use in source and binary forms, with or without
1075353Smjacob * modification, are permitted provided that the following conditions
1175353Smjacob * are met:
1275353Smjacob * 1. Redistributions of source code must retain the above copyright
1375353Smjacob *    notice unmodified, this list of conditions, and the following
1475353Smjacob *    disclaimer.
1575353Smjacob * 2. Redistributions in binary form must reproduce the above copyright
1675353Smjacob *    notice, this list of conditions and the following disclaimer in the
1775353Smjacob *    documentation and/or other materials provided with the distribution.
1875353Smjacob *
1975353Smjacob * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
2075353Smjacob * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2175353Smjacob * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2275353Smjacob * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2375353Smjacob * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2475353Smjacob * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2575353Smjacob * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2675353Smjacob * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2775353Smjacob * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2875353Smjacob * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2975353Smjacob * SUCH DAMAGE.
3075353Smjacob *
3175353Smjacob * Additonal Copyright (c) 2001 by Traakan Software under same licence.
3275353Smjacob * Secondary Author: Matthew Jacob
3375353Smjacob */
3475353Smjacob
3575353Smjacob/*
3675353Smjacob * driver for the Marvell 88E1000 series external 1000/100/10-BT PHY.
3775353Smjacob */
3875353Smjacob
39120281Swilko/*
40120281Swilko * Support added for the Marvell 88E1011 (Alaska) 1000/100/10baseTX and
41120281Swilko * 1000baseSX PHY.
42120281Swilko * Nathan Binkert <nate@openbsd.org>
43120281Swilko * Jung-uk Kim <jkim@niksun.com>
44120281Swilko */
45120281Swilko
4675353Smjacob#include <sys/param.h>
4775353Smjacob#include <sys/systm.h>
4875353Smjacob#include <sys/kernel.h>
4975353Smjacob#include <sys/socket.h>
5075353Smjacob#include <sys/bus.h>
5175353Smjacob
5275353Smjacob#include <machine/clock.h>
5375353Smjacob
5475353Smjacob#include <net/if.h>
5575353Smjacob#include <net/if_media.h>
5675353Smjacob
5775353Smjacob#include <dev/mii/mii.h>
5875353Smjacob#include <dev/mii/miivar.h>
59109514Sobrien#include "miidevs.h"
6075353Smjacob
6175353Smjacob#include <dev/mii/e1000phyreg.h>
6275353Smjacob
6375353Smjacob#include "miibus_if.h"
6475353Smjacob
6575353Smjacobstatic int e1000phy_probe(device_t);
6675353Smjacobstatic int e1000phy_attach(device_t);
6775353Smjacob
6875353Smjacobstatic device_method_t e1000phy_methods[] = {
6975353Smjacob	/* device interface */
7075353Smjacob	DEVMETHOD(device_probe,		e1000phy_probe),
7175353Smjacob	DEVMETHOD(device_attach,	e1000phy_attach),
7295722Sphk	DEVMETHOD(device_detach,	mii_phy_detach),
7375353Smjacob	DEVMETHOD(device_shutdown,	bus_generic_shutdown),
7475353Smjacob	{ 0, 0 }
7575353Smjacob};
7675353Smjacob
7775353Smjacobstatic devclass_t e1000phy_devclass;
7875353Smjacobstatic driver_t e1000phy_driver = {
7975353Smjacob	"e1000phy", e1000phy_methods, sizeof (struct mii_softc)
8075353Smjacob};
8175353SmjacobDRIVER_MODULE(e1000phy, miibus, e1000phy_driver, e1000phy_devclass, 0, 0);
8275353Smjacob
8384145Sjlemonstatic int	e1000phy_service(struct mii_softc *, struct mii_data *, int);
8484145Sjlemonstatic void	e1000phy_status(struct mii_softc *);
8584145Sjlemonstatic void	e1000phy_reset(struct mii_softc *);
8696026Sphkstatic int	e1000phy_mii_phy_auto(struct mii_softc *);
8775353Smjacob
8875353Smjacobstatic int e1000phy_debug = 0;
8975353Smjacob
9075353Smjacobstatic int
9175353Smjacobe1000phy_probe(device_t	dev)
9275353Smjacob{
9375353Smjacob	struct mii_attach_args *ma;
9475353Smjacob	u_int32_t id;
9575353Smjacob
9675353Smjacob	ma = device_get_ivars(dev);
9775353Smjacob	id = ((ma->mii_id1 << 16) | ma->mii_id2) & E1000_ID_MASK;
98120281Swilko	if (id != E1000_ID_88E1000
99120281Swilko	    && id != E1000_ID_88E1000S
100120281Swilko	    && id != E1000_ID_88E1011) {
10175353Smjacob		return ENXIO;
10275353Smjacob	}
10375353Smjacob
10475353Smjacob	device_set_desc(dev, MII_STR_MARVELL_E1000);
10575353Smjacob	return 0;
10675353Smjacob}
10775353Smjacob
10875353Smjacobstatic int
10975353Smjacobe1000phy_attach(device_t dev)
11075353Smjacob{
11175353Smjacob	struct mii_softc *sc;
11275353Smjacob	struct mii_attach_args *ma;
11375353Smjacob	struct mii_data *mii;
114120281Swilko	u_int32_t id;
11575353Smjacob
11675353Smjacob	getenv_int("e1000phy_debug", &e1000phy_debug);
11775353Smjacob
11875353Smjacob	sc = device_get_softc(dev);
11975353Smjacob	ma = device_get_ivars(dev);
12075353Smjacob	sc->mii_dev = device_get_parent(dev);
12175353Smjacob	mii = device_get_softc(sc->mii_dev);
12275353Smjacob	LIST_INSERT_HEAD(&mii->mii_phys, sc, mii_list);
12375353Smjacob
12475353Smjacob	sc->mii_inst = mii->mii_instance;
12575353Smjacob	sc->mii_phy = ma->mii_phyno;
12675353Smjacob	sc->mii_service = e1000phy_service;
12775353Smjacob	sc->mii_pdata = mii;
128120281Swilko	sc->mii_flags |= MIIF_NOISOLATE;
12975353Smjacob
130120281Swilko	id = ((ma->mii_id1 << 16) | ma->mii_id2) & E1000_ID_MASK;
131120281Swilko	if (id == E1000_ID_88E1011
132120281Swilko	    && (PHY_READ(sc, E1000_ESSR) & E1000_ESSR_FIBER_LINK))
133120281Swilko		sc->mii_flags |= MIIF_HAVEFIBER;
13475353Smjacob	mii->mii_instance++;
13575353Smjacob	e1000phy_reset(sc);
13675353Smjacob
13784144Sjlemon	device_printf(dev, " ");
13884144Sjlemon
13975353Smjacob#define	ADD(m, c)	ifmedia_add(&mii->mii_media, (m), (c), NULL)
140120281Swilko	if ((sc->mii_flags & MIIF_HAVEFIBER) == 0) {
141120281Swilko#if 0
142120281Swilko		ADD(IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, sc->mii_inst),
143120281Swilko		    E1000_CR_ISOLATE);
144120281Swilko#endif
145120281Swilko		ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, 0, sc->mii_inst),
146120281Swilko		    E1000_CR_SPEED_10);
147120281Swilko		printf("10baseT, ");
148120281Swilko		ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, IFM_FDX, sc->mii_inst),
149120281Swilko		    E1000_CR_SPEED_10 | E1000_CR_FULL_DUPLEX);
150120281Swilko		printf("10baseT-FDX, ");
151120281Swilko		ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, 0, sc->mii_inst),
152120281Swilko		    E1000_CR_SPEED_100);
153120281Swilko		printf("100baseTX, ");
154120281Swilko		ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_FDX, sc->mii_inst),
155120281Swilko		    E1000_CR_SPEED_100 | E1000_CR_FULL_DUPLEX);
156120281Swilko		printf("100baseTX-FDX, ");
157120281Swilko		/*
158120281Swilko		 * 1000BT-simplex not supported; driver must ignore this entry,
159120281Swilko		 * but it must be present in order to manually set full-duplex.
160120281Swilko		 */
161120281Swilko		ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T, 0, sc->mii_inst),
162120281Swilko		    E1000_CR_SPEED_1000);
163120281Swilko		ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T, IFM_FDX, sc->mii_inst),
164120281Swilko		    E1000_CR_SPEED_1000 | E1000_CR_FULL_DUPLEX);
165120281Swilko		printf("1000baseTX-FDX, ");
166120281Swilko	} else {
167120281Swilko		ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_SX, IFM_FDX, sc->mii_inst),
168120281Swilko		    E1000_CR_SPEED_1000 | E1000_CR_FULL_DUPLEX);
169120281Swilko		printf("1000baseSX-FDX, ");
170120281Swilko	}
17175353Smjacob	ADD(IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, 0, sc->mii_inst), 0);
17284144Sjlemon	printf("auto\n");
17375353Smjacob#undef ADD
17475353Smjacob
17575353Smjacob	MIIBUS_MEDIAINIT(sc->mii_dev);
17675353Smjacob	return(0);
17775353Smjacob}
17875353Smjacob
17975353Smjacobstatic void
18075353Smjacobe1000phy_reset(struct mii_softc *sc)
18175353Smjacob{
18275353Smjacob	u_int32_t reg;
18375353Smjacob	int i;
18475353Smjacob
18575353Smjacob	/* initialize custom E1000 registers to magic values */
18675353Smjacob	reg = PHY_READ(sc, E1000_SCR);
18775353Smjacob	reg &= ~E1000_SCR_AUTO_X_MODE;
18875353Smjacob	PHY_WRITE(sc, E1000_SCR, reg);
18975353Smjacob
19075353Smjacob	/* normal PHY reset */
19175353Smjacob	/*mii_phy_reset(sc);*/
19275353Smjacob	reg = PHY_READ(sc, E1000_CR);
19375353Smjacob	reg |= E1000_CR_RESET;
19475353Smjacob	PHY_WRITE(sc, E1000_CR, reg);
19575353Smjacob
19675353Smjacob	for (i = 0; i < 500; i++) {
19775353Smjacob		DELAY(1);
19875353Smjacob		reg = PHY_READ(sc, E1000_CR);
19975353Smjacob		if (!(reg & E1000_CR_RESET))
20075353Smjacob			break;
20175353Smjacob	}
20275353Smjacob
20375353Smjacob	/* set more custom E1000 registers to magic values */
20475353Smjacob	reg = PHY_READ(sc, E1000_SCR);
20575353Smjacob	reg |= E1000_SCR_ASSERT_CRS_ON_TX;
20675353Smjacob	PHY_WRITE(sc, E1000_SCR, reg);
20775353Smjacob
20875353Smjacob	reg = PHY_READ(sc, E1000_ESCR);
20975353Smjacob	reg |= E1000_ESCR_TX_CLK_25;
21075353Smjacob	PHY_WRITE(sc, E1000_ESCR, reg);
21175353Smjacob
21275353Smjacob	/* even more magic to reset DSP? */
21375353Smjacob	PHY_WRITE(sc, 29, 0x1d);
21475353Smjacob	PHY_WRITE(sc, 30, 0xc1);
21575353Smjacob	PHY_WRITE(sc, 30, 0x00);
21675353Smjacob}
21775353Smjacob
21884145Sjlemonstatic int
21975353Smjacobe1000phy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
22075353Smjacob{
22175353Smjacob	struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
22275353Smjacob	int reg;
22375353Smjacob
22475353Smjacob	switch (cmd) {
22575353Smjacob	case MII_POLLSTAT:
22675353Smjacob		/*
22775353Smjacob		 * If we're not polling our PHY instance, just return.
22875353Smjacob		 */
22975353Smjacob		if (IFM_INST(ife->ifm_media) != sc->mii_inst)
23075353Smjacob			return (0);
23175353Smjacob		break;
23275353Smjacob
23375353Smjacob	case MII_MEDIACHG:
23475353Smjacob		/*
23575353Smjacob		 * If the media indicates a different PHY instance,
23675353Smjacob		 * isolate ourselves.
23775353Smjacob		 */
23875353Smjacob		if (IFM_INST(ife->ifm_media) != sc->mii_inst) {
23975353Smjacob			reg = PHY_READ(sc, E1000_CR);
24075353Smjacob			PHY_WRITE(sc, E1000_CR, reg | E1000_CR_ISOLATE);
24175353Smjacob			return (0);
24275353Smjacob		}
24375353Smjacob
24475353Smjacob		/*
24575353Smjacob		 * If the interface is not up, don't do anything.
24675353Smjacob		 */
24775353Smjacob		if ((mii->mii_ifp->if_flags & IFF_UP) == 0) {
24875353Smjacob			break;
24975353Smjacob		}
25075353Smjacob
25175353Smjacob		switch (IFM_SUBTYPE(ife->ifm_media)) {
25275353Smjacob		case IFM_AUTO:
25375353Smjacob			e1000phy_reset(sc);
25496026Sphk			(void)e1000phy_mii_phy_auto(sc);
25575353Smjacob			break;
25675353Smjacob
25795673Sphk		case IFM_1000_T:
25875353Smjacob			e1000phy_reset(sc);
25975353Smjacob
26075353Smjacob			/* TODO - any other way to force 1000BT? */
26196026Sphk			(void)e1000phy_mii_phy_auto(sc);
26275353Smjacob			break;
26375353Smjacob
264120281Swilko		case IFM_1000_SX:
265120281Swilko			e1000phy_reset(sc);
266120281Swilko
267120281Swilko			PHY_WRITE(sc, E1000_CR,
268120281Swilko			    E1000_CR_FULL_DUPLEX | E1000_CR_SPEED_1000);
269120281Swilko			PHY_WRITE(sc, E1000_AR, E1000_FA_1000X_FD);
270120281Swilko			break;
271120281Swilko
27275353Smjacob		case IFM_100_TX:
27375353Smjacob			e1000phy_reset(sc);
27475353Smjacob
27575353Smjacob			if ((ife->ifm_media & IFM_GMASK) == IFM_FDX) {
27675353Smjacob				PHY_WRITE(sc, E1000_CR,
27775353Smjacob				    E1000_CR_FULL_DUPLEX | E1000_CR_SPEED_100);
27875353Smjacob				PHY_WRITE(sc, E1000_AR, E1000_AR_100TX_FD);
27975353Smjacob			} else {
28075353Smjacob				PHY_WRITE(sc, E1000_CR, E1000_CR_SPEED_100);
28175353Smjacob				PHY_WRITE(sc, E1000_AR, E1000_AR_100TX);
28275353Smjacob			}
28375353Smjacob			break;
28475353Smjacob
28575353Smjacob		case IFM_10_T:
28675353Smjacob			e1000phy_reset(sc);
28775353Smjacob
28875353Smjacob			if ((ife->ifm_media & IFM_GMASK) == IFM_FDX) {
28975353Smjacob				PHY_WRITE(sc, E1000_CR,
29075353Smjacob				    E1000_CR_FULL_DUPLEX | E1000_CR_SPEED_10);
29175353Smjacob				PHY_WRITE(sc, E1000_AR, E1000_AR_10T_FD);
29275353Smjacob			} else {
29375353Smjacob				PHY_WRITE(sc, E1000_CR, E1000_CR_SPEED_10);
29475353Smjacob				PHY_WRITE(sc, E1000_AR, E1000_AR_10T);
29575353Smjacob			}
29675353Smjacob
29775353Smjacob			break;
29875353Smjacob
29975353Smjacob		default:
30075353Smjacob			return (EINVAL);
30175353Smjacob		}
30275353Smjacob
30375353Smjacob		break;
30475353Smjacob
30575353Smjacob	case MII_TICK:
30675353Smjacob		/*
30775353Smjacob		 * If we're not currently selected, just return.
30875353Smjacob		 */
30975353Smjacob		if (IFM_INST(ife->ifm_media) != sc->mii_inst) {
31075353Smjacob			return (0);
31175353Smjacob		}
31275353Smjacob
31375353Smjacob		/*
31484145Sjlemon		 * Is the interface even up?
31575353Smjacob		 */
31684145Sjlemon		if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
31775353Smjacob			return (0);
31875353Smjacob
31975353Smjacob		/*
32084145Sjlemon		 * Only used for autonegotiation.
32175353Smjacob		 */
32284145Sjlemon		if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO)
32384145Sjlemon			break;
32475353Smjacob
32575353Smjacob		/*
32684145Sjlemon		 * check for link.
32784145Sjlemon		 * Read the status register twice; BMSR_LINK is latch-low.
32875353Smjacob		 */
32984145Sjlemon		reg = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR);
33084145Sjlemon		if (reg & BMSR_LINK)
33184145Sjlemon			break;
33275353Smjacob
33375353Smjacob		/*
33484145Sjlemon		 * Only retry autonegotiation every 5 seconds.
33575353Smjacob		 */
33684145Sjlemon		if (++sc->mii_ticks != 5)
33784145Sjlemon			return (0);
33875353Smjacob
33984145Sjlemon		sc->mii_ticks = 0;
34075353Smjacob		e1000phy_reset(sc);
34196026Sphk		e1000phy_mii_phy_auto(sc);
34296026Sphk		return (0);
34375353Smjacob	}
34475353Smjacob
34575353Smjacob	/* Update the media status. */
34675353Smjacob	e1000phy_status(sc);
34775353Smjacob
34875353Smjacob	/* Callback if something changed. */
34984145Sjlemon	mii_phy_update(sc, cmd);
35075353Smjacob	return (0);
35175353Smjacob}
35275353Smjacob
35384145Sjlemonstatic void
35475353Smjacobe1000phy_status(struct mii_softc *sc)
35575353Smjacob{
35675353Smjacob	struct mii_data *mii = sc->mii_pdata;
35775353Smjacob	int bmsr, bmcr, esr, ssr, isr, ar, lpar;
35875353Smjacob
35975353Smjacob	mii->mii_media_status = IFM_AVALID;
36075353Smjacob	mii->mii_media_active = IFM_ETHER;
36175353Smjacob
36275353Smjacob	bmsr = PHY_READ(sc, E1000_SR) | PHY_READ(sc, E1000_SR);
36375353Smjacob	esr = PHY_READ(sc, E1000_ESR);
36475353Smjacob	bmcr = PHY_READ(sc, E1000_CR);
36575353Smjacob	ssr = PHY_READ(sc, E1000_SSR);
36675353Smjacob	isr = PHY_READ(sc, E1000_ISR);
36775353Smjacob	ar = PHY_READ(sc, E1000_AR);
36875353Smjacob	lpar = PHY_READ(sc, E1000_LPAR);
36975353Smjacob
37075353Smjacob	if (bmsr & E1000_SR_LINK_STATUS)
37175353Smjacob		mii->mii_media_status |= IFM_ACTIVE;
37275353Smjacob
37375353Smjacob	if (bmcr & E1000_CR_LOOPBACK)
37475353Smjacob		mii->mii_media_active |= IFM_LOOP;
37575353Smjacob
37696026Sphk	if ((!(bmsr & E1000_SR_AUTO_NEG_COMPLETE) || !(ssr & E1000_SSR_LINK) ||
37775353Smjacob	    !(ssr & E1000_SSR_SPD_DPLX_RESOLVED))) {
37875353Smjacob		/* Erg, still trying, I guess... */
37975353Smjacob		mii->mii_media_active |= IFM_NONE;
38075353Smjacob		return;
38175353Smjacob	}
38275353Smjacob
383120281Swilko	if ((sc->mii_flags & MIIF_HAVEFIBER) == 0) {
384120281Swilko		if (ssr & E1000_SSR_1000MBS)
385120281Swilko			mii->mii_media_active |= IFM_1000_T;
386120281Swilko		else if (ssr & E1000_SSR_100MBS)
387120281Swilko			mii->mii_media_active |= IFM_100_TX;
388120281Swilko		else
389120281Swilko			mii->mii_media_active |= IFM_10_T;
390120281Swilko	} else {
391120281Swilko		if (ssr & E1000_SSR_1000MBS)
392120281Swilko			mii->mii_media_active |= IFM_1000_SX;
393120281Swilko	}
39475353Smjacob
39575353Smjacob	if (ssr & E1000_SSR_DUPLEX)
39675353Smjacob		mii->mii_media_active |= IFM_FDX;
39775353Smjacob	else
39875353Smjacob		mii->mii_media_active |= IFM_HDX;
39975353Smjacob
400120281Swilko	if ((sc->mii_flags & MIIF_HAVEFIBER) == 0) {
401120281Swilko		/* FLAG0==rx-flow-control FLAG1==tx-flow-control */
402120281Swilko		if ((ar & E1000_AR_PAUSE) && (lpar & E1000_LPAR_PAUSE)) {
403120281Swilko			mii->mii_media_active |= IFM_FLAG0 | IFM_FLAG1;
404120281Swilko		} else if (!(ar & E1000_AR_PAUSE) && (ar & E1000_AR_ASM_DIR) &&
405120281Swilko		    (lpar & E1000_LPAR_PAUSE) && (lpar & E1000_LPAR_ASM_DIR)) {
406120281Swilko			mii->mii_media_active |= IFM_FLAG1;
407120281Swilko		} else if ((ar & E1000_AR_PAUSE) && (ar & E1000_AR_ASM_DIR) &&
408120281Swilko		    !(lpar & E1000_LPAR_PAUSE) && (lpar & E1000_LPAR_ASM_DIR)) {
409120281Swilko			mii->mii_media_active |= IFM_FLAG0;
410120281Swilko		}
41175353Smjacob	}
41275353Smjacob}
41375353Smjacob
41475353Smjacobstatic int
41596026Sphke1000phy_mii_phy_auto(struct mii_softc *mii)
41675353Smjacob{
41775353Smjacob
418120281Swilko	if ((mii->mii_flags & MIIF_HAVEFIBER) == 0) {
419120281Swilko		PHY_WRITE(mii, E1000_AR, E1000_AR_10T | E1000_AR_10T_FD |
420120281Swilko		    E1000_AR_100TX | E1000_AR_100TX_FD |
421120281Swilko		    E1000_AR_PAUSE | E1000_AR_ASM_DIR);
422120281Swilko		PHY_WRITE(mii, E1000_1GCR, E1000_1GCR_1000T_FD);
423120281Swilko		PHY_WRITE(mii, E1000_CR,
424120281Swilko		    E1000_CR_AUTO_NEG_ENABLE | E1000_CR_RESTART_AUTO_NEG);
425120281Swilko	}
42675353Smjacob
42775353Smjacob	return (EJUSTRETURN);
42875353Smjacob}
429