Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/mii Flow-control advertisement and parsing support. ...
details: https://anonhg.NetBSD.org/src/rev/1c1f4f778f10
branches: trunk
changeset: 565470:1c1f4f778f10
user: thorpej <thorpej%NetBSD.org@localhost>
date: Sat Apr 10 02:32:10 2004 +0000
description:
Flow-control advertisement and parsing support. From HITOSHI Osada.
Slightly modified by me.
diffstat:
sys/dev/mii/mii_physubr.c | 76 ++++++++++++++++++++++++++++++++++++++++++++--
sys/dev/mii/miivar.h | 4 +-
2 files changed, 75 insertions(+), 5 deletions(-)
diffs (177 lines):
diff -r e3fedc29f87b -r 1c1f4f778f10 sys/dev/mii/mii_physubr.c
--- a/sys/dev/mii/mii_physubr.c Sat Apr 10 01:59:19 2004 +0000
+++ b/sys/dev/mii/mii_physubr.c Sat Apr 10 02:32:10 2004 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: mii_physubr.c,v 1.37 2003/09/10 05:25:22 briggs Exp $ */
+/* $NetBSD: mii_physubr.c,v 1.38 2004/04/10 02:32:10 thorpej Exp $ */
/*-
* Copyright (c) 1998, 1999, 2000, 2001 The NetBSD Foundation, Inc.
@@ -42,7 +42,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: mii_physubr.c,v 1.37 2003/09/10 05:25:22 briggs Exp $");
+__KERNEL_RCSID(0, "$NetBSD: mii_physubr.c,v 1.38 2004/04/10 02:32:10 thorpej Exp $");
#include <sys/param.h>
#include <sys/device.h>
@@ -114,8 +114,9 @@
int bmcr, anar, gtcr;
if (IFM_SUBTYPE(ife->ifm_media) == IFM_AUTO) {
+ /* Force renegotiation if MIIF_DOPAUSE. */
if ((PHY_READ(sc, MII_BMCR) & BMCR_AUTOEN) == 0 ||
- (sc->mii_flags & MIIF_FORCEANEG))
+ (sc->mii_flags & (MIIF_FORCEANEG|MIIF_DOPAUSE)))
(void) mii_phy_auto(sc, 1);
return;
}
@@ -144,6 +145,19 @@
}
}
+ if (mii->mii_media.ifm_media & IFM_FLOW) {
+ if (sc->mii_flags & MIIF_IS_1000X)
+ anar |= ANAR_X_PAUSE_SYM | ANAR_X_PAUSE_ASYM;
+ else {
+ anar |= ANAR_FC;
+ /* XXX Only 1000BASE-T has PAUSE_ASYM? */
+ if ((sc->mii_flags & MIIF_HAVE_GTCR) &&
+ (sc->mii_extcapabilities &
+ (EXTSR_1000THDX|EXTSR_1000TFDX)))
+ anar |= ANAR_X_PAUSE_ASYM;
+ }
+ }
+
if (ife->ifm_media & IFM_LOOP)
bmcr |= BMCR_LOOP;
@@ -182,8 +196,14 @@
anar = BMSR_MEDIA_TO_ANAR(sc->mii_capabilities) |
ANAR_CSMA;
- if (sc->mii_flags & MIIF_DOPAUSE)
+ if (sc->mii_flags & MIIF_DOPAUSE) {
anar |= ANAR_FC;
+ /* XXX Only 1000BASE-T has PAUSE_ASYM? */
+ if ((sc->mii_flags & MIIF_HAVE_GTCR) &&
+ (sc->mii_extcapabilities &
+ (EXTSR_1000THDX|EXTSR_1000TFDX)))
+ anar |= ANAR_X_PAUSE_ASYM;
+ }
PHY_WRITE(sc, MII_ANAR, anar);
if (sc->mii_flags & MIIF_HAVE_GTCR) {
uint16_t gtcr = 0;
@@ -416,6 +436,7 @@
{
struct mii_data *mii = sc->mii_pdata;
const char *sep = "";
+ int fdx = 0;
#define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL)
#define PRINT(n) aprint_normal("%s%s", sep, (n)); sep = ", "
@@ -448,6 +469,7 @@
ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, IFM_FDX, sc->mii_inst),
MII_MEDIA_10_T_FDX);
PRINT("10baseT-FDX");
+ fdx = 1;
}
if (sc->mii_capabilities & BMSR_100TXHDX) {
ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, 0, sc->mii_inst),
@@ -458,6 +480,7 @@
ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_FDX, sc->mii_inst),
MII_MEDIA_100_TX_FDX);
PRINT("100baseTX-FDX");
+ fdx = 1;
}
if (sc->mii_capabilities & BMSR_100T4) {
ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_T4, 0, sc->mii_inst),
@@ -487,6 +510,7 @@
ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_SX, IFM_FDX,
sc->mii_inst), MII_MEDIA_1000_X_FDX);
PRINT("1000baseSX-FDX");
+ fdx = 1;
}
/*
@@ -512,6 +536,7 @@
ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T, IFM_FDX,
sc->mii_inst), MII_MEDIA_1000_T_FDX);
PRINT("1000baseT-FDX");
+ fdx = 1;
}
}
@@ -522,6 +547,8 @@
}
#undef ADD
#undef PRINT
+ if (fdx != 0 && (sc->mii_flags & MIIF_DOPAUSE))
+ mii->mii_media.ifm_mask |= IFM_ETH_FMASK;
}
void
@@ -575,3 +602,44 @@
}
return (NULL);
}
+
+/*
+ * Return the flow control status flag from MII_ANAR & MII_ANLPAR.
+ * (1000BASE only?)
+ */
+u_int
+gmii_phy_getflowcontrol(struct mii_softc *sc)
+{
+ u_int anar, anlpar;
+
+ anar = PHY_READ(sc, MII_ANAR);
+ anlpar = PHY_READ(sc, MII_ANLPAR);
+
+ 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 */
+}
diff -r e3fedc29f87b -r 1c1f4f778f10 sys/dev/mii/miivar.h
--- a/sys/dev/mii/miivar.h Sat Apr 10 01:59:19 2004 +0000
+++ b/sys/dev/mii/miivar.h Sat Apr 10 02:32:10 2004 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: miivar.h,v 1.37 2003/07/01 22:58:48 msaitoh Exp $ */
+/* $NetBSD: miivar.h,v 1.38 2004/04/10 02:32:10 thorpej Exp $ */
/*-
* Copyright (c) 1998, 1999, 2000, 2001 The NetBSD Foundation, Inc.
@@ -255,6 +255,8 @@
void mii_phy_update __P((struct mii_softc *, int));
int mii_phy_statusmsg __P((struct mii_softc *));
+u_int gmii_phy_getflowcontrol __P((struct mii_softc *));
+
void ukphy_status __P((struct mii_softc *));
u_int mii_oui __P((u_int, u_int));
Home |
Main Index |
Thread Index |
Old Index