Source-Changes-HG archive

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

[src/trunk]: src/sys/dev/qbus Set up multicast (input) filter on qt (DELQA-Tu...



details:   https://anonhg.NetBSD.org/src/rev/6ea33fcc5ed2
branches:  trunk
changeset: 1029066:6ea33fcc5ed2
user:      rhialto <rhialto%NetBSD.org@localhost>
date:      Mon Dec 20 17:12:41 2021 +0000

description:
Set up multicast (input) filter on qt (DELQA-Turbo).

diffstat:

 sys/dev/qbus/if_qt.c    |  71 ++++++++++++++++++++++++++++++++++++++++++++++--
 sys/dev/qbus/if_qtreg.h |  26 ++++++++--------
 2 files changed, 81 insertions(+), 16 deletions(-)

diffs (146 lines):

diff -r 0b2be7f95c45 -r 6ea33fcc5ed2 sys/dev/qbus/if_qt.c
--- a/sys/dev/qbus/if_qt.c      Mon Dec 20 14:52:25 2021 +0000
+++ b/sys/dev/qbus/if_qt.c      Mon Dec 20 17:12:41 2021 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_qt.c,v 1.25 2020/01/29 05:57:21 thorpej Exp $       */
+/*     $NetBSD: if_qt.c,v 1.26 2021/12/20 17:12:41 rhialto Exp $       */
 /*
  * Copyright (c) 1992 Steven M. Schultz
  * All rights reserved.
@@ -80,7 +80,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_qt.c,v 1.25 2020/01/29 05:57:21 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_qt.c,v 1.26 2021/12/20 17:12:41 rhialto Exp $");
 
 #include "opt_inet.h"
 
@@ -162,6 +162,7 @@
 
 static int qtmatch(device_t, cfdata_t, void *);
 static void qtattach(device_t, device_t, void *);
+static void lance_setladrf(struct ethercom *ec, uint16_t *af);
 static void qtintr(void *);
 static int qtinit(struct ifnet *);
 static int qtioctl(struct ifnet *, u_long, void *);
@@ -332,6 +333,67 @@
        return(1);
 }
 
+#define ETHER_CMP(a,b) memcmp((a), (b), 6)
+
+/*
+ * Set up the logical address filter.
+ */
+void
+lance_setladrf(struct ethercom *ec, uint16_t *af)
+{
+       struct ifnet *ifp = &ec->ec_if;
+       struct ether_multi *enm;
+       uint32_t crc;
+       struct ether_multistep step;
+
+       /*
+        * 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 64 bit logical address filter.  The high order bit
+        * selects the word, while the rest of the bits select the bit within
+        * the word.
+        */
+
+       if (ifp->if_flags & IFF_PROMISC)
+               goto allmulti;
+
+       af[0] = af[1] = af[2] = af[3] = 0x0000;
+
+       ETHER_LOCK(ec);
+       ETHER_FIRST_MULTI(step, ec, enm);
+       while (enm != NULL) {
+               if (ETHER_CMP(enm->enm_addrlo, enm->enm_addrhi)) {
+                       /*
+                        * 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.)
+                        */
+                       ETHER_UNLOCK(ec);
+                       goto allmulti;
+               }
+
+               crc = ether_crc32_le(enm->enm_addrlo, ETHER_ADDR_LEN);
+
+               /* Just want the 6 most significant bits. */
+               crc >>= 26;
+
+               /* Set the corresponding bit in the filter. */
+               af[crc >> 4] |= 1 << (crc & 0xf);
+
+               ETHER_NEXT_MULTI(step, enm);
+       }
+       ETHER_UNLOCK(ec);
+       ifp->if_flags &= ~IFF_ALLMULTI;
+       return;
+
+allmulti:
+       ifp->if_flags |= IFF_ALLMULTI;
+       af[0] = af[1] = af[2] = af[3] = 0xffff;
+}
+
 int
 qtinit(struct ifnet *ifp)
 {
@@ -388,7 +450,10 @@
        }
        iniblk = &sc->sc_ib->qc_init;
        iniblk->mode = ifp->if_flags & IFF_PROMISC ? INIT_MODE_PRO : 0;
-
+/*
+ * The multicast filter works "like LANCE".
+ */
+       lance_setladrf(&sc->is_ec, iniblk->laddr);
 
 /*
  * Now initialize the receive ring descriptors.  Because this routine can be
diff -r 0b2be7f95c45 -r 6ea33fcc5ed2 sys/dev/qbus/if_qtreg.h
--- a/sys/dev/qbus/if_qtreg.h   Mon Dec 20 14:52:25 2021 +0000
+++ b/sys/dev/qbus/if_qtreg.h   Mon Dec 20 17:12:41 2021 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_qtreg.h,v 1.5 2005/12/11 12:23:29 christos Exp $    */
+/*     $NetBSD: if_qtreg.h,v 1.6 2021/12/20 17:12:41 rhialto Exp $     */
 /*
  * Copyright (c) 1992 Steven M. Schultz
  * All rights reserved.
@@ -207,18 +207,18 @@
 
        struct  qt_init
                {
-               short   mode;
-               u_char  paddr[6];       /* 48 bit physical address */
-               u_char  laddr[8];       /* 64 bit logical address filter */
-               u_short rx_lo;          /* low 16 bits of receive ring addr */
-               u_short rx_hi;          /* high 6 bits of receive ring addr */
-               u_short tx_lo;          /* low 16 bits of transmit ring addr */
-               u_short tx_hi;          /* high 6 bits of transmit ring addr */
-               u_short options;
-               u_short vector;
-               u_short hit;
-               char    passwd[6];
-               char    pad[4];         /* even on 40 byte for alignment */
+               int16_t         mode;
+               u_char          paddr[6];       /* 48 bit physical address */
+               uint16_t        laddr[4];       /* 64 bit logical address filter */
+               uint16_t        rx_lo;          /* low 16 bits of receive ring addr */
+               uint16_t        rx_hi;          /* high 6 bits of receive ring addr */
+               uint16_t        tx_lo;          /* low 16 bits of transmit ring addr */
+               uint16_t        tx_hi;          /* high 6 bits of transmit ring addr */
+               uint16_t        options;
+               uint16_t        vector;
+               uint16_t        hit;
+               char            passwd[6];
+               char            pad[4];         /* even on 40 byte for alignment */
                };
 
 #define        INIT_MODE_PRO   0x8000          /* Promiscuous mode */



Home | Main Index | Thread Index | Old Index