diff options
author | Theo de Raadt <deraadt@cvs.openbsd.org> | 1995-12-15 02:35:11 +0000 |
---|---|---|
committer | Theo de Raadt <deraadt@cvs.openbsd.org> | 1995-12-15 02:35:11 +0000 |
commit | 6a986d2671c3b7e72a320f7a9f2c48e7ca56c9ff (patch) | |
tree | 5b6b9f4eaf15ebfcea3e7f210cc9cf88fc7fed61 | |
parent | 4e5fa6064091f4f4e4bc82f8f935199314ab15f2 (diff) |
from netbsd; mi lance driver
-rw-r--r-- | sys/dev/ic/am7990.c | 232 | ||||
-rw-r--r-- | sys/dev/ic/am7990var.h | 31 |
2 files changed, 138 insertions, 125 deletions
diff --git a/sys/dev/ic/am7990.c b/sys/dev/ic/am7990.c index d1a8ef3d68d..8bd6769e09c 100644 --- a/sys/dev/ic/am7990.c +++ b/sys/dev/ic/am7990.c @@ -1,4 +1,4 @@ -/* $NetBSD: am7990.c,v 1.3 1995/07/24 04:34:51 mycroft Exp $ */ +/* $NetBSD: am7990.c,v 1.8 1995/12/11 19:48:53 mycroft Exp $ */ /*- * Copyright (c) 1995 Charles M. Hannum. All rights reserved. @@ -69,11 +69,12 @@ void recv_print __P((struct le_softc *, int)); void xmit_print __P((struct le_softc *, int)); #endif +#define ifp (&sc->sc_arpcom.ac_if) + void leconfig(sc) struct le_softc *sc; { - struct ifnet *ifp = &sc->sc_arpcom.ac_if; int mem; /* Make sure the chip is stopped. */ @@ -86,6 +87,9 @@ leconfig(sc) ifp->if_watchdog = lewatchdog; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST; +#ifdef LANCE_REVC_BUG + ifp->if_flags &= ~IFF_MULTICAST; +#endif /* Attach the interface. */ if_attach(ifp); @@ -116,9 +120,9 @@ leconfig(sc) panic("leconfig: weird memory size"); } - printf(": address %s, %d receive buffers, %d transmit buffers\n", + printf(": address %s\n%s: %d receive buffers, %d transmit buffers\n", ether_sprintf(sc->sc_arpcom.ac_enaddr), - sc->sc_nrbuf, sc->sc_ntbuf); + sc->sc_dev.dv_xname, sc->sc_nrbuf, sc->sc_ntbuf); mem = 0; sc->sc_initaddr = mem; @@ -150,12 +154,12 @@ lereset(sc) void lewatchdog(unit) - short unit; + int unit; { struct le_softc *sc = LE_SOFTC(unit); log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname); - ++sc->sc_arpcom.ac_if.if_oerrors; + ++ifp->if_oerrors; lereset(sc); } @@ -167,7 +171,6 @@ void lememinit(sc) register struct le_softc *sc; { - struct ifnet *ifp = &sc->sc_arpcom.ac_if; u_long a; int bix; struct leinit init; @@ -246,7 +249,6 @@ void leinit(sc) register struct le_softc *sc; { - struct ifnet *ifp = &sc->sc_arpcom.ac_if; register int timo; u_long a; @@ -333,7 +335,7 @@ leget(sc, boff, totlen) MGETHDR(m, M_DONTWAIT, MT_DATA); if (m == 0) return (0); - m->m_pkthdr.rcvif = &sc->sc_arpcom.ac_if; + m->m_pkthdr.rcvif = ifp; m->m_pkthdr.len = totlen; pad = ALIGN(sizeof(struct ether_header)) - sizeof(struct ether_header); m->m_data += pad; @@ -374,14 +376,15 @@ leread(sc, boff, len) register struct le_softc *sc; int boff, len; { - struct ifnet *ifp = &sc->sc_arpcom.ac_if; struct mbuf *m; struct ether_header *eh; if (len <= sizeof(struct ether_header) || len > ETHERMTU + sizeof(struct ether_header)) { +#ifdef LEDEBUG printf("%s: invalid packet size %d; dropping\n", sc->sc_dev.dv_xname, len); +#endif ifp->if_ierrors++; return; } @@ -406,6 +409,7 @@ leread(sc, boff, len) if (ifp->if_bpf) { bpf_mtap(ifp->if_bpf, m); +#ifndef LANCE_REVC_BUG /* * Note that the interface cannot be in promiscuous mode if * there are no BPF listeners. And if we are in promiscuous @@ -418,6 +422,17 @@ leread(sc, boff, len) m_freem(m); return; } +#endif + } +#endif + +#ifdef LANCE_REVC_BUG + if (bcmp(eh->ether_dhost, sc->sc_arpcom.ac_enaddr, + sizeof(eh->ether_dhost)) != 0 && + bcmp(eh->ether_dhost, etherbroadcastaddr, + sizeof(eh->ether_dhost)) != 0) { + m_freem(m); + return; } #endif @@ -446,6 +461,7 @@ lerint(sc) if (rmd.rmd1_bits & LE_R1_ERR) { if (rmd.rmd1_bits & LE_R1_ENP) { +#ifdef LEDEBUG if ((rmd.rmd1_bits & LE_R1_OFLO) == 0) { if (rmd.rmd1_bits & LE_R1_FRAM) printf("%s: framing error\n", @@ -454,6 +470,7 @@ lerint(sc) printf("%s: crc mismatch\n", sc->sc_dev.dv_xname); } +#endif } else { if (rmd.rmd1_bits & LE_R1_OFLO) printf("%s: overflow\n", @@ -462,10 +479,12 @@ lerint(sc) if (rmd.rmd1_bits & LE_R1_BUFF) printf("%s: receive buffer error\n", sc->sc_dev.dv_xname); + ifp->if_ierrors++; } else if (rmd.rmd1_bits & (LE_R1_STP | LE_R1_ENP) != (LE_R1_STP | LE_R1_ENP)) { printf("%s: dropping chained buffer\n", sc->sc_dev.dv_xname); + ifp->if_ierrors++; } else { #ifdef LEDEBUG if (sc->sc_debug) @@ -496,7 +515,6 @@ integrate void letint(sc) register struct le_softc *sc; { - register struct ifnet *ifp = &sc->sc_arpcom.ac_if; register int bix; struct letmd tmd; @@ -593,17 +611,23 @@ leintr(arg) LE_C0_RINT | LE_C0_TINT | LE_C0_IDON)); if (isr & LE_C0_ERR) { if (isr & LE_C0_BABL) { +#ifdef LEDEBUG printf("%s: babble\n", sc->sc_dev.dv_xname); - sc->sc_arpcom.ac_if.if_oerrors++; +#endif + ifp->if_oerrors++; } #if 0 if (isr & LE_C0_CERR) { printf("%s: collision error\n", sc->sc_dev.dv_xname); - sc->sc_arpcom.ac_if.if_collisions++; + ifp->if_collisions++; } #endif - if (isr & LE_C0_MISS) - sc->sc_arpcom.ac_if.if_ierrors++; + if (isr & LE_C0_MISS) { +#ifdef LEDEBUG + printf("%s: missed packet\n", sc->sc_dev.dv_xname); +#endif + ifp->if_ierrors++; + } if (isr & LE_C0_MERR) { printf("%s: memory error\n", sc->sc_dev.dv_xname); lereset(sc); @@ -613,13 +637,13 @@ leintr(arg) if ((isr & LE_C0_RXON) == 0) { printf("%s: receiver disabled\n", sc->sc_dev.dv_xname); - sc->sc_arpcom.ac_if.if_ierrors++; + ifp->if_ierrors++; lereset(sc); return (1); } if ((isr & LE_C0_TXON) == 0) { printf("%s: transmitter disabled\n", sc->sc_dev.dv_xname); - sc->sc_arpcom.ac_if.if_oerrors++; + ifp->if_oerrors++; lereset(sc); return (1); } @@ -632,6 +656,8 @@ leintr(arg) return (1); } +#undef ifp + /* * Setup output on interface. * Get another datagram to send off of the interface queue, and map it to the @@ -960,49 +986,27 @@ allmulti: } -#if 0 /* USE OF THE FOLLOWING IS MACHINE-SPECIFIC */ /* - * Routines for accessing the transmit and receive buffers. Unfortunately, - * CPU addressing of these buffers is done in one of 3 ways: - * - contiguous (for the 3max and turbochannel option card) - * - gap2, which means shorts (2 bytes) interspersed with short (2 byte) - * spaces (for the pmax) - * - gap16, which means 16bytes interspersed with 16byte spaces - * for buffers which must begin on a 32byte boundary (for 3min and maxine) - * The buffer offset is the logical byte offset, assuming contiguous storage. + * Routines for accessing the transmit and receive buffers. + * The various CPU and adapter configurations supported by this + * driver require three different access methods for buffers + * and descriptors: + * (1) contig (contiguous data; no padding), + * (2) gap2 (two bytes of data followed by two bytes of padding), + * (3) gap16 (16 bytes of data followed by 16 bytes of padding). */ -void -copytodesc_contig(sc, from, boff, len) - struct le_softc *sc; - caddr_t from; - int boff, len; -{ - volatile caddr_t buf = sc->sc_mem; - /* - * Just call bcopy() to do the work. - */ - bcopy(from, buf + boff, len); -} - -void -copyfromdesc_contig(sc, to, boff, len) - struct le_softc *sc; - caddr_t to; - int boff, len; -{ - volatile caddr_t buf = sc->sc_mem; - - /* - * Just call bcopy() to do the work. - */ - bcopy(buf + boff, to, len); -} +#ifdef LE_NEED_BUF_CONTIG +/* + * contig: contiguous data with no padding. + * + * Buffers may have any alignment. + */ -void +integrate void copytobuf_contig(sc, from, boff, len) struct le_softc *sc; - caddr_t from; + void *from; int boff, len; { volatile caddr_t buf = sc->sc_mem; @@ -1013,10 +1017,10 @@ copytobuf_contig(sc, from, boff, len) bcopy(from, buf + boff, len); } -void +integrate void copyfrombuf_contig(sc, to, boff, len) struct le_softc *sc; - caddr_t to; + void *to; int boff, len; { volatile caddr_t buf = sc->sc_mem; @@ -1027,7 +1031,7 @@ copyfrombuf_contig(sc, to, boff, len) bcopy(buf + boff, to, len); } -void +integrate void zerobuf_contig(sc, boff, len) struct le_softc *sc; int boff, len; @@ -1039,123 +1043,116 @@ zerobuf_contig(sc, boff, len) */ bzero(buf + boff, len); } +#endif /* LE_NEED_BUF_CONTIG */ +#ifdef LE_NEED_BUF_GAP2 /* - * For the pmax the buffer consists of shorts (2 bytes) interspersed with - * short (2 byte) spaces and must be accessed with halfword load/stores. - * (don't worry about doing an extra byte) + * gap2: two bytes of data followed by two bytes of pad. + * + * Buffers must be 4-byte aligned. The code doesn't worry about + * doing an extra byte. */ -void -copytobuf_gap2(sc, from, boff, len) + +integrate void +copytobuf_gap2(sc, fromv, boff, len) struct le_softc *sc; - register caddr_t from; + void *fromv; int boff; register int len; { volatile caddr_t buf = sc->sc_mem; - register volatile u_short *bptr; + register caddr_t from = fromv; + register volatile u_int16_t *bptr; register int xfer; if (boff & 0x1) { /* handle unaligned first byte */ - bptr = ((volatile u_short *)buf) + (boff - 1); + bptr = ((volatile u_int16_t *)buf) + (boff - 1); *bptr = (*from++ << 8) | (*bptr & 0xff); bptr += 2; len--; } else - bptr = ((volatile u_short *)buf) + boff; - if ((unsigned)from & 0x1) { - while (len > 1) { - *bptr = (from[1] << 8) | (from[0] & 0xff); - bptr += 2; - from += 2; - len -= 2; - } - } else { - /* optimize for aligned transfers */ - xfer = (int)((unsigned)len & ~0x1); - CopyToBuffer((u_short *)from, bptr, xfer); - bptr += xfer; - from += xfer; - len -= xfer; + bptr = ((volatile u_int16_t *)buf) + boff; + while (len > 1) { + *bptr = (from[1] << 8) | (from[0] & 0xff); + bptr += 2; + from += 2; + len -= 2; } if (len == 1) - *bptr = (u_short)*from; + *bptr = (u_int16_t)*from; } -void -copyfrombuf_gap2(sc, to, boff, len) +integrate void +copyfrombuf_gap2(sc, tov, boff, len) struct le_softc *sc; - register caddr_t to; + void *tov; int boff, len; { volatile caddr_t buf = sc->sc_mem; - register volatile u_short *bptr; - register u_short tmp; + register caddr_t to = tov; + register volatile u_int16_t *bptr; + register u_int16_t tmp; register int xfer; if (boff & 0x1) { /* handle unaligned first byte */ - bptr = ((volatile u_short *)buf) + (boff - 1); + bptr = ((volatile u_int16_t *)buf) + (boff - 1); *to++ = (*bptr >> 8) & 0xff; bptr += 2; len--; } else - bptr = ((volatile u_short *)buf) + boff; - if ((unsigned)to & 0x1) { - while (len > 1) { - tmp = *bptr; - *to++ = tmp & 0xff; - *to++ = (tmp >> 8) & 0xff; - bptr += 2; - len -= 2; - } - } else { - /* optimize for aligned transfers */ - xfer = (int)((unsigned)len & ~0x1); - CopyFromBuffer(bptr, to, xfer); - bptr += xfer; - to += xfer; - len -= xfer; + bptr = ((volatile u_int16_t *)buf) + boff; + while (len > 1) { + tmp = *bptr; + *to++ = tmp & 0xff; + *to++ = (tmp >> 8) & 0xff; + bptr += 2; + len -= 2; } if (len == 1) *to = *bptr & 0xff; } -void +integrate void zerobuf_gap2(sc, boff, len) struct le_softc *sc; int boff, len; { volatile caddr_t buf = sc->sc_mem; - register volatile u_short *bptr; + register volatile u_int16_t *bptr; if ((unsigned)boff & 0x1) { - bptr = ((volatile u_short *)buf) + (boff - 1); + bptr = ((volatile u_int16_t *)buf) + (boff - 1); *bptr &= 0xff; bptr += 2; len--; } else - bptr = ((volatile u_short *)buf) + boff; + bptr = ((volatile u_int16_t *)buf) + boff; while (len > 0) { *bptr = 0; bptr += 2; len -= 2; } } +#endif /* LE_NEED_BUF_GAP2 */ +#ifdef LE_NEED_BUF_GAP16 /* - * For the 3min and maxine, the buffers are in main memory filled in with - * 16byte blocks interspersed with 16byte spaces. + * gap16: 16 bytes of data followed by 16 bytes of pad. + * + * Buffers must be 32-byte aligned. */ -void -copytobuf_gap16(sc, from, boff, len) + +integrate void +copytobuf_gap16(sc, fromv, boff, len) struct le_softc *sc; - register caddr_t from; + void *fromv; int boff; register int len; { volatile caddr_t buf = sc->sc_mem; + register caddr_t from = fromv; register caddr_t bptr; register int xfer; @@ -1172,13 +1169,14 @@ copytobuf_gap16(sc, from, boff, len) } } -void -copyfrombuf_gap16(sc, to, boff, len) +integrate void +copyfrombuf_gap16(sc, tov, boff, len) struct le_softc *sc; - register caddr_t to; + void *tov; int boff, len; { volatile caddr_t buf = sc->sc_mem; + register caddr_t to = tov; register caddr_t bptr; register int xfer; @@ -1195,7 +1193,7 @@ copyfrombuf_gap16(sc, to, boff, len) } } -void +integrate void zerobuf_gap16(sc, boff, len) struct le_softc *sc; int boff, len; @@ -1215,4 +1213,4 @@ zerobuf_gap16(sc, boff, len) xfer = min(len, 16); } } -#endif +#endif /* LE_NEED_BUF_GAP16 */ diff --git a/sys/dev/ic/am7990var.h b/sys/dev/ic/am7990var.h index b1f86584a42..f2fc2a23773 100644 --- a/sys/dev/ic/am7990var.h +++ b/sys/dev/ic/am7990var.h @@ -1,4 +1,4 @@ -/* $NetBSD: am7990var.h,v 1.1 1995/06/28 02:24:56 cgd Exp $ */ +/* $NetBSD: am7990var.h,v 1.3 1995/12/11 19:48:58 mycroft Exp $ */ /* * Copyright (c) 1995 Charles M. Hannum. All rights reserved. @@ -43,7 +43,7 @@ void lereset __P((struct le_softc *)); void lesetladrf __P((struct arpcom *, u_int16_t *)); void lestart __P((struct ifnet *)); void lestop __P((struct le_softc *)); -void lewatchdog __P((/* short */)); +void lewatchdog __P((int)); integrate u_int16_t lerdcsr __P((/* struct le_softc *, u_int16_t */)); integrate void lewrcsr __P((/* struct le_softc *, u_int16_t, u_int16_t */)); @@ -55,9 +55,24 @@ integrate int leput __P((struct le_softc *, int, struct mbuf *)); integrate struct mbuf *leget __P((struct le_softc *, int, int)); integrate void leread __P((struct le_softc *, int, int)); -void copytodesc_contig(), copyfromdesc_contig(); -void copytobuf_contig(), copyfrombuf_contig(), zerobuf_contig(); -#ifdef 0 -void copytobuf_gap2(), copyfrombuf_gap2(), zerobuf_gap2(); -void copytobuf_gap16(), copyfrombuf_gap16(), zerobuf_gap16(); -#endif +/* + * The following functions are only useful on certain cpu/bus + * combinations. They should be written in assembly language for + * maximum efficiency, but machine-independent versions are provided + * for drivers that have not yet been optimized. + */ +#ifdef LE_NEED_BUF_CONTIG +integrate void copytobuf_contig __P((struct le_softc *, void *, int, int)); +integrate void copyfrombuf_contig __P((struct le_softc *, void *, int, int)); +integrate void zerobuf_contig __P((struct le_softc *, int, int)); +#endif /* LE_NEED_BUF_CONTIG */ +#ifdef LE_NEED_BUF_GAP2 +integrate void copytobuf_gap2 __P((struct le_softc *, void *, int, int)); +integrate void copyfrombuf_gap2 __P((struct le_softc *, void *, int, int)); +integrate void zerobuf_gap2 __P((struct le_softc *, int, int)); +#endif /* LE_NEED_BUF_GAP2 */ +#ifdef LE_NEED_BUF_GAP16 +integrate void copytobuf_gap16 __P((struct le_softc *, void *, int, int)); +integrate void copyfrombuf_gap16 __P((struct le_softc *, void *, int, int)); +integrate void zerobuf_gap16 __P((struct le_softc *, int, int)); +#endif /* LE_NEED_BUF_GAP16 */ |