diff options
author | phk <phk@FreeBSD.org> | 2002-04-29 07:18:26 +0000 |
---|---|---|
committer | phk <phk@FreeBSD.org> | 2002-04-29 07:18:26 +0000 |
commit | 03000f5700d4ab2a38021db193c2d41c54479b59 (patch) | |
tree | 6b8e043c8285a57ab8885d82ba7b860ba0da3234 /sys | |
parent | 9e268405661ecd7735e088325129da32fd8546f6 (diff) | |
download | FreeBSD-src-03000f5700d4ab2a38021db193c2d41c54479b59.zip FreeBSD-src-03000f5700d4ab2a38021db193c2d41c54479b59.tar.gz |
Moving closer to being able to use NetBSD's generic mii_set_media()
function.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/mii/mii_physubr.c | 120 | ||||
-rw-r--r-- | sys/dev/mii/miivar.h | 36 | ||||
-rw-r--r-- | sys/dev/mii/nsgphy.c | 5 |
3 files changed, 141 insertions, 20 deletions
diff --git a/sys/dev/mii/mii_physubr.c b/sys/dev/mii/mii_physubr.c index 1add691..2bc17b0 100644 --- a/sys/dev/mii/mii_physubr.c +++ b/sys/dev/mii/mii_physubr.c @@ -63,8 +63,99 @@ static const char rcsid[] = "$FreeBSD$"; #endif +/* + * Media to register setting conversion table. Order matters. + */ +const struct mii_media mii_media_table[MII_NMEDIA] = { + /* None */ + { BMCR_ISO, ANAR_CSMA, + 0, }, + + /* 10baseT */ + { BMCR_S10, ANAR_CSMA|ANAR_10, + 0, }, + + /* 10baseT-FDX */ + { BMCR_S10|BMCR_FDX, ANAR_CSMA|ANAR_10_FD, + 0, }, + + /* 100baseT4 */ + { BMCR_S100, ANAR_CSMA|ANAR_T4, + 0, }, + + /* 100baseTX */ + { BMCR_S100, ANAR_CSMA|ANAR_TX, + 0, }, + + /* 100baseTX-FDX */ + { BMCR_S100|BMCR_FDX, ANAR_CSMA|ANAR_TX_FD, + 0, }, + + /* 1000baseX */ + { BMCR_S1000, ANAR_CSMA, + 0, }, + + /* 1000baseX-FDX */ + { BMCR_S1000|BMCR_FDX, ANAR_CSMA, + 0, }, + + /* 1000baseT */ + { BMCR_S1000, ANAR_CSMA, + GTCR_ADV_1000THDX }, + + /* 1000baseT-FDX */ + { BMCR_S1000, ANAR_CSMA, + GTCR_ADV_1000TFDX }, +}; + void mii_phy_auto_timeout(void *); +void +mii_phy_setmedia(struct mii_softc *sc) +{ + struct mii_data *mii = sc->mii_pdata; + struct ifmedia_entry *ife = mii->mii_media.ifm_cur; + int bmcr, anar, gtcr; + + if (IFM_SUBTYPE(ife->ifm_media) == IFM_AUTO) { + if ((PHY_READ(sc, MII_BMCR) & BMCR_AUTOEN) == 0) + (void) mii_phy_auto(sc, 1); + return; + } + + /* + * Table index is stored in the media entry. + */ + +#ifdef DIAGNOSTIC + if (ife->ifm_data < 0 || ife->ifm_data >= MII_NMEDIA) + panic("mii_phy_setmedia"); +#endif + + anar = mii_media_table[ife->ifm_data].mm_anar; + bmcr = mii_media_table[ife->ifm_data].mm_bmcr; + gtcr = mii_media_table[ife->ifm_data].mm_gtcr; + + if (mii->mii_media.ifm_media & IFM_ETH_MASTER) { + switch (IFM_SUBTYPE(ife->ifm_media)) { + case IFM_1000_T: + gtcr |= GTCR_MAN_MS|GTCR_ADV_MS; + break; + + default: + panic("mii_phy_setmedia: MASTER on wrong media"); + } + } + + if (ife->ifm_media & IFM_LOOP) + bmcr |= BMCR_LOOP; + + PHY_WRITE(sc, MII_ANAR, anar); + PHY_WRITE(sc, MII_BMCR, bmcr); + if (sc->mii_flags & MIIF_HAVE_GTCR) + PHY_WRITE(sc, MII_100T2CR, gtcr); +} + int mii_phy_auto(mii, waitfor) struct mii_softc *mii; @@ -293,13 +384,10 @@ void mii_add_media(struct mii_softc *sc) { const char *sep = ""; - int bmsr, instance; struct mii_data *mii; - bmsr = sc->mii_capabilities; - instance = sc->mii_inst; mii = device_get_softc(sc->mii_dev); - if ((bmsr & BMSR_MEDIAMASK) == 0) { + if ((sc->mii_capabilities & BMSR_MEDIAMASK) == 0) { printf("no media present"); return; } @@ -307,38 +395,38 @@ mii_add_media(struct mii_softc *sc) #define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL) #define PRINT(s) printf("%s%s", sep, s); sep = ", " - if (bmsr & BMSR_10THDX) { - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, 0, instance), 0); + if (sc->mii_capabilities & BMSR_10THDX) { + ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, 0, sc->mii_inst), 0); PRINT("10baseT"); } - if (bmsr & BMSR_10TFDX) { - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, IFM_FDX, instance), + if (sc->mii_capabilities & BMSR_10TFDX) { + ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, IFM_FDX, sc->mii_inst), BMCR_FDX); PRINT("10baseT-FDX"); } - if (bmsr & BMSR_100TXHDX) { - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, 0, instance), + if (sc->mii_capabilities & BMSR_100TXHDX) { + ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, 0, sc->mii_inst), BMCR_S100); PRINT("100baseTX"); } - if (bmsr & BMSR_100TXFDX) { - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_FDX, instance), + if (sc->mii_capabilities & BMSR_100TXFDX) { + ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_FDX, sc->mii_inst), BMCR_S100|BMCR_FDX); PRINT("100baseTX-FDX"); } - if (bmsr & BMSR_100T4) { + if (sc->mii_capabilities & BMSR_100T4) { /* * XXX How do you enable 100baseT4? I assume we set * XXX BMCR_S100 and then assume the PHYs will take * XXX watever action is necessary to switch themselves * XXX into T4 mode. */ - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_T4, 0, instance), + ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_T4, 0, sc->mii_inst), BMCR_S100); PRINT("100baseT4"); } - if (bmsr & BMSR_ANEG) { - ADD(IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, 0, instance), + if (sc->mii_capabilities & BMSR_ANEG) { + ADD(IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, 0, sc->mii_inst), BMCR_AUTOEN); PRINT("auto"); } diff --git a/sys/dev/mii/miivar.h b/sys/dev/mii/miivar.h index 3b56146..69668b0 100644 --- a/sys/dev/mii/miivar.h +++ b/sys/dev/mii/miivar.h @@ -130,8 +130,18 @@ struct mii_softc { typedef struct mii_softc mii_softc_t; /* mii_flags */ -#define MIIF_NOISOLATE 0x0001 /* do not isolate the PHY */ -#define MIIF_DOINGAUTO 0x0002 /* doing autonegotiation */ +#define MIIF_INITDONE 0x0001 /* has been initialized (mii_data) */ +#define MIIF_NOISOLATE 0x0002 /* do not isolate the PHY */ +#define MIIF_NOLOOP 0x0004 /* no loopback capability */ +#define MIIF_DOINGAUTO 0x0008 /* doing autonegotiation (mii_softc) */ +#define MIIF_AUTOTSLEEP 0x0010 /* use tsleep(), not callout() */ +#define MIIF_HAVEFIBER 0x0020 /* from parent: has fiber interface */ +#define MIIF_HAVE_GTCR 0x0040 /* has 100base-T2/1000base-T CR */ +#define MIIF_IS_1000X 0x0080 /* is a 1000BASE-X device */ +#define MIIF_DOPAUSE 0x0100 /* advertise PAUSE capability */ +#define MIIF_IS_HPNA 0x0200 /* is a HomePNA device */ + +#define MIIF_INHERIT_MASK (MIIF_NOISOLATE|MIIF_NOLOOP|MIIF_AUTOTSLEEP) /* * Used to attach a PHY to a parent. @@ -145,6 +155,27 @@ struct mii_attach_args { }; typedef struct mii_attach_args mii_attach_args_t; +/* + * An array of these structures map MII media types to BMCR/ANAR settings. + */ +struct mii_media { + int mm_bmcr; /* BMCR settings for this media */ + int mm_anar; /* ANAR settings for this media */ + int mm_gtcr; /* 100base-T2 or 1000base-T CR */ +}; + +#define MII_MEDIA_NONE 0 +#define MII_MEDIA_10_T 1 +#define MII_MEDIA_10_T_FDX 2 +#define MII_MEDIA_100_T4 3 +#define MII_MEDIA_100_TX 4 +#define MII_MEDIA_100_TX_FDX 5 +#define MII_MEDIA_1000_X 6 +#define MII_MEDIA_1000_X_FDX 7 +#define MII_MEDIA_1000_T 8 +#define MII_MEDIA_1000_T_FDX 9 +#define MII_NMEDIA 10 + #ifdef _KERNEL #define PHY_READ(p, r) \ @@ -172,6 +203,7 @@ int mii_media_from_bmcr(int); int mii_phy_auto(struct mii_softc *, int); void mii_phy_auto_stop(struct mii_softc *); void mii_phy_reset(struct mii_softc *); +void mii_phy_setmedia(struct mii_softc *sc); void mii_phy_update(struct mii_softc *, int); int mii_phy_tick(struct mii_softc *); diff --git a/sys/dev/mii/nsgphy.c b/sys/dev/mii/nsgphy.c index 2f4cad6..adae9fb 100644 --- a/sys/dev/mii/nsgphy.c +++ b/sys/dev/mii/nsgphy.c @@ -162,9 +162,10 @@ nsgphy_attach(device_t dev) ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T, 0, sc->mii_inst), BMCR_S1000); PRINT("1000baseTX"); - sc->mii_capabilities = - (PHY_READ(sc, MII_BMSR) | + sc->mii_capabilities = (PHY_READ(sc, MII_BMSR) | (BMSR_10TFDX|BMSR_10THDX)) & ma->mii_capmask; + if (sc->mii_capabilities & BMSR_EXTSTAT) + sc->mii_extcapabilities = PHY_READ(sc, MII_EXTSR); ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_FDX, sc->mii_inst), BMCR_S100|BMCR_FDX); PRINT("100baseTX-FDX"); |