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