1 /* $NetBSD: if_mc.c,v 1.20 2003/04/02 00:44:22 thorpej Exp $ */ 2 3 /*- 4 * Copyright (c) 1997 David Huang <khym@bga.com> 5 * All rights reserved. 6 * 7 * Portions of this code are based on code by Denton Gentry <denny1@home.com>, 8 * Charles M. Hannum, Yanagisawa Takeshi <yanagisw@aa.ap.titech.ac.jp>, and 9 * Jason R. Thorpe. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. The name of the author may not be used to endorse or promote products 17 * derived from this software without specific prior written permission 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 * 30 */ 31 32 /* 33 * Driver for the AMD Am79C940 (MACE) ethernet chip, used for onboard 34 * ethernet on the Centris/Quadra 660av and Quadra 840av. 35 */ 36 37 #include "opt_ddb.h" 38 #include "opt_inet.h" 39 #include "opt_ccitt.h" 40 #include "opt_llc.h" 41 #include "opt_ns.h" 42 43 #include <sys/param.h> 44 #include <sys/systm.h> 45 #include <sys/mbuf.h> 46 #include <sys/buf.h> 47 #include <sys/protosw.h> 48 #include <sys/socket.h> 49 #include <sys/syslog.h> 50 #include <sys/ioctl.h> 51 #include <sys/errno.h> 52 #include <sys/device.h> 53 54 #include <uvm/uvm_extern.h> 55 56 #include <net/if.h> 57 #include <net/if_dl.h> 58 #include <net/if_ether.h> 59 60 #ifdef INET 61 #include <netinet/in.h> 62 #include <netinet/if_inarp.h> 63 #include <netinet/in_systm.h> 64 #include <netinet/in_var.h> 65 #include <netinet/ip.h> 66 #endif 67 68 #ifdef NS 69 #include <netns/ns.h> 70 #include <netns/ns_if.h> 71 #endif 72 73 #if defined(CCITT) && defined(LLC) 74 #include <sys/socketvar.h> 75 #include <netccitt/x25.h> 76 #include <netccitt/pk.h> 77 #include <netccitt/pk_var.h> 78 #include <netccitt/pk_extern.h> 79 #endif 80 81 #include <uvm/uvm_extern.h> 82 83 #include "bpfilter.h" 84 #if NBPFILTER > 0 85 #include <net/bpf.h> 86 #include <net/bpfdesc.h> 87 #endif 88 89 #include <machine/bus.h> 90 #include <mac68k/dev/if_mcreg.h> 91 #include <mac68k/dev/if_mcvar.h> 92 93 hide void mcwatchdog __P((struct ifnet *)); 94 hide int mcinit __P((struct mc_softc *sc)); 95 hide int mcstop __P((struct mc_softc *sc)); 96 hide int mcioctl __P((struct ifnet *ifp, u_long cmd, caddr_t data)); 97 hide void mcstart __P((struct ifnet *ifp)); 98 hide void mcreset __P((struct mc_softc *sc)); 99 100 integrate u_int maceput __P((struct mc_softc *sc, struct mbuf *m0)); 101 integrate void mc_tint __P((struct mc_softc *sc)); 102 integrate void mace_read __P((struct mc_softc *, caddr_t, int)); 103 integrate struct mbuf *mace_get __P((struct mc_softc *, caddr_t, int)); 104 static void mace_calcladrf __P((struct ethercom *ac, u_int8_t *af)); 105 static inline u_int16_t ether_cmp __P((void *, void *)); 106 107 108 /* 109 * Compare two Ether/802 addresses for equality, inlined and 110 * unrolled for speed. Use this like bcmp(). 111 * 112 * XXX: Add <machine/inlines.h> for stuff like this? 113 * XXX: or maybe add it to libkern.h instead? 114 * 115 * "I'd love to have an inline assembler version of this." 116 * XXX: Who wanted that? mycroft? I wrote one, but this 117 * version in C is as good as hand-coded assembly. -gwr 118 * 119 * Please do NOT tweak this without looking at the actual 120 * assembly code generated before and after your tweaks! 121 */ 122 static inline u_int16_t 123 ether_cmp(one, two) 124 void *one, *two; 125 { 126 register u_int16_t *a = (u_short *) one; 127 register u_int16_t *b = (u_short *) two; 128 register u_int16_t diff; 129 130 #ifdef m68k 131 /* 132 * The post-increment-pointer form produces the best 133 * machine code for m68k. This was carefully tuned 134 * so it compiles to just 8 short (2-byte) op-codes! 135 */ 136 diff = *a++ - *b++; 137 diff |= *a++ - *b++; 138 diff |= *a++ - *b++; 139 #else 140 /* 141 * Most modern CPUs do better with a single expresion. 142 * Note that short-cut evaluation is NOT helpful here, 143 * because it just makes the code longer, not faster! 144 */ 145 diff = (a[0] - b[0]) | (a[1] - b[1]) | (a[2] - b[2]); 146 #endif 147 148 return (diff); 149 } 150 151 #define ETHER_CMP ether_cmp 152 153 /* 154 * Interface exists: make available by filling in network interface 155 * record. System will initialize the interface when it is ready 156 * to accept packets. 157 */ 158 int 159 mcsetup(sc, lladdr) 160 struct mc_softc *sc; 161 u_int8_t *lladdr; 162 { 163 struct ifnet *ifp = &sc->sc_if; 164 165 /* reset the chip and disable all interrupts */ 166 NIC_PUT(sc, MACE_BIUCC, SWRST); 167 DELAY(100); 168 NIC_PUT(sc, MACE_IMR, ~0); 169 170 bcopy(lladdr, sc->sc_enaddr, ETHER_ADDR_LEN); 171 printf(": address %s\n", ether_sprintf(lladdr)); 172 173 bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ); 174 ifp->if_softc = sc; 175 ifp->if_ioctl = mcioctl; 176 ifp->if_start = mcstart; 177 ifp->if_flags = 178 IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST; 179 ifp->if_watchdog = mcwatchdog; 180 181 if_attach(ifp); 182 ether_ifattach(ifp, lladdr); 183 184 return (0); 185 } 186 187 hide int 188 mcioctl(ifp, cmd, data) 189 struct ifnet *ifp; 190 u_long cmd; 191 caddr_t data; 192 { 193 struct mc_softc *sc = ifp->if_softc; 194 struct ifaddr *ifa; 195 struct ifreq *ifr; 196 197 int s = splnet(), err = 0; 198 int temp; 199 200 switch (cmd) { 201 202 case SIOCSIFADDR: 203 ifa = (struct ifaddr *)data; 204 ifp->if_flags |= IFF_UP; 205 switch (ifa->ifa_addr->sa_family) { 206 #ifdef INET 207 case AF_INET: 208 mcinit(sc); 209 arp_ifinit(ifp, ifa); 210 break; 211 #endif 212 #ifdef NS 213 case AF_NS: 214 { 215 register struct ns_addr *ina = &IA_SNS(ifa)->sns_addr; 216 217 if (ns_nullhost(*ina)) 218 ina->x_host = 219 *(union ns_host *)LLADDR(ifp->if_sadl); 220 else { 221 bcopy(ina->x_host.c_host, 222 LLADDR(ifp->if_sadl), 223 sizeof(sc->sc_enaddr)); 224 } 225 /* Set new address. */ 226 mcinit(sc); 227 break; 228 } 229 #endif 230 default: 231 mcinit(sc); 232 break; 233 } 234 break; 235 236 case SIOCSIFFLAGS: 237 if ((ifp->if_flags & IFF_UP) == 0 && 238 (ifp->if_flags & IFF_RUNNING) != 0) { 239 /* 240 * If interface is marked down and it is running, 241 * then stop it. 242 */ 243 mcstop(sc); 244 ifp->if_flags &= ~IFF_RUNNING; 245 } else if ((ifp->if_flags & IFF_UP) != 0 && 246 (ifp->if_flags & IFF_RUNNING) == 0) { 247 /* 248 * If interface is marked up and it is stopped, 249 * then start it. 250 */ 251 (void)mcinit(sc); 252 } else { 253 /* 254 * reset the interface to pick up any other changes 255 * in flags 256 */ 257 temp = ifp->if_flags & IFF_UP; 258 mcreset(sc); 259 ifp->if_flags |= temp; 260 mcstart(ifp); 261 } 262 break; 263 264 case SIOCADDMULTI: 265 case SIOCDELMULTI: 266 ifr = (struct ifreq *) data; 267 err = (cmd == SIOCADDMULTI) ? 268 ether_addmulti(ifr, &sc->sc_ethercom) : 269 ether_delmulti(ifr, &sc->sc_ethercom); 270 271 if (err == ENETRESET) { 272 /* 273 * Multicast list has changed; set the hardware 274 * filter accordingly. But remember UP flag! 275 */ 276 temp = ifp->if_flags & IFF_UP; 277 mcreset(sc); 278 ifp->if_flags |= temp; 279 err = 0; 280 } 281 break; 282 default: 283 err = EINVAL; 284 } 285 splx(s); 286 return (err); 287 } 288 289 /* 290 * Encapsulate a packet of type family for the local net. 291 */ 292 hide void 293 mcstart(ifp) 294 struct ifnet *ifp; 295 { 296 struct mc_softc *sc = ifp->if_softc; 297 struct mbuf *m; 298 299 if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING) 300 return; 301 302 while (1) { 303 if (ifp->if_flags & IFF_OACTIVE) 304 return; 305 306 IF_DEQUEUE(&ifp->if_snd, m); 307 if (m == 0) 308 return; 309 310 #if NBPFILTER > 0 311 /* 312 * If bpf is listening on this interface, let it 313 * see the packet before we commit it to the wire. 314 */ 315 if (ifp->if_bpf) 316 bpf_mtap(ifp->if_bpf, m); 317 #endif 318 319 /* 320 * Copy the mbuf chain into the transmit buffer. 321 */ 322 ifp->if_flags |= IFF_OACTIVE; 323 maceput(sc, m); 324 325 ifp->if_opackets++; /* # of pkts */ 326 } 327 } 328 329 /* 330 * reset and restart the MACE. Called in case of fatal 331 * hardware/software errors. 332 */ 333 hide void 334 mcreset(sc) 335 struct mc_softc *sc; 336 { 337 mcstop(sc); 338 mcinit(sc); 339 } 340 341 hide int 342 mcinit(sc) 343 struct mc_softc *sc; 344 { 345 int s; 346 u_int8_t maccc, ladrf[8]; 347 348 if (sc->sc_if.if_flags & IFF_RUNNING) 349 /* already running */ 350 return (0); 351 352 s = splnet(); 353 354 NIC_PUT(sc, MACE_BIUCC, sc->sc_biucc); 355 NIC_PUT(sc, MACE_FIFOCC, sc->sc_fifocc); 356 NIC_PUT(sc, MACE_IMR, ~0); /* disable all interrupts */ 357 NIC_PUT(sc, MACE_PLSCC, sc->sc_plscc); 358 359 NIC_PUT(sc, MACE_UTR, RTRD); /* disable reserved test registers */ 360 361 /* set MAC address */ 362 NIC_PUT(sc, MACE_IAC, ADDRCHG); 363 while (NIC_GET(sc, MACE_IAC) & ADDRCHG) 364 ; 365 NIC_PUT(sc, MACE_IAC, PHYADDR); 366 bus_space_write_multi_1(sc->sc_regt, sc->sc_regh, MACE_REG(MACE_PADR), 367 sc->sc_enaddr, ETHER_ADDR_LEN); 368 369 /* set logical address filter */ 370 mace_calcladrf(&sc->sc_ethercom, ladrf); 371 372 NIC_PUT(sc, MACE_IAC, ADDRCHG); 373 while (NIC_GET(sc, MACE_IAC) & ADDRCHG) 374 ; 375 NIC_PUT(sc, MACE_IAC, LOGADDR); 376 bus_space_write_multi_1(sc->sc_regt, sc->sc_regh, MACE_REG(MACE_LADRF), 377 ladrf, 8); 378 379 NIC_PUT(sc, MACE_XMTFC, APADXMT); 380 /* 381 * No need to autostrip padding on receive... Ethernet frames 382 * don't have a length field, unlike 802.3 frames, so the MACE 383 * can't figure out the length of the packet anyways. 384 */ 385 NIC_PUT(sc, MACE_RCVFC, 0); 386 387 maccc = ENXMT | ENRCV; 388 if (sc->sc_if.if_flags & IFF_PROMISC) 389 maccc |= PROM; 390 391 NIC_PUT(sc, MACE_MACCC, maccc); 392 393 if (sc->sc_bus_init) 394 (*sc->sc_bus_init)(sc); 395 396 /* 397 * Enable all interrupts except receive, since we use the DMA 398 * completion interrupt for that. 399 */ 400 NIC_PUT(sc, MACE_IMR, RCVINTM); 401 402 /* flag interface as "running" */ 403 sc->sc_if.if_flags |= IFF_RUNNING; 404 sc->sc_if.if_flags &= ~IFF_OACTIVE; 405 406 splx(s); 407 return (0); 408 } 409 410 /* 411 * close down an interface and free its buffers 412 * Called on final close of device, or if mcinit() fails 413 * part way through. 414 */ 415 hide int 416 mcstop(sc) 417 struct mc_softc *sc; 418 { 419 int s = splnet(); 420 421 NIC_PUT(sc, MACE_BIUCC, SWRST); 422 DELAY(100); 423 424 sc->sc_if.if_timer = 0; 425 sc->sc_if.if_flags &= ~(IFF_RUNNING | IFF_UP); 426 427 splx(s); 428 return (0); 429 } 430 431 /* 432 * Called if any Tx packets remain unsent after 5 seconds, 433 * In all cases we just reset the chip, and any retransmission 434 * will be handled by higher level protocol timeouts. 435 */ 436 hide void 437 mcwatchdog(ifp) 438 struct ifnet *ifp; 439 { 440 struct mc_softc *sc = ifp->if_softc; 441 int temp; 442 443 printf("mcwatchdog: resetting chip\n"); 444 temp = ifp->if_flags & IFF_UP; 445 mcreset(sc); 446 ifp->if_flags |= temp; 447 } 448 449 /* 450 * stuff packet into MACE (at splnet) 451 */ 452 integrate u_int 453 maceput(sc, m) 454 struct mc_softc *sc; 455 struct mbuf *m; 456 { 457 struct mbuf *n; 458 u_int len, totlen = 0; 459 u_char *buff; 460 461 buff = sc->sc_txbuf; 462 463 for (; m; m = n) { 464 u_char *data = mtod(m, u_char *); 465 len = m->m_len; 466 totlen += len; 467 bcopy(data, buff, len); 468 buff += len; 469 MFREE(m, n); 470 } 471 472 if (totlen > PAGE_SIZE) 473 panic("%s: maceput: packet overflow", sc->sc_dev.dv_xname); 474 475 #if 0 476 if (totlen < ETHERMIN + sizeof(struct ether_header)) { 477 int pad = ETHERMIN + sizeof(struct ether_header) - totlen; 478 bzero(sc->sc_txbuf + totlen, pad); 479 totlen = ETHERMIN + sizeof(struct ether_header); 480 } 481 #endif 482 483 (*sc->sc_putpacket)(sc, totlen); 484 485 sc->sc_if.if_timer = 5; /* 5 seconds to watch for failing to transmit */ 486 return (totlen); 487 } 488 489 void 490 mcintr(arg) 491 void *arg; 492 { 493 struct mc_softc *sc = arg; 494 u_int8_t ir; 495 496 ir = NIC_GET(sc, MACE_IR) & ~NIC_GET(sc, MACE_IMR); 497 if (ir & JAB) { 498 #ifdef MCDEBUG 499 printf("%s: jabber error\n", sc->sc_dev.dv_xname); 500 #endif 501 sc->sc_if.if_oerrors++; 502 } 503 504 if (ir & BABL) { 505 #ifdef MCDEBUG 506 printf("%s: babble\n", sc->sc_dev.dv_xname); 507 #endif 508 sc->sc_if.if_oerrors++; 509 } 510 511 if (ir & CERR) { 512 #ifdef MCDEBUG 513 printf("%s: collision error\n", sc->sc_dev.dv_xname); 514 #endif 515 sc->sc_if.if_collisions++; 516 } 517 518 /* 519 * Pretend we have carrier; if we don't this will be cleared 520 * shortly. 521 */ 522 sc->sc_havecarrier = 1; 523 524 if (ir & XMTINT) 525 mc_tint(sc); 526 527 if (ir & RCVINT) 528 mc_rint(sc); 529 } 530 531 integrate void 532 mc_tint(sc) 533 struct mc_softc *sc; 534 { 535 u_int8_t xmtrc, xmtfs; 536 537 xmtrc = NIC_GET(sc, MACE_XMTRC); 538 xmtfs = NIC_GET(sc, MACE_XMTFS); 539 540 if ((xmtfs & XMTSV) == 0) 541 return; 542 543 if (xmtfs & UFLO) { 544 printf("%s: underflow\n", sc->sc_dev.dv_xname); 545 mcreset(sc); 546 return; 547 } 548 549 if (xmtfs & LCOL) { 550 printf("%s: late collision\n", sc->sc_dev.dv_xname); 551 sc->sc_if.if_oerrors++; 552 sc->sc_if.if_collisions++; 553 } 554 555 if (xmtfs & MORE) 556 /* Real number is unknown. */ 557 sc->sc_if.if_collisions += 2; 558 else if (xmtfs & ONE) 559 sc->sc_if.if_collisions++; 560 else if (xmtfs & RTRY) { 561 printf("%s: excessive collisions\n", sc->sc_dev.dv_xname); 562 sc->sc_if.if_collisions += 16; 563 sc->sc_if.if_oerrors++; 564 } 565 566 if (xmtfs & LCAR) { 567 sc->sc_havecarrier = 0; 568 printf("%s: lost carrier\n", sc->sc_dev.dv_xname); 569 sc->sc_if.if_oerrors++; 570 } 571 572 sc->sc_if.if_flags &= ~IFF_OACTIVE; 573 sc->sc_if.if_timer = 0; 574 mcstart(&sc->sc_if); 575 } 576 577 void 578 mc_rint(sc) 579 struct mc_softc *sc; 580 { 581 #define rxf sc->sc_rxframe 582 u_int len; 583 584 len = (rxf.rx_rcvcnt | ((rxf.rx_rcvsts & 0xf) << 8)) - 4; 585 586 #ifdef MCDEBUG 587 if (rxf.rx_rcvsts & 0xf0) 588 printf("%s: rcvcnt %02x rcvsts %02x rntpc 0x%02x rcvcc 0x%02x\n", 589 sc->sc_dev.dv_xname, rxf.rx_rcvcnt, rxf.rx_rcvsts, 590 rxf.rx_rntpc, rxf.rx_rcvcc); 591 #endif 592 593 if (rxf.rx_rcvsts & OFLO) { 594 printf("%s: receive FIFO overflow\n", sc->sc_dev.dv_xname); 595 sc->sc_if.if_ierrors++; 596 return; 597 } 598 599 if (rxf.rx_rcvsts & CLSN) 600 sc->sc_if.if_collisions++; 601 602 if (rxf.rx_rcvsts & FRAM) { 603 #ifdef MCDEBUG 604 printf("%s: framing error\n", sc->sc_dev.dv_xname); 605 #endif 606 sc->sc_if.if_ierrors++; 607 return; 608 } 609 610 if (rxf.rx_rcvsts & FCS) { 611 #ifdef MCDEBUG 612 printf("%s: frame control checksum error\n", sc->sc_dev.dv_xname); 613 #endif 614 sc->sc_if.if_ierrors++; 615 return; 616 } 617 618 mace_read(sc, rxf.rx_frame, len); 619 #undef rxf 620 } 621 622 integrate void 623 mace_read(sc, pkt, len) 624 struct mc_softc *sc; 625 caddr_t pkt; 626 int len; 627 { 628 struct ifnet *ifp = &sc->sc_if; 629 struct mbuf *m; 630 631 if (len <= sizeof(struct ether_header) || 632 len > ETHERMTU + sizeof(struct ether_header)) { 633 #ifdef MCDEBUG 634 printf("%s: invalid packet size %d; dropping\n", 635 sc->sc_dev.dv_xname, len); 636 #endif 637 ifp->if_ierrors++; 638 return; 639 } 640 641 m = mace_get(sc, pkt, len); 642 if (m == NULL) { 643 ifp->if_ierrors++; 644 return; 645 } 646 647 ifp->if_ipackets++; 648 649 #if NBPFILTER > 0 650 /* Pass the packet to any BPF listeners. */ 651 if (ifp->if_bpf) 652 bpf_mtap(ifp->if_bpf, m); 653 #endif 654 655 /* Pass the packet up. */ 656 (*ifp->if_input)(ifp, m); 657 } 658 659 /* 660 * Pull data off an interface. 661 * Len is length of data, with local net header stripped. 662 * We copy the data into mbufs. When full cluster sized units are present 663 * we copy into clusters. 664 */ 665 integrate struct mbuf * 666 mace_get(sc, pkt, totlen) 667 struct mc_softc *sc; 668 caddr_t pkt; 669 int totlen; 670 { 671 register struct mbuf *m; 672 struct mbuf *top, **mp; 673 int len; 674 675 MGETHDR(m, M_DONTWAIT, MT_DATA); 676 if (m == 0) 677 return (0); 678 m->m_pkthdr.rcvif = &sc->sc_if; 679 m->m_pkthdr.len = totlen; 680 len = MHLEN; 681 top = 0; 682 mp = ⊤ 683 684 while (totlen > 0) { 685 if (top) { 686 MGET(m, M_DONTWAIT, MT_DATA); 687 if (m == 0) { 688 m_freem(top); 689 return 0; 690 } 691 len = MLEN; 692 } 693 if (totlen >= MINCLSIZE) { 694 MCLGET(m, M_DONTWAIT); 695 if ((m->m_flags & M_EXT) == 0) { 696 m_free(m); 697 m_freem(top); 698 return 0; 699 } 700 len = MCLBYTES; 701 } 702 m->m_len = len = min(totlen, len); 703 bcopy(pkt, mtod(m, caddr_t), len); 704 pkt += len; 705 totlen -= len; 706 *mp = m; 707 mp = &m->m_next; 708 } 709 710 return (top); 711 } 712 713 /* 714 * Go through the list of multicast addresses and calculate the logical 715 * address filter. 716 */ 717 void 718 mace_calcladrf(ac, af) 719 struct ethercom *ac; 720 u_int8_t *af; 721 { 722 struct ifnet *ifp = &ac->ec_if; 723 struct ether_multi *enm; 724 register u_char *cp; 725 register u_int32_t crc; 726 static const u_int32_t crctab[] = { 727 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 728 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c, 729 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, 730 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c 731 }; 732 register int len; 733 struct ether_multistep step; 734 735 /* 736 * Set up multicast address filter by passing all multicast addresses 737 * through a crc generator, and then using the high order 6 bits as an 738 * index into the 64 bit logical address filter. The high order bit 739 * selects the word, while the rest of the bits select the bit within 740 * the word. 741 */ 742 743 *((u_int32_t *)af) = *((u_int32_t *)af + 1) = 0; 744 ETHER_FIRST_MULTI(step, ac, enm); 745 while (enm != NULL) { 746 if (ETHER_CMP(enm->enm_addrlo, enm->enm_addrhi)) { 747 /* 748 * We must listen to a range of multicast addresses. 749 * For now, just accept all multicasts, rather than 750 * trying to set only those filter bits needed to match 751 * the range. (At this time, the only use of address 752 * ranges is for IP multicast routing, for which the 753 * range is big enough to require all bits set.) 754 */ 755 goto allmulti; 756 } 757 758 cp = enm->enm_addrlo; 759 crc = 0xffffffff; 760 for (len = sizeof(enm->enm_addrlo); --len >= 0;) { 761 crc ^= *cp++; 762 crc = (crc >> 4) ^ crctab[crc & 0xf]; 763 crc = (crc >> 4) ^ crctab[crc & 0xf]; 764 } 765 /* Just want the 6 most significant bits. */ 766 crc >>= 26; 767 768 /* Set the corresponding bit in the filter. */ 769 af[crc >> 3] |= 1 << (crc & 7); 770 771 ETHER_NEXT_MULTI(step, enm); 772 } 773 ifp->if_flags &= ~IFF_ALLMULTI; 774 return; 775 776 allmulti: 777 ifp->if_flags |= IFF_ALLMULTI; 778 *((u_int32_t *)af) = *((u_int32_t *)af + 1) = 0xffffffff; 779 } 780 781 static u_char bbr4[] = {0,8,4,12,2,10,6,14,1,9,5,13,3,11,7,15}; 782 #define bbr(v) ((bbr4[(v)&0xf] << 4) | bbr4[((v)>>4) & 0xf]) 783 784 u_char 785 mc_get_enaddr(t, h, o, dst) 786 bus_space_tag_t t; 787 bus_space_handle_t h; 788 bus_size_t o; 789 u_char *dst; 790 { 791 int i; 792 u_char b, csum; 793 794 /* 795 * The XOR of the 8 bytes of the ROM must be 0xff for it to be 796 * valid 797 */ 798 for (i = 0, csum = 0; i < 8; i++) { 799 b = bus_space_read_1(t, h, o+16*i); 800 if (i < ETHER_ADDR_LEN) 801 dst[i] = bbr(b); 802 csum ^= b; 803 } 804 805 return csum; 806 } 807