summaryrefslogtreecommitdiff
path: root/sys/arch/hp300/dev/if_le.c
diff options
context:
space:
mode:
authorTheo de Raadt <deraadt@cvs.openbsd.org>1995-12-14 05:29:32 +0000
committerTheo de Raadt <deraadt@cvs.openbsd.org>1995-12-14 05:29:32 +0000
commit86b4fdd623d3c50d7bfd9427c2c9208454cd0da7 (patch)
tree5d95abcaf58d01703a30c7ab600537d3b8f67989 /sys/arch/hp300/dev/if_le.c
parente2cd6c399798843e13e76f49dc8ee048b51f99f1 (diff)
update from netbsd (verbatim)
Diffstat (limited to 'sys/arch/hp300/dev/if_le.c')
-rw-r--r--sys/arch/hp300/dev/if_le.c1010
1 files changed, 75 insertions, 935 deletions
diff --git a/sys/arch/hp300/dev/if_le.c b/sys/arch/hp300/dev/if_le.c
index e62fcfd5803..c0bb48780da 100644
--- a/sys/arch/hp300/dev/if_le.c
+++ b/sys/arch/hp300/dev/if_le.c
@@ -1,8 +1,12 @@
-/* $NetBSD: if_le.c,v 1.22 1995/08/04 08:08:41 thorpej Exp $ */
+/* $NetBSD: if_le.c,v 1.24 1995/12/10 00:49:33 mycroft Exp $ */
-/*
- * Copyright (c) 1982, 1990 The Regents of the University of California.
- * All rights reserved.
+/*-
+ * Copyright (c) 1995 Charles M. Hannum. All rights reserved.
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell and Rick Macklem.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -32,51 +36,28 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)if_le.c 7.6 (Berkeley) 5/8/91
+ * @(#)if_le.c 8.2 (Berkeley) 11/16/93
*/
-#include "le.h"
-#if NLE > 0
-
#include "bpfilter.h"
-/*
- * AMD 7990 LANCE
- */
#include <sys/param.h>
#include <sys/systm.h>
-#include <sys/kernel.h>
#include <sys/mbuf.h>
-#include <sys/buf.h>
-#include <sys/socket.h>
#include <sys/syslog.h>
-#include <sys/ioctl.h>
-#include <sys/malloc.h>
-#include <sys/errno.h>
+#include <sys/socket.h>
+#include <sys/device.h>
#include <net/if.h>
-#include <net/netisr.h>
-#include <net/route.h>
-#if NBPFILTER > 0
-#include <net/bpf.h>
-#include <net/bpfdesc.h>
-#endif
#ifdef INET
#include <netinet/in.h>
-#include <netinet/in_systm.h>
-#include <netinet/in_var.h>
-#include <netinet/ip.h>
#include <netinet/if_ether.h>
#endif
-#ifdef NS
-#include <netns/ns.h>
-#include <netns/ns_if.h>
-#endif
-
#include <machine/cpu.h>
#include <machine/mtpr.h>
+
#include <hp300/hp300/isr.h>
#ifdef USELEDS
#include <hp300/hp300/led.h>
@@ -84,71 +65,33 @@
#include <hp300/dev/device.h>
#include <hp300/dev/if_lereg.h>
+#include <hp300/dev/if_levar.h>
+#include <dev/ic/am7990reg.h>
+#define LE_NEED_BUF_CONTIG
+#include <dev/ic/am7990var.h>
+#include "le.h"
+struct le_softc le_softc[NLE];
-#define ETHER_MIN_LEN 64
-#define ETHER_MAX_LEN 1518
-#define ETHER_ADDR_LEN 6
-
-
-/* offsets for: ID, REGS, MEM, NVRAM */
-int lestd[] = { 0, 0x4000, 0x8000, 0xC008 };
-
-struct isr le_isr[NLE];
-
-/*
- * Ethernet software status per interface.
- *
- * Each interface is referenced by a network interface structure,
- * arpcom.ac_if, which the routing code uses to locate the interface.
- * This structure contains the output queue for the interface, its address, ...
- */
-struct le_softc {
- struct arpcom sc_arpcom; /* common Ethernet structures */
- struct lereg0 *sc_r0; /* DIO registers */
- struct lereg1 *sc_r1; /* LANCE registers */
- void *sc_mem;
- struct init_block *sc_init;
- struct mds *sc_rd, *sc_td;
- u_char *sc_rbuf, *sc_tbuf;
- int sc_last_rd, sc_last_td;
- int sc_no_td;
-#ifdef LEDEBUG
- int sc_debug;
-#endif
-} le_softc[NLE];
-
-int leintr __P((int));
-int leioctl __P((struct ifnet *, u_long, caddr_t));
-void lestart __P((struct ifnet *));
-void lewatchdog __P((int));
-static inline void lewrcsr __P((/* struct le_softc *, u_short, u_short */));
-static inline u_short lerdcsr __P((/* struct le_softc *, u_short */));
-void leinit __P((struct le_softc *));
-void lememinit __P((struct le_softc *));
-void lereset __P((struct le_softc *));
-void lestop __P((struct le_softc *));
-void letint __P((int));
-void lerint __P((int));
-void leread __P((struct le_softc *, u_char *, int));
-struct mbuf *leget __P((u_char *, int, struct ifnet *));
-#ifdef LEDEBUG
-void recv_print __P((struct le_softc *, int));
-void xmit_print __P((struct le_softc *, int));
-#endif
-void lesetladrf __P((struct arpcom *, u_long *));
+#define LE_SOFTC(unit) &le_softc[unit]
+#define LE_DELAY(x) DELAY(x)
+#define LEINTR_UNIT
-int leattach __P((struct hp_device *));
+int lematch __P((struct hp_device *));
+void leattach __P((struct hp_device *));
+int leintr __P((int));
struct driver ledriver = {
- leattach, "le",
+ lematch, leattach, "le",
};
-static inline void
+/* offsets for: ID, REGS, MEM, NVRAM */
+int lestd[] = { 0, 0x4000, 0x8000, 0xC008 };
+
+integrate void
lewrcsr(sc, port, val)
struct le_softc *sc;
- register u_short port;
- register u_short val;
+ u_int16_t port, val;
{
register struct lereg0 *ler0 = sc->sc_r0;
register struct lereg1 *ler1 = sc->sc_r1;
@@ -161,14 +104,14 @@ lewrcsr(sc, port, val)
} while ((ler0->ler0_status & LE_ACK) == 0);
}
-static inline u_short
+integrate u_int16_t
lerdcsr(sc, port)
struct le_softc *sc;
- register u_short port;
+ u_int16_t port;
{
register struct lereg0 *ler0 = sc->sc_r0;
register struct lereg1 *ler1 = sc->sc_r1;
- register u_short val;
+ u_int16_t val;
do {
ler1->ler1_rap = port;
@@ -179,32 +122,51 @@ lerdcsr(sc, port)
return (val);
}
+int
+lematch(hd)
+ struct hp_device *hd;
+{
+ register struct lereg0 *ler0;
+ struct le_softc *sc = LE_SOFTC(hd->hp_unit);
+
+ ler0 = (struct lereg0 *)(lestd[0] + (int)hd->hp_addr);
+ if (ler0->ler0_id != LEID)
+ return (0);
+
+ hd->hp_ipl = LE_IPL(ler0->ler0_status);
+ sc->sc_hd = hd;
+
+ return (1);
+}
+
/*
* Interface exists: make available by filling in network interface
* record. System will initialize the interface when it is ready
* to accept packets.
*/
-int
+void
leattach(hd)
struct hp_device *hd;
{
register struct lereg0 *ler0;
- struct le_softc *sc = &le_softc[hd->hp_unit];
- struct ifnet *ifp = &sc->sc_arpcom.ac_if;
+ struct le_softc *sc = LE_SOFTC(hd->hp_unit);
char *cp;
int i;
ler0 = sc->sc_r0 = (struct lereg0 *)(lestd[0] + (int)hd->hp_addr);
- if (ler0->ler0_id != LEID)
- return(0);
- sc->sc_r1 = (struct lereg1 *)(lestd[1] + (int)hd->hp_addr);
- sc->sc_mem = (void *)(lestd[2] + (int)hd->hp_addr);
- le_isr[hd->hp_unit].isr_intr = leintr;
- hd->hp_ipl = le_isr[hd->hp_unit].isr_ipl = LE_IPL(ler0->ler0_status);
- le_isr[hd->hp_unit].isr_arg = hd->hp_unit;
ler0->ler0_id = 0xFF;
DELAY(100);
+ /* XXXX kluge for now */
+ sc->sc_dev.dv_unit = hd->hp_unit;
+ sprintf(sc->sc_dev.dv_xname, "%s%d", ledriver.d_name, hd->hp_unit);
+
+ sc->sc_r1 = (struct lereg1 *)(lestd[1] + (int)hd->hp_addr);
+ sc->sc_mem = (void *)(lestd[2] + (int)hd->hp_addr);
+ sc->sc_conf3 = LE_C3_BSWP;
+ sc->sc_addr = 0;
+ sc->sc_memsize = 16384;
+
/*
* Read the ethernet address off the board, one nibble at a time.
*/
@@ -215,843 +177,21 @@ leattach(hd)
sc->sc_arpcom.ac_enaddr[i] |= *++cp & 0xF;
cp++;
}
- printf("le%d: hardware address %s\n", hd->hp_unit,
- ether_sprintf(sc->sc_arpcom.ac_enaddr));
-
- isrlink(&le_isr[hd->hp_unit]);
- ler0->ler0_status = LE_IE;
-
- ifp->if_unit = hd->hp_unit;
- ifp->if_name = "le";
- ifp->if_output = ether_output;
- ifp->if_start = lestart;
- ifp->if_ioctl = leioctl;
- ifp->if_watchdog = lewatchdog;
- ifp->if_flags =
- IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST;
-
- if_attach(ifp);
- ether_ifattach(ifp);
-
-#if NBPFILTER > 0
- bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
-#endif
- return (1);
-}
-
-void
-lereset(sc)
- struct le_softc *sc;
-{
-
- leinit(sc);
-}
-
-void
-lewatchdog(unit)
- int unit;
-{
- struct le_softc *sc = &le_softc[unit];
-
- log(LOG_ERR, "le%d: device timeout\n", unit);
- ++sc->sc_arpcom.ac_if.if_oerrors;
-
- lereset(sc);
-}
-
-#define LANCE_ADDR(sc, a) \
- ((u_long)(a) - (u_long)sc->sc_mem)
-
-/* LANCE initialization block set up. */
-void
-lememinit(sc)
- register struct le_softc *sc;
-{
- struct ifnet *ifp = &sc->sc_arpcom.ac_if;
- int i;
- void *mem;
- u_long a;
-
- /*
- * At this point we assume that the memory allocated to the Lance is
- * quadword aligned. If it isn't then the initialisation is going
- * fail later on.
- */
- mem = sc->sc_mem;
-
- sc->sc_init = mem;
-#if NBPFILTER > 0
- if (ifp->if_flags & IFF_PROMISC)
- sc->sc_init->mode = LE_NORMAL | LE_PROM;
- else
-#endif
- sc->sc_init->mode = LE_NORMAL;
- for (i = 0; i < ETHER_ADDR_LEN; i++)
- sc->sc_init->padr[i] = sc->sc_arpcom.ac_enaddr[i^1];
- lesetladrf(&sc->sc_arpcom, sc->sc_init->ladrf);
- mem += sizeof(struct init_block);
-
- sc->sc_rd = mem;
- a = LANCE_ADDR(sc, mem);
- sc->sc_init->rdra = a;
- sc->sc_init->rlen = ((a >> 16) & 0xff) | (RLEN << 13);
- mem += NRBUF * sizeof(struct mds);
-
- sc->sc_td = mem;
- a = LANCE_ADDR(sc, mem);
- sc->sc_init->tdra = a;
- sc->sc_init->tlen = ((a >> 16) & 0xff) | (TLEN << 13);
- mem += NTBUF * sizeof(struct mds);
-
- /*
- * Set up receive ring descriptors.
- */
- sc->sc_rbuf = mem;
- for (i = 0; i < NRBUF; i++) {
- a = LANCE_ADDR(sc, mem);
- sc->sc_rd[i].addr = a;
- sc->sc_rd[i].flags = ((a >> 16) & 0xff) | LE_OWN;
- sc->sc_rd[i].bcnt = -BUFSIZE;
- sc->sc_rd[i].mcnt = 0;
- mem += BUFSIZE;
- }
-
- /*
- * Set up transmit ring descriptors.
- */
- sc->sc_tbuf = mem;
- for (i = 0; i < NTBUF; i++) {
- a = LANCE_ADDR(sc, mem);
- sc->sc_td[i].addr = a;
- sc->sc_td[i].flags= ((a >> 16) & 0xff);
- sc->sc_td[i].bcnt = 0xf000;
- sc->sc_td[i].mcnt = 0;
- mem += BUFSIZE;
- }
-}
-
-void
-lestop(sc)
- struct le_softc *sc;
-{
-
- lewrcsr(sc, 0, LE_STOP);
-}
-/*
- * Initialization of interface; set up initialization block
- * and transmit/receive descriptor rings.
- */
-void
-leinit(sc)
- register struct le_softc *sc;
-{
- struct ifnet *ifp = &sc->sc_arpcom.ac_if;
- int s;
- register int timo;
- u_long a;
+ sc->sc_copytodesc = copytobuf_contig;
+ sc->sc_copyfromdesc = copyfrombuf_contig;
+ sc->sc_copytobuf = copytobuf_contig;
+ sc->sc_copyfrombuf = copyfrombuf_contig;
+ sc->sc_zerobuf = zerobuf_contig;
- s = splimp();
+ sc->sc_arpcom.ac_if.if_name = ledriver.d_name;
+ leconfig(sc);
- /* Don't want to get in a weird state. */
- lewrcsr(sc, 0, LE_STOP);
- DELAY(100);
-
- sc->sc_last_rd = sc->sc_last_td = sc->sc_no_td = 0;
-
- /* Set up LANCE init block. */
- lememinit(sc);
-
- /* Turn on byte swapping. */
- lewrcsr(sc, 3, LE_BSWP);
-
- /* Give LANCE the physical address of its init block. */
- a = LANCE_ADDR(sc, sc->sc_init);
- lewrcsr(sc, 1, a);
- lewrcsr(sc, 2, (a >> 16) & 0xff);
-
- /* Try to initialize the LANCE. */
- DELAY(100);
- lewrcsr(sc, 0, LE_INIT);
-
- /* Wait for initialization to finish. */
- for (timo = 100000; timo; timo--)
- if (lerdcsr(sc, 0) & LE_IDON)
- break;
-
- if (lerdcsr(sc, 0) & LE_IDON) {
- /* Start the LANCE. */
- lewrcsr(sc, 0, LE_INEA | LE_STRT | LE_IDON);
- ifp->if_flags |= IFF_RUNNING;
- ifp->if_flags &= ~IFF_OACTIVE;
- lestart(ifp);
- } else
- printf("le%d: card failed to initialize\n", ifp->if_unit);
-
- (void) splx(s);
-}
-
-/*
- * Controller interrupt.
- */
-int
-leintr(unit)
- int unit;
-{
- register struct le_softc *sc = &le_softc[unit];
- register u_short isr;
-
- isr = lerdcsr(sc, 0);
-#ifdef LEDEBUG
- if (sc->sc_debug)
- printf("le%d: leintr entering with isr=%04x\n",
- unit, isr);
-#endif
- if ((isr & LE_INTR) == 0)
- return 0;
-
- do {
- lewrcsr(sc, 0,
- isr & (LE_INEA | LE_BABL | LE_MISS | LE_MERR |
- LE_RINT | LE_TINT | LE_IDON));
- if (isr & (LE_BABL | LE_CERR | LE_MISS | LE_MERR)) {
- if (isr & LE_BABL) {
- printf("le%d: BABL\n", unit);
- sc->sc_arpcom.ac_if.if_oerrors++;
- }
-#if 0
- if (isr & LE_CERR) {
- printf("le%d: CERR\n", unit);
- sc->sc_arpcom.ac_if.if_collisions++;
- }
-#endif
- if (isr & LE_MISS) {
-#if 0
- printf("le%d: MISS\n", unit);
-#endif
- sc->sc_arpcom.ac_if.if_ierrors++;
- }
- if (isr & LE_MERR) {
- printf("le%d: MERR\n", unit);
- lereset(sc);
- goto out;
- }
- }
-
- if ((isr & LE_RXON) == 0) {
- printf("le%d: receiver disabled\n", unit);
- sc->sc_arpcom.ac_if.if_ierrors++;
- lereset(sc);
- goto out;
- }
- if ((isr & LE_TXON) == 0) {
- printf("le%d: transmitter disabled\n", unit);
- sc->sc_arpcom.ac_if.if_oerrors++;
- lereset(sc);
- goto out;
- }
-
- if (isr & LE_RINT) {
- /* Reset watchdog timer. */
- sc->sc_arpcom.ac_if.if_timer = 0;
- lerint(unit);
- }
- if (isr & LE_TINT) {
- /* Reset watchdog timer. */
- sc->sc_arpcom.ac_if.if_timer = 0;
- letint(unit);
- }
-
- isr = lerdcsr(sc, 0);
- } while ((isr & LE_INTR) != 0);
-
-#ifdef LEDEBUG
- if (sc->sc_debug)
- printf("le%d: leintr returning with isr=%04x\n",
- unit, isr);
-#endif
-
-out:
- return 1;
-}
-
-#define NEXTTDS \
- if (++tmd == NTBUF) tmd=0, cdm=sc->sc_td; else ++cdm
-
-/*
- * Setup output on interface.
- * Get another datagram to send off of the interface queue, and map it to the
- * interface before starting the output.
- * Called only at splimp or interrupt level.
- */
-void
-lestart(ifp)
- struct ifnet *ifp;
-{
- register struct le_softc *sc = &le_softc[ifp->if_unit];
- register int tmd;
- struct mds *cdm;
- struct mbuf *m0, *m;
- u_char *buffer;
- int len;
-
- if ((sc->sc_arpcom.ac_if.if_flags & (IFF_RUNNING | IFF_OACTIVE)) !=
- IFF_RUNNING)
- return;
-
- tmd = sc->sc_last_td;
- cdm = &sc->sc_td[tmd];
-
- for (;;) {
- if (sc->sc_no_td >= NTBUF) {
- sc->sc_arpcom.ac_if.if_flags |= IFF_OACTIVE;
-#ifdef LEDEBUG
- if (sc->sc_debug)
- printf("no_td = %d, last_td = %d\n", sc->sc_no_td,
- sc->sc_last_td);
-#endif
- break;
- }
-
-#ifdef LEDEBUG
- if (cdm->flags & LE_OWN) {
- sc->sc_arpcom.ac_if.if_flags |= IFF_OACTIVE;
- printf("missing buffer, no_td = %d, last_td = %d\n",
- sc->sc_no_td, sc->sc_last_td);
- }
-#endif
-
- IF_DEQUEUE(&sc->sc_arpcom.ac_if.if_snd, m);
- if (!m)
- break;
-
- ++sc->sc_no_td;
-
- /*
- * Copy the mbuf chain into the transmit buffer.
- */
- buffer = sc->sc_tbuf + (BUFSIZE * sc->sc_last_td);
- len = 0;
- for (m0 = m; m; m = m->m_next) {
- bcopy(mtod(m, caddr_t), buffer, m->m_len);
- buffer += m->m_len;
- len += m->m_len;
- }
-
-#ifdef LEDEBUG
- if (len > ETHER_MAX_LEN)
- printf("packet length %d\n", len);
-#endif
-
-#if NBPFILTER > 0
- if (sc->sc_arpcom.ac_if.if_bpf)
- bpf_mtap(sc->sc_arpcom.ac_if.if_bpf, m0);
-#endif
-
- m_freem(m0);
- len = max(len, ETHER_MIN_LEN);
-
- /*
- * Init transmit registers, and set transmit start flag.
- */
- cdm->bcnt = -len;
- cdm->mcnt = 0;
- cdm->flags |= LE_OWN | LE_STP | LE_ENP;
-
-#ifdef LEDEBUG
- if (sc->sc_debug)
- xmit_print(sc, sc->sc_last_td);
-#endif
-
- lewrcsr(sc, 0, LE_INEA | LE_TDMD);
-
- NEXTTDS;
- }
-
- sc->sc_last_td = tmd;
-}
-
-void
-letint(unit)
- int unit;
-{
- register struct le_softc *sc = &le_softc[unit];
- register int tmd = (sc->sc_last_td - sc->sc_no_td + NTBUF) % NTBUF;
- struct mds *cdm = &sc->sc_td[tmd];
-
-#ifdef USELEDS
- if (inledcontrol == 0)
- ledcontrol(0, 0, LED_LANXMT);
-#endif
-
- if (cdm->flags & LE_OWN) {
- /* Race condition with loop below. */
-#ifdef LEDEBUG
- if (sc->sc_debug)
- printf("le%d: extra tint\n", unit);
-#endif
- return;
- }
-
- sc->sc_arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
-
- do {
- if (sc->sc_no_td <= 0)
- break;
-#ifdef LEDEBUG
- if (sc->sc_debug)
- printf("trans cdm = %x\n", cdm);
-#endif
- sc->sc_arpcom.ac_if.if_opackets++;
- --sc->sc_no_td;
- if (cdm->mcnt & (LE_TBUFF | LE_UFLO | LE_LCOL | LE_LCAR | LE_RTRY)) {
- if (cdm->mcnt & LE_TBUFF)
- printf("le%d: TBUFF\n", unit);
- if ((cdm->mcnt & (LE_TBUFF | LE_UFLO)) == LE_UFLO)
- printf("le%d: UFLO\n", unit);
- if (cdm->mcnt & LE_UFLO) {
- lereset(sc);
- return;
- }
-#if 0
- if (cdm->mcnt & LE_LCOL) {
- printf("le%d: late collision\n", unit);
- sc->sc_arpcom.ac_if.if_collisions++;
- }
- if (cdm->mcnt & LE_LCAR)
- printf("le%d: lost carrier\n", unit);
- if (cdm->mcnt & LE_RTRY) {
- printf("le%d: excessive collisions, tdr %d\n",
- unit, cdm->mcnt & 0x1ff);
- sc->sc_arpcom.ac_if.if_collisions += 16;
- }
-#endif
- } else if (cdm->flags & LE_ONE)
- sc->sc_arpcom.ac_if.if_collisions++;
- else if (cdm->flags & LE_MORE)
- /* Real number is unknown. */
- sc->sc_arpcom.ac_if.if_collisions += 2;
- NEXTTDS;
- } while ((cdm->flags & LE_OWN) == 0);
-
- lestart(&sc->sc_arpcom.ac_if);
-}
-
-#define NEXTRDS \
- if (++rmd == NRBUF) rmd=0, cdm=sc->sc_rd; else ++cdm
-
-/* only called from one place, so may as well integrate */
-void
-lerint(unit)
- int unit;
-{
- register struct le_softc *sc = &le_softc[unit];
- register int rmd = sc->sc_last_rd;
- struct mds *cdm = &sc->sc_rd[rmd];
-
-#ifdef USELEDS
- if (inledcontrol == 0)
- ledcontrol(0, 0, LED_LANRCV);
-#endif
-
- if (cdm->flags & LE_OWN) {
- /* Race condition with loop below. */
-#ifdef LEDEBUG
- if (sc->sc_debug)
- printf("le%d: extra rint\n", unit);
-#endif
- return;
- }
-
- /* Process all buffers with valid data. */
- do {
- if (cdm->flags & (LE_FRAM | LE_OFLO | LE_CRC | LE_RBUFF)) {
- if ((cdm->flags & (LE_FRAM | LE_OFLO | LE_ENP)) == (LE_FRAM | LE_ENP))
- printf("le%d: FRAM\n", unit);
- if ((cdm->flags & (LE_OFLO | LE_ENP)) == LE_OFLO)
- printf("le%d: OFLO\n", unit);
- if ((cdm->flags & (LE_CRC | LE_OFLO | LE_ENP)) == (LE_CRC | LE_ENP))
- printf("le%d: CRC\n", unit);
- if (cdm->flags & LE_RBUFF)
- printf("le%d: RBUFF\n", unit);
- } else if (cdm->flags & (LE_STP | LE_ENP) != (LE_STP | LE_ENP)) {
- do {
- cdm->mcnt = 0;
- cdm->flags |= LE_OWN;
- NEXTRDS;
- } while ((cdm->flags & (LE_OWN | LE_ERR | LE_STP | LE_ENP)) == 0);
- sc->sc_last_rd = rmd;
- printf("le%d: chained buffer\n", unit);
- if ((cdm->flags & (LE_OWN | LE_ERR | LE_STP | LE_ENP)) != LE_ENP) {
- lereset(sc);
- return;
- }
- } else {
-#ifdef LEDEBUG
- if (sc->sc_debug)
- recv_print(sc, sc->sc_last_rd);
-#endif
- leread(sc, sc->sc_rbuf + (BUFSIZE * rmd),
- (int)cdm->mcnt);
- sc->sc_arpcom.ac_if.if_ipackets++;
- }
-
- cdm->mcnt = 0;
- cdm->flags |= LE_OWN;
- NEXTRDS;
-#ifdef LEDEBUG
- if (sc->sc_debug)
- printf("sc->sc_last_rd = %x, cdm = %x\n",
- sc->sc_last_rd, cdm);
-#endif
- } while ((cdm->flags & LE_OWN) == 0);
-
- sc->sc_last_rd = rmd;
-}
-
-/*
- * Pass a packet to the higher levels.
- */
-void
-leread(sc, buf, len)
- register struct le_softc *sc;
- u_char *buf;
- int len;
-{
- struct ifnet *ifp;
- struct mbuf *m;
- struct ether_header *eh;
-
- len -= 4;
- if (len <= 0)
- return;
-
- /* Pull packet off interface. */
- ifp = &sc->sc_arpcom.ac_if;
- m = leget(buf, len, ifp);
- if (m == 0)
- return;
-
- /* We assume that the header fit entirely in one mbuf. */
- eh = mtod(m, struct ether_header *);
-
-#if NBPFILTER > 0
- /*
- * Check if there's a BPF listener on this interface.
- * If so, hand off the raw packet to BPF.
- */
- if (ifp->if_bpf) {
- bpf_mtap(ifp->if_bpf, m);
-
- /*
- * Note that the interface cannot be in promiscuous mode if
- * there are no BPF listeners. And if we are in promiscuous
- * mode, we have to check if this packet is really ours.
- */
- if ((ifp->if_flags & IFF_PROMISC) &&
- (eh->ether_dhost[0] & 1) == 0 && /* !mcast and !bcast */
- bcmp(eh->ether_dhost, sc->sc_arpcom.ac_enaddr,
- sizeof(eh->ether_dhost)) != 0) {
- m_freem(m);
- return;
- }
- }
-#endif
-
- /* We assume that the header fit entirely in one mbuf. */
- m->m_pkthdr.len -= sizeof(*eh);
- m->m_len -= sizeof(*eh);
- m->m_data += sizeof(*eh);
-
- ether_input(ifp, eh, m);
-}
-
-/*
- * Supporting routines
- */
-
-/*
- * Pull data off an interface.
- * Len is length of data, with local net header stripped.
- * We copy the data into mbufs. When full cluster sized units are present
- * we copy into clusters.
- */
-struct mbuf *
-leget(buf, totlen, ifp)
- u_char *buf;
- int totlen;
- struct ifnet *ifp;
-{
- struct mbuf *top, **mp, *m;
- int len;
-
- MGETHDR(m, M_DONTWAIT, MT_DATA);
- if (m == 0)
- return 0;
- m->m_pkthdr.rcvif = ifp;
- m->m_pkthdr.len = totlen;
- len = MHLEN;
- top = 0;
- mp = &top;
-
- while (totlen > 0) {
- if (top) {
- MGET(m, M_DONTWAIT, MT_DATA);
- if (m == 0) {
- m_freem(top);
- return 0;
- }
- len = MLEN;
- }
- if (totlen >= MINCLSIZE) {
- MCLGET(m, M_DONTWAIT);
- if (m->m_flags & M_EXT)
- len = MCLBYTES;
- }
- m->m_len = len = min(totlen, len);
- bcopy((caddr_t)buf, mtod(m, caddr_t), len);
- buf += len;
- totlen -= len;
- *mp = m;
- mp = &m->m_next;
- }
-
- return top;
-}
-
-/*
- * Process an ioctl request.
- */
-int
-leioctl(ifp, cmd, data)
- register struct ifnet *ifp;
- u_long cmd;
- caddr_t data;
-{
- struct le_softc *sc = &le_softc[ifp->if_unit];
- struct ifaddr *ifa = (struct ifaddr *)data;
- struct ifreq *ifr = (struct ifreq *)data;
- int s, error = 0;
-
- s = splimp();
-
- switch (cmd) {
-
- case SIOCSIFADDR:
- ifp->if_flags |= IFF_UP;
-
- switch (ifa->ifa_addr->sa_family) {
-#ifdef INET
- case AF_INET:
- leinit(sc);
- arp_ifinit(&sc->sc_arpcom, ifa);
- break;
-#endif
-#ifdef NS
- /* XXX - This code is probably wrong. */
- case AF_NS:
- {
- register struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
-
- if (ns_nullhost(*ina))
- ina->x_host =
- *(union ns_host *)(sc->sc_arpcom.ac_enaddr);
- else
- bcopy(ina->x_host.c_host,
- sc->sc_arpcom.ac_enaddr,
- sizeof(sc->sc_arpcom.ac_enaddr));
- /* Set new address. */
- leinit(sc);
- break;
- }
-#endif
- default:
- leinit(sc);
- break;
- }
- break;
-
- case SIOCSIFFLAGS:
- /*
- * If interface is marked down and it is running, then stop it
- */
- if ((ifp->if_flags & IFF_UP) == 0 &&
- (ifp->if_flags & IFF_RUNNING) != 0) {
- /*
- * If interface is marked down and it is running, then
- * stop it.
- */
- lestop(sc);
- ifp->if_flags &= ~IFF_RUNNING;
- } else if ((ifp->if_flags & IFF_UP) != 0 &&
- (ifp->if_flags & IFF_RUNNING) == 0) {
- /*
- * If interface is marked up and it is stopped, then
- * start it.
- */
- leinit(sc);
- } else {
- /*
- * Reset the interface to pick up changes in any other
- * flags that affect hardware registers.
- */
- /*lestop(sc);*/
- leinit(sc);
- }
-#ifdef LEDEBUG
- if (ifp->if_flags & IFF_DEBUG)
- sc->sc_debug = 1;
- else
- sc->sc_debug = 0;
-#endif
- break;
-
- case SIOCADDMULTI:
- case SIOCDELMULTI:
- error = (cmd == SIOCADDMULTI) ?
- ether_addmulti(ifr, &sc->sc_arpcom):
- ether_delmulti(ifr, &sc->sc_arpcom);
-
- if (error == ENETRESET) {
- /*
- * Multicast list has changed; set the hardware filter
- * accordingly.
- */
- leinit(sc);
- error = 0;
- }
- break;
-
- default:
- error = EINVAL;
- }
- (void) splx(s);
- return error;
-}
-
-#ifdef LEDEBUG
-void
-recv_print(sc, no)
- struct le_softc *sc;
- int no;
-{
- struct mds *rmd;
- int i, printed = 0;
- u_short len;
-
- rmd = &sc->sc_rd[no];
- len = rmd->mcnt;
- printf("%s: receive buffer %d, len = %d\n", sc->sc_dev.dv_xname, no,
- len);
- printf("%s: status %x\n", sc->sc_dev.dv_xname, lerdcsr(sc, 0));
- for (i = 0; i < len; i++) {
- if (!printed) {
- printed = 1;
- printf("%s: data: ", sc->sc_dev.dv_xname);
- }
- printf("%x ", *(sc->sc_rbuf + (BUFSIZE*no) + i));
- }
- if (printed)
- printf("\n");
-}
-
-void
-xmit_print(sc, no)
- struct le_softc *sc;
- int no;
-{
- struct mds *rmd;
- int i, printed=0;
- u_short len;
-
- rmd = &sc->sc_td[no];
- len = -rmd->bcnt;
- printf("%s: transmit buffer %d, len = %d\n", sc->sc_dev.dv_xname, no,
- len);
- printf("%s: status %x\n", sc->sc_dev.dv_xname, lerdcsr(sc, 0));
- printf("%s: addr %x, flags %x, bcnt %x, mcnt %x\n",
- sc->sc_dev.dv_xname, rmd->addr, rmd->flags, rmd->bcnt, rmd->mcnt);
- for (i = 0; i < len; i++) {
- if (!printed) {
- printed = 1;
- printf("%s: data: ", sc->sc_dev.dv_xname);
- }
- printf("%x ", *(sc->sc_tbuf + (BUFSIZE*no) + i));
- }
- if (printed)
- printf("\n");
-}
-#endif /* LEDEBUG */
-
-/*
- * Set up the logical address filter.
- */
-void
-lesetladrf(ac, af)
- struct arpcom *ac;
- u_long *af;
-{
- struct ifnet *ifp = &ac->ac_if;
- struct ether_multi *enm;
- register u_char *cp, c;
- register u_long crc;
- register int i, len;
- struct ether_multistep step;
-
- /*
- * Set up multicast address filter by passing all multicast addresses
- * through a crc generator, and then using the high order 6 bits as an
- * index into the 64 bit logical address filter. The high order bit
- * selects the word, while the rest of the bits select the bit within
- * the word.
- */
-
- if (ifp->if_flags & IFF_PROMISC) {
- ifp->if_flags |= IFF_ALLMULTI;
- af[0] = af[1] = 0xffffffff;
- return;
- }
-
- af[0] = af[1] = 0;
- ETHER_FIRST_MULTI(step, ac, enm);
- while (enm != NULL) {
- if (bcmp(enm->enm_addrlo, enm->enm_addrhi,
- sizeof(enm->enm_addrlo)) != 0) {
- /*
- * We must listen to a range of multicast addresses.
- * For now, just accept all multicasts, rather than
- * trying to set only those filter bits needed to match
- * the range. (At this time, the only use of address
- * ranges is for IP multicast routing, for which the
- * range is big enough to require all bits set.)
- */
- ifp->if_flags |= IFF_ALLMULTI;
- af[0] = af[1] = 0xffffffff;
- return;
- }
-
- cp = enm->enm_addrlo;
- crc = 0xffffffff;
- for (len = sizeof(enm->enm_addrlo); --len >= 0;) {
- c = *cp++;
- for (i = 8; --i >= 0;) {
- if ((crc & 0x01) ^ (c & 0x01)) {
- crc >>= 1;
- crc ^= 0x6db88320 | 0x80000000;
- } else
- crc >>= 1;
- c >>= 1;
- }
- }
- /* Just want the 6 most significant bits. */
- crc >>= 26;
-
- /* Turn on the corresponding bit in the filter. */
- af[crc >> 5] |= 1 << ((crc & 0x1f) ^ 16);
-
- ETHER_NEXT_MULTI(step, enm);
- }
- ifp->if_flags &= ~IFF_ALLMULTI;
+ sc->sc_isr.isr_intr = leintr;
+ sc->sc_isr.isr_arg = hd->hp_unit;
+ sc->sc_isr.isr_ipl = hd->hp_ipl;
+ isrlink(&sc->sc_isr);
+ ler0->ler0_status = LE_IE;
}
-#endif /* NLE > 0 */
+#include <dev/ic/am7990.c>