summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Wright <jason@cvs.openbsd.org>1998-11-11 19:34:52 +0000
committerJason Wright <jason@cvs.openbsd.org>1998-11-11 19:34:52 +0000
commitb67320a002793e8f496722a85d888421724eb4dc (patch)
tree4c109936ccfb901a84c59a7f464a83c8a9a31a41
parentb4d28fc47cc2f346e2f660be351cb60a89bd26ee (diff)
Merge with NetBSD:
o additional phy drivers (seeq, ics, level1) o "unknown phy" driver for unsupported phys o collected common code into mii_physubr o exphy isn't the only phy that doesn't have valid id registers
-rw-r--r--sys/dev/mii/exphy.c199
-rw-r--r--sys/dev/mii/files.mii36
-rw-r--r--sys/dev/mii/icsphy.c319
-rw-r--r--sys/dev/mii/icsphyreg.h92
-rw-r--r--sys/dev/mii/inphy.c189
-rw-r--r--sys/dev/mii/lxtphy.c323
-rw-r--r--sys/dev/mii/lxtphyreg.h89
-rw-r--r--sys/dev/mii/mii.c25
-rw-r--r--sys/dev/mii/mii_physubr.c102
-rw-r--r--sys/dev/mii/miivar.h29
-rw-r--r--sys/dev/mii/nsphy.c192
-rw-r--r--sys/dev/mii/qsphy.c200
-rw-r--r--sys/dev/mii/sqphy.c319
-rw-r--r--sys/dev/mii/sqphyreg.h128
-rw-r--r--sys/dev/mii/tlphy.c133
-rw-r--r--sys/dev/mii/ukphy.c274
-rw-r--r--sys/dev/mii/ukphy_subr.c113
17 files changed, 2128 insertions, 634 deletions
diff --git a/sys/dev/mii/exphy.c b/sys/dev/mii/exphy.c
index 7c062f925ff..8a16211e1ec 100644
--- a/sys/dev/mii/exphy.c
+++ b/sys/dev/mii/exphy.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: exphy.c,v 1.1 1998/09/10 17:17:33 jason Exp $ */
-/* $NetBSD: exphy.c,v 1.5 1998/08/28 12:50:36 fvdl Exp $ */
+/* $OpenBSD: exphy.c,v 1.2 1998/11/11 19:34:44 jason Exp $ */
+/* $NetBSD: exphy.c,v 1.15 1998/11/05 00:19:32 thorpej Exp $ */
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -85,12 +85,6 @@
#include <dev/mii/miivar.h>
#include <dev/mii/miidevs.h>
-struct exphy_softc {
- struct mii_softc sc_mii; /* generic PHY */
- int sc_capabilities;
- int sc_active;
-};
-
#ifdef __NetBSD__
int exphymatch __P((struct device *, struct cfdata *, void *));
#else
@@ -99,7 +93,7 @@ int exphymatch __P((struct device *, void *, void *));
void exphyattach __P((struct device *, struct device *, void *));
struct cfattach exphy_ca = {
- sizeof(struct exphy_softc), exphymatch, exphyattach
+ sizeof(struct mii_softc), exphymatch, exphyattach
};
#ifdef __OpenBSD__
@@ -108,18 +102,8 @@ struct cfdriver exphy_cd = {
};
#endif
-#define EXPHY_READ(sc, reg) \
- (*(sc)->sc_mii.mii_pdata->mii_readreg)((sc)->sc_mii.mii_dev.dv_parent, \
- (sc)->sc_mii.mii_phy, (reg))
-
-#define EXPHY_WRITE(sc, reg, val) \
- (*(sc)->sc_mii.mii_pdata->mii_writereg)((sc)->sc_mii.mii_dev.dv_parent, \
- (sc)->sc_mii.mii_phy, (reg), (val))
-
int exphy_service __P((struct mii_softc *, struct mii_data *, int));
-void exphy_reset __P((struct exphy_softc *));
-void exphy_auto __P((struct exphy_softc *));
-void exphy_status __P((struct exphy_softc *));
+void exphy_reset __P((struct mii_softc *));
int
exphymatch(parent, match, aux)
@@ -136,11 +120,17 @@ exphymatch(parent, match, aux)
/*
* Argh, 3Com PHY reports oui == 0 model == 0!
*/
- if (MII_OUI(ma->mii_id1, ma->mii_id2) == 0 &&
- MII_MODEL(ma->mii_id2) == 0)
- return (1);
+ if (MII_OUI(ma->mii_id1, ma->mii_id2) != 0 &&
+ MII_MODEL(ma->mii_id2) != 0)
+ return (0);
- return (0);
+ /*
+ * Make sure the parent is an `ex'.
+ */
+ if (strcmp(parent->dv_cfdata->cf_driver->cd_name, "ex") != 0)
+ return (0);
+
+ return (10);
}
void
@@ -148,17 +138,16 @@ exphyattach(parent, self, aux)
struct device *parent, *self;
void *aux;
{
- struct exphy_softc *sc = (struct exphy_softc *)self;
+ struct mii_softc *sc = (struct mii_softc *)self;
struct mii_attach_args *ma = aux;
struct mii_data *mii = ma->mii_data;
- printf(": 3Com internal media interface, rev. %d\n",
- MII_REV(ma->mii_id2));
+ printf(": 3Com internal media interface\n");
- sc->sc_mii.mii_inst = mii->mii_instance;
- sc->sc_mii.mii_phy = ma->mii_phyno;
- sc->sc_mii.mii_service = exphy_service;
- sc->sc_mii.mii_pdata = mii;
+ sc->mii_inst = mii->mii_instance;
+ sc->mii_phy = ma->mii_phyno;
+ sc->mii_service = exphy_service;
+ sc->mii_pdata = mii;
/*
* The 3Com PHY can never be isolated, so never allow non-zero
@@ -166,45 +155,49 @@ exphyattach(parent, self, aux)
*/
if (mii->mii_instance != 0) {
printf("%s: ignoring this PHY, non-zero instance\n",
- sc->sc_mii.mii_dev.dv_xname);
+ sc->mii_dev.dv_xname);
return;
}
+ sc->mii_flags |= MIIF_NOISOLATE;
#define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL)
- ADD(IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, sc->sc_mii.mii_inst),
+#if 0 /* See above. */
+ ADD(IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, sc->mii_inst),
BMCR_ISO);
+#endif
- ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_LOOP, sc->sc_mii.mii_inst),
+ ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_LOOP, sc->mii_inst),
BMCR_LOOP|BMCR_S100);
exphy_reset(sc);
- sc->sc_capabilities = EXPHY_READ(sc, MII_BMSR) & ma->mii_capmask;
- printf("%s: ", sc->sc_mii.mii_dev.dv_xname);
- if ((sc->sc_capabilities & BMSR_MEDIAMASK) == 0)
+ sc->mii_capabilities =
+ PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
+ printf("%s: ", sc->mii_dev.dv_xname);
+ if ((sc->mii_capabilities & BMSR_MEDIAMASK) == 0)
printf("no media present");
else
- mii_add_media(mii, sc->sc_capabilities, sc->sc_mii.mii_inst);
+ mii_add_media(mii, sc->mii_capabilities,
+ sc->mii_inst);
printf("\n");
#undef ADD
}
int
-exphy_service(self, mii, cmd)
- struct mii_softc *self;
+exphy_service(sc, mii, cmd)
+ struct mii_softc *sc;
struct mii_data *mii;
int cmd;
{
- struct exphy_softc *sc = (struct exphy_softc *)self;
+ struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
/*
* We can't isolate the 3Com PHY, so it has to be the only one!
*/
- if (IFM_INST(mii->mii_media.ifm_media) != sc->sc_mii.mii_inst)
+ if (IFM_INST(ife->ifm_media) != sc->mii_inst)
panic("exphy_service: can't isolate 3Com PHY");
-
switch (cmd) {
case MII_POLLSTAT:
break;
@@ -216,14 +209,14 @@ exphy_service(self, mii, cmd)
if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
break;
- switch (IFM_SUBTYPE(mii->mii_media.ifm_media)) {
+ switch (IFM_SUBTYPE(ife->ifm_media)) {
case IFM_AUTO:
/*
* If we're already in auto mode, just return.
*/
- if (EXPHY_READ(sc, MII_BMCR) & BMCR_AUTOEN)
+ if (PHY_READ(sc, MII_BMCR) & BMCR_AUTOEN)
return (0);
- exphy_auto(sc);
+ (void) mii_phy_auto(sc);
break;
case IFM_100_T4:
/*
@@ -234,10 +227,9 @@ exphy_service(self, mii, cmd)
/*
* BMCR data is stored in the ifmedia entry.
*/
- EXPHY_WRITE(sc, MII_ANAR,
- mii_anar(mii->mii_media.ifm_media));
- EXPHY_WRITE(sc, MII_BMCR,
- mii->mii_media.ifm_cur->ifm_data);
+ PHY_WRITE(sc, MII_ANAR,
+ mii_anar(ife->ifm_media));
+ PHY_WRITE(sc, MII_BMCR, ife->ifm_data);
}
break;
@@ -245,7 +237,7 @@ exphy_service(self, mii, cmd)
/*
* Only used for autonegotiation.
*/
- if (IFM_SUBTYPE(mii->mii_media.ifm_media) != IFM_AUTO)
+ if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO)
return (0);
/*
@@ -262,117 +254,26 @@ exphy_service(self, mii, cmd)
}
/* Update the media status. */
- exphy_status(sc);
+ ukphy_status(sc);
/* Callback if something changed. */
- if (sc->sc_active != mii->mii_media_active || cmd == MII_MEDIACHG) {
- (*mii->mii_statchg)(sc->sc_mii.mii_dev.dv_parent);
- sc->sc_active = mii->mii_media_active;
+ if (sc->mii_active != mii->mii_media_active || cmd == MII_MEDIACHG) {
+ (*mii->mii_statchg)(sc->mii_dev.dv_parent);
+ sc->mii_active = mii->mii_media_active;
}
return (0);
}
void
-exphy_status(sc)
- struct exphy_softc *sc;
-{
- struct mii_data *mii = sc->sc_mii.mii_pdata;
- int bmsr, bmcr, anlpar;
-
- mii->mii_media_status = IFM_AVALID;
- mii->mii_media_active = IFM_ETHER;
-
- bmsr = EXPHY_READ(sc, MII_BMSR) | EXPHY_READ(sc, MII_BMSR);
- if (bmsr & BMSR_LINK)
- mii->mii_media_status |= IFM_ACTIVE;
-
- bmcr = EXPHY_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;
-
- if (bmcr & BMCR_AUTOEN) {
- /*
- * The 3Com PHY uses the highest-order common bit of
- * the ANAR and ANLPAR (i.e. best media advertised
- * both by us and our link partner).
- */
- if ((bmsr & BMSR_ACOMP) == 0) {
- /* Erg, still trying, I guess... */
- mii->mii_media_active |= IFM_NONE;
- return;
- }
-
- anlpar = EXPHY_READ(sc, MII_ANAR) & EXPHY_READ(sc, MII_ANLPAR);
- 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;
- else
- mii->mii_media_active |= IFM_NONE;
- } else {
- if (bmcr & BMCR_S100)
- mii->mii_media_active |= IFM_100_TX;
- else
- mii->mii_media_active |= IFM_10_T;
- if (bmcr & BMCR_FDX)
- mii->mii_media_active |= IFM_FDX;
- }
-}
-
-void
-exphy_auto(sc)
- struct exphy_softc *sc;
-{
- int bmsr, i;
-
- EXPHY_WRITE(sc, MII_ANAR,
- BMSR_MEDIA_TO_ANAR(sc->sc_capabilities) | ANAR_CSMA);
- EXPHY_WRITE(sc, MII_BMCR, BMCR_AUTOEN | BMCR_STARTNEG);
-
- /* Wait 500ms for it to complete. */
- for (i = 0; i < 500; i++) {
- if ((bmsr = EXPHY_READ(sc, MII_BMSR)) & BMSR_ACOMP)
- return;
- delay(1000);
- }
-#if 0
- if ((bmsr & BMSR_ACOMP) == 0)
- printf("%s: autonegotiation failed to complete\n",
- sc->sc_mii.mii_dev.dv_xname);
-#endif
-}
-
-void
exphy_reset(sc)
- struct exphy_softc *sc;
+ struct mii_softc *sc;
{
- int reg, i;
-
- EXPHY_WRITE(sc, MII_BMCR, BMCR_RESET);
- /* Wait 100ms for it to complete. */
- for (i = 0; i < 100; i++) {
- reg = EXPHY_READ(sc, MII_BMCR);
- if ((reg & BMCR_RESET) == 0)
- break;
- delay(1000);
- }
+ mii_phy_reset(sc);
/*
* XXX 3Com PHY doesn't set the BMCR properly after
* XXX reset, which breaks autonegotiation.
*/
- EXPHY_WRITE(sc, MII_BMCR, BMCR_S100|BMCR_AUTOEN|BMCR_FDX);
+ PHY_WRITE(sc, MII_BMCR, BMCR_S100|BMCR_AUTOEN|BMCR_FDX);
}
diff --git a/sys/dev/mii/files.mii b/sys/dev/mii/files.mii
index c8d7e79b420..d7929a20a23 100644
--- a/sys/dev/mii/files.mii
+++ b/sys/dev/mii/files.mii
@@ -1,24 +1,46 @@
-# $OpenBSD: files.mii,v 1.1 1998/09/10 17:17:33 jason Exp $
-# $NetBSD: files.mii,v 1.7 1998/08/12 08:46:20 thorpej Exp $
+# $OpenBSD: files.mii,v 1.2 1998/11/11 19:34:45 jason Exp $
+# $NetBSD: files.mii,v 1.13 1998/11/05 00:36:48 thorpej Exp $
file dev/mii/mii.c mii
-device tlphy
+define mii_phy
+file dev/mii/mii_physubr.c mii_phy
+
+define ukphy_subr
+file dev/mii/ukphy_subr.c ukphy_subr
+
+device tlphy: mii_phy
attach tlphy at mii
file dev/mii/tlphy.c tlphy
-device nsphy
+device nsphy: mii_phy
attach nsphy at mii
file dev/mii/nsphy.c nsphy
-device qsphy
+device qsphy: mii_phy
attach qsphy at mii
file dev/mii/qsphy.c qsphy
-device inphy
+device inphy: mii_phy
attach inphy at mii
file dev/mii/inphy.c inphy
-device exphy
+device exphy: mii_phy, ukphy_subr
attach exphy at mii
file dev/mii/exphy.c exphy
+
+device lxtphy: mii_phy
+attach lxtphy at mii
+file dev/mii/lxtphy.c lxtphy
+
+device icsphy: mii_phy
+attach icsphy at mii
+file dev/mii/icsphy.c icsphy
+
+device sqphy: mii_phy
+attach sqphy at mii
+file dev/mii/sqphy.c sqphy
+
+device ukphy: mii_phy, ukphy_subr
+attach ukphy at mii
+file dev/mii/ukphy.c ukphy
diff --git a/sys/dev/mii/icsphy.c b/sys/dev/mii/icsphy.c
new file mode 100644
index 00000000000..8e26627278c
--- /dev/null
+++ b/sys/dev/mii/icsphy.c
@@ -0,0 +1,319 @@
+/* $OpenBSD: icsphy.c,v 1.1 1998/11/11 19:34:45 jason Exp $ */
+/* $NetBSD: icsphy.c,v 1.8 1998/11/05 04:08:01 thorpej Exp $ */
+
+/*-
+ * Copyright (c) 1998 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
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 1997 Manuel Bouyer. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Manuel Bouyer.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * driver for Integrated Circuit Systems' ICS1890 ethernet 10/100 PHY
+ * datasheet from www.icst.com
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/device.h>
+#include <sys/malloc.h>
+#include <sys/socket.h>
+
+#include <net/if.h>
+#include <net/if_media.h>
+
+#include <dev/mii/mii.h>
+#include <dev/mii/miivar.h>
+#include <dev/mii/miidevs.h>
+
+#include <dev/mii/icsphyreg.h>
+
+#ifdef __NetBSD__
+int icsphymatch __P((struct device *, struct cfdata *, void *));
+#else
+int icsphymatch __P((struct device *, void *, void *));
+#endif
+void icsphyattach __P((struct device *, struct device *, void *));
+
+struct cfattach icsphy_ca = {
+ sizeof(struct mii_softc), icsphymatch, icsphyattach
+};
+
+#ifdef __OpenBSD__
+struct cfdriver icsphy_cd = {
+ NULL, "icsphy", DV_DULL
+};
+#endif
+
+int icsphy_service __P((struct mii_softc *, struct mii_data *, int));
+void icsphy_reset __P((struct mii_softc *));
+void icsphy_status __P((struct mii_softc *));
+
+int
+icsphymatch(parent, match, aux)
+ struct device *parent;
+#ifdef __NetBSD__
+ struct cfdata *match;
+#else
+ void *match;
+#endif
+ void *aux;
+{
+ struct mii_attach_args *ma = aux;
+
+ if (MII_OUI(ma->mii_id1, ma->mii_id2) == MII_OUI_ICS &&
+ MII_MODEL(ma->mii_id2) == MII_MODEL_ICS_1890)
+ return (10);
+
+ return (0);
+}
+
+void
+icsphyattach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct mii_softc *sc = (struct mii_softc *)self;
+ struct mii_attach_args *ma = aux;
+ struct mii_data *mii = ma->mii_data;
+
+ printf(": %s, rev. %d\n", MII_STR_ICS_1890,
+ MII_REV(ma->mii_id2));
+
+ sc->mii_inst = mii->mii_instance;
+ sc->mii_phy = ma->mii_phyno;
+ sc->mii_service = icsphy_service;
+ sc->mii_pdata = mii;
+
+#define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL)
+
+ ADD(IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, sc->mii_inst),
+ BMCR_ISO);
+ ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_LOOP, sc->mii_inst),
+ BMCR_LOOP|BMCR_S100);
+
+ icsphy_reset(sc);
+
+ sc->mii_capabilities =
+ PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
+ printf("%s: ", sc->mii_dev.dv_xname);
+ if ((sc->mii_capabilities & BMSR_MEDIAMASK) == 0)
+ printf("no media present");
+ else
+ mii_add_media(mii, sc->mii_capabilities,
+ sc->mii_inst);
+ printf("\n");
+#undef ADD
+}
+
+int
+icsphy_service(sc, mii, cmd)
+ struct mii_softc *sc;
+ struct mii_data *mii;
+ int cmd;
+{
+ struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
+ int reg;
+
+ switch (cmd) {
+ case MII_POLLSTAT:
+ /*
+ * If we're not polling our PHY instance, just return.
+ */
+ if (IFM_INST(ife->ifm_media) != sc->mii_inst)
+ return (0);
+ break;
+
+ case MII_MEDIACHG:
+ /*
+ * If the media indicates a different PHY instance,
+ * isolate ourselves.
+ */
+ if (IFM_INST(ife->ifm_media) != sc->mii_inst) {
+ reg = PHY_READ(sc, MII_BMCR);
+ PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO);
+ return (0);
+ }
+
+ /*
+ * If the interface is not up, don't do anything.
+ */
+ 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);
+ 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);
+ }
+ break;
+
+ case MII_TICK:
+ /*
+ * If we're not currently selected, just return.
+ */
+ if (IFM_INST(ife->ifm_media) != sc->mii_inst)
+ return (0);
+
+ /*
+ * Only used for autonegotiation.
+ */
+ if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO)
+ return (0);
+
+ /*
+ * Is the interface even up?
+ */
+ if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
+ return (0);
+
+ /*
+ * The ICS1890's autonegotiation doesn't need to be
+ * kicked; it continues in the background.
+ */
+ break;
+ }
+
+ /* Update the media status. */
+ icsphy_status(sc);
+
+ /* Callback if something changed. */
+ if (sc->mii_active != mii->mii_media_active || cmd == MII_MEDIACHG) {
+ (*mii->mii_statchg)(sc->mii_dev.dv_parent);
+ sc->mii_active = mii->mii_media_active;
+ }
+ return (0);
+}
+
+void
+icsphy_status(sc)
+ struct mii_softc *sc;
+{
+ struct mii_data *mii = sc->mii_pdata;
+ int bmcr, qpr;
+
+ mii->mii_media_status = IFM_AVALID;
+ mii->mii_media_active = IFM_ETHER;
+
+ /*
+ * Don't get link from the BMSR. It's available in the QPR,
+ * and we have to read it twice to unlatch it anyhow. This
+ * gives us fewer register reads.
+ */
+ qpr = PHY_READ(sc, MII_ICSPHY_QPR); /* unlatch */
+ qpr = PHY_READ(sc, MII_ICSPHY_QPR); /* real value */
+
+ if (qpr & QPR_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;
+
+ if (bmcr & BMCR_AUTOEN) {
+ if ((qpr & QPR_ACOMP) == 0) {
+ /* Erg, still trying, I guess... */
+ mii->mii_media_active |= IFM_NONE;
+ return;
+ }
+ if (qpr & QPR_SPEED)
+ mii->mii_media_active |= IFM_100_TX;
+ else
+ mii->mii_media_active |= IFM_10_T;
+ if (qpr & QPR_FDX)
+ mii->mii_media_active |= IFM_FDX;
+ } else
+ mii->mii_media_active = mii_media_from_bmcr(bmcr);
+}
+
+void
+icsphy_reset(sc)
+ struct mii_softc *sc;
+{
+
+ mii_phy_reset(sc);
+ PHY_WRITE(sc, MII_ICSPHY_ECR2, ECR2_10TPROT|ECR2_Q10T);
+}
diff --git a/sys/dev/mii/icsphyreg.h b/sys/dev/mii/icsphyreg.h
new file mode 100644
index 00000000000..efa8544ec8e
--- /dev/null
+++ b/sys/dev/mii/icsphyreg.h
@@ -0,0 +1,92 @@
+/* $OpenBSD: icsphyreg.h,v 1.1 1998/11/11 19:34:46 jason Exp $ */
+/* $NetBSD: icsphyreg.h,v 1.1 1998/11/02 23:46:20 thorpej Exp $ */
+
+/*-
+ * Copyright (c) 1998 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
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _DEV_MII_ICSPHYREG_H_
+#define _DEV_MII_ICSPHYREG_H_
+
+/*
+ * ICS1890 registers.
+ */
+
+#define MII_ICSPHY_ECR 0x10 /* Extended Control Register */
+#define ECR_OVR 0x8000 /* disable command reg overwrites */
+#define ECR_PHYADDR_MASK 0x07c0 /* PHY address mask */
+#define ECR_CTEST 0x0020 /* Stream Cipher Test Mode */
+#define ECR_IECT 0x0004 /* Invalid Error Code Test */
+#define ECR_SSD 0x0001 /* Stream Cipher Disable */
+
+#define MII_ICSPHY_QPR 0x11 /* Quick Poll Register */
+#define QPR_SPEED 0x8000 /* 100Mbps */
+#define QPR_FDX 0x4000 /* Full dupled */
+#define QPR_ANB2 0x2000 /* Autoneg monitor bit 2 */
+#define QPR_ANB1 0x1000 /* Autoneg monitor bit 1 */
+#define QPR_ANB0 0x0800 /* Autoneg monitor bit 0 */
+#define QPR_RXERR 0x0400 /* Receive signal lost */
+#define QPR_PLLERR 0x0200 /* PLL error */
+#define QPR_FCARR 0x0100 /* False carrier detected */
+#define QPR_INVALSYM 0x0080 /* Invalid Symbol Detected */
+#define QPR_HALT 0x0040 /* Halt Symbol Detected */
+#define QPR_PREEM 0x0020 /* Two Idle Symbols together */
+#define QPR_ACOMP 0x0010 /* Autonegotiation complete */
+#define QPR_JABBER 0x0004 /* Jabber detected */
+#define QPR_RFAULT 0x0002 /* Remote Fault */
+#define QPR_LINK 0x0001 /* Link */
+
+#define MII_ICSPHY_TTR 0x12 /* 10baseT Operations Register */
+#define TTR_RJABBER 0x8000 /* Remote Jabber */
+#define TTR_POLARITY 0x4000 /* Polarity Reversed */
+#define TTR_NOJABBER 0x0020 /* Disable Jabber Check */
+#define TTR_LOOP 0x0010 /* Loopback mode */
+#define TTR_NOAPOLARITY 0x0008 /* Disable auto polarity correction */
+#define TTR_NOSQE 0x0004 /* Disable SQE check */
+#define TTR_NOLINK 0x0002 /* Disable Link check */
+#define TTR_NOSQUELCH 0x0001 /* Disable squelch */
+
+#define MII_ICSPHY_ECR2 0x13 /* Extended Control Register 2 */
+#define ECR2_REPEATER 0x8000 /* Repeater Mode */
+#define ECR2_HWSW 0x4000 /* hw/sw config priority */
+#define ECR2_LPRF 0x2000 /* link partner supports rem fault */
+#define ECR2_FORCERF 0x0400 /* Force transmit of rem fault */
+#define ECR2_RFPUP 0x0010 /* Rem fault on power up */
+#define ECR2_Q10T 0x0004 /* Qualified 10baseT data */
+#define ECR2_10TPROT 0x0002 /* 10baseT protect */
+#define ECR2_AUTOPWRDN 0x0001 /* automatic power down */
+
+#endif /* _DEV_MII_ICSPHYREG_H_ */
diff --git a/sys/dev/mii/inphy.c b/sys/dev/mii/inphy.c
index 70cedb54345..6f43b03fb1a 100644
--- a/sys/dev/mii/inphy.c
+++ b/sys/dev/mii/inphy.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: inphy.c,v 1.1 1998/09/10 17:17:33 jason Exp $ */
-/* $NetBSD: inphy.c,v 1.3 1998/08/12 20:56:35 thorpej Exp $ */
+/* $OpenBSD: inphy.c,v 1.2 1998/11/11 19:34:46 jason Exp $ */
+/* $NetBSD: inphy.c,v 1.10 1998/11/05 04:08:02 thorpej Exp $ */
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -88,13 +88,6 @@
#include <dev/mii/inphyreg.h>
-struct inphy_softc {
- struct mii_softc sc_mii; /* generic PHY */
- int sc_capabilities;
- int sc_ticks;
- int sc_active;
-};
-
#ifdef __NetBSD__
int inphymatch __P((struct device *, struct cfdata *, void *));
#else
@@ -103,7 +96,7 @@ int inphymatch __P((struct device *, void *, void *));
void inphyattach __P((struct device *, struct device *, void *));
struct cfattach inphy_ca = {
- sizeof(struct inphy_softc), inphymatch, inphyattach
+ sizeof(struct mii_softc), inphymatch, inphyattach
};
#ifdef __OpenBSD__
@@ -112,18 +105,8 @@ struct cfdriver inphy_cd = {
};
#endif
-#define INPHY_READ(sc, reg) \
- (*(sc)->sc_mii.mii_pdata->mii_readreg)((sc)->sc_mii.mii_dev.dv_parent, \
- (sc)->sc_mii.mii_phy, (reg))
-
-#define INPHY_WRITE(sc, reg, val) \
- (*(sc)->sc_mii.mii_pdata->mii_writereg)((sc)->sc_mii.mii_dev.dv_parent, \
- (sc)->sc_mii.mii_phy, (reg), (val))
-
int inphy_service __P((struct mii_softc *, struct mii_data *, int));
-void inphy_reset __P((struct inphy_softc *));
-void inphy_auto __P((struct inphy_softc *));
-void inphy_status __P((struct inphy_softc *));
+void inphy_status __P((struct mii_softc *));
int
inphymatch(parent, match, aux)
@@ -139,7 +122,7 @@ inphymatch(parent, match, aux)
if (MII_OUI(ma->mii_id1, ma->mii_id2) == MII_OUI_INTEL &&
MII_MODEL(ma->mii_id2) == MII_MODEL_INTEL_I82555)
- return (1);
+ return (10);
return (0);
}
@@ -149,47 +132,55 @@ inphyattach(parent, self, aux)
struct device *parent, *self;
void *aux;
{
- struct inphy_softc *sc = (struct inphy_softc *)self;
+ struct mii_softc *sc = (struct mii_softc *)self;
struct mii_attach_args *ma = aux;
struct mii_data *mii = ma->mii_data;
printf(": %s, rev. %d\n", MII_STR_INTEL_I82555,
MII_REV(ma->mii_id2));
- sc->sc_mii.mii_inst = mii->mii_instance;
- sc->sc_mii.mii_phy = ma->mii_phyno;
- sc->sc_mii.mii_service = inphy_service;
- sc->sc_mii.mii_pdata = mii;
+ sc->mii_inst = mii->mii_instance;
+ sc->mii_phy = ma->mii_phyno;
+ sc->mii_service = inphy_service;
+ sc->mii_pdata = mii;
+
+ /*
+ * i82557 wedges if all of its PHYs are isolated!
+ */
+ if (strcmp(parent->dv_cfdata->cf_driver->cd_name, "fxp") == 0 &&
+ mii->mii_instance == 0)
+ sc->mii_flags |= MIIF_NOISOLATE;
#define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL)
-#if 0
- /* Can't do this on the i82557! */
- ADD(IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, sc->sc_mii.mii_inst),
- BMCR_ISO);
-#endif
- ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_LOOP, sc->sc_mii.mii_inst),
+ if ((sc->mii_flags & MIIF_NOISOLATE) == 0)
+ ADD(IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, sc->mii_inst),
+ BMCR_ISO);
+
+ ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_LOOP, sc->mii_inst),
BMCR_LOOP|BMCR_S100);
- inphy_reset(sc);
+ mii_phy_reset(sc);
- sc->sc_capabilities = INPHY_READ(sc, MII_BMSR) & ma->mii_capmask;
- printf("%s: ", sc->sc_mii.mii_dev.dv_xname);
- if ((sc->sc_capabilities & BMSR_MEDIAMASK) == 0)
+ sc->mii_capabilities =
+ PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
+ printf("%s: ", sc->mii_dev.dv_xname);
+ if ((sc->mii_capabilities & BMSR_MEDIAMASK) == 0)
printf("no media present");
else
- mii_add_media(mii, sc->sc_capabilities, sc->sc_mii.mii_inst);
+ mii_add_media(mii, sc->mii_capabilities,
+ sc->mii_inst);
printf("\n");
#undef ADD
}
int
-inphy_service(self, mii, cmd)
- struct mii_softc *self;
+inphy_service(sc, mii, cmd)
+ struct mii_softc *sc;
struct mii_data *mii;
int cmd;
{
- struct inphy_softc *sc = (struct inphy_softc *)self;
+ struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
int reg;
switch (cmd) {
@@ -197,8 +188,7 @@ inphy_service(self, mii, cmd)
/*
* If we're not polling our PHY instance, just return.
*/
- if (IFM_INST(mii->mii_media.ifm_media) !=
- sc->sc_mii.mii_inst)
+ if (IFM_INST(ife->ifm_media) != sc->mii_inst)
return (0);
break;
@@ -207,10 +197,9 @@ inphy_service(self, mii, cmd)
* If the media indicates a different PHY instance,
* isolate ourselves.
*/
- if (IFM_INST(mii->mii_media.ifm_media) !=
- sc->sc_mii.mii_inst) {
- reg = INPHY_READ(sc, MII_BMCR);
- INPHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO);
+ if (IFM_INST(ife->ifm_media) != sc->mii_inst) {
+ reg = PHY_READ(sc, MII_BMCR);
+ PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO);
return (0);
}
@@ -220,14 +209,14 @@ inphy_service(self, mii, cmd)
if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
break;
- switch (IFM_SUBTYPE(mii->mii_media.ifm_media)) {
+ switch (IFM_SUBTYPE(ife->ifm_media)) {
case IFM_AUTO:
/*
* If we're already in auto mode, just return.
*/
- if (INPHY_READ(sc, MII_BMCR) & BMCR_AUTOEN)
+ if (PHY_READ(sc, MII_BMCR) & BMCR_AUTOEN)
return (0);
- inphy_auto(sc);
+ (void) mii_phy_auto(sc);
break;
case IFM_100_T4:
/*
@@ -238,10 +227,9 @@ inphy_service(self, mii, cmd)
/*
* BMCR data is stored in the ifmedia entry.
*/
- INPHY_WRITE(sc, MII_ANAR,
- mii_anar(mii->mii_media.ifm_media));
- INPHY_WRITE(sc, MII_BMCR,
- mii->mii_media.ifm_cur->ifm_data);
+ PHY_WRITE(sc, MII_ANAR,
+ mii_anar(ife->ifm_media));
+ PHY_WRITE(sc, MII_BMCR, ife->ifm_data);
}
break;
@@ -249,14 +237,13 @@ inphy_service(self, mii, cmd)
/*
* If we're not currently selected, just return.
*/
- if (IFM_INST(mii->mii_media.ifm_media) !=
- sc->sc_mii.mii_inst)
+ if (IFM_INST(ife->ifm_media) != sc->mii_inst)
return (0);
/*
* Only used for autonegotiation.
*/
- if (IFM_SUBTYPE(mii->mii_media.ifm_media) != IFM_AUTO)
+ if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO)
return (0);
/*
@@ -270,19 +257,20 @@ inphy_service(self, mii, cmd)
* need to restart the autonegotiation process. Read
* the BMSR twice in case it's latched.
*/
- reg = INPHY_READ(sc, MII_BMSR) | INPHY_READ(sc, MII_BMSR);
+ reg = PHY_READ(sc, MII_BMSR) |
+ PHY_READ(sc, MII_BMSR);
if (reg & BMSR_LINK)
return (0);
/*
* Only retry autonegotiation every 5 seconds.
*/
- if (++sc->sc_ticks != 5)
+ if (++sc->mii_ticks != 5)
return (0);
- sc->sc_ticks = 0;
- inphy_reset(sc);
- inphy_auto(sc);
+ sc->mii_ticks = 0;
+ mii_phy_reset(sc);
+ (void) mii_phy_auto(sc);
break;
}
@@ -290,28 +278,29 @@ inphy_service(self, mii, cmd)
inphy_status(sc);
/* Callback if something changed. */
- if (sc->sc_active != mii->mii_media_active || cmd == MII_MEDIACHG) {
- (*mii->mii_statchg)(sc->sc_mii.mii_dev.dv_parent);
- sc->sc_active = mii->mii_media_active;
+ if (sc->mii_active != mii->mii_media_active || cmd == MII_MEDIACHG) {
+ (*mii->mii_statchg)(sc->mii_dev.dv_parent);
+ sc->mii_active = mii->mii_media_active;
}
return (0);
}
void
inphy_status(sc)
- struct inphy_softc *sc;
+ struct mii_softc *sc;
{
- struct mii_data *mii = sc->sc_mii.mii_pdata;
+ struct mii_data *mii = sc->mii_pdata;
int bmsr, bmcr, scr;
mii->mii_media_status = IFM_AVALID;
mii->mii_media_active = IFM_ETHER;
- bmsr = INPHY_READ(sc, MII_BMSR) | INPHY_READ(sc, MII_BMSR);
+ bmsr = PHY_READ(sc, MII_BMSR) |
+ PHY_READ(sc, MII_BMSR);
if (bmsr & BMSR_LINK)
mii->mii_media_status |= IFM_ACTIVE;
- bmcr = INPHY_READ(sc, MII_BMCR);
+ bmcr = PHY_READ(sc, MII_BMCR);
if (bmcr & BMCR_ISO) {
mii->mii_media_active |= IFM_NONE;
mii->mii_media_status = 0;
@@ -327,7 +316,7 @@ inphy_status(sc)
mii->mii_media_active |= IFM_NONE;
return;
}
- scr = INPHY_READ(sc, MII_INPHY_SCR);
+ scr = PHY_READ(sc, MII_INPHY_SCR);
if (scr & SCR_T4)
mii->mii_media_active |= IFM_100_T4;
else if (scr & SCR_S100)
@@ -336,62 +325,6 @@ inphy_status(sc)
mii->mii_media_active |= IFM_10_T;
if (scr & SCR_FDX)
mii->mii_media_active |= IFM_FDX;
- } else {
- if (bmcr & BMCR_S100)
- mii->mii_media_active |= IFM_100_TX;
- else
- mii->mii_media_active |= IFM_10_T;
- if (bmcr & BMCR_FDX)
- mii->mii_media_active |= IFM_FDX;
- }
-}
-
-void
-inphy_auto(sc)
- struct inphy_softc *sc;
-{
- int bmsr, i;
-
- INPHY_WRITE(sc, MII_ANAR,
- BMSR_MEDIA_TO_ANAR(sc->sc_capabilities) | ANAR_CSMA);
- INPHY_WRITE(sc, MII_BMCR, BMCR_AUTOEN | BMCR_STARTNEG);
-
- /* Wait 500ms for it to complete. */
- for (i = 0; i < 500; i++) {
- if ((bmsr = INPHY_READ(sc, MII_BMSR)) & BMSR_ACOMP)
- return;
- delay(1000);
- }
-#if 0
- if ((bmsr & BMSR_ACOMP) == 0)
- printf("%s: autonegotiation failed to complete\n",
- sc->sc_mii.mii_dev.dv_xname);
-#endif
-}
-
-void
-inphy_reset(sc)
- struct inphy_softc *sc;
-{
- int reg, i;
-
- /*
- * The i82557 wedges if we isolate all of its PHYs!
- */
- if (sc->sc_mii.mii_inst == 0)
- INPHY_WRITE(sc, MII_BMCR, BMCR_RESET);
- else
- INPHY_WRITE(sc, MII_BMCR, BMCR_RESET|BMCR_ISO);
-
- /* Wait 100ms for it to complete. */
- for (i = 0; i < 100; i++) {
- reg = INPHY_READ(sc, MII_BMCR);
- if ((reg & BMCR_RESET) == 0)
- break;
- delay(1000);
- }
-
- /* Make sure the PHY is isolated. */
- if (sc->sc_mii.mii_inst != 0)
- INPHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO);
+ } else
+ mii->mii_media_active = mii_media_from_bmcr(bmcr);
}
diff --git a/sys/dev/mii/lxtphy.c b/sys/dev/mii/lxtphy.c
new file mode 100644
index 00000000000..5209d172d63
--- /dev/null
+++ b/sys/dev/mii/lxtphy.c
@@ -0,0 +1,323 @@
+/* $OpenBSD: lxtphy.c,v 1.1 1998/11/11 19:34:46 jason Exp $ */
+/* $NetBSD: lxtphy.c,v 1.9 1998/11/05 04:08:02 thorpej Exp $ */
+
+/*-
+ * Copyright (c) 1998 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
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 1997 Manuel Bouyer. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Manuel Bouyer.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * driver for Level One's LXT-970 ethernet 10/100 PHY
+ * datasheet from www.level1.com
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/device.h>
+#include <sys/malloc.h>
+#include <sys/socket.h>
+
+#include <net/if.h>
+#include <net/if_media.h>
+
+#include <dev/mii/mii.h>
+#include <dev/mii/miivar.h>
+#include <dev/mii/miidevs.h>
+
+#include <dev/mii/lxtphyreg.h>
+
+#ifdef __NetBSD__
+int lxtphymatch __P((struct device *, struct cfdata *, void *));
+#else
+int lxtphymatch __P((struct device *, void *, void *));
+#endif
+void lxtphyattach __P((struct device *, struct device *, void *));
+
+struct cfattach lxtphy_ca = {
+ sizeof(struct mii_softc), lxtphymatch, lxtphyattach
+};
+
+#ifdef __OpenBSD__
+struct cfdriver lxtphy_cd = {
+ NULL, "lxtphy", DV_DULL
+};
+#endif
+
+int lxtphy_service __P((struct mii_softc *, struct mii_data *, int));
+void lxtphy_status __P((struct mii_softc *));
+
+int
+lxtphymatch(parent, match, aux)
+ struct device *parent;
+#ifdef __NetBSD__
+ struct cfdata *match;
+#else
+ void *match;
+#endif
+ void *aux;
+{
+ struct mii_attach_args *ma = aux;
+
+ if (MII_OUI(ma->mii_id1, ma->mii_id2) == MII_OUI_LEVEL1 &&
+ MII_MODEL(ma->mii_id2) == MII_MODEL_LEVEL1_LXT970)
+ return (10);
+
+ return (0);
+}
+
+void
+lxtphyattach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct mii_softc *sc = (struct mii_softc *)self;
+ struct mii_attach_args *ma = aux;
+ struct mii_data *mii = ma->mii_data;
+
+ printf(": %s, rev. %d\n", MII_STR_LEVEL1_LXT970,
+ MII_REV(ma->mii_id2));
+
+ sc->mii_inst = mii->mii_instance;
+ sc->mii_phy = ma->mii_phyno;
+ sc->mii_service = lxtphy_service;
+ sc->mii_pdata = mii;
+
+#define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL)
+
+ ADD(IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, sc->mii_inst),
+ BMCR_ISO);
+ ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_LOOP, sc->mii_inst),
+ BMCR_LOOP|BMCR_S100);
+
+ mii_phy_reset(sc);
+
+ sc->mii_capabilities =
+ PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
+ printf("%s: ", sc->mii_dev.dv_xname);
+ if ((sc->mii_capabilities & BMSR_MEDIAMASK) == 0)
+ printf("no media present");
+ else
+ mii_add_media(mii, sc->mii_capabilities,
+ sc->mii_inst);
+ printf("\n");
+#undef ADD
+}
+
+int
+lxtphy_service(sc, mii, cmd)
+ struct mii_softc *sc;
+ struct mii_data *mii;
+ int cmd;
+{
+ struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
+ int reg;
+
+ switch (cmd) {
+ case MII_POLLSTAT:
+ /*
+ * If we're not polling our PHY instance, just return.
+ */
+ if (IFM_INST(ife->ifm_media) != sc->mii_inst)
+ return (0);
+ break;
+
+ case MII_MEDIACHG:
+ /*
+ * If the media indicates a different PHY instance,
+ * isolate ourselves.
+ */
+ if (IFM_INST(ife->ifm_media) != sc->mii_inst) {
+ reg = PHY_READ(sc, MII_BMCR);
+ PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO);
+ return (0);
+ }
+
+ /*
+ * If the interface is not up, don't do anything.
+ */
+ 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);
+ 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);
+ }
+ break;
+
+ case MII_TICK:
+ /*
+ * If we're not currently selected, just return.
+ */
+ if (IFM_INST(ife->ifm_media) != sc->mii_inst)
+ return (0);
+
+ /*
+ * Only used for autonegotiation.
+ */
+ if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO)
+ return (0);
+
+ /*
+ * Is the interface even up?
+ */
+ if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
+ return (0);
+
+ /*
+ * Check to see if we have link. If we do, we don't
+ * need to restart the autonegotiation process. Use
+ * the LXT CSR instead of the BMSR, since the CSR's
+ * link indication is dynamic, not latched, so only
+ * one register read is required.
+ */
+ reg = PHY_READ(sc, MII_LXTPHY_CSR);
+ if (reg & CSR_LINK)
+ return (0);
+
+ /*
+ * Only retry autonegotiation every 5 seconds.
+ */
+ if (++sc->mii_ticks != 5)
+ return (0);
+
+ sc->mii_ticks = 0;
+ mii_phy_reset(sc);
+ (void) mii_phy_auto(sc);
+ break;
+ }
+
+ /* Update the media status. */
+ lxtphy_status(sc);
+
+ /* Callback if something changed. */
+ if (sc->mii_active != mii->mii_media_active || cmd == MII_MEDIACHG) {
+ (*mii->mii_statchg)(sc->mii_dev.dv_parent);
+ sc->mii_active = mii->mii_media_active;
+ }
+ return (0);
+}
+
+void
+lxtphy_status(sc)
+ struct mii_softc *sc;
+{
+ struct mii_data *mii = sc->mii_pdata;
+ int bmcr, csr;
+
+ mii->mii_media_status = IFM_AVALID;
+ mii->mii_media_active = IFM_ETHER;
+
+ /*
+ * Get link status from the CSR; we need to read the CSR
+ * for media type anyhow, and the link status in the CSR
+ * doens't latch, so fewer register reads are required.
+ */
+ csr = PHY_READ(sc, MII_LXTPHY_CSR);
+ if (csr & CSR_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;
+
+ if (bmcr & BMCR_AUTOEN) {
+ if ((csr & CSR_ACOMP) == 0) {
+ /* Erg, still trying, I guess... */
+ mii->mii_media_active |= IFM_NONE;
+ return;
+ }
+ if (csr & CSR_SPEED)
+ mii->mii_media_active |= IFM_100_TX;
+ else
+ mii->mii_media_active |= IFM_10_T;
+ if (csr & CSR_DUPLEX)
+ mii->mii_media_active |= IFM_FDX;
+ } else
+ mii->mii_media_active = mii_media_from_bmcr(bmcr);
+}
diff --git a/sys/dev/mii/lxtphyreg.h b/sys/dev/mii/lxtphyreg.h
new file mode 100644
index 00000000000..f78e454fb73
--- /dev/null
+++ b/sys/dev/mii/lxtphyreg.h
@@ -0,0 +1,89 @@
+/* $OpenBSD: lxtphyreg.h,v 1.1 1998/11/11 19:34:47 jason Exp $ */
+/* $NetBSD: lxtphyreg.h,v 1.1 1998/10/24 00:33:17 thorpej Exp $ */
+
+/*-
+ * Copyright (c) 1998 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
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _DEV_MII_LXTPHYREG_H_
+#define _DEV_MII_LXTPHYREG_H_
+
+/*
+ * LXT970 registers.
+ */
+
+#define MII_LXTPHY_MIRROR 0x10 /* Mirror register */
+ /* All bits user-defined */
+
+#define MII_LXTPHY_IER 0x11 /* Interrupt Enable Register */
+#define IER_MIIDRVLVL 0x0008 /* Rediced MII driver levels */
+#define IER_LNK_CRITERIA 0x0004 /* Enhanced Link Loss Criteria */
+#define IER_INTEN 0x0002 /* Interrupt Enable */
+#define IER_TINT 0x0001 /* Force Interrupt */
+
+#define MII_LXTPHY_ISR 0x12 /* Interrupt Status Register */
+#define ISR_MINT 0x8000 /* MII Interrupt Pending */
+#define ISR_XTALOK 0x4000 /* Clocks OK */
+
+#define MII_LXTPHY_CONFIG 0x13 /* Configuration Register */
+#define CONFIG_TXMIT_TEST 0x4000 /* 100base-T Transmit Test */
+#define CONFIG_REPEATER 0x2000 /* Repeater Mode */
+#define CONFIG_MDIO_INT 0x1000 /* Enable intr signalling on MDIO */
+#define CONFIG_TPLOOP 0x0800 /* Disable 10base-T Loopback */
+#define CONFIG_SQE 0x0400 /* Enable SQE */
+#define CONFIG_DISJABBER 0x0200 /* Disable Jabber */
+#define CONFIG_DISLINKTEST 0x0100 /* Disable Link Test */
+#define CONFIG_LEDC1 0x0080 /* LEDC configuration */
+#define CONFIG_LEDC0 0x0040 /* ... */
+ /* 0 0 LEDC indicates collision */
+ /* 0 1 LEDC is off */
+ /* 1 0 LEDC indicates activity */
+ /* 1 1 LEDC is on */
+#define CONFIG_ADVTXCLK 0x0020 /* Advance TX clock */
+#define CONFIG_5BSYMBOL 0x0010 /* 5-bit Symbol mode */
+#define CONFIG_SCRAMBLER 0x0008 /* Bypass scrambler */
+#define CONFIG_100BASEFX 0x0004 /* 100base-FX */
+#define CONFIG_TXDISCON 0x0001 /* Disconnect TP transmitter */
+
+#define MII_LXTPHY_CSR 0x14 /* Chip Status Register */
+#define CSR_LINK 0x2000 /* Link is up */
+#define CSR_DUPLEX 0x1000 /* Full-duplex */
+#define CSR_SPEED 0x0800 /* 100Mbps */
+#define CSR_ACOMP 0x0400 /* Autonegotiation complete */
+#define CSR_PAGERCVD 0x0200 /* Link page received */
+#define CSR_LOWVCC 0x0004 /* Low Voltage Fault */
+
+#endif /* _DEV_MII_LXTPHYREG_H_ */
diff --git a/sys/dev/mii/mii.c b/sys/dev/mii/mii.c
index 40cc6e12194..1bec2fc803e 100644
--- a/sys/dev/mii/mii.c
+++ b/sys/dev/mii/mii.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: mii.c,v 1.1 1998/09/10 17:17:33 jason Exp $ */
-/* $NetBSD: mii.c,v 1.7 1998/08/11 00:41:44 thorpej Exp $ */
+/* $OpenBSD: mii.c,v 1.2 1998/11/11 19:34:47 jason Exp $ */
+/* $NetBSD: mii.c,v 1.9 1998/11/05 04:08:02 thorpej Exp $ */
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -131,7 +131,7 @@ mii_print(aux, pnp)
struct mii_attach_args *ma = aux;
if (pnp != NULL)
- printf("PHY oui 0x%x model 0x%x rev 0x%x at %s",
+ printf("OUI 0x%06x model 0x%04x rev %d at %s",
MII_OUI(ma->mii_id1, ma->mii_id2), MII_MODEL(ma->mii_id2),
MII_REV(ma->mii_id2), pnp);
@@ -197,6 +197,25 @@ mii_anar(media)
}
/*
+ * Given a BMCR value, return the corresponding ifmedia word.
+ */
+int
+mii_media_from_bmcr(bmcr)
+ int bmcr;
+{
+ int rv = IFM_ETHER;
+
+ if (bmcr & BMCR_S100)
+ rv |= IFM_100_TX;
+ else
+ rv |= IFM_10_T;
+ if (bmcr & IFM_FDX)
+ rv |= IFM_FDX;
+
+ return (rv);
+}
+
+/*
* Media changed; notify all PHYs.
*/
int
diff --git a/sys/dev/mii/mii_physubr.c b/sys/dev/mii/mii_physubr.c
new file mode 100644
index 00000000000..4d7ee6dd5fd
--- /dev/null
+++ b/sys/dev/mii/mii_physubr.c
@@ -0,0 +1,102 @@
+/* $OpenBSD: mii_physubr.c,v 1.1 1998/11/11 19:34:47 jason Exp $ */
+/* $NetBSD: mii_physubr.c,v 1.2 1998/11/04 23:28:15 thorpej Exp $ */
+
+/*-
+ * Copyright (c) 1998 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
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Subroutines common to all PHYs.
+ */
+
+#include <sys/param.h>
+#include <sys/device.h>
+#include <sys/systm.h>
+#include <sys/socket.h>
+
+#include <net/if.h>
+#include <net/if_media.h>
+
+#include <dev/mii/mii.h>
+#include <dev/mii/miivar.h>
+
+int
+mii_phy_auto(mii)
+ struct mii_softc *mii;
+{
+ int bmsr, i;
+
+ PHY_WRITE(mii, MII_ANAR,
+ BMSR_MEDIA_TO_ANAR(mii->mii_capabilities) | ANAR_CSMA);
+ PHY_WRITE(mii, MII_BMCR, BMCR_AUTOEN | BMCR_STARTNEG);
+
+ /* Wait 500ms for it to complete. */
+ for (i = 0; i < 500; i++) {
+ if ((bmsr = PHY_READ(mii, MII_BMSR)) & BMSR_ACOMP)
+ return (1);
+ delay(1000);
+ }
+#if 0
+ if ((bmsr & BMSR_ACOMP) == 0)
+ printf("%s: autonegotiation failed to complete\n",
+ mii->mii_dev.dv_xname);
+#endif
+ return (0);
+}
+
+void
+mii_phy_reset(mii)
+ struct mii_softc *mii;
+{
+ int reg, i;
+
+ if (mii->mii_flags & MIIF_NOISOLATE)
+ reg = BMCR_RESET;
+ else
+ reg = BMCR_RESET | BMCR_ISO;
+ PHY_WRITE(mii, MII_BMCR, reg);
+
+ /* Wait 100ms for it to complete. */
+ for (i = 0; i < 100; i++) {
+ reg = PHY_READ(mii, 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);
+}
diff --git a/sys/dev/mii/miivar.h b/sys/dev/mii/miivar.h
index e25a1d354f8..be716d91b86 100644
--- a/sys/dev/mii/miivar.h
+++ b/sys/dev/mii/miivar.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: miivar.h,v 1.1 1998/09/10 17:17:34 jason Exp $ */
-/* $NetBSD: miivar.h,v 1.1 1998/08/10 23:55:18 thorpej Exp $ */
+/* $OpenBSD: miivar.h,v 1.2 1998/11/11 19:34:48 jason Exp $ */
+/* $NetBSD: miivar.h,v 1.7 1998/11/05 04:08:02 thorpej Exp $ */
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -100,7 +100,7 @@ typedef int (*mii_downcall_t) __P((struct mii_softc *, struct mii_data *, int));
/*
* Requests that can be made to the downcall.
*/
-#define MII_TICK 1
+#define MII_TICK 1 /* once-per-second tick */
#define MII_MEDIACHG 2 /* user changed media; perform the switch */
#define MII_POLLSTAT 3 /* user requested media status; fill it in */
@@ -119,9 +119,17 @@ struct mii_softc {
mii_downcall_t mii_service; /* our downcall */
struct mii_data *mii_pdata; /* pointer to parent's mii_data */
+
+ int mii_flags; /* misc. flags; see below */
+ int mii_capabilities; /* capabilities from BMSR */
+ int mii_ticks; /* MII_TICK counter */
+ int mii_active; /* last active media */
};
typedef struct mii_softc mii_softc_t;
+/* mii_flags */
+#define MIIF_NOISOLATE 0x0001 /* do not isolate the PHY */
+
/*
* Used to attach a PHY to a parent.
*/
@@ -136,12 +144,27 @@ typedef struct mii_attach_args mii_attach_args_t;
#ifdef _KERNEL
+#define PHY_READ(p, r) \
+ (*(p)->mii_pdata->mii_readreg)((p)->mii_dev.dv_parent, \
+ (p)->mii_phy, (r))
+
+#define PHY_WRITE(p, r, v) \
+ (*(p)->mii_pdata->mii_writereg)((p)->mii_dev.dv_parent, \
+ (p)->mii_phy, (r), (v))
+
int mii_anar __P((int));
int mii_mediachg __P((struct mii_data *));
void mii_tick __P((struct mii_data *));
void mii_pollstat __P((struct mii_data *));
void mii_phy_probe __P((struct device *, struct mii_data *, int));
void mii_add_media __P((struct mii_data *, int, int));
+
+int mii_media_from_bmcr __P((int));
+
+int mii_phy_auto __P((struct mii_softc *));
+void mii_phy_reset __P((struct mii_softc *));
+
+void ukphy_status __P((struct mii_softc *));
#endif /* _KERNEL */
#endif /* _DEV_MII_MIIVAR_H_ */
diff --git a/sys/dev/mii/nsphy.c b/sys/dev/mii/nsphy.c
index ee9430df8ae..73eba605f97 100644
--- a/sys/dev/mii/nsphy.c
+++ b/sys/dev/mii/nsphy.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: nsphy.c,v 1.1 1998/09/10 17:17:34 jason Exp $ */
-/* $NetBSD: nsphy.c,v 1.9 1998/08/14 00:23:26 thorpej Exp $ */
+/* $OpenBSD: nsphy.c,v 1.2 1998/11/11 19:34:48 jason Exp $ */
+/* $NetBSD: nsphy.c,v 1.16 1998/11/05 04:08:02 thorpej Exp $ */
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -88,13 +88,6 @@
#include <dev/mii/nsphyreg.h>
-struct nsphy_softc {
- struct mii_softc sc_mii; /* generic PHY */
- int sc_capabilities;
- int sc_ticks;
- int sc_active;
-};
-
#ifdef __NetBSD__
int nsphymatch __P((struct device *, struct cfdata *, void *));
#else
@@ -103,7 +96,7 @@ int nsphymatch __P((struct device *, void *, void *));
void nsphyattach __P((struct device *, struct device *, void *));
struct cfattach nsphy_ca = {
- sizeof(struct nsphy_softc), nsphymatch, nsphyattach
+ sizeof(struct mii_softc), nsphymatch, nsphyattach
};
#ifdef __OpenBSD__
@@ -112,18 +105,8 @@ struct cfdriver nsphy_cd = {
};
#endif
-#define NSPHY_READ(sc, reg) \
- (*(sc)->sc_mii.mii_pdata->mii_readreg)((sc)->sc_mii.mii_dev.dv_parent, \
- (sc)->sc_mii.mii_phy, (reg))
-
-#define NSPHY_WRITE(sc, reg, val) \
- (*(sc)->sc_mii.mii_pdata->mii_writereg)((sc)->sc_mii.mii_dev.dv_parent, \
- (sc)->sc_mii.mii_phy, (reg), (val))
-
int nsphy_service __P((struct mii_softc *, struct mii_data *, int));
-void nsphy_reset __P((struct nsphy_softc *));
-void nsphy_auto __P((struct nsphy_softc *));
-void nsphy_status __P((struct nsphy_softc *));
+void nsphy_status __P((struct mii_softc *));
int
nsphymatch(parent, match, aux)
@@ -139,7 +122,7 @@ nsphymatch(parent, match, aux)
if (MII_OUI(ma->mii_id1, ma->mii_id2) == MII_OUI_NATSEMI &&
MII_MODEL(ma->mii_id2) == MII_MODEL_NATSEMI_DP83840)
- return (1);
+ return (10);
return (0);
}
@@ -150,47 +133,56 @@ nsphyattach(parent, self, aux)
struct device *self;
void *aux;
{
- struct nsphy_softc *sc = (struct nsphy_softc *)self;
+ struct mii_softc *sc = (struct mii_softc *)self;
struct mii_attach_args *ma = aux;
struct mii_data *mii = ma->mii_data;
printf(": %s, rev. %d\n", MII_STR_NATSEMI_DP83840,
MII_REV(ma->mii_id2));
- sc->sc_mii.mii_inst = mii->mii_instance;
- sc->sc_mii.mii_phy = ma->mii_phyno;
- sc->sc_mii.mii_service = nsphy_service;
- sc->sc_mii.mii_pdata = mii;
+ sc->mii_inst = mii->mii_instance;
+ sc->mii_phy = ma->mii_phyno;
+ sc->mii_service = nsphy_service;
+ sc->mii_pdata = mii;
+
+ /*
+ * i82557 wedges if all of its PHYs are isolated!
+ */
+ if (strcmp(parent->dv_cfdata->cf_driver->cd_name, "fxp") == 0 &&
+ mii->mii_instance == 0)
+ sc->mii_flags |= MIIF_NOISOLATE;
#define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL)
#if 0
/* Can't do this on the i82557! */
- ADD(IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, sc->sc_mii.mii_inst),
+ ADD(IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, sc->mii_inst),
BMCR_ISO);
#endif
- ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_LOOP, sc->sc_mii.mii_inst),
+ ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_LOOP, sc->mii_inst),
BMCR_LOOP|BMCR_S100);
- nsphy_reset(sc);
+ mii_phy_reset(sc);
- sc->sc_capabilities = NSPHY_READ(sc, MII_BMSR) & ma->mii_capmask;
- printf("%s: ", sc->sc_mii.mii_dev.dv_xname);
- if ((sc->sc_capabilities & BMSR_MEDIAMASK) == 0)
+ sc->mii_capabilities =
+ PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
+ printf("%s: ", sc->mii_dev.dv_xname);
+ if ((sc->mii_capabilities & BMSR_MEDIAMASK) == 0)
printf("no media present");
else
- mii_add_media(mii, sc->sc_capabilities, sc->sc_mii.mii_inst);
+ mii_add_media(mii, sc->mii_capabilities,
+ sc->mii_inst);
printf("\n");
#undef ADD
}
int
-nsphy_service(self, mii, cmd)
- struct mii_softc *self;
+nsphy_service(sc, mii, cmd)
+ struct mii_softc *sc;
struct mii_data *mii;
int cmd;
{
- struct nsphy_softc *sc = (struct nsphy_softc *)self;
+ struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
int reg;
switch (cmd) {
@@ -198,8 +190,7 @@ nsphy_service(self, mii, cmd)
/*
* If we're not polling our PHY instance, just return.
*/
- if (IFM_INST(mii->mii_media.ifm_media) !=
- sc->sc_mii.mii_inst)
+ if (IFM_INST(ife->ifm_media) != sc->mii_inst)
return (0);
break;
@@ -208,10 +199,9 @@ nsphy_service(self, mii, cmd)
* If the media indicates a different PHY instance,
* isolate ourselves.
*/
- if (IFM_INST(mii->mii_media.ifm_media) !=
- sc->sc_mii.mii_inst) {
- reg = NSPHY_READ(sc, MII_BMCR);
- NSPHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO);
+ if (IFM_INST(ife->ifm_media) != sc->mii_inst) {
+ reg = PHY_READ(sc, MII_BMCR);
+ PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO);
return (0);
}
@@ -221,7 +211,7 @@ nsphy_service(self, mii, cmd)
if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
break;
- reg = NSPHY_READ(sc, MII_NSPHY_PCR);
+ reg = PHY_READ(sc, MII_NSPHY_PCR);
/*
* Set up the PCR to use LED4 to indicate full-duplex
@@ -252,16 +242,16 @@ nsphy_service(self, mii, cmd)
reg |= 0x0100 | 0x0400;
#endif
- NSPHY_WRITE(sc, MII_NSPHY_PCR, reg);
+ PHY_WRITE(sc, MII_NSPHY_PCR, reg);
- switch (IFM_SUBTYPE(mii->mii_media.ifm_media)) {
+ switch (IFM_SUBTYPE(ife->ifm_media)) {
case IFM_AUTO:
/*
* If we're already in auto mode, just return.
*/
- if (NSPHY_READ(sc, MII_BMCR) & BMCR_AUTOEN)
+ if (PHY_READ(sc, MII_BMCR) & BMCR_AUTOEN)
return (0);
- nsphy_auto(sc);
+ (void) mii_phy_auto(sc);
break;
case IFM_100_T4:
/*
@@ -272,10 +262,9 @@ nsphy_service(self, mii, cmd)
/*
* BMCR data is stored in the ifmedia entry.
*/
- NSPHY_WRITE(sc, MII_ANAR,
- mii_anar(mii->mii_media.ifm_media));
- NSPHY_WRITE(sc, MII_BMCR,
- mii->mii_media.ifm_cur->ifm_data);
+ PHY_WRITE(sc, MII_ANAR,
+ mii_anar(ife->ifm_media));
+ PHY_WRITE(sc, MII_BMCR, ife->ifm_data);
}
break;
@@ -283,14 +272,13 @@ nsphy_service(self, mii, cmd)
/*
* If we're not currently selected, just return.
*/
- if (IFM_INST(mii->mii_media.ifm_media) !=
- sc->sc_mii.mii_inst)
+ if (IFM_INST(ife->ifm_media) != sc->mii_inst)
return (0);
/*
* Only used for autonegotiation.
*/
- if (IFM_SUBTYPE(mii->mii_media.ifm_media) != IFM_AUTO)
+ if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO)
return (0);
/*
@@ -304,19 +292,20 @@ nsphy_service(self, mii, cmd)
* need to restart the autonegotiation process. Read
* the BMSR twice in case it's latched.
*/
- reg = NSPHY_READ(sc, MII_BMSR) | NSPHY_READ(sc, MII_BMSR);
+ reg = PHY_READ(sc, MII_BMSR) |
+ PHY_READ(sc, MII_BMSR);
if (reg & BMSR_LINK)
return (0);
/*
* Only retry autonegotiation every 5 seconds.
*/
- if (++sc->sc_ticks != 5)
+ if (++sc->mii_ticks != 5)
return (0);
- sc->sc_ticks = 0;
- nsphy_reset(sc);
- nsphy_auto(sc);
+ sc->mii_ticks = 0;
+ mii_phy_reset(sc);
+ (void) mii_phy_auto(sc);
break;
}
@@ -324,28 +313,29 @@ nsphy_service(self, mii, cmd)
nsphy_status(sc);
/* Callback if something changed. */
- if (sc->sc_active != mii->mii_media_active || cmd == MII_MEDIACHG) {
- (*mii->mii_statchg)(sc->sc_mii.mii_dev.dv_parent);
- sc->sc_active = mii->mii_media_active;
+ if (sc->mii_active != mii->mii_media_active || cmd == MII_MEDIACHG) {
+ (*mii->mii_statchg)(sc->mii_dev.dv_parent);
+ sc->mii_active = mii->mii_media_active;
}
return (0);
}
void
nsphy_status(sc)
- struct nsphy_softc *sc;
+ struct mii_softc *sc;
{
- struct mii_data *mii = sc->sc_mii.mii_pdata;
+ struct mii_data *mii = sc->mii_pdata;
int bmsr, bmcr, par, anlpar;
mii->mii_media_status = IFM_AVALID;
mii->mii_media_active = IFM_ETHER;
- bmsr = NSPHY_READ(sc, MII_BMSR) | NSPHY_READ(sc, MII_BMSR);
+ bmsr = PHY_READ(sc, MII_BMSR) |
+ PHY_READ(sc, MII_BMSR);
if (bmsr & BMSR_LINK)
mii->mii_media_status |= IFM_ACTIVE;
- bmcr = NSPHY_READ(sc, MII_BMCR);
+ bmcr = PHY_READ(sc, MII_BMCR);
if (bmcr & BMCR_ISO) {
mii->mii_media_active |= IFM_NONE;
mii->mii_media_status = 0;
@@ -371,9 +361,9 @@ nsphy_status(sc)
* properly! Determine media based on link partner's
* advertised capabilities.
*/
- if (NSPHY_READ(sc, MII_ANER) & ANER_LPAN) {
- anlpar = NSPHY_READ(sc, MII_ANAR) &
- NSPHY_READ(sc, MII_ANLPAR);
+ if (PHY_READ(sc, MII_ANER) & ANER_LPAN) {
+ anlpar = PHY_READ(sc, MII_ANAR) &
+ PHY_READ(sc, MII_ANLPAR);
if (anlpar & ANLPAR_T4)
mii->mii_media_active |= IFM_100_T4;
else if (anlpar & ANLPAR_TX_FD)
@@ -394,7 +384,7 @@ nsphy_status(sc)
* We will never be in full-duplex mode if this is
* the case, so reading the PAR is OK.
*/
- par = NSPHY_READ(sc, MII_NSPHY_PAR);
+ par = PHY_READ(sc, MII_NSPHY_PAR);
if (par & PAR_10)
mii->mii_media_active |= IFM_10_T;
else
@@ -403,62 +393,6 @@ nsphy_status(sc)
if (par & PAR_FDX)
mii->mii_media_active |= IFM_FDX;
#endif
- } else {
- if (bmcr & BMCR_S100)
- mii->mii_media_active |= IFM_100_TX;
- else
- mii->mii_media_active |= IFM_10_T;
- if (bmcr & BMCR_FDX)
- mii->mii_media_active |= IFM_FDX;
- }
-}
-
-void
-nsphy_auto(sc)
- struct nsphy_softc *sc;
-{
- int bmsr, i;
-
- NSPHY_WRITE(sc, MII_ANAR,
- BMSR_MEDIA_TO_ANAR(sc->sc_capabilities) | ANAR_CSMA);
- NSPHY_WRITE(sc, MII_BMCR, BMCR_AUTOEN | BMCR_STARTNEG);
-
- /* Wait 500ms for it to complete. */
- for (i = 0; i < 500; i++) {
- if ((bmsr = NSPHY_READ(sc, MII_BMSR)) & BMSR_ACOMP)
- return;
- delay(1000);
- }
-#if 0
- if ((bmsr & BMSR_ACOMP) == 0)
- printf("%s: autonegotiation failed to complete\n",
- sc->sc_mii.mii_dev.dv_xname);
-#endif
-}
-
-void
-nsphy_reset(sc)
- struct nsphy_softc *sc;
-{
- int reg, i;
-
- /*
- * The i82557 wedges if we isolate all of its PHYs!
- */
- if (sc->sc_mii.mii_inst == 0)
- NSPHY_WRITE(sc, MII_BMCR, BMCR_RESET);
- else
- NSPHY_WRITE(sc, MII_BMCR, BMCR_RESET|BMCR_ISO);
-
- /* Wait 100ms for it to complete. */
- for (i = 0; i < 100; i++) {
- reg = NSPHY_READ(sc, MII_BMCR);
- if ((reg & BMCR_RESET) == 0)
- break;
- delay(1000);
- }
-
- /* Make sure the PHY is isolated. */
- if (sc->sc_mii.mii_inst != 0)
- NSPHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO);
+ } else
+ mii->mii_media_active = mii_media_from_bmcr(bmcr);
}
diff --git a/sys/dev/mii/qsphy.c b/sys/dev/mii/qsphy.c
index d199bd46256..5ac3f7f752e 100644
--- a/sys/dev/mii/qsphy.c
+++ b/sys/dev/mii/qsphy.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: qsphy.c,v 1.1 1998/09/10 17:17:34 jason Exp $ */
-/* $NetBSD: qsphy.c,v 1.3 1998/08/12 20:56:37 thorpej Exp $ */
+/* $OpenBSD: qsphy.c,v 1.2 1998/11/11 19:34:48 jason Exp $ */
+/* $NetBSD: qsphy.c,v 1.11 1998/11/05 04:08:02 thorpej Exp $ */
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -88,12 +88,6 @@
#include <dev/mii/qsphyreg.h>
-struct qsphy_softc {
- struct mii_softc sc_mii; /* generic PHY */
- int sc_capabilities;
- int sc_active;
-};
-
#ifdef __NetBSD__
int qsphymatch __P((struct device *, struct cfdata *, void *));
#else
@@ -102,7 +96,7 @@ int qsphymatch __P((struct device *, void *, void *));
void qsphyattach __P((struct device *, struct device *, void *));
struct cfattach qsphy_ca = {
- sizeof(struct qsphy_softc), qsphymatch, qsphyattach
+ sizeof(struct mii_softc), qsphymatch, qsphyattach
};
#ifdef __OpenBSD__
@@ -111,18 +105,9 @@ struct cfdriver qsphy_cd = {
};
#endif
-#define QSPHY_READ(sc, reg) \
- (*(sc)->sc_mii.mii_pdata->mii_readreg)((sc)->sc_mii.mii_dev.dv_parent, \
- (sc)->sc_mii.mii_phy, (reg))
-
-#define QSPHY_WRITE(sc, reg, val) \
- (*(sc)->sc_mii.mii_pdata->mii_writereg)((sc)->sc_mii.mii_dev.dv_parent, \
- (sc)->sc_mii.mii_phy, (reg), (val))
-
int qsphy_service __P((struct mii_softc *, struct mii_data *, int));
-void qsphy_reset __P((struct qsphy_softc *));
-void qsphy_auto __P((struct qsphy_softc *));
-void qsphy_status __P((struct qsphy_softc *));
+void qsphy_reset __P((struct mii_softc *));
+void qsphy_status __P((struct mii_softc *));
int
qsphymatch(parent, match, aux)
@@ -138,7 +123,7 @@ qsphymatch(parent, match, aux)
if (MII_OUI(ma->mii_id1, ma->mii_id2) == MII_OUI_QUALSEMI &&
MII_MODEL(ma->mii_id2) == MII_MODEL_QUALSEMI_QS6612)
- return (1);
+ return (10);
return (0);
}
@@ -148,44 +133,46 @@ qsphyattach(parent, self, aux)
struct device *parent, *self;
void *aux;
{
- struct qsphy_softc *sc = (struct qsphy_softc *)self;
+ struct mii_softc *sc = (struct mii_softc *)self;
struct mii_attach_args *ma = aux;
struct mii_data *mii = ma->mii_data;
printf(": %s, rev. %d\n", MII_STR_QUALSEMI_QS6612,
MII_REV(ma->mii_id2));
- sc->sc_mii.mii_inst = mii->mii_instance;
- sc->sc_mii.mii_phy = ma->mii_phyno;
- sc->sc_mii.mii_service = qsphy_service;
- sc->sc_mii.mii_pdata = mii;
+ sc->mii_inst = mii->mii_instance;
+ sc->mii_phy = ma->mii_phyno;
+ sc->mii_service = qsphy_service;
+ sc->mii_pdata = mii;
#define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL)
- ADD(IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, sc->sc_mii.mii_inst),
+ ADD(IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, sc->mii_inst),
BMCR_ISO);
- ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_LOOP, sc->sc_mii.mii_inst),
+ ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_LOOP, sc->mii_inst),
BMCR_LOOP|BMCR_S100);
qsphy_reset(sc);
- sc->sc_capabilities = QSPHY_READ(sc, MII_BMSR) & ma->mii_capmask;
- printf("%s: ", sc->sc_mii.mii_dev.dv_xname);
- if ((sc->sc_capabilities & BMSR_MEDIAMASK) == 0)
+ sc->mii_capabilities =
+ PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
+ printf("%s: ", sc->mii_dev.dv_xname);
+ if ((sc->mii_capabilities & BMSR_MEDIAMASK) == 0)
printf("no media present");
else
- mii_add_media(mii, sc->sc_capabilities, sc->sc_mii.mii_inst);
+ mii_add_media(mii, sc->mii_capabilities,
+ sc->mii_inst);
printf("\n");
#undef ADD
}
int
-qsphy_service(self, mii, cmd)
- struct mii_softc *self;
+qsphy_service(sc, mii, cmd)
+ struct mii_softc *sc;
struct mii_data *mii;
int cmd;
{
- struct qsphy_softc *sc = (struct qsphy_softc *)self;
+ struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
int reg;
switch (cmd) {
@@ -193,8 +180,7 @@ qsphy_service(self, mii, cmd)
/*
* If we're not polling our PHY instance, just return.
*/
- if (IFM_INST(mii->mii_media.ifm_media) !=
- sc->sc_mii.mii_inst)
+ if (IFM_INST(ife->ifm_media) != sc->mii_inst)
return (0);
break;
@@ -203,10 +189,9 @@ qsphy_service(self, mii, cmd)
* If the media indicates a different PHY instance,
* isolate ourselves.
*/
- if (IFM_INST(mii->mii_media.ifm_media) !=
- sc->sc_mii.mii_inst) {
- reg = QSPHY_READ(sc, MII_BMCR);
- QSPHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO);
+ if (IFM_INST(ife->ifm_media) != sc->mii_inst) {
+ reg = PHY_READ(sc, MII_BMCR);
+ PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO);
return (0);
}
@@ -216,14 +201,14 @@ qsphy_service(self, mii, cmd)
if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
break;
- switch (IFM_SUBTYPE(mii->mii_media.ifm_media)) {
+ switch (IFM_SUBTYPE(ife->ifm_media)) {
case IFM_AUTO:
/*
* If we're already in auto mode, just return.
*/
- if (QSPHY_READ(sc, MII_BMCR) & BMCR_AUTOEN)
+ if (PHY_READ(sc, MII_BMCR) & BMCR_AUTOEN)
return (0);
- qsphy_auto(sc);
+ (void) mii_phy_auto(sc);
break;
case IFM_100_T4:
/*
@@ -234,10 +219,9 @@ qsphy_service(self, mii, cmd)
/*
* BMCR data is stored in the ifmedia entry.
*/
- QSPHY_WRITE(sc, MII_ANAR,
- mii_anar(mii->mii_media.ifm_media));
- QSPHY_WRITE(sc, MII_BMCR,
- mii->mii_media.ifm_cur->ifm_data);
+ PHY_WRITE(sc, MII_ANAR,
+ mii_anar(ife->ifm_media));
+ PHY_WRITE(sc, MII_BMCR, ife->ifm_data);
}
break;
@@ -245,14 +229,13 @@ qsphy_service(self, mii, cmd)
/*
* If we're not currently selected, just return.
*/
- if (IFM_INST(mii->mii_media.ifm_media) !=
- sc->sc_mii.mii_inst)
+ if (IFM_INST(ife->ifm_media) != sc->mii_inst)
return (0);
/*
* Only used for autonegotiation.
*/
- if (IFM_SUBTYPE(mii->mii_media.ifm_media) != IFM_AUTO)
+ if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO)
return (0);
/*
@@ -272,28 +255,29 @@ qsphy_service(self, mii, cmd)
qsphy_status(sc);
/* Callback if something changed. */
- if (sc->sc_active != mii->mii_media_active || cmd == MII_MEDIACHG) {
- (*mii->mii_statchg)(sc->sc_mii.mii_dev.dv_parent);
- sc->sc_active = mii->mii_media_active;
+ if (sc->mii_active != mii->mii_media_active || cmd == MII_MEDIACHG) {
+ (*mii->mii_statchg)(sc->mii_dev.dv_parent);
+ sc->mii_active = mii->mii_media_active;
}
return (0);
}
void
qsphy_status(sc)
- struct qsphy_softc *sc;
+ struct mii_softc *sc;
{
- struct mii_data *mii = sc->sc_mii.mii_pdata;
+ struct mii_data *mii = sc->mii_pdata;
int bmsr, bmcr, pctl;
mii->mii_media_status = IFM_AVALID;
mii->mii_media_active = IFM_ETHER;
- bmsr = QSPHY_READ(sc, MII_BMSR) | QSPHY_READ(sc, MII_BMSR);
+ bmsr = PHY_READ(sc, MII_BMSR) |
+ PHY_READ(sc, MII_BMSR);
if (bmsr & BMSR_LINK)
mii->mii_media_status |= IFM_ACTIVE;
- bmcr = QSPHY_READ(sc, MII_BMCR);
+ bmcr = PHY_READ(sc, MII_BMCR);
if (bmcr & BMCR_ISO) {
mii->mii_media_active |= IFM_NONE;
mii->mii_media_status = 0;
@@ -303,78 +287,44 @@ qsphy_status(sc)
if (bmcr & BMCR_LOOP)
mii->mii_media_active |= IFM_LOOP;
- if ((bmcr & BMCR_AUTOEN) && (bmsr & BMSR_ACOMP) == 0) {
- /* Erg, still trying, I guess... */
- mii->mii_media_active |= IFM_NONE;
- return;
- }
-
- pctl = QSPHY_READ(sc, MII_QSPHY_PCTL) | QSPHY_READ(sc, MII_QSPHY_PCTL);
- switch (pctl & PCTL_OPMASK) {
- case PCTL_10_T:
- mii->mii_media_active |= IFM_10_T;
- break;
- case PCTL_10_T_FDX:
- mii->mii_media_active |= IFM_10_T|IFM_FDX;
- break;
- case PCTL_100_TX:
- mii->mii_media_active |= IFM_100_TX;
- break;
- case PCTL_100_TX_FDX:
- mii->mii_media_active |= IFM_100_TX|IFM_FDX;
- break;
- case PCTL_100_T4:
- mii->mii_media_active |= IFM_100_T4;
- break;
- default:
- /* Erg... this shouldn't happen. */
- mii->mii_media_active |= IFM_NONE;
- break;
- }
-}
-
-void
-qsphy_auto(sc)
- struct qsphy_softc *sc;
-{
- int bmsr, i;
-
- QSPHY_WRITE(sc, MII_ANAR,
- BMSR_MEDIA_TO_ANAR(sc->sc_capabilities) | ANAR_CSMA);
- QSPHY_WRITE(sc, MII_BMCR, BMCR_AUTOEN | BMCR_STARTNEG);
-
- /* Wait 500ms for it to complete. */
- for (i = 0; i < 500; i++) {
- if ((bmsr = QSPHY_READ(sc, MII_BMSR)) & BMSR_ACOMP)
+ if (bmcr & BMCR_AUTOEN) {
+ if ((bmsr & BMSR_ACOMP) == 0) {
+ /* Erg, still trying, I guess... */
+ mii->mii_media_active |= IFM_NONE;
return;
- delay(1000);
- }
-#if 0
- if ((bmsr & BMSR_ACOMP) == 0)
- printf("%s: autonegotiation failed to complete\n",
- sc->sc_mii.mii_dev.dv_xname);
-#endif
+ }
+ pctl = PHY_READ(sc, MII_QSPHY_PCTL) |
+ PHY_READ(sc, MII_QSPHY_PCTL);
+ switch (pctl & PCTL_OPMASK) {
+ case PCTL_10_T:
+ mii->mii_media_active |= IFM_10_T;
+ break;
+ case PCTL_10_T_FDX:
+ mii->mii_media_active |= IFM_10_T|IFM_FDX;
+ break;
+ case PCTL_100_TX:
+ mii->mii_media_active |= IFM_100_TX;
+ break;
+ case PCTL_100_TX_FDX:
+ mii->mii_media_active |= IFM_100_TX|IFM_FDX;
+ break;
+ case PCTL_100_T4:
+ mii->mii_media_active |= IFM_100_T4;
+ break;
+ default:
+ /* Erg... this shouldn't happen. */
+ mii->mii_media_active |= IFM_NONE;
+ break;
+ }
+ } else
+ mii->mii_media_active = mii_media_from_bmcr(bmcr);
}
void
qsphy_reset(sc)
- struct qsphy_softc *sc;
+ struct mii_softc *sc;
{
- int reg, i;
-
- QSPHY_WRITE(sc, MII_BMCR, BMCR_RESET|BMCR_ISO);
-
- /* Wait 100ms for it to complete. */
- for (i = 0; i < 100; i++) {
- reg = QSPHY_READ(sc, MII_BMCR);
- if ((reg & BMCR_RESET) == 0)
- break;
- delay(1000);
- }
-
- /* Make sure the PHY is isolated. */
- if (sc->sc_mii.mii_inst != 0)
- QSPHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO);
- QSPHY_WRITE(sc, MII_QSPHY_IMASK, 0);
+ mii_phy_reset(sc);
+ PHY_WRITE(sc, MII_QSPHY_IMASK, 0);
}
diff --git a/sys/dev/mii/sqphy.c b/sys/dev/mii/sqphy.c
new file mode 100644
index 00000000000..eecc2ec46ec
--- /dev/null
+++ b/sys/dev/mii/sqphy.c
@@ -0,0 +1,319 @@
+/* $OpenBSD: sqphy.c,v 1.1 1998/11/11 19:34:49 jason Exp $ */
+/* $NetBSD: sqphy.c,v 1.8 1998/11/05 04:08:02 thorpej Exp $ */
+
+/*-
+ * Copyright (c) 1998 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
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 1997 Manuel Bouyer. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Manuel Bouyer.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * driver for Seeq 80220/80221 and 80223 10/100 ethernet PHYs
+ * datasheet from www.seeq.com
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/device.h>
+#include <sys/malloc.h>
+#include <sys/socket.h>
+
+#include <net/if.h>
+#include <net/if_media.h>
+
+#include <dev/mii/mii.h>
+#include <dev/mii/miivar.h>
+#include <dev/mii/miidevs.h>
+
+#include <dev/mii/sqphyreg.h>
+
+#ifdef __NetBSD__
+int sqphymatch __P((struct device *, struct cfdata *, void *));
+#else
+int sqphymatch __P((struct device *, void *, void *));
+#endif
+void sqphyattach __P((struct device *, struct device *, void *));
+
+struct cfattach sqphy_ca = {
+ sizeof(struct mii_softc), sqphymatch, sqphyattach
+};
+
+#ifdef __OpenBSD__
+struct cfdriver sqphy_cd = {
+ NULL, "sqphy", DV_DULL
+};
+#endif
+
+int sqphy_service __P((struct mii_softc *, struct mii_data *, int));
+void sqphy_status __P((struct mii_softc *));
+
+int
+sqphymatch(parent, match, aux)
+ struct device *parent;
+#ifdef __NetBSD__
+ struct cfdata *match;
+#else
+ void *match;
+#endif
+ void *aux;
+{
+ struct mii_attach_args *ma = aux;
+
+ if (MII_OUI(ma->mii_id1, ma->mii_id2) == MII_OUI_SEEQ &&
+ MII_MODEL(ma->mii_id2) == MII_MODEL_SEEQ_80220)
+ return (10);
+
+ return (0);
+}
+
+void
+sqphyattach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct mii_softc *sc = (struct mii_softc *)self;
+ struct mii_attach_args *ma = aux;
+ struct mii_data *mii = ma->mii_data;
+
+ printf(": %s, rev. %d\n", MII_STR_SEEQ_80220,
+ MII_REV(ma->mii_id2));
+
+ sc->mii_inst = mii->mii_instance;
+ sc->mii_phy = ma->mii_phyno;
+ sc->mii_service = sqphy_service;
+ sc->mii_pdata = mii;
+
+#define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL)
+
+ ADD(IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, sc->mii_inst),
+ BMCR_ISO);
+ ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_LOOP, sc->mii_inst),
+ BMCR_LOOP|BMCR_S100);
+
+ mii_phy_reset(sc);
+
+ sc->mii_capabilities =
+ PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
+ printf("%s: ", sc->mii_dev.dv_xname);
+ if ((sc->mii_capabilities & BMSR_MEDIAMASK) == 0)
+ printf("no media present");
+ else
+ mii_add_media(mii, sc->mii_capabilities,
+ sc->mii_inst);
+ printf("\n");
+#undef ADD
+}
+
+int
+sqphy_service(sc, mii, cmd)
+ struct mii_softc *sc;
+ struct mii_data *mii;
+ int cmd;
+{
+ struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
+ int reg;
+
+ switch (cmd) {
+ case MII_POLLSTAT:
+ /*
+ * If we're not polling our PHY instance, just return.
+ */
+ if (IFM_INST(ife->ifm_media) != sc->mii_inst)
+ return (0);
+ break;
+
+ case MII_MEDIACHG:
+ /*
+ * If the media indicates a different PHY instance,
+ * isolate ourselves.
+ */
+ if (IFM_INST(ife->ifm_media) != sc->mii_inst) {
+ reg = PHY_READ(sc, MII_BMCR);
+ PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO);
+ return (0);
+ }
+
+ /*
+ * If the interface is not up, don't do anything.
+ */
+ 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);
+ 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);
+ }
+ break;
+
+ case MII_TICK:
+ /*
+ * If we're not currently selected, just return.
+ */
+ if (IFM_INST(ife->ifm_media) != sc->mii_inst)
+ return (0);
+
+ /*
+ * Only used for autonegotiation.
+ */
+ if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO)
+ return (0);
+
+ /*
+ * Is the interface even up?
+ */
+ if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
+ return (0);
+
+ /*
+ * 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, MII_BMSR) |
+ PHY_READ(sc, MII_BMSR);
+ if (reg & BMSR_LINK)
+ return (0);
+
+ /*
+ * Only retry autonegotiation every 5 seconds.
+ */
+ if (++sc->mii_ticks != 5)
+ return (0);
+
+ sc->mii_ticks = 0;
+ mii_phy_reset(sc);
+ (void) mii_phy_auto(sc);
+ break;
+ }
+
+ /* Update the media status. */
+ sqphy_status(sc);
+
+ /* Callback if something changed. */
+ if (sc->mii_active != mii->mii_media_active || cmd == MII_MEDIACHG) {
+ (*mii->mii_statchg)(sc->mii_dev.dv_parent);
+ sc->mii_active = mii->mii_media_active;
+ }
+ return (0);
+}
+
+void
+sqphy_status(sc)
+ struct mii_softc *sc;
+{
+ struct mii_data *mii = sc->mii_pdata;
+ int bmsr, bmcr, status;
+
+ mii->mii_media_status = IFM_AVALID;
+ mii->mii_media_active = IFM_ETHER;
+
+ bmsr = PHY_READ(sc, MII_BMSR) |
+ PHY_READ(sc, MII_BMSR);
+ if (bmsr & BMSR_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;
+
+ if (bmcr & BMCR_AUTOEN) {
+ if ((bmsr & BMSR_ACOMP) == 0) {
+ /* Erg, still trying, I guess... */
+ mii->mii_media_active |= IFM_NONE;
+ return;
+ }
+ status = PHY_READ(sc, MII_SQPHY_STATUS);
+ if (status & STATUS_SPD_DET)
+ mii->mii_media_active |= IFM_100_TX;
+ else
+ mii->mii_media_active |= IFM_10_T;
+ if (status & STATUS_DPLX_DET)
+ mii->mii_media_active |= IFM_FDX;
+ } else
+ mii->mii_media_active = mii_media_from_bmcr(bmcr);
+}
diff --git a/sys/dev/mii/sqphyreg.h b/sys/dev/mii/sqphyreg.h
new file mode 100644
index 00000000000..169c1de4c7e
--- /dev/null
+++ b/sys/dev/mii/sqphyreg.h
@@ -0,0 +1,128 @@
+/* $OpenBSD: sqphyreg.h,v 1.1 1998/11/11 19:34:49 jason Exp $ */
+/* $NetBSD: sqphyreg.h,v 1.1 1998/11/03 23:51:29 thorpej Exp $ */
+
+/*-
+ * Copyright (c) 1998 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
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _DEV_MII_SQPHYREG_H_
+#define _DEV_MII_SQPHYREG_H_
+
+/*
+ * Seeq 80220 registers.
+ */
+
+#define MII_SQPHY_CONFIG1 0x10 /* Configuration 1 Register */
+#define CONFIG1_LNK_DIS 0x8000 /* Link Detect Disable */
+#define CONFIG1_XMT_DIS 0x4000 /* TP Transmitter Disable */
+#define CONFIG1_XMT_PDN 0x2000 /* TP Transmitter Powerdown */
+#define CONFIG1_TXEN_CRS 0x1000 /* TX_EN to CRS Loopback Disable */
+#define CONFIG1_BYP_ENC 0x0800 /* Bypass Encoder */
+#define CONFIG1_BYP_SCR 0x0400 /* Bypass Scrambler */
+#define CONFIG1_UNSCR_DIS 0x0200 /* Unscr. Idle Reception Disable */
+#define CONFIG1_EQLZR 0x0100 /* Rx Equalizer Disable */
+#define CONFIG1_CABLE 0x0080 /* Cable: 1 = STP, 0 = UTP */
+#define CONFIG1_RLVL0 0x0040 /* Receive Level Adjust */
+#define CONFIG1_TLVL3 0x0020 /* Transmit output level adjust */
+#define CONFIG1_TLVL2 0x0010
+#define CONFIG1_TLVL1 0x0008
+#define CONFIG1_TLVL0 0x0004
+#define CONFIG1_TRF1 0x0002 /* Transmitter Rise/Fall Adjust */
+#define CONFIG1_TRF0 0x0001
+
+#define MII_SQPHY_CONFIG2 0x11 /* Configuration 2 Register */
+#define CONFIG2_PLED3_1 0x8000 /* PLED3 configuration */
+#define CONFIG2_PLED3_0 0x4000
+ /* 1 1 LINK100 (default) */
+ /* 1 0 Blink */
+ /* 0 1 On */
+ /* 0 0 Off */
+#define CONFIG2_PLED2_1 0x2000 /* PLED2 configuration */
+#define CONFIG2_PLED2_0 0x1000
+ /* 1 1 Activity (default) */
+ /* 1 0 Blink */
+ /* 0 1 On */
+ /* 0 0 Off */
+#define CONFIG2_PLED1_1 0x0800 /* PLED1 configuration */
+#define CONFIG2_PLED1_0 0x0400
+ /* 1 1 Full duplex (default) */
+ /* 1 0 Blink */
+ /* 0 1 On */
+ /* 0 0 Off */
+#define CONFIG2_PLED0_1 0x0200 /* PLED0 configuration */
+#define CONFIG2_PLED0_0 0x0100
+ /* 1 1 LINK10 (default) */
+ /* 1 0 Blink */
+ /* 0 1 On */
+ /* 0 0 Off */
+#define CONFIG2_LED_DEF1 0x0080 /* LED Normal Function Select */
+#define CONFIG2_LED_DEF0 0x0040
+#define CONFIG2_APOL_DIS 0x0020 /* Auto Polarity Correct Disable */
+#define CONFIG2_JAB_DIS 0x0010 /* Jabber Disable */
+#define CONFIG2_MREG 0x0008 /* Multiple Register Access Enable */
+#define CONFIG2_INT_MDIO 0x0004 /* MDIO Interrupt when idle */
+#define CONFIG2_RJ_CFG 0x0002 /* R/J Configuration Select */
+
+#define MII_SQPHY_STATUS 0x12 /* Status Output Register */
+#define STATUS_INT 0x8000 /* Interrupt Detect */
+#define STATUS_LNK_FAIL 0x4000 /* Link Fail */
+#define STATUS_LOSS_SYNC 0x2000 /* Descrabler lost synchronization */
+#define STATUS_CWRD 0x1000 /* Codeword Error */
+#define STATUS_SSD 0x0800 /* Start of Stream Error */
+#define STATUS_ESD 0x0400 /* End of Stream Error */
+#define STATUS_RPOL 0x0200 /* Reverse Polarity Detected */
+#define STATUS_JAB 0x0100 /* Jabber Detected */
+#define STATUS_SPD_DET 0x0080 /* 100Mbps */
+#define STATUS_DPLX_DET 0x0040 /* Full Duplex */
+
+#define MII_SQPHY_MASK 0x13 /* Mask Register */
+#define MASK_INT 0x8000 /* mask INT */
+#define MASK_LNK_FAIL 0x4000 /* mask LNK_FAIL */
+#define MASK_LOSS_SYNC 0x2000 /* mask LOSS_SYNC */
+#define MASK_CWRD 0x1000 /* mask CWRD */
+#define MASK_SSD 0x0800 /* mask SSD */
+#define MASK_ESD 0x0400 /* mask ESD */
+#define MASK_RPOL 0x0200 /* mask RPOL */
+#define MASK_JAB 0x0100 /* mask JAB */
+#define MASK_SPD_DET 0x0080 /* mask SPD_DET */
+#define MASK_DPLX_DET 0x0040 /* mask DPLX_DET */
+#define MASK_ANEG_STS1 0x0020 /* mask ANEG_STS1 */
+#define MASK_ANEG_STS0 0x0010 /* mask ANEG_STS0 */
+
+#define MII_SQPHY_RESERVED 0x14 /* Reserved Register */
+ /* All bits must be 0 */
+
+#endif /* _DEV_MII_SQPHYREG_H_ */
diff --git a/sys/dev/mii/tlphy.c b/sys/dev/mii/tlphy.c
index 6ef3c6b5d80..18dcfab285e 100644
--- a/sys/dev/mii/tlphy.c
+++ b/sys/dev/mii/tlphy.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: tlphy.c,v 1.1 1998/09/10 17:17:34 jason Exp $ */
-/* $NetBSD: tlphy.c,v 1.10 1998/08/17 16:41:45 bouyer Exp $ */
+/* $OpenBSD: tlphy.c,v 1.2 1998/11/11 19:34:50 jason Exp $ */
+/* $NetBSD: tlphy.c,v 1.16 1998/11/05 00:19:32 thorpej Exp $ */
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -104,10 +104,7 @@
struct tlphy_softc {
struct mii_softc sc_mii; /* generic PHY */
- int sc_capabilities;
- int sc_ticks;
int sc_tlphycap;
- int sc_active;
};
#ifdef __NetBSD__
@@ -127,16 +124,7 @@ struct cfattach tlphy_ca = {
sizeof(struct tlphy_softc), tlphymatch, tlphyattach
};
-#define TLPHY_READ(sc, reg) \
- (*(sc)->sc_mii.mii_pdata->mii_readreg)((sc)->sc_mii.mii_dev.dv_parent, \
- (sc)->sc_mii.mii_phy, (reg))
-
-#define TLPHY_WRITE(sc, reg, val) \
- (*(sc)->sc_mii.mii_pdata->mii_writereg)((sc)->sc_mii.mii_dev.dv_parent, \
- (sc)->sc_mii.mii_phy, (reg), (val))
-
int tlphy_service __P((struct mii_softc *, struct mii_data *, int));
-void tlphy_reset __P((struct tlphy_softc *));
void tlphy_auto __P((struct tlphy_softc *));
void tlphy_status __P((struct tlphy_softc *));
@@ -154,7 +142,7 @@ tlphymatch(parent, match, aux)
if (MII_OUI(ma->mii_id1, ma->mii_id2) == MII_OUI_TI &&
MII_MODEL(ma->mii_id2) == MII_MODEL_TI_TLAN10T)
- return (1);
+ return (10);
return (0);
}
@@ -178,7 +166,7 @@ tlphyattach(parent, self, aux)
sc->sc_mii.mii_service = tlphy_service;
sc->sc_mii.mii_pdata = mii;
- tlphy_reset(sc);
+ mii_phy_reset(&sc->sc_mii);
/*
* Note that if we're on a device that also supports 100baseTX,
@@ -189,10 +177,10 @@ tlphyattach(parent, self, aux)
*/
sc->sc_tlphycap = tlsc->tl_product->tp_tlphymedia;
if ((sc->sc_tlphycap & TLPHY_MEDIA_NO_10_T) == 0)
- sc->sc_capabilities =
- TLPHY_READ(sc, MII_BMSR) & ma->mii_capmask;
+ sc->sc_mii.mii_capabilities =
+ PHY_READ(&sc->sc_mii, MII_BMSR) & ma->mii_capmask;
else
- sc->sc_capabilities = 0;
+ sc->sc_mii.mii_capabilities = 0;
#define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL)
@@ -217,9 +205,10 @@ tlphyattach(parent, self, aux)
PRINT("10base5/AUI");
}
}
- if (sc->sc_capabilities & BMSR_MEDIAMASK) {
+ if (sc->sc_mii.mii_capabilities & BMSR_MEDIAMASK) {
printf(sep);
- mii_add_media(mii, sc->sc_capabilities, sc->sc_mii.mii_inst);
+ mii_add_media(mii, sc->sc_mii.mii_capabilities,
+ sc->sc_mii.mii_inst);
} else if ((sc->sc_tlphycap & (TLPHY_MEDIA_10_2 | TLPHY_MEDIA_10_5))
== 0)
printf("no media present");
@@ -235,6 +224,7 @@ tlphy_service(self, mii, cmd)
int cmd;
{
struct tlphy_softc *sc = (struct tlphy_softc *)self;
+ struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
int reg;
switch (cmd) {
@@ -242,8 +232,7 @@ tlphy_service(self, mii, cmd)
/*
* If we're not polling our PHY instance, just return.
*/
- if (IFM_INST(mii->mii_media.ifm_media) !=
- sc->sc_mii.mii_inst)
+ if (IFM_INST(ife->ifm_media) != sc->sc_mii.mii_inst)
return (0);
break;
@@ -252,10 +241,9 @@ tlphy_service(self, mii, cmd)
* If the media indicates a different PHY instance,
* isolate ourselves.
*/
- if (IFM_INST(mii->mii_media.ifm_media) !=
- sc->sc_mii.mii_inst) {
- reg = TLPHY_READ(sc, MII_BMCR);
- TLPHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO);
+ if (IFM_INST(ife->ifm_media) != sc->sc_mii.mii_inst) {
+ reg = PHY_READ(&sc->sc_mii, MII_BMCR);
+ PHY_WRITE(&sc->sc_mii, MII_BMCR, reg | BMCR_ISO);
return (0);
}
@@ -265,7 +253,7 @@ tlphy_service(self, mii, cmd)
if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
break;
- switch (IFM_SUBTYPE(mii->mii_media.ifm_media)) {
+ switch (IFM_SUBTYPE(ife->ifm_media)) {
case IFM_AUTO:
/*
* The ThunderLAN PHY doesn't self-configure after
@@ -276,17 +264,16 @@ tlphy_service(self, mii, cmd)
break;
case IFM_10_2:
case IFM_10_5:
- TLPHY_WRITE(sc, MII_BMCR, 0);
- TLPHY_WRITE(sc, MII_TLPHY_CTRL, CTRL_AUISEL);
+ PHY_WRITE(&sc->sc_mii, MII_BMCR, 0);
+ PHY_WRITE(&sc->sc_mii, MII_TLPHY_CTRL, CTRL_AUISEL);
delay(100000);
break;
default:
- TLPHY_WRITE(sc, MII_TLPHY_CTRL, 0);
+ PHY_WRITE(&sc->sc_mii, MII_TLPHY_CTRL, 0);
delay(100000);
- TLPHY_WRITE(sc, MII_ANAR,
- mii_anar(mii->mii_media.ifm_media));
- TLPHY_WRITE(sc, MII_BMCR,
- mii->mii_media.ifm_cur->ifm_data);
+ PHY_WRITE(&sc->sc_mii, MII_ANAR,
+ mii_anar(ife->ifm_media));
+ PHY_WRITE(&sc->sc_mii, MII_BMCR, ife->ifm_data);
}
break;
@@ -294,14 +281,13 @@ tlphy_service(self, mii, cmd)
/*
* If we're not currently selected, just return.
*/
- if (IFM_INST(mii->mii_media.ifm_media) !=
- sc->sc_mii.mii_inst)
+ if (IFM_INST(ife->ifm_media) != sc->sc_mii.mii_inst)
return (0);
/*
* Only used for autonegotiation.
*/
- if (IFM_SUBTYPE(mii->mii_media.ifm_media) != IFM_AUTO)
+ if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO)
return (0);
/*
@@ -317,18 +303,19 @@ tlphy_service(self, mii, cmd)
*
* XXX WHAT ABOUT CHECKING LINK ON THE BNC/AUI?!
*/
- reg = TLPHY_READ(sc, MII_BMSR) | TLPHY_READ(sc, MII_BMSR);
+ reg = PHY_READ(&sc->sc_mii, MII_BMSR) |
+ PHY_READ(&sc->sc_mii, MII_BMSR);
if (reg & BMSR_LINK)
return (0);
/*
* Only retry autonegotiation every 5 seconds.
*/
- if (++sc->sc_ticks != 5)
+ if (++sc->sc_mii.mii_ticks != 5)
return (0);
- sc->sc_ticks = 0;
- tlphy_reset(sc);
+ sc->sc_mii.mii_ticks = 0;
+ mii_phy_reset(&sc->sc_mii);
tlphy_auto(sc);
break;
}
@@ -337,9 +324,10 @@ tlphy_service(self, mii, cmd)
tlphy_status(sc);
/* Callback if something changed. */
- if (sc->sc_active != mii->mii_media_active || cmd == MII_MEDIACHG) {
+ if (sc->sc_mii.mii_active != mii->mii_media_active ||
+ cmd == MII_MEDIACHG) {
(*mii->mii_statchg)(sc->sc_mii.mii_dev.dv_parent);
- sc->sc_active = mii->mii_media_active;
+ sc->sc_mii.mii_active = mii->mii_media_active;
}
return (0);
}
@@ -355,14 +343,14 @@ tlphy_status(sc)
mii->mii_media_status = IFM_AVALID;
mii->mii_media_active = IFM_ETHER;
- bmcr = TLPHY_READ(sc, MII_BMCR);
+ bmcr = PHY_READ(&sc->sc_mii, MII_BMCR);
if (bmcr & BMCR_ISO) {
mii->mii_media_active |= IFM_NONE;
mii->mii_media_status = 0;
return;
}
- tlctrl = TLPHY_READ(sc, MII_TLPHY_CTRL);
+ tlctrl = PHY_READ(&sc->sc_mii, MII_TLPHY_CTRL);
if (tlctrl & CTRL_AUISEL) {
if (sc->sc_tlphycap & TLPHY_MEDIA_10_2)
mii->mii_media_active |= IFM_10_2;
@@ -376,7 +364,8 @@ tlphy_status(sc)
return;
}
- bmsr = TLPHY_READ(sc, MII_BMSR) | TLPHY_READ(sc, MII_BMSR);
+ bmsr = PHY_READ(&sc->sc_mii, MII_BMSR) |
+ PHY_READ(&sc->sc_mii, MII_BMSR);
if (bmsr & BMSR_LINK)
mii->mii_media_status |= IFM_ACTIVE;
@@ -398,25 +387,10 @@ void
tlphy_auto(sc)
struct tlphy_softc *sc;
{
- int aner, anlpar, bmsr, i;
-
- TLPHY_WRITE(sc, MII_ANAR,
- BMSR_MEDIA_TO_ANAR(sc->sc_capabilities) | ANAR_CSMA);
- TLPHY_WRITE(sc, MII_BMCR, BMCR_AUTOEN | BMCR_STARTNEG);
+ int aner, anlpar;
- /* Wait 500ms for it to complete. */
- for (i = 0; i < 500; i++) {
- if ((bmsr = TLPHY_READ(sc, MII_BMSR)) & BMSR_ACOMP)
- return;
- delay(1000);
- }
- if ((bmsr & BMSR_ACOMP) == 0) {
-#if 0
- printf("%s: autonegotiation failed to complete\n",
- sc->sc_mii.mii_dev.dv_xname);
-#endif
+ if (mii_phy_auto(&sc->sc_mii) == 0)
goto dflt;
- }
/*
* Grr, braindead ThunderLAN PHY doesn't self-configure
@@ -424,12 +398,12 @@ tlphy_auto(sc)
* based on the link partner status.
*/
- aner = TLPHY_READ(sc, MII_ANER);
+ aner = PHY_READ(&sc->sc_mii, MII_ANER);
if (aner & ANER_LPAN) {
- anlpar = TLPHY_READ(sc, MII_ANLPAR) &
- TLPHY_READ(sc, MII_ANAR);
+ anlpar = PHY_READ(&sc->sc_mii, MII_ANLPAR) &
+ PHY_READ(&sc->sc_mii, MII_ANAR);
if (anlpar & ANAR_10_FD) {
- TLPHY_WRITE(sc, MII_BMCR, BMCR_FDX);
+ PHY_WRITE(&sc->sc_mii, MII_BMCR, BMCR_FDX);
return;
}
}
@@ -439,26 +413,5 @@ tlphy_auto(sc)
* Just assume we're not in full-duplex mode.
* XXX Check link and try AUI/BNC?
*/
- TLPHY_WRITE(sc, MII_BMCR, 0);
-}
-
-void
-tlphy_reset(sc)
- struct tlphy_softc *sc;
-{
- int reg, i;
-
- TLPHY_WRITE(sc, MII_BMCR, BMCR_RESET|BMCR_ISO);
-
- /* Wait 100ms for it to complete. */
- for (i = 0; i < 100; i++) {
- reg = TLPHY_READ(sc, MII_BMCR);
- if ((reg & BMCR_RESET) == 0)
- break;
- delay(1000);
- }
-
- /* Make sure the PHY is isolated. */
- if (sc->sc_mii.mii_inst != 0)
- TLPHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO);
+ PHY_WRITE(&sc->sc_mii, MII_BMCR, 0);
}
diff --git a/sys/dev/mii/ukphy.c b/sys/dev/mii/ukphy.c
new file mode 100644
index 00000000000..a797a5e25b8
--- /dev/null
+++ b/sys/dev/mii/ukphy.c
@@ -0,0 +1,274 @@
+/* $OpenBSD: ukphy.c,v 1.1 1998/11/11 19:34:50 jason Exp $ */
+/* $NetBSD: ukphy.c,v 1.1 1998/11/05 00:36:48 thorpej Exp $ */
+
+/*-
+ * Copyright (c) 1998 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, and by Frank van der Linden.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 1997 Manuel Bouyer. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Manuel Bouyer.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * driver for generic unknown PHYs
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/device.h>
+#include <sys/malloc.h>
+#include <sys/socket.h>
+
+#include <net/if.h>
+#include <net/if_media.h>
+
+#include <dev/mii/mii.h>
+#include <dev/mii/miivar.h>
+
+#ifdef __NetBSD__
+int ukphymatch __P((struct device *, struct cfdata *, void *));
+#else
+int ukphymatch __P((struct device *, void *, void *));
+#endif
+void ukphyattach __P((struct device *, struct device *, void *));
+
+struct cfattach ukphy_ca = {
+ sizeof(struct mii_softc), ukphymatch, ukphyattach
+};
+
+#ifdef __OpenBSD__
+struct cfdriver ukphy_cd = {
+ NULL, "ukphy", DV_DULL
+};
+#endif
+
+int ukphy_service __P((struct mii_softc *, struct mii_data *, int));
+
+int
+ukphymatch(parent, match, aux)
+ struct device *parent;
+#ifdef __NetBSD__
+ struct cfdata *match;
+#else
+ void *match;
+#endif
+ void *aux;
+{
+
+ /*
+ * We know something is here, so always match at a low priority.
+ */
+ return (1);
+}
+
+void
+ukphyattach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct mii_softc *sc = (struct mii_softc *)self;
+ struct mii_attach_args *ma = aux;
+ struct mii_data *mii = ma->mii_data;
+
+ printf(": Generic IEEE 802.3u media interface\n");
+ printf("%s: OUI 0x%06x, model 0x%04x, rev. %d\n",
+ sc->mii_dev.dv_xname, MII_OUI(ma->mii_id1, ma->mii_id2),
+ MII_MODEL(ma->mii_id2), MII_REV(ma->mii_id2));
+
+ sc->mii_inst = mii->mii_instance;
+ sc->mii_phy = ma->mii_phyno;
+ sc->mii_service = ukphy_service;
+ sc->mii_pdata = mii;
+
+#define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL)
+
+ 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);
+
+ sc->mii_capabilities =
+ PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
+ printf("%s: ", sc->mii_dev.dv_xname);
+ if ((sc->mii_capabilities & BMSR_MEDIAMASK) == 0)
+ printf("no media present");
+ else
+ mii_add_media(mii, sc->mii_capabilities,
+ sc->mii_inst);
+ printf("\n");
+#undef ADD
+}
+
+int
+ukphy_service(sc, mii, cmd)
+ struct mii_softc *sc;
+ struct mii_data *mii;
+ int cmd;
+{
+ struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
+ int reg;
+
+ switch (cmd) {
+ case MII_POLLSTAT:
+ /*
+ * If we're not polling our PHY instance, just return.
+ */
+ if (IFM_INST(ife->ifm_media) != sc->mii_inst)
+ return (0);
+ break;
+
+ case MII_MEDIACHG:
+ /*
+ * If the media indicates a different PHY instance,
+ * isolate ourselves.
+ */
+ if (IFM_INST(ife->ifm_media) != sc->mii_inst) {
+ reg = PHY_READ(sc, MII_BMCR);
+ PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO);
+ return (0);
+ }
+
+ /*
+ * If the interface is not up, don't do anything.
+ */
+ 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);
+ 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);
+ }
+ break;
+
+ case MII_TICK:
+ /*
+ * If we're not currently selected, just return.
+ */
+ if (IFM_INST(ife->ifm_media) != sc->mii_inst)
+ return (0);
+
+ /*
+ * Only used for autonegotiation.
+ */
+ if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO)
+ return (0);
+
+ /*
+ * Is the interface even up?
+ */
+ if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
+ return (0);
+
+ /*
+ * 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, MII_BMSR) |
+ PHY_READ(sc, MII_BMSR);
+ if (reg & BMSR_LINK)
+ return (0);
+
+ /*
+ * Only retry autonegotiation every 5 seconds.
+ */
+ if (++sc->mii_ticks != 5)
+ return (0);
+
+ sc->mii_ticks = 0;
+ mii_phy_reset(sc);
+ (void) mii_phy_auto(sc);
+ break;
+ }
+
+ /* Update the media status. */
+ ukphy_status(sc);
+
+ /* Callback if something changed. */
+ if (sc->mii_active != mii->mii_media_active || cmd == MII_MEDIACHG) {
+ (*mii->mii_statchg)(sc->mii_dev.dv_parent);
+ sc->mii_active = mii->mii_media_active;
+ }
+ return (0);
+}
diff --git a/sys/dev/mii/ukphy_subr.c b/sys/dev/mii/ukphy_subr.c
new file mode 100644
index 00000000000..d389507e3ad
--- /dev/null
+++ b/sys/dev/mii/ukphy_subr.c
@@ -0,0 +1,113 @@
+/* $OpenBSD: ukphy_subr.c,v 1.1 1998/11/11 19:34:51 jason Exp $ */
+/* $NetBSD: ukphy_subr.c,v 1.2 1998/11/05 04:08:02 thorpej Exp $ */
+
+/*-
+ * Copyright (c) 1998 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, and by Frank van der Linden.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Subroutines shared by the ukphy driver and other PHY drivers.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/device.h>
+#include <sys/malloc.h>
+#include <sys/socket.h>
+
+#include <net/if.h>
+#include <net/if_media.h>
+
+#include <dev/mii/mii.h>
+#include <dev/mii/miivar.h>
+
+/*
+ * Media status subroutine. If a PHY driver does media detection simply
+ * by decoding the NWay autonegotiation, use this routine.
+ */
+void
+ukphy_status(phy)
+ struct mii_softc *phy;
+{
+ struct mii_data *mii = phy->mii_pdata;
+ int bmsr, bmcr, anlpar;
+
+ mii->mii_media_status = IFM_AVALID;
+ mii->mii_media_active = IFM_ETHER;
+
+ bmsr = PHY_READ(phy, MII_BMSR) | PHY_READ(phy, MII_BMSR);
+ if (bmsr & BMSR_LINK)
+ mii->mii_media_status |= IFM_ACTIVE;
+
+ bmcr = PHY_READ(phy, 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;
+
+ if (bmcr & BMCR_AUTOEN) {
+ /*
+ * NWay autonegotiation takes the highest-order common
+ * bit of the ANAR and ANLPAR (i.e. best media advertised
+ * both by us and our link partner).
+ */
+ if ((bmsr & BMSR_ACOMP) == 0) {
+ /* Erg, still trying, I guess... */
+ mii->mii_media_active |= IFM_NONE;
+ return;
+ }
+
+ anlpar = PHY_READ(phy, MII_ANAR) & PHY_READ(phy, MII_ANLPAR);
+ 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;
+ else
+ mii->mii_media_active |= IFM_NONE;
+ } else
+ mii->mii_media_active = mii_media_from_bmcr(bmcr);
+}