Source-Changes-HG archive

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

[src/netbsd-3]: src/sys/dev/ic Pull up revision 1.137 (requested by rpaulo in...



details:   https://anonhg.NetBSD.org/src/rev/cc045784fb5d
branches:  netbsd-3
changeset: 576348:cc045784fb5d
user:      tron <tron%NetBSD.org@localhost>
date:      Fri Jul 01 12:28:32 2005 +0000

description:
Pull up revision 1.137 (requested by rpaulo in ticket #493):
Add support for ASIX AX88140A/AX88141 chipsets using only
the 10/100 MII with inspiration from FreeBSD dc(4) driver.
Tested on i386 and macppc.
Reviewed by Jason Thorpe and ok'ed by Hubert Feyrer.

diffstat:

 sys/dev/ic/tulip.c |  247 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 240 insertions(+), 7 deletions(-)

diffs (truncated from 345 to 300 lines):

diff -r 50efbb436125 -r cc045784fb5d sys/dev/ic/tulip.c
--- a/sys/dev/ic/tulip.c        Fri Jul 01 12:28:25 2005 +0000
+++ b/sys/dev/ic/tulip.c        Fri Jul 01 12:28:32 2005 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: tulip.c,v 1.135 2005/02/27 00:27:02 perry Exp $        */
+/*     $NetBSD: tulip.c,v 1.135.2.1 2005/07/01 12:28:32 tron Exp $     */
 
 /*-
  * Copyright (c) 1998, 1999, 2000, 2002 The NetBSD Foundation, Inc.
@@ -43,7 +43,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: tulip.c,v 1.135 2005/02/27 00:27:02 perry Exp $");
+__KERNEL_RCSID(0, "$NetBSD: tulip.c,v 1.135.2.1 2005/07/01 12:28:32 tron Exp $");
 
 #include "bpfilter.h"
 
@@ -116,6 +116,7 @@
 void   tlp_filter_setup(struct tulip_softc *);
 void   tlp_winb_filter_setup(struct tulip_softc *);
 void   tlp_al981_filter_setup(struct tulip_softc *);
+void   tlp_asix_filter_setup(struct tulip_softc *);
 
 void   tlp_rxintr(struct tulip_softc *);
 void   tlp_txintr(struct tulip_softc *);
@@ -141,6 +142,7 @@
 void   tlp_2114x_mii_preinit(struct tulip_softc *);
 void   tlp_pnic_preinit(struct tulip_softc *);
 void   tlp_dm9102_preinit(struct tulip_softc *);
+void   tlp_asix_preinit(struct tulip_softc *);
 
 void   tlp_21140_reset(struct tulip_softc *);
 void   tlp_21142_reset(struct tulip_softc *);
@@ -241,6 +243,11 @@
                sc->sc_filter_setup = tlp_al981_filter_setup;
                break;
 
+       case TULIP_CHIP_AX88140:
+       case TULIP_CHIP_AX88141:
+               sc->sc_filter_setup = tlp_asix_filter_setup;
+               break;
+
        default:
                sc->sc_filter_setup = tlp_filter_setup;
                break;
@@ -360,6 +367,16 @@
                sc->sc_txthresh = TXTH_DM9102_SF;
                break;
 
+       case TULIP_CHIP_AX88140:
+       case TULIP_CHIP_AX88141:
+               /*
+                * Run these chips in ring mode.
+                */
+               sc->sc_tdctl_ch = 0;
+               sc->sc_tdctl_er = TDCTL_ER;
+               sc->sc_preinit = tlp_asix_preinit;
+               break;
+
        default:
                /*
                 * Default to running in ring mode.
@@ -434,6 +451,8 @@
        case TULIP_CHIP_X3201_3:
        case TULIP_CHIP_DM9102:
        case TULIP_CHIP_DM9102A:
+       case TULIP_CHIP_AX88140:
+       case TULIP_CHIP_AX88141:
                sc->sc_ntxsegs = 1;
                break;
 
@@ -1579,11 +1598,14 @@
        TULIP_WRITE(sc, CSR_BUSMODE, BUSMODE_SWR);
 
        /*
-        * Xircom clone doesn't bring itself out of reset automatically.
+        * Xircom and ASIX clones don't bring themselves out of 
+        * reset automatically.
         * Instead, we have to wait at least 50 PCI cycles, and then
         * clear SWR.
         */
-       if (sc->sc_chip == TULIP_CHIP_X3201_3) {
+       if (sc->sc_chip == TULIP_CHIP_X3201_3 ||
+           sc->sc_chip == TULIP_CHIP_AX88140 ||
+           sc->sc_chip == TULIP_CHIP_AX88141) {
                delay(10);
                TULIP_WRITE(sc, CSR_BUSMODE, 0);
        }
@@ -1684,6 +1706,12 @@
                if (sc->sc_maxburst == 0)
                        sc->sc_maxburst = 16;
                break;
+       
+       case TULIP_CHIP_AX88140:
+       case TULIP_CHIP_AX88141:
+               if (sc->sc_maxburst == 0)
+                       sc->sc_maxburst = 16;
+               break;
 
        default:
                /* Nothing. */
@@ -1915,6 +1943,26 @@
                reg = enaddr[4] |
                      (enaddr[5] << 8);
                bus_space_write_4(sc->sc_st, sc->sc_sh, CSR_ADM_PAR1, reg);
+               break;
+           }
+
+       case TULIP_CHIP_AX88140:
+       case TULIP_CHIP_AX88141:
+           {
+               u_int32_t reg;
+               u_int8_t *enaddr = LLADDR(ifp->if_sadl);
+                   
+               reg = enaddr[0] |
+                     (enaddr[1] << 8) |
+                     (enaddr[2] << 16) |
+                     (enaddr[3] << 24);
+               TULIP_WRITE(sc, CSR_AX_FILTIDX, AX_FILTIDX_PAR0);
+               TULIP_WRITE(sc, CSR_AX_FILTDATA, reg);
+
+               reg = enaddr[4] | (enaddr[5] << 8);
+               TULIP_WRITE(sc, CSR_AX_FILTIDX, AX_FILTIDX_PAR1);
+               TULIP_WRITE(sc, CSR_AX_FILTDATA, reg);
+               break;
            }
 
        default:
@@ -2980,6 +3028,78 @@
 }
 
 /*
+ * tlp_asix_filter_setup:
+ * 
+ *     Set the ASIX AX8814x recieve filter.
+ */
+void
+tlp_asix_filter_setup(sc)
+       struct tulip_softc *sc;
+{
+       struct ethercom *ec = &sc->sc_ethercom;
+       struct ifnet *ifp = &sc->sc_ethercom.ec_if;
+       struct ether_multi *enm;
+       struct ether_multistep step;
+       u_int32_t hash, mchash[2];
+
+       DPRINTF(sc, ("%s: tlp_asix_filter_setup: sc_flags 0x%08x\n",
+               sc->sc_dev.dv_xname, sc->sc_flags));
+
+       sc->sc_opmode &= ~(OPMODE_PM|OPMODE_AX_RB|OPMODE_PR);
+
+       if (ifp->if_flags & IFF_MULTICAST)
+               sc->sc_opmode |= OPMODE_PM;
+
+       if (ifp->if_flags & IFF_BROADCAST)
+               sc->sc_opmode |= OPMODE_AX_RB;
+
+       if (ifp->if_flags & IFF_PROMISC) {
+               sc->sc_opmode |= OPMODE_PR;
+               goto allmulti;
+       }
+
+       mchash[0] = mchash[1] = 0;
+
+       ETHER_FIRST_MULTI(step, ec, enm);
+       while (enm != NULL) {
+               if (memcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) {
+                       /*
+                        * We must listen to a range of multicast addresses.
+                        * For now, just accept all multicasts, rather than
+                        * trying to set only those filter bits needed to match
+                        * the range.  (At this time, the only use of address
+                        * ranges is for IP multicast routing, for which the
+                        * range is big enough to require all bits set.)
+                        */
+                       goto allmulti;
+               }
+               hash = (ether_crc32_be(enm->enm_addrlo, ETHER_ADDR_LEN) >> 26) 
+                      & 0x3f;
+               if (hash < 32)
+                       mchash[0] |= (1 << hash);
+               else
+                       mchash[1] |= (1 << (hash - 32));
+               ETHER_NEXT_MULTI(step, enm);
+       }
+       ifp->if_flags &= ~IFF_ALLMULTI;
+       goto setit;
+
+allmulti:
+       ifp->if_flags |= IFF_ALLMULTI;
+       mchash[0] = mchash[1] = 0xffffffff;
+
+setit:
+       TULIP_WRITE(sc, CSR_AX_FILTIDX, AX_FILTIDX_MAR0);
+       TULIP_WRITE(sc, CSR_AX_FILTDATA, mchash[0]);
+       TULIP_WRITE(sc, CSR_AX_FILTIDX, AX_FILTIDX_MAR1);
+       TULIP_WRITE(sc, CSR_AX_FILTDATA, mchash[1]);
+       TULIP_WRITE(sc, CSR_OPMODE, sc->sc_opmode);
+       DPRINTF(sc, ("%s: tlp_asix_filter_setup: returning\n",
+               sc->sc_dev.dv_xname));
+}
+
+
+/*
  * tlp_idle:
  *
  *     Cause the transmit and/or receive processes to go idle.
@@ -3065,9 +3185,18 @@
        if ((csr & ackmask) != ackmask) {
                if ((bits & OPMODE_ST) != 0 && (csr & STATUS_TPS) == 0 &&
                    (csr & STATUS_TS) != STATUS_TS_STOPPED) {
-                       printf("%s: transmit process failed to idle: "
-                           "state %s\n", sc->sc_dev.dv_xname,
-                           tx_state_names[(csr & STATUS_TS) >> 20]);
+                       switch (sc->sc_chip) {
+                       case TULIP_CHIP_AX88140:
+                       case TULIP_CHIP_AX88141:
+                               /*
+                                * Filter the message out on noisy chips.
+                                */
+                               break;
+                       default:
+                               printf("%s: transmit process failed to idle: "
+                                   "state %s\n", sc->sc_dev.dv_xname,
+                                   tx_state_names[(csr & STATUS_TS) >> 20]);
+                       }
                }
                if ((bits & OPMODE_SR) != 0 && (csr & STATUS_RPS) == 0 &&
                    (csr & STATUS_RS) != STATUS_RS_STOPPED) {
@@ -3544,6 +3673,30 @@
 }
 
 /*
+ * tlp_asix_preinit:
+ * 
+ *     Pre-init function for the ASIX chipsets.
+ */
+void
+tlp_asix_preinit(sc)
+       struct tulip_softc *sc;
+{
+
+       switch (sc->sc_chip) {
+               case TULIP_CHIP_AX88140:
+               case TULIP_CHIP_AX88141:
+                       /* XXX Handle PHY. */
+                       sc->sc_opmode |= OPMODE_HBD|OPMODE_PS; 
+                       break;
+               default:
+                       /* Nothing */
+                       break;
+       }
+
+       TULIP_WRITE(sc, CSR_OPMODE, sc->sc_opmode);
+}
+
+/*
  * tlp_dm9102_preinit:
  *
  *     Pre-init function for the Davicom DM9102.
@@ -6095,3 +6248,83 @@
        /* XXX HomePNA on DM9102A. */
        return (tlp_mii_setmedia(sc));
 }
+
+/*
+ * ASIX AX88140A/AX88141 media switch. Internal PHY or MII.
+ */
+
+void   tlp_asix_tmsw_init(struct tulip_softc *);
+void   tlp_asix_tmsw_getmedia(struct tulip_softc *, struct ifmediareq *);
+int    tlp_asix_tmsw_setmedia(struct tulip_softc *);
+
+const struct tulip_mediasw tlp_asix_mediasw = {
+       tlp_asix_tmsw_init, tlp_asix_tmsw_getmedia,
+       tlp_asix_tmsw_setmedia
+};
+
+void
+tlp_asix_tmsw_init(sc)
+       struct tulip_softc *sc;
+{
+       struct ifnet *ifp = &sc->sc_ethercom.ec_if;
+       u_int32_t opmode;
+
+       sc->sc_mii.mii_ifp = ifp;
+        sc->sc_mii.mii_readreg = tlp_bitbang_mii_readreg;
+        sc->sc_mii.mii_writereg = tlp_bitbang_mii_writereg;
+       sc->sc_mii.mii_statchg = sc->sc_statchg;
+       ifmedia_init(&sc->sc_mii.mii_media, 0, tlp_mediachange,
+            tlp_mediastatus);
+
+       /*
+        * Configure OPMODE properly for the internal MII interface.
+        */
+       switch (sc->sc_chip) {
+       case TULIP_CHIP_AX88140:
+       case TULIP_CHIP_AX88141:
+               opmode = OPMODE_HBD|OPMODE_PS;



Home | Main Index | Thread Index | Old Index