summaryrefslogtreecommitdiffstats
path: root/freebsd/sys/dev/mii
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2016-10-07 15:10:20 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2017-01-10 09:53:31 +0100
commitc40e45b75eb76d79a05c7fa85c1fa9b5c728a12f (patch)
treead4f2519067709f00ab98b3c591186c26dc3a21f /freebsd/sys/dev/mii
parentuserspace-header-gen.py: Simplify program ports (diff)
downloadrtems-libbsd-c40e45b75eb76d79a05c7fa85c1fa9b5c728a12f.tar.bz2
Update to FreeBSD head 2016-08-23
Git mirror commit 9fe7c416e6abb28b1398fd3e5687099846800cfd.
Diffstat (limited to 'freebsd/sys/dev/mii')
-rw-r--r--freebsd/sys/dev/mii/brgphy.c95
-rw-r--r--freebsd/sys/dev/mii/e1000phy.c26
-rw-r--r--freebsd/sys/dev/mii/icsphy.c6
-rw-r--r--freebsd/sys/dev/mii/micphy.c148
-rw-r--r--freebsd/sys/dev/mii/mii.c57
-rw-r--r--freebsd/sys/dev/mii/mii.h43
-rw-r--r--freebsd/sys/dev/mii/mii_physubr.c172
-rw-r--r--freebsd/sys/dev/mii/miivar.h46
-rw-r--r--freebsd/sys/dev/mii/rgephy.c54
-rw-r--r--freebsd/sys/dev/mii/rgephyreg.h16
10 files changed, 429 insertions, 234 deletions
diff --git a/freebsd/sys/dev/mii/brgphy.c b/freebsd/sys/dev/mii/brgphy.c
index 75c15774..e07cd968 100644
--- a/freebsd/sys/dev/mii/brgphy.c
+++ b/freebsd/sys/dev/mii/brgphy.c
@@ -45,8 +45,10 @@ __FBSDID("$FreeBSD$");
#include <sys/module.h>
#include <sys/socket.h>
#include <sys/bus.h>
+#include <sys/taskqueue.h>
#include <net/if.h>
+#include <net/if_var.h>
#include <net/ethernet.h>
#include <net/if_media.h>
@@ -118,7 +120,10 @@ static void brgphy_jumbo_settings(struct mii_softc *, u_long);
static const struct mii_phydesc brgphys[] = {
MII_PHY_DESC(BROADCOM, BCM5400),
MII_PHY_DESC(BROADCOM, BCM5401),
+ MII_PHY_DESC(BROADCOM, BCM5402),
MII_PHY_DESC(BROADCOM, BCM5411),
+ MII_PHY_DESC(BROADCOM, BCM5404),
+ MII_PHY_DESC(BROADCOM, BCM5424),
MII_PHY_DESC(BROADCOM, BCM54K2),
MII_PHY_DESC(BROADCOM, BCM5701),
MII_PHY_DESC(BROADCOM, BCM5703),
@@ -131,6 +136,9 @@ static const struct mii_phydesc brgphys[] = {
MII_PHY_DESC(BROADCOM, BCM5752),
MII_PHY_DESC(BROADCOM, BCM5780),
MII_PHY_DESC(BROADCOM, BCM5708C),
+ MII_PHY_DESC(BROADCOM, BCM5466),
+ MII_PHY_DESC(BROADCOM2, BCM5478),
+ MII_PHY_DESC(BROADCOM2, BCM5488),
MII_PHY_DESC(BROADCOM2, BCM5482),
MII_PHY_DESC(BROADCOM2, BCM5708S),
MII_PHY_DESC(BROADCOM2, BCM5709C),
@@ -160,25 +168,33 @@ static const struct mii_phy_funcs brgphy_funcs = {
brgphy_reset
};
-#define HS21_PRODUCT_ID "IBM eServer BladeCenter HS21"
-#define HS21_BCM_CHIPID 0x57081021
+static const struct hs21_type {
+ const uint32_t id;
+ const char *prod;
+} hs21_type_lists[] = {
+ { 0x57081021, "IBM eServer BladeCenter HS21" },
+ { 0x57081011, "IBM eServer BladeCenter HS21 -[8853PAU]-" },
+};
static int
detect_hs21(struct bce_softc *bce_sc)
{
char *sysenv;
- int found;
+ int found, i;
found = 0;
- if (bce_sc->bce_chipid == HS21_BCM_CHIPID) {
- sysenv = getenv("smbios.system.product");
- if (sysenv != NULL) {
- if (strncmp(sysenv, HS21_PRODUCT_ID,
- strlen(HS21_PRODUCT_ID)) == 0)
- found = 1;
- freeenv(sysenv);
+ sysenv = kern_getenv("smbios.system.product");
+ if (sysenv == NULL)
+ return (found);
+ for (i = 0; i < nitems(hs21_type_lists); i++) {
+ if (bce_sc->bce_chipid == hs21_type_lists[i].id &&
+ strncmp(sysenv, hs21_type_lists[i].prod,
+ strlen(hs21_type_lists[i].prod)) == 0) {
+ found++;
+ break;
}
}
+ freeenv(sysenv);
return (found);
}
@@ -198,7 +214,6 @@ brgphy_attach(device_t dev)
struct bge_softc *bge_sc = NULL;
struct bce_softc *bce_sc = NULL;
struct mii_softc *sc;
- struct ifnet *ifp;
bsc = device_get_softc(dev);
sc = &bsc->mii_sc;
@@ -207,13 +222,12 @@ brgphy_attach(device_t dev)
&brgphy_funcs, 0);
bsc->serdes_flags = 0;
- ifp = sc->mii_pdata->mii_ifp;
/* Find the MAC driver associated with this PHY. */
- if (strcmp(ifp->if_dname, "bge") == 0)
- bge_sc = ifp->if_softc;
- else if (strcmp(ifp->if_dname, "bce") == 0)
- bce_sc = ifp->if_softc;
+ if (mii_dev_mac_match(dev, "bge"))
+ bge_sc = mii_dev_mac_softc(dev);
+ else if (mii_dev_mac_match(dev, "bce"))
+ bce_sc = mii_dev_mac_softc(dev);
/* Handle any special cases based on the PHY ID */
switch (sc->mii_mpd_oui) {
@@ -268,20 +282,25 @@ brgphy_attach(device_t dev)
sc->mii_extcapabilities = PHY_READ(sc, MII_EXTSR);
device_printf(dev, " ");
-#define ADD(m, c) ifmedia_add(&sc->mii_pdata->mii_media, (m), (c), NULL)
-
/* Add the supported media types */
if ((sc->mii_flags & MIIF_HAVEFIBER) == 0) {
mii_phy_add_media(sc);
printf("\n");
} else {
sc->mii_anegticks = MII_ANEGTICKS_GIGE;
- ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_SX, IFM_FDX, sc->mii_inst),
- BRGPHY_S1000 | BRGPHY_BMCR_FDX);
+ ifmedia_add(&sc->mii_pdata->mii_media,
+ IFM_MAKEWORD(IFM_ETHER, IFM_1000_SX, IFM_FDX, sc->mii_inst),
+ 0, NULL);
printf("1000baseSX-FDX, ");
- /* 2.5G support is a software enabled feature on the 5708S and 5709S. */
- if (bce_sc && (bce_sc->bce_phy_flags & BCE_PHY_2_5G_CAPABLE_FLAG)) {
- ADD(IFM_MAKEWORD(IFM_ETHER, IFM_2500_SX, IFM_FDX, sc->mii_inst), 0);
+ /*
+ * 2.5G support is a software enabled feature
+ * on the 5708S and 5709S.
+ */
+ if (bce_sc && (bce_sc->bce_phy_flags &
+ BCE_PHY_2_5G_CAPABLE_FLAG)) {
+ ifmedia_add(&sc->mii_pdata->mii_media,
+ IFM_MAKEWORD(IFM_ETHER, IFM_2500_SX, IFM_FDX,
+ sc->mii_inst), 0, NULL);
printf("2500baseSX-FDX, ");
} else if ((bsc->serdes_flags & BRGPHY_5708S) && bce_sc &&
(detect_hs21(bce_sc) != 0)) {
@@ -297,11 +316,11 @@ brgphy_attach(device_t dev)
printf("auto-neg workaround, ");
bsc->serdes_flags |= BRGPHY_NOANWAIT;
}
- ADD(IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, 0, sc->mii_inst), 0);
+ ifmedia_add(&sc->mii_pdata->mii_media, IFM_MAKEWORD(IFM_ETHER,
+ IFM_AUTO, 0, sc->mii_inst), 0, NULL);
printf("auto\n");
}
-#undef ADD
MIIBUS_MEDIAINIT(sc->mii_dev);
return (0);
}
@@ -316,10 +335,6 @@ brgphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
case MII_POLLSTAT:
break;
case MII_MEDIACHG:
- /* If the interface is not up, don't do anything. */
- if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
- break;
-
/* Todo: Why is this here? Is it really needed? */
PHY_RESET(sc); /* XXX hardware bug work-around */
@@ -339,11 +354,6 @@ brgphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
}
break;
case MII_TICK:
- /* Bail if the interface isn't up. */
- if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
- return (0);
-
-
/* Bail if autoneg isn't in process. */
if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) {
sc->mii_ticks = 0;
@@ -889,7 +899,7 @@ brgphy_reset(struct mii_softc *sc)
{
struct bge_softc *bge_sc = NULL;
struct bce_softc *bce_sc = NULL;
- struct ifnet *ifp;
+ if_t ifp;
int i, val;
/*
@@ -942,11 +952,10 @@ brgphy_reset(struct mii_softc *sc)
ifp = sc->mii_pdata->mii_ifp;
/* Find the driver associated with this PHY. */
- if (strcmp(ifp->if_dname, "bge") == 0) {
- bge_sc = ifp->if_softc;
- } else if (strcmp(ifp->if_dname, "bce") == 0) {
- bce_sc = ifp->if_softc;
- }
+ if (mii_phy_mac_match(sc, "bge"))
+ bge_sc = mii_phy_mac_softc(sc);
+ else if (mii_phy_mac_match(sc, "bce"))
+ bce_sc = mii_phy_mac_softc(sc);
if (bge_sc) {
/* Fix up various bugs */
@@ -964,7 +973,7 @@ brgphy_reset(struct mii_softc *sc)
brgphy_fixup_jitter_bug(sc);
if (bge_sc->bge_flags & BGE_FLAG_JUMBO)
- brgphy_jumbo_settings(sc, ifp->if_mtu);
+ brgphy_jumbo_settings(sc, if_getmtu(ifp));
if ((bge_sc->bge_phy_flags & BGE_PHY_NO_WIRESPEED) == 0)
brgphy_ethernet_wirespeed(sc);
@@ -1075,11 +1084,11 @@ brgphy_reset(struct mii_softc *sc)
(BCE_CHIP_REV(bce_sc) == BCE_CHIP_REV_Bx))
brgphy_fixup_disable_early_dac(sc);
- brgphy_jumbo_settings(sc, ifp->if_mtu);
+ brgphy_jumbo_settings(sc, if_getmtu(ifp));
brgphy_ethernet_wirespeed(sc);
} else {
brgphy_fixup_ber_bug(sc);
- brgphy_jumbo_settings(sc, ifp->if_mtu);
+ brgphy_jumbo_settings(sc, if_getmtu(ifp));
brgphy_ethernet_wirespeed(sc);
}
}
diff --git a/freebsd/sys/dev/mii/e1000phy.c b/freebsd/sys/dev/mii/e1000phy.c
index f50d41a9..10d6fc68 100644
--- a/freebsd/sys/dev/mii/e1000phy.c
+++ b/freebsd/sys/dev/mii/e1000phy.c
@@ -52,8 +52,8 @@ __FBSDID("$FreeBSD$");
#include <sys/socket.h>
#include <sys/bus.h>
-
#include <net/if.h>
+#include <net/if_var.h>
#include <net/if_media.h>
#include <dev/mii/mii.h>
@@ -114,7 +114,9 @@ static const struct mii_phydesc e1000phys[] = {
MII_PHY_DESC(xxMARVELL, E1111),
MII_PHY_DESC(xxMARVELL, E1116),
MII_PHY_DESC(xxMARVELL, E1116R),
+ MII_PHY_DESC(xxMARVELL, E1116R_29),
MII_PHY_DESC(xxMARVELL, E1118),
+ MII_PHY_DESC(xxMARVELL, E1145),
MII_PHY_DESC(xxMARVELL, E1149R),
MII_PHY_DESC(xxMARVELL, E3016),
MII_PHY_DESC(xxMARVELL, PHYG65G),
@@ -141,14 +143,12 @@ static int
e1000phy_attach(device_t dev)
{
struct mii_softc *sc;
- struct ifnet *ifp;
sc = device_get_softc(dev);
mii_phy_dev_attach(dev, MIIF_NOMANPAUSE, &e1000phy_funcs, 0);
- ifp = sc->mii_pdata->mii_ifp;
- if (strcmp(ifp->if_dname, "msk") == 0 &&
+ if (mii_dev_mac_match(dev, "msk") &&
(sc->mii_flags & MIIF_MACPRIV0) != 0)
sc->mii_flags |= MIIF_PHYPRIV0;
@@ -223,6 +223,7 @@ e1000phy_reset(struct mii_softc *sc)
case MII_MODEL_xxMARVELL_E1111:
case MII_MODEL_xxMARVELL_E1112:
case MII_MODEL_xxMARVELL_E1116:
+ case MII_MODEL_xxMARVELL_E1116R_29:
case MII_MODEL_xxMARVELL_E1118:
case MII_MODEL_xxMARVELL_E1149:
case MII_MODEL_xxMARVELL_E1149R:
@@ -230,7 +231,8 @@ e1000phy_reset(struct mii_softc *sc)
/* Disable energy detect mode. */
reg &= ~E1000_SCR_EN_DETECT_MASK;
reg |= E1000_SCR_AUTO_X_MODE;
- if (sc->mii_mpd_model == MII_MODEL_xxMARVELL_E1116)
+ if (sc->mii_mpd_model == MII_MODEL_xxMARVELL_E1116 ||
+ sc->mii_mpd_model == MII_MODEL_xxMARVELL_E1116R_29)
reg &= ~E1000_SCR_POWER_DOWN;
reg |= E1000_SCR_ASSERT_CRS_ON_TX;
break;
@@ -258,6 +260,7 @@ e1000phy_reset(struct mii_softc *sc)
PHY_WRITE(sc, E1000_SCR, reg);
if (sc->mii_mpd_model == MII_MODEL_xxMARVELL_E1116 ||
+ sc->mii_mpd_model == MII_MODEL_xxMARVELL_E1116R_29 ||
sc->mii_mpd_model == MII_MODEL_xxMARVELL_E1149 ||
sc->mii_mpd_model == MII_MODEL_xxMARVELL_E1149R) {
PHY_WRITE(sc, E1000_EADR, 2);
@@ -274,6 +277,7 @@ e1000phy_reset(struct mii_softc *sc)
case MII_MODEL_xxMARVELL_E1118:
break;
case MII_MODEL_xxMARVELL_E1116:
+ case MII_MODEL_xxMARVELL_E1116R_29:
page = PHY_READ(sc, E1000_EADR);
/* Select page 3, LED control register. */
PHY_WRITE(sc, E1000_EADR, 3);
@@ -320,12 +324,6 @@ e1000phy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
break;
case MII_MEDIACHG:
- /*
- * If the interface is not up, don't do anything.
- */
- if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
- break;
-
if (IFM_SUBTYPE(ife->ifm_media) == IFM_AUTO) {
e1000phy_mii_phy_auto(sc, ife->ifm_media);
break;
@@ -382,12 +380,6 @@ done:
break;
case MII_TICK:
/*
- * Is the interface even up?
- */
- if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
- return (0);
-
- /*
* Only used for autonegotiation.
*/
if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) {
diff --git a/freebsd/sys/dev/mii/icsphy.c b/freebsd/sys/dev/mii/icsphy.c
index 3d5e6384..29444f38 100644
--- a/freebsd/sys/dev/mii/icsphy.c
+++ b/freebsd/sys/dev/mii/icsphy.c
@@ -147,12 +147,6 @@ icsphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
break;
case MII_MEDIACHG:
- /*
- * If the interface is not up, don't do anything.
- */
- if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
- break;
-
mii_phy_setmedia(sc);
break;
diff --git a/freebsd/sys/dev/mii/micphy.c b/freebsd/sys/dev/mii/micphy.c
index ab40dab5..acaa8b73 100644
--- a/freebsd/sys/dev/mii/micphy.c
+++ b/freebsd/sys/dev/mii/micphy.c
@@ -71,6 +71,14 @@ __FBSDID("$FreeBSD$");
#define MII_KSZPHY_CLK_CONTROL_PAD_SKEW 0x104
#define MII_KSZPHY_RX_DATA_PAD_SKEW 0x105
#define MII_KSZPHY_TX_DATA_PAD_SKEW 0x106
+/* KSZ9031 */
+#define MII_KSZ9031_MMD_ACCESS_CTRL 0x0d
+#define MII_KSZ9031_MMD_ACCESS_DATA 0x0e
+#define MII_KSZ9031_MMD_DATA_NOINC (1 << 14)
+#define MII_KSZ9031_CONTROL_PAD_SKEW 0x4
+#define MII_KSZ9031_RX_DATA_PAD_SKEW 0x5
+#define MII_KSZ9031_TX_DATA_PAD_SKEW 0x6
+#define MII_KSZ9031_CLOCK_PAD_SKEW 0x8
#define PS_TO_REG(p) ((p) / 200)
@@ -99,6 +107,7 @@ DRIVER_MODULE(micphy, miibus, micphy_driver, micphy_devclass, 0, 0);
static const struct mii_phydesc micphys[] = {
MII_PHY_DESC(MICREL, KSZ9021),
+ MII_PHY_DESC(MICREL, KSZ9031),
MII_PHY_END
};
@@ -108,8 +117,50 @@ static const struct mii_phy_funcs micphy_funcs = {
mii_phy_reset
};
+#ifndef __rtems__
+static uint32_t
+ksz9031_read(struct mii_softc *sc, uint32_t devaddr, uint32_t reg)
+{
+ /* Set up device address and register. */
+ PHY_WRITE(sc, MII_KSZ9031_MMD_ACCESS_CTRL, devaddr);
+ PHY_WRITE(sc, MII_KSZ9031_MMD_ACCESS_DATA, reg);
+
+ /* Select register data for MMD and read the value. */
+ PHY_WRITE(sc, MII_KSZ9031_MMD_ACCESS_CTRL,
+ MII_KSZ9031_MMD_DATA_NOINC | devaddr);
+
+ return (PHY_READ(sc, MII_KSZ9031_MMD_ACCESS_DATA));
+}
+#endif /* __rtems__ */
+
static void
-micphy_write(struct mii_softc *sc, uint32_t reg, uint32_t val)
+ksz9031_write(struct mii_softc *sc, uint32_t devaddr, uint32_t reg,
+ uint32_t val)
+{
+
+ /* Set up device address and register. */
+ PHY_WRITE(sc, MII_KSZ9031_MMD_ACCESS_CTRL, devaddr);
+ PHY_WRITE(sc, MII_KSZ9031_MMD_ACCESS_DATA, reg);
+
+ /* Select register data for MMD and write the value. */
+ PHY_WRITE(sc, MII_KSZ9031_MMD_ACCESS_CTRL,
+ MII_KSZ9031_MMD_DATA_NOINC | devaddr);
+ PHY_WRITE(sc, MII_KSZ9031_MMD_ACCESS_DATA, val);
+}
+
+#ifndef __rtems__
+static uint32_t
+ksz9021_read(struct mii_softc *sc, uint32_t reg)
+{
+
+ PHY_WRITE(sc, MII_KSZPHY_EXTREG, reg);
+
+ return (PHY_READ(sc, MII_KSZPHY_EXTREG_READ));
+}
+#endif /* __rtems__ */
+
+static void
+ksz9021_write(struct mii_softc *sc, uint32_t reg, uint32_t val)
{
PHY_WRITE(sc, MII_KSZPHY_EXTREG, KSZPHY_EXTREG_WRITE | reg);
@@ -117,40 +168,82 @@ micphy_write(struct mii_softc *sc, uint32_t reg, uint32_t val)
}
#ifndef __rtems__
-static int
-ksz9021_load_values(struct mii_softc *sc, phandle_t node, uint32_t reg,
- char *field1, char *field2,
- char *field3, char *field4)
+static void
+ksz90x1_load_values(struct mii_softc *sc, phandle_t node,
+ uint32_t dev, uint32_t reg, char *field1, uint32_t f1mask, int f1off,
+ char *field2, uint32_t f2mask, int f2off, char *field3, uint32_t f3mask,
+ int f3off, char *field4, uint32_t f4mask, int f4off)
{
pcell_t dts_value[1];
int len;
int val;
- val = 0;
+ if (sc->mii_mpd_model == MII_MODEL_MICREL_KSZ9031)
+ val = ksz9031_read(sc, dev, reg);
+ else
+ val = ksz9021_read(sc, reg);
if ((len = OF_getproplen(node, field1)) > 0) {
OF_getencprop(node, field1, dts_value, len);
- val = PS_TO_REG(dts_value[0]);
+ val &= ~(f1mask << f1off);
+ val |= (PS_TO_REG(dts_value[0]) & f1mask) << f1off;
}
- if ((len = OF_getproplen(node, field2)) > 0) {
+ if (field2 != NULL && (len = OF_getproplen(node, field2)) > 0) {
OF_getencprop(node, field2, dts_value, len);
- val |= PS_TO_REG(dts_value[0]) << 4;
+ val &= ~(f2mask << f2off);
+ val |= (PS_TO_REG(dts_value[0]) & f2mask) << f2off;
}
- if ((len = OF_getproplen(node, field3)) > 0) {
+ if (field3 != NULL && (len = OF_getproplen(node, field3)) > 0) {
OF_getencprop(node, field3, dts_value, len);
- val |= PS_TO_REG(dts_value[0]) << 8;
+ val &= ~(f3mask << f3off);
+ val |= (PS_TO_REG(dts_value[0]) & f3mask) << f3off;
}
- if ((len = OF_getproplen(node, field4)) > 0) {
+ if (field4 != NULL && (len = OF_getproplen(node, field4)) > 0) {
OF_getencprop(node, field4, dts_value, len);
- val |= PS_TO_REG(dts_value[0]) << 12;
+ val &= ~(f4mask << f4off);
+ val |= (PS_TO_REG(dts_value[0]) & f4mask) << f4off;
}
- micphy_write(sc, reg, val);
+ if (sc->mii_mpd_model == MII_MODEL_MICREL_KSZ9031)
+ ksz9031_write(sc, dev, reg, val);
+ else
+ ksz9021_write(sc, reg, val);
+}
- return (0);
+static void
+ksz9031_load_values(struct mii_softc *sc, phandle_t node)
+{
+
+ ksz90x1_load_values(sc, node, 2, MII_KSZ9031_CONTROL_PAD_SKEW,
+ "txen-skew-ps", 0xf, 0, "rxdv-skew-ps", 0xf, 4,
+ NULL, 0, 0, NULL, 0, 0);
+ ksz90x1_load_values(sc, node, 2, MII_KSZ9031_RX_DATA_PAD_SKEW,
+ "rxd0-skew-ps", 0xf, 0, "rxd1-skew-ps", 0xf, 4,
+ "rxd2-skew-ps", 0xf, 8, "rxd3-skew-ps", 0xf, 12);
+ ksz90x1_load_values(sc, node, 2, MII_KSZ9031_TX_DATA_PAD_SKEW,
+ "txd0-skew-ps", 0xf, 0, "txd1-skew-ps", 0xf, 4,
+ "txd2-skew-ps", 0xf, 8, "txd3-skew-ps", 0xf, 12);
+ ksz90x1_load_values(sc, node, 2, MII_KSZ9031_CLOCK_PAD_SKEW,
+ "rxc-skew-ps", 0x1f, 0, "txc-skew-ps", 0x1f, 5,
+ NULL, 0, 0, NULL, 0, 0);
+}
+
+static void
+ksz9021_load_values(struct mii_softc *sc, phandle_t node)
+{
+
+ ksz90x1_load_values(sc, node, 0, MII_KSZPHY_CLK_CONTROL_PAD_SKEW,
+ "txen-skew-ps", 0xf, 0, "txc-skew-ps", 0xf, 4,
+ "rxdv-skew-ps", 0xf, 8, "rxc-skew-ps", 0xf, 12);
+ ksz90x1_load_values(sc, node, 0, MII_KSZPHY_RX_DATA_PAD_SKEW,
+ "rxd0-skew-ps", 0xf, 0, "rxd1-skew-ps", 0xf, 4,
+ "rxd2-skew-ps", 0xf, 8, "rxd3-skew-ps", 0xf, 12);
+ ksz90x1_load_values(sc, node, 0, MII_KSZPHY_TX_DATA_PAD_SKEW,
+ "txd0-skew-ps", 0xf, 0, "txd1-skew-ps", 0xf, 4,
+ "txd2-skew-ps", 0xf, 8, "txd3-skew-ps", 0xf, 12);
}
#endif /* __rtems__ */
@@ -183,22 +276,19 @@ micphy_attach(device_t dev)
if ((node = ofw_bus_get_node(parent)) == -1)
return (ENXIO);
- ksz9021_load_values(sc, node, MII_KSZPHY_CLK_CONTROL_PAD_SKEW,
- "txen-skew-ps", "txc-skew-ps",
- "rxdv-skew-ps", "rxc-skew-ps");
-
- ksz9021_load_values(sc, node, MII_KSZPHY_RX_DATA_PAD_SKEW,
- "rxd0-skew-ps", "rxd1-skew-ps",
- "rxd2-skew-ps", "rxd3-skew-ps");
-
- ksz9021_load_values(sc, node, MII_KSZPHY_TX_DATA_PAD_SKEW,
- "txd0-skew-ps", "txd1-skew-ps",
- "txd2-skew-ps", "txd3-skew-ps");
+ if (sc->mii_mpd_model == MII_MODEL_MICREL_KSZ9031)
+ ksz9031_load_values(sc, node);
+ else
+ ksz9021_load_values(sc, node);
#else /* __rtems__ */
/* FIXME */
- micphy_write(sc, MII_KSZPHY_CLK_CONTROL_PAD_SKEW, 0xf0f0);
- micphy_write(sc, MII_KSZPHY_RX_DATA_PAD_SKEW, 0x0000);
- micphy_write(sc, MII_KSZPHY_TX_DATA_PAD_SKEW, 0x0000);
+ if (sc->mii_mpd_model == MII_MODEL_MICREL_KSZ9031) {
+ BSD_ASSERT(0);
+ } else {
+ ksz9021_write(sc, MII_KSZPHY_CLK_CONTROL_PAD_SKEW, 0xf0f0);
+ ksz9021_write(sc, MII_KSZPHY_RX_DATA_PAD_SKEW, 0x0000);
+ ksz9021_write(sc, MII_KSZPHY_TX_DATA_PAD_SKEW, 0x0000);
+ }
#endif /* __rtems__ */
return (0);
diff --git a/freebsd/sys/dev/mii/mii.c b/freebsd/sys/dev/mii/mii.c
index d1f55cb0..1f0ead72 100644
--- a/freebsd/sys/dev/mii/mii.c
+++ b/freebsd/sys/dev/mii/mii.c
@@ -49,6 +49,7 @@ __FBSDID("$FreeBSD$");
#include <sys/bus.h>
#include <net/if.h>
+#include <net/if_var.h>
#include <net/if_media.h>
#include <dev/mii/mii.h>
@@ -107,7 +108,7 @@ driver_t miibus_driver = {
};
struct miibus_ivars {
- struct ifnet *ifp;
+ if_t ifp;
ifm_change_cb_t ifmedia_upd;
ifm_stat_cb_t ifmedia_sts;
u_int mii_flags;
@@ -148,8 +149,8 @@ miibus_attach(device_t dev)
ifmedia_init(&mii->mii_media, IFM_IMASK, ivars->ifmedia_upd,
ivars->ifmedia_sts);
mii->mii_ifp = ivars->ifp;
- mii->mii_ifp->if_capabilities |= IFCAP_LINKSTATE;
- mii->mii_ifp->if_capenable |= IFCAP_LINKSTATE;
+ if_setcapabilitiesbit(mii->mii_ifp, IFCAP_LINKSTATE, 0);
+ if_setcapenablebit(mii->mii_ifp, IFCAP_LINKSTATE, 0);
LIST_INIT(&mii->mii_phys);
return (bus_generic_attach(dev));
@@ -309,7 +310,7 @@ miibus_statchg(device_t dev)
MIIBUS_STATCHG(parent);
mii = device_get_softc(dev);
- mii->mii_ifp->if_baudrate = ifmedia_baudrate(mii->mii_media_active);
+ if_setbaudrate(mii->mii_ifp, ifmedia_baudrate(mii->mii_media_active));
}
static void
@@ -359,7 +360,7 @@ miibus_mediainit(device_t dev)
* the PHYs to the network interface driver parent.
*/
int
-mii_attach(device_t dev, device_t *miibus, struct ifnet *ifp,
+mii_attach(device_t dev, device_t *miibus, if_t ifp,
ifm_change_cb_t ifmedia_upd, ifm_stat_cb_t ifmedia_sts, int capmask,
int phyloc, int offloc, int flags)
{
@@ -375,7 +376,7 @@ mii_attach(device_t dev, device_t *miibus, struct ifnet *ifp,
}
if (offloc != MII_OFFSET_ANY && (offloc < 0 || offloc >= MII_NPHY)) {
- printf("%s: ivalid offloc %d\n", __func__, offloc);
+ printf("%s: invalid offloc %d\n", __func__, offloc);
return (EINVAL);
}
@@ -384,7 +385,7 @@ mii_attach(device_t dev, device_t *miibus, struct ifnet *ifp,
phymax = MII_NPHY - 1;
} else {
if (phyloc < 0 || phyloc >= MII_NPHY) {
- printf("%s: ivalid phyloc %d\n", __func__, phyloc);
+ printf("%s: invalid phyloc %d\n", __func__, phyloc);
return (EINVAL);
}
phymin = phymax = phyloc;
@@ -613,18 +614,6 @@ mii_pollstat(struct mii_data *mii)
}
}
-/*
- * Inform the PHYs that the interface is down.
- */
-void
-mii_down(struct mii_data *mii)
-{
- struct mii_softc *child;
-
- LIST_FOREACH(child, &mii->mii_phys, mii_list)
- mii_phy_down(child);
-}
-
static unsigned char
mii_bitreverse(unsigned char x)
{
@@ -646,3 +635,33 @@ mii_oui(u_int id1, u_int id2)
(mii_bitreverse((h >> 8) & 0xff) << 8) |
mii_bitreverse(h & 0xff));
}
+
+int
+mii_phy_mac_match(struct mii_softc *mii, const char *name)
+{
+
+ return (strcmp(device_get_name(device_get_parent(mii->mii_dev)),
+ name) == 0);
+}
+
+int
+mii_dev_mac_match(device_t parent, const char *name)
+{
+
+ return (strcmp(device_get_name(device_get_parent(
+ device_get_parent(parent))), name) == 0);
+}
+
+void *
+mii_phy_mac_softc(struct mii_softc *mii)
+{
+
+ return (device_get_softc(device_get_parent(mii->mii_dev)));
+}
+
+void *
+mii_dev_mac_softc(device_t parent)
+{
+
+ return (device_get_softc(device_get_parent(device_get_parent(parent))));
+}
diff --git a/freebsd/sys/dev/mii/mii.h b/freebsd/sys/dev/mii/mii.h
index 668fb8fb..fa1ec84e 100644
--- a/freebsd/sys/dev/mii/mii.h
+++ b/freebsd/sys/dev/mii/mii.h
@@ -1,4 +1,4 @@
-/* $NetBSD: mii.h,v 1.9 2001/05/31 03:07:14 thorpej Exp $ */
+/* $NetBSD: mii.h,v 1.18 2014/06/16 14:43:22 msaitoh Exp $ */
/*-
* Copyright (c) 1997 Manuel Bouyer. All rights reserved.
@@ -87,7 +87,7 @@
/*
* Note that the EXTSTAT bit indicates that there is extended status
* info available in register 15, but 802.3 section 22.2.4.3 also
- * states that that all 1000 Mb/s capable PHYs will set this bit to 1.
+ * states that all 1000 Mb/s capable PHYs will set this bit to 1.
*/
#define BMSR_MEDIAMASK (BMSR_100T4|BMSR_100TXFDX|BMSR_100TXHDX| \
@@ -111,6 +111,7 @@
#define ANAR_NP 0x8000 /* Next page (ro) */
#define ANAR_ACK 0x4000 /* link partner abilities acknowledged (ro) */
#define ANAR_RF 0x2000 /* remote fault (ro) */
+ /* Annex 28B.2 */
#define ANAR_FC 0x0400 /* local device supports PAUSE */
#define ANAR_T4 0x0200 /* local device supports 100bT4 */
#define ANAR_TX_FD 0x0100 /* local device supports 100bTx FD */
@@ -123,6 +124,7 @@
#define ANAR_PAUSE_ASYM (2 << 10)
#define ANAR_PAUSE_TOWARDS (3 << 10)
+ /* Annex 28D */
#define ANAR_X_FD 0x0020 /* local device supports 1000BASE-X FD */
#define ANAR_X_HD 0x0040 /* local device supports 1000BASE-X HD */
#define ANAR_X_PAUSE_NONE (0 << 7)
@@ -184,12 +186,47 @@
#define GTSR_MAN_MS_FLT 0x8000 /* master/slave config fault */
#define GTSR_MS_RES 0x4000 /* result: 1 = master, 0 = slave */
#define GTSR_LRS 0x2000 /* local rx status, 1 = ok */
-#define GTSR_RRS 0x1000 /* remove rx status, 1 = ok */
+#define GTSR_RRS 0x1000 /* remote rx status, 1 = ok */
#define GTSR_LP_1000TFDX 0x0800 /* link partner 1000baseT FDX capable */
#define GTSR_LP_1000THDX 0x0400 /* link partner 1000baseT HDX capable */
#define GTSR_LP_ASM_DIR 0x0200 /* link partner asym. pause dir. capable */
#define GTSR_IDLE_ERR 0x00ff /* IDLE error count */
+#define MII_PSECR 0x0b /* PSE control register */
+#define PSECR_PACTLMASK 0x000c /* pair control mask */
+#define PSECR_PSEENMASK 0x0003 /* PSE enable mask */
+#define PSECR_PINOUTB 0x0008 /* PSE pinout Alternative B */
+#define PSECR_PINOUTA 0x0004 /* PSE pinout Alternative A */
+#define PSECR_FOPOWTST 0x0002 /* Force Power Test Mode */
+#define PSECR_PSEEN 0x0001 /* PSE Enabled */
+#define PSECR_PSEDIS 0x0000 /* PSE Disabled */
+
+#define MII_PSESR 0x0c /* PSE status register */
+#define PSESR_PWRDENIED 0x1000 /* Power Denied */
+#define PSESR_VALSIG 0x0800 /* Valid PD signature detected */
+#define PSESR_INVALSIG 0x0400 /* Invalid PD signature detected */
+#define PSESR_SHORTCIRC 0x0200 /* Short circuit condition detected */
+#define PSESR_OVERLOAD 0x0100 /* Overload condition detected */
+#define PSESR_MPSABSENT 0x0080 /* MPS absent condition detected */
+#define PSESR_PDCLMASK 0x0070 /* PD Class mask */
+#define PSESR_STATMASK 0x000e /* PSE Status mask */
+#define PSESR_PAIRCTABL 0x0001 /* PAIR Control Ability */
+#define PSESR_PDCL_4 (4 << 4) /* Class 4 */
+#define PSESR_PDCL_3 (3 << 4) /* Class 3 */
+#define PSESR_PDCL_2 (2 << 4) /* Class 2 */
+#define PSESR_PDCL_1 (1 << 4) /* Class 1 */
+#define PSESR_PDCL_0 (0 << 4) /* Class 0 */
+
+#define MII_MMDACR 0x0d /* MMD access control register */
+#define MMDACR_FUNCMASK 0xc000 /* function */
+#define MMDACR_DADDRMASK 0x001f /* device address */
+#define MMDACR_FN_ADDRESS (0 << 14) /* address */
+#define MMDACR_FN_DATANPI (1 << 14) /* data, no post increment */
+#define MMDACR_FN_DATAPIRW (2 << 14) /* data, post increment on r/w */
+#define MMDACR_FN_DATAPIW (3 << 14) /* data, post increment on wr only */
+
+#define MII_MMDAADR 0x0e /* MMD access address data register */
+
#define MII_EXTSR 0x0f /* Extended status register */
#define EXTSR_1000XFDX 0x8000 /* 1000X full-duplex capable */
#define EXTSR_1000XHDX 0x4000 /* 1000X half-duplex capable */
diff --git a/freebsd/sys/dev/mii/mii_physubr.c b/freebsd/sys/dev/mii/mii_physubr.c
index e2725ba6..e03d153a 100644
--- a/freebsd/sys/dev/mii/mii_physubr.c
+++ b/freebsd/sys/dev/mii/mii_physubr.c
@@ -56,9 +56,28 @@ __FBSDID("$FreeBSD$");
#include <rtems/bsd/local/miibus_if.h>
/*
- * Media to register setting conversion table. Order matters.
+ *
+ * An array of structures to map MII media types to BMCR/ANAR settings.
*/
-static const struct mii_media mii_media_table[MII_NMEDIA] = {
+enum {
+ MII_MEDIA_NONE = 0,
+ MII_MEDIA_10_T,
+ MII_MEDIA_10_T_FDX,
+ MII_MEDIA_100_T4,
+ MII_MEDIA_100_TX,
+ MII_MEDIA_100_TX_FDX,
+ MII_MEDIA_1000_X,
+ MII_MEDIA_1000_X_FDX,
+ MII_MEDIA_1000_T,
+ MII_MEDIA_1000_T_FDX,
+ MII_NMEDIA,
+};
+
+static const struct mii_media {
+ u_int mm_bmcr; /* BMCR settings for this media */
+ u_int mm_anar; /* ANAR settings for this media */
+ u_int mm_gtcr; /* 100base-T2 or 1000base-T CR */
+} mii_media_table[MII_NMEDIA] = {
/* None */
{ BMCR_ISO, ANAR_CSMA,
0, },
@@ -106,8 +125,10 @@ 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;
+ int index = -1;
- if (IFM_SUBTYPE(ife->ifm_media) == IFM_AUTO) {
+ switch (IFM_SUBTYPE(ife->ifm_media)) {
+ case IFM_AUTO:
/*
* Force renegotiation if MIIF_DOPAUSE or MIIF_FORCEANEG.
* The former is necessary as we might switch from flow-
@@ -117,19 +138,78 @@ mii_phy_setmedia(struct mii_softc *sc)
(sc->mii_flags & (MIIF_DOPAUSE | MIIF_FORCEANEG)) != 0)
(void)mii_phy_auto(sc);
return;
- }
- /*
- * Table index is stored in the media entry.
- */
+ case IFM_NONE:
+ index = MII_MEDIA_NONE;
+ break;
+
+ case IFM_HPNA_1:
+ index = MII_MEDIA_10_T;
+ break;
+
+ case IFM_10_T:
+ switch (IFM_OPTIONS(ife->ifm_media)) {
+ case 0:
+ index = MII_MEDIA_10_T;
+ break;
+ case IFM_FDX:
+ case (IFM_FDX | IFM_FLOW):
+ index = MII_MEDIA_10_T_FDX;
+ break;
+ }
+ break;
+
+ case IFM_100_TX:
+ case IFM_100_FX:
+ switch (IFM_OPTIONS(ife->ifm_media)) {
+ case 0:
+ index = MII_MEDIA_100_TX;
+ break;
+ case IFM_FDX:
+ case (IFM_FDX | IFM_FLOW):
+ index = MII_MEDIA_100_TX_FDX;
+ break;
+ }
+ break;
+
+ case IFM_100_T4:
+ index = MII_MEDIA_100_T4;
+ break;
- KASSERT(ife->ifm_data >=0 && ife->ifm_data < MII_NMEDIA,
- ("invalid ife->ifm_data (0x%x) in mii_phy_setmedia",
- ife->ifm_data));
+ case IFM_1000_SX:
+ switch (IFM_OPTIONS(ife->ifm_media)) {
+ case 0:
+ index = MII_MEDIA_1000_X;
+ break;
+ case IFM_FDX:
+ case (IFM_FDX | IFM_FLOW):
+ index = MII_MEDIA_1000_X_FDX;
+ break;
+ }
+ break;
+
+ case IFM_1000_T:
+ switch (IFM_OPTIONS(ife->ifm_media)) {
+ case 0:
+ case IFM_ETH_MASTER:
+ index = MII_MEDIA_1000_T;
+ break;
+ case IFM_FDX:
+ case (IFM_FDX | IFM_ETH_MASTER):
+ case (IFM_FDX | IFM_FLOW):
+ case (IFM_FDX | IFM_FLOW | IFM_ETH_MASTER):
+ index = MII_MEDIA_1000_T_FDX;
+ break;
+ }
+ break;
+ }
- 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;
+ KASSERT(index != -1, ("%s: failed to map media word %d",
+ __func__, ife->ifm_media));
+
+ anar = mii_media_table[index].mm_anar;
+ bmcr = mii_media_table[index].mm_bmcr;
+ gtcr = mii_media_table[index].mm_gtcr;
if (IFM_SUBTYPE(ife->ifm_media) == IFM_1000_T) {
gtcr |= GTCR_MAN_MS;
@@ -211,13 +291,8 @@ int
mii_phy_tick(struct mii_softc *sc)
{
struct ifmedia_entry *ife = sc->mii_pdata->mii_media.ifm_cur;
- struct ifnet *ifp = sc->mii_pdata->mii_ifp;
int reg;
- /* Just bail now if the interface is down. */
- if ((ifp->if_flags & IFF_UP) == 0)
- return (EJUSTRETURN);
-
/*
* If we're not doing autonegotiation, we don't need to do
* any extra work here. However, we need to check the link
@@ -286,12 +361,6 @@ mii_phy_reset(struct mii_softc *sc)
}
void
-mii_phy_down(struct mii_softc *sc)
-{
-
-}
-
-void
mii_phy_update(struct mii_softc *sc, int cmd)
{
struct mii_data *mii = sc->mii_pdata;
@@ -331,12 +400,11 @@ mii_phy_add_media(struct mii_softc *sc)
*/
sc->mii_anegticks = MII_ANEGTICKS;
-#define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL)
+#define ADD(m) ifmedia_add(&mii->mii_media, (m), 0, NULL)
#define PRINT(s) printf("%s%s", sep, s); sep = ", "
if ((sc->mii_flags & MIIF_NOISOLATE) == 0) {
- ADD(IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, sc->mii_inst),
- MII_MEDIA_NONE);
+ ADD(IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, sc->mii_inst));
PRINT("none");
}
@@ -348,51 +416,44 @@ mii_phy_add_media(struct mii_softc *sc)
if ((sc->mii_flags & MIIF_IS_HPNA) != 0) {
if ((sc->mii_capabilities & BMSR_10THDX) != 0) {
ADD(IFM_MAKEWORD(IFM_ETHER, IFM_HPNA_1, 0,
- sc->mii_inst), MII_MEDIA_10_T);
+ sc->mii_inst));
PRINT("HomePNA1");
}
return;
}
if ((sc->mii_capabilities & BMSR_10THDX) != 0) {
- ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, 0, sc->mii_inst),
- MII_MEDIA_10_T);
+ ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, 0, sc->mii_inst));
PRINT("10baseT");
}
if ((sc->mii_capabilities & BMSR_10TFDX) != 0) {
- ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, IFM_FDX, sc->mii_inst),
- MII_MEDIA_10_T_FDX);
+ ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, IFM_FDX, sc->mii_inst));
PRINT("10baseT-FDX");
if ((sc->mii_flags & MIIF_DOPAUSE) != 0 &&
(sc->mii_flags & MIIF_NOMANPAUSE) == 0) {
ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T,
- IFM_FDX | IFM_FLOW, sc->mii_inst),
- MII_MEDIA_10_T_FDX);
+ IFM_FDX | IFM_FLOW, sc->mii_inst));
PRINT("10baseT-FDX-flow");
}
fdx = 1;
}
if ((sc->mii_capabilities & BMSR_100TXHDX) != 0) {
- ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, 0, sc->mii_inst),
- MII_MEDIA_100_TX);
+ ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, 0, sc->mii_inst));
PRINT("100baseTX");
}
if ((sc->mii_capabilities & BMSR_100TXFDX) != 0) {
- ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_FDX, sc->mii_inst),
- MII_MEDIA_100_TX_FDX);
+ ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_FDX, sc->mii_inst));
PRINT("100baseTX-FDX");
if ((sc->mii_flags & MIIF_DOPAUSE) != 0 &&
(sc->mii_flags & MIIF_NOMANPAUSE) == 0) {
ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX,
- IFM_FDX | IFM_FLOW, sc->mii_inst),
- MII_MEDIA_100_TX_FDX);
+ IFM_FDX | IFM_FLOW, sc->mii_inst));
PRINT("100baseTX-FDX-flow");
}
fdx = 1;
}
if ((sc->mii_capabilities & BMSR_100T4) != 0) {
- ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_T4, 0, sc->mii_inst),
- MII_MEDIA_100_T4);
+ ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_T4, 0, sc->mii_inst));
PRINT("100baseT4");
}
@@ -405,20 +466,19 @@ mii_phy_add_media(struct mii_softc *sc)
sc->mii_anegticks = MII_ANEGTICKS_GIGE;
sc->mii_flags |= MIIF_IS_1000X;
ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_SX, 0,
- sc->mii_inst), MII_MEDIA_1000_X);
+ sc->mii_inst));
PRINT("1000baseSX");
}
if ((sc->mii_extcapabilities & EXTSR_1000XFDX) != 0) {
sc->mii_anegticks = MII_ANEGTICKS_GIGE;
sc->mii_flags |= MIIF_IS_1000X;
ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_SX, IFM_FDX,
- sc->mii_inst), MII_MEDIA_1000_X_FDX);
+ sc->mii_inst));
PRINT("1000baseSX-FDX");
if ((sc->mii_flags & MIIF_DOPAUSE) != 0 &&
(sc->mii_flags & MIIF_NOMANPAUSE) == 0) {
ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_SX,
- IFM_FDX | IFM_FLOW, sc->mii_inst),
- MII_MEDIA_1000_X_FDX);
+ IFM_FDX | IFM_FLOW, sc->mii_inst));
PRINT("1000baseSX-FDX-flow");
}
fdx = 1;
@@ -434,31 +494,29 @@ mii_phy_add_media(struct mii_softc *sc)
sc->mii_anegticks = MII_ANEGTICKS_GIGE;
sc->mii_flags |= MIIF_HAVE_GTCR;
ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T, 0,
- sc->mii_inst), MII_MEDIA_1000_T);
+ sc->mii_inst));
PRINT("1000baseT");
ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T,
- IFM_ETH_MASTER, sc->mii_inst), MII_MEDIA_1000_T);
+ IFM_ETH_MASTER, sc->mii_inst));
PRINT("1000baseT-master");
}
if ((sc->mii_extcapabilities & EXTSR_1000TFDX) != 0) {
sc->mii_anegticks = MII_ANEGTICKS_GIGE;
sc->mii_flags |= MIIF_HAVE_GTCR;
ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T, IFM_FDX,
- sc->mii_inst), MII_MEDIA_1000_T_FDX);
+ sc->mii_inst));
PRINT("1000baseT-FDX");
ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T,
- IFM_FDX | IFM_ETH_MASTER, sc->mii_inst),
- MII_MEDIA_1000_T_FDX);
+ IFM_FDX | IFM_ETH_MASTER, sc->mii_inst));
PRINT("1000baseT-FDX-master");
if ((sc->mii_flags & MIIF_DOPAUSE) != 0 &&
(sc->mii_flags & MIIF_NOMANPAUSE) == 0) {
ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T,
- IFM_FDX | IFM_FLOW, sc->mii_inst),
- MII_MEDIA_1000_T_FDX);
+ IFM_FDX | IFM_FLOW, sc->mii_inst));
PRINT("1000baseT-FDX-flow");
ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T,
IFM_FDX | IFM_FLOW | IFM_ETH_MASTER,
- sc->mii_inst), MII_MEDIA_1000_T_FDX);
+ sc->mii_inst));
PRINT("1000baseT-FDX-flow-master");
}
fdx = 1;
@@ -467,12 +525,11 @@ mii_phy_add_media(struct mii_softc *sc)
if ((sc->mii_capabilities & BMSR_ANEG) != 0) {
/* intentionally invalid index */
- ADD(IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, 0, sc->mii_inst),
- MII_NMEDIA);
+ ADD(IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, 0, sc->mii_inst));
PRINT("auto");
if (fdx != 0 && (sc->mii_flags & MIIF_DOPAUSE) != 0) {
ADD(IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, IFM_FLOW,
- sc->mii_inst), MII_NMEDIA);
+ sc->mii_inst));
PRINT("auto-flow");
}
}
@@ -486,7 +543,6 @@ mii_phy_detach(device_t dev)
struct mii_softc *sc;
sc = device_get_softc(dev);
- mii_phy_down(sc);
sc->mii_dev = NULL;
LIST_REMOVE(sc, mii_list);
return (0);
diff --git a/freebsd/sys/dev/mii/miivar.h b/freebsd/sys/dev/mii/miivar.h
index 34b0e9ed..498e7204 100644
--- a/freebsd/sys/dev/mii/miivar.h
+++ b/freebsd/sys/dev/mii/miivar.h
@@ -36,6 +36,7 @@
#define _DEV_MII_MIIVAR_H_
#include <sys/queue.h>
+#include <net/if_var.h> /* XXX driver API temporary */
/*
* Media Independent Interface data structure defintions
@@ -44,20 +45,13 @@
struct mii_softc;
/*
- * Callbacks from MII layer into network interface device driver.
- */
-typedef int (*mii_readreg_t)(struct device *, int, int);
-typedef void (*mii_writereg_t)(struct device *, int, int, int);
-typedef void (*mii_statchg_t)(struct device *);
-
-/*
* A network interface driver has one of these structures in its softc.
* It is the interface from the network interface driver to the MII
* layer.
*/
struct mii_data {
struct ifmedia mii_media; /* media information */
- struct ifnet *mii_ifp; /* pointer back to network interface */
+ if_t mii_ifp; /* pointer back to network interface */
/*
* For network interfaces with multiple PHYs, a list of all
@@ -72,13 +66,6 @@ struct mii_data {
*/
u_int mii_media_status;
u_int mii_media_active;
-
- /*
- * Calls from MII layer into network interface driver.
- */
- mii_readreg_t mii_readreg;
- mii_writereg_t mii_writereg;
- mii_statchg_t mii_statchg;
};
typedef struct mii_data mii_data_t;
@@ -193,27 +180,6 @@ struct mii_phydesc {
MII_STR_ ## a ## _ ## b }
#define MII_PHY_END { 0, 0, NULL }
-/*
- * An array of these structures map MII media types to BMCR/ANAR settings.
- */
-struct mii_media {
- u_int mm_bmcr; /* BMCR settings for this media */
- u_int mm_anar; /* ANAR settings for this media */
- u_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) \
@@ -246,9 +212,8 @@ MIIBUS_ACCESSOR(flags, FLAGS, u_int)
extern devclass_t miibus_devclass;
extern driver_t miibus_driver;
-int mii_attach(device_t, device_t *, struct ifnet *, ifm_change_cb_t,
+int mii_attach(device_t, device_t *, if_t, ifm_change_cb_t,
ifm_stat_cb_t, int, int, int, int);
-void mii_down(struct mii_data *);
int mii_mediachg(struct mii_data *);
void mii_tick(struct mii_data *);
void mii_pollstat(struct mii_data *);
@@ -256,12 +221,15 @@ void mii_phy_add_media(struct mii_softc *);
int mii_phy_auto(struct mii_softc *);
int mii_phy_detach(device_t dev);
-void mii_phy_down(struct mii_softc *);
u_int mii_phy_flowstatus(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 *);
+int mii_phy_mac_match(struct mii_softc *, const char *);
+int mii_dev_mac_match(device_t, const char *);
+void *mii_phy_mac_softc(struct mii_softc *);
+void *mii_dev_mac_softc(device_t);
const struct mii_phydesc * mii_phy_match(const struct mii_attach_args *ma,
const struct mii_phydesc *mpd);
diff --git a/freebsd/sys/dev/mii/rgephy.c b/freebsd/sys/dev/mii/rgephy.c
index 8dacb0e8..067bbadf 100644
--- a/freebsd/sys/dev/mii/rgephy.c
+++ b/freebsd/sys/dev/mii/rgephy.c
@@ -44,9 +44,11 @@ __FBSDID("$FreeBSD$");
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/socket.h>
+#include <sys/taskqueue.h>
#include <sys/bus.h>
#include <net/if.h>
+#include <net/if_var.h>
#include <net/if_arp.h>
#include <net/if_media.h>
@@ -59,7 +61,7 @@ __FBSDID("$FreeBSD$");
#include <rtems/bsd/local/miibus_if.h>
#include <machine/bus.h>
-#include <pci/if_rlreg.h>
+#include <dev/rl/if_rlreg.h>
static int rgephy_probe(device_t);
static int rgephy_attach(device_t);
@@ -90,6 +92,7 @@ static void rgephy_reset(struct mii_softc *);
static int rgephy_linkup(struct mii_softc *);
static void rgephy_loop(struct mii_softc *);
static void rgephy_load_dspcode(struct mii_softc *);
+static void rgephy_disable_eee(struct mii_softc *);
static const struct mii_phydesc rgephys[] = {
MII_PHY_DESC(REALTEK, RTL8169S),
@@ -114,13 +117,11 @@ static int
rgephy_attach(device_t dev)
{
struct mii_softc *sc;
- struct mii_attach_args *ma;
u_int flags;
sc = device_get_softc(dev);
- ma = device_get_ivars(dev);
flags = 0;
- if (strcmp(ma->mii_data->mii_ifp->if_dname, "re") == 0)
+ if (mii_dev_mac_match(dev, "re"))
flags |= MIIF_PHYPRIV0;
mii_phy_dev_attach(dev, flags, &rgephy_funcs, 0);
@@ -157,12 +158,6 @@ rgephy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
break;
case MII_MEDIACHG:
- /*
- * If the interface is not up, don't do anything.
- */
- if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
- break;
-
PHY_RESET(sc); /* XXX hardware bug work-around */
anar = PHY_READ(sc, RGEPHY_MII_ANAR);
@@ -235,12 +230,6 @@ setit:
case MII_TICK:
/*
- * Is the interface even up?
- */
- if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
- return (0);
-
- /*
* Only used for autonegotiation.
*/
if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) {
@@ -531,10 +520,9 @@ rgephy_reset(struct mii_softc *sc)
switch (sc->mii_mpd_rev) {
case RGEPHY_8211F:
pcr = PHY_READ(sc, RGEPHY_F_MII_PCR1);
- if ((pcr & RGEPHY_F_PCR1_MDI_MM) != 0) {
- pcr &= ~RGEPHY_F_PCR1_MDI_MM;
- PHY_WRITE(sc, RGEPHY_F_MII_PCR1, pcr);
- }
+ pcr &= ~(RGEPHY_F_PCR1_MDI_MM | RGEPHY_F_PCR1_ALDPS_EN);
+ PHY_WRITE(sc, RGEPHY_F_MII_PCR1, pcr);
+ rgephy_disable_eee(sc);
break;
case RGEPHY_8211C:
if ((sc->mii_flags & MIIF_PHYPRIV0) == 0) {
@@ -562,3 +550,29 @@ rgephy_reset(struct mii_softc *sc)
DELAY(1000);
rgephy_load_dspcode(sc);
}
+
+static void
+rgephy_disable_eee(struct mii_softc *sc)
+{
+ uint16_t anar;
+
+ PHY_WRITE(sc, RGEPHY_F_EPAGSR, 0x0000);
+ PHY_WRITE(sc, MII_MMDACR, MMDACR_FN_ADDRESS |
+ (MMDACR_DADDRMASK & RGEPHY_F_MMD_DEV_7));
+ PHY_WRITE(sc, MII_MMDAADR, RGEPHY_F_MMD_EEEAR);
+ PHY_WRITE(sc, MII_MMDACR, MMDACR_FN_DATANPI |
+ (MMDACR_DADDRMASK & RGEPHY_F_MMD_DEV_7));
+ PHY_WRITE(sc, MII_MMDAADR, 0x0000);
+ PHY_WRITE(sc, MII_MMDACR, 0x0000);
+ /*
+ * XXX
+ * Restart auto-negotiation to take changes effect.
+ * This may result in link establishment.
+ */
+ anar = BMSR_MEDIA_TO_ANAR(sc->mii_capabilities) | ANAR_CSMA;
+ PHY_WRITE(sc, RGEPHY_MII_ANAR, anar);
+ PHY_WRITE(sc, RGEPHY_MII_1000CTL, RGEPHY_1000CTL_AHD |
+ RGEPHY_1000CTL_AFD);
+ PHY_WRITE(sc, RGEPHY_MII_BMCR, RGEPHY_BMCR_RESET |
+ RGEPHY_BMCR_AUTOEN | RGEPHY_BMCR_STARTNEG);
+}
diff --git a/freebsd/sys/dev/mii/rgephyreg.h b/freebsd/sys/dev/mii/rgephyreg.h
index 2a00517e..7c24a1f7 100644
--- a/freebsd/sys/dev/mii/rgephyreg.h
+++ b/freebsd/sys/dev/mii/rgephyreg.h
@@ -183,4 +183,20 @@
#define RGEPHY_F_SSR_MDI 0x0002 /* MDI/MDIX */
#define RGEPHY_F_SSR_JABBER 0x0001 /* Jabber */
+/* RTL8211F */
+#define RGEPHY_F_EPAGSR 0x1F /* Extension page select register */
+
+/* RTL8211F */
+#define RGEPHY_F_MMD_DEV_7 0x07
+
+/* RTL8211F MMD device 7 */
+#define RGEPHY_F_MMD_EEEAR 0x3C /* EEE advertisement */
+#define EEEAR_1000T 0x0004 /* adv. 1000baseT EEE */
+#define EEEAR_100TX 0x0002 /* adv. 100baseTX EEE */
+
+/* RTL8211F MMD device 7 */
+#define RGEPHY_F_MMD_EEELPAR 0x3D /* EEE link partner abilities */
+#define EEELPAR_1000T 0x0004 /* link partner 1000baseT EEE capable */
+#define EEELPAR_100TX 0x0002 /* link partner 100baseTX EEE capable */
+
#endif /* _DEV_RGEPHY_MIIREG_H_ */