lance.c (155093) | lance.c (158663) |
---|---|
1/* $NetBSD: lance.c,v 1.34 2005/12/24 20:27:30 perry 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 --- 58 unchanged lines hidden (view full) --- 67 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 68 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 69 * SUCH DAMAGE. 70 * 71 * @(#)if_le.c 8.2 (Berkeley) 11/16/93 72 */ 73 74#include <sys/cdefs.h> | 1/* $NetBSD: lance.c,v 1.34 2005/12/24 20:27:30 perry 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 --- 58 unchanged lines hidden (view full) --- 67 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 68 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 69 * SUCH DAMAGE. 70 * 71 * @(#)if_le.c 8.2 (Berkeley) 11/16/93 72 */ 73 74#include <sys/cdefs.h> |
75__FBSDID("$FreeBSD: head/sys/dev/le/lance.c 155093 2006-01-31 14:48:58Z marius $"); | 75__FBSDID("$FreeBSD: head/sys/dev/le/lance.c 158663 2006-05-16 21:04:01Z marius $"); |
76 77#include <sys/param.h> 78#include <sys/bus.h> 79#include <sys/endian.h> 80#include <sys/lock.h> 81#include <sys/mbuf.h> 82#include <sys/mutex.h> 83#include <sys/socket.h> 84#include <sys/sockio.h> 85 86#include <net/ethernet.h> 87#include <net/if.h> 88#include <net/if_arp.h> 89#include <net/if_dl.h> 90#include <net/if_media.h> 91#include <net/if_types.h> 92#include <net/if_vlan_var.h> 93 | 76 77#include <sys/param.h> 78#include <sys/bus.h> 79#include <sys/endian.h> 80#include <sys/lock.h> 81#include <sys/mbuf.h> 82#include <sys/mutex.h> 83#include <sys/socket.h> 84#include <sys/sockio.h> 85 86#include <net/ethernet.h> 87#include <net/if.h> 88#include <net/if_arp.h> 89#include <net/if_dl.h> 90#include <net/if_media.h> 91#include <net/if_types.h> 92#include <net/if_vlan_var.h> 93 |
94#include <machine/bus.h> 95 |
|
94#include <dev/le/lancereg.h> 95#include <dev/le/lancevar.h> 96 97devclass_t le_devclass; 98 | 96#include <dev/le/lancereg.h> 97#include <dev/le/lancevar.h> 98 99devclass_t le_devclass; 100 |
99static inline uint16_t ether_cmp(void *, void *); 100 | |
101static void lance_start(struct ifnet *); 102static void lance_stop(struct lance_softc *); 103static void lance_init(void *); | 101static void lance_start(struct ifnet *); 102static void lance_stop(struct lance_softc *); 103static void lance_init(void *); |
104static struct mbuf *lance_get(struct lance_softc *, int, int); | |
105static void lance_watchdog(struct ifnet *); 106static int lance_mediachange(struct ifnet *); 107static void lance_mediastatus(struct ifnet *, struct ifmediareq *); 108static int lance_ioctl(struct ifnet *, u_long, caddr_t); 109 | 104static void lance_watchdog(struct ifnet *); 105static int lance_mediachange(struct ifnet *); 106static void lance_mediastatus(struct ifnet *, struct ifmediareq *); 107static int lance_ioctl(struct ifnet *, u_long, caddr_t); 108 |
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 */ 124static inline uint16_t 125ether_cmp(void *one, void *two) 126{ 127 uint16_t *a = (u_short *)one; 128 uint16_t *b = (u_short *)two; 129 uint16_t diff; 130 131#ifdef m68k 132 /* 133 * The post-increment-pointer form produces the best 134 * machine code for m68k. This was carefully tuned 135 * so it compiles to just 8 short (2-byte) op-codes! 136 */ 137 diff = *a++ - *b++; 138 diff |= *a++ - *b++; 139 diff |= *a++ - *b++; 140#else 141 /* 142 * Most modern CPUs do better with a single expresion. 143 * Note that short-cut evaluation is NOT helpful here, 144 * because it just makes the code longer, not faster! 145 */ 146 diff = (a[0] - b[0]) | (a[1] - b[1]) | (a[2] - b[2]); 147#endif 148 149 return (diff); 150} 151 152#define ETHER_CMP ether_cmp 153 154#ifdef LANCE_REVC_BUG 155/* Make sure this is short-aligned, for ether_cmp(). */ 156static uint16_t bcast_enaddr[3] = { ~0, ~0, ~0 }; 157#endif 158 | |
159int 160lance_config(struct lance_softc *sc, const char* name, int unit) 161{ 162 struct ifnet *ifp; 163 int i, nbuf; 164 165 if (LE_LOCK_INITIALIZED(sc) == 0) 166 return (ENXIO); --- 252 unchanged lines hidden (view full) --- 419} 420 421/* 422 * Pull data off an interface. 423 * Len is length of data, with local net header stripped. 424 * We copy the data into mbufs. When full cluster sized units are present 425 * we copy into clusters. 426 */ | 109int 110lance_config(struct lance_softc *sc, const char* name, int unit) 111{ 112 struct ifnet *ifp; 113 int i, nbuf; 114 115 if (LE_LOCK_INITIALIZED(sc) == 0) 116 return (ENXIO); --- 252 unchanged lines hidden (view full) --- 369} 370 371/* 372 * Pull data off an interface. 373 * Len is length of data, with local net header stripped. 374 * We copy the data into mbufs. When full cluster sized units are present 375 * we copy into clusters. 376 */ |
427static struct mbuf * | 377struct mbuf * |
428lance_get(struct lance_softc *sc, int boff, int totlen) 429{ 430 struct ifnet *ifp = sc->sc_ifp; 431 struct mbuf *m, *m0, *newm; 432 caddr_t newdata; 433 int len; 434 | 378lance_get(struct lance_softc *sc, int boff, int totlen) 379{ 380 struct ifnet *ifp = sc->sc_ifp; 381 struct mbuf *m, *m0, *newm; 382 caddr_t newdata; 383 int len; 384 |
385 if (totlen <= ETHER_HDR_LEN || totlen > LEBLEN - ETHER_CRC_LEN) { 386#ifdef LEDEBUG 387 if_printf(ifp, "invalid packet size %d; dropping\n", totlen); 388#endif 389 return (NULL); 390 } 391 |
|
435 MGETHDR(m0, M_DONTWAIT, MT_DATA); | 392 MGETHDR(m0, M_DONTWAIT, MT_DATA); |
436 if (m0 == 0) 437 return (0); | 393 if (m0 == NULL) 394 return (NULL); |
438 m0->m_pkthdr.rcvif = ifp; 439 m0->m_pkthdr.len = totlen; 440 len = MHLEN; 441 m = m0; 442 443 while (totlen > 0) { 444 if (totlen >= MINCLSIZE) { 445 MCLGET(m, M_DONTWAIT); --- 22 unchanged lines hidden (view full) --- 468 m = m->m_next = newm; 469 } 470 } 471 472 return (m0); 473 474 bad: 475 m_freem(m0); | 395 m0->m_pkthdr.rcvif = ifp; 396 m0->m_pkthdr.len = totlen; 397 len = MHLEN; 398 m = m0; 399 400 while (totlen > 0) { 401 if (totlen >= MINCLSIZE) { 402 MCLGET(m, M_DONTWAIT); --- 22 unchanged lines hidden (view full) --- 425 m = m->m_next = newm; 426 } 427 } 428 429 return (m0); 430 431 bad: 432 m_freem(m0); |
476 return (0); | 433 return (NULL); |
477} 478 | 434} 435 |
479/* 480 * Pass a packet to the higher levels. 481 */ 482void 483lance_read(struct lance_softc *sc, int boff, int len) 484{ 485 struct ifnet *ifp = sc->sc_ifp; 486 struct ether_header *eh; 487 struct mbuf *m; 488 489 LE_LOCK_ASSERT(sc, MA_OWNED); 490 491 if (len <= ETHER_HDR_LEN || len > LEBLEN - ETHER_CRC_LEN) { 492#ifdef LEDEBUG 493 if_printf(ifp, "invalid packet size %d; dropping\n", len); 494#endif 495 ifp->if_ierrors++; 496 return; 497 } 498 499 /* Pull packet off interface. */ 500 m = lance_get(sc, boff, len); 501 if (m == 0) { 502 ifp->if_ierrors++; 503 return; 504 } 505 506 ifp->if_ipackets++; 507 508 eh = mtod(m, struct ether_header *); 509 510#ifdef LANCE_REVC_BUG 511 /* 512 * The old LANCE (Rev. C) chips have a bug which causes 513 * garbage to be inserted in front of the received packet. 514 * The work-around is to ignore packets with an invalid 515 * destination address (garbage will usually not match). 516 * Of course, this precludes multicast support... 517 */ 518 if (ETHER_CMP(eh->ether_dhost, sc->sc_enaddr) && 519 ETHER_CMP(eh->ether_dhost, bcast_enaddr)) { 520 m_freem(m); 521 return; 522 } 523#endif 524 525 /* 526 * Some lance device does not present IFF_SIMPLEX behavior on multicast 527 * packets. Make sure to drop it if it is from ourselves. 528 */ 529 if (!ETHER_CMP(eh->ether_shost, sc->sc_enaddr)) { 530 m_freem(m); 531 return; 532 } 533 534 /* Pass the packet up. */ 535 LE_UNLOCK(sc); 536 (*ifp->if_input)(ifp, m); 537 LE_LOCK(sc); 538} 539 | |
540static void 541lance_watchdog(struct ifnet *ifp) 542{ 543 struct lance_softc *sc = ifp->if_softc; 544 545 LE_LOCK(sc); 546 if_printf(ifp, "device timeout\n"); 547 ++ifp->if_oerrors; --- 149 unchanged lines hidden (view full) --- 697 698 crc = ether_crc32_le(LLADDR((struct sockaddr_dl *) 699 ifma->ifma_addr), ETHER_ADDR_LEN); 700 701 /* Just want the 6 most significant bits. */ 702 crc >>= 26; 703 704 /* Set the corresponding bit in the filter. */ | 436static void 437lance_watchdog(struct ifnet *ifp) 438{ 439 struct lance_softc *sc = ifp->if_softc; 440 441 LE_LOCK(sc); 442 if_printf(ifp, "device timeout\n"); 443 ++ifp->if_oerrors; --- 149 unchanged lines hidden (view full) --- 593 594 crc = ether_crc32_le(LLADDR((struct sockaddr_dl *) 595 ifma->ifma_addr), ETHER_ADDR_LEN); 596 597 /* Just want the 6 most significant bits. */ 598 crc >>= 26; 599 600 /* Set the corresponding bit in the filter. */ |
705 af[crc >> 4] |= LE_HTOLE16(1U << (crc & 0xf)); | 601 af[crc >> 4] |= LE_HTOLE16(1 << (crc & 0xf)); |
706 } 707 IF_ADDR_UNLOCK(ifp); 708} 709 710/* 711 * Routines for accessing the transmit and receive buffers. 712 * The various CPU and adapter configurations supported by this 713 * driver require three different access methods for buffers --- 195 unchanged lines hidden --- | 602 } 603 IF_ADDR_UNLOCK(ifp); 604} 605 606/* 607 * Routines for accessing the transmit and receive buffers. 608 * The various CPU and adapter configurations supported by this 609 * driver require three different access methods for buffers --- 195 unchanged lines hidden --- |