summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorNathan Binkert <nate@cvs.openbsd.org>2000-08-26 20:04:19 +0000
committerNathan Binkert <nate@cvs.openbsd.org>2000-08-26 20:04:19 +0000
commit841e005741a8dcb32a106f13731c7dd1e832d2b7 (patch)
tree61d0acb17595089ed91f7518d6314428615d1b9e /sys
parentbd43edc61a95550b14f127a9a6b2902a6208f11b (diff)
sync mii code with netbsd
adds detach functionality for phys some code cleanup Nobody really had time to test all of this out, but theo said commit anyway
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/mii/dcphy.c23
-rw-r--r--sys/dev/mii/dmphy.c49
-rw-r--r--sys/dev/mii/exphy.c43
-rw-r--r--sys/dev/mii/icsphy.c59
-rw-r--r--sys/dev/mii/inphy.c73
-rw-r--r--sys/dev/mii/iophy.c81
-rw-r--r--sys/dev/mii/lxtphy.c72
-rw-r--r--sys/dev/mii/mii.c176
-rw-r--r--sys/dev/mii/mii.h7
-rw-r--r--sys/dev/mii/mii_physubr.c255
-rw-r--r--sys/dev/mii/miivar.h64
-rw-r--r--sys/dev/mii/mtdphy.c49
-rw-r--r--sys/dev/mii/nsphy.c41
-rw-r--r--sys/dev/mii/nsphyter.c70
-rw-r--r--sys/dev/mii/qsphy.c50
-rw-r--r--sys/dev/mii/rlphy.c48
-rw-r--r--sys/dev/mii/sqphy.c66
-rw-r--r--sys/dev/mii/tlphy.c70
-rw-r--r--sys/dev/mii/tqphy.c74
-rw-r--r--sys/dev/mii/txphy.c47
-rw-r--r--sys/dev/mii/ukphy.c71
-rw-r--r--sys/net/if.h19
-rw-r--r--sys/net/if_media.c48
-rw-r--r--sys/net/if_media.h77
24 files changed, 786 insertions, 846 deletions
diff --git a/sys/dev/mii/dcphy.c b/sys/dev/mii/dcphy.c
index 87df1e3538a..f9ccebb2c91 100644
--- a/sys/dev/mii/dcphy.c
+++ b/sys/dev/mii/dcphy.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: dcphy.c,v 1.2 2000/04/18 19:35:32 jason Exp $ */
+/* $OpenBSD: dcphy.c,v 1.3 2000/08/26 20:04:17 nate Exp $ */
/*
* Copyright (c) 1997, 1998, 1999
@@ -90,7 +90,8 @@ int dcphy_match __P((struct device *, void *, void *));
void dcphy_attach __P((struct device *, struct device *, void *));
struct cfattach dcphy_ca = {
- sizeof(struct mii_softc), dcphy_match, dcphy_attach
+ sizeof(struct mii_softc), dcphy_match, dcphy_attach, mii_phy_detach,
+ mii_phy_activate
};
struct cfdriver dcphy_cd = {
@@ -135,7 +136,9 @@ dcphy_attach(parent, self, aux)
sc->mii_inst = mii->mii_instance;
sc->mii_phy = ma->mii_phyno;
sc->mii_service = dcphy_service;
+ sc->mii_status = dcphy_status;
sc->mii_pdata = mii;
+ sc->mii_flags = mii->mii_flags;
sc->mii_flags |= MIIF_NOISOLATE;
mii->mii_instance++;
@@ -162,10 +165,8 @@ dcphy_attach(parent, self, aux)
}
sc->mii_capabilities &= ma->mii_capmask;
- if ((sc->mii_capabilities & BMSR_MEDIAMASK) == 0)
- printf("no media present");
- else
- mii_add_media(sc);
+ if (sc->mii_capabilities & BMSR_MEDIAMASK)
+ mii_phy_add_media(sc);
#undef ADD
}
@@ -180,6 +181,9 @@ dcphy_service(sc, mii, cmd)
int reg;
u_int32_t mode;
+ if ((sc->mii_dev.dv_flags & DVF_ACTIVE) == 0)
+ return (ENXIO);
+
dc_sc = mii->mii_ifp->if_softc;
switch (cmd) {
@@ -333,13 +337,10 @@ dcphy_service(sc, mii, cmd)
}
/* Update the media status. */
- dcphy_status(sc);
+ mii_phy_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;
- }
+ mii_phy_update(sc, cmd);
return (0);
}
diff --git a/sys/dev/mii/dmphy.c b/sys/dev/mii/dmphy.c
index abd48a48076..aa7cdff366e 100644
--- a/sys/dev/mii/dmphy.c
+++ b/sys/dev/mii/dmphy.c
@@ -1,3 +1,4 @@
+/* $OpenBSD: dmphy.c,v 1.2 2000/08/26 20:04:17 nate Exp $ */
/* $NetBSD: dmphy.c,v 1.7.4.1 2000/07/04 04:11:12 thorpej Exp $ */
/*-
@@ -92,7 +93,8 @@ int dmphymatch __P((struct device *, void *, void *));
void dmphyattach __P((struct device *, struct device *, void *));
struct cfattach dmphy_ca = {
- sizeof(struct mii_softc), dmphymatch, dmphyattach
+ sizeof(struct mii_softc), dmphymatch, dmphyattach, mii_phy_detach,
+ mii_phy_activate
};
struct cfdriver dmphy_cd = {
@@ -133,14 +135,16 @@ dmphyattach(parent, self, aux)
sc->mii_inst = mii->mii_instance;
sc->mii_phy = ma->mii_phyno;
sc->mii_service = dmphy_service;
+ sc->mii_status = ukphy_status;
sc->mii_pdata = mii;
+ sc->mii_flags = mii->mii_flags;
mii_phy_reset(sc);
sc->mii_capabilities =
PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
if (sc->mii_capabilities & BMSR_MEDIAMASK)
- mii_add_media(sc);
+ mii_phy_add_media(sc);
}
int
@@ -181,18 +185,7 @@ dmphy_service(sc, mii, cmd)
if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
break;
- switch (IFM_SUBTYPE(ife->ifm_media)) {
- case IFM_AUTO:
- /*
- * If we're already in auto mode, just return.
- */
- if (PHY_READ(sc, MII_BMCR) & BMCR_AUTOEN)
- return (0);
- (void) mii_phy_auto(sc, 1);
- break;
- default:
- mii_phy_setmedia(sc);
- }
+ mii_phy_setmedia(sc);
break;
case MII_TICK:
@@ -202,25 +195,7 @@ dmphy_service(sc, mii, cmd)
if (IFM_INST(ife->ifm_media) != sc->mii_inst)
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);
- if (mii_phy_auto(sc, 0) == EJUSTRETURN)
+ if (mii_phy_tick(sc) == EJUSTRETURN)
return (0);
break;
@@ -230,13 +205,9 @@ dmphy_service(sc, mii, cmd)
}
/* Update the media status. */
- dmphy_status(sc);
+ mii_phy_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;
- }
+ mii_phy_update(sc, cmd);
return (0);
}
diff --git a/sys/dev/mii/exphy.c b/sys/dev/mii/exphy.c
index 55ccad79aff..990f03ee707 100644
--- a/sys/dev/mii/exphy.c
+++ b/sys/dev/mii/exphy.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: exphy.c,v 1.7 2000/02/16 05:06:01 jason Exp $ */
-/* $NetBSD: exphy.c,v 1.15.6.1 1999/04/23 15:39:33 perry Exp $ */
+/* $OpenBSD: exphy.c,v 1.8 2000/08/26 20:04:17 nate Exp $ */
+/* $NetBSD: exphy.c,v 1.23 2000/02/02 23:34:56 thorpej Exp $ */
/*-
* Copyright (c) 1998, 1999 The NetBSD Foundation, Inc.
@@ -89,7 +89,8 @@ int exphymatch __P((struct device *, void *, void *));
void exphyattach __P((struct device *, struct device *, void *));
struct cfattach exphy_ca = {
- sizeof(struct mii_softc), exphymatch, exphyattach
+ sizeof(struct mii_softc), exphymatch, exphyattach, mii_phy_detach,
+ mii_phy_activate
};
struct cfdriver exphy_cd = {
@@ -147,7 +148,9 @@ exphyattach(parent, self, aux)
sc->mii_inst = mii->mii_instance;
sc->mii_phy = ma->mii_phyno;
sc->mii_service = exphy_service;
+ sc->mii_status = ukphy_status;
sc->mii_pdata = mii;
+ sc->mii_flags = mii->mii_flags;
/*
* The 3Com PHY can never be isolated, so never allow non-zero
@@ -165,7 +168,7 @@ exphyattach(parent, self, aux)
sc->mii_capabilities =
PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
if (sc->mii_capabilities & BMSR_MEDIAMASK)
- mii_add_media(sc);
+ mii_phy_add_media(sc);
}
int
@@ -176,6 +179,9 @@ exphy_service(sc, mii, cmd)
{
struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
+ if ((sc->mii_dev.dv_flags & DVF_ACTIVE) == 0)
+ return (ENXIO);
+
/*
* We can't isolate the 3Com PHY, so it has to be the only one!
*/
@@ -193,18 +199,7 @@ exphy_service(sc, mii, cmd)
if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
break;
- switch (IFM_SUBTYPE(ife->ifm_media)) {
- case IFM_AUTO:
- /*
- * If we're already in auto mode, just return.
- */
- if (PHY_READ(sc, MII_BMCR) & BMCR_AUTOEN)
- return (0);
- (void) mii_phy_auto(sc, 1);
- break;
- default:
- mii_phy_setmedia(sc);
- }
+ mii_phy_setmedia(sc);
break;
case MII_TICK:
@@ -214,16 +209,9 @@ exphy_service(sc, mii, cmd)
if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO)
return (0);
- /*
- * Is the interface even up?
- */
- if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
+ if (mii_phy_tick(sc) == EJUSTRETURN)
return (0);
- /*
- * The 3Com PHY's autonegotiation doesn't need to be
- * kicked; it continues in the background.
- */
break;
case MII_DOWN:
@@ -232,13 +220,10 @@ exphy_service(sc, mii, cmd)
}
/* Update the media status. */
- ukphy_status(sc);
+ mii_phy_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;
- }
+ mii_phy_update(sc, cmd);
return (0);
}
diff --git a/sys/dev/mii/icsphy.c b/sys/dev/mii/icsphy.c
index f349c0af6c7..d98a42cf58c 100644
--- a/sys/dev/mii/icsphy.c
+++ b/sys/dev/mii/icsphy.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: icsphy.c,v 1.5 1999/12/07 22:01:30 jason Exp $ */
-/* $NetBSD: icsphy.c,v 1.8.6.1 1999/04/23 15:40:56 perry Exp $ */
+/* $OpenBSD: icsphy.c,v 1.6 2000/08/26 20:04:17 nate Exp $ */
+/* $NetBSD: icsphy.c,v 1.17 2000/02/02 23:34:56 thorpej Exp $ */
/*-
* Copyright (c) 1998, 1999 The NetBSD Foundation, Inc.
@@ -90,10 +90,10 @@
int icsphymatch __P((struct device *, void *, void *));
void icsphyattach __P((struct device *, struct device *, void *));
-int icsphydetach __P((struct device *, int));
struct cfattach icsphy_ca = {
- sizeof(struct mii_softc), icsphymatch, icsphyattach, icsphydetach
+ sizeof(struct mii_softc), icsphymatch, icsphyattach, mii_phy_detach,
+ mii_phy_activate
};
struct cfdriver icsphy_cd = {
@@ -134,22 +134,16 @@ icsphyattach(parent, self, aux)
sc->mii_inst = mii->mii_instance;
sc->mii_phy = ma->mii_phyno;
sc->mii_service = icsphy_service;
+ sc->mii_status = icsphy_status;
sc->mii_pdata = mii;
+ sc->mii_flags = mii->mii_flags;
icsphy_reset(sc);
sc->mii_capabilities =
PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
if (sc->mii_capabilities & BMSR_MEDIAMASK)
- mii_add_media(sc);
-}
-
-int
-icsphydetach(dev, flags)
- struct device *dev;
- int flags;
-{
- return (0);
+ mii_phy_add_media(sc);
}
int
@@ -161,6 +155,9 @@ icsphy_service(sc, mii, cmd)
struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
int reg;
+ if ((sc->mii_dev.dv_flags & DVF_ACTIVE) == 0)
+ return (ENXIO);
+
switch (cmd) {
case MII_POLLSTAT:
/*
@@ -187,18 +184,7 @@ icsphy_service(sc, mii, cmd)
if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
break;
- switch (IFM_SUBTYPE(ife->ifm_media)) {
- case IFM_AUTO:
- /*
- * If we're already in auto mode, just return.
- */
- if (PHY_READ(sc, MII_BMCR) & BMCR_AUTOEN)
- return (0);
- (void) mii_phy_auto(sc, 1);
- break;
- default:
- mii_phy_setmedia(sc);
- }
+ mii_phy_setmedia(sc);
break;
case MII_TICK:
@@ -208,22 +194,8 @@ icsphy_service(sc, mii, cmd)
if (IFM_INST(ife->ifm_media) != sc->mii_inst)
return (0);
- /*
- * Only used for autonegotiation.
- */
- if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO)
+ if (mii_phy_tick(sc) == EJUSTRETURN)
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;
case MII_DOWN:
@@ -232,13 +204,10 @@ icsphy_service(sc, mii, cmd)
}
/* Update the media status. */
- icsphy_status(sc);
+ mii_phy_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;
- }
+ mii_phy_update(sc, cmd);
return (0);
}
diff --git a/sys/dev/mii/inphy.c b/sys/dev/mii/inphy.c
index 938e283f04b..2d6b5c9b614 100644
--- a/sys/dev/mii/inphy.c
+++ b/sys/dev/mii/inphy.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: inphy.c,v 1.5 1999/12/07 22:01:30 jason Exp $ */
-/* $NetBSD: inphy.c,v 1.10.6.1 1999/04/23 15:39:09 perry Exp $ */
+/* $OpenBSD: inphy.c,v 1.6 2000/08/26 20:04:17 nate Exp $ */
+/* $NetBSD: inphy.c,v 1.18 2000/02/02 23:34:56 thorpej Exp $ */
/*-
* Copyright (c) 1998, 1999 The NetBSD Foundation, Inc.
@@ -93,7 +93,8 @@ int inphymatch __P((struct device *, void *, void *));
void inphyattach __P((struct device *, struct device *, void *));
struct cfattach inphy_ca = {
- sizeof(struct mii_softc), inphymatch, inphyattach
+ sizeof(struct mii_softc), inphymatch, inphyattach, mii_phy_detach,
+ mii_phy_activate
};
struct cfdriver inphy_cd = {
@@ -133,21 +134,16 @@ inphyattach(parent, self, aux)
sc->mii_inst = mii->mii_instance;
sc->mii_phy = ma->mii_phyno;
sc->mii_service = inphy_service;
+ sc->mii_status = inphy_status;
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;
+ sc->mii_flags = mii->mii_flags;
mii_phy_reset(sc);
sc->mii_capabilities =
PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
if (sc->mii_capabilities & BMSR_MEDIAMASK)
- mii_add_media(sc);
+ mii_phy_add_media(sc);
}
int
@@ -159,6 +155,9 @@ inphy_service(sc, mii, cmd)
struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
int reg;
+ if ((sc->mii_dev.dv_flags & DVF_ACTIVE) == 0)
+ return (ENXIO);
+
switch (cmd) {
case MII_POLLSTAT:
/*
@@ -185,18 +184,7 @@ inphy_service(sc, mii, cmd)
if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
break;
- switch (IFM_SUBTYPE(ife->ifm_media)) {
- case IFM_AUTO:
- /*
- * If we're already in auto mode, just return.
- */
- if (PHY_READ(sc, MII_BMCR) & BMCR_AUTOEN)
- return (0);
- (void) mii_phy_auto(sc, 1);
- break;
- default:
- mii_phy_setmedia(sc);
- }
+ mii_phy_setmedia(sc);
break;
case MII_TICK:
@@ -206,37 +194,7 @@ inphy_service(sc, mii, cmd)
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);
- if (mii_phy_auto(sc, 0) == EJUSTRETURN)
+ if (mii_phy_tick(sc) == EJUSTRETURN)
return (0);
break;
@@ -246,13 +204,10 @@ inphy_service(sc, mii, cmd)
}
/* Update the media status. */
- inphy_status(sc);
+ mii_phy_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;
- }
+ mii_phy_update(sc, cmd);
return (0);
}
diff --git a/sys/dev/mii/iophy.c b/sys/dev/mii/iophy.c
index fe5247da650..da3ef62bd53 100644
--- a/sys/dev/mii/iophy.c
+++ b/sys/dev/mii/iophy.c
@@ -1,8 +1,8 @@
-/* $OpenBSD: iophy.c,v 1.5 1999/12/07 22:01:30 jason Exp $ */
-/* $NetBSD: iophy.c,v 1.1 1999/09/05 00:40:27 soren Exp $ */
+/* $OpenBSD: iophy.c,v 1.6 2000/08/26 20:04:17 nate Exp $ */
+/* $NetBSD: iophy.c,v 1.8 2000/02/02 23:34:56 thorpej Exp $ */
/*
- * Copyright (c) 1998 The NetBSD Foundation, Inc.
+ * Copyright (c) 1998, 1999 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
@@ -90,12 +90,13 @@
int iophymatch __P((struct device *, void *, void *));
void iophyattach __P((struct device *, struct device *, void *));
-struct cfdriver iophy_cd = {
- NULL, "iophy", DV_DULL
+struct cfattach iophy_ca = {
+ sizeof(struct mii_softc), iophymatch, iophyattach, mii_phy_detach,
+ mii_phy_activate
};
-struct cfattach iophy_ca = {
- sizeof(struct mii_softc), iophymatch, iophyattach
+struct cfdriver iophy_cd = {
+ NULL, "iophy", DV_DULL
};
int iophy_service __P((struct mii_softc *, struct mii_data *, int));
@@ -135,21 +136,16 @@ iophyattach(parent, self, aux)
sc->mii_inst = mii->mii_instance;
sc->mii_phy = ma->mii_phyno;
sc->mii_service = iophy_service;
+ sc->mii_status = iophy_status;
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;
+ sc->mii_flags = mii->mii_flags;
mii_phy_reset(sc);
sc->mii_capabilities =
PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
if (sc->mii_capabilities & BMSR_MEDIAMASK)
- mii_add_media(sc);
+ mii_phy_add_media(sc);
}
int
@@ -161,6 +157,9 @@ iophy_service(sc, mii, cmd)
struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
int reg;
+ if ((sc->mii_dev.dv_flags & DVF_ACTIVE) == 0)
+ return (ENXIO);
+
switch (cmd) {
case MII_POLLSTAT:
/*
@@ -187,18 +186,7 @@ iophy_service(sc, mii, cmd)
if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
break;
- switch (IFM_SUBTYPE(ife->ifm_media)) {
- case IFM_AUTO:
- /*
- * If we're already in auto mode, just return.
- */
- if (PHY_READ(sc, MII_BMCR) & BMCR_AUTOEN)
- return (0);
- (void) mii_phy_auto(sc, 1);
- break;
- default:
- mii_phy_setmedia(sc);
- }
+ mii_phy_setmedia(sc);
break;
case MII_TICK:
@@ -208,37 +196,7 @@ iophy_service(sc, mii, cmd)
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);
- if (mii_phy_auto(sc, 0) == EJUSTRETURN)
+ if (mii_phy_tick(sc) == EJUSTRETURN)
return (0);
break;
@@ -248,13 +206,10 @@ iophy_service(sc, mii, cmd)
}
/* Update the media status. */
- iophy_status(sc);
+ mii_phy_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;
- }
+ mii_phy_update(sc, cmd);
return (0);
}
diff --git a/sys/dev/mii/lxtphy.c b/sys/dev/mii/lxtphy.c
index 5c290b39fe8..6b7e8ddc2dd 100644
--- a/sys/dev/mii/lxtphy.c
+++ b/sys/dev/mii/lxtphy.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: lxtphy.c,v 1.4 1999/12/07 22:01:31 jason Exp $ */
-/* $NetBSD: lxtphy.c,v 1.9.6.1 1999/04/23 15:41:43 perry Exp $ */
+/* $OpenBSD: lxtphy.c,v 1.5 2000/08/26 20:04:17 nate Exp $ */
+/* $NetBSD: lxtphy.c,v 1.19 2000/02/02 23:34:57 thorpej Exp $ */
/*-
* Copyright (c) 1998, 1999 The NetBSD Foundation, Inc.
@@ -93,7 +93,8 @@ int lxtphymatch __P((struct device *, void *, void *));
void lxtphyattach __P((struct device *, struct device *, void *));
struct cfattach lxtphy_ca = {
- sizeof(struct mii_softc), lxtphymatch, lxtphyattach
+ sizeof(struct mii_softc), lxtphymatch, lxtphyattach, mii_phy_detach,
+ mii_phy_activate
};
struct cfdriver lxtphy_cd = {
@@ -133,14 +134,16 @@ lxtphyattach(parent, self, aux)
sc->mii_inst = mii->mii_instance;
sc->mii_phy = ma->mii_phyno;
sc->mii_service = lxtphy_service;
+ sc->mii_status = lxtphy_status;
sc->mii_pdata = mii;
+ sc->mii_flags = mii->mii_flags;
mii_phy_reset(sc);
sc->mii_capabilities =
PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
if (sc->mii_capabilities & BMSR_MEDIAMASK)
- mii_add_media(sc);
+ mii_phy_add_media(sc);
}
int
@@ -152,6 +155,9 @@ lxtphy_service(sc, mii, cmd)
struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
int reg;
+ if ((sc->mii_dev.dv_flags & DVF_ACTIVE) == 0)
+ return (ENXIO);
+
switch (cmd) {
case MII_POLLSTAT:
/*
@@ -178,18 +184,7 @@ lxtphy_service(sc, mii, cmd)
if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
break;
- switch (IFM_SUBTYPE(ife->ifm_media)) {
- case IFM_AUTO:
- /*
- * If we're already in auto mode, just return.
- */
- if (PHY_READ(sc, MII_BMCR) & BMCR_AUTOEN)
- return (0);
- (void) mii_phy_auto(sc, 1);
- break;
- default:
- mii_phy_setmedia(sc);
- }
+ mii_phy_setmedia(sc);
break;
case MII_TICK:
@@ -199,38 +194,7 @@ lxtphy_service(sc, mii, cmd)
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);
- if (mii_phy_auto(sc, 0) == EJUSTRETURN)
+ if (mii_phy_tick(sc) == EJUSTRETURN)
return (0);
break;
@@ -240,13 +204,10 @@ lxtphy_service(sc, mii, cmd)
}
/* Update the media status. */
- lxtphy_status(sc);
+ mii_phy_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;
- }
+ mii_phy_update(sc, cmd);
return (0);
}
@@ -256,7 +217,7 @@ lxtphy_status(sc)
{
struct mii_data *mii = sc->mii_pdata;
struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
- int bmcr, csr;
+ int bmcr, bmsr, csr;
mii->mii_media_status = IFM_AVALID;
mii->mii_media_active = IFM_ETHER;
@@ -281,7 +242,8 @@ lxtphy_status(sc)
mii->mii_media_active |= IFM_LOOP;
if (bmcr & BMCR_AUTOEN) {
- if ((csr & CSR_ACOMP) == 0) {
+ bmsr = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR);
+ if ((bmsr & BMSR_ACOMP) == 0) {
/* Erg, still trying, I guess... */
mii->mii_media_active |= IFM_NONE;
return;
diff --git a/sys/dev/mii/mii.c b/sys/dev/mii/mii.c
index 59388fc65ae..560e3ee7c99 100644
--- a/sys/dev/mii/mii.c
+++ b/sys/dev/mii/mii.c
@@ -1,8 +1,8 @@
-/* $OpenBSD: mii.c,v 1.8 2000/04/27 07:37:13 niklas Exp $ */
-/* $NetBSD: mii.c,v 1.9 1998/11/05 04:08:02 thorpej Exp $ */
+/* $OpenBSD: mii.c,v 1.9 2000/08/26 20:04:17 nate Exp $ */
+/* $NetBSD: mii.c,v 1.19 2000/02/02 17:09:44 thorpej Exp $ */
/*-
- * Copyright (c) 1998 The NetBSD Foundation, Inc.
+ * Copyright (c) 1998, 2000 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
@@ -66,71 +66,163 @@ int mii_submatch __P((struct device *, void *, void *));
* to the network interface driver parent.
*/
void
-mii_phy_probe(parent, mii, capmask)
+mii_attach(parent, mii, capmask, phyloc, offloc, flags)
struct device *parent;
struct mii_data *mii;
- int capmask;
+ int capmask, phyloc, offloc, flags;
{
struct mii_attach_args ma;
struct mii_softc *child;
+ int bmsr, offset = 0;
+ int phymin, phymax;
- LIST_INIT(&mii->mii_phys);
+ if (phyloc != MII_PHY_ANY && offloc != MII_PHY_ANY)
+ panic("mii_attach: phyloc and offloc specified");
+
+ if (phyloc == MII_PHY_ANY) {
+ phymin = 0;
+ phymax = MII_NPHY - 1;
+ } else
+ phymin = phymax = phyloc;
+
+ if ((mii->mii_flags & MIIF_INITDONE) == 0) {
+ LIST_INIT(&mii->mii_phys);
+ mii->mii_flags |= MIIF_INITDONE;
+ }
+
+ for (ma.mii_phyno = phymin; ma.mii_phyno <= phymax; ma.mii_phyno++) {
+ /*
+ * Make sure we haven't already configured a PHY at this
+ * address. This allows mii_attach() to be called
+ * multiple times.
+ */
+ for (child = LIST_FIRST(&mii->mii_phys); child != NULL;
+ child = LIST_NEXT(child, mii_list)) {
+ if (child->mii_phy == ma.mii_phyno) {
+ /*
+ * Yes, there is already something
+ * configured at this address.
+ */
+ offset++;
+ continue;
+ }
+ }
+
+ /*
+ * Check to see if there is a PHY at this address. Note,
+ * many braindead PHYs report 0/0 in their ID registers,
+ * so we test for media in the BMSR.
+ */
+ bmsr = (*mii->mii_readreg)(parent, ma.mii_phyno, MII_BMSR);
+ if (bmsr == 0 || bmsr == 0xffff ||
+ (bmsr & BMSR_MEDIAMASK) == 0) {
+ /* Assume no PHY at this address. */
+ continue;
+ }
- for (ma.mii_phyno = 0; ma.mii_phyno < MII_NPHY; ma.mii_phyno++) {
/*
- * Check to see if there is a PHY at this address. If
- * the register contains garbage, assume no.
+ * There is a PHY at this address. If we were given an
+ * `offset' locator, skip this PHY if it doesn't match.
+ */
+ if (offloc != MII_OFFSET_ANY && offloc != offset) {
+ offset++;
+ continue;
+ }
+
+ /*
+ * Extract the IDs. Braindead PHYs will be handled by
+ * the `ukphy' driver, as we have no ID information to
+ * match on.
*/
ma.mii_id1 = (*mii->mii_readreg)(parent, ma.mii_phyno,
MII_PHYIDR1);
ma.mii_id2 = (*mii->mii_readreg)(parent, ma.mii_phyno,
MII_PHYIDR2);
- if ((ma.mii_id1 == 0 || ma.mii_id1 == 0xffff) &&
- (ma.mii_id2 == 0 || ma.mii_id2 == 0xffff)) {
- /*
- * ARGH!! 3Com internal PHYs report 0/0 in their
- * ID registers! If we spot this, check to see
- * if the BMSR has reasonable data in it.
- * And if that wasn't enough there are PHYs
- * reporting 0xffff/0xffff too.
- */
- if ((MII_OUI(ma.mii_id1, ma.mii_id2) == 0 &&
- MII_MODEL(ma.mii_id2) == 0) ||
- (MII_OUI(ma.mii_id1, ma.mii_id2) == 0x3fffff &&
- MII_MODEL(ma.mii_id2) == 0x3f)) {
- int bmsr = (*mii->mii_readreg)(parent,
- ma.mii_phyno, MII_BMSR);
- if (bmsr == 0 || bmsr == 0xffff ||
- (bmsr & BMSR_MEDIAMASK) == 0)
- continue;
- } else
- continue;
- }
ma.mii_data = mii;
ma.mii_capmask = capmask;
+ ma.mii_flags = flags;
if ((child = (struct mii_softc *)config_found_sm(parent, &ma,
mii_print, mii_submatch)) != NULL) {
/*
* Link it up in the parent's MII data.
*/
+#if defined(__NetBSD__)
+ callout_init(&child->mii_nway_ch);
+#endif
LIST_INSERT_HEAD(&mii->mii_phys, child, mii_list);
+ child->mii_offset = offset;
mii->mii_instance++;
}
+ offset++;
}
}
-int
-mii_detach(msc, flags)
- struct mii_softc *msc;
- int flags;
+void
+mii_activate(mii, act, phyloc, offloc)
+ struct mii_data *mii;
+ enum devact act;
+ int phyloc, offloc;
+{
+ struct mii_softc *child;
+
+ if (phyloc != MII_PHY_ANY && offloc != MII_PHY_ANY)
+ panic("mii_activate: phyloc and offloc specified");
+
+ if ((mii->mii_flags & MIIF_INITDONE) == 0)
+ return;
+
+ for (child = LIST_FIRST(&mii->mii_phys);
+ child != NULL; child = LIST_NEXT(child, mii_list)) {
+ if (phyloc != MII_PHY_ANY || offloc != MII_OFFSET_ANY) {
+ if (phyloc != MII_PHY_ANY &&
+ phyloc != child->mii_phy)
+ continue;
+ if (offloc != MII_OFFSET_ANY &&
+ offloc != child->mii_offset)
+ continue;
+ }
+ switch (act) {
+ case DVACT_ACTIVATE:
+ panic("mii_activate: DVACT_ACTIVATE");
+ break;
+
+ case DVACT_DEACTIVATE:
+ if (config_deactivate(&child->mii_dev) != 0)
+ panic("%s: config_activate(%d) failed\n",
+ child->mii_dev.dv_xname, act);
+ }
+ }
+}
+
+void
+mii_detach(mii, phyloc, offloc)
+ struct mii_data *mii;
+ int phyloc, offloc;
{
- LIST_REMOVE(msc, mii_list);
- /* XXX The following condition should always be true. */
- if (msc->mii_inst == msc->mii_pdata->mii_instance - 1)
- msc->mii_pdata->mii_instance--;
- return config_detach(&msc->mii_dev, flags);
+ struct mii_softc *child, *nchild;
+
+ if (phyloc != MII_PHY_ANY && offloc != MII_PHY_ANY)
+ panic("mii_detach: phyloc and offloc specified");
+
+ if ((mii->mii_flags & MIIF_INITDONE) == 0)
+ return;
+
+ for (child = LIST_FIRST(&mii->mii_phys);
+ child != NULL; child = nchild) {
+ nchild = LIST_NEXT(child, mii_list);
+ if (phyloc != MII_PHY_ANY || offloc != MII_OFFSET_ANY) {
+ if (phyloc != MII_PHY_ANY &&
+ phyloc != child->mii_phy)
+ continue;
+ if (offloc != MII_OFFSET_ANY &&
+ offloc != child->mii_offset)
+ continue;
+ }
+ LIST_REMOVE(child, mii_list);
+ (void) config_detach(&child->mii_dev, DETACH_FORCE);
+ }
}
int
@@ -223,10 +315,10 @@ mii_pollstat(mii)
void
mii_down(mii)
struct mii_data *mii;
-{
+{
struct mii_softc *child;
-
+
for (child = LIST_FIRST(&mii->mii_phys); child != NULL;
child = LIST_NEXT(child, mii_list))
(void) (*child->mii_service)(child, mii, MII_DOWN);
-}
+}
diff --git a/sys/dev/mii/mii.h b/sys/dev/mii/mii.h
index 798bd488e6d..ead15f2bc5d 100644
--- a/sys/dev/mii/mii.h
+++ b/sys/dev/mii/mii.h
@@ -1,5 +1,5 @@
-/* $OpenBSD: mii.h,v 1.1 1998/09/10 17:17:33 jason Exp $ */
-/* $NetBSD: mii.h,v 1.1 1998/08/10 23:55:17 thorpej Exp $ */
+/* $OpenBSD: mii.h,v 1.2 2000/08/26 20:04:17 nate Exp $ */
+/* $NetBSD: mii.h,v 1.2 1999/09/29 22:49:33 thorpej Exp $ */
/*
* Copyright (c) 1997 Manuel Bouyer. All rights reserved.
@@ -68,6 +68,7 @@
#define BMSR_100TXHDX 0x2000 /* 100 base Tx half duplex capable */
#define BMSR_10TFDX 0x1000 /* 10 base T full duplex capable */
#define BMSR_10THDX 0x0800 /* 10 base T half duplex capable */
+#define BMSR_MFPS 0x0040 /* MII Frame Preamble Suppression */
#define BMSR_ACOMP 0x0020 /* Autonegotiation complete */
#define BMSR_RFAULT 0x0010 /* Link partner fault */
#define BMSR_ANEG 0x0008 /* Autonegotiation capable */
@@ -99,6 +100,7 @@
#define ANAR_NP 0x8000 /* Next page (ro) */
#define ANAR_ACK 0x4000 /* link partner abilities acknowledged (ro) */
#define ANAR_RF 0x2000 /* remote fault (ro) */
+#define ANAR_FC 0x0400 /* local device supports PAUSE */
#define ANAR_T4 0x0200 /* local device supports 100bT4 */
#define ANAR_TX_FD 0x0100 /* local device supports 100bTx FD */
#define ANAR_TX 0x0080 /* local device supports 100bTx */
@@ -110,6 +112,7 @@
#define ANLPAR_NP 0x8000 /* Next page (ro) */
#define ANLPAR_ACK 0x4000 /* link partner accepted ACK (ro) */
#define ANLPAR_RF 0x2000 /* remote fault (ro) */
+#define ANLPAR_FC 0x0400 /* link partner supports PAUSE */
#define ANLPAR_T4 0x0200 /* link partner supports 100bT4 */
#define ANLPAR_TX_FD 0x0100 /* link partner supports 100bTx FD */
#define ANLPAR_TX 0x0080 /* link partner supports 100bTx */
diff --git a/sys/dev/mii/mii_physubr.c b/sys/dev/mii/mii_physubr.c
index fdd73799975..00cf21dc32e 100644
--- a/sys/dev/mii/mii_physubr.c
+++ b/sys/dev/mii/mii_physubr.c
@@ -1,8 +1,8 @@
-/* $OpenBSD: mii_physubr.c,v 1.4 2000/06/30 01:02:33 art Exp $ */
-/* $NetBSD: mii_physubr.c,v 1.2.6.1 1999/04/23 15:40:26 perry Exp $ */
+/* $OpenBSD: mii_physubr.c,v 1.5 2000/08/26 20:04:17 nate Exp $ */
+/* $NetBSD: mii_physubr.c,v 1.16 2000/03/15 20:34:43 thorpej Exp $ */
/*-
- * Copyright (c) 1998, 1999 The NetBSD Foundation, Inc.
+ * Copyright (c) 1998, 1999, 2000 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
@@ -51,6 +51,7 @@
#include <net/if.h>
#include <net/if_media.h>
+#include <net/route.h>
#include <dev/mii/mii.h>
#include <dev/mii/miivar.h>
@@ -64,7 +65,7 @@ const struct mii_media mii_media_table[] = {
{ BMCR_FDX, ANAR_CSMA|ANAR_10_FD }, /* 10baseT-FDX */
{ BMCR_S100, ANAR_CSMA|ANAR_T4 }, /* 100baseT4 */
{ BMCR_S100, ANAR_CSMA|ANAR_TX }, /* 100baseTX */
- { BMCR_S100|BMCR_FDX, ANAR_CSMA|ANAR_TX_FD }, /* 100baseTX-FDX */
+ { BMCR_S100|BMCR_FDX, ANAR_CSMA|ANAR_TX_FD }, /* 100baseTX-FDX */
};
void mii_phy_auto_timeout __P((void *));
@@ -73,10 +74,16 @@ void
mii_phy_setmedia(sc)
struct mii_softc *sc;
{
- struct mii_data*mii = sc->mii_pdata;
+ struct mii_data *mii = sc->mii_pdata;
struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
int bmcr, anar;
+ if (IFM_SUBTYPE(ife->ifm_media) == IFM_AUTO) {
+ if ((PHY_READ(sc, MII_BMCR) & BMCR_AUTOEN) == 0)
+ (void) mii_phy_auto(sc, 1);
+ return;
+ }
+
/*
* Table index is stored in the media entry.
*/
@@ -97,28 +104,24 @@ mii_phy_setmedia(sc)
}
int
-mii_phy_auto(mii, waitfor)
- struct mii_softc *mii;
+mii_phy_auto(sc, waitfor)
+ struct mii_softc *sc;
+ int waitfor;
{
int bmsr, i;
- if ((mii->mii_flags & MIIF_DOINGAUTO) == 0) {
- PHY_WRITE(mii, MII_ANAR,
- BMSR_MEDIA_TO_ANAR(mii->mii_capabilities) | ANAR_CSMA);
- PHY_WRITE(mii, MII_BMCR, BMCR_AUTOEN | BMCR_STARTNEG);
+ if ((sc->mii_flags & MIIF_DOINGAUTO) == 0) {
+ PHY_WRITE(sc, MII_ANAR,
+ BMSR_MEDIA_TO_ANAR(sc->mii_capabilities) | ANAR_CSMA);
+ PHY_WRITE(sc, MII_BMCR, BMCR_AUTOEN | BMCR_STARTNEG);
}
if (waitfor) {
/* Wait 500ms for it to complete. */
for (i = 0; i < 500; i++) {
- if ((bmsr = PHY_READ(mii, MII_BMSR)) & BMSR_ACOMP)
+ if ((bmsr = PHY_READ(sc, MII_BMSR)) & BMSR_ACOMP)
return (0);
delay(1000);
-#if 0
- if ((bmsr & BMSR_ACOMP) == 0)
- printf("%s: autonegotiation failed to complete\n",
- mii->mii_dev.dv_xname);
-#endif
}
/*
@@ -134,10 +137,10 @@ mii_phy_auto(mii, waitfor)
* the tick handler driving autonegotiation. Don't want 500ms
* delays all the time while the system is running!
*/
- if ((mii->mii_flags & MIIF_DOINGAUTO) == 0) {
- mii->mii_flags |= MIIF_DOINGAUTO;
- timeout_set(&mii->mii_phy_timo, mii_phy_auto_timeout, mii);
- timeout_add(&mii->mii_phy_timo, hz / 2);
+ if ((sc->mii_flags & MIIF_DOINGAUTO) == 0) {
+ sc->mii_flags |= MIIF_DOINGAUTO;
+ timeout_set(&sc->mii_phy_timo, mii_phy_auto_timeout, sc);
+ timeout_add(&sc->mii_phy_timo, hz / 2);
}
return (EJUSTRETURN);
}
@@ -146,41 +149,94 @@ void
mii_phy_auto_timeout(arg)
void *arg;
{
- struct mii_softc *mii = arg;
+ struct mii_softc *sc = arg;
int s, bmsr;
+ if ((sc->mii_dev.dv_flags & DVF_ACTIVE) == 0)
+ return;
+
s = splnet();
- mii->mii_flags &= ~MIIF_DOINGAUTO;
- bmsr = PHY_READ(mii, MII_BMSR);
+ sc->mii_flags &= ~MIIF_DOINGAUTO;
+ bmsr = PHY_READ(sc, MII_BMSR);
/* Update the media status. */
- (void) (*mii->mii_service)(mii, mii->mii_pdata, MII_POLLSTAT);
+ (void) (*sc->mii_service)(sc, sc->mii_pdata, MII_POLLSTAT);
splx(s);
}
+int
+mii_phy_tick(sc)
+ struct mii_softc *sc;
+{
+ struct mii_data *mii = sc->mii_pdata;
+ struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
+ int reg;
+
+ /* Just bail now if the interface is down. */
+ if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
+ return (EJUSTRETURN);
+
+ /*
+ * If we're not doing autonegotiation, we don't need to do
+ * any extra work here. However, we need to check the link
+ * status so we can generate an announcement if the status
+ * changes.
+ */
+ if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO)
+ return (0);
+
+ /* Read the status register twice; BMSR_LINK is latch-low. */
+ reg = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR);
+ if (reg & BMSR_LINK) {
+ /*
+ * See above.
+ */
+ return (0);
+ }
+
+ /*
+ * Only retry autonegotiation every 5 seconds.
+ */
+ if (++sc->mii_ticks != 5)
+ return (EJUSTRETURN);
+
+ sc->mii_ticks = 0;
+ mii_phy_reset(sc);
+
+ if (mii_phy_auto(sc, 0) == EJUSTRETURN)
+ return (EJUSTRETURN);
+
+ /*
+ * Might need to generate a status message if autonegotiation
+ * failed.
+ */
+ return (0);
+}
+
void
-mii_phy_reset(mii)
- struct mii_softc *mii;
+mii_phy_reset(sc)
+ struct mii_softc *sc;
{
int reg, i;
- if (mii->mii_flags & MIIF_NOISOLATE)
+ if (sc->mii_flags & MIIF_NOISOLATE)
reg = BMCR_RESET;
else
reg = BMCR_RESET | BMCR_ISO;
- PHY_WRITE(mii, MII_BMCR, reg);
+ PHY_WRITE(sc, MII_BMCR, reg);
/* Wait 100ms for it to complete. */
for (i = 0; i < 100; i++) {
- reg = PHY_READ(mii, MII_BMCR);
+ reg = PHY_READ(sc, MII_BMCR);
if ((reg & BMCR_RESET) == 0)
break;
delay(1000);
}
- if (mii->mii_inst != 0 && ((mii->mii_flags & MIIF_NOISOLATE) == 0))
- PHY_WRITE(mii, MII_BMCR, reg | BMCR_ISO);
+ if (sc->mii_inst != 0 && ((sc->mii_flags & MIIF_NOISOLATE) == 0))
+ PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO);
}
+
void
mii_phy_down(sc)
struct mii_softc *sc;
@@ -191,18 +247,86 @@ mii_phy_down(sc)
}
}
+
+void
+mii_phy_status(sc)
+ struct mii_softc *sc;
+{
+
+ (*sc->mii_status)(sc);
+}
+
+void
+mii_phy_update(sc, cmd)
+ struct mii_softc *sc;
+ int cmd;
+{
+ struct mii_data *mii = sc->mii_pdata;
+
+ if (sc->mii_media_active != mii->mii_media_active ||
+ sc->mii_media_status != mii->mii_media_status ||
+ cmd == MII_MEDIACHG) {
+ (*mii->mii_statchg)(sc->mii_dev.dv_parent);
+ mii_phy_statusmsg(sc);
+ sc->mii_media_active = mii->mii_media_active;
+ sc->mii_media_status = mii->mii_media_status;
+ }
+}
+
+void
+mii_phy_statusmsg(sc)
+ struct mii_softc *sc;
+{
+ struct mii_data *mii = sc->mii_pdata;
+ struct ifnet *ifp = mii->mii_ifp;
+ int s, baudrate, link_state, announce = 0;
+
+ if (mii->mii_media_status & IFM_AVALID) {
+ if (mii->mii_media_status & IFM_ACTIVE)
+ link_state = LINK_STATE_UP;
+ else
+ link_state = LINK_STATE_DOWN;
+ } else
+ link_state = LINK_STATE_UNKNOWN;
+
+ baudrate = ifmedia_baudrate(mii->mii_media_active);
+
+ if (link_state != ifp->if_link_state) {
+ ifp->if_link_state = link_state;
+ /*
+ * XXX Right here we'd like to notify protocols
+ * XXX that the link status has changed, so that
+ * XXX e.g. Duplicate Address Detection can restart.
+ */
+ announce = 1;
+ }
+
+ if (baudrate != ifp->if_baudrate) {
+ ifp->if_baudrate = baudrate;
+ announce = 1;
+ }
+
+ if (announce) {
+ s = splimp(); /* XXX Should be splnet() */
+ rt_ifmsg(ifp);
+ splx(s);
+ }
+}
+
/*
* Initialize generic PHY media based on BMSR, called when a PHY is
* attached. We expect to be set up to print a comma-separated list
* of media names. Does not print a newline.
*/
void
-mii_add_media(sc)
+mii_phy_add_media(sc)
struct mii_softc *sc;
{
struct mii_data *mii = sc->mii_pdata;
+ const char *sep = "";
#define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL)
+#define PRINT(s) printf("%s%s", sep, s); sep = ", "
if ((sc->mii_flags & MIIF_NOISOLATE) == 0)
ADD(IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, sc->mii_inst),
@@ -216,23 +340,28 @@ mii_add_media(sc)
ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, IFM_LOOP,
sc->mii_inst), MII_MEDIA_10_T);
#endif
+ PRINT("10baseT");
}
-
- if (sc->mii_capabilities & BMSR_10TFDX)
+ if (sc->mii_capabilities & BMSR_10TFDX) {
ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, IFM_FDX, sc->mii_inst),
MII_MEDIA_10_T_FDX);
+ PRINT("10baseT-FDX");
+ }
if (sc->mii_capabilities & BMSR_100TXHDX) {
ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, 0, sc->mii_inst),
MII_MEDIA_100_TX);
#if 0
if ((sc->mii_flags & MIIF_NOLOOP) == 0)
- ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_T4, IFM_LOOP,
- sc->mii_inst), MII_MEDIA_100_T4);
+ ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_LOOP,
+ sc->mii_inst), MII_MEDIA_100_TX);
#endif
+ PRINT("100baseTX");
}
- if (sc->mii_capabilities & BMSR_100TXFDX)
+ if (sc->mii_capabilities & BMSR_100TXFDX) {
ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_FDX, sc->mii_inst),
MII_MEDIA_100_TX_FDX);
+ PRINT("100baseTX-FDX");
+ }
if (sc->mii_capabilities & BMSR_100T4) {
ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_T4, 0, sc->mii_inst),
MII_MEDIA_100_T4);
@@ -241,9 +370,57 @@ mii_add_media(sc)
ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_T4, IFM_LOOP,
sc->mii_inst), MII_MEDIA_100_T4);
#endif
+ PRINT("100baseT4");
}
- if (sc->mii_capabilities & BMSR_ANEG)
+ if (sc->mii_capabilities & BMSR_ANEG) {
ADD(IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, 0, sc->mii_inst),
MII_NMEDIA); /* intentionally invalid index */
+ PRINT("auto");
+ }
#undef ADD
+#undef PRINT
+}
+
+void
+mii_phy_delete_media(sc)
+ struct mii_softc *sc;
+{
+ struct mii_data *mii = sc->mii_pdata;
+
+ ifmedia_delete_instance(&mii->mii_media, sc->mii_inst);
+}
+
+int
+mii_phy_activate(self, act)
+ struct device *self;
+ enum devact act;
+{
+ int rv = 0;
+
+ switch (act) {
+ case DVACT_ACTIVATE:
+ rv = EOPNOTSUPP;
+ break;
+
+ case DVACT_DEACTIVATE:
+ /* Nothing special to do. */
+ break;
+ }
+
+ return (rv);
+}
+
+int
+mii_phy_detach(self, flags)
+ struct device *self;
+ int flags;
+{
+ struct mii_softc *sc = (void *) self;
+
+ if (sc->mii_flags & MIIF_DOINGAUTO)
+ untimeout(mii_phy_auto_timeout, sc);
+
+ mii_phy_delete_media(sc);
+
+ return (0);
}
diff --git a/sys/dev/mii/miivar.h b/sys/dev/mii/miivar.h
index 073670da42e..f39c4ab9cee 100644
--- a/sys/dev/mii/miivar.h
+++ b/sys/dev/mii/miivar.h
@@ -1,8 +1,8 @@
-/* $OpenBSD: miivar.h,v 1.6 2000/06/30 01:02:33 art Exp $ */
-/* $NetBSD: miivar.h,v 1.7.6.1 1999/04/23 15:40:35 perry Exp $ */
+/* $OpenBSD: miivar.h,v 1.7 2000/08/26 20:04:17 nate Exp $ */
+/* $NetBSD: miivar.h,v 1.17 2000/03/06 20:56:57 thorpej Exp $ */
/*-
- * Copyright (c) 1998, 1999 The NetBSD Foundation, Inc.
+ * Copyright (c) 1998, 1999, 2000 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
@@ -42,7 +42,12 @@
#define _DEV_MII_MIIVAR_H_
#include <sys/queue.h>
+
+#if defined(__NetBSD__)
+#include <sys/callout.h>
+#elif defined(__OpenBSD__)
#include <sys/timeout.h>
+#endif
/*
* Media Independent Interface autoconfiguration defintions.
@@ -69,6 +74,8 @@ struct mii_data {
struct ifmedia mii_media; /* media information */
struct ifnet *mii_ifp; /* pointer back to network interface */
+ int mii_flags; /* misc. flags; see below */
+
/*
* For network interfaces with multiple PHYs, a list of all
* PHYs is required so they can all be notified when a media
@@ -99,6 +106,11 @@ typedef struct mii_data mii_data_t;
typedef int (*mii_downcall_t) __P((struct mii_softc *, struct mii_data *, int));
/*
+ * This is a call back into the PHY driver made by a `status request'.
+ */
+typedef void (*mii_statusreq_t) __P((struct mii_softc *));
+
+/*
* Requests that can be made to the downcall.
*/
#define MII_TICK 1 /* once-per-second tick */
@@ -117,15 +129,24 @@ struct mii_softc {
LIST_ENTRY(mii_softc) mii_list; /* entry on parent's PHY list */
int mii_phy; /* our MII address */
+ int mii_offset; /* first PHY, second PHY, etc. */
int mii_inst; /* instance for ifmedia */
mii_downcall_t mii_service; /* our downcall */
+ mii_statusreq_t mii_status; /* our status request fn */
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 */
+
+#if defined(__NetBSD__)
+ struct callout mii_nway_ch; /* NWAY callout */
+#endif
+
+ int mii_media_active; /* last active media */
+ int mii_media_status; /* last active status */
+
struct timeout mii_phy_timo; /* timeout handle */
};
typedef struct mii_softc mii_softc_t;
@@ -139,6 +160,14 @@ typedef struct mii_softc mii_softc_t;
#define MIIF_INHERIT_MASK (MIIF_NOISOLATE|MIIF_NOLOOP)
/*
+ * Special `locators' passed to mii_attach(). If one of these is not
+ * an `any' value, we look for *that* PHY and configure it. If both
+ * are not `any', that is an error, and mii_attach() will panic.
+ */
+#define MII_OFFSET_ANY -1
+#define MII_PHY_ANY -1
+
+/*
* Used to attach a PHY to a parent.
*/
struct mii_attach_args {
@@ -147,6 +176,7 @@ struct mii_attach_args {
int mii_id1; /* PHY ID register 1 */
int mii_id2; /* PHY ID register 2 */
int mii_capmask; /* capability mask from BMSR */
+ int mii_flags; /* flags from parent */
};
typedef struct mii_attach_args mii_attach_args_t;
@@ -154,8 +184,8 @@ typedef struct mii_attach_args mii_attach_args_t;
* An array of these structures map MII media types to BMCR/ANAR settings.
*/
struct mii_media {
- int mm_bmcr; /* BMCR settings for this media */
- int mm_anar; /* ANAR settings for this media */
+ int mm_bmcr; /* BMCR settings for this media */
+ int mm_anar; /* ANAR settings for this media */
};
#define MII_MEDIA_NONE 0
@@ -176,18 +206,34 @@ struct mii_media {
(*(p)->mii_pdata->mii_writereg)((p)->mii_dev.dv_parent, \
(p)->mii_phy, (r), (v))
+#define mii_phy_probe(x, y, z) \
+ mii_attach((x), (y), (z), MII_PHY_ANY, MII_OFFSET_ANY, MIIF_NOISOLATE)
+
+void mii_attach __P((struct device *, struct mii_data *, int, int,
+ int, int));
+void mii_activate __P((struct mii_data *, enum devact, int, int));
+void mii_detach __P((struct mii_data *, int, int));
+
int mii_mediachg __P((struct mii_data *));
void mii_tick __P((struct mii_data *));
void mii_pollstat __P((struct mii_data *));
void mii_down __P((struct mii_data *));
-void mii_phy_probe __P((struct device *, struct mii_data *, int));
-int mii_detach __P((struct mii_softc *, int));
-void mii_add_media __P((struct mii_softc *));
+
+int mii_phy_activate __P((struct device *, enum devact));
+int mii_phy_detach __P((struct device *, int));
+
+void mii_phy_add_media __P((struct mii_softc *));
+void mii_phy_delete_media __P((struct mii_softc *));
void mii_phy_setmedia __P((struct mii_softc *));
int mii_phy_auto __P((struct mii_softc *, int));
void mii_phy_reset __P((struct mii_softc *));
void mii_phy_down __P((struct mii_softc *));
+int mii_phy_tick __P((struct mii_softc *));
+
+void mii_phy_status __P((struct mii_softc *));
+void mii_phy_update __P((struct mii_softc *, int));
+void mii_phy_statusmsg __P((struct mii_softc *));
void ukphy_status __P((struct mii_softc *));
#endif /* _KERNEL */
diff --git a/sys/dev/mii/mtdphy.c b/sys/dev/mii/mtdphy.c
index 67086f5d24c..803b88c381a 100644
--- a/sys/dev/mii/mtdphy.c
+++ b/sys/dev/mii/mtdphy.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mtdphy.c,v 1.4 1999/12/07 22:01:31 jason Exp $ */
+/* $OpenBSD: mtdphy.c,v 1.5 2000/08/26 20:04:18 nate Exp $ */
/*
* Copyright (c) 1998, 1999 Jason L. Wright (jason@thought.net)
@@ -55,7 +55,8 @@ int mtdphymatch __P((struct device *, void *, void *));
void mtdphyattach __P((struct device *, struct device *, void *));
struct cfattach mtdphy_ca = {
- sizeof(struct mii_softc), mtdphymatch, mtdphyattach
+ sizeof(struct mii_softc), mtdphymatch, mtdphyattach, mii_phy_detach,
+ mii_phy_activate
};
struct cfdriver mtdphy_cd = {
@@ -93,14 +94,16 @@ mtdphyattach(parent, self, aux)
sc->mii_inst = mii->mii_instance;
sc->mii_phy = ma->mii_phyno;
sc->mii_service = mtdphy_service;
+ sc->mii_status = ukphy_status;
sc->mii_pdata = mii;
+ sc->mii_flags = mii->mii_flags;
mii_phy_reset(sc);
sc->mii_capabilities =
PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
if (sc->mii_capabilities & BMSR_MEDIAMASK)
- mii_add_media(sc);
+ mii_phy_add_media(sc);
}
int
@@ -112,6 +115,9 @@ mtdphy_service(sc, mii, cmd)
struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
int reg;
+ if ((sc->mii_dev.dv_flags & DVF_ACTIVE) == 0)
+ return (ENXIO);
+
switch (cmd) {
case MII_POLLSTAT:
/*
@@ -134,19 +140,7 @@ mtdphy_service(sc, mii, cmd)
if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
break;
- switch (IFM_SUBTYPE(ife->ifm_media)) {
- case IFM_AUTO:
- /*
- * If we're already in auto mode, just return.
- */
- if (PHY_READ(sc, MII_BMCR) & BMCR_AUTOEN)
- return (0);
- (void) mii_phy_auto(sc, 1);
- break;
-
- default:
- mii_phy_setmedia(sc);
- }
+ mii_phy_setmedia(sc);
break;
case MII_TICK:
@@ -156,22 +150,8 @@ mtdphy_service(sc, mii, cmd)
if (IFM_INST(ife->ifm_media) != sc->mii_inst)
return (0);
- /*
- * Only used for autonegotiation.
- */
- if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO)
+ if (mii_phy_tick(sc) == EJUSTRETURN)
return (0);
-
- /*
- * Is the interface even up?
- */
- if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
- return (0);
-
- /*
- * The MTD972 autonegotiation doesn't need to be
- * kicked; it continues in the background.
- */
break;
case MII_DOWN:
@@ -180,12 +160,9 @@ mtdphy_service(sc, mii, cmd)
}
/* Update the media status. */
- ukphy_status(sc);
+ mii_phy_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;
- }
+ mii_phy_update(sc, cmd);
return (0);
}
diff --git a/sys/dev/mii/nsphy.c b/sys/dev/mii/nsphy.c
index 509023f200a..be76f77c46f 100644
--- a/sys/dev/mii/nsphy.c
+++ b/sys/dev/mii/nsphy.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: nsphy.c,v 1.8 2000/01/18 04:20:49 jason Exp $ */
-/* $NetBSD: nsphy.c,v 1.18 1999/07/14 23:57:36 thorpej Exp $ */
+/* $OpenBSD: nsphy.c,v 1.9 2000/08/26 20:04:18 nate Exp $ */
+/* $NetBSD: nsphy.c,v 1.25 2000/02/02 23:34:57 thorpej Exp $ */
/*-
* Copyright (c) 1998, 1999 The NetBSD Foundation, Inc.
@@ -93,7 +93,8 @@ int nsphymatch __P((struct device *, void *, void *));
void nsphyattach __P((struct device *, struct device *, void *));
struct cfattach nsphy_ca = {
- sizeof(struct mii_softc), nsphymatch, nsphyattach
+ sizeof(struct mii_softc), nsphymatch, nsphyattach, mii_phy_detach,
+ mii_phy_activate
};
struct cfdriver nsphy_cd = {
@@ -135,21 +136,16 @@ nsphyattach(parent, self, aux)
sc->mii_inst = mii->mii_instance;
sc->mii_phy = ma->mii_phyno;
sc->mii_service = nsphy_service;
+ sc->mii_status = nsphy_status;
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;
+ sc->mii_flags = mii->mii_flags;
nsphy_reset(sc);
sc->mii_capabilities =
PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
if (sc->mii_capabilities & BMSR_MEDIAMASK)
- mii_add_media(sc);
+ mii_phy_add_media(sc);
}
int
@@ -161,6 +157,9 @@ nsphy_service(sc, mii, cmd)
struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
int reg;
+ if ((sc->mii_dev.dv_flags & DVF_ACTIVE) == 0)
+ return (ENXIO);
+
switch (cmd) {
case MII_POLLSTAT:
/*
@@ -217,18 +216,7 @@ nsphy_service(sc, mii, cmd)
PHY_WRITE(sc, MII_NSPHY_PCR, reg);
- 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, 1);
- break;
- default:
- mii_phy_setmedia(sc);
- }
+ mii_phy_setmedia(sc);
break;
case MII_TICK:
@@ -278,13 +266,10 @@ nsphy_service(sc, mii, cmd)
}
/* Update the media status. */
- nsphy_status(sc);
+ mii_phy_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;
- }
+ mii_phy_update(sc, cmd);
return (0);
}
diff --git a/sys/dev/mii/nsphyter.c b/sys/dev/mii/nsphyter.c
index 566af96a2a7..493856296df 100644
--- a/sys/dev/mii/nsphyter.c
+++ b/sys/dev/mii/nsphyter.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: nsphyter.c,v 1.2 2000/02/26 03:42:20 jason Exp $ */
-/* $NetBSD: nsphyter.c,v 1.1 1999/12/07 19:36:37 thorpej Exp $ */
+/* $OpenBSD: nsphyter.c,v 1.3 2000/08/26 20:04:18 nate Exp $ */
+/* $NetBSD: nsphyter.c,v 1.5 2000/02/02 23:34:57 thorpej Exp $ */
/*-
* Copyright (c) 1998, 1999 The NetBSD Foundation, Inc.
@@ -93,7 +93,8 @@ int nsphytermatch __P((struct device *, void *, void *));
void nsphyterattach __P((struct device *, struct device *, void *));
struct cfattach nsphyter_ca = {
- sizeof(struct mii_softc), nsphytermatch, nsphyterattach
+ sizeof(struct mii_softc), nsphytermatch, nsphyterattach,
+ mii_phy_detach, mii_phy_activate
};
struct cfdriver nsphyter_cd = {
@@ -133,16 +134,16 @@ nsphyterattach(parent, self, aux)
sc->mii_inst = mii->mii_instance;
sc->mii_phy = ma->mii_phyno;
sc->mii_service = nsphyter_service;
+ sc->mii_status = nsphyter_status;
sc->mii_pdata = mii;
+ sc->mii_flags = mii->mii_flags;
mii_phy_reset(sc);
sc->mii_capabilities =
PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
- if ((sc->mii_capabilities & BMSR_MEDIAMASK) == 0)
- printf("no media present");
- else
- mii_add_media(sc);
+ if (sc->mii_capabilities & BMSR_MEDIAMASK)
+ mii_phy_add_media(sc);
}
int
@@ -154,6 +155,9 @@ nsphyter_service(sc, mii, cmd)
struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
int reg;
+ if ((sc->mii_dev.dv_flags & DVF_ACTIVE) == 0)
+ return (ENXIO);
+
switch (cmd) {
case MII_POLLSTAT:
/*
@@ -180,18 +184,7 @@ nsphyter_service(sc, mii, cmd)
if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
break;
- switch (IFM_SUBTYPE(ife->ifm_media)) {
- case IFM_AUTO:
- /*
- * If we're already in auto mode, just return.
- */
- if (PHY_READ(sc, MII_BMCR) & BMCR_AUTOEN)
- return (0);
- (void) mii_phy_auto(sc, 1);
- break;
- default:
- mii_phy_setmedia(sc);
- }
+ mii_phy_setmedia(sc);
break;
case MII_TICK:
@@ -201,37 +194,7 @@ nsphyter_service(sc, mii, cmd)
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);
- if (mii_phy_auto(sc, 0) == EJUSTRETURN)
+ if (mii_phy_tick(sc) == EJUSTRETURN)
return (0);
break;
@@ -241,13 +204,10 @@ nsphyter_service(sc, mii, cmd)
}
/* Update the media status. */
- nsphyter_status(sc);
+ mii_phy_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;
- }
+ mii_phy_update(sc, cmd);
return (0);
}
diff --git a/sys/dev/mii/qsphy.c b/sys/dev/mii/qsphy.c
index 8bc841649a8..48b7404dab3 100644
--- a/sys/dev/mii/qsphy.c
+++ b/sys/dev/mii/qsphy.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: qsphy.c,v 1.5 1999/12/07 22:01:32 jason Exp $ */
-/* $NetBSD: qsphy.c,v 1.11.6.1 1999/04/23 15:39:21 perry Exp $ */
+/* $OpenBSD: qsphy.c,v 1.6 2000/08/26 20:04:18 nate Exp $ */
+/* $NetBSD: qsphy.c,v 1.19 2000/02/02 23:34:57 thorpej Exp $ */
/*-
* Copyright (c) 1998, 1999 The NetBSD Foundation, Inc.
@@ -92,7 +92,8 @@ int qsphymatch __P((struct device *, void *, void *));
void qsphyattach __P((struct device *, struct device *, void *));
struct cfattach qsphy_ca = {
- sizeof(struct mii_softc), qsphymatch, qsphyattach
+ sizeof(struct mii_softc), qsphymatch, qsphyattach, mii_phy_detach,
+ mii_phy_activate
};
struct cfdriver qsphy_cd = {
@@ -133,14 +134,16 @@ qsphyattach(parent, self, aux)
sc->mii_inst = mii->mii_instance;
sc->mii_phy = ma->mii_phyno;
sc->mii_service = qsphy_service;
+ sc->mii_status = qsphy_status;
sc->mii_pdata = mii;
+ sc->mii_flags = mii->mii_flags;
qsphy_reset(sc);
sc->mii_capabilities =
PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
if (sc->mii_capabilities & BMSR_MEDIAMASK)
- mii_add_media(sc);
+ mii_phy_add_media(sc);
}
int
@@ -152,6 +155,9 @@ qsphy_service(sc, mii, cmd)
struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
int reg;
+ if ((sc->mii_dev.dv_flags & DVF_ACTIVE) == 0)
+ return (ENXIO);
+
switch (cmd) {
case MII_POLLSTAT:
/*
@@ -178,18 +184,7 @@ qsphy_service(sc, mii, cmd)
if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
break;
- switch (IFM_SUBTYPE(ife->ifm_media)) {
- case IFM_AUTO:
- /*
- * If we're already in auto mode, just return.
- */
- if (PHY_READ(sc, MII_BMCR) & BMCR_AUTOEN)
- return (0);
- (void) mii_phy_auto(sc, 1);
- break;
- default:
- mii_phy_setmedia(sc);
- }
+ mii_phy_setmedia(sc);
break;
case MII_TICK:
@@ -199,22 +194,8 @@ qsphy_service(sc, mii, cmd)
if (IFM_INST(ife->ifm_media) != sc->mii_inst)
return (0);
- /*
- * Only used for autonegotiation.
- */
- if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO)
+ if (mii_phy_tick(sc) == EJUSTRETURN)
return (0);
-
- /*
- * Is the interface even up?
- */
- if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
- return (0);
-
- /*
- * The QS6612's autonegotiation doesn't need to be
- * kicked; it continues in the background.
- */
break;
case MII_DOWN:
@@ -223,13 +204,10 @@ qsphy_service(sc, mii, cmd)
}
/* Update the media status. */
- qsphy_status(sc);
+ mii_phy_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;
- }
+ mii_phy_update(sc, cmd);
return (0);
}
diff --git a/sys/dev/mii/rlphy.c b/sys/dev/mii/rlphy.c
index 5fdd8ee8ffa..d4948d867a6 100644
--- a/sys/dev/mii/rlphy.c
+++ b/sys/dev/mii/rlphy.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rlphy.c,v 1.5 1999/12/07 22:01:32 jason Exp $ */
+/* $OpenBSD: rlphy.c,v 1.6 2000/08/26 20:04:18 nate Exp $ */
/*
* Copyright (c) 1998, 1999 Jason L. Wright (jason@thought.net)
@@ -56,7 +56,8 @@ int rlphymatch __P((struct device *, void *, void *));
void rlphyattach __P((struct device *, struct device *, void *));
struct cfattach rlphy_ca = {
- sizeof(struct mii_softc), rlphymatch, rlphyattach
+ sizeof(struct mii_softc), rlphymatch, rlphyattach, mii_phy_detach,
+ mii_phy_activate
};
struct cfdriver rlphy_cd = {
@@ -102,14 +103,16 @@ rlphyattach(parent, self, aux)
sc->mii_inst = mii->mii_instance;
sc->mii_phy = ma->mii_phyno;
sc->mii_service = rlphy_service;
+ sc->mii_status = ukphy_status;
sc->mii_pdata = mii;
+ sc->mii_flags = mii->mii_flags;
rlphy_reset(sc);
sc->mii_capabilities =
PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
if (sc->mii_capabilities & BMSR_MEDIAMASK)
- mii_add_media(sc);
+ mii_phy_add_media(sc);
}
int
@@ -120,6 +123,9 @@ rlphy_service(sc, mii, cmd)
{
struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
+ if ((sc->mii_dev.dv_flags & DVF_ACTIVE) == 0)
+ return (ENXIO);
+
/*
* Can't isolate the RTL8139 phy, so it has to be the only one.
*/
@@ -137,37 +143,12 @@ rlphy_service(sc, mii, cmd)
if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
break;
- switch (IFM_SUBTYPE(ife->ifm_media)) {
- case IFM_AUTO:
- /*
- * If we're already in auto mode, just return.
- */
- if (PHY_READ(sc, MII_BMCR) & BMCR_AUTOEN)
- return (0);
- (void) mii_phy_auto(sc, 1);
- break;
- default:
- mii_phy_setmedia(sc);
- }
+ mii_phy_setmedia(sc);
break;
case MII_TICK:
- /*
- * Only used for autonegotiation.
- */
- if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO)
+ if (mii_phy_tick(sc) == EJUSTRETURN)
return (0);
-
- /*
- * Is the interface even up?
- */
- if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
- return (0);
-
- /*
- * The RTL8139 autonegotiation doesn't need to be
- * kicked; it continues in the background.
- */
break;
case MII_DOWN:
@@ -176,13 +157,10 @@ rlphy_service(sc, mii, cmd)
}
/* Update the media status. */
- ukphy_status(sc);
+ mii_phy_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;
- }
+ mii_phy_update(sc, cmd);
return (0);
}
diff --git a/sys/dev/mii/sqphy.c b/sys/dev/mii/sqphy.c
index 3b13d8a5abc..523d0aaa1f3 100644
--- a/sys/dev/mii/sqphy.c
+++ b/sys/dev/mii/sqphy.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: sqphy.c,v 1.4 1999/12/07 22:01:32 jason Exp $ */
-/* $NetBSD: sqphy.c,v 1.8.6.1 1999/04/23 15:41:25 perry Exp $ */
+/* $OpenBSD: sqphy.c,v 1.5 2000/08/26 20:04:18 nate Exp $ */
+/* $NetBSD: sqphy.c,v 1.17 2000/02/02 23:34:57 thorpej Exp $ */
/*-
* Copyright (c) 1998, 1999 The NetBSD Foundation, Inc.
@@ -93,7 +93,8 @@ int sqphymatch __P((struct device *, void *, void *));
void sqphyattach __P((struct device *, struct device *, void *));
struct cfattach sqphy_ca = {
- sizeof(struct mii_softc), sqphymatch, sqphyattach
+ sizeof(struct mii_softc), sqphymatch, sqphyattach, mii_phy_detach,
+ mii_phy_activate
};
struct cfdriver sqphy_cd = {
@@ -133,14 +134,16 @@ sqphyattach(parent, self, aux)
sc->mii_inst = mii->mii_instance;
sc->mii_phy = ma->mii_phyno;
sc->mii_service = sqphy_service;
+ sc->mii_status = sqphy_status;
sc->mii_pdata = mii;
+ sc->mii_flags = mii->mii_flags;
mii_phy_reset(sc);
sc->mii_capabilities =
PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
if (sc->mii_capabilities & BMSR_MEDIAMASK)
- mii_add_media(sc);
+ mii_phy_add_media(sc);
}
int
@@ -152,6 +155,9 @@ sqphy_service(sc, mii, cmd)
struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
int reg;
+ if ((sc->mii_dev.dv_flags & DVF_ACTIVE) == 0)
+ return (ENXIO);
+
switch (cmd) {
case MII_POLLSTAT:
/*
@@ -178,18 +184,7 @@ sqphy_service(sc, mii, cmd)
if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
break;
- switch (IFM_SUBTYPE(ife->ifm_media)) {
- case IFM_AUTO:
- /*
- * If we're already in auto mode, just return.
- */
- if (PHY_READ(sc, MII_BMCR) & BMCR_AUTOEN)
- return (0);
- (void) mii_phy_auto(sc, 1);
- break;
- default:
- mii_phy_setmedia(sc);
- }
+ mii_phy_setmedia(sc);
break;
case MII_TICK:
@@ -199,37 +194,7 @@ sqphy_service(sc, mii, cmd)
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);
- if (mii_phy_auto(sc, 0) == EJUSTRETURN)
+ if (mii_phy_tick(sc) == EJUSTRETURN)
return (0);
break;
@@ -239,13 +204,10 @@ sqphy_service(sc, mii, cmd)
}
/* Update the media status. */
- sqphy_status(sc);
+ mii_phy_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;
- }
+ mii_phy_update(sc, cmd);
return (0);
}
diff --git a/sys/dev/mii/tlphy.c b/sys/dev/mii/tlphy.c
index ce92a2d8348..dada41b4bed 100644
--- a/sys/dev/mii/tlphy.c
+++ b/sys/dev/mii/tlphy.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: tlphy.c,v 1.5 1999/12/07 22:01:32 jason Exp $ */
-/* $NetBSD: tlphy.c,v 1.16.6.1 1999/04/23 15:40:13 perry Exp $ */
+/* $OpenBSD: tlphy.c,v 1.6 2000/08/26 20:04:18 nate Exp $ */
+/* $NetBSD: tlphy.c,v 1.24 2000/02/02 17:50:46 thorpej Exp $ */
/*-
* Copyright (c) 1998, 1999 The NetBSD Foundation, Inc.
@@ -105,7 +105,8 @@ struct cfdriver tlphy_cd = {
};
struct cfattach tlphy_ca = {
- sizeof(struct tlphy_softc), tlphymatch, tlphyattach
+ sizeof(struct tlphy_softc), tlphymatch, tlphyattach, mii_phy_detach,
+ mii_phy_activate
};
int tlphy_service __P((struct mii_softc *, struct mii_data *, int));
@@ -144,7 +145,9 @@ tlphyattach(parent, self, aux)
sc->sc_mii.mii_inst = mii->mii_instance;
sc->sc_mii.mii_phy = ma->mii_phyno;
sc->sc_mii.mii_service = tlphy_service;
+ sc->sc_mii.mii_status = tlphy_status;
sc->sc_mii.mii_pdata = mii;
+ sc->sc_mii.mii_flags = mii->mii_flags;
mii_phy_reset(&sc->sc_mii);
@@ -162,9 +165,22 @@ tlphyattach(parent, self, aux)
else
sc->sc_mii.mii_capabilities = 0;
+ if (sc->sc_tlphycap) {
+ if (sc->sc_tlphycap & TLPHY_MEDIA_10_2)
+ ifmedia_add(&mii->mii_media,
+ IFM_MAKEWORD(IFM_ETHER, IFM_10_2, 0,
+ sc->sc_mii.mii_inst),
+ 0, NULL);
+ else if (sc->sc_tlphycap & TLPHY_MEDIA_10_5)
+ ifmedia_add(&mii->mii_media,
+ IFM_MAKEWORD(IFM_ETHER, IFM_10_5, 0,
+ sc->sc_mii.mii_inst),
+ 0, NULL);
+ }
+ }
+
if (sc->sc_mii.mii_capabilities & BMSR_MEDIAMASK) {
- mii_add_media(mii, sc->sc_mii.mii_capabilities,
- sc->sc_mii.mii_inst);
+ mii_phy_add_media(&sc->sc_mii);
}
}
@@ -178,6 +194,9 @@ tlphy_service(self, mii, cmd)
struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
int reg;
+ if ((sc->sc_mii.mii_dev.dv_flags & DVF_ACTIVE) == 0)
+ return (ENXIO);
+
if ((sc->sc_mii.mii_flags & MIIF_DOINGAUTO) == 0 && sc->sc_need_acomp)
tlphy_acomp(sc);
@@ -237,55 +256,23 @@ tlphy_service(self, mii, cmd)
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.
- *
* XXX WHAT ABOUT CHECKING LINK ON THE BNC/AUI?!
*/
- 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_mii.mii_ticks != 5)
- return (0);
- sc->sc_mii.mii_ticks = 0;
- mii_phy_reset(&sc->sc_mii);
- if (tlphy_auto(sc, 0) == EJUSTRETURN)
+ if (mii_phy_tick(&sc->sc_mii) == EJUSTRETURN)
return (0);
break;
case MII_DOWN:
- mii_phy_down(sc);
+ mii_phy_down(&sc->sc_mii);
return (0);
}
/* Update the media status. */
- tlphy_status(sc);
+ mii_phy_status(&sc->sc_mii);
/* Callback if something changed. */
- 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_mii.mii_active = mii->mii_media_active;
- }
+ mii_phy_update(&sc->sc_mii, cmd);
return (0);
}
@@ -391,4 +378,5 @@ tlphy_acomp(sc)
return;
}
}
+ PHY_WRITE(&sc->sc_mii, MII_BMCR, 0);
}
diff --git a/sys/dev/mii/tqphy.c b/sys/dev/mii/tqphy.c
index fed0baa2cd2..7192042d13a 100644
--- a/sys/dev/mii/tqphy.c
+++ b/sys/dev/mii/tqphy.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: tqphy.c,v 1.2 2000/05/15 06:11:53 niklas Exp $ */
-/* $NetBSD: tqphy.c,v 1.4 1999/11/12 18:13:01 thorpej Exp $ */
+/* $OpenBSD: tqphy.c,v 1.3 2000/08/26 20:04:18 nate Exp $ */
+/* $NetBSD: tqphy.c,v 1.9 2000/02/02 23:34:57 thorpej Exp $ */
/*
* Copyright (c) 1998, 1999 The NetBSD Foundation, Inc.
@@ -94,7 +94,8 @@ void tqphyattach __P((struct device *, struct device *, void *));
int tqphydetach __P((struct device *, int));
struct cfattach tqphy_ca = {
- sizeof(struct mii_softc), tqphymatch, tqphyattach, tqphydetach
+ sizeof(struct mii_softc), tqphymatch, tqphyattach, mii_phy_detach,
+ mii_phy_activate
};
struct cfdriver tqphy_cd = {
@@ -137,7 +138,9 @@ tqphyattach(parent, self, aux)
sc->mii_inst = mii->mii_instance;
sc->mii_phy = ma->mii_phyno;
sc->mii_service = tqphy_service;
+ sc->mii_status = tqphy_status;
sc->mii_pdata = mii;
+ sc->mii_flags = mii->mii_flags;
/*
* Apparently, we can't do loopback on this PHY.
@@ -149,15 +152,7 @@ tqphyattach(parent, self, aux)
sc->mii_capabilities =
PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
if (sc->mii_capabilities & BMSR_MEDIAMASK)
- mii_add_media(sc);
-}
-
-int
-tqphydetach(dev, flags)
- struct device *dev;
- int flags;
-{
- return (0);
+ mii_phy_add_media(sc);
}
int
@@ -169,6 +164,9 @@ tqphy_service(sc, mii, cmd)
struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
int reg;
+ if ((sc->mii_dev.dv_flags & DVF_ACTIVE) == 0)
+ return (ENXIO);
+
switch (cmd) {
case MII_POLLSTAT:
/*
@@ -195,18 +193,7 @@ tqphy_service(sc, mii, cmd)
if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
break;
- switch (IFM_SUBTYPE(ife->ifm_media)) {
- case IFM_AUTO:
- /*
- * If we're already in auto mode, just return.
- */
- if (PHY_READ(sc, MII_BMCR) & BMCR_AUTOEN)
- return (0);
- (void) mii_phy_auto(sc, 1);
- break;
- default:
- mii_phy_setmedia(sc);
- }
+ mii_phy_setmedia(sc);
break;
case MII_TICK:
@@ -216,37 +203,7 @@ tqphy_service(sc, mii, cmd)
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);
- if (mii_phy_auto(sc, 0) == EJUSTRETURN)
+ if (mii_phy_tick(sc) == EJUSTRETURN)
return (0);
break;
@@ -256,13 +213,10 @@ tqphy_service(sc, mii, cmd)
}
/* Update the media status. */
- tqphy_status(sc);
+ mii_phy_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;
- }
+ mii_phy_update(sc, cmd);
return (0);
}
diff --git a/sys/dev/mii/txphy.c b/sys/dev/mii/txphy.c
index 25372163cea..2e78574b7ad 100644
--- a/sys/dev/mii/txphy.c
+++ b/sys/dev/mii/txphy.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: txphy.c,v 1.1 1999/12/10 21:48:20 jason Exp $ */
+/* $OpenBSD: txphy.c,v 1.2 2000/08/26 20:04:18 nate Exp $ */
/*
* Copyright (c) 1999 Jason L. Wright (jason@thought.net)
@@ -54,7 +54,8 @@ int txphymatch __P((struct device *, void *, void *));
void txphyattach __P((struct device *, struct device *, void *));
struct cfattach txphy_ca = {
- sizeof(struct mii_softc), txphymatch, txphyattach
+ sizeof(struct mii_softc), txphymatch, txphyattach, mii_phy_detach,
+ mii_phy_activate
};
struct cfdriver txphy_cd = {
@@ -92,14 +93,16 @@ txphyattach(parent, self, aux)
sc->mii_inst = mii->mii_instance;
sc->mii_phy = ma->mii_phyno;
sc->mii_service = txphy_service;
+ sc->mii_status = ukphy_status;
sc->mii_pdata = mii;
+ sc->mii_flags = mii->mii_flags;
mii_phy_reset(sc);
sc->mii_capabilities =
PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
if (sc->mii_capabilities & BMSR_MEDIAMASK)
- mii_add_media(sc);
+ mii_phy_add_media(sc);
}
int
@@ -110,6 +113,9 @@ txphy_service(sc, mii, cmd)
{
struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
+ if ((sc->mii_dev.dv_flags & DVF_ACTIVE) == 0)
+ return (ENXIO);
+
/*
* Can't isolate the RTL8139 phy, so it has to be the only one.
*/
@@ -128,36 +134,12 @@ txphy_service(sc, mii, cmd)
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, 1);
- break;
- default:
- mii_phy_setmedia(sc);
- }
+ mii_phy_setmedia(sc);
break;
case MII_TICK:
- /*
- * Only used for autonegotiation.
- */
- if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO)
+ if (mii_phy_tick(sc) == EJUSTRETURN)
return (0);
-
- /*
- * Is the interface even up?
- */
- if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
- return (0);
-
- /*
- * The TNETE2101 autonegotiation doesn't need to be
- * kicked; it continues in the background.
- */
break;
case MII_DOWN:
@@ -166,12 +148,9 @@ txphy_service(sc, mii, cmd)
}
/* Update the media status. */
- ukphy_status(sc);
+ mii_phy_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;
- }
+ mii_phy_update(sc, cmd);
return (0);
}
diff --git a/sys/dev/mii/ukphy.c b/sys/dev/mii/ukphy.c
index ee24f04f8a2..74dea9903d0 100644
--- a/sys/dev/mii/ukphy.c
+++ b/sys/dev/mii/ukphy.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: ukphy.c,v 1.6 1999/12/07 22:01:33 jason Exp $ */
-/* $NetBSD: ukphy.c,v 1.1.6.1 1999/04/23 15:39:00 perry Exp $ */
+/* $OpenBSD: ukphy.c,v 1.7 2000/08/26 20:04:18 nate Exp $ */
+/* $NetBSD: ukphy.c,v 1.9 2000/02/02 23:34:57 thorpej Exp $ */
/*-
* Copyright (c) 1998, 1999 The NetBSD Foundation, Inc.
@@ -89,7 +89,8 @@ int ukphymatch __P((struct device *, void *, void *));
void ukphyattach __P((struct device *, struct device *, void *));
struct cfattach ukphy_ca = {
- sizeof(struct mii_softc), ukphymatch, ukphyattach
+ sizeof(struct mii_softc), ukphymatch, ukphyattach, mii_phy_detach,
+ mii_phy_activate
};
struct cfdriver ukphy_cd = {
@@ -128,14 +129,25 @@ ukphyattach(parent, self, aux)
sc->mii_inst = mii->mii_instance;
sc->mii_phy = ma->mii_phyno;
sc->mii_service = ukphy_service;
+ sc->mii_status = ukphy_status;
sc->mii_pdata = mii;
+ sc->mii_flags = mii->mii_flags;
+
+ /*
+ * Don't do loopback on unknown PHYs. It might confuse some of them.
+ */
+ sc->mii_flags |= MIIF_NOLOOP;
mii_phy_reset(sc);
sc->mii_capabilities =
PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
- if (sc->mii_capabilities & BMSR_MEDIAMASK)
- mii_add_media(sc);
+ printf("%s: ", sc->mii_dev.dv_xname);
+ if ((sc->mii_capabilities & BMSR_MEDIAMASK) == 0)
+ printf("no media present");
+ else
+ mii_phy_add_media(sc);
+ printf("\n");
}
int
@@ -147,6 +159,9 @@ ukphy_service(sc, mii, cmd)
struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
int reg;
+ if ((sc->mii_dev.dv_flags & DVF_ACTIVE) == 0)
+ return (ENXIO);
+
switch (cmd) {
case MII_POLLSTAT:
/*
@@ -173,18 +188,7 @@ ukphy_service(sc, mii, cmd)
if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
break;
- switch (IFM_SUBTYPE(ife->ifm_media)) {
- case IFM_AUTO:
- /*
- * If we're already in auto mode, just return.
- */
- if (PHY_READ(sc, MII_BMCR) & BMCR_AUTOEN)
- return (0);
- (void) mii_phy_auto(sc, 1);
- break;
- default:
- mii_phy_setmedia(sc);
- }
+ mii_phy_setmedia(sc);
break;
case MII_TICK:
@@ -200,31 +204,7 @@ ukphy_service(sc, mii, cmd)
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);
- if (mii_phy_auto(sc, 0) == EJUSTRETURN)
+ if (mii_phy_tick(sc) == EJUSTRETURN)
return (0);
break;
@@ -234,12 +214,9 @@ ukphy_service(sc, mii, cmd)
}
/* Update the media status. */
- ukphy_status(sc);
+ mii_phy_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;
- }
+ mii_phy_update(sc, cmd);
return (0);
}
diff --git a/sys/net/if.h b/sys/net/if.h
index f9ec5377e43..7b40a7f117d 100644
--- a/sys/net/if.h
+++ b/sys/net/if.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: if.h,v 1.17 2000/03/22 11:28:42 itojun Exp $ */
+/* $OpenBSD: if.h,v 1.18 2000/08/26 20:04:16 nate Exp $ */
/* $NetBSD: if.h,v 1.23 1996/05/07 02:40:27 thorpej Exp $ */
/*
@@ -81,6 +81,7 @@ struct if_data {
u_char ifi_type; /* ethernet, tokenring, etc. */
u_char ifi_addrlen; /* media address length */
u_char ifi_hdrlen; /* media header length */
+ int ifi_link_state; /* current link state */
u_long ifi_mtu; /* maximum transmission unit */
u_long ifi_metric; /* routing metric (external only) */
u_long ifi_baudrate; /* linespeed */
@@ -100,6 +101,13 @@ struct if_data {
};
/*
+ * Values for if_link_state.
+ */
+#define LINK_STATE_UNKNOWN 0 /* link invalid/unknown */
+#define LINK_STATE_DOWN 1 /* link is down */
+#define LINK_STATE_UP 2 /* link is up */
+
+/*
* Structure defining a queue for a network interface.
*
* (Would like to call this struct ``if'', but C isn't PL/1.)
@@ -151,6 +159,7 @@ struct ifnet { /* and the entries */
#define if_addrlen if_data.ifi_addrlen
#define if_hdrlen if_data.ifi_hdrlen
#define if_metric if_data.ifi_metric
+#define if_link_state if_data.ifi_link_state
#define if_baudrate if_data.ifi_baudrate
#define if_ipackets if_data.ifi_ipackets
#define if_ierrors if_data.ifi_ierrors
@@ -188,6 +197,14 @@ struct ifnet { /* and the entries */
IFF_SIMPLEX|IFF_MULTICAST|IFF_ALLMULTI)
/*
+ * Some convenience macros used for setting ifi_baudrate.
+ * XXX 1000 vs. 1024? --thorpej@netbsd.org
+ */
+#define IF_Kbps(x) ((x) * 1000) /* kilobits/sec. */
+#define IF_Mbps(x) (IF_Kbps((x) * 1000)) /* megabits/sec. */
+#define IF_Gbps(x) (IF_Mbps((x) * 1000)) /* gigabits/sec. */
+
+/*
* Output queues (ifp->if_snd) and internetwork datagram level (pup level 1)
* input routines have queues of messages stored on ifqueue structures
* (defined above). Entries are added to and deleted from these structures
diff --git a/sys/net/if_media.c b/sys/net/if_media.c
index 344a080bd7b..916eebd38cf 100644
--- a/sys/net/if_media.c
+++ b/sys/net/if_media.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: if_media.c,v 1.4 2000/03/21 23:18:13 mickey Exp $ */
-/* $NetBSD: if_media.c,v 1.7 1999/11/03 23:06:35 thorpej Exp $ */
+/* $OpenBSD: if_media.c,v 1.5 2000/08/26 20:04:16 nate Exp $ */
+/* $NetBSD: if_media.c,v 1.10 2000/03/13 23:52:39 soren Exp $ */
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -117,7 +117,7 @@ ifmedia_init(ifm, dontcare_mask, change_callback, status_callback)
ifm_stat_cb_t status_callback;
{
- LIST_INIT(&ifm->ifm_list);
+ TAILQ_INIT(&ifm->ifm_list);
ifm->ifm_cur = NULL;
ifm->ifm_media = 0;
ifm->ifm_mask = dontcare_mask; /* IF don't-care bits */
@@ -157,7 +157,7 @@ ifmedia_add(ifm, mword, data, aux)
entry->ifm_data = data;
entry->ifm_aux = aux;
- LIST_INSERT_HEAD(&ifm->ifm_list, entry, ifm_list);
+ TAILQ_INSERT_TAIL(&ifm->ifm_list, entry, ifm_list);
}
/*
@@ -303,7 +303,7 @@ ifmedia_ioctl(ifp, ifr, ifm, cmd)
(*ifm->ifm_status)(ifp, ifmr);
count = 0;
- ep = LIST_FIRST(&ifm->ifm_list);
+ ep = TAILQ_FIRST(&ifm->ifm_list);
if (ifmr->ifm_count != 0) {
kptr = (int *)malloc(ifmr->ifm_count * sizeof(int),
@@ -313,7 +313,7 @@ ifmedia_ioctl(ifp, ifr, ifm, cmd)
* Get the media words from the interface's list.
*/
for (; ep != NULL && count < ifmr->ifm_count;
- ep = LIST_NEXT(ep, ifm_list), count++)
+ ep = TAILQ_NEXT(ep, ifm_list), count++)
kptr[count] = ep->ifm_media;
if (ep != NULL)
@@ -326,7 +326,7 @@ ifmedia_ioctl(ifp, ifr, ifm, cmd)
* to 0 on the first call to know how much space to
* callocate.
*/
- for (; ep != NULL; ep = LIST_NEXT(ep, ifm_list))
+ for (; ep != NULL; ep = TAILQ_NEXT(ep, ifm_list))
count++;
/*
@@ -373,8 +373,8 @@ ifmedia_match(ifm, target, mask)
match = NULL;
mask = ~mask;
- for (next = LIST_FIRST(&ifm->ifm_list); next != NULL;
- next = LIST_NEXT(next, ifm_list)) {
+ for (next = TAILQ_FIRST(&ifm->ifm_list); next != NULL;
+ next = TAILQ_NEXT(next, ifm_list)) {
if ((next->ifm_media & mask) == (target & mask)) {
#if defined(IFMEDIA_DEBUG) || defined(DIAGNOSTIC)
if (match) {
@@ -399,18 +399,40 @@ ifmedia_delete_instance(ifm, inst)
{
struct ifmedia_entry *ife, *nife;
- for (ife = LIST_FIRST(&ifm->ifm_list); ife != NULL;
+ for (ife = TAILQ_FIRST(&ifm->ifm_list); ife != NULL;
ife = nife) {
-
- nife = LIST_NEXT(ife, ifm_list);
+ nife = TAILQ_NEXT(ife, ifm_list);
if (inst == IFM_INST_ANY ||
inst == IFM_INST(ife->ifm_media)) {
- LIST_REMOVE(ife, ifm_list);
+ TAILQ_REMOVE(&ifm->ifm_list, ife, ifm_list);
free(ife, M_DEVBUF);
}
}
}
+/*
+ * Compute the interface `baudrate' from the media, for the interface
+ * metrics (used by routing daemons).
+ */
+struct ifmedia_baudrate ifmedia_baudrate_descriptions[] =
+ IFM_BAUDRATE_DESCRIPTIONS;
+
+int
+ifmedia_baudrate(mword)
+ int mword;
+{
+ int i;
+
+ for (i = 0; ifmedia_baudrate_descriptions[i].ifmb_word != 0; i++) {
+ if ((mword & (IFM_NMASK|IFM_TMASK)) ==
+ ifmedia_baudrate_descriptions[i].ifmb_word)
+ return (ifmedia_baudrate_descriptions[i].ifmb_baudrate);
+ }
+
+ /* Not known. */
+ return (0);
+}
+
#ifdef IFMEDIA_DEBUG
struct ifmedia_description ifm_type_descriptions[] =
diff --git a/sys/net/if_media.h b/sys/net/if_media.h
index 695846ff4c3..6da8fc3c53f 100644
--- a/sys/net/if_media.h
+++ b/sys/net/if_media.h
@@ -1,8 +1,8 @@
-/* $OpenBSD: if_media.h,v 1.6 2000/03/21 23:18:13 mickey Exp $ */
-/* $NetBSD: if_media.h,v 1.11 1998/08/12 23:23:29 thorpej Exp $ */
+/* $OpenBSD: if_media.h,v 1.7 2000/08/26 20:04:16 nate Exp $ */
+/* $NetBSD: if_media.h,v 1.22 2000/02/17 21:53:16 sommerfeld Exp $ */
/*-
- * Copyright (c) 1998 The NetBSD Foundation, Inc.
+ * Copyright (c) 1998, 2000 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
@@ -101,7 +101,7 @@ typedef void (*ifm_stat_cb_t) __P((struct ifnet *ifp, struct ifmediareq *req));
* In-kernel representation of a single supported media type.
*/
struct ifmedia_entry {
- LIST_ENTRY(ifmedia_entry) ifm_list;
+ TAILQ_ENTRY(ifmedia_entry) ifm_list;
int ifm_media; /* description of this media attachment */
int ifm_data; /* for driver-specific use */
void *ifm_aux; /* for driver-specific use */
@@ -115,7 +115,7 @@ struct ifmedia {
int ifm_mask; /* mask of changes we don't care about */
int ifm_media; /* current user-set media word */
struct ifmedia_entry *ifm_cur; /* currently selected media */
- LIST_HEAD(, ifmedia_entry) ifm_list; /* list of all supported media */
+ TAILQ_HEAD(, ifmedia_entry) ifm_list; /* list of all supported media */
ifm_change_cb_t ifm_change; /* media change driver callback */
ifm_stat_cb_t ifm_status; /* media status driver callback */
};
@@ -145,13 +145,15 @@ struct ifmedia_entry *ifmedia_match __P((struct ifmedia *ifm,
/* Delete all media for a given media instance */
void ifmedia_delete_instance __P((struct ifmedia *, int));
+/* Compute baudrate for a given media. */
+int ifmedia_baudrate __P((int));
#endif /*_KERNEL */
/*
* if_media Options word:
* Bits Use
* ---- -------
- * 0-4 Media variant MAX SUBTYPE == 31!
+ * 0-4 Media subtype MAX SUBTYPE == 31!
* 5-7 Media type
* 8-15 Type specific options
* 16-19 RFU
@@ -171,14 +173,13 @@ void ifmedia_delete_instance __P((struct ifmedia *, int));
#define IFM_100_T4 8 /* 100BaseT4 - 4 pair cat 3 */
#define IFM_100_VG 9 /* 100VG-AnyLAN */
#define IFM_100_T2 10 /* 100BaseT2 */
-#define IFM_1000_FX 11 /* 1000BaseFX - gigabit over fiber */
+#define IFM_1000_SX 11 /* 1000BaseSX - multi-mode fiber */
#define IFM_10_STP 12 /* 10BaseT over shielded TP */
#define IFM_10_FL 13 /* 10BaseFL - Fiber */
-#define IFM_1000_SX 14 /* 1000baseSX Multi-mode Fiber */
-#define IFM_1000_LX 15 /* 1000baseLX Single-mode Fiber */
-#define IFM_1000_CX 16 /* 1000baseCX 150ohm STP */
-#define IFM_1000_TX 17 /* 1000baseTX 4 pair cat 5 */
-#define IFM_HPNA_1 18 /* HomePNA 1.0 (1Mb/s) */
+#define IFM_1000_LX 14 /* 1000baseLX - single-mode fiber */
+#define IFM_1000_CX 15 /* 1000baseCX - 150ohm STP */
+#define IFM_1000_TX 16 /* 1000baseTX - 4 pair cat 5 */
+#define IFM_HPNA_1 17 /* HomePNA 1.0 (1Mb/s) */
/*
* Token ring
@@ -335,18 +336,20 @@ struct ifmedia_description {
{ IFM_ETHER|IFM_100_VG, "100VG" }, \
{ IFM_ETHER|IFM_100_T2, "100baseT2" }, \
{ IFM_ETHER|IFM_100_T2, "100T2" }, \
- { IFM_ETHER|IFM_1000_FX, "1000baseFX" }, \
- { IFM_ETHER|IFM_1000_FX, "1000FX" }, \
+ { IFM_ETHER|IFM_1000_SX, "1000baseSX" }, \
+ { IFM_ETHER|IFM_1000_SX, "1000SX" }, \
{ IFM_ETHER|IFM_10_STP, "10baseSTP" }, \
{ IFM_ETHER|IFM_10_STP, "STP" }, \
{ IFM_ETHER|IFM_10_STP, "10STP" }, \
{ IFM_ETHER|IFM_10_FL, "10baseFL" }, \
{ IFM_ETHER|IFM_10_FL, "FL" }, \
{ IFM_ETHER|IFM_10_FL, "10FL" }, \
- { IFM_ETHER|IFM_1000_SX, "1000baseSX" }, \
{ IFM_ETHER|IFM_1000_LX, "1000baseLX" }, \
+ { IFM_ETHER|IFM_1000_LX, "1000LX" }, \
{ IFM_ETHER|IFM_1000_CX, "1000baseCX" }, \
+ { IFM_ETHER|IFM_1000_CX, "1000CX" }, \
{ IFM_ETHER|IFM_1000_TX, "1000baseTX" }, \
+ { IFM_ETHER|IFM_1000_TX, "1000TX" }, \
{ IFM_ETHER|IFM_HPNA_1, "HomePNA1" }, \
{ IFM_ETHER|IFM_HPNA_1, "HPNA1" }, \
\
@@ -404,6 +407,50 @@ struct ifmedia_description {
}
/*
+ * Baudrate descriptions for the various media types.
+ */
+struct ifmedia_baudrate {
+ int ifmb_word; /* media word */
+ int ifmb_baudrate; /* corresponding baudrate */
+};
+
+#define IFM_BAUDRATE_DESCRIPTIONS { \
+ { IFM_ETHER|IFM_10_T, IF_Mbps(10) }, \
+ { IFM_ETHER|IFM_10_2, IF_Mbps(10) }, \
+ { IFM_ETHER|IFM_10_5, IF_Mbps(10) }, \
+ { IFM_ETHER|IFM_100_TX, IF_Mbps(100) }, \
+ { IFM_ETHER|IFM_100_FX, IF_Mbps(100) }, \
+ { IFM_ETHER|IFM_100_T4, IF_Mbps(100) }, \
+ { IFM_ETHER|IFM_100_VG, IF_Mbps(100) }, \
+ { IFM_ETHER|IFM_100_T2, IF_Mbps(100) }, \
+ { IFM_ETHER|IFM_1000_SX, IF_Mbps(1000) }, \
+ { IFM_ETHER|IFM_10_STP, IF_Mbps(10) }, \
+ { IFM_ETHER|IFM_10_FL, IF_Mbps(10) }, \
+ { IFM_ETHER|IFM_1000_LX, IF_Mbps(1000) }, \
+ { IFM_ETHER|IFM_1000_CX, IF_Mbps(1000) }, \
+ { IFM_ETHER|IFM_1000_TX, IF_Mbps(1000) }, \
+ { IFM_ETHER|IFM_HPNA_1, IF_Mbps(1) }, \
+ \
+ { IFM_TOKEN|IFM_TOK_STP4, IF_Mbps(4) }, \
+ { IFM_TOKEN|IFM_TOK_STP16, IF_Mbps(16) }, \
+ { IFM_TOKEN|IFM_TOK_UTP4, IF_Mbps(4) }, \
+ { IFM_TOKEN|IFM_TOK_UTP16, IF_Mbps(16) }, \
+ \
+ { IFM_FDDI|IFM_FDDI_SMF, IF_Mbps(100) }, \
+ { IFM_FDDI|IFM_FDDI_MMF, IF_Mbps(100) }, \
+ { IFM_FDDI|IFM_FDDI_UTP, IF_Mbps(100) }, \
+ \
+ { IFM_IEEE80211|IFM_IEEE80211_FH1, IF_Mbps(1) }, \
+ { IFM_IEEE80211|IFM_IEEE80211_FH2, IF_Mbps(2) }, \
+ { IFM_IEEE80211|IFM_IEEE80211_DS2, IF_Mbps(2) }, \
+ { IFM_IEEE80211|IFM_IEEE80211_DS5, IF_Mbps(5) }, \
+ { IFM_IEEE80211|IFM_IEEE80211_DS11, IF_Mbps(11) }, \
+ { IFM_IEEE80211|IFM_IEEE80211_DS1, IF_Mbps(1) }, \
+ \
+ { 0, 0 }, \
+}
+
+/*
* Status bit descriptions for the various media types.
*/
struct ifmedia_status_description {