Source-Changes-HG archive

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

[src/trunk]: src/sys/dev/ic Snapshot of work-in-progress to support the inter...



details:   https://anonhg.NetBSD.org/src/rev/18263706ea3b
branches:  trunk
changeset: 476215:18263706ea3b
user:      thorpej <thorpej%NetBSD.org@localhost>
date:      Thu Sep 09 21:48:18 1999 +0000

description:
Snapshot of work-in-progress to support the internal NWay block on
the Lite-On PNIC chips.  Not finished yet; some other infrastructure
work left to do.

diffstat:

 sys/dev/ic/tulip.c    |  327 +++++++++++++++++++++++++++++++++++++++++++++++--
 sys/dev/ic/tulipreg.h |   90 ++++++++-----
 sys/dev/ic/tulipvar.h |   16 ++-
 3 files changed, 381 insertions(+), 52 deletions(-)

diffs (truncated from 644 to 300 lines):

diff -r b917ad06e46d -r 18263706ea3b sys/dev/ic/tulip.c
--- a/sys/dev/ic/tulip.c        Thu Sep 09 20:23:58 1999 +0000
+++ b/sys/dev/ic/tulip.c        Thu Sep 09 21:48:18 1999 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: tulip.c,v 1.5 1999/09/02 23:25:28 thorpej Exp $        */
+/*     $NetBSD: tulip.c,v 1.6 1999/09/09 21:48:18 thorpej Exp $        */
 
 /*-
  * Copyright (c) 1998, 1999 The NetBSD Foundation, Inc.
@@ -1346,7 +1346,7 @@
                        /* Enable the MII port. */
                        sc->sc_opmode |= OPMODE_PS;
 
-                       TULIP_WRITE(sc, CSR_PNIC_ENDEC, PNIC_ENDEC_JABBERDIS);
+                       TULIP_WRITE(sc, CSR_PNIC_ENDEC, PNIC_ENDEC_JDIS);
                        break;
 
                case TULIP_CHIP_WB89C840F:
@@ -1493,9 +1493,9 @@
         */
        TULIP_WRITE(sc, CSR_RXPOLL, RXPOLL_RPD);
 
-       if (sc->sc_flags & TULIPF_HAS_MII) {
+       if (sc->sc_tick != NULL) {
                /* Start the one second clock. */
-               timeout(tlp_mii_tick, sc, hz);
+               timeout(sc->sc_tick, sc, hz);
        }
 
        /*
@@ -1552,9 +1552,9 @@
        struct ifnet *ifp = &sc->sc_ethercom.ec_if;
        struct tulip_txsoft *txs;
 
-       if (sc->sc_flags & TULIPF_HAS_MII) {
+       if (sc->sc_tick != NULL) {
                /* Stop the one second clock. */
-               untimeout(tlp_mii_tick, sc);
+               untimeout(sc->sc_tick, sc);
        }
 
        /* Disable interrupts. */
@@ -2219,7 +2219,7 @@
        mii_tick(&sc->sc_mii);
        splx(s);
 
-       timeout(tlp_mii_tick, sc, hz);
+       timeout(sc->sc_tick, sc, hz);
 }
 
 /*
@@ -2470,6 +2470,7 @@
        int i;
 
        TULIP_WRITE(sc, CSR_PNIC_MII,
+           PNIC_MII_MBO | PNIC_MII_RESERVED |
            PNIC_MII_READ | (phy << PNIC_MII_PHYSHIFT) |
            (reg << PNIC_MII_REGSHIFT));
 
@@ -2501,6 +2502,7 @@
        int i;
 
        TULIP_WRITE(sc, CSR_PNIC_MII,
+           PNIC_MII_MBO | PNIC_MII_RESERVED |
            PNIC_MII_WRITE | (phy << PNIC_MII_PHYSHIFT) |
            (reg << PNIC_MII_REGSHIFT) | val);
 
@@ -2544,6 +2546,7 @@
                ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_NONE);
        } else {
                sc->sc_flags |= TULIPF_HAS_MII;
+               sc->sc_tick = tlp_mii_tick;
                ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_AUTO);
        }
 }
@@ -2559,11 +2562,23 @@
        tlp_pnic_tmsw_init, tlp_pnic_tmsw_get, tlp_pnic_tmsw_set
 };
 
+void   tlp_pnic_nway_tick __P((void *));
+int    tlp_pnic_nway_service __P((struct tulip_softc *, int));
+void   tlp_pnic_nway_reset __P((struct tulip_softc *));
+int    tlp_pnic_nway_auto __P((struct tulip_softc *, int));
+void   tlp_pnic_nway_auto_timeout __P((void *));
+void   tlp_pnic_nway_status __P((struct tulip_softc *));
+void   tlp_pnic_nway_acomp __P((struct tulip_softc *));
+
 void
 tlp_pnic_tmsw_init(sc)
        struct tulip_softc *sc;
 {
        struct ifnet *ifp = &sc->sc_ethercom.ec_if;
+       const char *sep = "";
+
+#define        ADD(m, c)       ifmedia_add(&sc->sc_mii.mii_media, (m), (c), NULL)
+#define        PRINT(s)        printf("%s%s", sep, s); sep = ", "
 
        sc->sc_mii.mii_ifp = ifp;
        sc->sc_mii.mii_readreg = tlp_pnic_mii_readreg;
@@ -2573,15 +2588,44 @@
            tlp_mediastatus);
        mii_phy_probe(&sc->sc_dev, &sc->sc_mii, 0xffffffff);
        if (LIST_FIRST(&sc->sc_mii.mii_phys) == NULL) {
-               /* XXX USE INTERNAL NWAY! */
-               printf("%s: no support for PNIC NWAY yet\n",
-                   sc->sc_dev.dv_xname);
-               ifmedia_add(&sc->sc_mii.mii_media, IFM_ETHER|IFM_NONE, 0, NULL);
-               ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_NONE);
+               /* XXX What about AUI/BNC support? */
+               printf("%s: ", sc->sc_dev.dv_xname);
+
+               tlp_pnic_nway_reset(sc);
+
+               ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, 0, 0),
+                   PNIC_NWAY_TW|PNIC_NWAY_CAP10T);
+               PRINT("10baseT");
+
+               ADD(IFM_MAKEWORD(IFM_ETHER, IFM_10_T, IFM_FDX, 0),
+                   PNIC_NWAY_TW|PNIC_NWAY_FD|PNIC_NWAY_CAP10TFDX);
+               PRINT("10baseT-FDX");
+
+               ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, 0, 0),
+                   PNIC_NWAY_TW|PNIC_NWAY_100|PNIC_NWAY_CAP100TX);
+               PRINT("100baseTX");
+
+               ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_FDX, 0),
+                   PNIC_NWAY_TW|PNIC_NWAY_100|PNIC_NWAY_FD|
+                   PNIC_NWAY_CAP100TXFDX);
+               PRINT("100baseTX-FDX");
+
+               ADD(IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, 0, 0),
+                   PNIC_NWAY_TW|PNIC_NWAY_RN|PNIC_NWAY_NW|
+                   PNIC_NWAY_CAP10T|PNIC_NWAY_CAP10TFDX|
+                   PNIC_NWAY_CAP100TXFDX|PNIC_NWAY_CAP100TX);
+               PRINT("auto");
+
+               sc->sc_tick = tlp_pnic_nway_tick;
+               ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_AUTO);
        } else {
                sc->sc_flags |= TULIPF_HAS_MII;
+               sc->sc_tick = tlp_mii_tick;
                ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_AUTO);
        }
+
+#undef ADD
+#undef PRINT
 }
 
 void
@@ -2589,13 +2633,16 @@
        struct tulip_softc *sc;
        struct ifmediareq *ifmr;
 {
+       struct mii_data *mii = &sc->sc_mii;
 
        if (sc->sc_flags & TULIPF_HAS_MII)
                tlp_mii_getmedia(sc, ifmr);
        else {
-               /* XXX CHECK INTERNAL NWAY! */
-               ifmr->ifm_status = 0;
-               ifmr->ifm_active = IFM_ETHER|IFM_NONE;
+               mii->mii_media_status = 0;
+               mii->mii_media_active = IFM_NONE;
+               tlp_pnic_nway_service(sc, MII_POLLSTAT);
+               ifmr->ifm_status = sc->sc_mii.mii_media_status;
+               ifmr->ifm_active = sc->sc_mii.mii_media_active; 
        }
 }
 
@@ -2603,10 +2650,256 @@
 tlp_pnic_tmsw_set(sc)
        struct tulip_softc *sc;
 {
+       struct ifnet *ifp = &sc->sc_ethercom.ec_if;
+       struct mii_data *mii = &sc->sc_mii;
 
        if (sc->sc_flags & TULIPF_HAS_MII)
                return (tlp_mii_setmedia(sc));
 
-       /* XXX USE INTERNAL NWAY! */
-       return (EIO);
+       if (ifp->if_flags & IFF_UP) {
+               mii->mii_media_status = 0;
+               mii->mii_media_active = IFM_NONE;
+               return (tlp_pnic_nway_service(sc, MII_MEDIACHG));
+       }
+
+       return (0);
+}
+
+void
+tlp_pnic_nway_tick(arg)
+       void *arg;
+{
+       struct tulip_softc *sc = arg;
+       int s;
+
+       s = splnet();
+       tlp_pnic_nway_service(sc, MII_TICK);
+       splx(s);
+
+       timeout(tlp_pnic_nway_tick, sc, hz);
+}
+
+/*
+ * Support for the Lite-On PNIC internal NWay block.  This is constructed
+ * somewhat like a PHY driver for simplicity.
+ */
+
+int
+tlp_pnic_nway_service(sc, cmd)
+       struct tulip_softc *sc;
+       int cmd;
+{
+       struct mii_data *mii = &sc->sc_mii;
+       struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
+
+       if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
+               return (0);
+
+       switch (cmd) {
+       case MII_POLLSTAT:
+               /* Nothing special to do here. */
+               break;
+
+       case MII_MEDIACHG:
+               switch (IFM_SUBTYPE(ife->ifm_media)) {
+               case IFM_AUTO:
+                       (void) tlp_pnic_nway_auto(sc, 1);
+                       break;
+               case IFM_100_T4:
+                       /*
+                        * XXX Not supported as a manual setting right now.
+                        */
+                       return (EINVAL);
+               default:
+                       /*
+                        * NWAY register data is stored in the ifmedia entry.
+                        */
+                       TULIP_WRITE(sc, CSR_PNIC_NWAY, ife->ifm_data);
+               }
+               break;
+
+       case MII_TICK:
+               /*
+                * Only used for autonegotiation.
+                */
+               if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO)
+                       return (0);
+
+               /*
+                * Check to see if we have link.  If we do, we don't
+                * need to restart the autonegotiation process.
+                */
+               if (sc->sc_flags & TULIPF_LINK_UP)
+                       return (0);
+
+               /*
+                * Only retry autonegotiation every 5 seconds.
+                */
+               if (++sc->sc_nway_ticks != 5)
+                       return (0);
+
+               sc->sc_nway_ticks = 0;
+               tlp_pnic_nway_reset(sc);
+               if (tlp_pnic_nway_auto(sc, 0) == EJUSTRETURN)
+                       return (0);
+               break;
+       }
+
+       /* Update the media status. */
+       tlp_pnic_nway_status(sc);
+
+       /* Callback if something changed. */
+       if (sc->sc_nway_active != mii->mii_media_active ||
+           cmd == MII_MEDIACHG) {
+               (*sc->sc_statchg)(&sc->sc_dev);
+               sc->sc_nway_active = mii->mii_media_active;
+       }
+       return (0);
+}
+
+void
+tlp_pnic_nway_reset(sc)
+       struct tulip_softc *sc;
+{
+
+       TULIP_WRITE(sc, CSR_PNIC_NWAY, PNIC_NWAY_RS);
+       delay(100);
+       TULIP_WRITE(sc, CSR_PNIC_NWAY, 0);
 }
+
+int
+tlp_pnic_nway_auto(sc, waitfor)
+       struct tulip_softc *sc;
+       int waitfor;
+{
+       struct mii_data *mii = &sc->sc_mii;
+       struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
+       u_int32_t reg;



Home | Main Index | Thread Index | Old Index