diff options
author | jlemon <jlemon@FreeBSD.org> | 2001-09-29 18:40:06 +0000 |
---|---|---|
committer | jlemon <jlemon@FreeBSD.org> | 2001-09-29 18:40:06 +0000 |
commit | 5a10e7a36d455bb4862414f62bc665ef6247c9b7 (patch) | |
tree | bc0ddf76582b3057a355464d5aeb1dbf90e5d043 /sys/dev/mii | |
parent | 7659fef3a078e47125e1a905f5fa87b72120204a (diff) | |
download | FreeBSD-src-5a10e7a36d455bb4862414f62bc665ef6247c9b7.zip FreeBSD-src-5a10e7a36d455bb4862414f62bc665ef6247c9b7.tar.gz |
Add new device method miibus_linkchg, along with a service routine.
Diffstat (limited to 'sys/dev/mii')
-rw-r--r-- | sys/dev/mii/mii.c | 29 | ||||
-rw-r--r-- | sys/dev/mii/mii_physubr.c | 66 | ||||
-rw-r--r-- | sys/dev/mii/miibus_if.m | 7 |
3 files changed, 102 insertions, 0 deletions
diff --git a/sys/dev/mii/mii.c b/sys/dev/mii/mii.c index 2e77fe5..e463b75 100644 --- a/sys/dev/mii/mii.c +++ b/sys/dev/mii/mii.c @@ -68,6 +68,7 @@ static const char rcsid[] = static int miibus_readreg __P((device_t, int, int)); static int miibus_writereg __P((device_t, int, int, int)); static void miibus_statchg __P((device_t)); +static void miibus_linkchg __P((device_t)); static void miibus_mediainit __P((device_t)); static device_method_t miibus_methods[] = { @@ -85,6 +86,7 @@ static device_method_t miibus_methods[] = { DEVMETHOD(miibus_readreg, miibus_readreg), DEVMETHOD(miibus_writereg, miibus_writereg), DEVMETHOD(miibus_statchg, miibus_statchg), + DEVMETHOD(miibus_linkchg, miibus_linkchg), DEVMETHOD(miibus_mediainit, miibus_mediainit), { 0, 0 } @@ -218,6 +220,33 @@ static void miibus_statchg(dev) return; } +static void +miibus_linkchg(dev) + device_t dev; +{ + struct mii_data *mii; + struct ifnet *ifp; + device_t parent; + int link; + + parent = device_get_parent(dev); + MIIBUS_LINKCHG(parent); + + mii = device_get_softc(dev); + ifp = device_get_softc(parent); + + if (mii->mii_media_status & IFM_AVALID) { + if (mii->mii_media_status & IFM_ACTIVE) + link = NOTE_LINKUP; + else + link = NOTE_LINKDOWN; + } else { + link = NOTE_LINKINV; + } + + KNOTE(&ifp->if_klist, link); +} + static void miibus_mediainit(dev) device_t dev; { diff --git a/sys/dev/mii/mii_physubr.c b/sys/dev/mii/mii_physubr.c index 9139296..303864f 100644 --- a/sys/dev/mii/mii_physubr.c +++ b/sys/dev/mii/mii_physubr.c @@ -142,6 +142,55 @@ mii_phy_auto_timeout(arg) splx(s); } +int +mii_phy_tick(sc) + struct mii_softc *sc; +{ + struct ifmedia_entry *ife = sc->mii_pdata->mii_media.ifm_cur; + struct ifnet *ifp = sc->mii_pdata->mii_ifp; + int reg; + + /* + * Is the interface even up? + */ + if ((ifp->if_flags & IFF_UP) == 0) + return (EJUSTRETURN); + + /* + * If we're not doing autonegotiation, we don't need to do + * any extra work here. However, we need to check the link + * status so we can generate an announcement if the status + * changes. + */ + if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) + return (0); + + /* + * check for link. + * Read the status register twice; BMSR_LINK is latch-low. + */ + reg = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR); + if (reg & BMSR_LINK) + return (0); + + /* + * Only retry autonegotiation every 5 seconds. + */ + if (++sc->mii_ticks != 5) + return (EJUSTRETURN); + + sc->mii_ticks = 0; + mii_phy_reset(sc); + if (mii_phy_auto(sc, 0) == EJUSTRETURN) + return (EJUSTRETURN); + + /* + * Might need to generate a status message if autonegotiation + * failed. + */ + return (0); +} + void mii_phy_reset(mii) struct mii_softc *mii; @@ -166,6 +215,23 @@ mii_phy_reset(mii) PHY_WRITE(mii, MII_BMCR, reg | BMCR_ISO); } +void +mii_phy_update(sc, cmd) + struct mii_softc *sc; + int cmd; +{ + struct mii_data *mii = sc->mii_pdata; + + if (sc->mii_active != mii->mii_media_active || cmd == MII_MEDIACHG) { + MIIBUS_STATCHG(sc->mii_dev); + sc->mii_active = mii->mii_media_active; + } + if (sc->mii_status != mii->mii_media_status) { + MIIBUS_LINKCHG(sc->mii_dev); + sc->mii_status = mii->mii_media_status; + } +} + /* * Given an ifmedia word, return the corresponding ANAR value. */ diff --git a/sys/dev/mii/miibus_if.m b/sys/dev/mii/miibus_if.m index ee7cd08..017812f 100644 --- a/sys/dev/mii/miibus_if.m +++ b/sys/dev/mii/miibus_if.m @@ -31,6 +31,13 @@ METHOD void statchg { }; # +# Notify bus about PHY link change. +# +METHOD void linkchg { + device_t dev; +}; + +# # Notify bus that media has been set. # METHOD void mediainit { |