summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorphk <phk@FreeBSD.org>2002-04-29 07:18:26 +0000
committerphk <phk@FreeBSD.org>2002-04-29 07:18:26 +0000
commit03000f5700d4ab2a38021db193c2d41c54479b59 (patch)
tree6b8e043c8285a57ab8885d82ba7b860ba0da3234 /sys
parent9e268405661ecd7735e088325129da32fd8546f6 (diff)
downloadFreeBSD-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.c120
-rw-r--r--sys/dev/mii/miivar.h36
-rw-r--r--sys/dev/mii/nsgphy.c5
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");
OpenPOWER on IntegriCloud