On Tuesday 28 July 2009 19:36:18 Brad wrote:
> Please test the following diff to rewrite the promisc mode / multicast
> handling code for the sparc hme(4) driver and is based off of the MI
> hme(4) driver.

I'm still looking for someone to test this..

>
> Index: hme.c
> ===================================================================
> RCS file: /cvs/src/sys/arch/sparc/dev/hme.c,v
> retrieving revision 1.61
> diff -u -p -r1.61 hme.c
> --- hme.c     16 Jul 2009 07:18:47 -0000      1.61
> +++ hme.c     17 Jul 2009 21:58:10 -0000
> @@ -126,7 +126,7 @@ int       hme_mii_read(struct device *, int, i
>  void hme_mii_write(struct device *, int, int, int);
>  void hme_mii_statchg(struct device *);
>
> -void hme_mcreset(struct hme_softc *);
> +void hme_iff(struct hme_softc *);
>
>  struct cfattach hme_ca = {
>       sizeof (struct hme_softc), hmematch, hmeattach
> @@ -445,7 +445,7 @@ hmeioctl(ifp, cmd, data)
>
>       if (error == ENETRESET) {
>               if (ifp->if_flags & IFF_RUNNING)
> -                     hme_mcreset(sc);
> +                     hme_iff(sc);
>               error = 0;
>       }
>
> @@ -575,7 +575,7 @@ hmeinit(sc)
>               printf("%s: setting rxreg->cfg failed.\n", sc->sc_dev.dv_xname);
>
>       cr->rx_cfg = 0;
> -     hme_mcreset(sc);
> +     hme_iff(sc);
>       DELAY(10);
>
>       cr->tx_cfg |= CR_TXCFG_DGIVEUP;
> @@ -959,89 +959,52 @@ hme_read(sc, idx, len, flags)
>       ether_input_mbuf(ifp, m);
>  }
>
> -/*
> - * Program the multicast receive filter.
> - */
>  void
> -hme_mcreset(sc)
> +hme_iff(sc)
>       struct hme_softc *sc;
>  {
>       struct arpcom *ac = &sc->sc_arpcom;
>       struct ifnet *ifp = &sc->sc_arpcom.ac_if;
>       struct hme_cr *cr = sc->sc_cr;
> -     u_int32_t crc;
> -     u_int16_t hash[4];
> -     u_int8_t octet;
> -     int i, j;
>       struct ether_multi *enm;
>       struct ether_multistep step;
> +     u_int32_t rxfg, crc;
> +     u_int32_t hash[4];
>
> -     if (ifp->if_flags & IFF_PROMISC) {
> -             cr->rx_cfg |= CR_RXCFG_PMISC;
> -             return;
> -     }
> -     else
> -             cr->rx_cfg &= ~CR_RXCFG_PMISC;
> +     rxcfg = cr->rx_cfg;
> +     rxcfg &= ~(CR_RXCFG_HENABLE | CR_RXCFG_PMISC);
> +     if->if_flags &= ~IFF_ALLMULTI;
> +     /* Clear hash table */
> +     hash[0] = hash[1] = hash[2] = hash[3] = 0;
>
> -     if (ifp->if_flags & IFF_ALLMULTI) {
> -             cr->htable3 = 0xffff;
> -             cr->htable2 = 0xffff;
> -             cr->htable1 = 0xffff;
> -             cr->htable0 = 0xffff;
> -             cr->rx_cfg |= CR_RXCFG_HENABLE;
> -             return;
> -     }
> -
> -     hash[3] = hash[2] = hash[1] = hash[0] = 0;
> -
> -     ETHER_FIRST_MULTI(step, ac, enm);
> -     while (enm != NULL) {
> -             if (bcmp(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.)
> -                      */
> -                     cr->htable3 = 0xffff;
> -                     cr->htable2 = 0xffff;
> -                     cr->htable1 = 0xffff;
> -                     cr->htable0 = 0xffff;
> -                     cr->rx_cfg |= CR_RXCFG_HENABLE;
> -                     ifp->if_flags |= IFF_ALLMULTI;
> -                     return;
> -             }
> -
> -             crc = 0xffffffff;
> +     if (ifp->if_flags & IFF_PROMISC) {
> +             ifp->if_flags |= IFF_ALLMULTI;
> +             rxcfg |= CR_RXCFG_PMISC;
> +     } else if (ac->ac_multirangecnt > 0) {
> +             ifp->if_flags |= IFF_ALLMULTI;
> +             rxcfg |= CR_RXFG_HENABLE;
> +             hash[0] = hash[1] = hash[2] = hash[3] = 0xffff;
> +     } else {
> +             rxcfg |= CR_RXFG_HENABLE;
> +
> +             ETHER_FIRST_MULTI(step, ac, enm);
> +             while (enm != NULL) {
> +                     crc = ether_crc32_le(enm->enm_addrlo,
> +                         ETHER_ADDR_LEN) >> 26;
>
> -             for (i = 0; i < ETHER_ADDR_LEN; i++) {
> -                     octet = enm->enm_addrlo[i];
> +                     /* Set the corresponding bit in the filter. */
> +                     hash[crc >> 4] |= 1 << (crc & 0xf);
>
> -                     for (j = 0; j < 8; j++) {
> -                             if ((crc & 1) ^ (octet & 1)) {
> -                                     crc >>= 1;
> -                                     crc ^= ETHER_CRC_POLY_LE;
> -                             }
> -                             else
> -                                     crc >>= 1;
> -                             octet >>= 1;
> -                     }
> +                     ETHER_NEXT_MULTI(step, enm);
>               }
> -
> -             crc >>=26;
> -             hash[crc >> 4] |= 1 << (crc & 0xf);
> -             ETHER_NEXT_MULTI(step, enm);
>       }
> -     cr->htable3 = hash[3];
> -     cr->htable2 = hash[2];
> -     cr->htable1 = hash[1];
> +
> +     /* Now load the hash table into the chip */
>       cr->htable0 = hash[0];
> -     cr->rx_cfg |= CR_RXCFG_HENABLE;
> -     ifp->if_flags &= ~IFF_ALLMULTI;
> +     cr->htable1 = hash[1];
> +     cr->htable2 = hash[2];
> +     cr->htable3 = hash[3];
> +     cr->rx_cfg = rxcfg;
>  }
>
>  /*

-- 
This message has been scanned for viruses and
dangerous content by MailScanner, and is
believed to be clean.

Reply via email to