1 /* $NetBSD: lance.c,v 1.17 2000/12/14 06:27:25 thorpej Exp $ */ 2 3 /*- 4 * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Charles M. Hannum and by Jason R. Thorpe of the Numerical Aerospace 9 * Simulation Facility, NASA Ames Research Center. 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. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgement: 21 * This product includes software developed by the NetBSD 22 * Foundation, Inc. and its contributors. 23 * 4. Neither the name of The NetBSD Foundation nor the names of its 24 * contributors may be used to endorse or promote products derived 25 * from this software without specific prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 37 * POSSIBILITY OF SUCH DAMAGE. 38 */ 39 40 /*- 41 * Copyright (c) 1992, 1993 42 * The Regents of the University of California. All rights reserved. 43 * 44 * This code is derived from software contributed to Berkeley by 45 * Ralph Campbell and Rick Macklem. 46 * 47 * Redistribution and use in source and binary forms, with or without 48 * modification, are permitted provided that the following conditions 49 * are met: 50 * 1. Redistributions of source code must retain the above copyright 51 * notice, this list of conditions and the following disclaimer. 52 * 2. Redistributions in binary form must reproduce the above copyright 53 * notice, this list of conditions and the following disclaimer in the 54 * documentation and/or other materials provided with the distribution. 55 * 3. All advertising materials mentioning features or use of this software 56 * must display the following acknowledgement: 57 * This product includes software developed by the University of 58 * California, Berkeley and its contributors. 59 * 4. Neither the name of the University nor the names of its contributors 60 * may be used to endorse or promote products derived from this software 61 * without specific prior written permission. 62 * 63 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 64 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 65 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 66 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 67 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 68 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 69 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 70 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 71 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 72 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 73 * SUCH DAMAGE. 74 * 75 * @(#)if_le.c 8.2 (Berkeley) 11/16/93 76 */ 77 78 #include "opt_inet.h" 79 #include "opt_ccitt.h" 80 #include "opt_llc.h" 81 #include "opt_ns.h" 82 #include "bpfilter.h" 83 #include "rnd.h" 84 85 #include <sys/param.h> 86 #include <sys/systm.h> 87 #include <sys/mbuf.h> 88 #include <sys/syslog.h> 89 #include <sys/socket.h> 90 #include <sys/device.h> 91 #include <sys/malloc.h> 92 #include <sys/ioctl.h> 93 #include <sys/errno.h> 94 #if NRND > 0 95 #include <sys/rnd.h> 96 #endif 97 98 #include <net/if.h> 99 #include <net/if_dl.h> 100 #include <net/if_ether.h> 101 #include <net/if_media.h> 102 103 #ifdef INET 104 #include <netinet/in.h> 105 #include <netinet/if_inarp.h> 106 #include <netinet/in_systm.h> 107 #include <netinet/in_var.h> 108 #include <netinet/ip.h> 109 #endif 110 111 #ifdef NS 112 #include <netns/ns.h> 113 #include <netns/ns_if.h> 114 #endif 115 116 #if defined(CCITT) && defined(LLC) 117 #include <sys/socketvar.h> 118 #include <netccitt/x25.h> 119 #include <netccitt/pk.h> 120 #include <netccitt/pk_var.h> 121 #include <netccitt/pk_extern.h> 122 #endif 123 124 #if NBPFILTER > 0 125 #include <net/bpf.h> 126 #include <net/bpfdesc.h> 127 #endif 128 129 #include <dev/ic/lancereg.h> 130 #include <dev/ic/lancevar.h> 131 132 #if defined(_KERNEL) && !defined(_LKM) 133 #include "opt_ddb.h" 134 #endif 135 136 #ifdef DDB 137 #define integrate 138 #define hide 139 #else 140 #define integrate static __inline 141 #define hide static 142 #endif 143 144 integrate struct mbuf *lance_get __P((struct lance_softc *, int, int)); 145 146 hide void lance_shutdown __P((void *)); 147 148 int lance_mediachange __P((struct ifnet *)); 149 void lance_mediastatus __P((struct ifnet *, struct ifmediareq *)); 150 151 static inline u_int16_t ether_cmp __P((void *, void *)); 152 153 void lance_stop __P((struct lance_softc *)); 154 int lance_ioctl __P((struct ifnet *, u_long, caddr_t)); 155 void lance_watchdog __P((struct ifnet *)); 156 157 /* 158 * Compare two Ether/802 addresses for equality, inlined and 159 * unrolled for speed. Use this like bcmp(). 160 * 161 * XXX: Add <machine/inlines.h> for stuff like this? 162 * XXX: or maybe add it to libkern.h instead? 163 * 164 * "I'd love to have an inline assembler version of this." 165 * XXX: Who wanted that? mycroft? I wrote one, but this 166 * version in C is as good as hand-coded assembly. -gwr 167 * 168 * Please do NOT tweak this without looking at the actual 169 * assembly code generated before and after your tweaks! 170 */ 171 static inline u_int16_t 172 ether_cmp(one, two) 173 void *one, *two; 174 { 175 u_int16_t *a = (u_short *) one; 176 u_int16_t *b = (u_short *) two; 177 u_int16_t diff; 178 179 #ifdef m68k 180 /* 181 * The post-increment-pointer form produces the best 182 * machine code for m68k. This was carefully tuned 183 * so it compiles to just 8 short (2-byte) op-codes! 184 */ 185 diff = *a++ - *b++; 186 diff |= *a++ - *b++; 187 diff |= *a++ - *b++; 188 #else 189 /* 190 * Most modern CPUs do better with a single expresion. 191 * Note that short-cut evaluation is NOT helpful here, 192 * because it just makes the code longer, not faster! 193 */ 194 diff = (a[0] - b[0]) | (a[1] - b[1]) | (a[2] - b[2]); 195 #endif 196 197 return (diff); 198 } 199 200 #define ETHER_CMP ether_cmp 201 202 #ifdef LANCE_REVC_BUG 203 /* Make sure this is short-aligned, for ether_cmp(). */ 204 static u_int16_t bcast_enaddr[3] = { ~0, ~0, ~0 }; 205 #endif 206 207 #define ifp (&sc->sc_ethercom.ec_if) 208 209 void 210 lance_config(sc) 211 struct lance_softc *sc; 212 { 213 int i; 214 215 /* Make sure the chip is stopped. */ 216 lance_stop(sc); 217 218 /* Initialize ifnet structure. */ 219 bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ); 220 ifp->if_softc = sc; 221 ifp->if_start = sc->sc_start; 222 ifp->if_ioctl = lance_ioctl; 223 ifp->if_watchdog = lance_watchdog; 224 ifp->if_flags = 225 IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST; 226 #ifdef LANCE_REVC_BUG 227 ifp->if_flags &= ~IFF_MULTICAST; 228 #endif 229 IFQ_SET_READY(&ifp->if_snd); 230 231 /* Initialize ifmedia structures. */ 232 ifmedia_init(&sc->sc_media, 0, lance_mediachange, lance_mediastatus); 233 if (sc->sc_supmedia != NULL) { 234 for (i = 0; i < sc->sc_nsupmedia; i++) 235 ifmedia_add(&sc->sc_media, sc->sc_supmedia[i], 236 0, NULL); 237 ifmedia_set(&sc->sc_media, sc->sc_defaultmedia); 238 } else { 239 ifmedia_add(&sc->sc_media, IFM_ETHER|IFM_MANUAL, 0, NULL); 240 ifmedia_set(&sc->sc_media, IFM_ETHER|IFM_MANUAL); 241 } 242 243 switch (sc->sc_memsize) { 244 case 8192: 245 sc->sc_nrbuf = 4; 246 sc->sc_ntbuf = 1; 247 break; 248 case 16384: 249 sc->sc_nrbuf = 8; 250 sc->sc_ntbuf = 2; 251 break; 252 case 32768: 253 sc->sc_nrbuf = 16; 254 sc->sc_ntbuf = 4; 255 break; 256 case 65536: 257 sc->sc_nrbuf = 32; 258 sc->sc_ntbuf = 8; 259 break; 260 case 131072: 261 sc->sc_nrbuf = 64; 262 sc->sc_ntbuf = 16; 263 break; 264 case 262144: 265 sc->sc_nrbuf = 128; 266 sc->sc_ntbuf = 32; 267 break; 268 default: 269 panic("lance_config: weird memory size"); 270 } 271 272 printf(": address %s\n", ether_sprintf(sc->sc_enaddr)); 273 printf("%s: %d receive buffers, %d transmit buffers\n", 274 sc->sc_dev.dv_xname, sc->sc_nrbuf, sc->sc_ntbuf); 275 276 /* claim 802.1q capability */ 277 sc->sc_ethercom.ec_capabilities |= ETHERCAP_VLAN_MTU; 278 /* Attach the interface. */ 279 if_attach(ifp); 280 ether_ifattach(ifp, sc->sc_enaddr); 281 282 sc->sc_sh = shutdownhook_establish(lance_shutdown, sc); 283 if (sc->sc_sh == NULL) 284 panic("lance_config: can't establish shutdownhook"); 285 sc->sc_rbufaddr = malloc(sc->sc_nrbuf * sizeof(int), M_DEVBUF, 286 M_WAITOK); 287 sc->sc_tbufaddr = malloc(sc->sc_ntbuf * sizeof(int), M_DEVBUF, 288 M_WAITOK); 289 290 #if NRND > 0 291 rnd_attach_source(&sc->rnd_source, sc->sc_dev.dv_xname, 292 RND_TYPE_NET, 0); 293 #endif 294 } 295 296 void 297 lance_reset(sc) 298 struct lance_softc *sc; 299 { 300 int s; 301 302 s = splnet(); 303 lance_init(sc); 304 splx(s); 305 } 306 307 void 308 lance_stop(sc) 309 struct lance_softc *sc; 310 { 311 312 (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_STOP); 313 } 314 315 /* 316 * Initialization of interface; set up initialization block 317 * and transmit/receive descriptor rings. 318 */ 319 void 320 lance_init(sc) 321 struct lance_softc *sc; 322 { 323 int timo; 324 u_long a; 325 326 (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_STOP); 327 DELAY(100); 328 329 /* Newer LANCE chips have a reset register */ 330 if (sc->sc_hwreset) 331 (*sc->sc_hwreset)(sc); 332 333 /* Set the correct byte swapping mode, etc. */ 334 (*sc->sc_wrcsr)(sc, LE_CSR3, sc->sc_conf3); 335 336 /* Set up LANCE init block. */ 337 (*sc->sc_meminit)(sc); 338 339 /* Give LANCE the physical address of its init block. */ 340 a = sc->sc_addr + LE_INITADDR(sc); 341 (*sc->sc_wrcsr)(sc, LE_CSR1, a); 342 (*sc->sc_wrcsr)(sc, LE_CSR2, a >> 16); 343 344 /* Try to initialize the LANCE. */ 345 DELAY(100); 346 (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INIT); 347 348 /* Wait for initialization to finish. */ 349 for (timo = 100000; timo; timo--) 350 if ((*sc->sc_rdcsr)(sc, LE_CSR0) & LE_C0_IDON) 351 break; 352 353 if ((*sc->sc_rdcsr)(sc, LE_CSR0) & LE_C0_IDON) { 354 /* Start the LANCE. */ 355 (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INEA | LE_C0_STRT | 356 LE_C0_IDON); 357 ifp->if_flags |= IFF_RUNNING; 358 ifp->if_flags &= ~IFF_OACTIVE; 359 ifp->if_timer = 0; 360 (*sc->sc_start)(ifp); 361 } else 362 printf("%s: controller failed to initialize\n", 363 sc->sc_dev.dv_xname); 364 if (sc->sc_hwinit) 365 (*sc->sc_hwinit)(sc); 366 } 367 368 /* 369 * Routine to copy from mbuf chain to transmit buffer in 370 * network buffer memory. 371 */ 372 int 373 lance_put(sc, boff, m) 374 struct lance_softc *sc; 375 int boff; 376 struct mbuf *m; 377 { 378 struct mbuf *n; 379 int len, tlen = 0; 380 381 for (; m; m = n) { 382 len = m->m_len; 383 if (len == 0) { 384 MFREE(m, n); 385 continue; 386 } 387 (*sc->sc_copytobuf)(sc, mtod(m, caddr_t), boff, len); 388 boff += len; 389 tlen += len; 390 MFREE(m, n); 391 } 392 if (tlen < LEMINSIZE) { 393 (*sc->sc_zerobuf)(sc, boff, LEMINSIZE - tlen); 394 tlen = LEMINSIZE; 395 } 396 return (tlen); 397 } 398 399 /* 400 * Pull data off an interface. 401 * Len is length of data, with local net header stripped. 402 * We copy the data into mbufs. When full cluster sized units are present 403 * we copy into clusters. 404 */ 405 integrate struct mbuf * 406 lance_get(sc, boff, totlen) 407 struct lance_softc *sc; 408 int boff, totlen; 409 { 410 struct mbuf *m, *m0, *newm; 411 int len; 412 413 MGETHDR(m0, M_DONTWAIT, MT_DATA); 414 if (m0 == 0) 415 return (0); 416 m0->m_pkthdr.rcvif = ifp; 417 m0->m_pkthdr.len = totlen; 418 len = MHLEN; 419 m = m0; 420 421 while (totlen > 0) { 422 if (totlen >= MINCLSIZE) { 423 MCLGET(m, M_DONTWAIT); 424 if ((m->m_flags & M_EXT) == 0) 425 goto bad; 426 len = MCLBYTES; 427 } 428 429 if (m == m0) { 430 caddr_t newdata = (caddr_t) 431 ALIGN(m->m_data + sizeof(struct ether_header)) - 432 sizeof(struct ether_header); 433 len -= newdata - m->m_data; 434 m->m_data = newdata; 435 } 436 437 m->m_len = len = min(totlen, len); 438 (*sc->sc_copyfrombuf)(sc, mtod(m, caddr_t), boff, len); 439 boff += len; 440 441 totlen -= len; 442 if (totlen > 0) { 443 MGET(newm, M_DONTWAIT, MT_DATA); 444 if (newm == 0) 445 goto bad; 446 len = MLEN; 447 m = m->m_next = newm; 448 } 449 } 450 451 return (m0); 452 453 bad: 454 m_freem(m0); 455 return (0); 456 } 457 458 /* 459 * Pass a packet to the higher levels. 460 */ 461 void 462 lance_read(sc, boff, len) 463 struct lance_softc *sc; 464 int boff, len; 465 { 466 struct mbuf *m; 467 #ifdef LANCE_REVC_BUG 468 struct ether_header *eh; 469 #endif 470 471 if (len <= sizeof(struct ether_header) || 472 len > ((sc->sc_ethercom.ec_capenable & ETHERCAP_VLAN_MTU) ? 473 ETHER_VLAN_ENCAP_LEN + ETHERMTU + sizeof(struct ether_header) : 474 ETHERMTU + sizeof(struct ether_header))) { 475 #ifdef LEDEBUG 476 printf("%s: invalid packet size %d; dropping\n", 477 sc->sc_dev.dv_xname, len); 478 #endif 479 ifp->if_ierrors++; 480 return; 481 } 482 483 /* Pull packet off interface. */ 484 m = lance_get(sc, boff, len); 485 if (m == 0) { 486 ifp->if_ierrors++; 487 return; 488 } 489 490 ifp->if_ipackets++; 491 492 #if NBPFILTER > 0 493 /* 494 * Check if there's a BPF listener on this interface. 495 * If so, hand off the raw packet to BPF. 496 */ 497 if (ifp->if_bpf) 498 bpf_mtap(ifp->if_bpf, m); 499 #endif 500 501 #ifdef LANCE_REVC_BUG 502 /* 503 * The old LANCE (Rev. C) chips have a bug which causes 504 * garbage to be inserted in front of the received packet. 505 * The work-around is to ignore packets with an invalid 506 * destination address (garbage will usually not match). 507 * Of course, this precludes multicast support... 508 */ 509 eh = mtod(m, struct ether_header *); 510 if (ETHER_CMP(eh->ether_dhost, sc->sc_enaddr) && 511 ETHER_CMP(eh->ether_dhost, bcast_enaddr)) { 512 m_freem(m); 513 return; 514 } 515 #endif 516 517 /* Pass the packet up. */ 518 (*ifp->if_input)(ifp, m); 519 } 520 521 #undef ifp 522 523 void 524 lance_watchdog(ifp) 525 struct ifnet *ifp; 526 { 527 struct lance_softc *sc = ifp->if_softc; 528 529 log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname); 530 ++ifp->if_oerrors; 531 532 lance_reset(sc); 533 } 534 535 int 536 lance_mediachange(ifp) 537 struct ifnet *ifp; 538 { 539 struct lance_softc *sc = ifp->if_softc; 540 541 if (sc->sc_mediachange) 542 return ((*sc->sc_mediachange)(sc)); 543 return (0); 544 } 545 546 void 547 lance_mediastatus(ifp, ifmr) 548 struct ifnet *ifp; 549 struct ifmediareq *ifmr; 550 { 551 struct lance_softc *sc = ifp->if_softc; 552 553 if ((ifp->if_flags & IFF_UP) == 0) 554 return; 555 556 ifmr->ifm_status = IFM_AVALID; 557 if (sc->sc_havecarrier) 558 ifmr->ifm_status |= IFM_ACTIVE; 559 560 if (sc->sc_mediastatus) 561 (*sc->sc_mediastatus)(sc, ifmr); 562 } 563 564 /* 565 * Process an ioctl request. 566 */ 567 int 568 lance_ioctl(ifp, cmd, data) 569 struct ifnet *ifp; 570 u_long cmd; 571 caddr_t data; 572 { 573 struct lance_softc *sc = ifp->if_softc; 574 struct ifaddr *ifa = (struct ifaddr *)data; 575 struct ifreq *ifr = (struct ifreq *)data; 576 int s, error = 0; 577 578 s = splnet(); 579 580 switch (cmd) { 581 582 case SIOCSIFADDR: 583 ifp->if_flags |= IFF_UP; 584 585 switch (ifa->ifa_addr->sa_family) { 586 #ifdef INET 587 case AF_INET: 588 lance_init(sc); 589 arp_ifinit(ifp, ifa); 590 break; 591 #endif 592 #ifdef NS 593 case AF_NS: 594 { 595 struct ns_addr *ina = &IA_SNS(ifa)->sns_addr; 596 597 if (ns_nullhost(*ina)) 598 ina->x_host = 599 *(union ns_host *)LLADDR(ifp->if_sadl); 600 else { 601 bcopy(ina->x_host.c_host, 602 LLADDR(ifp->if_sadl), 603 sizeof(sc->sc_enaddr)); 604 } 605 /* Set new address. */ 606 lance_init(sc); 607 break; 608 } 609 #endif 610 default: 611 lance_init(sc); 612 break; 613 } 614 break; 615 616 #if defined(CCITT) && defined(LLC) 617 case SIOCSIFCONF_X25: 618 ifp->if_flags |= IFF_UP; 619 ifa->ifa_rtrequest = cons_rtrequest; /* XXX */ 620 error = x25_llcglue(PRC_IFUP, ifa->ifa_addr); 621 if (error == 0) 622 lance_init(sc); 623 break; 624 #endif /* CCITT && LLC */ 625 626 case SIOCSIFFLAGS: 627 if ((ifp->if_flags & IFF_UP) == 0 && 628 (ifp->if_flags & IFF_RUNNING) != 0) { 629 /* 630 * If interface is marked down and it is running, then 631 * stop it. 632 */ 633 lance_stop(sc); 634 ifp->if_flags &= ~IFF_RUNNING; 635 } else if ((ifp->if_flags & IFF_UP) != 0 && 636 (ifp->if_flags & IFF_RUNNING) == 0) { 637 /* 638 * If interface is marked up and it is stopped, then 639 * start it. 640 */ 641 lance_init(sc); 642 } else if ((ifp->if_flags & IFF_UP) != 0) { 643 /* 644 * Reset the interface to pick up changes in any other 645 * flags that affect hardware registers. 646 */ 647 /*lance_stop(sc);*/ 648 lance_init(sc); 649 } 650 #ifdef LEDEBUG 651 if (ifp->if_flags & IFF_DEBUG) 652 sc->sc_debug = 1; 653 else 654 sc->sc_debug = 0; 655 #endif 656 break; 657 658 case SIOCADDMULTI: 659 case SIOCDELMULTI: 660 error = (cmd == SIOCADDMULTI) ? 661 ether_addmulti(ifr, &sc->sc_ethercom) : 662 ether_delmulti(ifr, &sc->sc_ethercom); 663 664 if (error == ENETRESET) { 665 /* 666 * Multicast list has changed; set the hardware filter 667 * accordingly. 668 */ 669 lance_reset(sc); 670 error = 0; 671 } 672 break; 673 674 case SIOCGIFMEDIA: 675 case SIOCSIFMEDIA: 676 error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd); 677 break; 678 679 default: 680 error = EINVAL; 681 break; 682 } 683 684 splx(s); 685 return (error); 686 } 687 688 hide void 689 lance_shutdown(arg) 690 void *arg; 691 { 692 693 lance_stop((struct lance_softc *)arg); 694 } 695 696 /* 697 * Set up the logical address filter. 698 */ 699 void 700 lance_setladrf(ac, af) 701 struct ethercom *ac; 702 u_int16_t *af; 703 { 704 struct ifnet *ifp = &ac->ec_if; 705 struct ether_multi *enm; 706 u_int32_t crc; 707 struct ether_multistep step; 708 709 /* 710 * Set up multicast address filter by passing all multicast addresses 711 * through a crc generator, and then using the high order 6 bits as an 712 * index into the 64 bit logical address filter. The high order bit 713 * selects the word, while the rest of the bits select the bit within 714 * the word. 715 */ 716 717 if (ifp->if_flags & IFF_PROMISC) 718 goto allmulti; 719 720 af[0] = af[1] = af[2] = af[3] = 0x0000; 721 ETHER_FIRST_MULTI(step, ac, enm); 722 while (enm != NULL) { 723 if (ETHER_CMP(enm->enm_addrlo, enm->enm_addrhi)) { 724 /* 725 * We must listen to a range of multicast addresses. 726 * For now, just accept all multicasts, rather than 727 * trying to set only those filter bits needed to match 728 * the range. (At this time, the only use of address 729 * ranges is for IP multicast routing, for which the 730 * range is big enough to require all bits set.) 731 */ 732 goto allmulti; 733 } 734 735 crc = ether_crc32_le(enm->enm_addrlo, ETHER_ADDR_LEN); 736 737 /* Just want the 6 most significant bits. */ 738 crc >>= 26; 739 740 /* Set the corresponding bit in the filter. */ 741 af[crc >> 4] |= 1 << (crc & 0xf); 742 743 ETHER_NEXT_MULTI(step, enm); 744 } 745 ifp->if_flags &= ~IFF_ALLMULTI; 746 return; 747 748 allmulti: 749 ifp->if_flags |= IFF_ALLMULTI; 750 af[0] = af[1] = af[2] = af[3] = 0xffff; 751 } 752 753 /* 754 * Routines for accessing the transmit and receive buffers. 755 * The various CPU and adapter configurations supported by this 756 * driver require three different access methods for buffers 757 * and descriptors: 758 * (1) contig (contiguous data; no padding), 759 * (2) gap2 (two bytes of data followed by two bytes of padding), 760 * (3) gap16 (16 bytes of data followed by 16 bytes of padding). 761 */ 762 763 /* 764 * contig: contiguous data with no padding. 765 * 766 * Buffers may have any alignment. 767 */ 768 769 void 770 lance_copytobuf_contig(sc, from, boff, len) 771 struct lance_softc *sc; 772 void *from; 773 int boff, len; 774 { 775 volatile caddr_t buf = sc->sc_mem; 776 777 /* 778 * Just call bcopy() to do the work. 779 */ 780 bcopy(from, buf + boff, len); 781 } 782 783 void 784 lance_copyfrombuf_contig(sc, to, boff, len) 785 struct lance_softc *sc; 786 void *to; 787 int boff, len; 788 { 789 volatile caddr_t buf = sc->sc_mem; 790 791 /* 792 * Just call bcopy() to do the work. 793 */ 794 bcopy(buf + boff, to, len); 795 } 796 797 void 798 lance_zerobuf_contig(sc, boff, len) 799 struct lance_softc *sc; 800 int boff, len; 801 { 802 volatile caddr_t buf = sc->sc_mem; 803 804 /* 805 * Just let bzero() do the work 806 */ 807 bzero(buf + boff, len); 808 } 809 810 #if 0 811 /* 812 * Examples only; duplicate these and tweak (if necessary) in 813 * machine-specific front-ends. 814 */ 815 816 /* 817 * gap2: two bytes of data followed by two bytes of pad. 818 * 819 * Buffers must be 4-byte aligned. The code doesn't worry about 820 * doing an extra byte. 821 */ 822 823 void 824 lance_copytobuf_gap2(sc, fromv, boff, len) 825 struct lance_softc *sc; 826 void *fromv; 827 int boff; 828 int len; 829 { 830 volatile caddr_t buf = sc->sc_mem; 831 caddr_t from = fromv; 832 volatile u_int16_t *bptr; 833 834 if (boff & 0x1) { 835 /* handle unaligned first byte */ 836 bptr = ((volatile u_int16_t *)buf) + (boff - 1); 837 *bptr = (*from++ << 8) | (*bptr & 0xff); 838 bptr += 2; 839 len--; 840 } else 841 bptr = ((volatile u_int16_t *)buf) + boff; 842 while (len > 1) { 843 *bptr = (from[1] << 8) | (from[0] & 0xff); 844 bptr += 2; 845 from += 2; 846 len -= 2; 847 } 848 if (len == 1) 849 *bptr = (u_int16_t)*from; 850 } 851 852 void 853 lance_copyfrombuf_gap2(sc, tov, boff, len) 854 struct lance_softc *sc; 855 void *tov; 856 int boff, len; 857 { 858 volatile caddr_t buf = sc->sc_mem; 859 caddr_t to = tov; 860 volatile u_int16_t *bptr; 861 u_int16_t tmp; 862 863 if (boff & 0x1) { 864 /* handle unaligned first byte */ 865 bptr = ((volatile u_int16_t *)buf) + (boff - 1); 866 *to++ = (*bptr >> 8) & 0xff; 867 bptr += 2; 868 len--; 869 } else 870 bptr = ((volatile u_int16_t *)buf) + boff; 871 while (len > 1) { 872 tmp = *bptr; 873 *to++ = tmp & 0xff; 874 *to++ = (tmp >> 8) & 0xff; 875 bptr += 2; 876 len -= 2; 877 } 878 if (len == 1) 879 *to = *bptr & 0xff; 880 } 881 882 void 883 lance_zerobuf_gap2(sc, boff, len) 884 struct lance_softc *sc; 885 int boff, len; 886 { 887 volatile caddr_t buf = sc->sc_mem; 888 volatile u_int16_t *bptr; 889 890 if ((unsigned)boff & 0x1) { 891 bptr = ((volatile u_int16_t *)buf) + (boff - 1); 892 *bptr &= 0xff; 893 bptr += 2; 894 len--; 895 } else 896 bptr = ((volatile u_int16_t *)buf) + boff; 897 while (len > 0) { 898 *bptr = 0; 899 bptr += 2; 900 len -= 2; 901 } 902 } 903 904 /* 905 * gap16: 16 bytes of data followed by 16 bytes of pad. 906 * 907 * Buffers must be 32-byte aligned. 908 */ 909 910 void 911 lance_copytobuf_gap16(sc, fromv, boff, len) 912 struct lance_softc *sc; 913 void *fromv; 914 int boff; 915 int len; 916 { 917 volatile caddr_t buf = sc->sc_mem; 918 caddr_t from = fromv; 919 caddr_t bptr; 920 int xfer; 921 922 bptr = buf + ((boff << 1) & ~0x1f); 923 boff &= 0xf; 924 xfer = min(len, 16 - boff); 925 while (len > 0) { 926 bcopy(from, bptr + boff, xfer); 927 from += xfer; 928 bptr += 32; 929 boff = 0; 930 len -= xfer; 931 xfer = min(len, 16); 932 } 933 } 934 935 void 936 lance_copyfrombuf_gap16(sc, tov, boff, len) 937 struct lance_softc *sc; 938 void *tov; 939 int boff, len; 940 { 941 volatile caddr_t buf = sc->sc_mem; 942 caddr_t to = tov; 943 caddr_t bptr; 944 int xfer; 945 946 bptr = buf + ((boff << 1) & ~0x1f); 947 boff &= 0xf; 948 xfer = min(len, 16 - boff); 949 while (len > 0) { 950 bcopy(bptr + boff, to, xfer); 951 to += xfer; 952 bptr += 32; 953 boff = 0; 954 len -= xfer; 955 xfer = min(len, 16); 956 } 957 } 958 959 void 960 lance_zerobuf_gap16(sc, boff, len) 961 struct lance_softc *sc; 962 int boff, len; 963 { 964 volatile caddr_t buf = sc->sc_mem; 965 caddr_t bptr; 966 int xfer; 967 968 bptr = buf + ((boff << 1) & ~0x1f); 969 boff &= 0xf; 970 xfer = min(len, 16 - boff); 971 while (len > 0) { 972 bzero(bptr + boff, xfer); 973 bptr += 32; 974 boff = 0; 975 len -= xfer; 976 xfer = min(len, 16); 977 } 978 } 979 #endif /* Example only */ 980