summaryrefslogtreecommitdiff
path: root/sys/dev/mii/rgephy.c
diff options
context:
space:
mode:
authorBrad Smith <brad@cvs.openbsd.org>2006-08-28 01:54:25 +0000
committerBrad Smith <brad@cvs.openbsd.org>2006-08-28 01:54:25 +0000
commitf28d443b8308de361467163828fbc840ee0d5c06 (patch)
tree3ca97d49a02868698f0c701563a331c227b1b1c1 /sys/dev/mii/rgephy.c
parentb0901da970d1df2483f5b089537ebd118aeeffcf (diff)
Fix manual media types by always leaving the PHY in autoneg mode but adjusting
the ANAR as appropriate. Derived from a diff for FreeBSD; same technique used by the Linux r8169 driver.
Diffstat (limited to 'sys/dev/mii/rgephy.c')
-rw-r--r--sys/dev/mii/rgephy.c53
1 files changed, 30 insertions, 23 deletions
diff --git a/sys/dev/mii/rgephy.c b/sys/dev/mii/rgephy.c
index c6a317c41fa..5e2b4780409 100644
--- a/sys/dev/mii/rgephy.c
+++ b/sys/dev/mii/rgephy.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rgephy.c,v 1.14 2006/08/11 19:50:48 brad Exp $ */
+/* $OpenBSD: rgephy.c,v 1.15 2006/08/28 01:54:24 brad Exp $ */
/*
* Copyright (c) 2003
* Bill Paul <wpaul@windriver.com>. All rights reserved.
@@ -147,7 +147,7 @@ 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 anar, reg, speed, gig = 0;
switch (cmd) {
case MII_POLLSTAT:
@@ -177,6 +177,10 @@ rgephy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
PHY_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
@@ -190,32 +194,30 @@ rgephy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
break;
case IFM_1000_T:
speed = RGEPHY_S1000;
+ anar |= RGEPHY_ANAR_TX_FD | RGEPHY_ANAR_TX |
+ RGEPHY_ANAR_10_FD | RGEPHY_ANAR_10;
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;
+ if (IFM_SUBTYPE(ife->ifm_media) == IFM_1000_T)
+ gig = RGEPHY_1000CTL_AFD;
+ anar &= ~(RGEPHY_ANAR_TX | RGEPHY_ANAR_10);
} else {
- gig = RGEPHY_1000CTL_AHD;
+ if (IFM_SUBTYPE(ife->ifm_media) == IFM_1000_T)
+ 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)
- break;
-
- PHY_WRITE(sc, RGEPHY_MII_1000CTL, gig);
- PHY_WRITE(sc, RGEPHY_MII_BMCR,
- speed|RGEPHY_BMCR_AUTOEN|RGEPHY_BMCR_STARTNEG);
-
/*
* When setting the link manually, one side must
* be the master and the other the slave. However
@@ -224,13 +226,16 @@ setit:
* flags. If LINK0 is set, we program the PHY to
* be a master, otherwise it's a slave.
*/
- if ((mii->mii_ifp->if_flags & IFF_LINK0)) {
- PHY_WRITE(sc, RGEPHY_MII_1000CTL,
- gig|RGEPHY_1000CTL_MSE|RGEPHY_1000CTL_MSC);
- } else {
- PHY_WRITE(sc, RGEPHY_MII_1000CTL,
- gig|RGEPHY_1000CTL_MSE);
+ if (IFM_SUBTYPE(ife->ifm_media) == IFM_1000_T) {
+ gig |= RGEPHY_1000CTL_MSE;
+ if (mii->mii_ifp->if_flags & IFF_LINK0)
+ gig |= RGEPHY_1000CTL_MSC;
}
+
+ PHY_WRITE(sc, RGEPHY_MII_1000CTL, gig);
+ PHY_WRITE(sc, RGEPHY_MII_BMCR, speed |
+ RGEPHY_BMCR_AUTOEN | RGEPHY_BMCR_STARTNEG);
+ PHY_WRITE(sc, RGEPHY_MII_ANAR, anar);
break;
#ifdef foo
case IFM_NONE:
@@ -292,10 +297,12 @@ setit:
*/
if (sc->mii_media_active != mii->mii_media_active ||
sc->mii_media_status != mii->mii_media_status ||
- cmd == MII_MEDIACHG) {
+ cmd == MII_MEDIACHG)
rgephy_load_dspcode(sc);
- }
+
+ /* Callback if something changed. */
mii_phy_update(sc, cmd);
+
return (0);
}