1 /* $NetBSD: lance.c,v 1.10 1999/11/17 03:42:24 simonb 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 register u_int16_t *a = (u_short *) one; 176 register u_int16_t *b = (u_short *) two; 177 register 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 230 /* Initialize ifmedia structures. */ 231 ifmedia_init(&sc->sc_media, 0, lance_mediachange, lance_mediastatus); 232 if (sc->sc_supmedia != NULL) { 233 for (i = 0; i < sc->sc_nsupmedia; i++) 234 ifmedia_add(&sc->sc_media, sc->sc_supmedia[i], 235 0, NULL); 236 ifmedia_set(&sc->sc_media, sc->sc_defaultmedia); 237 } else { 238 ifmedia_add(&sc->sc_media, IFM_ETHER|IFM_MANUAL, 0, NULL); 239 ifmedia_set(&sc->sc_media, IFM_ETHER|IFM_MANUAL); 240 } 241 242 switch (sc->sc_memsize) { 243 case 8192: 244 sc->sc_nrbuf = 4; 245 sc->sc_ntbuf = 1; 246 break; 247 case 16384: 248 sc->sc_nrbuf = 8; 249 sc->sc_ntbuf = 2; 250 break; 251 case 32768: 252 sc->sc_nrbuf = 16; 253 sc->sc_ntbuf = 4; 254 break; 255 case 65536: 256 sc->sc_nrbuf = 32; 257 sc->sc_ntbuf = 8; 258 break; 259 case 131072: 260 sc->sc_nrbuf = 64; 261 sc->sc_ntbuf = 16; 262 break; 263 case 262144: 264 sc->sc_nrbuf = 128; 265 sc->sc_ntbuf = 32; 266 break; 267 default: 268 panic("lance_config: weird memory size"); 269 } 270 271 printf(": address %s\n", ether_sprintf(sc->sc_enaddr)); 272 printf("%s: %d receive buffers, %d transmit buffers\n", 273 sc->sc_dev.dv_xname, sc->sc_nrbuf, sc->sc_ntbuf); 274 275 /* Attach the interface. */ 276 if_attach(ifp); 277 ether_ifattach(ifp, sc->sc_enaddr); 278 279 #if NBPFILTER > 0 280 bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header)); 281 #endif 282 283 sc->sc_sh = shutdownhook_establish(lance_shutdown, sc); 284 if (sc->sc_sh == NULL) 285 panic("lance_config: can't establish shutdownhook"); 286 sc->sc_rbufaddr = malloc(sc->sc_nrbuf * sizeof(int), M_DEVBUF, 287 M_WAITOK); 288 sc->sc_tbufaddr = malloc(sc->sc_ntbuf * sizeof(int), M_DEVBUF, 289 M_WAITOK); 290 291 #if NRND > 0 292 rnd_attach_source(&sc->rnd_source, sc->sc_dev.dv_xname, 293 RND_TYPE_NET, 0); 294 #endif 295 } 296 297 void 298 lance_reset(sc) 299 struct lance_softc *sc; 300 { 301 int s; 302 303 s = splnet(); 304 lance_init(sc); 305 splx(s); 306 } 307 308 void 309 lance_stop(sc) 310 struct lance_softc *sc; 311 { 312 313 (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_STOP); 314 } 315 316 /* 317 * Initialization of interface; set up initialization block 318 * and transmit/receive descriptor rings. 319 */ 320 void 321 lance_init(sc) 322 register struct lance_softc *sc; 323 { 324 register int timo; 325 u_long a; 326 327 (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_STOP); 328 DELAY(100); 329 330 /* Newer LANCE chips have a reset register */ 331 if (sc->sc_hwreset) 332 (*sc->sc_hwreset)(sc); 333 334 /* Set the correct byte swapping mode, etc. */ 335 (*sc->sc_wrcsr)(sc, LE_CSR3, sc->sc_conf3); 336 337 /* Set up LANCE init block. */ 338 (*sc->sc_meminit)(sc); 339 340 /* Give LANCE the physical address of its init block. */ 341 a = sc->sc_addr + LE_INITADDR(sc); 342 (*sc->sc_wrcsr)(sc, LE_CSR1, a); 343 (*sc->sc_wrcsr)(sc, LE_CSR2, a >> 16); 344 345 /* Try to initialize the LANCE. */ 346 DELAY(100); 347 (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INIT); 348 349 /* Wait for initialization to finish. */ 350 for (timo = 100000; timo; timo--) 351 if ((*sc->sc_rdcsr)(sc, LE_CSR0) & LE_C0_IDON) 352 break; 353 354 if ((*sc->sc_rdcsr)(sc, LE_CSR0) & LE_C0_IDON) { 355 /* Start the LANCE. */ 356 (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INEA | LE_C0_STRT | 357 LE_C0_IDON); 358 ifp->if_flags |= IFF_RUNNING; 359 ifp->if_flags &= ~IFF_OACTIVE; 360 ifp->if_timer = 0; 361 (*sc->sc_start)(ifp); 362 } else 363 printf("%s: controller failed to initialize\n", 364 sc->sc_dev.dv_xname); 365 if (sc->sc_hwinit) 366 (*sc->sc_hwinit)(sc); 367 } 368 369 /* 370 * Routine to copy from mbuf chain to transmit buffer in 371 * network buffer memory. 372 */ 373 int 374 lance_put(sc, boff, m) 375 struct lance_softc *sc; 376 int boff; 377 register struct mbuf *m; 378 { 379 register struct mbuf *n; 380 register int len, tlen = 0; 381 382 for (; m; m = n) { 383 len = m->m_len; 384 if (len == 0) { 385 MFREE(m, n); 386 continue; 387 } 388 (*sc->sc_copytobuf)(sc, mtod(m, caddr_t), boff, len); 389 boff += len; 390 tlen += len; 391 MFREE(m, n); 392 } 393 if (tlen < LEMINSIZE) { 394 (*sc->sc_zerobuf)(sc, boff, LEMINSIZE - tlen); 395 tlen = LEMINSIZE; 396 } 397 return (tlen); 398 } 399 400 /* 401 * Pull data off an interface. 402 * Len is length of data, with local net header stripped. 403 * We copy the data into mbufs. When full cluster sized units are present 404 * we copy into clusters. 405 */ 406 integrate struct mbuf * 407 lance_get(sc, boff, totlen) 408 struct lance_softc *sc; 409 int boff, totlen; 410 { 411 struct mbuf *m, *m0, *newm; 412 int len; 413 414 MGETHDR(m0, M_DONTWAIT, MT_DATA); 415 if (m0 == 0) 416 return (0); 417 m0->m_pkthdr.rcvif = ifp; 418 m0->m_pkthdr.len = totlen; 419 len = MHLEN; 420 m = m0; 421 422 while (totlen > 0) { 423 if (totlen >= MINCLSIZE) { 424 MCLGET(m, M_DONTWAIT); 425 if ((m->m_flags & M_EXT) == 0) 426 goto bad; 427 len = MCLBYTES; 428 } 429 430 if (m == m0) { 431 caddr_t newdata = (caddr_t) 432 ALIGN(m->m_data + sizeof(struct ether_header)) - 433 sizeof(struct ether_header); 434 len -= newdata - m->m_data; 435 m->m_data = newdata; 436 } 437 438 m->m_len = len = min(totlen, len); 439 (*sc->sc_copyfrombuf)(sc, mtod(m, caddr_t), boff, len); 440 boff += len; 441 442 totlen -= len; 443 if (totlen > 0) { 444 MGET(newm, M_DONTWAIT, MT_DATA); 445 if (newm == 0) 446 goto bad; 447 len = MLEN; 448 m = m->m_next = newm; 449 } 450 } 451 452 return (m0); 453 454 bad: 455 m_freem(m0); 456 return (0); 457 } 458 459 /* 460 * Pass a packet to the higher levels. 461 */ 462 void 463 lance_read(sc, boff, len) 464 register struct lance_softc *sc; 465 int boff, len; 466 { 467 struct mbuf *m; 468 struct ether_header *eh; 469 470 if (len <= sizeof(struct ether_header) || 471 len > ETHERMTU + sizeof(struct ether_header)) { 472 #ifdef LEDEBUG 473 printf("%s: invalid packet size %d; dropping\n", 474 sc->sc_dev.dv_xname, len); 475 #endif 476 ifp->if_ierrors++; 477 return; 478 } 479 480 /* Pull packet off interface. */ 481 m = lance_get(sc, boff, len); 482 if (m == 0) { 483 ifp->if_ierrors++; 484 return; 485 } 486 487 ifp->if_ipackets++; 488 489 /* We assume that the header fit entirely in one mbuf. */ 490 eh = mtod(m, struct ether_header *); 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 500 #ifndef LANCE_REVC_BUG 501 /* 502 * Note that the interface cannot be in promiscuous mode if 503 * there are no BPF listeners. And if we are in promiscuous 504 * mode, we have to check if this packet is really ours. 505 */ 506 if ((ifp->if_flags & IFF_PROMISC) != 0 && 507 (eh->ether_dhost[0] & 1) == 0 && /* !mcast and !bcast */ 508 ETHER_CMP(eh->ether_dhost, sc->sc_enaddr)) { 509 m_freem(m); 510 return; 511 } 512 #endif 513 } 514 #endif 515 516 #ifdef LANCE_REVC_BUG 517 /* 518 * The old LANCE (Rev. C) chips have a bug which causes 519 * garbage to be inserted in front of the received packet. 520 * The work-around is to ignore packets with an invalid 521 * destination address (garbage will usually not match). 522 * Of course, this precludes multicast support... 523 */ 524 if (ETHER_CMP(eh->ether_dhost, sc->sc_enaddr) && 525 ETHER_CMP(eh->ether_dhost, bcast_enaddr)) { 526 m_freem(m); 527 return; 528 } 529 #endif 530 531 /* Pass the packet up. */ 532 (*ifp->if_input)(ifp, m); 533 } 534 535 #undef ifp 536 537 void 538 lance_watchdog(ifp) 539 struct ifnet *ifp; 540 { 541 struct lance_softc *sc = ifp->if_softc; 542 543 log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname); 544 ++ifp->if_oerrors; 545 546 lance_reset(sc); 547 } 548 549 int 550 lance_mediachange(ifp) 551 struct ifnet *ifp; 552 { 553 struct lance_softc *sc = ifp->if_softc; 554 555 if (sc->sc_mediachange) 556 return ((*sc->sc_mediachange)(sc)); 557 return (0); 558 } 559 560 void 561 lance_mediastatus(ifp, ifmr) 562 struct ifnet *ifp; 563 struct ifmediareq *ifmr; 564 { 565 struct lance_softc *sc = ifp->if_softc; 566 567 if ((ifp->if_flags & IFF_UP) == 0) 568 return; 569 570 ifmr->ifm_status = IFM_AVALID; 571 if (sc->sc_havecarrier) 572 ifmr->ifm_status |= IFM_ACTIVE; 573 574 if (sc->sc_mediastatus) 575 (*sc->sc_mediastatus)(sc, ifmr); 576 } 577 578 /* 579 * Process an ioctl request. 580 */ 581 int 582 lance_ioctl(ifp, cmd, data) 583 register struct ifnet *ifp; 584 u_long cmd; 585 caddr_t data; 586 { 587 register struct lance_softc *sc = ifp->if_softc; 588 struct ifaddr *ifa = (struct ifaddr *)data; 589 struct ifreq *ifr = (struct ifreq *)data; 590 int s, error = 0; 591 592 s = splnet(); 593 594 switch (cmd) { 595 596 case SIOCSIFADDR: 597 ifp->if_flags |= IFF_UP; 598 599 switch (ifa->ifa_addr->sa_family) { 600 #ifdef INET 601 case AF_INET: 602 lance_init(sc); 603 arp_ifinit(ifp, ifa); 604 break; 605 #endif 606 #ifdef NS 607 case AF_NS: 608 { 609 register struct ns_addr *ina = &IA_SNS(ifa)->sns_addr; 610 611 if (ns_nullhost(*ina)) 612 ina->x_host = 613 *(union ns_host *)LLADDR(ifp->if_sadl); 614 else { 615 bcopy(ina->x_host.c_host, 616 LLADDR(ifp->if_sadl), 617 sizeof(sc->sc_enaddr)); 618 } 619 /* Set new address. */ 620 lance_init(sc); 621 break; 622 } 623 #endif 624 default: 625 lance_init(sc); 626 break; 627 } 628 break; 629 630 #if defined(CCITT) && defined(LLC) 631 case SIOCSIFCONF_X25: 632 ifp->if_flags |= IFF_UP; 633 ifa->ifa_rtrequest = cons_rtrequest; /* XXX */ 634 error = x25_llcglue(PRC_IFUP, ifa->ifa_addr); 635 if (error == 0) 636 lance_init(sc); 637 break; 638 #endif /* CCITT && LLC */ 639 640 case SIOCSIFFLAGS: 641 if ((ifp->if_flags & IFF_UP) == 0 && 642 (ifp->if_flags & IFF_RUNNING) != 0) { 643 /* 644 * If interface is marked down and it is running, then 645 * stop it. 646 */ 647 lance_stop(sc); 648 ifp->if_flags &= ~IFF_RUNNING; 649 } else if ((ifp->if_flags & IFF_UP) != 0 && 650 (ifp->if_flags & IFF_RUNNING) == 0) { 651 /* 652 * If interface is marked up and it is stopped, then 653 * start it. 654 */ 655 lance_init(sc); 656 } else if ((ifp->if_flags & IFF_UP) != 0) { 657 /* 658 * Reset the interface to pick up changes in any other 659 * flags that affect hardware registers. 660 */ 661 /*lance_stop(sc);*/ 662 lance_init(sc); 663 } 664 #ifdef LEDEBUG 665 if (ifp->if_flags & IFF_DEBUG) 666 sc->sc_debug = 1; 667 else 668 sc->sc_debug = 0; 669 #endif 670 break; 671 672 case SIOCADDMULTI: 673 case SIOCDELMULTI: 674 error = (cmd == SIOCADDMULTI) ? 675 ether_addmulti(ifr, &sc->sc_ethercom) : 676 ether_delmulti(ifr, &sc->sc_ethercom); 677 678 if (error == ENETRESET) { 679 /* 680 * Multicast list has changed; set the hardware filter 681 * accordingly. 682 */ 683 lance_reset(sc); 684 error = 0; 685 } 686 break; 687 688 case SIOCGIFMEDIA: 689 case SIOCSIFMEDIA: 690 error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd); 691 break; 692 693 default: 694 error = EINVAL; 695 break; 696 } 697 698 splx(s); 699 return (error); 700 } 701 702 hide void 703 lance_shutdown(arg) 704 void *arg; 705 { 706 707 lance_stop((struct lance_softc *)arg); 708 } 709 710 /* 711 * Set up the logical address filter. 712 */ 713 void 714 lance_setladrf(ac, af) 715 struct ethercom *ac; 716 u_int16_t *af; 717 { 718 struct ifnet *ifp = &ac->ec_if; 719 struct ether_multi *enm; 720 register u_char *cp; 721 register u_int32_t crc; 722 static const u_int32_t crctab[] = { 723 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 724 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c, 725 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, 726 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c 727 }; 728 register int len; 729 struct ether_multistep step; 730 731 /* 732 * Set up multicast address filter by passing all multicast addresses 733 * through a crc generator, and then using the high order 6 bits as an 734 * index into the 64 bit logical address filter. The high order bit 735 * selects the word, while the rest of the bits select the bit within 736 * the word. 737 */ 738 739 if (ifp->if_flags & IFF_PROMISC) 740 goto allmulti; 741 742 af[0] = af[1] = af[2] = af[3] = 0x0000; 743 ETHER_FIRST_MULTI(step, ac, enm); 744 while (enm != NULL) { 745 if (ETHER_CMP(enm->enm_addrlo, enm->enm_addrhi)) { 746 /* 747 * We must listen to a range of multicast addresses. 748 * For now, just accept all multicasts, rather than 749 * trying to set only those filter bits needed to match 750 * the range. (At this time, the only use of address 751 * ranges is for IP multicast routing, for which the 752 * range is big enough to require all bits set.) 753 */ 754 goto allmulti; 755 } 756 757 cp = enm->enm_addrlo; 758 crc = 0xffffffff; 759 for (len = sizeof(enm->enm_addrlo); --len >= 0;) { 760 crc ^= *cp++; 761 crc = (crc >> 4) ^ crctab[crc & 0xf]; 762 crc = (crc >> 4) ^ crctab[crc & 0xf]; 763 } 764 /* Just want the 6 most significant bits. */ 765 crc >>= 26; 766 767 /* Set the corresponding bit in the filter. */ 768 af[crc >> 4] |= 1 << (crc & 0xf); 769 770 ETHER_NEXT_MULTI(step, enm); 771 } 772 ifp->if_flags &= ~IFF_ALLMULTI; 773 return; 774 775 allmulti: 776 ifp->if_flags |= IFF_ALLMULTI; 777 af[0] = af[1] = af[2] = af[3] = 0xffff; 778 } 779 780 /* 781 * Routines for accessing the transmit and receive buffers. 782 * The various CPU and adapter configurations supported by this 783 * driver require three different access methods for buffers 784 * and descriptors: 785 * (1) contig (contiguous data; no padding), 786 * (2) gap2 (two bytes of data followed by two bytes of padding), 787 * (3) gap16 (16 bytes of data followed by 16 bytes of padding). 788 */ 789 790 /* 791 * contig: contiguous data with no padding. 792 * 793 * Buffers may have any alignment. 794 */ 795 796 void 797 lance_copytobuf_contig(sc, from, boff, len) 798 struct lance_softc *sc; 799 void *from; 800 int boff, len; 801 { 802 volatile caddr_t buf = sc->sc_mem; 803 804 /* 805 * Just call bcopy() to do the work. 806 */ 807 bcopy(from, buf + boff, len); 808 } 809 810 void 811 lance_copyfrombuf_contig(sc, to, boff, len) 812 struct lance_softc *sc; 813 void *to; 814 int boff, len; 815 { 816 volatile caddr_t buf = sc->sc_mem; 817 818 /* 819 * Just call bcopy() to do the work. 820 */ 821 bcopy(buf + boff, to, len); 822 } 823 824 void 825 lance_zerobuf_contig(sc, boff, len) 826 struct lance_softc *sc; 827 int boff, len; 828 { 829 volatile caddr_t buf = sc->sc_mem; 830 831 /* 832 * Just let bzero() do the work 833 */ 834 bzero(buf + boff, len); 835 } 836 837 #if 0 838 /* 839 * Examples only; duplicate these and tweak (if necessary) in 840 * machine-specific front-ends. 841 */ 842 843 /* 844 * gap2: two bytes of data followed by two bytes of pad. 845 * 846 * Buffers must be 4-byte aligned. The code doesn't worry about 847 * doing an extra byte. 848 */ 849 850 void 851 lance_copytobuf_gap2(sc, fromv, boff, len) 852 struct lance_softc *sc; 853 void *fromv; 854 int boff; 855 register int len; 856 { 857 volatile caddr_t buf = sc->sc_mem; 858 register caddr_t from = fromv; 859 register volatile u_int16_t *bptr; 860 861 if (boff & 0x1) { 862 /* handle unaligned first byte */ 863 bptr = ((volatile u_int16_t *)buf) + (boff - 1); 864 *bptr = (*from++ << 8) | (*bptr & 0xff); 865 bptr += 2; 866 len--; 867 } else 868 bptr = ((volatile u_int16_t *)buf) + boff; 869 while (len > 1) { 870 *bptr = (from[1] << 8) | (from[0] & 0xff); 871 bptr += 2; 872 from += 2; 873 len -= 2; 874 } 875 if (len == 1) 876 *bptr = (u_int16_t)*from; 877 } 878 879 void 880 lance_copyfrombuf_gap2(sc, tov, boff, len) 881 struct lance_softc *sc; 882 void *tov; 883 int boff, len; 884 { 885 volatile caddr_t buf = sc->sc_mem; 886 register caddr_t to = tov; 887 register volatile u_int16_t *bptr; 888 register u_int16_t tmp; 889 890 if (boff & 0x1) { 891 /* handle unaligned first byte */ 892 bptr = ((volatile u_int16_t *)buf) + (boff - 1); 893 *to++ = (*bptr >> 8) & 0xff; 894 bptr += 2; 895 len--; 896 } else 897 bptr = ((volatile u_int16_t *)buf) + boff; 898 while (len > 1) { 899 tmp = *bptr; 900 *to++ = tmp & 0xff; 901 *to++ = (tmp >> 8) & 0xff; 902 bptr += 2; 903 len -= 2; 904 } 905 if (len == 1) 906 *to = *bptr & 0xff; 907 } 908 909 void 910 lance_zerobuf_gap2(sc, boff, len) 911 struct lance_softc *sc; 912 int boff, len; 913 { 914 volatile caddr_t buf = sc->sc_mem; 915 register volatile u_int16_t *bptr; 916 917 if ((unsigned)boff & 0x1) { 918 bptr = ((volatile u_int16_t *)buf) + (boff - 1); 919 *bptr &= 0xff; 920 bptr += 2; 921 len--; 922 } else 923 bptr = ((volatile u_int16_t *)buf) + boff; 924 while (len > 0) { 925 *bptr = 0; 926 bptr += 2; 927 len -= 2; 928 } 929 } 930 931 /* 932 * gap16: 16 bytes of data followed by 16 bytes of pad. 933 * 934 * Buffers must be 32-byte aligned. 935 */ 936 937 void 938 lance_copytobuf_gap16(sc, fromv, boff, len) 939 struct lance_softc *sc; 940 void *fromv; 941 int boff; 942 register int len; 943 { 944 volatile caddr_t buf = sc->sc_mem; 945 register caddr_t from = fromv; 946 register caddr_t bptr; 947 register int xfer; 948 949 bptr = buf + ((boff << 1) & ~0x1f); 950 boff &= 0xf; 951 xfer = min(len, 16 - boff); 952 while (len > 0) { 953 bcopy(from, bptr + boff, xfer); 954 from += xfer; 955 bptr += 32; 956 boff = 0; 957 len -= xfer; 958 xfer = min(len, 16); 959 } 960 } 961 962 void 963 lance_copyfrombuf_gap16(sc, tov, boff, len) 964 struct lance_softc *sc; 965 void *tov; 966 int boff, len; 967 { 968 volatile caddr_t buf = sc->sc_mem; 969 register caddr_t to = tov; 970 register caddr_t bptr; 971 register int xfer; 972 973 bptr = buf + ((boff << 1) & ~0x1f); 974 boff &= 0xf; 975 xfer = min(len, 16 - boff); 976 while (len > 0) { 977 bcopy(bptr + boff, to, xfer); 978 to += xfer; 979 bptr += 32; 980 boff = 0; 981 len -= xfer; 982 xfer = min(len, 16); 983 } 984 } 985 986 void 987 lance_zerobuf_gap16(sc, boff, len) 988 struct lance_softc *sc; 989 int boff, len; 990 { 991 volatile caddr_t buf = sc->sc_mem; 992 register caddr_t bptr; 993 register int xfer; 994 995 bptr = buf + ((boff << 1) & ~0x1f); 996 boff &= 0xf; 997 xfer = min(len, 16 - boff); 998 while (len > 0) { 999 bzero(bptr + boff, xfer); 1000 bptr += 32; 1001 boff = 0; 1002 len -= xfer; 1003 xfer = min(len, 16); 1004 } 1005 } 1006 #endif /* Example only */ 1007