Date: Sun, 17 Mar 2002 13:05:51 +0100 From: Martin Nilsson <martin@gneto.com> To: hackers@freebsd.org Subject: Need help with MII-bus driver Message-ID: <3C94869F.1030800@gneto.com>
next in thread | raw e-mail | index | archive | help
Hello -hackers!
I'm trying to fix the problems in kern/30836 and kern/35691 where an
integrated SIS 900 NIC is not working with an external Realtek PHY.
(10baseT (or non NWAY) mode does not work)
I have modified the dev/mii/rlphy.c driver to also recognize the RTL8201
PHY.
The problem is that in the rlphy_status function I need to know if this
is a integrated 8139 phy or an external 8201 how can I find this out
when all I have is a mii_softc* ?
Below are my changes that work fine with the SIS900 but breaks when
using a Realtek 8139 and not doing NWAY negotiation.
Please cc me on any answers so I won't have to wait for my hackers
digest to arrive.
/martin
*** rlphy.c Thu Mar 7 07:23:00 2002
--- rlphy.c.mn Sun Mar 17 13:00:43 2002
***************
*** 80,85 ****
--- 80,86 ----
DRIVER_MODULE(rlphy, miibus, rlphy_driver, rlphy_devclass, 0, 0);
int rlphy_service __P((struct mii_softc *, struct mii_data *, int));
+ void rlphy_status __P((struct mii_softc *));
static int rlphy_probe(dev)
device_t dev;
***************
*** 90,95 ****
--- 91,103 ----
ma = device_get_ivars(dev);
parent = device_get_parent(device_get_parent(dev));
+ /* Realtek 8201L */
+ if (MII_OUI(ma->mii_id1, ma->mii_id2) == 0x000020 &&
+ MII_MODEL(ma->mii_id2) == 0x20) {
+ device_set_desc(dev, "RealTek 8201(L) media interface");
+ return (0);
+ }
+
/*
* RealTek PHY doesn't have vendor/device ID registers:
* the rl driver fakes up a return value of all zeros.
***************
*** 259,265 ****
}
/* Update the media status. */
! ukphy_status(sc);
/* Callback if something changed. */
if (sc->mii_active != mii->mii_media_active || cmd == MII_MEDIACHG) {
--- 267,273 ----
}
/* Update the media status. */
! rlphy_status(sc);
/* Callback if something changed. */
if (sc->mii_active != mii->mii_media_active || cmd == MII_MEDIACHG) {
***************
*** 267,270 ****
--- 275,353 ----
sc->mii_active = mii->mii_media_active;
}
return (0);
+ }
+
+ void
+ rlphy_status(phy)
+ struct mii_softc *phy;
+ {
+ struct mii_data *mii = phy->mii_pdata;
+ 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;
+ }
+
+ 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.
+ */
+
+ /*
+ * RTL8201 Link partner is not capable of autonegotiation.
+ * Magic register (0x0019) found in Linux driver for SiS900
+ */
+ if( 1 /* Is this a 8201? */ ) {
+
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 = mii_media_from_bmcr(bmcr);
}
---
Martin Nilsson - Home:<martin@gneto.com> Work:<martin@svenskabutiker.se>
UNIX & Webb programmer/architect Malmö, Sweden
FreeBSD - The power to serve. http://www.FreeBSD.org
To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-hackers" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?3C94869F.1030800>
