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