#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: ukphy_subr.c,v 1.17 2020/03/15 23:04:50 thorpej Exp $");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/device.h>
#include <sys/socket.h>
#include <net/if.h>
#include <net/if_media.h>
#include <dev/mii/mii.h>
#include <dev/mii/miivar.h>
void
ukphy_status(struct mii_softc *phy)
{
struct mii_data *mii = phy->mii_pdata;
struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
uint16_t bmsr, bmcr, anar, anlpar, gtcr, gtsr, result;
KASSERT(mii_locked(mii));
mii->mii_media_status = IFM_AVALID;
mii->mii_media_active = IFM_ETHER;
PHY_READ(phy, MII_BMSR, &bmsr);
PHY_READ(phy, MII_BMSR, &bmsr);
if (bmsr & BMSR_LINK)
mii->mii_media_status |= IFM_ACTIVE;
PHY_READ(phy, MII_BMCR, &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) {
if ((bmsr & BMSR_ACOMP) == 0) {
mii->mii_media_active |= IFM_NONE;
return;
}
PHY_READ(phy, MII_ANAR, &anar);
PHY_READ(phy, MII_ANLPAR, &anlpar);
result = anar & anlpar;
if ((phy->mii_flags & MIIF_HAVE_GTCR) != 0 &&
(phy->mii_extcapabilities &
(EXTSR_1000THDX | EXTSR_1000TFDX)) != 0) {
PHY_READ(phy, MII_100T2CR, >cr);
PHY_READ(phy, MII_100T2SR, >sr);
} else
gtcr = gtsr = 0;
if ((gtcr & GTCR_ADV_1000TFDX) && (gtsr & GTSR_LP_1000TFDX))
mii->mii_media_active |= IFM_1000_T | IFM_FDX;
else if ((gtcr & GTCR_ADV_1000THDX) &&
(gtsr & GTSR_LP_1000THDX))
mii->mii_media_active |= IFM_1000_T | IFM_HDX;
else if (result & ANLPAR_TX_FD)
mii->mii_media_active |= IFM_100_TX | IFM_FDX;
else if (result & ANLPAR_T4)
mii->mii_media_active |= IFM_100_T4 | IFM_HDX;
else if (result & ANLPAR_TX)
mii->mii_media_active |= IFM_100_TX | IFM_HDX;
else if (result & ANLPAR_10_FD)
mii->mii_media_active |= IFM_10_T | IFM_FDX;
else if (result & ANLPAR_10)
mii->mii_media_active |= IFM_10_T | IFM_HDX;
else
mii->mii_media_active |= IFM_NONE;
if ((IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_T) &&
(gtsr & GTSR_MS_RES))
mii->mii_media_active |= IFM_ETH_MASTER;
if (mii->mii_media_active & IFM_FDX)
mii->mii_media_active |= mii_phy_flowstatus(phy);
} else
mii->mii_media_active = ife->ifm_media;
}