aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/mii/ip1000phy.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/mii/ip1000phy.c')
-rw-r--r--sys/dev/mii/ip1000phy.c63
1 files changed, 14 insertions, 49 deletions
diff --git a/sys/dev/mii/ip1000phy.c b/sys/dev/mii/ip1000phy.c
index b60fab6fc7835..242baf7ed464e 100644
--- a/sys/dev/mii/ip1000phy.c
+++ b/sys/dev/mii/ip1000phy.c
@@ -84,7 +84,7 @@ DRIVER_MODULE(ip1000phy, miibus, ip1000phy_driver, ip1000phy_devclass, 0, 0);
static int ip1000phy_service(struct mii_softc *, struct mii_data *, int);
static void ip1000phy_status(struct mii_softc *);
static void ip1000phy_reset(struct mii_softc *);
-static int ip1000phy_mii_phy_auto(struct mii_softc *);
+static int ip1000phy_mii_phy_auto(struct mii_softc *, int);
static const struct mii_phydesc ip1000phys[] = {
MII_PHY_DESC(ICPLUS, IP1000A),
@@ -120,7 +120,7 @@ ip1000phy_attach(device_t dev)
sc->mii_service = ip1000phy_service;
sc->mii_pdata = mii;
- sc->mii_flags |= MIIF_NOISOLATE;
+ sc->mii_flags |= MIIF_NOISOLATE | MIIF_NOMANPAUSE;
isc->model = MII_MODEL(ma->mii_id2);
isc->revision = MII_REV(ma->mii_id2);
@@ -163,9 +163,8 @@ ip1000phy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
ip1000phy_reset(sc);
switch (IFM_SUBTYPE(ife->ifm_media)) {
case IFM_AUTO:
- (void)ip1000phy_mii_phy_auto(sc);
+ (void)ip1000phy_mii_phy_auto(sc, ife->ifm_media);
goto done;
- break;
case IFM_1000_T:
/*
@@ -199,26 +198,10 @@ ip1000phy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
if (IFM_SUBTYPE(ife->ifm_media) != IFM_1000_T)
break;
+ gig |= IP1000PHY_1000CR_MASTER | IP1000PHY_1000CR_MANUAL;
+ if ((ife->ifm_media & IFM_ETH_MASTER) != 0)
+ gig |= IP1000PHY_1000CR_MMASTER;
PHY_WRITE(sc, IP1000PHY_MII_1000CR, gig);
- PHY_WRITE(sc, IP1000PHY_MII_BMCR, speed);
-
- /*
- * When setting the link manually, one side must
- * be the master and the other the slave. However
- * ifmedia doesn't give us a good way to specify
- * this, so we fake it by using one of the LINK
- * flags. If LINK0 is set, we program the PHY to
- * be a master, otherwise it's a slave.
- */
- if ((mii->mii_ifp->if_flags & IFF_LINK0))
- PHY_WRITE(sc, IP1000PHY_MII_1000CR, gig |
- IP1000PHY_1000CR_MASTER |
- IP1000PHY_1000CR_MMASTER |
- IP1000PHY_1000CR_MANUAL);
- else
- PHY_WRITE(sc, IP1000PHY_MII_1000CR, gig |
- IP1000PHY_1000CR_MASTER |
- IP1000PHY_1000CR_MANUAL);
done:
break;
@@ -258,7 +241,7 @@ done:
break;
sc->mii_ticks = 0;
- ip1000phy_mii_phy_auto(sc);
+ ip1000phy_mii_phy_auto(sc, ife->ifm_media);
break;
}
@@ -276,7 +259,6 @@ ip1000phy_status(struct mii_softc *sc)
struct ip1000phy_softc *isc;
struct mii_data *mii = sc->mii_pdata;
uint32_t bmsr, bmcr, stat;
- uint32_t ar, lpar;
isc = (struct ip1000phy_softc *)sc;
@@ -345,36 +327,18 @@ ip1000phy_status(struct mii_softc *sc)
mii->mii_media_active |= IFM_HDX;
}
- ar = PHY_READ(sc, IP1000PHY_MII_ANAR);
- lpar = PHY_READ(sc, IP1000PHY_MII_ANLPAR);
-
- /*
- * FLAG0 : Rx flow-control
- * FLAG1 : Tx flow-control
- */
- if ((ar & IP1000PHY_ANAR_PAUSE) && (lpar & IP1000PHY_ANLPAR_PAUSE))
- mii->mii_media_active |= IFM_FLAG0 | IFM_FLAG1;
- else if (!(ar & IP1000PHY_ANAR_PAUSE) && (ar & IP1000PHY_ANAR_APAUSE) &&
- (lpar & IP1000PHY_ANLPAR_PAUSE) && (lpar & IP1000PHY_ANLPAR_APAUSE))
- mii->mii_media_active |= IFM_FLAG1;
- else if ((ar & IP1000PHY_ANAR_PAUSE) && (ar & IP1000PHY_ANAR_APAUSE) &&
- !(lpar & IP1000PHY_ANLPAR_PAUSE) &&
- (lpar & IP1000PHY_ANLPAR_APAUSE)) {
- mii->mii_media_active |= IFM_FLAG0;
- }
+ if ((mii->mii_media_active & IFM_FDX) != 0)
+ mii->mii_media_active |= mii_phy_flowstatus(sc);
- /*
- * FLAG2 : local PHY resolved to MASTER
- */
if ((mii->mii_media_active & IFM_1000_T) != 0) {
stat = PHY_READ(sc, IP1000PHY_MII_1000SR);
if ((stat & IP1000PHY_1000SR_MASTER) != 0)
- mii->mii_media_active |= IFM_FLAG2;
+ mii->mii_media_active |= IFM_ETH_MASTER;
}
}
static int
-ip1000phy_mii_phy_auto(struct mii_softc *sc)
+ip1000phy_mii_phy_auto(struct mii_softc *sc, int media)
{
struct ip1000phy_softc *isc;
uint32_t reg;
@@ -386,8 +350,9 @@ ip1000phy_mii_phy_auto(struct mii_softc *sc)
reg |= IP1000PHY_ANAR_NP;
}
reg |= IP1000PHY_ANAR_10T | IP1000PHY_ANAR_10T_FDX |
- IP1000PHY_ANAR_100TX | IP1000PHY_ANAR_100TX_FDX |
- IP1000PHY_ANAR_PAUSE | IP1000PHY_ANAR_APAUSE;
+ IP1000PHY_ANAR_100TX | IP1000PHY_ANAR_100TX_FDX;
+ if ((media & IFM_FLOW) != 0 || (sc->mii_flags & MIIF_FORCEPAUSE) != 0)
+ reg |= IP1000PHY_ANAR_PAUSE | IP1000PHY_ANAR_APAUSE;
PHY_WRITE(sc, IP1000PHY_MII_ANAR, reg | IP1000PHY_ANAR_CSMA);
reg = IP1000PHY_1000CR_1000T | IP1000PHY_1000CR_1000T_FDX;