summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoryongari <yongari@FreeBSD.org>2006-08-12 01:38:49 +0000
committeryongari <yongari@FreeBSD.org>2006-08-12 01:38:49 +0000
commit38e27927c91701f256654a22f2341b7197f00cee (patch)
tree779e0b364581a248fd01af3dac3a0fd515cecdfe
parent36aa6705100b69cc3c482c73a8b095f0c1e404d2 (diff)
downloadFreeBSD-src-38e27927c91701f256654a22f2341b7197f00cee.zip
FreeBSD-src-38e27927c91701f256654a22f2341b7197f00cee.tar.gz
Due to the poor PHY documentation from RealTek I can't sure but I
think the RealTek PHY needs driver to set RGEPHY_BMCR_AUTOEN bit of RGEPHY_MII_BMCR register and proper ANAR register setting for manual media type selection. This fixes long standing manual media type selection bug in rgephy(4). Reported by: Jelte Jansen <jelte AT NLnetLabs DOT nl> Tested by: Jelte Jansen <jelte AT NLnetLabs DOT nl>
-rw-r--r--sys/dev/mii/rgephy.c28
1 files changed, 18 insertions, 10 deletions
diff --git a/sys/dev/mii/rgephy.c b/sys/dev/mii/rgephy.c
index 3d36865..ffee835 100644
--- a/sys/dev/mii/rgephy.c
+++ b/sys/dev/mii/rgephy.c
@@ -166,7 +166,7 @@ static int
rgephy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
{
struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
- int reg, speed, gig;
+ int reg, speed, gig, anar;
switch (cmd) {
case MII_POLLSTAT:
@@ -196,6 +196,10 @@ rgephy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
rgephy_reset(sc); /* XXX hardware bug work-around */
+ anar = PHY_READ(sc, RGEPHY_MII_ANAR);
+ anar &= ~(RGEPHY_ANAR_TX_FD | RGEPHY_ANAR_TX |
+ RGEPHY_ANAR_10_FD | RGEPHY_ANAR_10);
+
switch (IFM_SUBTYPE(ife->ifm_media)) {
case IFM_AUTO:
#ifdef foo
@@ -212,28 +216,30 @@ rgephy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
goto setit;
case IFM_100_TX:
speed = RGEPHY_S100;
+ anar |= RGEPHY_ANAR_TX_FD | RGEPHY_ANAR_TX;
goto setit;
case IFM_10_T:
speed = RGEPHY_S10;
+ anar |= RGEPHY_ANAR_10_FD | RGEPHY_ANAR_10;
setit:
rgephy_loop(sc);
if ((ife->ifm_media & IFM_GMASK) == IFM_FDX) {
speed |= RGEPHY_BMCR_FDX;
gig = RGEPHY_1000CTL_AFD;
+ anar &= ~(RGEPHY_ANAR_TX | RGEPHY_ANAR_10);
} else {
gig = RGEPHY_1000CTL_AHD;
+ anar &=
+ ~(RGEPHY_ANAR_TX_FD | RGEPHY_ANAR_10_FD);
}
- PHY_WRITE(sc, RGEPHY_MII_1000CTL, 0);
- PHY_WRITE(sc, RGEPHY_MII_BMCR, speed);
- PHY_WRITE(sc, RGEPHY_MII_ANAR, RGEPHY_SEL_TYPE);
-
- if (IFM_SUBTYPE(ife->ifm_media) != IFM_1000_T)
+ if (IFM_SUBTYPE(ife->ifm_media) != IFM_1000_T) {
+ PHY_WRITE(sc, RGEPHY_MII_1000CTL, 0);
+ PHY_WRITE(sc, RGEPHY_MII_ANAR, anar);
+ PHY_WRITE(sc, RGEPHY_MII_BMCR, speed |
+ RGEPHY_BMCR_AUTOEN | RGEPHY_BMCR_STARTNEG);
break;
-
- PHY_WRITE(sc, RGEPHY_MII_1000CTL, gig);
- PHY_WRITE(sc, RGEPHY_MII_BMCR,
- speed|RGEPHY_BMCR_AUTOEN|RGEPHY_BMCR_STARTNEG);
+ }
/*
* When settning the link manually, one side must
@@ -250,6 +256,8 @@ setit:
PHY_WRITE(sc, RGEPHY_MII_1000CTL,
gig|RGEPHY_1000CTL_MSE);
}
+ PHY_WRITE(sc, RGEPHY_MII_BMCR, speed |
+ RGEPHY_BMCR_AUTOEN | RGEPHY_BMCR_STARTNEG);
break;
#ifdef foo
case IFM_NONE:
OpenPOWER on IntegriCloud