| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: if_cemac.c,v 1.5 2015/08/24 18:26:51 rjs Exp $ */ | | 1 | /* $NetBSD: if_cemac.c,v 1.6 2015/08/24 18:40:57 rjs Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 2015 Genetec Corporation. All rights reserved. | | 4 | * Copyright (c) 2015 Genetec Corporation. All rights reserved. |
5 | * Written by Hashimoto Kenichi for Genetec Corporation. | | 5 | * Written by Hashimoto Kenichi for Genetec Corporation. |
6 | * | | 6 | * |
7 | * Based on arch/arm/at91/at91emac.c | | 7 | * Based on arch/arm/at91/at91emac.c |
8 | * | | 8 | * |
9 | * Copyright (c) 2007 Embedtronics Oy | | 9 | * Copyright (c) 2007 Embedtronics Oy |
10 | * All rights reserved. | | 10 | * All rights reserved. |
11 | * | | 11 | * |
12 | * Copyright (c) 2004 Jesse Off | | 12 | * Copyright (c) 2004 Jesse Off |
13 | * All rights reserved. | | 13 | * All rights reserved. |
14 | * | | 14 | * |
| @@ -30,27 +30,27 @@ | | | @@ -30,27 +30,27 @@ |
30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | | 30 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | | 31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | 32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | | 33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
34 | * POSSIBILITY OF SUCH DAMAGE. | | 34 | * POSSIBILITY OF SUCH DAMAGE. |
35 | */ | | 35 | */ |
36 | | | 36 | |
37 | /* | | 37 | /* |
38 | * Cadence EMAC/GEM ethernet controller IP driver | | 38 | * Cadence EMAC/GEM ethernet controller IP driver |
39 | * used by arm/at91, arm/zynq SoC | | 39 | * used by arm/at91, arm/zynq SoC |
40 | */ | | 40 | */ |
41 | | | 41 | |
42 | #include <sys/cdefs.h> | | 42 | #include <sys/cdefs.h> |
43 | __KERNEL_RCSID(0, "$NetBSD: if_cemac.c,v 1.5 2015/08/24 18:26:51 rjs Exp $"); | | 43 | __KERNEL_RCSID(0, "$NetBSD: if_cemac.c,v 1.6 2015/08/24 18:40:57 rjs Exp $"); |
44 | | | 44 | |
45 | #include <sys/types.h> | | 45 | #include <sys/types.h> |
46 | #include <sys/param.h> | | 46 | #include <sys/param.h> |
47 | #include <sys/systm.h> | | 47 | #include <sys/systm.h> |
48 | #include <sys/ioctl.h> | | 48 | #include <sys/ioctl.h> |
49 | #include <sys/kernel.h> | | 49 | #include <sys/kernel.h> |
50 | #include <sys/proc.h> | | 50 | #include <sys/proc.h> |
51 | #include <sys/malloc.h> | | 51 | #include <sys/malloc.h> |
52 | #include <sys/time.h> | | 52 | #include <sys/time.h> |
53 | #include <sys/device.h> | | 53 | #include <sys/device.h> |
54 | #include <uvm/uvm_extern.h> | | 54 | #include <uvm/uvm_extern.h> |
55 | | | 55 | |
56 | #include <sys/bus.h> | | 56 | #include <sys/bus.h> |
| @@ -939,85 +939,89 @@ cemac_setaddr(struct ifnet *ifp) | | | @@ -939,85 +939,89 @@ cemac_setaddr(struct ifnet *ifp) |
939 | ifp->if_flags &= ~IFF_ALLMULTI; | | 939 | ifp->if_flags &= ~IFF_ALLMULTI; |
940 | | | 940 | |
941 | ETHER_FIRST_MULTI(step, ac, enm); | | 941 | ETHER_FIRST_MULTI(step, ac, enm); |
942 | while (enm != NULL) { | | 942 | while (enm != NULL) { |
943 | if (memcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) { | | 943 | if (memcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) { |
944 | /* | | 944 | /* |
945 | * We must listen to a range of multicast addresses. | | 945 | * We must listen to a range of multicast addresses. |
946 | * For now, just accept all multicasts, rather than | | 946 | * For now, just accept all multicasts, rather than |
947 | * trying to set only those filter bits needed to match | | 947 | * trying to set only those filter bits needed to match |
948 | * the range. (At this time, the only use of address | | 948 | * the range. (At this time, the only use of address |
949 | * ranges is for IP multicast routing, for which the | | 949 | * ranges is for IP multicast routing, for which the |
950 | * range is big enough to require all bits set.) | | 950 | * range is big enough to require all bits set.) |
951 | */ | | 951 | */ |
952 | cfg |= ETH_CFG_CAF; | | 952 | cfg |= ETH_CFG_MTI; |
953 | hashes[0] = 0xffffffffUL; | | 953 | hashes[0] = 0xffffffffUL; |
954 | hashes[1] = 0xffffffffUL; | | 954 | hashes[1] = 0xffffffffUL; |
955 | ifp->if_flags |= IFF_ALLMULTI; | | 955 | ifp->if_flags |= IFF_ALLMULTI; |
956 | nma = 0; | | 956 | nma = 0; |
957 | break; | | 957 | break; |
958 | } | | 958 | } |
959 | | | 959 | |
960 | if (nma < 3) { | | 960 | if (nma < 3) { |
961 | /* We can program 3 perfect address filters for mcast */ | | 961 | /* We can program 3 perfect address filters for mcast */ |
962 | memcpy(ias[nma], enm->enm_addrlo, ETHER_ADDR_LEN); | | 962 | memcpy(ias[nma], enm->enm_addrlo, ETHER_ADDR_LEN); |
963 | } else { | | 963 | } else { |
964 | /* | | 964 | /* |
965 | * XXX: Datasheet is not very clear here, I'm not sure | | 965 | * XXX: Datasheet is not very clear here, I'm not sure |
966 | * if I'm doing this right. --joff | | 966 | * if I'm doing this right. --joff |
967 | */ | | 967 | */ |
968 | h = ether_crc32_le(enm->enm_addrlo, ETHER_ADDR_LEN); | | 968 | h = ether_crc32_le(enm->enm_addrlo, ETHER_ADDR_LEN); |
969 | | | 969 | |
970 | /* Just want the 6 most-significant bits. */ | | 970 | /* Just want the 6 most-significant bits. */ |
971 | h = h >> 26; | | 971 | h = h >> 26; |
972 | | | 972 | #if 0 |
973 | hashes[h / 32] |= (1 << (h % 32)); | | 973 | hashes[h / 32] |= (1 << (h % 32)); |
| | | 974 | #else |
| | | 975 | hashes[0] = 0xffffffffUL; |
| | | 976 | hashes[1] = 0xffffffffUL; |
| | | 977 | #endif |
974 | cfg |= ETH_CFG_MTI; | | 978 | cfg |= ETH_CFG_MTI; |
975 | } | | 979 | } |
976 | ETHER_NEXT_MULTI(step, enm); | | 980 | ETHER_NEXT_MULTI(step, enm); |
977 | nma++; | | 981 | nma++; |
978 | } | | 982 | } |
979 | | | 983 | |
980 | // program... | | 984 | // program... |
981 | DPRINTFN(1,("%s: en0 %02x:%02x:%02x:%02x:%02x:%02x\n", __FUNCTION__, | | 985 | DPRINTFN(1,("%s: en0 %02x:%02x:%02x:%02x:%02x:%02x\n", __FUNCTION__, |
982 | sc->sc_enaddr[0], sc->sc_enaddr[1], sc->sc_enaddr[2], | | 986 | sc->sc_enaddr[0], sc->sc_enaddr[1], sc->sc_enaddr[2], |
983 | sc->sc_enaddr[3], sc->sc_enaddr[4], sc->sc_enaddr[5])); | | 987 | sc->sc_enaddr[3], sc->sc_enaddr[4], sc->sc_enaddr[5])); |
984 | CEMAC_GEM_WRITE(SA1L, (sc->sc_enaddr[3] << 24) | | 988 | CEMAC_GEM_WRITE(SA1L, (sc->sc_enaddr[3] << 24) |
985 | | (sc->sc_enaddr[2] << 16) | (sc->sc_enaddr[1] << 8) | | 989 | | (sc->sc_enaddr[2] << 16) | (sc->sc_enaddr[1] << 8) |
986 | | (sc->sc_enaddr[0])); | | 990 | | (sc->sc_enaddr[0])); |
987 | CEMAC_GEM_WRITE(SA1H, (sc->sc_enaddr[5] << 8) | | 991 | CEMAC_GEM_WRITE(SA1H, (sc->sc_enaddr[5] << 8) |
988 | | (sc->sc_enaddr[4])); | | 992 | | (sc->sc_enaddr[4])); |
989 | if (nma > 1) { | | 993 | if (nma > 0) { |
990 | DPRINTFN(1,("%s: en1 %02x:%02x:%02x:%02x:%02x:%02x\n", __FUNCTION__, | | 994 | DPRINTFN(1,("%s: en1 %02x:%02x:%02x:%02x:%02x:%02x\n", __FUNCTION__, |
991 | ias[0][0], ias[0][1], ias[0][2], | | 995 | ias[0][0], ias[0][1], ias[0][2], |
992 | ias[0][3], ias[0][4], ias[0][5])); | | 996 | ias[0][3], ias[0][4], ias[0][5])); |
993 | CEMAC_WRITE(ETH_SA2L, (ias[0][3] << 24) | | 997 | CEMAC_WRITE(ETH_SA2L, (ias[0][3] << 24) |
994 | | (ias[0][2] << 16) | (ias[0][1] << 8) | | 998 | | (ias[0][2] << 16) | (ias[0][1] << 8) |
995 | | (ias[0][0])); | | 999 | | (ias[0][0])); |
996 | CEMAC_WRITE(ETH_SA2H, (ias[0][4] << 8) | | 1000 | CEMAC_WRITE(ETH_SA2H, (ias[0][4] << 8) |
997 | | (ias[0][5])); | | 1001 | | (ias[0][5])); |
998 | } | | 1002 | } |
999 | if (nma > 2) { | | 1003 | if (nma > 1) { |
1000 | DPRINTFN(1,("%s: en2 %02x:%02x:%02x:%02x:%02x:%02x\n", __FUNCTION__, | | 1004 | DPRINTFN(1,("%s: en2 %02x:%02x:%02x:%02x:%02x:%02x\n", __FUNCTION__, |
1001 | ias[1][0], ias[1][1], ias[1][2], | | 1005 | ias[1][0], ias[1][1], ias[1][2], |
1002 | ias[1][3], ias[1][4], ias[1][5])); | | 1006 | ias[1][3], ias[1][4], ias[1][5])); |
1003 | CEMAC_WRITE(ETH_SA3L, (ias[1][3] << 24) | | 1007 | CEMAC_WRITE(ETH_SA3L, (ias[1][3] << 24) |
1004 | | (ias[1][2] << 16) | (ias[1][1] << 8) | | 1008 | | (ias[1][2] << 16) | (ias[1][1] << 8) |
1005 | | (ias[1][0])); | | 1009 | | (ias[1][0])); |
1006 | CEMAC_WRITE(ETH_SA3H, (ias[1][4] << 8) | | 1010 | CEMAC_WRITE(ETH_SA3H, (ias[1][4] << 8) |
1007 | | (ias[1][5])); | | 1011 | | (ias[1][5])); |
1008 | } | | 1012 | } |
1009 | if (nma > 3) { | | 1013 | if (nma > 2) { |
1010 | DPRINTFN(1,("%s: en3 %02x:%02x:%02x:%02x:%02x:%02x\n", __FUNCTION__, | | 1014 | DPRINTFN(1,("%s: en3 %02x:%02x:%02x:%02x:%02x:%02x\n", __FUNCTION__, |
1011 | ias[2][0], ias[2][1], ias[2][2], | | 1015 | ias[2][0], ias[2][1], ias[2][2], |
1012 | ias[2][3], ias[2][4], ias[2][5])); | | 1016 | ias[2][3], ias[2][4], ias[2][5])); |
1013 | CEMAC_WRITE(ETH_SA3L, (ias[2][3] << 24) | | 1017 | CEMAC_WRITE(ETH_SA4L, (ias[2][3] << 24) |
1014 | | (ias[2][2] << 16) | (ias[2][1] << 8) | | 1018 | | (ias[2][2] << 16) | (ias[2][1] << 8) |
1015 | | (ias[2][0])); | | 1019 | | (ias[2][0])); |
1016 | CEMAC_WRITE(ETH_SA3H, (ias[2][4] << 8) | | 1020 | CEMAC_WRITE(ETH_SA4H, (ias[2][4] << 8) |
1017 | | (ias[2][5])); | | 1021 | | (ias[2][5])); |
1018 | } | | 1022 | } |
1019 | CEMAC_GEM_WRITE(HSH, hashes[0]); | | 1023 | CEMAC_GEM_WRITE(HSH, hashes[0]); |
1020 | CEMAC_GEM_WRITE(HSL, hashes[1]); | | 1024 | CEMAC_GEM_WRITE(HSL, hashes[1]); |
1021 | CEMAC_WRITE(ETH_CFG, cfg); | | 1025 | CEMAC_WRITE(ETH_CFG, cfg); |
1022 | CEMAC_WRITE(ETH_CTL, ctl | ETH_CTL_RE); | | 1026 | CEMAC_WRITE(ETH_CTL, ctl | ETH_CTL_RE); |
1023 | } | | 1027 | } |