summaryrefslogtreecommitdiffstats
path: root/sys/dev/mii/nsgphy.c
diff options
context:
space:
mode:
authorphk <phk@FreeBSD.org>2002-04-29 11:57:30 +0000
committerphk <phk@FreeBSD.org>2002-04-29 11:57:30 +0000
commit2715240fe7a7238d5caa38cf8f6fb16ee0755a5c (patch)
treeab00a27fad6535ee94d5573484470b55ed8fe2c5 /sys/dev/mii/nsgphy.c
parent6685a257879878dde6afb0ae79cc136a587b275b (diff)
downloadFreeBSD-src-2715240fe7a7238d5caa38cf8f6fb16ee0755a5c.zip
FreeBSD-src-2715240fe7a7238d5caa38cf8f6fb16ee0755a5c.tar.gz
Move a lot closer to NetBSDs MII support for GigE.
Move fxp and nge drivers over to use the new stuff.
Diffstat (limited to 'sys/dev/mii/nsgphy.c')
-rw-r--r--sys/dev/mii/nsgphy.c255
1 files changed, 40 insertions, 215 deletions
diff --git a/sys/dev/mii/nsgphy.c b/sys/dev/mii/nsgphy.c
index adae9fb..0ee59ea 100644
--- a/sys/dev/mii/nsgphy.c
+++ b/sys/dev/mii/nsgphy.c
@@ -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)
- 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
- 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;
-}
+ 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;
+ break;
-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);
- }
+ case 0:
+ mii->mii_media_active |= IFM_10_T;
+ break;
- 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
+ default:
+ mii->mii_media_active |= IFM_NONE;
+ 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;
}
OpenPOWER on IntegriCloud