Unix Technical Forum

eephy(4) diff

This is a discussion on eephy(4) diff within the mailing.openbsd.tech forums, part of the OpenBSD category; --> This diff simplifies the code considerably and should improve the functionality as well. But it will need to be ...


Go Back   Unix Technical Forum > Unix Operating Systems > OpenBSD > mailing.openbsd.tech

FAQ Members List Calendar Search Today's Posts Mark Forums Read
  #1 (permalink)  
Old 02-18-2008, 09:05 AM
Mark Kettenis
 
Posts: n/a
Default eephy(4) diff

This diff simplifies the code considerably and should improve the
functionality as well. But it will need to be tested on all network
drivers eephy(4) attaches to:

* axe(4)
* gem(4): Found on certain PowerBook models.
* msk(4)
* nfe(4)
* sk(4)
* stge(4)

Please check whether the device functions as before, and
autonegotiates properly. Please report successes as well as failures
and please mail the relevant part of the dmesg output, like:

mskc0 at pci0 dev 8 function 0 "Schneider & Koch SK-9Sxx" rev 0x14,
Marvell Yukon-2 XL rev. A3 (0x3): irq 5
msk0 at mskc0 port A, address 00:00:5a:72:ea:e9
eephy0 at msk0 phy 0: Marvell 88E1112 Gigabit PHY, rev. 1

Thanks,

Mark


Index: mii/eephy.c
================================================== =================
RCS file: /cvs/src/sys/dev/mii/eephy.c,v
retrieving revision 1.37
diff -u -p -r1.37 eephy.c
--- mii/eephy.c 29 Dec 2006 11:03:46 -0000 1.37
+++ mii/eephy.c 29 Dec 2006 21:24:23 -0000
@@ -115,8 +115,6 @@ static const struct mii_phydesc eephys[]
NULL },
};

-static int fast_ether;
-
int
eephymatch(struct device *parent, void *match, void *aux)
{
@@ -135,6 +133,7 @@ eephyattach(struct device *parent, struc
struct mii_attach_args *ma = aux;
struct mii_data *mii = ma->mii_data;
const struct mii_phydesc *mpd;
+ int reg;

mpd = mii_phy_match(ma, eephys);
printf(": %s, rev. %d\n", mpd->mpd_name, MII_REV(ma->mii_id2));
@@ -145,7 +144,6 @@ eephyattach(struct device *parent, struc
sc->mii_model = MII_MODEL(ma->mii_id2);
sc->mii_pdata = mii;
sc->mii_flags = ma->mii_flags;
- sc->mii_anegticks = MII_ANEGTICKS_GIGE;

/*
* XXX really should be passed by the network controller
@@ -153,99 +151,87 @@ eephyattach(struct device *parent, struc
*/
sc->mii_flags |= MIIF_DOPAUSE;

- if (MII_OUI(ma->mii_id1, ma->mii_id2) == MII_OUI_MARVELL &&
- MII_MODEL(ma->mii_id2) == MII_MODEL_MARVELL_E1011 &&
- (PHY_READ(sc, E1000_ESSR) & E1000_ESSR_FIBER_LINK))
- sc->mii_flags |= MIIF_HAVEFIBER;
-
- fast_ether = 0;
- if (MII_OUI(ma->mii_id1, ma->mii_id2) == MII_OUI_MARVELL &&
- MII_MODEL(ma->mii_id2) == MII_MODEL_MARVELL_E3082) {
- /* 88E3082 10/100 Fast Ethernet PHY. */
- sc->mii_anegticks = MII_ANEGTICKS;
- fast_ether = 1;
- }
+ /* XXX No loopback support yet, although the hardware can do it. */
+ sc->mii_flags |= MIIF_NOLOOP;

- PHY_RESET(sc);
+ sc->mii_capabilities = PHY_READ(sc, E1000_SR) & ma->mii_capmask;
+ if (sc->mii_capabilities & BMSR_EXTSTAT)
+ sc->mii_extcapabilities = PHY_READ(sc, E1000_ESR);

-#define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL)
- ADD(IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, sc->mii_inst),
- E1000_CR_ISOLATE);
-
- if ((sc->mii_flags & MIIF_HAVEFIBER) == 0) {
- if (fast_ether == 0) {
- ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T, IFM_FDX,
- sc->mii_inst), E1000_CR_SPEED_1000 |
- E1000_CR_FULL_DUPLEX);
- /*
- * 1000BT-simplex not supported; driver must ignore this entry,
- * but it must be present in order to manually set full-duplex.
- */
- ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_T, 0,
- sc->mii_inst), E1000_CR_SPEED_1000);
- }
- ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_FDX, sc->mii_inst),
- E1000_CR_SPEED_100 | E1000_CR_FULL_DUPLEX);
- ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, 0, sc->mii_inst),
- E1000_CR_SPEED_100);
- ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, IFM_FDX, sc->mii_inst),
- E1000_CR_SPEED_10 | E1000_CR_FULL_DUPLEX);
- ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, 0, sc->mii_inst),
- E1000_CR_SPEED_10);
- } else {
- ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_SX, IFM_FDX,sc->mii_inst),
- E1000_CR_SPEED_1000 | E1000_CR_FULL_DUPLEX);
+ mii_phy_add_media(sc);
+
+ /*
+ * Initialize PHY Specific Control Register.
+ */
+
+ reg = PHY_READ(sc, E1000_SCR);
+
+ /* Assert CRS on transmit. */
+ reg |= E1000_SCR_ASSERT_CRS_ON_TX;
+
+ /* Enable auto crossover. */
+ switch (sc->mii_model) {
+ case MII_MODEL_MARVELL_E3082:
+ /* Bits are in a different position. */
+ reg |= (E1000_SCR_AUTO_X_MODE >> 1);
+ break;
+ default:
+ /* Automatic crossover causes problems for 1000baseX. */
+ if (sc->mii_flags & MIIF_IS_1000X)
+ reg &= ~E1000_SCR_AUTO_X_MODE;
+ else
+ reg |= E1000_SCR_AUTO_X_MODE;
+ }
+
+ /* Disable energy detect; only available on some models. */
+ switch(sc->mii_model) {
+ case MII_MODEL_MARVELL_E1011:
+ case MII_MODEL_MARVELL_E1111:
+ case MII_MODEL_MARVELL_E1112:
+ /* Disable energy detect. */
+ reg &= ~E1000_SCR_EN_DETECT_MASK;
+ break;
}

- ADD(IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, 0, sc->mii_inst), 0);
+ PHY_WRITE(sc, E1000_SCR, reg);
+
+ /* 25 MHz TX_CLK should always work. */
+ reg = PHY_READ(sc, E1000_ESCR);
+ reg |= E1000_ESCR_TX_CLK_25;
+ PHY_WRITE(sc, E1000_ESCR, reg);

-#undef ADD
+ /*
+ * Do a software reset for these settings to take effect.
+ * Disable autonegotiation, such that all capabilities get
+ * advertised when it is switched back on.
+ */
+ reg = PHY_READ(sc, E1000_CR);
+ reg &= ~E1000_CR_AUTO_NEG_ENABLE;
+ PHY_WRITE(sc, E1000_CR, reg | E1000_CR_RESET);
}

void
eephy_reset(struct mii_softc *sc)
{
- u_int32_t reg;
- int i;
-
- /* initialize custom E1000 registers to magic values */
- reg = PHY_READ(sc, E1000_SCR);
- reg &= ~E1000_SCR_AUTO_X_MODE;
- PHY_WRITE(sc, E1000_SCR, reg);
+ int reg, i;

- /* normal PHY reset */
- /*mii_phy_reset(sc);*/
reg = PHY_READ(sc, E1000_CR);
reg |= E1000_CR_RESET;
PHY_WRITE(sc, E1000_CR, reg);
-
+
for (i = 0; i < 500; i++) {
DELAY(1);
reg = PHY_READ(sc, E1000_CR);
if (!(reg & E1000_CR_RESET))
break;
}
-
- /* set more custom E1000 registers to magic values */
- reg = PHY_READ(sc, E1000_SCR);
- reg |= E1000_SCR_ASSERT_CRS_ON_TX;
- PHY_WRITE(sc, E1000_SCR, reg);
-
- reg = PHY_READ(sc, E1000_ESCR);
- reg |= E1000_ESCR_TX_CLK_25;
- PHY_WRITE(sc, E1000_ESCR, reg);
-
- /* even more magic to reset DSP? */
- PHY_WRITE(sc, 29, 0x1d);
- PHY_WRITE(sc, 30, 0xc1);
- PHY_WRITE(sc, 30, 0x00);
}

int
eephy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
{
struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
- int reg;
+ int bmcr;

if ((sc->mii_dev.dv_flags & DVF_ACTIVE) == 0)
return (ENXIO);
@@ -265,8 +251,8 @@ eephy_service(struct mii_softc *sc, stru
* isolate ourselves.
*/
if (IFM_INST(ife->ifm_media) != sc->mii_inst) {
- reg = PHY_READ(sc, E1000_CR);
- PHY_WRITE(sc, E1000_CR, reg | E1000_CR_ISOLATE);
+ bmcr = PHY_READ(sc, E1000_CR);
+ PHY_WRITE(sc, E1000_CR, bmcr | E1000_CR_ISOLATE);
return (0);
}

@@ -276,70 +262,16 @@ eephy_service(struct mii_softc *sc, stru
if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
break;

- switch (IFM_SUBTYPE(ife->ifm_media)) {
- case IFM_AUTO:
- PHY_RESET(sc);
- (void) eephy_mii_phy_auto(sc);
- break;
-
- case IFM_1000_SX:
- if (fast_ether == 1)
- return (EINVAL);
-
- PHY_RESET(sc);
-
- PHY_WRITE(sc, E1000_CR,
- E1000_CR_FULL_DUPLEX | E1000_CR_SPEED_1000);
- PHY_WRITE(sc, E1000_AR, E1000_FA_1000X_FD);
- break;
-
- case IFM_1000_T:
- if (fast_ether == 1)
- return (EINVAL);
-
- PHY_RESET(sc);
-
- /* TODO - any other way to force 1000BT? */
- (void) eephy_mii_phy_auto(sc);
- break;
-
- case IFM_100_TX:
- PHY_RESET(sc);
-
- if ((ife->ifm_media & IFM_GMASK) == IFM_FDX) {
- PHY_WRITE(sc, E1000_CR,
- E1000_CR_FULL_DUPLEX | E1000_CR_SPEED_100);
- PHY_WRITE(sc, E1000_AR, E1000_AR_100TX_FD);
- } else {
- PHY_WRITE(sc, E1000_CR, E1000_CR_SPEED_100);
- PHY_WRITE(sc, E1000_AR, E1000_AR_100TX);
- }
- break;
-
- case IFM_10_T:
- PHY_RESET(sc);
-
- if ((ife->ifm_media & IFM_GMASK) == IFM_FDX) {
- PHY_WRITE(sc, E1000_CR,
- E1000_CR_FULL_DUPLEX | E1000_CR_SPEED_10);
- PHY_WRITE(sc, E1000_AR, E1000_AR_10T_FD);
- } else {
- PHY_WRITE(sc, E1000_CR, E1000_CR_SPEED_10);
- PHY_WRITE(sc, E1000_AR, E1000_AR_10T);
- }
-
- break;
-
- case IFM_NONE:
- reg = PHY_READ(sc, E1000_CR);
- PHY_WRITE(sc, E1000_CR,
- reg | E1000_CR_ISOLATE | E1000_CR_POWER_DOWN);
- break;
+ mii_phy_setmedia(sc);

- default:
- return (EINVAL);
+ /*
+ * If autonegitation is not enabled, we need a
+ * software reset for the settings to take effect.
+ */
+ if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO) {
+ bmcr = PHY_READ(sc, E1000_CR);
+ PHY_WRITE(sc, E1000_CR, bmcr | E1000_CR_RESET);
}
-
break;

case MII_TICK:
@@ -349,46 +281,20 @@ eephy_service(struct mii_softc *sc, stru
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)
- return (0);
-
- /*
- * Only used for autonegotiation.
- */
- if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO)
- break;
-
- /*
- * Check to see if we have link. If we do, we don't
- * need to restart the autonegotiation process. Read
- * the BMSR twice in case it's latched.
- */
- reg = PHY_READ(sc, E1000_SR) | PHY_READ(sc, E1000_SR);
- if (reg & E1000_SR_LINK_STATUS)
- break;
-
- /*
- * Only retry autonegotiation every mii_anegticks seconds.
- */
- if (++sc->mii_ticks <= sc->mii_anegticks)
- break;
-
- sc->mii_ticks = 0;
- PHY_RESET(sc);
-
- eephy_mii_phy_auto(sc);
+ if (mii_phy_tick(sc) == EJUSTRETURN)
+ return (0);
break;
+
+ case MII_DOWN:
+ mii_phy_down(sc);
+ return (0);
}

/* Update the media status. */
- eephy_status(sc);
+ mii_phy_status(sc);

/* Callback if something changed. */
mii_phy_update(sc, cmd);
-
return (0);
}

@@ -396,38 +302,36 @@ void
eephy_status(struct mii_softc *sc)
{
struct mii_data *mii = sc->mii_pdata;
- int bmsr, bmcr, gsr, ssr;
+ int bmcr, gsr, ssr;

mii->mii_media_status = IFM_AVALID;
mii->mii_media_active = IFM_ETHER;

- bmsr = PHY_READ(sc, E1000_SR) | PHY_READ(sc, E1000_SR);
bmcr = PHY_READ(sc, E1000_CR);
ssr = PHY_READ(sc, E1000_SSR);

- if (bmsr & E1000_SR_LINK_STATUS)
+ if (ssr & E1000_SSR_LINK)
mii->mii_media_status |= IFM_ACTIVE;

if (bmcr & E1000_CR_LOOPBACK)
mii->mii_media_active |= IFM_LOOP;

- if ((!(bmsr & E1000_SR_AUTO_NEG_COMPLETE) || !(ssr & E1000_SSR_LINK) ||
- !(ssr & E1000_SSR_SPD_DPLX_RESOLVED))) {
+ if (!(ssr & E1000_SSR_SPD_DPLX_RESOLVED)) {
/* Erg, still trying, I guess... */
mii->mii_media_active |= IFM_NONE;
return;
}

- if ((sc->mii_flags & MIIF_HAVEFIBER) == 0) {
+ if (sc->mii_flags & MIIF_IS_1000X) {
+ if (ssr & E1000_SSR_1000MBS)
+ mii->mii_media_active |= IFM_1000_SX;
+ } else {
if (ssr & E1000_SSR_1000MBS)
mii->mii_media_active |= IFM_1000_T;
else if (ssr & E1000_SSR_100MBS)
mii->mii_media_active |= IFM_100_TX;
else
mii->mii_media_active |= IFM_10_T;
- } else {
- if (ssr & E1000_SSR_1000MBS)
- mii->mii_media_active |= IFM_1000_SX;
}

if (ssr & E1000_SSR_DUPLEX)
@@ -440,24 +344,4 @@ eephy_status(struct mii_softc *sc)
if (gsr & E1000_1GSR_MS_CONFIG_RES)
mii->mii_media_active |= IFM_ETH_MASTER;
}
-}
-
-int
-eephy_mii_phy_auto(struct mii_softc *sc)
-{
- if ((sc->mii_flags & MIIF_HAVEFIBER) == 0) {
- PHY_WRITE(sc, E1000_AR,
- E1000_AR_10T | E1000_AR_10T_FD |
- E1000_AR_100TX | E1000_AR_100TX_FD |
- E1000_AR_PAUSE | E1000_AR_ASM_DIR);
- if (fast_ether == 0)
- PHY_WRITE(sc, E1000_1GCR, E1000_1GCR_1000T_FD);
- } else {
- PHY_WRITE(sc, E1000_AR, E1000_FA_1000X_FD |
- E1000_FA_SYM_PAUSE | E1000_FA_ASYM_PAUSE);
- }
- PHY_WRITE(sc, E1000_CR,
- E1000_CR_AUTO_NEG_ENABLE | E1000_CR_RESTART_AUTO_NEG);
-
- return (EJUSTRETURN);
}
Index: mii/mii_physubr.c
================================================== =================
RCS file: /cvs/src/sys/dev/mii/mii_physubr.c,v
retrieving revision 1.30
diff -u -p -r1.30 mii_physubr.c
--- mii/mii_physubr.c 28 Dec 2006 09:24:27 -0000 1.30
+++ mii/mii_physubr.c 29 Dec 2006 21:24:24 -0000
@@ -147,12 +147,22 @@ mii_phy_auto(struct mii_softc *sc, int w
if (sc->mii_extcapabilities & EXTSR_1000XHDX)
anar |= ANAR_X_HD;

+ if (sc->mii_flags & MIIF_DOPAUSE &&
+ sc->mii_extcapabilities & EXTSR_1000XFDX)
+ anar |= ANAR_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) {
+ if (sc->mii_capabilities & BMSR_100TXFDX)
+ anar |= ANAR_FC;
+ if (sc->mii_extcapabilities & EXTSR_1000TFDX)
+ anar |= ANAR_X_PAUSE_TOWARDS;
+ }
PHY_WRITE(sc, MII_ANAR, anar);
if (sc->mii_flags & MIIF_HAVE_GTCR) {
uint16_t gtcr = 0;
Index: pci/if_msk.c
================================================== =================
RCS file: /cvs/src/sys/dev/pci/if_msk.c,v
retrieving revision 1.36
diff -u -p -r1.36 if_msk.c
--- pci/if_msk.c 28 Dec 2006 16:34:42 -0000 1.36
+++ pci/if_msk.c 29 Dec 2006 21:24:25 -0000
@@ -1097,7 +1097,7 @@ msk_attach(struct device *parent, struct
ifmedia_init(&sc_if->sk_mii.mii_media, 0,
msk_ifmedia_upd, msk_ifmedia_sts);
mii_attach(self, &sc_if->sk_mii, 0xffffffff, MII_PHY_ANY,
- MII_OFFSET_ANY, MIIF_DOPAUSE);
+ MII_OFFSET_ANY, MIIF_DOPAUSE|MIIF_FORCEANEG);
if (LIST_FIRST(&sc_if->sk_mii.mii_phys) == NULL) {
printf("%s: no PHY found!\n", sc_if->sk_dev.dv_xname);
ifmedia_add(&sc_if->sk_mii.mii_media, IFM_ETHER|IFM_MANUAL,

Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
Reply


Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On
Forum Jump


All times are GMT. The time now is 12:27 AM.


Powered by vBulletin® Version 3.6.5
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
SEO by vBSEO 3.2.0
www.UnixAdminTalk.com