Skip site navigation (1)Skip section navigation (2)
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>