summaryrefslogtreecommitdiff
path: root/sys/dev/mii
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/mii')
-rw-r--r--sys/dev/mii/rlphy.c85
1 files changed, 83 insertions, 2 deletions
diff --git a/sys/dev/mii/rlphy.c b/sys/dev/mii/rlphy.c
index 00587708100..28037f5b9c1 100644
--- a/sys/dev/mii/rlphy.c
+++ b/sys/dev/mii/rlphy.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rlphy.c,v 1.12 2004/09/27 18:25:48 brad Exp $ */
+/* $OpenBSD: rlphy.c,v 1.13 2004/09/30 14:58:02 jason Exp $ */
/*
* Copyright (c) 1998, 1999 Jason L. Wright (jason@thought.net)
@@ -41,10 +41,14 @@
#include <net/if.h>
#include <net/if_media.h>
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
#include <dev/mii/mii.h>
#include <dev/mii/miivar.h>
#include <dev/mii/miidevs.h>
+#include <machine/bus.h>
+#include <dev/ic/rtl81x9reg.h>
int rlphymatch(struct device *, void *, void *);
void rlphyattach(struct device *, struct device *, void *);
@@ -59,10 +63,11 @@ struct cfdriver rlphy_cd = {
};
int rlphy_service(struct mii_softc *, struct mii_data *, int);
+void rlphy_status(struct mii_softc *);
void rlphy_reset(struct mii_softc *);
const struct mii_phy_funcs rlphy_funcs = {
- rlphy_service, ukphy_status, rlphy_reset,
+ rlphy_service, rlphy_status, rlphy_reset,
};
int
@@ -177,3 +182,79 @@ rlphy_reset(struct mii_softc *sc)
mii_phy_reset(sc);
PHY_WRITE(sc, MII_BMCR, bmcr);
}
+
+void
+rlphy_status(struct mii_softc *phy)
+{
+ struct mii_data *mii = phy->mii_pdata;
+ struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
+ int bmsr, bmcr, anlpar;
+
+ mii->mii_media_status = IFM_AVALID;
+ mii->mii_media_active = IFM_ETHER;
+
+ bmsr = PHY_READ(phy, MII_BMSR) | PHY_READ(phy, MII_BMSR);
+ if (bmsr & BMSR_LINK)
+ mii->mii_media_status |= IFM_ACTIVE;
+
+ bmcr = PHY_READ(phy, MII_BMCR);
+ if (bmcr & BMCR_ISO) {
+ mii->mii_media_active |= IFM_NONE;
+ mii->mii_media_status = 0;
+ return;
+ }
+
+ if (bmcr & BMCR_LOOP)
+ mii->mii_media_active |= IFM_LOOP;
+
+ if (bmcr & BMCR_AUTOEN) {
+ /*
+ * NWay autonegotiation takes the highest-order common
+ * bit of the ANAR and ANLPAR (i.e. best media advertised
+ * both by us and our link partner).
+ */
+ if ((bmsr & BMSR_ACOMP) == 0) {
+ /* Erg, still trying, I guess... */
+ mii->mii_media_active |= IFM_NONE;
+ return;
+ }
+
+ anlpar = PHY_READ(phy, MII_ANAR) & PHY_READ(phy, MII_ANLPAR);
+
+ /*
+ * if anlpar is non-zero, NWay succeeded with an NWay
+ * link partner. Otherwise, punt.
+ */
+ if (anlpar != 0) {
+ if (anlpar & ANLPAR_T4)
+ mii->mii_media_active |= IFM_100_T4;
+ else if (anlpar & ANLPAR_TX_FD)
+ mii->mii_media_active |= IFM_100_TX|IFM_FDX;
+ else if (anlpar & ANLPAR_TX)
+ mii->mii_media_active |= IFM_100_TX;
+ else if (anlpar & ANLPAR_10_FD)
+ mii->mii_media_active |= IFM_10_T|IFM_FDX;
+ else if (anlpar & ANLPAR_10)
+ mii->mii_media_active |= IFM_10_T;
+ else
+ mii->mii_media_active |= IFM_NONE;
+ return;
+ }
+
+ if (strcmp("rl",
+ phy->mii_dev.dv_parent->dv_cfdata->cf_driver->cd_name)
+ == 0) {
+ if (PHY_READ(phy, RL_MEDIASTAT) & RL_MEDIASTAT_SPEED10)
+ mii->mii_media_active |= IFM_10_T;
+ else
+ mii->mii_media_active |= IFM_100_TX;
+ } else {
+ if (PHY_READ(phy, 0x0019) & 0x01)
+ mii->mii_media_active |= IFM_100_TX;
+ else
+ mii->mii_media_active |= IFM_10_T;
+ }
+
+ } else
+ mii->mii_media_active = ife->ifm_media;
+}