Move a lot closer to NetBSDs MII support for GigE.
Move fxp and nge drivers over to use the new stuff.
This commit is contained in:
parent
f7bf276ff5
commit
78c8c3db4b
@ -144,7 +144,7 @@ inphy_attach(device_t dev)
|
||||
|
||||
sc->mii_capabilities = PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
|
||||
device_printf(dev, " ");
|
||||
mii_add_media(sc);
|
||||
mii_phy_add_media(sc);
|
||||
printf("\n");
|
||||
|
||||
MIIBUS_MEDIAINIT(sc->mii_dev);
|
||||
@ -192,27 +192,7 @@ inphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
|
||||
if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
|
||||
break;
|
||||
|
||||
switch (IFM_SUBTYPE(ife->ifm_media)) {
|
||||
case IFM_AUTO:
|
||||
/*
|
||||
* If we're already in auto mode, just return.
|
||||
*/
|
||||
if (PHY_READ(sc, MII_BMCR) & BMCR_AUTOEN)
|
||||
return (0);
|
||||
(void) mii_phy_auto(sc, 0);
|
||||
break;
|
||||
case IFM_100_T4:
|
||||
/*
|
||||
* XXX Not supported as a manual setting right now.
|
||||
*/
|
||||
return (EINVAL);
|
||||
default:
|
||||
/*
|
||||
* BMCR data is stored in the ifmedia entry.
|
||||
*/
|
||||
PHY_WRITE(sc, MII_ANAR, mii_anar(ife->ifm_media));
|
||||
PHY_WRITE(sc, MII_BMCR, ife->ifm_data);
|
||||
}
|
||||
mii_phy_setmedia(sc);
|
||||
break;
|
||||
|
||||
case MII_TICK:
|
||||
@ -235,6 +215,7 @@ static void
|
||||
inphy_status(struct mii_softc *sc)
|
||||
{
|
||||
struct mii_data *mii = sc->mii_pdata;
|
||||
struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
|
||||
int bmsr, bmcr, scr;
|
||||
|
||||
mii->mii_media_status = IFM_AVALID;
|
||||
@ -268,5 +249,5 @@ inphy_status(struct mii_softc *sc)
|
||||
if (scr & SCR_FDX)
|
||||
mii->mii_media_active |= IFM_FDX;
|
||||
} else
|
||||
mii->mii_media_active |= mii_media_from_bmcr(bmcr);
|
||||
mii->mii_media_active = ife->ifm_media;
|
||||
}
|
||||
|
@ -92,7 +92,7 @@
|
||||
* 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.
|
||||
*/
|
||||
#if 1
|
||||
#if 0
|
||||
#define BMSR_MEDIAMASK (BMSR_100T4|BMSR_100TXFDX|BMSR_100TXHDX|BMSR_10TFDX| \
|
||||
BMSR_10THDX|BMSR_ANEG)
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
/* $NetBSD: mii_physubr.c,v 1.5 1999/08/03 19:41:49 drochner Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1998, 1999 The NetBSD Foundation, Inc.
|
||||
* Copyright (c) 1998, 1999, 2000, 2001 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
@ -127,10 +127,9 @@ mii_phy_setmedia(struct mii_softc *sc)
|
||||
* 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
|
||||
KASSERT(ife->ifm_data >=0 && ife->ifm_data < MII_NMEDIA,
|
||||
("invalid ife->ifm_data (0x%x) in mii_phy_setmedia",
|
||||
ife->ifm_data));
|
||||
|
||||
anar = mii_media_table[ife->ifm_data].mm_anar;
|
||||
bmcr = mii_media_table[ife->ifm_data].mm_bmcr;
|
||||
@ -157,29 +156,57 @@ mii_phy_setmedia(struct mii_softc *sc)
|
||||
}
|
||||
|
||||
int
|
||||
mii_phy_auto(mii, waitfor)
|
||||
struct mii_softc *mii;
|
||||
int waitfor;
|
||||
mii_phy_auto(struct mii_softc *sc, int waitfor)
|
||||
{
|
||||
int bmsr, i;
|
||||
|
||||
if ((mii->mii_flags & MIIF_DOINGAUTO) == 0) {
|
||||
PHY_WRITE(mii, MII_ANAR,
|
||||
BMSR_MEDIA_TO_ANAR(mii->mii_capabilities) | ANAR_CSMA);
|
||||
PHY_WRITE(mii, MII_BMCR, BMCR_AUTOEN | BMCR_STARTNEG);
|
||||
if ((sc->mii_flags & MIIF_DOINGAUTO) == 0) {
|
||||
/*
|
||||
* Check for 1000BASE-X. Autonegotiation is a bit
|
||||
* different on such devices.
|
||||
*/
|
||||
if (sc->mii_flags & MIIF_IS_1000X) {
|
||||
uint16_t anar = 0;
|
||||
|
||||
if (sc->mii_extcapabilities & EXTSR_1000XFDX)
|
||||
anar |= ANAR_X_FD;
|
||||
if (sc->mii_extcapabilities & EXTSR_1000XHDX)
|
||||
anar |= ANAR_X_HD;
|
||||
|
||||
if (sc->mii_flags & MIIF_DOPAUSE) {
|
||||
/* XXX Asymmetric vs. symmetric? */
|
||||
anar |= ANLPAR_X_PAUSE_TOWARDS;
|
||||
}
|
||||
|
||||
PHY_WRITE(sc, MII_ANAR, anar);
|
||||
} else {
|
||||
uint16_t anar;
|
||||
|
||||
anar = BMSR_MEDIA_TO_ANAR(sc->mii_capabilities) |
|
||||
ANAR_CSMA;
|
||||
if (sc->mii_flags & MIIF_DOPAUSE)
|
||||
anar |= ANAR_FC;
|
||||
PHY_WRITE(sc, MII_ANAR, anar);
|
||||
if (sc->mii_flags & MIIF_HAVE_GTCR) {
|
||||
uint16_t gtcr = 0;
|
||||
|
||||
if (sc->mii_extcapabilities & EXTSR_1000TFDX)
|
||||
gtcr |= GTCR_ADV_1000TFDX;
|
||||
if (sc->mii_extcapabilities & EXTSR_1000THDX)
|
||||
gtcr |= GTCR_ADV_1000THDX;
|
||||
|
||||
PHY_WRITE(sc, MII_100T2CR, gtcr);
|
||||
}
|
||||
}
|
||||
PHY_WRITE(sc, MII_BMCR, BMCR_AUTOEN | BMCR_STARTNEG);
|
||||
}
|
||||
|
||||
if (waitfor) {
|
||||
/* Wait 500ms for it to complete. */
|
||||
for (i = 0; i < 500; i++) {
|
||||
if ((bmsr = PHY_READ(mii, MII_BMSR)) & BMSR_ACOMP)
|
||||
if ((bmsr = PHY_READ(sc, MII_BMSR)) & BMSR_ACOMP)
|
||||
return (0);
|
||||
DELAY(1000);
|
||||
#if 0
|
||||
if ((bmsr & BMSR_ACOMP) == 0)
|
||||
printf("%s: autonegotiation failed to complete\n",
|
||||
mii->mii_dev.dv_xname);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
@ -195,9 +222,9 @@ mii_phy_auto(mii, waitfor)
|
||||
* the tick handler driving autonegotiation. Don't want 500ms
|
||||
* delays all the time while the system is running!
|
||||
*/
|
||||
if ((mii->mii_flags & MIIF_DOINGAUTO) == 0) {
|
||||
mii->mii_flags |= MIIF_DOINGAUTO;
|
||||
mii->mii_auto_ch = timeout(mii_phy_auto_timeout, mii, hz >> 1);
|
||||
if ((sc->mii_flags & MIIF_DOINGAUTO) == 0) {
|
||||
sc->mii_flags |= MIIF_DOINGAUTO;
|
||||
sc->mii_auto_ch = timeout(mii_phy_auto_timeout, sc, hz >> 1);
|
||||
}
|
||||
return (EJUSTRETURN);
|
||||
}
|
||||
@ -213,37 +240,33 @@ mii_phy_auto_stop(sc)
|
||||
}
|
||||
|
||||
void
|
||||
mii_phy_auto_timeout(arg)
|
||||
void *arg;
|
||||
mii_phy_auto_timeout(void *arg)
|
||||
{
|
||||
struct mii_softc *mii = arg;
|
||||
struct mii_softc *sc = arg;
|
||||
int s, bmsr;
|
||||
|
||||
s = splnet();
|
||||
mii->mii_flags &= ~MIIF_DOINGAUTO;
|
||||
bmsr = PHY_READ(mii, MII_BMSR);
|
||||
#if 0
|
||||
if ((bmsr & BMSR_ACOMP) == 0)
|
||||
printf("%s: autonegotiation failed to complete\n",
|
||||
sc->sc_dev.dv_xname);
|
||||
if ((sc->mii_dev.dv_flags & DVF_ACTIVE) == 0)
|
||||
return;
|
||||
#endif
|
||||
|
||||
s = splnet();
|
||||
sc->mii_flags &= ~MIIF_DOINGAUTO;
|
||||
bmsr = PHY_READ(sc, MII_BMSR);
|
||||
|
||||
/* Update the media status. */
|
||||
(void) (*mii->mii_service)(mii, mii->mii_pdata, MII_POLLSTAT);
|
||||
(void) (*sc->mii_service)(sc, sc->mii_pdata, MII_POLLSTAT);
|
||||
splx(s);
|
||||
}
|
||||
|
||||
int
|
||||
mii_phy_tick(sc)
|
||||
struct mii_softc *sc;
|
||||
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;
|
||||
|
||||
/*
|
||||
* Is the interface even up?
|
||||
*/
|
||||
/* Just bail now if the interface is down. */
|
||||
if ((ifp->if_flags & IFF_UP) == 0)
|
||||
return (EJUSTRETURN);
|
||||
|
||||
@ -256,18 +279,21 @@ mii_phy_tick(sc)
|
||||
if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO)
|
||||
return (0);
|
||||
|
||||
/*
|
||||
* check for link.
|
||||
* Read the status register twice; BMSR_LINK is latch-low.
|
||||
*/
|
||||
/* Read the status register twice; BMSR_LINK is latch-low. */
|
||||
reg = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR);
|
||||
if (reg & BMSR_LINK)
|
||||
if (reg & BMSR_LINK) {
|
||||
/*
|
||||
* See above.
|
||||
*/
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Only retry autonegotiation every 5 seconds.
|
||||
* Only retry autonegotiation every N seconds.
|
||||
*/
|
||||
if (++sc->mii_ticks != 5)
|
||||
if (sc->mii_anegticks == 0)
|
||||
sc->mii_anegticks = 5;
|
||||
if (++sc->mii_ticks != sc->mii_anegticks)
|
||||
return (EJUSTRETURN);
|
||||
|
||||
sc->mii_ticks = 0;
|
||||
@ -283,27 +309,26 @@ mii_phy_tick(sc)
|
||||
}
|
||||
|
||||
void
|
||||
mii_phy_reset(mii)
|
||||
struct mii_softc *mii;
|
||||
mii_phy_reset(struct mii_softc *sc)
|
||||
{
|
||||
int reg, i;
|
||||
|
||||
if (mii->mii_flags & MIIF_NOISOLATE)
|
||||
if (sc->mii_flags & MIIF_NOISOLATE)
|
||||
reg = BMCR_RESET;
|
||||
else
|
||||
reg = BMCR_RESET | BMCR_ISO;
|
||||
PHY_WRITE(mii, MII_BMCR, reg);
|
||||
PHY_WRITE(sc, MII_BMCR, reg);
|
||||
|
||||
/* Wait 100ms for it to complete. */
|
||||
for (i = 0; i < 100; i++) {
|
||||
reg = PHY_READ(mii, MII_BMCR);
|
||||
reg = PHY_READ(sc, MII_BMCR);
|
||||
if ((reg & BMCR_RESET) == 0)
|
||||
break;
|
||||
DELAY(1000);
|
||||
}
|
||||
|
||||
if (mii->mii_inst != 0 && ((mii->mii_flags & MIIF_NOISOLATE) == 0))
|
||||
PHY_WRITE(mii, MII_BMCR, reg | BMCR_ISO);
|
||||
if (sc->mii_inst != 0 && ((sc->mii_flags & MIIF_NOISOLATE) == 0))
|
||||
PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO);
|
||||
}
|
||||
|
||||
void
|
||||
@ -436,3 +461,122 @@ mii_add_media(struct mii_softc *sc)
|
||||
#undef ADD
|
||||
#undef PRINT
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize generic PHY media based on BMSR, called when a PHY is
|
||||
* attached. We expect to be set up to print a comma-separated list
|
||||
* of media names. Does not print a newline.
|
||||
*/
|
||||
void
|
||||
mii_phy_add_media(struct mii_softc *sc)
|
||||
{
|
||||
struct mii_data *mii = sc->mii_pdata;
|
||||
const char *sep = "";
|
||||
|
||||
#define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), 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);
|
||||
|
||||
/*
|
||||
* There are different interpretations for the bits in
|
||||
* HomePNA PHYs. And there is really only one media type
|
||||
* that is supported.
|
||||
*/
|
||||
if (sc->mii_flags & MIIF_IS_HPNA) {
|
||||
if (sc->mii_capabilities & BMSR_10THDX) {
|
||||
ADD(IFM_MAKEWORD(IFM_ETHER, IFM_HPNA_1, 0,
|
||||
sc->mii_inst),
|
||||
MII_MEDIA_10_T);
|
||||
PRINT("HomePNA1");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (sc->mii_capabilities & BMSR_10THDX) {
|
||||
ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, 0, sc->mii_inst),
|
||||
MII_MEDIA_10_T);
|
||||
PRINT("10baseT");
|
||||
}
|
||||
if (sc->mii_capabilities & BMSR_10TFDX) {
|
||||
ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, IFM_FDX, sc->mii_inst),
|
||||
MII_MEDIA_10_T_FDX);
|
||||
PRINT("10baseT-FDX");
|
||||
}
|
||||
if (sc->mii_capabilities & BMSR_100TXHDX) {
|
||||
ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, 0, sc->mii_inst),
|
||||
MII_MEDIA_100_TX);
|
||||
PRINT("100baseTX");
|
||||
}
|
||||
if (sc->mii_capabilities & BMSR_100TXFDX) {
|
||||
ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_FDX, sc->mii_inst),
|
||||
MII_MEDIA_100_TX_FDX);
|
||||
PRINT("100baseTX-FDX");
|
||||
}
|
||||
if (sc->mii_capabilities & BMSR_100T4) {
|
||||
ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_T4, 0, sc->mii_inst),
|
||||
MII_MEDIA_100_T4);
|
||||
PRINT("100baseT4");
|
||||
}
|
||||
|
||||
if (sc->mii_extcapabilities & EXTSR_MEDIAMASK) {
|
||||
/*
|
||||
* XXX Right now only handle 1000SX and 1000TX. Need
|
||||
* XXX to handle 1000LX and 1000CX some how.
|
||||
*
|
||||
* Note since it can take 5 seconds to auto-negotiate
|
||||
* a gigabit link, we make anegticks 10 seconds for
|
||||
* all the gigabit media types.
|
||||
*/
|
||||
if (sc->mii_extcapabilities & EXTSR_1000XHDX) {
|
||||
sc->mii_anegticks = 10;
|
||||
sc->mii_flags |= MIIF_IS_1000X;
|
||||
ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_SX, 0,
|
||||
sc->mii_inst), MII_MEDIA_1000_X);
|
||||
PRINT("1000baseSX");
|
||||
}
|
||||
if (sc->mii_extcapabilities & EXTSR_1000XFDX) {
|
||||
sc->mii_anegticks = 10;
|
||||
sc->mii_flags |= MIIF_IS_1000X;
|
||||
ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_SX, IFM_FDX,
|
||||
sc->mii_inst), MII_MEDIA_1000_X_FDX);
|
||||
PRINT("1000baseSX-FDX");
|
||||
}
|
||||
|
||||
/*
|
||||
* 1000baseT media needs to be able to manipulate
|
||||
* master/slave mode. We set IFM_ETH_MASTER in
|
||||
* the "don't care mask" and filter it out when
|
||||
* the media is set.
|
||||
*
|
||||
* All 1000baseT PHYs have a 1000baseT control register.
|
||||
*/
|
||||
if (sc->mii_extcapabilities & EXTSR_1000THDX) {
|
||||
sc->mii_anegticks = 10;
|
||||
sc->mii_flags |= MIIF_HAVE_GTCR;
|
||||
mii->mii_media.ifm_mask |= IFM_ETH_MASTER;
|
||||
ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T, 0,
|
||||
sc->mii_inst), MII_MEDIA_1000_T);
|
||||
PRINT("1000baseT");
|
||||
}
|
||||
if (sc->mii_extcapabilities & EXTSR_1000TFDX) {
|
||||
sc->mii_anegticks = 10;
|
||||
sc->mii_flags |= MIIF_HAVE_GTCR;
|
||||
mii->mii_media.ifm_mask |= IFM_ETH_MASTER;
|
||||
ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T, IFM_FDX,
|
||||
sc->mii_inst), MII_MEDIA_1000_T_FDX);
|
||||
PRINT("1000baseT-FDX");
|
||||
}
|
||||
}
|
||||
|
||||
if (sc->mii_capabilities & BMSR_ANEG) {
|
||||
ADD(IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, 0, sc->mii_inst),
|
||||
MII_NMEDIA); /* intentionally invalid index */
|
||||
PRINT("auto");
|
||||
}
|
||||
#undef ADD
|
||||
#undef PRINT
|
||||
}
|
||||
|
||||
|
@ -197,6 +197,7 @@ void mii_tick(struct mii_data *);
|
||||
void mii_pollstat(struct mii_data *);
|
||||
int mii_phy_probe(device_t, device_t *, ifm_change_cb_t, ifm_stat_cb_t);
|
||||
void mii_add_media(struct mii_softc *);
|
||||
void mii_phy_add_media(struct mii_softc *);
|
||||
|
||||
int mii_media_from_bmcr(int);
|
||||
|
||||
|
@ -2,6 +2,12 @@
|
||||
* Copyright (c) 2001 Wind River Systems
|
||||
* Copyright (c) 2001
|
||||
* Bill Paul <wpaul@bsdi.com>. All rights reserved.
|
||||
* Copyright (c) 1998, 1999, 2000, 2001 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
|
||||
* NASA Ames Research Center.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@ -97,7 +103,6 @@ DRIVER_MODULE(nsgphy, miibus, nsgphy_driver, nsgphy_devclass, 0, 0);
|
||||
|
||||
static int nsgphy_service(struct mii_softc *, struct mii_data *,int);
|
||||
static void nsgphy_status(struct mii_softc *);
|
||||
static int nsgphy_mii_phy_auto(struct mii_softc *, int);
|
||||
extern void mii_phy_auto_timeout(void *);
|
||||
|
||||
static int
|
||||
@ -127,7 +132,6 @@ nsgphy_attach(device_t dev)
|
||||
struct mii_softc *sc;
|
||||
struct mii_attach_args *ma;
|
||||
struct mii_data *mii;
|
||||
const char *sep = "";
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
ma = device_get_ivars(dev);
|
||||
@ -139,48 +143,17 @@ nsgphy_attach(device_t dev)
|
||||
sc->mii_phy = ma->mii_phyno;
|
||||
sc->mii_service = nsgphy_service;
|
||||
sc->mii_pdata = mii;
|
||||
sc->mii_anegticks = 5;
|
||||
|
||||
sc->mii_flags |= MIIF_NOISOLATE;
|
||||
mii->mii_instance++;
|
||||
|
||||
#define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL)
|
||||
#define PRINT(s) printf("%s%s", sep, s); sep = ", "
|
||||
|
||||
ADD(IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, sc->mii_inst),
|
||||
BMCR_ISO);
|
||||
#if 0
|
||||
ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_LOOP, sc->mii_inst),
|
||||
BMCR_LOOP|BMCR_S100);
|
||||
#endif
|
||||
|
||||
mii_phy_reset(sc);
|
||||
|
||||
device_printf(dev, " ");
|
||||
ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T, IFM_FDX, sc->mii_inst),
|
||||
BMCR_S1000|BMCR_FDX);
|
||||
PRINT("1000baseTX-FDX");
|
||||
ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T, 0, sc->mii_inst),
|
||||
BMCR_S1000);
|
||||
PRINT("1000baseTX");
|
||||
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");
|
||||
ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, 0, sc->mii_inst), BMCR_S100);
|
||||
PRINT("100baseTX");
|
||||
ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, IFM_FDX, sc->mii_inst),
|
||||
BMCR_S10|BMCR_FDX);
|
||||
PRINT("10baseT-FDX");
|
||||
ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, 0, sc->mii_inst), BMCR_S10);
|
||||
PRINT("10baseT");
|
||||
ADD(IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, 0, sc->mii_inst), 0);
|
||||
PRINT("auto");
|
||||
|
||||
mii_phy_add_media(sc);
|
||||
printf("\n");
|
||||
#undef ADD
|
||||
#undef PRINT
|
||||
|
||||
MIIBUS_MEDIAINIT(sc->mii_dev);
|
||||
return(0);
|
||||
@ -234,59 +207,7 @@ nsgphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
|
||||
if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
|
||||
break;
|
||||
|
||||
|
||||
switch (IFM_SUBTYPE(ife->ifm_media)) {
|
||||
case IFM_AUTO:
|
||||
#ifdef foo
|
||||
/*
|
||||
* If we're already in auto mode, just return.
|
||||
*/
|
||||
if (PHY_READ(sc, MII_BMCR) & BMCR_AUTOEN)
|
||||
return (0);
|
||||
#endif
|
||||
(void) nsgphy_mii_phy_auto(sc, 0);
|
||||
break;
|
||||
case IFM_1000_T:
|
||||
if ((ife->ifm_media & IFM_GMASK) == IFM_FDX) {
|
||||
PHY_WRITE(sc, MII_BMCR,
|
||||
BMCR_FDX|BMCR_SPEED1);
|
||||
} else {
|
||||
PHY_WRITE(sc, MII_BMCR,
|
||||
BMCR_SPEED1);
|
||||
}
|
||||
PHY_WRITE(sc, MII_ANAR, ANAR_CSMA);
|
||||
|
||||
/*
|
||||
* When setting the link manually, one side must
|
||||
* be the master and the other the slave. However
|
||||
* ifmedia doesn't give us a good way to specify
|
||||
* this, so we fake it by using one of the LINK
|
||||
* flags. If LINK0 is set, we program the PHY to
|
||||
* be a master, otherwise it's a slave.
|
||||
*/
|
||||
if ((mii->mii_ifp->if_flags & IFF_LINK0)) {
|
||||
PHY_WRITE(sc, MII_100T2CR,
|
||||
GTCR_MAN_MS|GTCR_ADV_MS);
|
||||
} else {
|
||||
PHY_WRITE(sc, MII_100T2CR, GTCR_MAN_MS);
|
||||
}
|
||||
break;
|
||||
case IFM_100_T4:
|
||||
/*
|
||||
* XXX Not supported as a manual setting right now.
|
||||
*/
|
||||
return (EINVAL);
|
||||
case IFM_NONE:
|
||||
PHY_WRITE(sc, MII_BMCR, BMCR_ISO|BMCR_PDOWN);
|
||||
break;
|
||||
default:
|
||||
/*
|
||||
* BMCR data is stored in the ifmedia entry.
|
||||
*/
|
||||
PHY_WRITE(sc, MII_ANAR, mii_anar(ife->ifm_media));
|
||||
PHY_WRITE(sc, MII_BMCR, ife->ifm_data);
|
||||
break;
|
||||
}
|
||||
mii_phy_setmedia(sc);
|
||||
break;
|
||||
|
||||
case MII_TICK:
|
||||
@ -296,39 +217,8 @@ nsgphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
|
||||
if (IFM_INST(ife->ifm_media) != sc->mii_inst)
|
||||
return (0);
|
||||
|
||||
/*
|
||||
* Is the interface even up?
|
||||
*/
|
||||
if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
|
||||
if (mii_phy_tick(sc) == EJUSTRETURN)
|
||||
return (0);
|
||||
|
||||
/*
|
||||
* Only used for autonegotiation.
|
||||
*/
|
||||
if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO)
|
||||
break;
|
||||
|
||||
/*
|
||||
* Check to see if we have link.
|
||||
*/
|
||||
reg = PHY_READ(sc, NSGPHY_MII_PHYSUP);
|
||||
if (reg & NSGPHY_PHYSUP_LNKSTS)
|
||||
break;
|
||||
|
||||
/*
|
||||
* Only retry autonegotiation every 5 seconds.
|
||||
* Actually, for gigE PHYs, we should wait longer, since
|
||||
* 5 seconds is the mimimum time the documentation
|
||||
* says to wait for a 1000mbps link to be established.
|
||||
*/
|
||||
if (++sc->mii_ticks != 10)
|
||||
return (0);
|
||||
|
||||
sc->mii_ticks = 0;
|
||||
|
||||
mii_phy_reset(sc);
|
||||
if (nsgphy_mii_phy_auto(sc, 0) == EJUSTRETURN)
|
||||
return(0);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -344,19 +234,25 @@ static void
|
||||
nsgphy_status(struct mii_softc *sc)
|
||||
{
|
||||
struct mii_data *mii = sc->mii_pdata;
|
||||
int bmsr, bmcr, physup, anlpar, gstat;
|
||||
struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
|
||||
int bmsr, bmcr, physup, gtsr;
|
||||
|
||||
mii->mii_media_status = IFM_AVALID;
|
||||
mii->mii_media_active = IFM_ETHER;
|
||||
|
||||
bmsr = PHY_READ(sc, MII_BMSR);
|
||||
bmsr = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR);
|
||||
|
||||
physup = PHY_READ(sc, NSGPHY_MII_PHYSUP);
|
||||
|
||||
if (physup & NSGPHY_PHYSUP_LNKSTS)
|
||||
if (physup & PHY_SUP_LINK)
|
||||
mii->mii_media_status |= IFM_ACTIVE;
|
||||
|
||||
bmcr = PHY_READ(sc, MII_BMCR);
|
||||
if (bmcr & BMCR_ISO) {
|
||||
mii->mii_media_active |= IFM_NONE;
|
||||
mii->mii_media_status = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (bmcr & BMCR_LOOP)
|
||||
mii->mii_media_active |= IFM_LOOP;
|
||||
@ -371,100 +267,29 @@ nsgphy_status(struct mii_softc *sc)
|
||||
mii->mii_media_active |= IFM_NONE;
|
||||
return;
|
||||
}
|
||||
anlpar = PHY_READ(sc, MII_ANLPAR);
|
||||
gstat = PHY_READ(sc, MII_100T2SR);
|
||||
if (gstat & GTSR_LP_1000TFDX)
|
||||
mii->mii_media_active |= IFM_1000_T|IFM_FDX;
|
||||
else if (gstat & GTSR_LP_1000THDX)
|
||||
mii->mii_media_active |= IFM_1000_T|IFM_HDX;
|
||||
else if (anlpar & ANLPAR_T4)
|
||||
mii->mii_media_active |= IFM_100_T4;
|
||||
else if (anlpar & ANLPAR_TX_FD)
|
||||
mii->mii_media_active |= IFM_100_TX|IFM_FDX;
|
||||
else if (anlpar & ANLPAR_TX)
|
||||
|
||||
switch (physup & (PHY_SUP_SPEED1|PHY_SUP_SPEED0)) {
|
||||
case PHY_SUP_SPEED1:
|
||||
mii->mii_media_active |= IFM_1000_T;
|
||||
gtsr = PHY_READ(sc, MII_100T2SR);
|
||||
if (gtsr & GTSR_MS_RES)
|
||||
mii->mii_media_active |= IFM_ETH_MASTER;
|
||||
break;
|
||||
|
||||
case PHY_SUP_SPEED0:
|
||||
mii->mii_media_active |= IFM_100_TX;
|
||||
else if (anlpar & ANLPAR_10_FD)
|
||||
mii->mii_media_active |= IFM_10_T|IFM_FDX;
|
||||
else if (anlpar & ANLPAR_10)
|
||||
mii->mii_media_active |= IFM_10_T|IFM_HDX;
|
||||
else
|
||||
break;
|
||||
|
||||
case 0:
|
||||
mii->mii_media_active |= IFM_10_T;
|
||||
break;
|
||||
|
||||
default:
|
||||
mii->mii_media_active |= IFM_NONE;
|
||||
return;
|
||||
}
|
||||
|
||||
switch(bmcr & (BMCR_SPEED1|BMCR_SPEED0)) {
|
||||
case BMCR_S1000:
|
||||
mii->mii_media_active |= IFM_1000_T;
|
||||
break;
|
||||
case BMCR_S100:
|
||||
mii->mii_media_active |= IFM_100_TX;
|
||||
break;
|
||||
case BMCR_S10:
|
||||
mii->mii_media_active |= IFM_10_T;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (bmcr & BMCR_FDX)
|
||||
mii->mii_media_active |= IFM_FDX;
|
||||
else
|
||||
mii->mii_media_active |= IFM_HDX;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
nsgphy_mii_phy_auto(struct mii_softc *mii, int waitfor)
|
||||
{
|
||||
int bmsr, ktcr = 0, i;
|
||||
|
||||
if ((mii->mii_flags & MIIF_DOINGAUTO) == 0) {
|
||||
mii_phy_reset(mii);
|
||||
PHY_WRITE(mii, MII_BMCR, 0);
|
||||
DELAY(1000);
|
||||
ktcr = PHY_READ(mii, MII_100T2CR);
|
||||
PHY_WRITE(mii, MII_100T2CR, ktcr |
|
||||
(GTCR_ADV_1000TFDX|GTCR_ADV_1000THDX));
|
||||
ktcr = PHY_READ(mii, MII_100T2CR);
|
||||
DELAY(1000);
|
||||
PHY_WRITE(mii, MII_ANAR,
|
||||
BMSR_MEDIA_TO_ANAR(mii->mii_capabilities) | ANAR_CSMA);
|
||||
DELAY(1000);
|
||||
PHY_WRITE(mii, MII_BMCR,
|
||||
BMCR_AUTOEN | BMCR_STARTNEG);
|
||||
}
|
||||
|
||||
if (waitfor) {
|
||||
/* Wait 500ms for it to complete. */
|
||||
for (i = 0; i < 500; i++) {
|
||||
if ((bmsr = PHY_READ(mii, MII_BMSR)) & BMSR_ACOMP)
|
||||
return (0);
|
||||
DELAY(1000);
|
||||
#if 0
|
||||
if ((bmsr & BMSR_ACOMP) == 0)
|
||||
printf("%s: autonegotiation failed to complete\n",
|
||||
mii->mii_dev.dv_xname);
|
||||
#endif
|
||||
mii->mii_media_status = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Don't need to worry about clearing MIIF_DOINGAUTO.
|
||||
* If that's set, a timeout is pending, and it will
|
||||
* clear the flag.
|
||||
*/
|
||||
return (EIO);
|
||||
}
|
||||
|
||||
/*
|
||||
* Just let it finish asynchronously. This is for the benefit of
|
||||
* the tick handler driving autonegotiation. Don't want 500ms
|
||||
* delays all the time while the system is running!
|
||||
*/
|
||||
if ((mii->mii_flags & MIIF_DOINGAUTO) == 0) {
|
||||
mii->mii_flags |= MIIF_DOINGAUTO;
|
||||
mii->mii_auto_ch = timeout(mii_phy_auto_timeout, mii, hz >> 1);
|
||||
}
|
||||
return (EJUSTRETURN);
|
||||
if (physup & PHY_SUP_DUPLEX)
|
||||
mii->mii_media_active |= IFM_FDX;
|
||||
} else
|
||||
mii->mii_media_active = ife->ifm_media;
|
||||
}
|
||||
|
@ -54,10 +54,14 @@
|
||||
#define NSGPHY_STRAPOPT_SPDSEL (NSGPHY_STRAPOPT_SPEED1|NSGPHY_STRAPOPT_SPEED0)
|
||||
|
||||
#define NSGPHY_MII_PHYSUP 0x11 /* PHY support/current status */
|
||||
#define PHY_SUP_SPEED1 0x0010 /* speed bit 1 */
|
||||
#define PHY_SUP_SPEED0 0x0008 /* speed bit 1 */
|
||||
#define NSGPHY_PHYSUP_SPEED1 0x0010 /* speed status */
|
||||
#define NSGPHY_PHYSUP_SPEED0 0x0008 /* speed status */
|
||||
#define NSGPHY_PHYSUP_SPDSTS (NSGPHY_PHYSUP_SPEED1|NSGPHY_PHYSUP_SPEED0)
|
||||
#define NSGPHY_PHYSUP_LNKSTS 0x0004 /* link status */
|
||||
#define PHY_SUP_LINK 0x0004 /* link status */
|
||||
#define PHY_SUP_DUPLEX 0x0002 /* 1 == full-duplex */
|
||||
#define NSGPHY_PHYSUP_DUPSTS 0x0002 /* duplex status 1 == full */
|
||||
#define NSGPHY_PHYSUP_10BT 0x0001 /* 10baseT resolved */
|
||||
|
||||
|
@ -1980,10 +1980,12 @@ static void nge_stop(sc)
|
||||
ifp->if_flags |= IFF_UP;
|
||||
ifm = mii->mii_media.ifm_cur;
|
||||
mtmp = ifm->ifm_media;
|
||||
ifm->ifm_media = IFM_ETHER|IFM_NONE;
|
||||
#if 0
|
||||
ifm->ifm_media = IFM_ETHER|IFM_AUTO;
|
||||
mii_mediachg(mii);
|
||||
ifm->ifm_media = mtmp;
|
||||
ifp->if_flags = itmp;
|
||||
#endif
|
||||
|
||||
sc->nge_link = 0;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user