summaryrefslogtreecommitdiffstats
path: root/sys/dev/mii/e1000phy.c
diff options
context:
space:
mode:
authorwilko <wilko@FreeBSD.org>2003-09-20 10:53:08 +0000
committerwilko <wilko@FreeBSD.org>2003-09-20 10:53:08 +0000
commit3d954f412f973cdef480c3711423fcadd2760349 (patch)
treecdb2a8a3cec0a4df31f4f70dc242b3e215c2ae39 /sys/dev/mii/e1000phy.c
parent6e6824e4bcd845d2681902b69bf6bd16809bbc05 (diff)
downloadFreeBSD-src-3d954f412f973cdef480c3711423fcadd2760349.zip
FreeBSD-src-3d954f412f973cdef480c3711423fcadd2760349.tar.gz
Add support for SK-9521 V2.0 and 3COM 3C940.
Tested at 100Mbit only, using Asus P4P800 onboard 3C940. The -stable version of this patch I have in use for ~2 weeks now, and works just fine for me. Based on: Nathan L. Binkert's patch for OpenBSD Patch submitted by and thanks to: Jung-uk Kim <jkim@niksun.com> MFC after: 2 weeks
Diffstat (limited to 'sys/dev/mii/e1000phy.c')
-rw-r--r--sys/dev/mii/e1000phy.c134
1 files changed, 85 insertions, 49 deletions
diff --git a/sys/dev/mii/e1000phy.c b/sys/dev/mii/e1000phy.c
index 1975986..6f9f458 100644
--- a/sys/dev/mii/e1000phy.c
+++ b/sys/dev/mii/e1000phy.c
@@ -36,6 +36,13 @@ __FBSDID("$FreeBSD$");
* driver for the Marvell 88E1000 series external 1000/100/10-BT PHY.
*/
+/*
+ * Support added for the Marvell 88E1011 (Alaska) 1000/100/10baseTX and
+ * 1000baseSX PHY.
+ * Nathan Binkert <nate@openbsd.org>
+ * Jung-uk Kim <jkim@niksun.com>
+ */
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
@@ -88,8 +95,9 @@ e1000phy_probe(device_t dev)
ma = device_get_ivars(dev);
id = ((ma->mii_id1 << 16) | ma->mii_id2) & E1000_ID_MASK;
-
- if (id != E1000_ID_88E1000 && id != E1000_ID_88E1000S) {
+ if (id != E1000_ID_88E1000
+ && id != E1000_ID_88E1000S
+ && id != E1000_ID_88E1011) {
return ENXIO;
}
@@ -103,6 +111,7 @@ e1000phy_attach(device_t dev)
struct mii_softc *sc;
struct mii_attach_args *ma;
struct mii_data *mii;
+ u_int32_t id;
getenv_int("e1000phy_debug", &e1000phy_debug);
@@ -116,39 +125,49 @@ e1000phy_attach(device_t dev)
sc->mii_phy = ma->mii_phyno;
sc->mii_service = e1000phy_service;
sc->mii_pdata = mii;
-
sc->mii_flags |= MIIF_NOISOLATE;
+
+ id = ((ma->mii_id1 << 16) | ma->mii_id2) & E1000_ID_MASK;
+ if (id == E1000_ID_88E1011
+ && (PHY_READ(sc, E1000_ESSR) & E1000_ESSR_FIBER_LINK))
+ sc->mii_flags |= MIIF_HAVEFIBER;
mii->mii_instance++;
e1000phy_reset(sc);
device_printf(dev, " ");
#define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL)
-/*
- ADD(IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, sc->mii_inst),
- E1000_CR_ISOLATE);
-*/
- ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, 0, sc->mii_inst),
- E1000_CR_SPEED_10);
- printf("10baseT, ");
- ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, IFM_FDX, sc->mii_inst),
- E1000_CR_SPEED_10 | E1000_CR_FULL_DUPLEX);
- printf("10baseT-FDX, ");
- ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, 0, sc->mii_inst),
- E1000_CR_SPEED_100);
- printf("100baseTX, ");
- ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_FDX, sc->mii_inst),
- E1000_CR_SPEED_100 | E1000_CR_FULL_DUPLEX);
- printf("100baseTX-FDX, ");
- /*
- * 1000BT-simplex not supported; driver must ignore this entry,
- * but it must be present in order to manually set full-duplex.
- */
- ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T, 0, sc->mii_inst),
- E1000_CR_SPEED_1000);
- ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T, IFM_FDX, sc->mii_inst),
- E1000_CR_SPEED_1000 | E1000_CR_FULL_DUPLEX);
- printf("1000baseTX-FDX, ");
+ if ((sc->mii_flags & MIIF_HAVEFIBER) == 0) {
+#if 0
+ ADD(IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, sc->mii_inst),
+ E1000_CR_ISOLATE);
+#endif
+ ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, 0, sc->mii_inst),
+ E1000_CR_SPEED_10);
+ printf("10baseT, ");
+ ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, IFM_FDX, sc->mii_inst),
+ E1000_CR_SPEED_10 | E1000_CR_FULL_DUPLEX);
+ printf("10baseT-FDX, ");
+ ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, 0, sc->mii_inst),
+ E1000_CR_SPEED_100);
+ printf("100baseTX, ");
+ ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_FDX, sc->mii_inst),
+ E1000_CR_SPEED_100 | E1000_CR_FULL_DUPLEX);
+ printf("100baseTX-FDX, ");
+ /*
+ * 1000BT-simplex not supported; driver must ignore this entry,
+ * but it must be present in order to manually set full-duplex.
+ */
+ ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T, 0, sc->mii_inst),
+ E1000_CR_SPEED_1000);
+ ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T, IFM_FDX, sc->mii_inst),
+ E1000_CR_SPEED_1000 | E1000_CR_FULL_DUPLEX);
+ printf("1000baseTX-FDX, ");
+ } else {
+ ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_SX, IFM_FDX, sc->mii_inst),
+ E1000_CR_SPEED_1000 | E1000_CR_FULL_DUPLEX);
+ printf("1000baseSX-FDX, ");
+ }
ADD(IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, 0, sc->mii_inst), 0);
printf("auto\n");
#undef ADD
@@ -242,6 +261,14 @@ e1000phy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
(void)e1000phy_mii_phy_auto(sc);
break;
+ case IFM_1000_SX:
+ e1000phy_reset(sc);
+
+ PHY_WRITE(sc, E1000_CR,
+ E1000_CR_FULL_DUPLEX | E1000_CR_SPEED_1000);
+ PHY_WRITE(sc, E1000_AR, E1000_FA_1000X_FD);
+ break;
+
case IFM_100_TX:
e1000phy_reset(sc);
@@ -353,27 +380,34 @@ e1000phy_status(struct mii_softc *sc)
return;
}
- if (ssr & E1000_SSR_1000MBS)
- mii->mii_media_active |= IFM_1000_T;
- else if (ssr & E1000_SSR_100MBS)
- mii->mii_media_active |= IFM_100_TX;
- else
- mii->mii_media_active |= IFM_10_T;
+ if ((sc->mii_flags & MIIF_HAVEFIBER) == 0) {
+ if (ssr & E1000_SSR_1000MBS)
+ mii->mii_media_active |= IFM_1000_T;
+ else if (ssr & E1000_SSR_100MBS)
+ mii->mii_media_active |= IFM_100_TX;
+ else
+ mii->mii_media_active |= IFM_10_T;
+ } else {
+ if (ssr & E1000_SSR_1000MBS)
+ mii->mii_media_active |= IFM_1000_SX;
+ }
if (ssr & E1000_SSR_DUPLEX)
mii->mii_media_active |= IFM_FDX;
else
mii->mii_media_active |= IFM_HDX;
- /* 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;
+ if ((sc->mii_flags & MIIF_HAVEFIBER) == 0) {
+ /* 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;
+ }
}
}
@@ -381,12 +415,14 @@ static int
e1000phy_mii_phy_auto(struct mii_softc *mii)
{
- PHY_WRITE(mii, E1000_AR, E1000_AR_10T | E1000_AR_10T_FD |
- E1000_AR_100TX | E1000_AR_100TX_FD |
- E1000_AR_PAUSE | E1000_AR_ASM_DIR);
- PHY_WRITE(mii, E1000_1GCR, E1000_1GCR_1000T_FD);
- PHY_WRITE(mii, E1000_CR,
- E1000_CR_AUTO_NEG_ENABLE | E1000_CR_RESTART_AUTO_NEG);
+ if ((mii->mii_flags & MIIF_HAVEFIBER) == 0) {
+ PHY_WRITE(mii, E1000_AR, E1000_AR_10T | E1000_AR_10T_FD |
+ E1000_AR_100TX | E1000_AR_100TX_FD |
+ E1000_AR_PAUSE | E1000_AR_ASM_DIR);
+ PHY_WRITE(mii, E1000_1GCR, E1000_1GCR_1000T_FD);
+ PHY_WRITE(mii, E1000_CR,
+ E1000_CR_AUTO_NEG_ENABLE | E1000_CR_RESTART_AUTO_NEG);
+ }
return (EJUSTRETURN);
}
OpenPOWER on IntegriCloud