Source-Changes-HG archive

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

[src/trunk]: src/sys/dev/ic Many fixes. Multicast hash filter works now. Au...



details:   https://anonhg.NetBSD.org/src/rev/32852abf25d1
branches:  trunk
changeset: 526799:32852abf25d1
user:      matt <matt%NetBSD.org@localhost>
date:      Sat May 11 00:36:02 2002 +0000

description:
Many fixes.  Multicast hash filter works now.  Autonegotiation with GigE
on Mac G4's now works.  XXX Checksum offload still needs to be done.

diffstat:

 sys/dev/ic/gem.c    |  186 +++++++++++++++++++++++++++++++--------------------
 sys/dev/ic/gemreg.h |   11 +-
 sys/dev/ic/gemvar.h |   10 ++-
 3 files changed, 129 insertions(+), 78 deletions(-)

diffs (truncated from 431 to 300 lines):

diff -r 126ec56e155b -r 32852abf25d1 sys/dev/ic/gem.c
--- a/sys/dev/ic/gem.c  Fri May 10 23:21:17 2002 +0000
+++ b/sys/dev/ic/gem.c  Sat May 11 00:36:02 2002 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: gem.c,v 1.14 2002/05/08 02:12:55 matt Exp $ */
+/*     $NetBSD: gem.c,v 1.15 2002/05/11 00:36:02 matt Exp $ */
 
 /*
  * 
@@ -34,7 +34,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: gem.c,v 1.14 2002/05/08 02:12:55 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: gem.c,v 1.15 2002/05/11 00:36:02 matt Exp $");
 
 #include "bpfilter.h"
 
@@ -132,7 +132,9 @@
        struct ifnet *ifp = &sc->sc_ethercom.ec_if;
        struct mii_data *mii = &sc->sc_mii;
        struct mii_softc *child;
+       struct ifmedia_entry *ifm;
        int i, error;
+       u_int32_t v;
 
        /* Make sure the chip is stopped. */
        ifp->if_softc = sc;
@@ -189,8 +191,9 @@
 
                txs = &sc->sc_txsoft[i];
                txs->txs_mbuf = NULL;
-               if ((error = bus_dmamap_create(sc->sc_dmatag, MCLBYTES,
-                   GEM_NTXSEGS, MCLBYTES, 0, 0,
+               if ((error = bus_dmamap_create(sc->sc_dmatag,
+                   ETHER_MAX_LEN_JUMBO, GEM_NTXSEGS,
+                   ETHER_MAX_LEN_JUMBO, 0, 0,
                    &txs->txs_dmamap)) != 0) {
                        printf("%s: unable to create tx DMA map %d, "
                            "error = %d\n", sc->sc_dev.dv_xname, i, error);
@@ -219,9 +222,18 @@
         */
 
        /* Announce ourselves. */
-       printf("%s: Ethernet address %s\n", sc->sc_dev.dv_xname,
+       printf("%s: Ethernet address %s", sc->sc_dev.dv_xname,
            ether_sprintf(enaddr));
 
+       /* Get RX FIFO size */
+       sc->sc_rxfifosize = 64 *
+           bus_space_read_4(sc->sc_bustag, sc->sc_h, GEM_RX_FIFO_SIZE); 
+       printf(", %uKB RX fifo", sc->sc_rxfifosize / 1024);
+
+       /* Get TX FIFO size */
+       v = bus_space_read_4(sc->sc_bustag, sc->sc_h, GEM_TX_FIFO_SIZE); 
+       printf(", %uKB TX fifo\n", v / 16);
+
        /* Initialize ifnet structure. */
        strcpy(ifp->if_xname, sc->sc_dev.dv_xname);
        ifp->if_softc = sc;
@@ -276,6 +288,7 @@
                        }
 
                        sc->sc_phys[child->mii_inst] = child->mii_phy;
+                       
                }
 
                /*
@@ -305,6 +318,24 @@
                ifmedia_set(&sc->sc_media, IFM_ETHER|IFM_AUTO);
        }
 
+       /*
+        * If we support GigE media, we support jumbo frames too.
+        * Unless we are Apple.
+        */
+       TAILQ_FOREACH(ifm, &sc->sc_media.ifm_list, ifm_list) {
+               if (IFM_SUBTYPE(ifm->ifm_media) == IFM_1000_T ||
+                   IFM_SUBTYPE(ifm->ifm_media) == IFM_1000_SX ||
+                   IFM_SUBTYPE(ifm->ifm_media) == IFM_1000_LX ||
+                   IFM_SUBTYPE(ifm->ifm_media) == IFM_1000_CX) {
+                       if (sc->sc_variant != GEM_APPLE_GMAC)
+                               sc->sc_ethercom.ec_capabilities
+                                   |= ETHERCAP_JUMBO_MTU;
+
+                       sc->sc_flags |= GEM_GIGABIT;
+                       break;
+               }
+       }
+
        /* claim 802.1q capability */
        sc->sc_ethercom.ec_capabilities |= ETHERCAP_VLAN_MTU;
 
@@ -705,6 +736,7 @@
        bus_space_tag_t t = sc->sc_bustag;
        bus_space_handle_t h = sc->sc_h;
        int s;
+       u_int max_frame_size;
        u_int32_t v;
 
        s = splnet();
@@ -734,10 +766,12 @@
 
        /* step 4. TX MAC registers & counters */
        gem_init_regs(sc);
+       max_frame_size = max(sc->sc_ethercom.ec_if.if_mtu, ETHERMTU);
+       max_frame_size += ETHER_HDR_LEN + ETHER_CRC_LEN;
+       if (sc->sc_ethercom.ec_capenable & ETHERCAP_VLAN_MTU)
+               max_frame_size += ETHER_VLAN_ENCAP_LEN;
        bus_space_write_4(t, h, GEM_MAC_MAC_MAX_FRAME,
-           ((sc->sc_ethercom.ec_capenable & ETHERCAP_VLAN_MTU) ?
-           ETHER_VLAN_ENCAP_LEN + ETHER_MAX_LEN  + sizeof(struct ether_header):
-            ETHER_MAX_LEN + sizeof(struct ether_header)) | (0x2000<<16));
+           max_frame_size|/* burst size */(0x2000<<16));
 
        /* step 5. RX MAC registers & counters */
        gem_setladrf(sc);
@@ -782,14 +816,16 @@
                (2<<GEM_RX_CONFIG_FBOFF_SHFT)|GEM_RX_CONFIG_RXDMA_EN|
                (0<<GEM_RX_CONFIG_CXM_START_SHFT));
        /*
-        * The following value is for an OFF Threshold of about 15.5 Kbytes
-        * and an ON Threshold of 4K bytes.
+        * The following value is for an OFF Threshold of about 3/4 full
+        * and an ON Threshold of 1/4 full.
         */
-       bus_space_write_4(t, h, GEM_RX_PAUSE_THRESH, 0xf8 | (0x40 << 12));
-       bus_space_write_4(t, h, GEM_RX_BLANKING, (2<<12)|6);
+       bus_space_write_4(t, h, GEM_RX_PAUSE_THRESH,
+            (3 * sc->sc_rxfifosize / 256) |
+            (   (sc->sc_rxfifosize / 256) << 12));
+       bus_space_write_4(t, h, GEM_RX_BLANKING, (6<<12)|6);
 
        /* step 11. Configure Media */
-       gem_mii_statchg(&sc->sc_dev);
+       mii_mediachg(&sc->sc_mii);
 
 /* XXXX Serial link needs a whole different setup. */
 
@@ -827,6 +863,7 @@
        bus_space_tag_t t = sc->sc_bustag;
        bus_space_handle_t h = sc->sc_h;
        const u_char *laddr = LLADDR(ifp->if_sadl);
+       u_int32_t v;
 
        /* These regs are not cleared on reset */
        if (!sc->sc_inited) {
@@ -839,14 +876,15 @@
                bus_space_write_4(t, h, GEM_MAC_MAC_MIN_FRAME, ETHER_MIN_LEN);
                /* Max frame and max burst size */
                bus_space_write_4(t, h, GEM_MAC_MAC_MAX_FRAME,
-                       (ifp->if_mtu+18) | (0x2000<<16)/* Burst size */);
+                    ETHER_MAX_LEN | (0x2000<<16));
+
                bus_space_write_4(t, h, GEM_MAC_PREAMBLE_LEN, 0x7);
                bus_space_write_4(t, h, GEM_MAC_JAM_SIZE, 0x4);
                bus_space_write_4(t, h, GEM_MAC_ATTEMPT_LIMIT, 0x10);
                /* Dunno.... */
                bus_space_write_4(t, h, GEM_MAC_CONTROL_TYPE, 0x8088);
                bus_space_write_4(t, h, GEM_MAC_RANDOM_SEED,
-                       ((laddr[5]<<8)|laddr[4])&0x3ff);
+                   ((laddr[5]<<8)|laddr[4])&0x3ff);
 
                /* Secondary MAC addr set to 0:0:0:0:0:0 */
                bus_space_write_4(t, h, GEM_MAC_ADDR3, 0);
@@ -896,9 +934,23 @@
        bus_space_write_4(t, h, GEM_MAC_ADDR1, (laddr[2]<<8)|laddr[3]);
        bus_space_write_4(t, h, GEM_MAC_ADDR2, (laddr[0]<<8)|laddr[1]);
 
-}
+#if 0
+       if (sc->sc_variant != APPLE_GMAC)
+               return;
+#endif
 
-
+       /*
+        * Enable MII outputs.  Enable GMII if there is a gigabit PHY.
+        */
+       sc->sc_mif_config = bus_space_read_4(t, h, GEM_MIF_CONFIG);
+       v = GEM_MAC_XIF_TX_MII_ENA;
+       if (sc->sc_mif_config & GEM_MIF_CONFIG_MDI1) {
+               v |= GEM_MAC_XIF_FDPLX_LED;
+               if (sc->sc_flags & GEM_GIGABIT)
+                       v |= GEM_MAC_XIF_GMII_MODE;
+       }
+       bus_space_write_4(t, h, GEM_MAC_XIF_CONFIG, v);
+}
 
 void
 gem_start(ifp)
@@ -948,6 +1000,13 @@
                 */
                if (bus_dmamap_load_mbuf(sc->sc_dmatag, dmamap, m0,
                      BUS_DMA_WRITE|BUS_DMA_NOWAIT) != 0) {
+                       if (m0->m_pkthdr.len > MCLBYTES) {
+                               printf("%s: unable to allocate jumbo Tx "
+                                   "cluster\n", sc->sc_dev.dv_xname);
+                               IFQ_DEQUEUE(&ifp->if_snd, m0);
+                               m_freem(m0);
+                               continue;
+                       }
                        MGETHDR(m, M_DONTWAIT, MT_DATA);
                        if (m == NULL) {
                                printf("%s: unable to allocate Tx mbuf\n",
@@ -1636,6 +1695,7 @@
        v = bus_space_read_4(t, mac, GEM_MAC_XIF_CONFIG);
        v = GEM_MAC_XIF_LINK_LED;
        v |= GEM_MAC_XIF_TX_MII_ENA;
+
        /* If an external transceiver is connected, enable its MII drivers */
        sc->sc_mif_config = bus_space_read_4(t, mac, GEM_MIF_CONFIG);
        if ((sc->sc_mif_config & GEM_MIF_CONFIG_MDI1) != 0) {
@@ -1643,9 +1703,10 @@
                if ((IFM_OPTIONS(sc->sc_mii.mii_media_active) & IFM_FDX) != 0)
                        /* turn on full duplex LED */
                        v |= GEM_MAC_XIF_FDPLX_LED;
-                       else
-                               /* half duplex -- disable echo */
-                               v |= GEM_MAC_XIF_ECHO_DISABL;
+               else
+                       /* half duplex -- disable echo */
+                       v |= GEM_MAC_XIF_ECHO_DISABL;
+
                if (sc->sc_ethercom.ec_if.if_baudrate == IF_Mbps(1000))
                        v |= GEM_MAC_XIF_GMII_MODE;
                else
@@ -1746,44 +1807,46 @@
 gem_setladrf(sc)
        struct gem_softc *sc;
 {
-       struct ifnet *ifp = &sc->sc_ethercom.ec_if;
+       struct ethercom *ec = &sc->sc_ethercom;
+       struct ifnet *ifp = &ec->ec_if;
        struct ether_multi *enm;
        struct ether_multistep step;
-       struct ethercom *ec = &sc->sc_ethercom;
        bus_space_tag_t t = sc->sc_bustag;
        bus_space_handle_t h = sc->sc_h;
-       u_char *cp;
        u_int32_t crc;
        u_int32_t hash[16];
        u_int32_t v;
-       int len;
-
-       /* Clear hash table */
-       memset(hash, 0, sizeof(hash));
+       int i;
 
        /* Get current RX configuration */
        v = bus_space_read_4(t, h, GEM_MAC_RX_CONFIG);
 
+       /*
+        * Turn off promiscuous mode, promiscuous group mode (all multicast),
+        * and hash filter.  Depending on the case, the right bit will be
+        * enabled.
+        */
+       v &= ~(GEM_MAC_RX_PROMISCUOUS|GEM_MAC_RX_HASH_FILTER|
+           GEM_MAC_RX_PROMISC_GRP);
+
        if ((ifp->if_flags & IFF_PROMISC) != 0) {
-               /* Turn on promiscuous mode; turn off the hash filter */
+               /* Turn on promiscuous mode */
                v |= GEM_MAC_RX_PROMISCUOUS;
-               v &= ~GEM_MAC_RX_HASH_FILTER;
                ifp->if_flags |= IFF_ALLMULTI;
                goto chipit;
        }
 
-       /* Turn off promiscuous mode; turn on the hash filter */
-       v &= ~GEM_MAC_RX_PROMISCUOUS;
-       v |= GEM_MAC_RX_HASH_FILTER;
-
        /*
         * Set up multicast address filter by passing all multicast addresses
-        * through a crc generator, and then using the high order 6 bits as an
-        * index into the 256 bit logical address filter.  The high order bit
-        * selects the word, while the rest of the bits select the bit within
-        * the word.
+        * through a crc generator, and then using the high order 8 bits as an
+        * index into the 256 bit logical address filter.  The high order 4
+        * bits select the word, while the other 4 bits select the bit within
+        * the word (where bit 0 is the MSB).
         */
 
+       /* Clear hash table */
+       memset(hash, 0, sizeof(hash));
+
        ETHER_FIRST_MULTI(step, ec, enm);
        while (enm != NULL) {
                if (memcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) {
@@ -1794,59 +1857,36 @@
                         * 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.)
+                        * XXX use the addr filter for this
                         */
-                       hash[3] = hash[2] = hash[1] = hash[0] = 0xffff;
                        ifp->if_flags |= IFF_ALLMULTI;
+                       v |= GEM_MAC_RX_PROMISC_GRP;



Home | Main Index | Thread Index | Old Index