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:<[EMAIL PROTECTED]> Work:<[EMAIL PROTECTED]>
UNIX & Webb programmer/architect  Malmö, Sweden
FreeBSD - The power to serve. http://www.FreeBSD.org


To Unsubscribe: send mail to [EMAIL PROTECTED]
with "unsubscribe freebsd-hackers" in the body of the message

Reply via email to