1 /* $NetBSD: lance.c,v 1.7 1999/02/28 17:10:53 explorer 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 /* Attach the interface. */ 243 if_attach(ifp); 244 ether_ifattach(ifp, sc->sc_enaddr); 245 246 #if NBPFILTER > 0 247 bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header)); 248 #endif 249 250 switch (sc->sc_memsize) { 251 case 8192: 252 sc->sc_nrbuf = 4; 253 sc->sc_ntbuf = 1; 254 break; 255 case 16384: 256 sc->sc_nrbuf = 8; 257 sc->sc_ntbuf = 2; 258 break; 259 case 32768: 260 sc->sc_nrbuf = 16; 261 sc->sc_ntbuf = 4; 262 break; 263 case 65536: 264 sc->sc_nrbuf = 32; 265 sc->sc_ntbuf = 8; 266 break; 267 case 131072: 268 sc->sc_nrbuf = 64; 269 sc->sc_ntbuf = 16; 270 break; 271 case 262144: 272 sc->sc_nrbuf = 128; 273 sc->sc_ntbuf = 32; 274 break; 275 default: 276 panic("lance_config: weird memory size"); 277 } 278 279 printf(": address %s\n", ether_sprintf(sc->sc_enaddr)); 280 printf("%s: %d receive buffers, %d transmit buffers\n", 281 sc->sc_dev.dv_xname, sc->sc_nrbuf, sc->sc_ntbuf); 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, with the ether header sort-of removed. */ 532 m_adj(m, sizeof(struct ether_header)); 533 ether_input(ifp, eh, m); 534 } 535 536 #undef ifp 537 538 void 539 lance_watchdog(ifp) 540 struct ifnet *ifp; 541 { 542 struct lance_softc *sc = ifp->if_softc; 543 544 log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname); 545 ++ifp->if_oerrors; 546 547 lance_reset(sc); 548 } 549 550 int 551 lance_mediachange(ifp) 552 struct ifnet *ifp; 553 { 554 struct lance_softc *sc = ifp->if_softc; 555 556 if (sc->sc_mediachange) 557 return ((*sc->sc_mediachange)(sc)); 558 return (EINVAL); 559 } 560 561 void 562 lance_mediastatus(ifp, ifmr) 563 struct ifnet *ifp; 564 struct ifmediareq *ifmr; 565 { 566 struct lance_softc *sc = ifp->if_softc; 567 568 if ((ifp->if_flags & IFF_UP) == 0) 569 return; 570 571 ifmr->ifm_status = IFM_AVALID; 572 if (sc->sc_havecarrier) 573 ifmr->ifm_status |= IFM_ACTIVE; 574 575 if (sc->sc_mediastatus) 576 (*sc->sc_mediastatus)(sc, ifmr); 577 } 578 579 /* 580 * Process an ioctl request. 581 */ 582 int 583 lance_ioctl(ifp, cmd, data) 584 register struct ifnet *ifp; 585 u_long cmd; 586 caddr_t data; 587 { 588 register struct lance_softc *sc = ifp->if_softc; 589 struct ifaddr *ifa = (struct ifaddr *)data; 590 struct ifreq *ifr = (struct ifreq *)data; 591 int s, error = 0; 592 593 s = splnet(); 594 595 switch (cmd) { 596 597 case SIOCSIFADDR: 598 ifp->if_flags |= IFF_UP; 599 600 switch (ifa->ifa_addr->sa_family) { 601 #ifdef INET 602 case AF_INET: 603 lance_init(sc); 604 arp_ifinit(ifp, ifa); 605 break; 606 #endif 607 #ifdef NS 608 case AF_NS: 609 { 610 register struct ns_addr *ina = &IA_SNS(ifa)->sns_addr; 611 612 if (ns_nullhost(*ina)) 613 ina->x_host = 614 *(union ns_host *)LLADDR(ifp->if_sadl); 615 else { 616 bcopy(ina->x_host.c_host, 617 LLADDR(ifp->if_sadl), 618 sizeof(sc->sc_enaddr)); 619 } 620 /* Set new address. */ 621 lance_init(sc); 622 break; 623 } 624 #endif 625 default: 626 lance_init(sc); 627 break; 628 } 629 break; 630 631 #if defined(CCITT) && defined(LLC) 632 case SIOCSIFCONF_X25: 633 ifp->if_flags |= IFF_UP; 634 ifa->ifa_rtrequest = cons_rtrequest; /* XXX */ 635 error = x25_llcglue(PRC_IFUP, ifa->ifa_addr); 636 if (error == 0) 637 lance_init(sc); 638 break; 639 #endif /* CCITT && LLC */ 640 641 case SIOCSIFFLAGS: 642 if ((ifp->if_flags & IFF_UP) == 0 && 643 (ifp->if_flags & IFF_RUNNING) != 0) { 644 /* 645 * If interface is marked down and it is running, then 646 * stop it. 647 */ 648 lance_stop(sc); 649 ifp->if_flags &= ~IFF_RUNNING; 650 } else if ((ifp->if_flags & IFF_UP) != 0 && 651 (ifp->if_flags & IFF_RUNNING) == 0) { 652 /* 653 * If interface is marked up and it is stopped, then 654 * start it. 655 */ 656 lance_init(sc); 657 } else if ((ifp->if_flags & IFF_UP) != 0) { 658 /* 659 * Reset the interface to pick up changes in any other 660 * flags that affect hardware registers. 661 */ 662 /*lance_stop(sc);*/ 663 lance_init(sc); 664 } 665 #ifdef LEDEBUG 666 if (ifp->if_flags & IFF_DEBUG) 667 sc->sc_debug = 1; 668 else 669 sc->sc_debug = 0; 670 #endif 671 break; 672 673 case SIOCADDMULTI: 674 case SIOCDELMULTI: 675 error = (cmd == SIOCADDMULTI) ? 676 ether_addmulti(ifr, &sc->sc_ethercom) : 677 ether_delmulti(ifr, &sc->sc_ethercom); 678 679 if (error == ENETRESET) { 680 /* 681 * Multicast list has changed; set the hardware filter 682 * accordingly. 683 */ 684 lance_reset(sc); 685 error = 0; 686 } 687 break; 688 689 case SIOCGIFMEDIA: 690 case SIOCSIFMEDIA: 691 error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd); 692 break; 693 694 default: 695 error = EINVAL; 696 break; 697 } 698 699 splx(s); 700 return (error); 701 } 702 703 hide void 704 lance_shutdown(arg) 705 void *arg; 706 { 707 708 lance_stop((struct lance_softc *)arg); 709 } 710 711 /* 712 * Set up the logical address filter. 713 */ 714 void 715 lance_setladrf(ac, af) 716 struct ethercom *ac; 717 u_int16_t *af; 718 { 719 struct ifnet *ifp = &ac->ec_if; 720 struct ether_multi *enm; 721 register u_char *cp; 722 register u_int32_t crc; 723 static const u_int32_t crctab[] = { 724 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 725 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c, 726 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, 727 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c 728 }; 729 register int len; 730 struct ether_multistep step; 731 732 /* 733 * Set up multicast address filter by passing all multicast addresses 734 * through a crc generator, and then using the high order 6 bits as an 735 * index into the 64 bit logical address filter. The high order bit 736 * selects the word, while the rest of the bits select the bit within 737 * the word. 738 */ 739 740 if (ifp->if_flags & IFF_PROMISC) 741 goto allmulti; 742 743 af[0] = af[1] = af[2] = af[3] = 0x0000; 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 >> 4] |= 1 << (crc & 0xf); 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 af[0] = af[1] = af[2] = af[3] = 0xffff; 779 } 780 781 /* 782 * Routines for accessing the transmit and receive buffers. 783 * The various CPU and adapter configurations supported by this 784 * driver require three different access methods for buffers 785 * and descriptors: 786 * (1) contig (contiguous data; no padding), 787 * (2) gap2 (two bytes of data followed by two bytes of padding), 788 * (3) gap16 (16 bytes of data followed by 16 bytes of padding). 789 */ 790 791 /* 792 * contig: contiguous data with no padding. 793 * 794 * Buffers may have any alignment. 795 */ 796 797 void 798 lance_copytobuf_contig(sc, from, boff, len) 799 struct lance_softc *sc; 800 void *from; 801 int boff, len; 802 { 803 volatile caddr_t buf = sc->sc_mem; 804 805 /* 806 * Just call bcopy() to do the work. 807 */ 808 bcopy(from, buf + boff, len); 809 } 810 811 void 812 lance_copyfrombuf_contig(sc, to, boff, len) 813 struct lance_softc *sc; 814 void *to; 815 int boff, len; 816 { 817 volatile caddr_t buf = sc->sc_mem; 818 819 /* 820 * Just call bcopy() to do the work. 821 */ 822 bcopy(buf + boff, to, len); 823 } 824 825 void 826 lance_zerobuf_contig(sc, boff, len) 827 struct lance_softc *sc; 828 int boff, len; 829 { 830 volatile caddr_t buf = sc->sc_mem; 831 832 /* 833 * Just let bzero() do the work 834 */ 835 bzero(buf + boff, len); 836 } 837 838 #if 0 839 /* 840 * Examples only; duplicate these and tweak (if necessary) in 841 * machine-specific front-ends. 842 */ 843 844 /* 845 * gap2: two bytes of data followed by two bytes of pad. 846 * 847 * Buffers must be 4-byte aligned. The code doesn't worry about 848 * doing an extra byte. 849 */ 850 851 void 852 lance_copytobuf_gap2(sc, fromv, boff, len) 853 struct lance_softc *sc; 854 void *fromv; 855 int boff; 856 register int len; 857 { 858 volatile caddr_t buf = sc->sc_mem; 859 register caddr_t from = fromv; 860 register volatile u_int16_t *bptr; 861 862 if (boff & 0x1) { 863 /* handle unaligned first byte */ 864 bptr = ((volatile u_int16_t *)buf) + (boff - 1); 865 *bptr = (*from++ << 8) | (*bptr & 0xff); 866 bptr += 2; 867 len--; 868 } else 869 bptr = ((volatile u_int16_t *)buf) + boff; 870 while (len > 1) { 871 *bptr = (from[1] << 8) | (from[0] & 0xff); 872 bptr += 2; 873 from += 2; 874 len -= 2; 875 } 876 if (len == 1) 877 *bptr = (u_int16_t)*from; 878 } 879 880 void 881 lance_copyfrombuf_gap2(sc, tov, boff, len) 882 struct lance_softc *sc; 883 void *tov; 884 int boff, len; 885 { 886 volatile caddr_t buf = sc->sc_mem; 887 register caddr_t to = tov; 888 register volatile u_int16_t *bptr; 889 register u_int16_t tmp; 890 891 if (boff & 0x1) { 892 /* handle unaligned first byte */ 893 bptr = ((volatile u_int16_t *)buf) + (boff - 1); 894 *to++ = (*bptr >> 8) & 0xff; 895 bptr += 2; 896 len--; 897 } else 898 bptr = ((volatile u_int16_t *)buf) + boff; 899 while (len > 1) { 900 tmp = *bptr; 901 *to++ = tmp & 0xff; 902 *to++ = (tmp >> 8) & 0xff; 903 bptr += 2; 904 len -= 2; 905 } 906 if (len == 1) 907 *to = *bptr & 0xff; 908 } 909 910 void 911 lance_zerobuf_gap2(sc, boff, len) 912 struct lance_softc *sc; 913 int boff, len; 914 { 915 volatile caddr_t buf = sc->sc_mem; 916 register volatile u_int16_t *bptr; 917 918 if ((unsigned)boff & 0x1) { 919 bptr = ((volatile u_int16_t *)buf) + (boff - 1); 920 *bptr &= 0xff; 921 bptr += 2; 922 len--; 923 } else 924 bptr = ((volatile u_int16_t *)buf) + boff; 925 while (len > 0) { 926 *bptr = 0; 927 bptr += 2; 928 len -= 2; 929 } 930 } 931 932 /* 933 * gap16: 16 bytes of data followed by 16 bytes of pad. 934 * 935 * Buffers must be 32-byte aligned. 936 */ 937 938 void 939 lance_copytobuf_gap16(sc, fromv, boff, len) 940 struct lance_softc *sc; 941 void *fromv; 942 int boff; 943 register int len; 944 { 945 volatile caddr_t buf = sc->sc_mem; 946 register caddr_t from = fromv; 947 register caddr_t bptr; 948 register int xfer; 949 950 bptr = buf + ((boff << 1) & ~0x1f); 951 boff &= 0xf; 952 xfer = min(len, 16 - boff); 953 while (len > 0) { 954 bcopy(from, bptr + boff, xfer); 955 from += xfer; 956 bptr += 32; 957 boff = 0; 958 len -= xfer; 959 xfer = min(len, 16); 960 } 961 } 962 963 void 964 lance_copyfrombuf_gap16(sc, tov, boff, len) 965 struct lance_softc *sc; 966 void *tov; 967 int boff, len; 968 { 969 volatile caddr_t buf = sc->sc_mem; 970 register caddr_t to = tov; 971 register caddr_t bptr; 972 register int xfer; 973 974 bptr = buf + ((boff << 1) & ~0x1f); 975 boff &= 0xf; 976 xfer = min(len, 16 - boff); 977 while (len > 0) { 978 bcopy(bptr + boff, to, xfer); 979 to += xfer; 980 bptr += 32; 981 boff = 0; 982 len -= xfer; 983 xfer = min(len, 16); 984 } 985 } 986 987 void 988 lance_zerobuf_gap16(sc, boff, len) 989 struct lance_softc *sc; 990 int boff, len; 991 { 992 volatile caddr_t buf = sc->sc_mem; 993 register caddr_t bptr; 994 register int xfer; 995 996 bptr = buf + ((boff << 1) & ~0x1f); 997 boff &= 0xf; 998 xfer = min(len, 16 - boff); 999 while (len > 0) { 1000 bzero(bptr + boff, xfer); 1001 bptr += 32; 1002 boff = 0; 1003 len -= xfer; 1004 xfer = min(len, 16); 1005 } 1006 } 1007 #endif /* Example only */ 1008