summaryrefslogtreecommitdiffstats
path: root/sys/dev/mii/e1000phy.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/mii/e1000phy.c')
-rw-r--r--sys/dev/mii/e1000phy.c82
1 files changed, 28 insertions, 54 deletions
diff --git a/sys/dev/mii/e1000phy.c b/sys/dev/mii/e1000phy.c
index f49f7c4..1c0a267 100644
--- a/sys/dev/mii/e1000phy.c
+++ b/sys/dev/mii/e1000phy.c
@@ -91,7 +91,7 @@ DRIVER_MODULE(e1000phy, miibus, e1000phy_driver, e1000phy_devclass, 0, 0);
static int e1000phy_service(struct mii_softc *, struct mii_data *, int);
static void e1000phy_status(struct mii_softc *);
static void e1000phy_reset(struct mii_softc *);
-static int e1000phy_mii_phy_auto(struct e1000phy_softc *);
+static int e1000phy_mii_phy_auto(struct e1000phy_softc *, int);
static const struct mii_phydesc e1000phys[] = {
MII_PHY_DESC(MARVELL, E1000),
@@ -146,6 +146,8 @@ e1000phy_attach(device_t dev)
sc->mii_service = e1000phy_service;
sc->mii_pdata = mii;
+ sc->mii_flags |= MIIF_NOMANPAUSE;
+
esc->mii_model = MII_MODEL(ma->mii_id2);
ifp = sc->mii_pdata->mii_ifp;
if (strcmp(ifp->if_dname, "msk") == 0 &&
@@ -323,7 +325,7 @@ e1000phy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
break;
if (IFM_SUBTYPE(ife->ifm_media) == IFM_AUTO) {
- e1000phy_mii_phy_auto(esc);
+ e1000phy_mii_phy_auto(esc, ife->ifm_media);
break;
}
@@ -366,27 +368,14 @@ e1000phy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
reg &= ~E1000_CR_AUTO_NEG_ENABLE;
PHY_WRITE(sc, E1000_CR, reg | E1000_CR_RESET);
- /*
- * 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 (IFM_SUBTYPE(ife->ifm_media) == IFM_1000_T ||
- (IFM_SUBTYPE(ife->ifm_media) == IFM_1000_SX)) {
- if ((mii->mii_ifp->if_flags & IFF_LINK0))
- PHY_WRITE(sc, E1000_1GCR, gig |
- E1000_1GCR_MS_ENABLE | E1000_1GCR_MS_VALUE);
- else
- PHY_WRITE(sc, E1000_1GCR, gig |
- E1000_1GCR_MS_ENABLE);
- } else {
- if ((sc->mii_extcapabilities &
- (EXTSR_1000TFDX | EXTSR_1000THDX)) != 0)
- PHY_WRITE(sc, E1000_1GCR, 0);
- }
+ if (IFM_SUBTYPE(ife->ifm_media) == IFM_1000_T) {
+ gig |= E1000_1GCR_MS_ENABLE;
+ if ((ife->ifm_media & IFM_ETH_MASTER) != 0)
+ gig |= E1000_1GCR_MS_VALUE;
+ PHY_WRITE(sc, E1000_1GCR, gig);
+ } else if ((sc->mii_extcapabilities &
+ (EXTSR_1000TFDX | EXTSR_1000THDX)) != 0)
+ PHY_WRITE(sc, E1000_1GCR, 0);
PHY_WRITE(sc, E1000_AR, E1000_AR_SELECTOR_FIELD);
PHY_WRITE(sc, E1000_CR, speed | E1000_CR_RESET);
done:
@@ -424,7 +413,7 @@ done:
sc->mii_ticks = 0;
e1000phy_reset(sc);
- e1000phy_mii_phy_auto(esc);
+ e1000phy_mii_phy_auto(esc, ife->ifm_media);
break;
}
@@ -440,7 +429,7 @@ static void
e1000phy_status(struct mii_softc *sc)
{
struct mii_data *mii = sc->mii_pdata;
- int bmcr, bmsr, gsr, ssr, ar, lpar;
+ int bmcr, bmsr, ssr;
mii->mii_media_status = IFM_AVALID;
mii->mii_media_active = IFM_ETHER;
@@ -485,38 +474,22 @@ e1000phy_status(struct mii_softc *sc)
mii->mii_media_active |= IFM_1000_SX;
}
- if (ssr & E1000_SSR_DUPLEX)
+ if (ssr & E1000_SSR_DUPLEX) {
mii->mii_media_active |= IFM_FDX;
- else
+ if ((sc->mii_flags & MIIF_HAVEFIBER) == 0)
+ mii->mii_media_active |= mii_phy_flowstatus(sc);
+ } else
mii->mii_media_active |= IFM_HDX;
- if ((sc->mii_flags & MIIF_HAVEFIBER) == 0) {
- ar = PHY_READ(sc, E1000_AR);
- lpar = PHY_READ(sc, E1000_LPAR);
- /* FLAG0==rx-flow-control FLAG1==tx-flow-control */
- if ((ar & E1000_AR_PAUSE) && (lpar & E1000_LPAR_PAUSE)) {
- mii->mii_media_active |= IFM_FLAG0 | IFM_FLAG1;
- } else if (!(ar & E1000_AR_PAUSE) && (ar & E1000_AR_ASM_DIR) &&
- (lpar & E1000_LPAR_PAUSE) && (lpar & E1000_LPAR_ASM_DIR)) {
- mii->mii_media_active |= IFM_FLAG1;
- } else if ((ar & E1000_AR_PAUSE) && (ar & E1000_AR_ASM_DIR) &&
- !(lpar & E1000_LPAR_PAUSE) && (lpar & E1000_LPAR_ASM_DIR)) {
- mii->mii_media_active |= IFM_FLAG0;
- }
- }
-
- /* FLAG2 : local PHY resolved to MASTER */
- if ((IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_T) ||
- (IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_SX)) {
- PHY_READ(sc, E1000_1GSR);
- gsr = PHY_READ(sc, E1000_1GSR);
- if ((gsr & E1000_1GSR_MS_CONFIG_RES) != 0)
- mii->mii_media_active |= IFM_FLAG2;
+ if (IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_T) {
+ if (((PHY_READ(sc, E1000_1GSR) | PHY_READ(sc, E1000_1GSR)) &
+ E1000_1GSR_MS_CONFIG_RES) != 0)
+ mii->mii_media_active |= IFM_ETH_MASTER;
}
}
static int
-e1000phy_mii_phy_auto(struct e1000phy_softc *esc)
+e1000phy_mii_phy_auto(struct e1000phy_softc *esc, int media)
{
struct mii_softc *sc;
uint16_t reg;
@@ -525,12 +498,13 @@ e1000phy_mii_phy_auto(struct e1000phy_softc *esc)
if ((sc->mii_flags & MIIF_HAVEFIBER) == 0) {
reg = PHY_READ(sc, E1000_AR);
reg |= E1000_AR_10T | E1000_AR_10T_FD |
- E1000_AR_100TX | E1000_AR_100TX_FD |
- E1000_AR_PAUSE | E1000_AR_ASM_DIR;
+ E1000_AR_100TX | E1000_AR_100TX_FD;
+ if ((media & IFM_FLOW) != 0 ||
+ (sc->mii_flags & MIIF_FORCEPAUSE) != 0)
+ reg |= E1000_AR_PAUSE | E1000_AR_ASM_DIR;
PHY_WRITE(sc, E1000_AR, reg | E1000_AR_SELECTOR_FIELD);
} else
- PHY_WRITE(sc, E1000_AR, E1000_FA_1000X_FD | E1000_FA_1000X |
- E1000_FA_SYM_PAUSE | E1000_FA_ASYM_PAUSE);
+ PHY_WRITE(sc, E1000_AR, E1000_FA_1000X_FD | E1000_FA_1000X);
if ((sc->mii_extcapabilities & (EXTSR_1000TFDX | EXTSR_1000THDX)) != 0)
PHY_WRITE(sc, E1000_1GCR,
E1000_1GCR_1000T_FD | E1000_1GCR_1000T);
OpenPOWER on IntegriCloud