Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/sbus Shuffle some code around to allow two PHYs to a...
details: https://anonhg.NetBSD.org/src/rev/c75ff928aa5a
branches: trunk
changeset: 479805:c75ff928aa5a
user: pk <pk%NetBSD.org@localhost>
date: Tue Dec 21 21:07:42 1999 +0000
description:
Shuffle some code around to allow two PHYs to attach. Only one PHY can
be used at a time, but it's now possible to select one by using ifconfig(8)'s
`instance' parameter.
diffstat:
sys/dev/sbus/be.c | 166 +++++++++++++++++++++++++++++++++++++++++++----------
1 files changed, 135 insertions(+), 31 deletions(-)
diffs (truncated from 319 to 300 lines):
diff -r 5ef5240e5c3f -r c75ff928aa5a sys/dev/sbus/be.c
--- a/sys/dev/sbus/be.c Tue Dec 21 21:06:26 1999 +0000
+++ b/sys/dev/sbus/be.c Tue Dec 21 21:07:42 1999 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: be.c,v 1.10 1999/12/20 22:23:39 pk Exp $ */
+/* $NetBSD: be.c,v 1.11 1999/12/21 21:07:42 pk Exp $ */
/*-
* Copyright (c) 1999 The NetBSD Foundation, Inc.
@@ -131,6 +131,7 @@
/*struct ifmedia sc_ifmedia; -* interface media */
struct mii_data sc_mii; /* MII media control */
#define sc_media sc_mii.mii_media/* shorthand */
+ int sc_phys[2]; /* MII instance -> phy */
struct qec_softc *sc_qec; /* QEC parent */
@@ -172,7 +173,7 @@
static int be_put __P((struct be_softc *, int, struct mbuf *));
static struct mbuf *be_get __P((struct be_softc *, int, int));
-void be_tcvr_init __P((struct be_softc *));
+void be_pal_gate __P((struct be_softc *, int));
/* ifmedia callbacks */
void be_ifmedia_sts __P((struct ifnet *, struct ifmediareq *));
@@ -221,10 +222,13 @@
struct be_softc *sc = (struct be_softc *)self;
struct ifnet *ifp = &sc->sc_ethercom.ec_if;
struct mii_data *mii = &sc->sc_mii;
+ struct mii_softc *child;
+ int instance;
int node = sa->sa_node;
bus_dma_segment_t seg;
bus_size_t size;
int rseg, error;
+ u_int32_t v;
extern void myetheraddr __P((u_char *));
if (sa->sa_nreg < 3) {
@@ -318,11 +322,6 @@
}
/*
- * Initialize transceiver and determine which PHY connection to use.
- */
- be_tcvr_init(sc);
-
- /*
* Initialize our media structures and MII info.
*/
mii->mii_ifp = ifp;
@@ -332,23 +331,66 @@
ifmedia_init(&mii->mii_media, 0, be_ifmedia_upd, be_ifmedia_sts);
- if ((sc->sc_conf & BE_CONF_MII) != 0) {
+ /*
+ * Initialize transceiver and determine which PHY connection to use.
+ */
+ be_mii_sync(sc);
+ v = bus_space_read_4(sc->sc_bustag, sc->sc_tr, BE_TRI_MGMTPAL);
+
+ instance = 0;
+
+ if ((v & MGMT_PAL_EXT_MDIO) != 0) {
mii_phy_probe(&sc->sc_dev, mii, 0xffffffff, BE_PHY_EXTERNAL,
MII_OFFSET_ANY);
- if (LIST_FIRST(&sc->sc_mii.mii_phys) == NULL) {
+ child = LIST_FIRST(&mii->mii_phys);
+ if (child == NULL) {
/* No PHY attached */
- ifmedia_add(&sc->sc_media, IFM_ETHER|IFM_NONE, 0, NULL);
- ifmedia_set(&sc->sc_media, IFM_ETHER|IFM_NONE);
+ ifmedia_add(&sc->sc_media,
+ IFM_MAKEWORD(IFM_ETHER,IFM_NONE,0,instance),
+ 0, NULL);
+ ifmedia_set(&sc->sc_media,
+ IFM_MAKEWORD(IFM_ETHER,IFM_NONE,0,instance));
} else {
/*
+ * Note: we support just one PHY on the external
+ * MII connector.
+ */
+#ifdef DIAGNOSTIC
+ if (LIST_NEXT(child, mii_list) != NULL) {
+ printf("%s: spurious MII device %s attached\n",
+ sc->sc_dev.dv_xname,
+ child->mii_dev.dv_xname);
+ }
+#endif
+ if (child->mii_phy != BE_PHY_EXTERNAL ||
+ child->mii_inst > 0) {
+ printf("%s: cannot accomodate MII device %s"
+ " at phy %d, instance %d\n",
+ sc->sc_dev.dv_xname,
+ child->mii_dev.dv_xname,
+ child->mii_phy, child->mii_inst);
+ } else {
+ sc->sc_phys[instance] = child->mii_phy;
+ }
+
+ /*
* XXX - we can really do the following ONLY if the
* phy indeed has the auto negotiation capability!!
*/
- ifmedia_set(&sc->sc_media, IFM_ETHER|IFM_AUTO);
+ ifmedia_set(&sc->sc_media,
+ IFM_MAKEWORD(IFM_ETHER,IFM_AUTO,0,instance));
+
+ /* Mark our current media setting */
+ be_pal_gate(sc, BE_PHY_EXTERNAL);
+ sc->sc_conf |= BE_CONF_MII;
+ instance++;
}
- } else {
+
+ }
+
+ if ((v & MGMT_PAL_INT_MDIO) != 0) {
/*
* The be internal phy looks vaguely like MII hardware,
* but not enough to be able to use the MII device
@@ -356,23 +398,35 @@
* ourselves.
*/
+ sc->sc_phys[instance] = BE_PHY_INTERNAL;
+
/* Use `ifm_data' to store BMCR bits */
ifmedia_add(&sc->sc_media,
- IFM_MAKEWORD(IFM_ETHER,IFM_10_T,0,0),
+ IFM_MAKEWORD(IFM_ETHER,IFM_10_T,0,instance),
0, NULL);
ifmedia_add(&sc->sc_media,
- IFM_MAKEWORD(IFM_ETHER,IFM_10_T,IFM_FDX,0),
+ IFM_MAKEWORD(IFM_ETHER,IFM_10_T,IFM_FDX,instance),
BMCR_FDX, NULL);
ifmedia_add(&sc->sc_media,
- IFM_MAKEWORD(IFM_ETHER,IFM_100_TX,0,0),
+ IFM_MAKEWORD(IFM_ETHER,IFM_100_TX,0,instance),
BMCR_S100, NULL);
ifmedia_add(&sc->sc_media,
- IFM_MAKEWORD(IFM_ETHER,IFM_100_TX,IFM_FDX,0),
+ IFM_MAKEWORD(IFM_ETHER,IFM_100_TX,IFM_FDX,instance),
BMCR_S100|BMCR_FDX, NULL);
ifmedia_add(&sc->sc_media,
- IFM_MAKEWORD(IFM_ETHER,IFM_AUTO,0,0),
+ IFM_MAKEWORD(IFM_ETHER,IFM_AUTO,0,instance),
0, NULL);
- ifmedia_set(&sc->sc_media, IFM_ETHER|IFM_AUTO);
+
+ /* Only set default medium here if there's no external PHY */
+ if (instance == 0) {
+ be_pal_gate(sc, BE_PHY_INTERNAL);
+ ifmedia_set(&sc->sc_media,
+ IFM_MAKEWORD(IFM_ETHER,IFM_AUTO,0,instance));
+ } else {
+ /* Isolate internal transceiver */
+ be_mii_writereg((struct device *)sc,
+ BE_PHY_INTERNAL, MII_BMCR, BMCR_ISO);
+ }
}
bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
@@ -388,8 +442,7 @@
ether_ifattach(ifp, sc->sc_enaddr);
#if NBPFILTER > 0
- bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB,
- sizeof(struct ether_header));
+ bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
#endif
}
@@ -1010,9 +1063,8 @@
s = splimp();
qec_meminit(&sc->sc_rb, BE_PKT_BUF_SZ);
- be_tcvr_init(sc);
- be_ifmedia_upd(ifp);
+ be_mii_sync(sc);
bestop(sc);
@@ -1194,10 +1246,31 @@
}
}
+void
+be_pal_gate(sc, phy)
+ struct be_softc *sc;
+ int phy;
+{
+ bus_space_tag_t t = sc->sc_bustag;
+ bus_space_handle_t tr = sc->sc_tr;
+ u_int32_t v;
+
+ be_mii_sync(sc);
+
+ v = ~(TCVR_PAL_EXTLBACK | TCVR_PAL_MSENSE | TCVR_PAL_LTENABLE);
+ if (phy == BE_PHY_INTERNAL)
+ v &= ~TCVR_PAL_SERIAL;
+
+ bus_space_write_4(t, tr, BE_TRI_TCVRPAL, v);
+ (void)bus_space_read_4(t, tr, BE_TRI_TCVRPAL);
+}
+
+#if 0
/*
* Initialize the transceiver and figure out whether we're using the
* external or internal one.
*/
+void be_tcvr_init(struct be_softc *);
void
be_tcvr_init(sc)
struct be_softc *sc;
@@ -1250,7 +1323,7 @@
sc->sc_dev.dv_xname);
}
}
-
+#endif
static int
be_tcvr_read_bit(sc, phy)
@@ -1409,10 +1482,14 @@
struct be_softc *sc = (struct be_softc *)self;
bus_space_tag_t t = sc->sc_bustag;
bus_space_handle_t br = sc->sc_br;
+ u_int instance;
u_int32_t v;
- printf("%s: media_active=%x\n",
- self->dv_xname, sc->sc_mii.mii_media_active);
+ instance = IFM_INST(sc->sc_mii.mii_media.ifm_cur->ifm_media);
+#ifdef DIAGNOSTIC
+ if (instance > 1)
+ panic("be_mii_statchg: instance %d out of range", instance);
+#endif
/* Update duplex mode in TX configuration */
v = bus_space_read_4(t, br, BE_BRI_TXCFG);
@@ -1421,6 +1498,9 @@
else
v &= ~BE_BR_TXCFG_FULLDPLX;
bus_space_write_4(t, br, BE_BRI_TXCFG, v);
+
+ /* Change to appropriate gate in transceiver PAL */
+ be_pal_gate(sc, sc->sc_phys[instance]);
}
void
@@ -1529,7 +1609,7 @@
bmsr = be_mii_readreg((struct device *)sc, BE_PHY_INTERNAL, MII_BMSR)|
be_mii_readreg((struct device *)sc, BE_PHY_INTERNAL, MII_BMSR);
if (bmsr & BMSR_LINK)
- ifmr->ifm_status |= IFM_ACTIVE;
+ media_status |= IFM_ACTIVE;
ifmr->ifm_status = media_status;
ifmr->ifm_active = media_active;
@@ -1545,17 +1625,36 @@
struct be_softc *sc = ifp->if_softc;
struct ifmedia *ifm = &sc->sc_media;
int newmedia = ifm->ifm_media;
- int n, error, phy, bmcr;
+ int n, error, bmcr;
char *speed, *mode;
bus_space_tag_t t;
bus_space_handle_t br;
u_int32_t v;
+ u_int instance, phy;
+
+ instance = IFM_INST(sc->sc_mii.mii_media.ifm_cur->ifm_media);
+
+#ifdef DIAGNOSTIC
+ if (instance > 1)
+ panic("be_mii_statchg: instance %d out of range", instance);
+#endif
+
+ phy = sc->sc_phys[instance];
if (IFM_TYPE(newmedia) != IFM_ETHER)
return (EINVAL);
- if ((sc->sc_conf & BE_CONF_MII) != 0)
- return (mii_mediachg(&sc->sc_mii));
+ if ((error = mii_mediachg(&sc->sc_mii)) != 0)
+ return (error);
+
+ if (phy == BE_PHY_EXTERNAL) {
+ /* Isolate the internal transceiver */
+ be_mii_writereg((struct device *)sc,
+ BE_PHY_INTERNAL, MII_BMCR, BMCR_ISO);
+ sc->sc_conf |= BE_CONF_MII;
+ return (0);
Home |
Main Index |
Thread Index |
Old Index