Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/mii - Use auto-negotiation when forcing 1000BASE-T.



details:   https://anonhg.NetBSD.org/src/rev/de38da990d3c
branches:  trunk
changeset: 461048:de38da990d3c
user:      msaitoh <msaitoh%NetBSD.org@localhost>
date:      Thu Nov 14 09:06:21 2019 +0000

description:
- Use auto-negotiation when forcing 1000BASE-T.
- Add XXX comment for strange pause setting code. I suspect this is wrong.
- On my environments, 1000BASE-T half duplex doesn't work, so we might remove
  IFM_1000T_HDX from this device in future.

diffstat:

 sys/dev/mii/ipgphy.c |  59 ++++++++++++++++++++++-----------------------------
 1 files changed, 26 insertions(+), 33 deletions(-)

diffs (140 lines):

diff -r 8561215a6c43 -r de38da990d3c sys/dev/mii/ipgphy.c
--- a/sys/dev/mii/ipgphy.c      Thu Nov 14 09:00:23 2019 +0000
+++ b/sys/dev/mii/ipgphy.c      Thu Nov 14 09:06:21 2019 +0000
@@ -32,7 +32,7 @@
  * Driver for the IC Plus IP1000A/IP1001 10/100/1000 PHY.
  */
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ipgphy.c,v 1.3 2019/11/14 09:00:23 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ipgphy.c,v 1.4 2019/11/14 09:06:21 msaitoh Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -60,7 +60,7 @@
 
 static int     ipgphy_service(struct mii_softc *, struct mii_data *, int);
 static void    ipgphy_status(struct mii_softc *);
-static int     ipgphy_mii_phy_auto(struct mii_softc *);
+static int     ipgphy_mii_phy_auto(struct mii_softc *, u_int);
 static void    ipgphy_load_dspcode(struct mii_softc *);
 static void    ipgphy_reset(struct mii_softc *);
 
@@ -126,7 +126,7 @@
 ipgphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
 {
        struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
-       uint16_t gig, reg, speed;
+       uint16_t reg, speed;
 
        switch (cmd) {
        case MII_POLLSTAT:
@@ -154,16 +154,13 @@
 
                switch (IFM_SUBTYPE(ife->ifm_media)) {
                case IFM_AUTO:
-                       (void)ipgphy_mii_phy_auto(sc);
-                       goto done;
-                       break;
-
                case IFM_1000_T:
                        /*
-                        * XXX
-                        * Manual 1000baseT setting doesn't seem to work.
+                        * This device is required to do auto negotiation
+                        * on 1000BASE-T.
                         */
-                       speed = BMCR_S1000;
+                       (void)ipgphy_mii_phy_auto(sc, ife->ifm_media);
+                       goto done;
                        break;
 
                case IFM_100_TX:
@@ -178,26 +175,11 @@
                        return EINVAL;
                }
 
-               if (((ife->ifm_media & IFM_GMASK) & IFM_FDX) != 0) {
+               if ((ife->ifm_media & IFM_FDX) != 0)
                        speed |= BMCR_FDX;
-                       gig = GTCR_ADV_1000TFDX;
-               } else
-                       gig = GTCR_ADV_1000THDX;
 
                PHY_WRITE(sc, MII_100T2CR, 0);
                PHY_WRITE(sc, MII_BMCR, speed);
-
-               if (IFM_SUBTYPE(ife->ifm_media) != IFM_1000_T)
-                       break;
-
-               PHY_WRITE(sc, MII_100T2CR, gig);
-               PHY_WRITE(sc, MII_BMCR, speed);
-
-               if (mii->mii_media.ifm_media & IFM_ETH_MASTER)
-                       gig |= GTCR_MAN_MS | GTCR_ADV_MS;
-
-               PHY_WRITE(sc, MII_100T2CR, gig);
-
 done:
                break;
 
@@ -211,7 +193,8 @@
                        return 0;
 
                /* Only used for autonegotiation. */
-               if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) {
+               if ((IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) &&
+                   (IFM_SUBTYPE(ife->ifm_media) != IFM_1000_T)) {
                        sc->mii_ticks = 0;
                        break;
                }
@@ -242,7 +225,7 @@
                        break;
 
                sc->mii_ticks = 0;
-               ipgphy_mii_phy_auto(sc);
+               ipgphy_mii_phy_auto(sc, ife->ifm_media);
                break;
        }
 
@@ -320,26 +303,36 @@
 }
 
 static int
-ipgphy_mii_phy_auto(struct mii_softc *sc)
+ipgphy_mii_phy_auto(struct mii_softc *sc, u_int media)
 {
        uint16_t reg = 0;
+       u_int subtype = IFM_SUBTYPE(media);
 
+       /* XXX Is it requreid ? */
        if (sc->mii_mpd_model == MII_MODEL_xxICPLUS_IP1001) {
                PHY_READ(sc, MII_ANAR, &reg);
                reg &= ~(ANAR_PAUSE_SYM | ANAR_PAUSE_ASYM);
                reg |= ANAR_NP;
        }
 
-       reg |= ANAR_10 | ANAR_10_FD | ANAR_TX | ANAR_TX_FD;
+       if (subtype == IFM_AUTO)
+               reg |= ANAR_10 | ANAR_10_FD | ANAR_TX | ANAR_TX_FD;
 
        if (sc->mii_flags & MIIF_DOPAUSE)
                reg |= ANAR_PAUSE_SYM | ANAR_PAUSE_ASYM;
 
        PHY_WRITE(sc, MII_ANAR, reg | ANAR_CSMA);
 
-       reg = GTCR_ADV_1000TFDX | GTCR_ADV_1000THDX;
-       if (sc->mii_mpd_model != MII_MODEL_xxICPLUS_IP1001)
-               reg |= GTCR_ADV_MS;
+       if (subtype == IFM_AUTO)
+               reg = GTCR_ADV_1000TFDX | GTCR_ADV_1000THDX;
+       else if (subtype == IFM_1000_T) {
+               if ((media & IFM_FDX) != 0)
+                       reg = GTCR_ADV_1000TFDX;
+               else
+                       reg = GTCR_ADV_1000THDX;
+       } else
+               reg = 0;
+
        PHY_WRITE(sc, MII_100T2CR, reg);
 
        PHY_WRITE(sc, MII_BMCR, BMCR_FDX | BMCR_AUTOEN | BMCR_STARTNEG);



Home | Main Index | Thread Index | Old Index