summaryrefslogtreecommitdiff
path: root/sys/dev/mii/rlphy.c
diff options
context:
space:
mode:
authorBrad Smith <brad@cvs.openbsd.org>2005-01-10 20:33:02 +0000
committerBrad Smith <brad@cvs.openbsd.org>2005-01-10 20:33:02 +0000
commitd683e16f7bbded6a48e94ccdb73f989325b75155 (patch)
tree5055a52cb203d257633910182c878d1b882efac4 /sys/dev/mii/rlphy.c
parent4c8c11fc534fcd2868054ae522c79c266bddcedc (diff)
remove unnecessary rlphy_reset(), mii_phy_tick() and
some clean up. fixes issue with axe@usb. Tested by a number of developers and users.
Diffstat (limited to 'sys/dev/mii/rlphy.c')
-rw-r--r--sys/dev/mii/rlphy.c97
1 files changed, 70 insertions, 27 deletions
diff --git a/sys/dev/mii/rlphy.c b/sys/dev/mii/rlphy.c
index 9019af0a0ed..55b2af1d7a0 100644
--- a/sys/dev/mii/rlphy.c
+++ b/sys/dev/mii/rlphy.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rlphy.c,v 1.14 2004/10/07 21:30:57 brad Exp $ */
+/* $OpenBSD: rlphy.c,v 1.15 2005/01/10 20:33:01 brad Exp $ */
/*
* Copyright (c) 1998, 1999 Jason L. Wright (jason@thought.net)
@@ -64,10 +64,9 @@ 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, rlphy_status, rlphy_reset,
+ rlphy_service, rlphy_status, mii_phy_reset,
};
int
@@ -114,6 +113,8 @@ rlphyattach(struct device *parent, struct device *self, void *aux)
sc->mii_pdata = mii;
sc->mii_flags = mii->mii_flags;
+ sc->mii_flags |= MIIF_NOISOLATE;
+
PHY_RESET(sc);
sc->mii_capabilities =
@@ -147,12 +148,47 @@ rlphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
break;
- mii_phy_setmedia(sc);
+ switch (IFM_SUBTYPE(ife->ifm_media)) {
+ case IFM_AUTO:
+ /*
+ * If we're already in auto mode, just return.
+ */
+ if (PHY_READ(sc, MII_BMCR) & BMCR_AUTOEN)
+ return (0);
+ (void) mii_phy_auto(sc);
+ break;
+ case IFM_100_T4:
+ /*
+ * XXX Not supported as a manual setting right now.
+ */
+ return (EINVAL);
+ default:
+ /*
+ * BMCR data is stored in the ifmedia entry.
+ */
+ PHY_WRITE(sc, MII_ANAR,
+ mii_anar(ife->ifm_media));
+ PHY_WRITE(sc, MII_BMCR, ife->ifm_data);
+ }
break;
case MII_TICK:
- if (mii_phy_tick(sc) == EJUSTRETURN)
+ /*
+ * Is the interface even up?
+ */
+ if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
return (0);
+
+ /*
+ * Only used for autonegotiation.
+ */
+ if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO)
+ break;
+
+ /*
+ * The RealTek PHY's autonegotiation doesn't need to be
+ * kicked; it continues in the background.
+ */
break;
case MII_DOWN:
@@ -169,21 +205,6 @@ rlphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
}
void
-rlphy_reset(struct mii_softc *sc)
-{
- int bmcr;
-
- /*
- * XXX The RTL8139 doesn't set the BMCR properly
- * XXX after reset, which breaks autoneg.
- */
-
- bmcr = PHY_READ(sc, MII_BMCR);
- mii_phy_reset(sc);
- PHY_WRITE(sc, MII_BMCR, bmcr);
-}
-
-void
rlphy_status(struct mii_softc *sc)
{
struct mii_data *mii = sc->mii_pdata;
@@ -219,13 +240,8 @@ rlphy_status(struct mii_softc *sc)
return;
}
- anlpar = PHY_READ(sc, MII_ANAR) & PHY_READ(sc, MII_ANLPAR);
-
- /*
- * if anlpar is non-zero, NWay succeeded with an NWay
- * link partner. Otherwise, punt.
- */
- if (anlpar != 0) {
+ if ((anlpar = PHY_READ(sc, MII_ANAR) &
+ PHY_READ(sc, MII_ANLPAR))) {
if (anlpar & ANLPAR_T4)
mii->mii_media_active |= IFM_100_T4;
else if (anlpar & ANLPAR_TX_FD)
@@ -241,6 +257,33 @@ rlphy_status(struct mii_softc *sc)
return;
}
+ /*
+ * If the other side doesn't support NWAY, then the
+ * best we can do is determine if we have a 10Mbps or
+ * 100Mbps link. There's no way to know if the link
+ * is full or half duplex, so we default to half duplex
+ * and hope that the user is clever enough to manually
+ * change the media settings if we're wrong.
+ */
+
+ /*
+ * The RealTek PHY supports non-NWAY link speed
+ * detection, however it does not report the link
+ * detection results via the ANLPAR or BMSR registers.
+ * (What? RealTek doesn't do things the way everyone
+ * else does? I'm just shocked, shocked I tell you.)
+ * To determine the link speed, we have to do one
+ * of two things:
+ *
+ * - If this is a standalone RealTek RTL8201(L) PHY,
+ * we can determine the link speed by testing bit 0
+ * in the magic, vendor-specific register at offset
+ * 0x19.
+ *
+ * - If this is a RealTek MAC with integrated PHY, we
+ * can test the 'SPEED10' bit of the MAC's media status
+ * register.
+ */
if (strcmp("rl",
sc->mii_dev.dv_parent->dv_cfdata->cf_driver->cd_name)
== 0) {