Implement asynchronous autonegotiation when driven by the MII tick

(one-second clock).  Prevents .5s delays every 5 seconds when the interface
is up but there is no link.  Fixes PR 7361.
This commit is contained in:
thorpej 1999-04-23 04:24:32 +00:00
parent 9751244932
commit 83f9ab3c87
11 changed files with 145 additions and 60 deletions

View File

@ -1,7 +1,7 @@
/* $NetBSD: exphy.c,v 1.15 1998/11/05 00:19:32 thorpej Exp $ */
/* $NetBSD: exphy.c,v 1.16 1999/04/23 04:24:32 thorpej Exp $ */
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* Copyright (c) 1998, 1999 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
@ -201,7 +201,7 @@ exphy_service(sc, mii, cmd)
*/
if (PHY_READ(sc, MII_BMCR) & BMCR_AUTOEN)
return (0);
(void) mii_phy_auto(sc);
(void) mii_phy_auto(sc, 1);
break;
case IFM_100_T4:
/*

View File

@ -1,7 +1,7 @@
/* $NetBSD: icsphy.c,v 1.8 1998/11/05 04:08:01 thorpej Exp $ */
/* $NetBSD: icsphy.c,v 1.9 1999/04/23 04:24:32 thorpej Exp $ */
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* Copyright (c) 1998, 1999 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
@ -193,7 +193,7 @@ icsphy_service(sc, mii, cmd)
*/
if (PHY_READ(sc, MII_BMCR) & BMCR_AUTOEN)
return (0);
(void) mii_phy_auto(sc);
(void) mii_phy_auto(sc, 1);
break;
case IFM_100_T4:
/*

View File

@ -1,7 +1,7 @@
/* $NetBSD: inphy.c,v 1.10 1998/11/05 04:08:02 thorpej Exp $ */
/* $NetBSD: inphy.c,v 1.11 1999/04/23 04:24:32 thorpej Exp $ */
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* Copyright (c) 1998, 1999 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
@ -77,6 +77,7 @@
#include <sys/device.h>
#include <sys/malloc.h>
#include <sys/socket.h>
#include <sys/errno.h>
#include <net/if.h>
#include <net/if_media.h>
@ -201,7 +202,7 @@ inphy_service(sc, mii, cmd)
*/
if (PHY_READ(sc, MII_BMCR) & BMCR_AUTOEN)
return (0);
(void) mii_phy_auto(sc);
(void) mii_phy_auto(sc, 1);
break;
case IFM_100_T4:
/*
@ -255,7 +256,8 @@ inphy_service(sc, mii, cmd)
sc->mii_ticks = 0;
mii_phy_reset(sc);
(void) mii_phy_auto(sc);
if (mii_phy_auto(sc, 0) == EJUSTRETURN)
return (0);
break;
}

View File

@ -1,7 +1,7 @@
/* $NetBSD: lxtphy.c,v 1.9 1998/11/05 04:08:02 thorpej Exp $ */
/* $NetBSD: lxtphy.c,v 1.10 1999/04/23 04:24:32 thorpej Exp $ */
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* Copyright (c) 1998, 1999 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
@ -77,6 +77,7 @@
#include <sys/device.h>
#include <sys/malloc.h>
#include <sys/socket.h>
#include <sys/errno.h>
#include <net/if.h>
#include <net/if_media.h>
@ -192,7 +193,7 @@ lxtphy_service(sc, mii, cmd)
*/
if (PHY_READ(sc, MII_BMCR) & BMCR_AUTOEN)
return (0);
(void) mii_phy_auto(sc);
(void) mii_phy_auto(sc, 1);
break;
case IFM_100_T4:
/*
@ -247,7 +248,8 @@ lxtphy_service(sc, mii, cmd)
sc->mii_ticks = 0;
mii_phy_reset(sc);
(void) mii_phy_auto(sc);
if (mii_phy_auto(sc, 0) == EJUSTRETURN)
return (0);
break;
}

View File

@ -1,7 +1,7 @@
/* $NetBSD: mii_physubr.c,v 1.2 1998/11/04 23:28:15 thorpej Exp $ */
/* $NetBSD: mii_physubr.c,v 1.3 1999/04/23 04:24:32 thorpej Exp $ */
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* Copyright (c) 1998, 1999 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
@ -44,7 +44,9 @@
#include <sys/param.h>
#include <sys/device.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/socket.h>
#include <sys/errno.h>
#include <net/if.h>
#include <net/if_media.h>
@ -52,28 +54,72 @@
#include <dev/mii/mii.h>
#include <dev/mii/miivar.h>
void mii_phy_auto_timeout __P((void *));
int
mii_phy_auto(mii)
mii_phy_auto(mii, waitfor)
struct mii_softc *mii;
{
int bmsr, i;
PHY_WRITE(mii, MII_ANAR,
BMSR_MEDIA_TO_ANAR(mii->mii_capabilities) | ANAR_CSMA);
PHY_WRITE(mii, MII_BMCR, BMCR_AUTOEN | BMCR_STARTNEG);
/* Wait 500ms for it to complete. */
for (i = 0; i < 500; i++) {
if ((bmsr = PHY_READ(mii, MII_BMSR)) & BMSR_ACOMP)
return (1);
delay(1000);
if ((mii->mii_flags & MIIF_DOINGAUTO) == 0) {
PHY_WRITE(mii, MII_ANAR,
BMSR_MEDIA_TO_ANAR(mii->mii_capabilities) | ANAR_CSMA);
PHY_WRITE(mii, MII_BMCR, BMCR_AUTOEN | BMCR_STARTNEG);
}
if (waitfor) {
/* Wait 500ms for it to complete. */
for (i = 0; i < 500; i++) {
if ((bmsr = PHY_READ(mii, MII_BMSR)) & BMSR_ACOMP)
return (0);
delay(1000);
#if 0
if ((bmsr & BMSR_ACOMP) == 0)
printf("%s: autonegotiation failed to complete\n",
mii->mii_dev.dv_xname);
#endif
}
/*
* 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 ((mii->mii_flags & MIIF_DOINGAUTO) == 0) {
mii->mii_flags |= MIIF_DOINGAUTO;
timeout(mii_phy_auto_timeout, mii, hz >> 1);
}
return (EJUSTRETURN);
}
void
mii_phy_auto_timeout(arg)
void *arg;
{
struct mii_softc *mii = arg;
int s, bmsr;
s = splnet();
mii->mii_flags &= ~MIIF_DOINGAUTO;
bmsr = PHY_READ(mii, MII_BMSR);
#if 0
if ((bmsr & BMSR_ACOMP) == 0)
printf("%s: autonegotiation failed to complete\n",
mii->mii_dev.dv_xname);
sc->sc_dev.dv_xname);
#endif
return (0);
/* Update the media status. */
(void) (*mii->mii_service)(mii, mii->mii_pdata, MII_POLLSTAT);
splx(s);
}
void

View File

@ -1,7 +1,7 @@
/* $NetBSD: miivar.h,v 1.7 1998/11/05 04:08:02 thorpej Exp $ */
/* $NetBSD: miivar.h,v 1.8 1999/04/23 04:24:32 thorpej Exp $ */
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* Copyright (c) 1998, 1999 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
@ -128,6 +128,7 @@ typedef struct mii_softc mii_softc_t;
/* mii_flags */
#define MIIF_NOISOLATE 0x0001 /* do not isolate the PHY */
#define MIIF_DOINGAUTO 0x0002 /* doing autonegotiation */
/*
* Used to attach a PHY to a parent.
@ -161,7 +162,7 @@ void mii_add_media __P((struct mii_data *, int, int));
int mii_media_from_bmcr __P((int));
int mii_phy_auto __P((struct mii_softc *));
int mii_phy_auto __P((struct mii_softc *, int));
void mii_phy_reset __P((struct mii_softc *));
void ukphy_status __P((struct mii_softc *));

View File

@ -1,7 +1,7 @@
/* $NetBSD: nsphy.c,v 1.16 1998/11/05 04:08:02 thorpej Exp $ */
/* $NetBSD: nsphy.c,v 1.17 1999/04/23 04:24:32 thorpej Exp $ */
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* Copyright (c) 1998, 1999 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
@ -77,6 +77,7 @@
#include <sys/device.h>
#include <sys/malloc.h>
#include <sys/socket.h>
#include <sys/errno.h>
#include <net/if.h>
#include <net/if_media.h>
@ -235,7 +236,7 @@ nsphy_service(sc, mii, cmd)
*/
if (PHY_READ(sc, MII_BMCR) & BMCR_AUTOEN)
return (0);
(void) mii_phy_auto(sc);
(void) mii_phy_auto(sc, 1);
break;
case IFM_100_T4:
/*
@ -289,7 +290,8 @@ nsphy_service(sc, mii, cmd)
sc->mii_ticks = 0;
mii_phy_reset(sc);
(void) mii_phy_auto(sc);
if (mii_phy_auto(sc, 0) == EJUSTRETURN)
return (0);
break;
}

View File

@ -1,7 +1,7 @@
/* $NetBSD: qsphy.c,v 1.11 1998/11/05 04:08:02 thorpej Exp $ */
/* $NetBSD: qsphy.c,v 1.12 1999/04/23 04:24:32 thorpej Exp $ */
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* Copyright (c) 1998, 1999 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
@ -193,7 +193,7 @@ qsphy_service(sc, mii, cmd)
*/
if (PHY_READ(sc, MII_BMCR) & BMCR_AUTOEN)
return (0);
(void) mii_phy_auto(sc);
(void) mii_phy_auto(sc, 1);
break;
case IFM_100_T4:
/*

View File

@ -1,7 +1,7 @@
/* $NetBSD: sqphy.c,v 1.8 1998/11/05 04:08:02 thorpej Exp $ */
/* $NetBSD: sqphy.c,v 1.9 1999/04/23 04:24:32 thorpej Exp $ */
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* Copyright (c) 1998, 1999 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
@ -77,6 +77,7 @@
#include <sys/device.h>
#include <sys/malloc.h>
#include <sys/socket.h>
#include <sys/errno.h>
#include <net/if.h>
#include <net/if_media.h>
@ -192,7 +193,7 @@ sqphy_service(sc, mii, cmd)
*/
if (PHY_READ(sc, MII_BMCR) & BMCR_AUTOEN)
return (0);
(void) mii_phy_auto(sc);
(void) mii_phy_auto(sc, 1);
break;
case IFM_100_T4:
/*
@ -246,7 +247,8 @@ sqphy_service(sc, mii, cmd)
sc->mii_ticks = 0;
mii_phy_reset(sc);
(void) mii_phy_auto(sc);
if (mii_phy_auto(sc, 0) == EJUSTRETURN)
return (0);
break;
}

View File

@ -1,7 +1,7 @@
/* $NetBSD: tlphy.c,v 1.16 1998/11/05 00:19:32 thorpej Exp $ */
/* $NetBSD: tlphy.c,v 1.17 1999/04/23 04:24:32 thorpej Exp $ */
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* Copyright (c) 1998, 1999 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
@ -75,6 +75,7 @@
#include <sys/kernel.h>
#include <sys/device.h>
#include <sys/socket.h>
#include <sys/errno.h>
#include <machine/bus.h>
@ -98,6 +99,7 @@
struct tlphy_softc {
struct mii_softc sc_mii; /* generic PHY */
int sc_tlphycap;
int sc_need_acomp;
};
int tlphymatch __P((struct device *, struct cfdata *, void *));
@ -108,7 +110,8 @@ struct cfattach tlphy_ca = {
};
int tlphy_service __P((struct mii_softc *, struct mii_data *, int));
void tlphy_auto __P((struct tlphy_softc *));
int tlphy_auto __P((struct tlphy_softc *, int));
void tlphy_acomp __P((struct tlphy_softc *));
void tlphy_status __P((struct tlphy_softc *));
int
@ -206,6 +209,9 @@ tlphy_service(self, mii, cmd)
struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
int reg;
if ((sc->sc_mii.mii_flags & MIIF_DOINGAUTO) == 0 && sc->sc_need_acomp)
tlphy_acomp(sc);
switch (cmd) {
case MII_POLLSTAT:
/*
@ -239,7 +245,7 @@ tlphy_service(self, mii, cmd)
* an autonegotiation cycle, so there's no such
* thing as "already in auto mode".
*/
tlphy_auto(sc);
(void) tlphy_auto(sc, 1);
break;
case IFM_10_2:
case IFM_10_5:
@ -295,7 +301,8 @@ tlphy_service(self, mii, cmd)
sc->sc_mii.mii_ticks = 0;
mii_phy_reset(&sc->sc_mii);
tlphy_auto(sc);
if (tlphy_auto(sc, 0) == EJUSTRETURN)
return (0);
break;
}
@ -362,14 +369,41 @@ tlphy_status(sc)
mii->mii_media_active |= IFM_10_T;
}
int
tlphy_auto(sc, waitfor)
struct tlphy_softc *sc;
int waitfor;
{
int error;
switch ((error = mii_phy_auto(&sc->sc_mii, waitfor))) {
case EIO:
/*
* Just assume we're not in full-duplex mode.
* XXX Check link and try AUI/BNC?
*/
PHY_WRITE(&sc->sc_mii, MII_BMCR, 0);
break;
case EJUSTRETURN:
/* Flag that we need to program when it completes. */
sc->sc_need_acomp = 1;
break;
default:
tlphy_acomp(sc);
}
return (error);
}
void
tlphy_auto(sc)
tlphy_acomp(sc)
struct tlphy_softc *sc;
{
int aner, anlpar;
if (mii_phy_auto(&sc->sc_mii) == 0)
goto dflt;
sc->sc_need_acomp = 0;
/*
* Grr, braindead ThunderLAN PHY doesn't self-configure
@ -386,11 +420,5 @@ tlphy_auto(sc)
return;
}
}
dflt:
/*
* Just assume we're not in full-duplex mode.
* XXX Check link and try AUI/BNC?
*/
PHY_WRITE(&sc->sc_mii, MII_BMCR, 0);
}

View File

@ -1,7 +1,7 @@
/* $NetBSD: ukphy.c,v 1.1 1998/11/05 00:36:48 thorpej Exp $ */
/* $NetBSD: ukphy.c,v 1.2 1999/04/23 04:24:32 thorpej Exp $ */
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* Copyright (c) 1998, 1999 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
@ -76,6 +76,7 @@
#include <sys/device.h>
#include <sys/malloc.h>
#include <sys/socket.h>
#include <sys/errno.h>
#include <net/if.h>
#include <net/if_media.h>
@ -189,7 +190,7 @@ ukphy_service(sc, mii, cmd)
*/
if (PHY_READ(sc, MII_BMCR) & BMCR_AUTOEN)
return (0);
(void) mii_phy_auto(sc);
(void) mii_phy_auto(sc, 1);
break;
case IFM_100_T4:
/*
@ -243,7 +244,8 @@ ukphy_service(sc, mii, cmd)
sc->mii_ticks = 0;
mii_phy_reset(sc);
(void) mii_phy_auto(sc);
if (mii_phy_auto(sc, 0) == EJUSTRETURN)
return (0);
break;
}