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