Source-Changes-HG archive

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

[src/netbsd-1-5]: src/sys/dev/pci Pull up revisions 1.25-1.26 (requested by b...



details:   https://anonhg.NetBSD.org/src/rev/2ec44c0a94d4
branches:  netbsd-1-5
changeset: 490845:2ec44c0a94d4
user:      he <he%NetBSD.org@localhost>
date:      Tue Mar 13 20:26:01 2001 +0000

description:
Pull up revisions 1.25-1.26 (requested by briggs):
  Fix support for the DP83815 so that it works properly with the
  current crop of Netgear FA311 10/100 cards.

diffstat:

 sys/dev/pci/if_sip.c |  173 +++++++++++++++++++++++++++++++++++++++++---------
 1 files changed, 142 insertions(+), 31 deletions(-)

diffs (262 lines):

diff -r f741addbeaff -r 2ec44c0a94d4 sys/dev/pci/if_sip.c
--- a/sys/dev/pci/if_sip.c      Tue Mar 13 20:25:44 2001 +0000
+++ b/sys/dev/pci/if_sip.c      Tue Mar 13 20:26:01 2001 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_sip.c,v 1.11.4.4 2001/02/26 17:03:33 he Exp $       */
+/*     $NetBSD: if_sip.c,v 1.11.4.5 2001/03/13 20:26:01 he Exp $       */
 
 /*-
  * Copyright (c) 1999 Network Computer, Inc.
@@ -269,6 +269,9 @@
 void   sip_sis900_set_filter __P((struct sip_softc *));
 void   sip_dp83815_set_filter __P((struct sip_softc *));
 
+void   sip_sis900_read_macaddr __P((struct sip_softc *, u_int8_t *));
+void   sip_dp83815_read_macaddr __P((struct sip_softc *, u_int8_t *));
+
 int    sip_intr __P((void *));
 void   sip_txintr __P((struct sip_softc *));
 void   sip_rxintr __P((struct sip_softc *));
@@ -301,16 +304,19 @@
        void    (*sipv_mii_writereg) __P((struct device *, int, int, int));
        void    (*sipv_mii_statchg) __P((struct device *));
        void    (*sipv_set_filter) __P((struct sip_softc *));
+       void    (*sipv_read_macaddr) __P((struct sip_softc *, u_int8_t *));
 };
 
 const struct sip_variant sip_variant_sis900 = {
        sip_sis900_mii_readreg, sip_sis900_mii_writereg,
-           sip_sis900_mii_statchg, sip_sis900_set_filter
+           sip_sis900_mii_statchg, sip_sis900_set_filter,
+           sip_sis900_read_macaddr
 };
 
 const struct sip_variant sip_variant_dp83815 = {
        sip_dp83815_mii_readreg, sip_dp83815_mii_writereg,
-           sip_dp83815_mii_statchg, sip_dp83815_set_filter
+           sip_dp83815_mii_statchg, sip_dp83815_set_filter,
+           sip_dp83815_read_macaddr
 };
 
 /*
@@ -386,7 +392,6 @@
        int i, rseg, error;
        const struct sip_product *sip;
        pcireg_t pmode;
-       u_int16_t myea[ETHER_ADDR_LEN / 2];
        u_int8_t enaddr[ETHER_ADDR_LEN];
        int pmreg;
 
@@ -543,15 +548,7 @@
        /*
         * Read the Ethernet address from the EEPROM.
         */
-       sip_read_eeprom(sc, SIP_EEPROM_ETHERNET_ID0 >> 1,
-           sizeof(myea) / sizeof(myea[0]), myea);
-
-       enaddr[0] = myea[0] & 0xff;
-       enaddr[1] = myea[0] >> 8;
-       enaddr[2] = myea[1] & 0xff;
-       enaddr[3] = myea[1] >> 8;
-       enaddr[4] = myea[2] & 0xff;
-       enaddr[5] = myea[2] >> 8;
+       sip->sip_variant->sipv_read_macaddr(sc, enaddr);
 
        printf("%s: Ethernet address %s\n", sc->sc_dev.dv_xname,
            ether_sprintf(enaddr));
@@ -1415,6 +1412,36 @@
         */
        sip_reset(sc);
 
+       if (   sc->sc_model->sip_vendor == PCI_VENDOR_NS
+           && sc->sc_model->sip_product == PCI_PRODUCT_NS_DP83815) {
+               /*
+                * DP83815 manual, page 78:
+                *    4.4 Recommended Registers Configuration
+                *    For optimum performance of the DP83815, version noted
+                *    as DP83815CVNG (SRR = 203h), the listed register
+                *    modifications must be followed in sequence...
+                *
+                * It's not clear if this should be 302h or 203h because that
+                * chip name is listed as SRR 302h in the description of the
+                * SRR register.  However, my revision 302h DP83815 on the
+                * Netgear FA311 purchased in 02/2001 needs these settings
+                * to avoid tons of errors in AcceptPerfectMatch (non-
+                * IFF_PROMISC) mode.  I do not know if other revisions need
+                * this set or not.  [briggs -- 09 March 2001]
+                *
+                * Note that only the low-order 12 bits of 0xe4 are documented
+                * and that this sets reserved bits in that register.
+                */
+               cfg = bus_space_read_4(st, sh, SIP_NS_SRR);
+               if (cfg == 0x302) {
+                       bus_space_write_4(st, sh, 0x00cc, 0x0001);
+                       bus_space_write_4(st, sh, 0x00e4, 0x189C);
+                       bus_space_write_4(st, sh, 0x00fc, 0x0000);
+                       bus_space_write_4(st, sh, 0x00f4, 0x5040);
+                       bus_space_write_4(st, sh, 0x00f8, 0x008c);
+               }
+       }
+
        /*
         * Initialize the transmit descriptor ring.
         */
@@ -1926,6 +1953,11 @@
 
        /*
         * Initialize the prototype RFCR.
+        * Enable the receive filter, and accept ARP
+        * and on Perfect (destination address) Match
+        * If IFF_BROADCAST, also accept all broadcast packets.
+        * If IFF_PROMISC, accept all unicast packets (and later, set
+        *    IFF_ALLMULTI and accept all multicast, too).
         */
        sc->sc_rfcr = RFCR_RFEN | RFCR_AARP | RFCR_APM;
        if (ifp->if_flags & IFF_BROADCAST)
@@ -1946,9 +1978,12 @@
 
        memset(mchash, 0, sizeof(mchash));
 
+       ifp->if_flags &= ~IFF_ALLMULTI;
        ETHER_FIRST_MULTI(step, ec, enm);
-       while (enm != NULL) {
-               if (memcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) {
+       if (enm != NULL) {
+               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
@@ -1957,22 +1992,22 @@
                         * ranges is for IP multicast routing, for which the
                         * range is big enough to require all bits set.)
                         */
-                       goto allmulti;
+                               goto allmulti;
+                       }
+
+                       crc = ether_crc32_le(enm->enm_addrlo, ETHER_ADDR_LEN);
+
+                       /* Just want the 9 most significant bits. */
+                       crc >>= 23;
+
+                       /* Set the corresponding bit in the hash table. */
+                       mchash[crc >> 5] |= 1 << (crc & 0x1f);
+
+                       ETHER_NEXT_MULTI(step, enm);
                }
 
-               crc = ether_crc32_le(enm->enm_addrlo, ETHER_ADDR_LEN);
-
-               /* Just want the 9 most significant bits. */
-               crc >>= 23;
-
-               /* Set the corresponding bit in the hash table. */
-               mchash[crc >> 5] |= 1 << (crc & 0x1f);
-
-               ETHER_NEXT_MULTI(step, enm);
+               sc->sc_rfcr |= RFCR_MHEN;
        }
-
-       ifp->if_flags &= ~IFF_ALLMULTI;
-       sc->sc_rfcr |= RFCR_MHEN;
        goto setit;
 
  allmulti:
@@ -1990,9 +2025,9 @@
         * Disable receive filter, and program the node address.
         */
        cp = LLADDR(ifp->if_sadl);
-       FILTER_EMIT(RFCR_NS_RFADDR_PMATCH, (cp[1] << 8) | cp[0]);
-       FILTER_EMIT(RFCR_NS_RFADDR_PMATCH, (cp[3] << 8) | cp[2]);
-       FILTER_EMIT(RFCR_NS_RFADDR_PMATCH, (cp[5] << 8) | cp[4]);
+       FILTER_EMIT(RFCR_NS_RFADDR_PMATCH0, (cp[1] << 8) | cp[0]);
+       FILTER_EMIT(RFCR_NS_RFADDR_PMATCH2, (cp[3] << 8) | cp[2]);
+       FILTER_EMIT(RFCR_NS_RFADDR_PMATCH4, (cp[5] << 8) | cp[4]);
 
        if ((ifp->if_flags & IFF_ALLMULTI) == 0) {
                /*
@@ -2211,6 +2246,82 @@
        bus_space_write_4(sc->sc_st, sc->sc_sh, SIP_RXCFG, sc->sc_rxcfg);
 }
 
+void
+sip_sis900_read_macaddr(sc, enaddr)
+       struct sip_softc *sc;
+       u_int8_t *enaddr;
+{
+       u_int16_t myea[ETHER_ADDR_LEN / 2];
+
+       sip_read_eeprom(sc, SIP_EEPROM_ETHERNET_ID0 >> 1,
+           sizeof(myea) / sizeof(myea[0]), myea);
+
+       enaddr[0] = myea[0] & 0xff;
+       enaddr[1] = myea[0] >> 8;
+       enaddr[2] = myea[1] & 0xff;
+       enaddr[3] = myea[1] >> 8;
+       enaddr[4] = myea[2] & 0xff;
+       enaddr[5] = myea[2] >> 8;
+}
+
+static u_char bbr4[] = {0,8,4,12,2,10,6,14,1,9,5,13,3,11,7,15};
+#define bbr(v) ((bbr4[(v)&0xf] << 4) | bbr4[((v)>>4) & 0xf])
+
+void
+sip_dp83815_read_macaddr(sc, enaddr)
+       struct sip_softc *sc;
+       u_int8_t *enaddr;
+{
+       u_int16_t eeprom_data[SIP_DP83815_EEPROM_LENGTH / 2], *ea;
+       u_int8_t cksum, *e, match;
+       int i;
+
+       sip_read_eeprom(sc, 0, sizeof(eeprom_data) / sizeof(eeprom_data[0]),
+           eeprom_data);
+
+       match = eeprom_data[SIP_DP83815_EEPROM_CHECKSUM/2] >> 8;
+       match = ~(match - 1);
+
+       cksum = 0x55;
+       e = (u_int8_t *) eeprom_data;
+       for (i=0 ; i<SIP_DP83815_EEPROM_CHECKSUM ; i++) {
+               cksum += *e++;
+       }
+       if (cksum != match) {
+               printf("%s: Checksum (%x) mismatch (%x)",
+                   sc->sc_dev.dv_xname, cksum, match);
+       }
+
+       /*
+        * Unrolled because it makes slightly more sense this way.
+        * The DP83815 stores the MAC address in bit 0 of word 6
+        * through bit 15 of word 8.
+        */
+       ea = &eeprom_data[6];
+       enaddr[0] = ((*ea & 0x1) << 7);
+       ea++;
+       enaddr[0] |= ((*ea & 0xFE00) >> 9);
+       enaddr[1] = ((*ea & 0x1FE) >> 1);
+       enaddr[2] = ((*ea & 0x1) << 7);
+       ea++;
+       enaddr[2] |= ((*ea & 0xFE00) >> 9);
+       enaddr[3] = ((*ea & 0x1FE) >> 1);
+       enaddr[4] = ((*ea & 0x1) << 7);
+       ea++;
+       enaddr[4] |= ((*ea & 0xFE00) >> 9);
+       enaddr[5] = ((*ea & 0x1FE) >> 1);
+
+       /*
+        * In case that's not weird enough, we also need to reverse
+        * the bits in each byte.  This all actually makes more sense
+        * if you think about the EEPROM storage as an array of bits
+        * being shifted into bytes, but that's not how we're looking
+        * at it here...
+        */
+       for (i=0 ; i<6 ; i++)
+               enaddr[i] = bbr(enaddr[i]);
+}
+
 /*
  * sip_mediastatus:    [ifmedia interface function]
  *



Home | Main Index | Thread Index | Old Index