diff options
Diffstat (limited to 'sys/dev/mii/mii_physubr.c')
-rw-r--r-- | sys/dev/mii/mii_physubr.c | 48 |
1 files changed, 47 insertions, 1 deletions
diff --git a/sys/dev/mii/mii_physubr.c b/sys/dev/mii/mii_physubr.c index 1ef0455bc73..0fe41652334 100644 --- a/sys/dev/mii/mii_physubr.c +++ b/sys/dev/mii/mii_physubr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mii_physubr.c,v 1.29 2006/12/15 21:47:27 reyk Exp $ */ +/* $OpenBSD: mii_physubr.c,v 1.30 2006/12/28 09:24:27 kettenis Exp $ */ /* $NetBSD: mii_physubr.c,v 1.20 2001/04/13 23:30:09 thorpej Exp $ */ /*- @@ -519,6 +519,52 @@ mii_phy_match(const struct mii_attach_args *ma, const struct mii_phydesc *mpd) } /* + * Return the flow control status flag from MII_ANAR & MII_ANLPAR. + */ +int +mii_phy_flowstatus(struct mii_softc *sc) +{ + int anar, anlpar; + + if ((sc->mii_flags & MIIF_DOPAUSE) == 0) + return (0); + + anar = PHY_READ(sc, MII_ANAR); + anlpar = PHY_READ(sc, MII_ANLPAR); + + if ((anar & ANAR_X_PAUSE_SYM) & (anlpar & ANLPAR_X_PAUSE_SYM)) + return (IFM_FLOW|IFM_ETH_TXPAUSE|IFM_ETH_RXPAUSE); + + if ((anar & ANAR_X_PAUSE_SYM) == 0) { + if ((anar & ANAR_X_PAUSE_ASYM) && + ((anlpar & + ANLPAR_X_PAUSE_TOWARDS) == ANLPAR_X_PAUSE_TOWARDS)) + return (IFM_FLOW|IFM_ETH_TXPAUSE); + else + return (0); + } + + if ((anar & ANAR_X_PAUSE_ASYM) == 0) { + if (anlpar & ANLPAR_X_PAUSE_SYM) + return (IFM_FLOW|IFM_ETH_TXPAUSE|IFM_ETH_RXPAUSE); + else + return (0); + } + + switch ((anlpar & ANLPAR_X_PAUSE_TOWARDS)) { + case ANLPAR_X_PAUSE_NONE: + return (0); + + case ANLPAR_X_PAUSE_ASYM: + return (IFM_FLOW|IFM_ETH_RXPAUSE); + + default: + return (IFM_FLOW|IFM_ETH_RXPAUSE|IFM_ETH_TXPAUSE); + } + /* NOTREACHED */ +} + +/* * Given an ifmedia word, return the corresponding ANAR value. */ int |