summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwpaul <wpaul@FreeBSD.org>2002-04-07 20:55:50 +0000
committerwpaul <wpaul@FreeBSD.org>2002-04-07 20:55:50 +0000
commit68bdebcaab8f3305ba9ad9735ad57b6b1cd13d26 (patch)
treed8d07d2e39818081fc33934d98636b41b3ef3379
parent71240839dd1bfe2ce39c28d43ace740bab9b2ad7 (diff)
downloadFreeBSD-src-68bdebcaab8f3305ba9ad9735ad57b6b1cd13d26.zip
FreeBSD-src-68bdebcaab8f3305ba9ad9735ad57b6b1cd13d26.tar.gz
Teach the rlphy driver how to do parallel link detection. If the link partner
doesn't support NWAY, the RealTek PHY (both the integrated ones on 8139 chips and the RTL8201L 10/100 PHY) will not report the link speed via the ANLPAR or BMSR registers. For the 8201L, we need to look in magic vendor-specific PHY register 0x19. For the 8139 MAC+PHY combo, we have to be able to test the RL_MEDIASTAT register. The changes to rlphy.c are based largely on the patch from PR 30836, however I tried to eliminate some magic numbers by creating an entry for the 8201 PHY in miidevs. Also updated if_rl.c to allow the rlphy driver to read the RL_MEDIASTAT register via the rl_miibus_readreg() routine.
-rw-r--r--sys/dev/mii/miidevs4
-rw-r--r--sys/dev/mii/rlphy.c114
-rw-r--r--sys/pci/if_rl.c11
3 files changed, 128 insertions, 1 deletions
diff --git a/sys/dev/mii/miidevs b/sys/dev/mii/miidevs
index 081ea1f..7b80866 100644
--- a/sys/dev/mii/miidevs
+++ b/sys/dev/mii/miidevs
@@ -59,6 +59,7 @@ oui JATO 0x00e083 Jato Technologies
oui LEVEL1 0x00207b Level 1
oui NATSEMI 0x080017 National Semiconductor
oui QUALSEMI 0x006051 Quality Semiconductor
+oui REALTEK 0x000020 RealTek Semicondctor
oui SEEQ 0x00a07d Seeq
oui SIS 0x00e006 Silicon Integrated Systems
oui TDK 0x00c039 TDK
@@ -138,6 +139,9 @@ model NATSEMI DP83861 0x0006 DP83861 10/100/1000 media interface
/* Quality Semiconductor PHYs */
model QUALSEMI QS6612 0x0000 QS6612 10/100 media interface
+/* RealTek Semiconductor PHYs */
+model REALTEK RTL8201L 0x0020 RTL8201L 10/100 media interface
+
/* Seeq PHYs */
model xxSEEQ 80220 0x0003 Seeq 80220 10/100 media interface
model xxSEEQ 84220 0x0004 Seeq 84220 10/100 media interface
diff --git a/sys/dev/mii/rlphy.c b/sys/dev/mii/rlphy.c
index 1704b1b..560465b 100644
--- a/sys/dev/mii/rlphy.c
+++ b/sys/dev/mii/rlphy.c
@@ -43,10 +43,15 @@
#include <sys/bus.h>
#include <net/if.h>
+#include <net/if_arp.h>
#include <net/if_media.h>
#include <dev/mii/mii.h>
#include <dev/mii/miivar.h>
+#include <dev/mii/miidevs.h>
+
+#include <machine/bus.h>
+#include <pci/if_rlreg.h>
#include "miibus_if.h"
@@ -79,6 +84,7 @@ static driver_t rlphy_driver = {
DRIVER_MODULE(rlphy, miibus, rlphy_driver, rlphy_devclass, 0, 0);
static int rlphy_service(struct mii_softc *, struct mii_data *, int);
+static void rlphy_status(struct mii_softc *);
static int rlphy_probe(dev)
device_t dev;
@@ -89,6 +95,13 @@ static int rlphy_probe(dev)
ma = device_get_ivars(dev);
parent = device_get_parent(device_get_parent(dev));
+ /* Test for RealTek 8201L PHY */
+ if (MII_OUI(ma->mii_id1, ma->mii_id2) == MII_OUI_REALTEK &&
+ MII_MODEL(ma->mii_id2) == MII_MODEL_REALTEK_RTL8201L) {
+ device_set_desc(dev, MII_STR_REALTEK_RTL8201L);
+ return(0);
+ }
+
/*
* RealTek PHY doesn't have vendor/device ID registers:
* the rl driver fakes up a return value of all zeros.
@@ -250,9 +263,108 @@ rlphy_service(sc, mii, cmd)
}
/* Update the media status. */
- ukphy_status(sc);
+ rlphy_status(sc);
/* Callback if something changed. */
mii_phy_update(sc, cmd);
return (0);
}
+
+void
+rlphy_status(phy)
+ struct mii_softc *phy;
+{
+ struct mii_data *mii = phy->mii_pdata;
+ int bmsr, bmcr, anlpar;
+ device_t parent;
+
+ 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;
+ }
+
+ if ((anlpar = PHY_READ(phy, MII_ANAR) &
+ PHY_READ(phy, MII_ANLPAR))) {
+ 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 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.
+ */
+ parent = device_get_parent(phy->mii_dev);
+ if (strcmp(device_get_name(parent), "rl") != 0) {
+ if (PHY_READ(phy, 0x0019) & 0x01)
+ mii->mii_media_active |= IFM_100_TX;
+ else
+ mii->mii_media_active |= IFM_10_T;
+ } else {
+ 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
+ mii->mii_media_active = mii_media_from_bmcr(bmcr);
+}
diff --git a/sys/pci/if_rl.c b/sys/pci/if_rl.c
index b912571..a08e561 100644
--- a/sys/pci/if_rl.c
+++ b/sys/pci/if_rl.c
@@ -609,6 +609,17 @@ static int rl_miibus_readreg(dev, phy, reg)
RL_UNLOCK(sc);
return(0);
break;
+ /*
+ * Allow the rlphy driver to read the media status
+ * register. If we have a link partner which does not
+ * support NWAY, this is the register which will tell
+ * us the results of parallel detection.
+ */
+ case RL_MEDIASTAT:
+ rval = CSR_READ_1(sc, RL_MEDIASTAT);
+ RL_UNLOCK(sc);
+ return(rval);
+ break;
default:
printf("rl%d: bad phy register\n", sc->rl_unit);
RL_UNLOCK(sc);
OpenPOWER on IntegriCloud