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