Deleted Added
full compact
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 ---