diff options
author | wilko <wilko@FreeBSD.org> | 2003-09-20 10:53:08 +0000 |
---|---|---|
committer | wilko <wilko@FreeBSD.org> | 2003-09-20 10:53:08 +0000 |
commit | 3d954f412f973cdef480c3711423fcadd2760349 (patch) | |
tree | cdb2a8a3cec0a4df31f4f70dc242b3e215c2ae39 /sys/dev/mii | |
parent | 6e6824e4bcd845d2681902b69bf6bd16809bbc05 (diff) | |
download | FreeBSD-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')
-rw-r--r-- | sys/dev/mii/e1000phy.c | 134 | ||||
-rw-r--r-- | sys/dev/mii/e1000phyreg.h | 28 | ||||
-rw-r--r-- | sys/dev/mii/miidevs | 2 |
3 files changed, 114 insertions, 50 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); } diff --git a/sys/dev/mii/e1000phyreg.h b/sys/dev/mii/e1000phyreg.h index e7dfb36..bdfc665 100644 --- a/sys/dev/mii/e1000phyreg.h +++ b/sys/dev/mii/e1000phyreg.h @@ -107,6 +107,7 @@ #define E1000_ID2 0x03 /* ID register 2 */ #define E1000_ID_88E1000 0x01410C50 #define E1000_ID_88E1000S 0x01410C40 +#define E1000_ID_88E1011 0x01410C20 #define E1000_ID_MASK 0xFFFFFFF0 #define E1000_AR 0x04 /* autonegotiation advertise reg */ @@ -122,6 +123,15 @@ #define E1000_AR_NEXT_PAGE 0x8000 #define E1000_AR_SPEED_MASK 0x01E0 +/* Autonegotiation register bits for fiber cards (Alaska Only!) */ +#define E1000_FA_1000X_FD 0x0020 +#define E1000_FA_1000X 0x0040 +#define E1000_FA_SYM_PAUSE 0x0080 +#define E1000_FA_ASYM_PAUSE 0x0100 +#define E1000_FA_FAULT1 0x1000 +#define E1000_FA_FAULT2 0x2000 +#define E1000_FA_NEXT_PAGE 0x8000 + #define E1000_LPAR 0x05 /* autoneg link partner abilities reg */ #define E1000_LPAR_SELECTOR_FIELD 0x0001 #define E1000_LPAR_10T 0x0020 @@ -135,6 +145,16 @@ #define E1000_LPAR_ACKNOWLEDGE 0x4000 #define E1000_LPAR_NEXT_PAGE 0x8000 +/* autoneg link partner ability register bits for fiber cards (Alaska Only!) */ +#define E1000_FPAR_1000X_FD 0x0020 +#define E1000_FPAR_1000X 0x0040 +#define E1000_FPAR_SYM_PAUSE 0x0080 +#define E1000_FPAR_ASYM_PAUSE 0x0100 +#define E1000_FPAR_FAULT1 0x1000 +#define E1000_FPAR_FAULT2 0x2000 +#define E1000_FPAR_ACK 0x4000 +#define E1000_FPAR_NEXT_PAGE 0x8000 + #define E1000_ER 0x06 /* autoneg expansion reg */ #define E1000_ER_LP_NWAY 0x0001 #define E1000_ER_PAGE_RXD 0x0002 @@ -284,3 +304,11 @@ #define E1000_LCR_PULSE_340_670MS 0x5000 #define E1000_LCR_PULSE_670_13S 0x6000 #define E1000_LCR_PULSE_13_26S 0x7000 + +/* The following register is found only on the 88E1011 Alaska PHY */ +#define E1000_ESSR 0x1B /* Extended PHY specific sts */ +#define E1000_ESSR_FIBER_LINK 0x2000 +#define E1000_ESSR_GMII_COPPER 0x000f +#define E1000_ESSR_GMII_FIBER 0x0007 +#define E1000_ESSR_TBI_COPPER 0x000d +#define E1000_ESSR_TBI_FIBER 0x0005 diff --git a/sys/dev/mii/miidevs b/sys/dev/mii/miidevs index c430fa4..1f58417 100644 --- a/sys/dev/mii/miidevs +++ b/sys/dev/mii/miidevs @@ -172,5 +172,5 @@ model XAQTI XMACII 0x0000 XaQti Corp. XMAC II gigabit interface /* Marvell Semiconductor PHYs */ model MARVELL E1000 0x0000 Marvell 88E1000 Gigabit PHY +model MARVELL E1011 0x0002 Marvell 88E1011 Gigabit PHY model xxMARVELL E1000 0x0005 Marvell 88E1000 Gigabit PHY - |