Tue Mar 31 23:26:32 2020 UTC ()
iron out multicast filter logic and pick better name for its work


(nisimura)
diff -r1.5 -r1.6 src/sys/dev/usb/if_mos.c

cvs diff -r1.5 -r1.6 src/sys/dev/usb/if_mos.c (expand / switch to unified diff)

--- src/sys/dev/usb/if_mos.c 2020/03/15 23:04:50 1.5
+++ src/sys/dev/usb/if_mos.c 2020/03/31 23:26:32 1.6
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: if_mos.c,v 1.5 2020/03/15 23:04:50 thorpej Exp $ */ 1/* $NetBSD: if_mos.c,v 1.6 2020/03/31 23:26:32 nisimura Exp $ */
2/* $OpenBSD: if_mos.c,v 1.40 2019/07/07 06:40:10 kevlo Exp $ */ 2/* $OpenBSD: if_mos.c,v 1.40 2019/07/07 06:40:10 kevlo Exp $ */
3 3
4/* 4/*
5 * Copyright (c) 2008 Johann Christian Rode <jcrode@gmx.net> 5 * Copyright (c) 2008 Johann Christian Rode <jcrode@gmx.net>
6 * 6 *
7 * Permission to use, copy, modify, and distribute this software for any 7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above 8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies. 9 * copyright notice and this permission notice appear in all copies.
10 * 10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
@@ -62,27 +62,27 @@ @@ -62,27 +62,27 @@
62 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 62 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
63 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 63 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
64 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 64 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
65 * THE POSSIBILITY OF SUCH DAMAGE. 65 * THE POSSIBILITY OF SUCH DAMAGE.
66 */ 66 */
67 67
68/* 68/*
69 * Moschip MCS7730/MCS7830/MCS7832 USB to Ethernet controller  69 * Moschip MCS7730/MCS7830/MCS7832 USB to Ethernet controller
70 * The datasheet is available at the following URL:  70 * The datasheet is available at the following URL:
71 * http://www.moschip.com/data/products/MCS7830/Data%20Sheet_7830.pdf 71 * http://www.moschip.com/data/products/MCS7830/Data%20Sheet_7830.pdf
72 */ 72 */
73 73
74#include <sys/cdefs.h> 74#include <sys/cdefs.h>
75__KERNEL_RCSID(0, "$NetBSD: if_mos.c,v 1.5 2020/03/15 23:04:50 thorpej Exp $"); 75__KERNEL_RCSID(0, "$NetBSD: if_mos.c,v 1.6 2020/03/31 23:26:32 nisimura Exp $");
76 76
77#include <sys/param.h> 77#include <sys/param.h>
78 78
79#include <dev/usb/usbnet.h> 79#include <dev/usb/usbnet.h>
80#include <dev/usb/if_mosreg.h> 80#include <dev/usb/if_mosreg.h>
81 81
82#define MOS_PAUSE_REWRITES 3 82#define MOS_PAUSE_REWRITES 3
83 83
84#define MOS_TIMEOUT 1000 84#define MOS_TIMEOUT 1000
85 85
86#define MOS_RX_LIST_CNT 1 86#define MOS_RX_LIST_CNT 1
87#define MOS_TX_LIST_CNT 1 87#define MOS_TX_LIST_CNT 1
88 88
@@ -444,77 +444,76 @@ mos_uno_mii_statchg(struct ifnet *ifp) @@ -444,77 +444,76 @@ mos_uno_mii_statchg(struct ifnet *ifp)
444 } 444 }
445 usbnet_set_link(un, true); 445 usbnet_set_link(un, true);
446 } 446 }
447 447
448 /* re-enable TX, RX */ 448 /* re-enable TX, RX */
449 val |= (MOS_CTL_TX_ENB | MOS_CTL_RX_ENB); 449 val |= (MOS_CTL_TX_ENB | MOS_CTL_RX_ENB);
450 err = mos_reg_write_1(un, MOS_CTL, val); 450 err = mos_reg_write_1(un, MOS_CTL, val);
451 451
452 if (err) 452 if (err)
453 aprint_error_dev(un->un_dev, "media change failed\n"); 453 aprint_error_dev(un->un_dev, "media change failed\n");
454} 454}
455 455
456static void 456static void
457mos_setiff_locked(struct usbnet *un) 457mos_rcvfilt_locked(struct usbnet *un)
458{ 458{
459 struct ifnet *ifp = usbnet_ifp(un); 459 struct ifnet *ifp = usbnet_ifp(un);
460 struct ethercom *ec = usbnet_ec(un); 460 struct ethercom *ec = usbnet_ec(un);
461 struct ether_multi *enm; 461 struct ether_multi *enm;
462 struct ether_multistep step; 462 struct ether_multistep step;
463 u_int32_t h = 0; 463 u_int32_t h = 0;
464 u_int8_t rxmode, hashtbl[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; 464 u_int8_t rxmode, mchash[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
465 465
466 if (usbnet_isdying(un)) 466 if (usbnet_isdying(un))
467 return; 467 return;
468 468
469 rxmode = mos_reg_read_1(un, MOS_CTL); 469 rxmode = mos_reg_read_1(un, MOS_CTL);
470 rxmode &= ~(MOS_CTL_ALLMULTI | MOS_CTL_RX_PROMISC); 470 rxmode &= ~(MOS_CTL_ALLMULTI | MOS_CTL_RX_PROMISC);
471 471
472 ETHER_LOCK(ec); 472 ETHER_LOCK(ec);
473 if (ifp->if_flags & IFF_PROMISC) { 473 if (ifp->if_flags & IFF_PROMISC) {
474allmulti: 
475 ec->ec_flags |= ETHER_F_ALLMULTI; 474 ec->ec_flags |= ETHER_F_ALLMULTI;
476 rxmode |= MOS_CTL_ALLMULTI; 475 ETHER_UNLOCK(ec);
477 if (ifp->if_flags & IFF_PROMISC) 476 /* run promisc. mode */
478 rxmode |= MOS_CTL_RX_PROMISC; 477 rxmode |= MOS_CTL_ALLMULTI; /* ??? */
479 } else { 478 rxmode |= MOS_CTL_RX_PROMISC;
480 /* now program new ones */ 479 goto update;
481 ec->ec_flags &= ~ETHER_F_ALLMULTI; 480 }
482 481 ec->ec_flags &= ~ETHER_F_ALLMULTI;
483 ETHER_FIRST_MULTI(step, ec, enm); 482 ETHER_FIRST_MULTI(step, ec, enm);
484 while (enm != NULL) { 483 while (enm != NULL) {
485 if (memcmp(enm->enm_addrlo, enm->enm_addrhi, 484 if (memcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) {
486 ETHER_ADDR_LEN)) { 485 ec->ec_flags |= ETHER_F_ALLMULTI;
487 memset(hashtbl, 0, sizeof(hashtbl)); 486 ETHER_UNLOCK(ec);
488 goto allmulti; 487 memset(mchash, 0, sizeof(mchash)); /* correct ??? */
489 } 488 /* accept all mulicast frame */
490 h = ether_crc32_be(enm->enm_addrlo, 489 rxmode |= MOS_CTL_ALLMULTI;
491 ETHER_ADDR_LEN) >> 26; 490 goto update;
492 hashtbl[h / 8] |= 1 << (h % 8); 
493 
494 ETHER_NEXT_MULTI(step, enm); 
495 } 491 }
 492 h = ether_crc32_be(enm->enm_addrlo, ETHER_ADDR_LEN);
 493 /* 3(31:29) and 3(28:26) sampling to have uint8_t[8] */
 494 mchash[h >> 29] |= 1 << ((h >> 26) % 8);
 495 ETHER_NEXT_MULTI(step, enm);
496 } 496 }
497 ETHER_UNLOCK(ec); 497 ETHER_UNLOCK(ec);
498 498 /* MOS receive filter is always on */
 499 update:
499 /*  500 /*
500 * The datasheet claims broadcast frames were always accepted 501 * The datasheet claims broadcast frames were always accepted
501 * regardless of filter settings. But the hardware seems to 502 * regardless of filter settings. But the hardware seems to
502 * filter broadcast frames, so pass them explicitly. 503 * filter broadcast frames, so pass them explicitly.
503 */ 504 */
504 h = ether_crc32_be(etherbroadcastaddr, ETHER_ADDR_LEN) >> 26; 505 mchash[7] |= 0x80;
505 hashtbl[h / 8] |= 1 << (h % 8); 506 mos_write_mcast(un, mchash);
506 
507 mos_write_mcast(un, hashtbl); 
508 mos_reg_write_1(un, MOS_CTL, rxmode); 507 mos_reg_write_1(un, MOS_CTL, rxmode);
509} 508}
510 509
511static void 510static void
512mos_reset(struct usbnet *un) 511mos_reset(struct usbnet *un)
513{ 512{
514 u_int8_t ctl; 513 u_int8_t ctl;
515 514
516 if (usbnet_isdying(un)) 515 if (usbnet_isdying(un))
517 return; 516 return;
518 517
519 ctl = mos_reg_read_1(un, MOS_CTL); 518 ctl = mos_reg_read_1(un, MOS_CTL);
520 ctl &= ~(MOS_CTL_RX_PROMISC | MOS_CTL_ALLMULTI | MOS_CTL_TX_ENB | 519 ctl &= ~(MOS_CTL_RX_PROMISC | MOS_CTL_ALLMULTI | MOS_CTL_TX_ENB |
@@ -735,27 +734,27 @@ mos_init_locked(struct ifnet *ifp) @@ -735,27 +734,27 @@ mos_init_locked(struct ifnet *ifp)
735 /* Reset the ethernet interface. */ 734 /* Reset the ethernet interface. */
736 mos_reset(un); 735 mos_reset(un);
737 736
738 /* Write MAC address. */ 737 /* Write MAC address. */
739 mos_writemac(un); 738 mos_writemac(un);
740 739
741 /* Read and set transmitter IPG values */ 740 /* Read and set transmitter IPG values */
742 ipgs[0] = mos_reg_read_1(un, MOS_IPG0); 741 ipgs[0] = mos_reg_read_1(un, MOS_IPG0);
743 ipgs[1] = mos_reg_read_1(un, MOS_IPG1); 742 ipgs[1] = mos_reg_read_1(un, MOS_IPG1);
744 mos_reg_write_1(un, MOS_IPG0, ipgs[0]); 743 mos_reg_write_1(un, MOS_IPG0, ipgs[0]);
745 mos_reg_write_1(un, MOS_IPG1, ipgs[1]); 744 mos_reg_write_1(un, MOS_IPG1, ipgs[1]);
746 745
747 /* Program promiscuous mode and multicast filters. */ 746 /* Program promiscuous mode and multicast filters. */
748 mos_setiff_locked(un); 747 mos_rcvfilt_locked(un);
749 748
750 /* Enable receiver and transmitter, bridge controls speed/duplex mode */ 749 /* Enable receiver and transmitter, bridge controls speed/duplex mode */
751 rxmode = mos_reg_read_1(un, MOS_CTL); 750 rxmode = mos_reg_read_1(un, MOS_CTL);
752 rxmode |= MOS_CTL_RX_ENB | MOS_CTL_TX_ENB | MOS_CTL_BS_ENB; 751 rxmode |= MOS_CTL_RX_ENB | MOS_CTL_TX_ENB | MOS_CTL_BS_ENB;
753 rxmode &= ~(MOS_CTL_SLEEP); 752 rxmode &= ~(MOS_CTL_SLEEP);
754 mos_reg_write_1(un, MOS_CTL, rxmode); 753 mos_reg_write_1(un, MOS_CTL, rxmode);
755 754
756 return usbnet_init_rx_tx(un); 755 return usbnet_init_rx_tx(un);
757} 756}
758 757
759static int 758static int
760mos_uno_init(struct ifnet *ifp) 759mos_uno_init(struct ifnet *ifp)
761{ 760{
@@ -771,27 +770,27 @@ mos_uno_init(struct ifnet *ifp) @@ -771,27 +770,27 @@ mos_uno_init(struct ifnet *ifp)
771} 770}
772 771
773static int 772static int
774mos_uno_ioctl(struct ifnet *ifp, u_long cmd, void *data) 773mos_uno_ioctl(struct ifnet *ifp, u_long cmd, void *data)
775{ 774{
776 struct usbnet * const un = ifp->if_softc; 775 struct usbnet * const un = ifp->if_softc;
777 776
778 usbnet_lock_core(un); 777 usbnet_lock_core(un);
779 usbnet_busy(un); 778 usbnet_busy(un);
780 779
781 switch (cmd) { 780 switch (cmd) {
782 case SIOCADDMULTI: 781 case SIOCADDMULTI:
783 case SIOCDELMULTI: 782 case SIOCDELMULTI:
784 mos_setiff_locked(un); 783 mos_rcvfilt_locked(un);
785 break; 784 break;
786 default: 785 default:
787 break; 786 break;
788 } 787 }
789 788
790 usbnet_unbusy(un); 789 usbnet_unbusy(un);
791 usbnet_unlock_core(un); 790 usbnet_unlock_core(un);
792 791
793 return 0; 792 return 0;
794} 793}
795 794
796void 795void
797mos_uno_stop(struct ifnet *ifp, int disable) 796mos_uno_stop(struct ifnet *ifp, int disable)