Moving closer to being able to use NetBSD's generic mii_set_media()
function.
This commit is contained in:
parent
8ad896e0ad
commit
b7dee1db97
@ -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");
|
||||
}
|
||||
|
@ -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 *);
|
||||
|
||||
|
@ -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");
|
||||
|
Loading…
Reference in New Issue
Block a user