Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/ic Preserve the current PHY select bit in the MIF co...



details:   https://anonhg.NetBSD.org/src/rev/735b1e29a6f3
branches:  trunk
changeset: 542985:735b1e29a6f3
user:      pk <pk%NetBSD.org@localhost>
date:      Thu Feb 13 12:10:20 2003 +0000

description:
Preserve the current PHY select bit in the MIF configuration register
in mii_readreg()/mii_writereg(). Also restore this bit based on the
currently selected media instance every time we need to reinitialise
the interface.

diffstat:

 sys/dev/ic/hme.c    |  161 +++++++++++++++++++++++++++++++++------------------
 sys/dev/ic/hmevar.h |    3 +-
 2 files changed, 106 insertions(+), 58 deletions(-)

diffs (truncated from 320 to 300 lines):

diff -r c7d57d964629 -r 735b1e29a6f3 sys/dev/ic/hme.c
--- a/sys/dev/ic/hme.c  Thu Feb 13 11:47:27 2003 +0000
+++ b/sys/dev/ic/hme.c  Thu Feb 13 12:10:20 2003 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: hme.c,v 1.32 2002/12/18 23:13:02 martin Exp $  */
+/*     $NetBSD: hme.c,v 1.33 2003/02/13 12:10:20 pk Exp $      */
 
 /*-
  * Copyright (c) 1999 The NetBSD Foundation, Inc.
@@ -41,7 +41,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: hme.c,v 1.32 2002/12/18 23:13:02 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: hme.c,v 1.33 2003/02/13 12:10:20 pk Exp $");
 
 #define HMEDEBUG
 
@@ -262,7 +262,7 @@
        mii->mii_writereg = hme_mii_writereg;
        mii->mii_statchg = hme_mii_statchg;
 
-       ifmedia_init(&mii->mii_media, IFM_IMASK, hme_mediachange, hme_mediastatus);
+       ifmedia_init(&mii->mii_media, 0, hme_mediachange, hme_mediastatus);
 
        hme_mifinit(sc);
 
@@ -318,15 +318,6 @@
        if (sc->sc_sh == NULL)
                panic("hme_config: can't establish shutdownhook");
 
-#if 0
-       printf("%s: %d receive buffers, %d transmit buffers\n",
-           sc->sc_dev.dv_xname, sc->sc_nrbuf, sc->sc_ntbuf);
-       sc->sc_rbufaddr = malloc(sc->sc_nrbuf * sizeof(int), M_DEVBUF,
-                                       M_WAITOK);
-       sc->sc_tbufaddr = malloc(sc->sc_ntbuf * sizeof(int), M_DEVBUF,
-                                       M_WAITOK);
-#endif
-
 #if NRND > 0
        rnd_attach_source(&sc->rnd_source, sc->sc_dev.dv_xname,
                          RND_TYPE_NET, 0);
@@ -371,6 +362,9 @@
        callout_stop(&sc->sc_tick_ch);
        mii_down(&sc->sc_mii);
 
+       /* Mask all interrupts */
+       bus_space_write_4(t, seb, HME_SEBI_IMASK, 0xffffffff);
+
        /* Reset transmitter and receiver */
        bus_space_write_4(t, seb, HME_SEBI_RESET,
                          (HME_SEB_RESET_ETX | HME_SEB_RESET_ERX));
@@ -555,6 +549,7 @@
                          HME_SEB_STAT_TXALL |
                          HME_SEB_STAT_TXPERR |
                          HME_SEB_STAT_RCNTEXP |
+                         /*HME_SEB_STAT_MIFIRQ |*/
                          HME_SEB_STAT_ALL_ERRORS ));
 
        switch (sc->sc_burst) {
@@ -970,7 +965,14 @@
        char bits[128];
 
        if ((status & HME_SEB_STAT_MIFIRQ) != 0) {
-               printf("%s: XXXlink status changed\n", sc->sc_dev.dv_xname);
+               bus_space_tag_t t = sc->sc_bustag;
+               bus_space_handle_t mif = sc->sc_mif;
+               u_int32_t cf, st, sm;
+               cf = bus_space_read_4(t, mif, HME_MIFI_CFG);
+               st = bus_space_read_4(t, mif, HME_MIFI_STAT);
+               sm = bus_space_read_4(t, mif, HME_MIFI_SM);
+               printf("%s: XXXlink status changed: cfg=%x, stat %x, sm %x\n",
+                       sc->sc_dev.dv_xname, cf, st, sm);
                return (1);
        }
 
@@ -1025,17 +1027,21 @@
 {
        bus_space_tag_t t = sc->sc_bustag;
        bus_space_handle_t mif = sc->sc_mif;
+       int instance, phy;
        u_int32_t v;
 
-       /* Configure the MIF in frame mode */
-       v = bus_space_read_4(t, mif, HME_MIFI_CFG);
-       v &= ~HME_MIF_CFG_BBMODE;
-       bus_space_write_4(t, mif, HME_MIFI_CFG, v);
+       if (sc->sc_media.ifm_cur != NULL) {
+               instance = IFM_INST(sc->sc_media.ifm_cur->ifm_media);
+               phy = sc->sc_phys[instance];
+       } else
+               /* No media set yet, pick phy arbitrarily.. */
+               phy = HME_PHYAD_EXTERNAL;
 
-       if (v & HME_MIF_CFG_MDI1)
-               sc->sc_tcvr = HME_PHYAD_EXTERNAL;
-       else if (v & HME_MIF_CFG_MDI0)
-               sc->sc_tcvr = HME_PHYAD_INTERNAL;
+       /* Configure the MIF in frame mode, no poll, current phy select */
+       v = 0;
+       if (phy == HME_PHYAD_EXTERNAL)
+               v |= HME_MIF_CFG_PHY;
+       bus_space_write_4(t, mif, HME_MIFI_CFG, v);
 }
 
 /*
@@ -1049,21 +1055,34 @@
        struct hme_softc *sc = (void *)self;
        bus_space_tag_t t = sc->sc_bustag;
        bus_space_handle_t mif = sc->sc_mif;
+       u_int32_t v, mifi_cfg;
        int n;
-       u_int32_t v;
 
-       if (sc->sc_tcvr != phy)
+       /* We can at most have two PHYs */
+       if (phy != HME_PHYAD_EXTERNAL && phy != HME_PHYAD_INTERNAL)
                return (0);
 
        /* Select the desired PHY in the MIF configuration register */
-       v = bus_space_read_4(t, mif, HME_MIFI_CFG);
-       /* Clear PHY select bit */
+       v = mifi_cfg = bus_space_read_4(t, mif, HME_MIFI_CFG);
        v &= ~HME_MIF_CFG_PHY;
        if (phy == HME_PHYAD_EXTERNAL)
-               /* Set PHY select bit to get at external device */
                v |= HME_MIF_CFG_PHY;
        bus_space_write_4(t, mif, HME_MIFI_CFG, v);
 
+#if 0
+/* This doesn't work reliably; the MDIO_1 bit is off most of the time */
+       /*
+        * Check whether a transceiver is connected by testing
+        * the MIF configuration register's MDI_X bits. Note that
+        * MDI_0 (int) == 0x100 and MDI_1 (ext) == 0x200; see hmereg.h
+        */
+       mif_mdi_bit = 1 << (8 + (1 - phy));
+       delay(100);
+       v = bus_space_read_4(t, mif, HME_MIFI_CFG);
+       if ((v & mif_mdi_bit) == 0)
+               return (0);
+#endif
+
        /* Construct the frame command */
        v = (MII_COMMAND_START << HME_MIF_FO_ST_SHIFT) |
            HME_MIF_FO_TAMSB |
@@ -1075,12 +1094,19 @@
        for (n = 0; n < 100; n++) {
                DELAY(1);
                v = bus_space_read_4(t, mif, HME_MIFI_FO);
-               if (v & HME_MIF_FO_TALSB)
-                       return (v & HME_MIF_FO_DATA);
+               if (v & HME_MIF_FO_TALSB) {
+                       v &= HME_MIF_FO_DATA;
+                       goto out;
+               }
        }
 
+       v = 0;
        printf("%s: mii_read timeout\n", sc->sc_dev.dv_xname);
-       return (0);
+
+out:
+       /* Restore MIFI_CFG register */
+       bus_space_write_4(t, mif, HME_MIFI_CFG, mifi_cfg);
+       return (v);
 }
 
 static void
@@ -1091,21 +1117,34 @@
        struct hme_softc *sc = (void *)self;
        bus_space_tag_t t = sc->sc_bustag;
        bus_space_handle_t mif = sc->sc_mif;
+       u_int32_t v, mifi_cfg;
        int n;
-       u_int32_t v;
 
-       if (sc->sc_tcvr != phy)
+       /* We can at most have two PHYs */
+       if (phy != HME_PHYAD_EXTERNAL && phy != HME_PHYAD_INTERNAL)
                return;
 
        /* Select the desired PHY in the MIF configuration register */
-       v = bus_space_read_4(t, mif, HME_MIFI_CFG);
-       /* Clear PHY select bit */
+       v = mifi_cfg = bus_space_read_4(t, mif, HME_MIFI_CFG);
        v &= ~HME_MIF_CFG_PHY;
        if (phy == HME_PHYAD_EXTERNAL)
-               /* Set PHY select bit to get at external device */
                v |= HME_MIF_CFG_PHY;
        bus_space_write_4(t, mif, HME_MIFI_CFG, v);
 
+#if 0
+/* This doesn't work reliably; the MDIO_1 bit is off most of the time */
+       /*
+        * Check whether a transceiver is connected by testing
+        * the MIF configuration register's MDI_X bits. Note that
+        * MDI_0 (int) == 0x100 and MDI_1 (ext) == 0x200; see hmereg.h
+        */
+       mif_mdi_bit = 1 << (8 + (1 - phy));
+       delay(100);
+       v = bus_space_read_4(t, mif, HME_MIFI_CFG);
+       if ((v & mif_mdi_bit) == 0)
+               return;
+#endif
+
        /* Construct the frame command */
        v = (MII_COMMAND_START << HME_MIF_FO_ST_SHIFT)  |
            HME_MIF_FO_TAMSB                            |
@@ -1119,10 +1158,13 @@
                DELAY(1);
                v = bus_space_read_4(t, mif, HME_MIFI_FO);
                if (v & HME_MIF_FO_TALSB)
-                       return;
+                       goto out;
        }
 
        printf("%s: mii_write timeout\n", sc->sc_dev.dv_xname);
+out:
+       /* Restore MIFI_CFG register */
+       bus_space_write_4(t, mif, HME_MIFI_CFG, mifi_cfg);
 }
 
 static void
@@ -1130,25 +1172,15 @@
        struct device *dev;
 {
        struct hme_softc *sc = (void *)dev;
-       int instance = IFM_INST(sc->sc_mii.mii_media.ifm_cur->ifm_media);
-       int phy = sc->sc_phys[instance];
        bus_space_tag_t t = sc->sc_bustag;
-       bus_space_handle_t mif = sc->sc_mif;
        bus_space_handle_t mac = sc->sc_mac;
        u_int32_t v;
 
 #ifdef HMEDEBUG
        if (sc->sc_debug)
-               printf("hme_mii_statchg: status change: phy = %d\n", phy);
+               printf("hme_mii_statchg: status change\n");
 #endif
 
-       /* Select the current PHY in the MIF configuration register */
-       v = bus_space_read_4(t, mif, HME_MIFI_CFG);
-       v &= ~HME_MIF_CFG_PHY;
-       if (phy == HME_PHYAD_EXTERNAL)
-               v |= HME_MIF_CFG_PHY;
-       bus_space_write_4(t, mif, HME_MIFI_CFG, v);
-
        /* Set the MAC Full Duplex bit appropriately */
        /* Apparently the hme chip is SIMPLEX if working in full duplex mode,
           but not otherwise. */
@@ -1161,6 +1193,33 @@
                sc->sc_ethercom.ec_if.if_flags &= ~IFF_SIMPLEX;
        }
        bus_space_write_4(t, mac, HME_MACI_TXCFG, v);
+}
+
+int
+hme_mediachange(ifp)
+       struct ifnet *ifp;
+{
+       struct hme_softc *sc = ifp->if_softc;
+       bus_space_tag_t t = sc->sc_bustag;
+       bus_space_handle_t mif = sc->sc_mif;
+       bus_space_handle_t mac = sc->sc_mac;
+       int instance = IFM_INST(sc->sc_mii.mii_media.ifm_cur->ifm_media);
+       int phy = sc->sc_phys[instance];
+       u_int32_t v;
+
+#ifdef HMEDEBUG
+       if (sc->sc_debug)
+               printf("hme_mediachange: phy = %d\n", phy);
+#endif
+       if (IFM_TYPE(sc->sc_media.ifm_media) != IFM_ETHER)
+               return (EINVAL);
+
+       /* Select the current PHY in the MIF configuration register */
+       v = bus_space_read_4(t, mif, HME_MIFI_CFG);
+       v &= ~HME_MIF_CFG_PHY;
+       if (phy == HME_PHYAD_EXTERNAL)
+               v |= HME_MIF_CFG_PHY;
+       bus_space_write_4(t, mif, HME_MIFI_CFG, v);
 
        /* If an external transceiver is selected, enable its MII drivers */
        v = bus_space_read_4(t, mac, HME_MACI_XIF);
@@ -1168,16 +1227,6 @@
        if (phy == HME_PHYAD_EXTERNAL)
                v |= HME_MAC_XIF_MIIENABLE;
        bus_space_write_4(t, mac, HME_MACI_XIF, v);
-}
-
-int
-hme_mediachange(ifp)
-       struct ifnet *ifp;
-{
-       struct hme_softc *sc = ifp->if_softc;
-
-       if (IFM_TYPE(sc->sc_media.ifm_media) != IFM_ETHER)
-               return (EINVAL);



Home | Main Index | Thread Index | Old Index