summaryrefslogtreecommitdiffstats
path: root/sys/dev/mii
diff options
context:
space:
mode:
authorjlemon <jlemon@FreeBSD.org>2001-09-29 18:40:06 +0000
committerjlemon <jlemon@FreeBSD.org>2001-09-29 18:40:06 +0000
commit5a10e7a36d455bb4862414f62bc665ef6247c9b7 (patch)
treebc0ddf76582b3057a355464d5aeb1dbf90e5d043 /sys/dev/mii
parent7659fef3a078e47125e1a905f5fa87b72120204a (diff)
downloadFreeBSD-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.c29
-rw-r--r--sys/dev/mii/mii_physubr.c66
-rw-r--r--sys/dev/mii/miibus_if.m7
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 {
OpenPOWER on IntegriCloud