155139Storek /*-
263322Sbostic * Copyright (c) 1982, 1992, 1993
363322Sbostic * The Regents of the University of California. All rights reserved.
455139Storek *
555139Storek * %sccs.include.redist.c%
655139Storek *
7*64777Storek * @(#)if_le.c 8.2 (Berkeley) 10/30/93
855139Storek *
9*64777Storek * from: $Header: if_le.c,v 1.25 93/10/31 04:47:50 leres Locked $
1055139Storek */
1155139Storek
1255139Storek #include "bpfilter.h"
1355139Storek
1455139Storek /*
1555139Storek * AMD 7990 LANCE
1655139Storek */
1756540Sbostic #include <sys/param.h>
1856540Sbostic #include <sys/device.h>
1956540Sbostic #include <sys/systm.h>
2056540Sbostic #include <sys/kernel.h>
2156540Sbostic #include <sys/mbuf.h>
2256540Sbostic #include <sys/buf.h>
2356540Sbostic #include <sys/socket.h>
2456540Sbostic #include <sys/syslog.h>
2556540Sbostic #include <sys/ioctl.h>
2656540Sbostic #include <sys/malloc.h>
2756540Sbostic #include <sys/errno.h>
2855139Storek
2956540Sbostic #include <net/if.h>
3056540Sbostic #include <net/netisr.h>
3156540Sbostic #include <net/route.h>
3255139Storek #if NBPFILTER > 0
3356540Sbostic #include <sys/select.h>
3456540Sbostic #include <net/bpf.h>
3556540Sbostic #include <net/bpfdesc.h>
3655139Storek #endif
3755139Storek
3855139Storek #ifdef INET
3956540Sbostic #include <netinet/in.h>
4056540Sbostic #include <netinet/in_systm.h>
4156540Sbostic #include <netinet/in_var.h>
4256540Sbostic #include <netinet/ip.h>
4356540Sbostic #include <netinet/if_ether.h>
4455139Storek #endif
4555139Storek
4655139Storek #ifdef NS
4756540Sbostic #include <netns/ns.h>
4856540Sbostic #include <netns/ns_if.h>
4955139Storek #endif
5055139Storek
5155139Storek #ifdef APPLETALK
5256540Sbostic #include <netddp/atalk.h>
5355139Storek #endif
5455139Storek
5556540Sbostic #include <machine/autoconf.h>
5656540Sbostic #include <machine/cpu.h>
5756540Sbostic #include <machine/pmap.h>
5855139Storek
5956540Sbostic #include <sparc/sbus/if_lereg.h>
6056540Sbostic #include <sparc/sbus/sbusvar.h>
6155139Storek
6255139Storek /* DVMA address to LANCE address -- the Sbus/MMU will resupply the 0xff */
6355139Storek #define LANCE_ADDR(x) ((int)(x) & ~0xff000000)
6455139Storek
6555139Storek int ledebug = 0; /* console error messages */
6655139Storek
6755139Storek #ifdef PACKETSTATS
6855139Storek long lexpacketsizes[LEMTU+1];
6955139Storek long lerpacketsizes[LEMTU+1];
7055139Storek #endif
7155139Storek
7255139Storek /* Per interface statistics */
7355139Storek /* XXX this should go in something like if_levar.h */
7455139Storek struct lestats {
7555139Storek long lexints; /* transmitter interrupts */
7655139Storek long lerints; /* receiver interrupts */
7755139Storek long lerbufs; /* total buffers received during interrupts */
7855139Storek long lerhits; /* times current rbuf was full */
7955139Storek long lerscans; /* rbufs scanned before finding first full */
8055139Storek };
8155139Storek
8255139Storek /*
8355139Storek * Ethernet software status per interface.
8455139Storek *
8555139Storek * Each interface is referenced by a network interface structure,
8655139Storek * le_if, which the routing code uses to locate the interface.
8755139Storek * This structure contains the output queue for the interface, its address, ...
8855139Storek */
8955139Storek struct le_softc {
9055139Storek struct device sc_dev; /* base device */
9155139Storek struct sbusdev sc_sd; /* sbus device */
9255139Storek struct intrhand sc_ih; /* interrupt vectoring */
9359215Storek struct evcnt sc_intrcnt; /* # of interrupts, per le */
9459215Storek struct evcnt sc_errcnt; /* # of errors, per le */
9555139Storek
9655139Storek struct arpcom sc_ac; /* common Ethernet structures */
9755139Storek #define sc_if sc_ac.ac_if /* network-visible interface */
9855139Storek #define sc_addr sc_ac.ac_enaddr /* hardware Ethernet address */
9955139Storek volatile struct lereg1 *sc_r1; /* LANCE registers */
10055139Storek volatile struct lereg2 *sc_r2; /* dual-port RAM */
10155139Storek int sc_rmd; /* predicted next rmd to process */
10255139Storek int sc_runt;
10355139Storek int sc_jab;
10455139Storek int sc_merr;
10555139Storek int sc_babl;
10655139Storek int sc_cerr;
10755139Storek int sc_miss;
10855139Storek int sc_xint;
10955139Storek int sc_xown;
11055139Storek int sc_uflo;
11155139Storek int sc_rxlen;
11255139Storek int sc_rxoff;
11355139Storek int sc_txoff;
11455139Storek int sc_busy;
11555139Storek short sc_iflags;
11655139Storek struct lestats sc_lestats; /* per interface statistics */
11755139Storek #if NBPFILTER > 0
11855139Storek caddr_t sc_bpf;
11955139Storek #endif
12055139Storek };
12155139Storek
12255139Storek
12355139Storek /* autoconfiguration driver */
12455139Storek void leattach(struct device *, struct device *, void *);
12555139Storek struct cfdriver lecd =
12655139Storek { NULL, "le", matchbyname, leattach, DV_IFNET, sizeof(struct le_softc) };
12755139Storek
12855139Storek /* Forwards */
12955139Storek void leattach(struct device *, struct device *, void *);
13055139Storek void lesetladrf(struct le_softc *);
13155139Storek void lereset(struct device *);
13255139Storek int leinit(int);
13355139Storek int lestart(struct ifnet *);
13455139Storek int leintr(void *);
13555139Storek void lexint(struct le_softc *);
13655139Storek void lerint(struct le_softc *);
13755139Storek void leread(struct le_softc *, char *, int);
13855139Storek int leput(char *, struct mbuf *);
13955139Storek struct mbuf *leget(char *, int, int, struct ifnet *);
14055139Storek int leioctl(struct ifnet *, int, caddr_t);
14155139Storek void leerror(struct le_softc *, int);
14255139Storek void lererror(struct le_softc *, char *);
14355139Storek void lexerror(struct le_softc *);
14455139Storek
14555139Storek /*
14655139Storek * Interface exists: make available by filling in network interface
14755139Storek * record. System will initialize the interface when it is ready
14855139Storek * to accept packets.
14955139Storek */
15055139Storek void
leattach(parent,self,args)15155139Storek leattach(parent, self, args)
15255139Storek struct device *parent;
15355139Storek struct device *self;
15455139Storek void *args;
15555139Storek {
15655139Storek register struct le_softc *sc = (struct le_softc *)self;
15755139Storek register struct sbus_attach_args *sa = args;
15855139Storek register volatile struct lereg2 *ler2;
15955139Storek struct ifnet *ifp = &sc->sc_if;
16059215Storek register struct bootpath *bp;
16155139Storek register int a, pri;
16255139Storek
16355139Storek /* XXX the following declarations should be elsewhere */
16455139Storek extern void myetheraddr(u_char *);
16555139Storek extern caddr_t dvma_malloc(size_t);
16655139Storek
16755139Storek if (sa->sa_ra.ra_nintr != 1) {
16855139Storek printf(": expected 1 interrupt, got %d\n", sa->sa_ra.ra_nintr);
16955139Storek return;
17055139Storek }
17155139Storek pri = sa->sa_ra.ra_intr[0].int_pri;
17255139Storek printf(" pri %d", pri);
17355139Storek sc->sc_r1 = (volatile struct lereg1 *)
17455139Storek mapiodev(sa->sa_ra.ra_paddr, sizeof(struct lereg1));
17555139Storek ler2 = sc->sc_r2 = (volatile struct lereg2 *)
17655139Storek dvma_malloc(sizeof(struct lereg2));
17755139Storek
17855139Storek myetheraddr(sc->sc_addr);
17955139Storek printf(": hardware address %s\n", ether_sprintf(sc->sc_addr));
18055139Storek
18155139Storek /*
18255139Storek * Setup for transmit/receive
18355139Storek *
18455139Storek * According to Van, some versions of the Lance only use this
18555139Storek * address to receive packets; it doesn't put them in
18655139Storek * output packets. We'll want to make sure that lestart()
18755139Storek * installs the address.
18855139Storek */
18955139Storek ler2->ler2_padr[0] = sc->sc_addr[1];
19055139Storek ler2->ler2_padr[1] = sc->sc_addr[0];
19155139Storek ler2->ler2_padr[2] = sc->sc_addr[3];
19255139Storek ler2->ler2_padr[3] = sc->sc_addr[2];
19355139Storek ler2->ler2_padr[4] = sc->sc_addr[5];
19455139Storek ler2->ler2_padr[5] = sc->sc_addr[4];
19555139Storek a = LANCE_ADDR(&ler2->ler2_rmd);
19655139Storek ler2->ler2_rlen = LE_RLEN | (a >> 16);
19755139Storek ler2->ler2_rdra = a;
19855139Storek a = LANCE_ADDR(&ler2->ler2_tmd);
19955139Storek ler2->ler2_tlen = LE_TLEN | (a >> 16);
20055139Storek ler2->ler2_tdra = a;
20155139Storek
20255139Storek /*
20355139Storek * Link into sbus, and establish interrupt handler.
20455139Storek */
20555139Storek sc->sc_sd.sd_reset = lereset;
20655139Storek sbus_establish(&sc->sc_sd, &sc->sc_dev);
20755139Storek sc->sc_ih.ih_fun = leintr;
20855139Storek sc->sc_ih.ih_arg = sc;
20955139Storek intr_establish(pri, &sc->sc_ih);
21055139Storek
21159215Storek /*
21259215Storek * Set up event counters.
21359215Storek */
21459215Storek evcnt_attach(&sc->sc_dev, "intr", &sc->sc_intrcnt);
21559215Storek evcnt_attach(&sc->sc_dev, "errs", &sc->sc_errcnt);
21659215Storek
21755139Storek ifp->if_unit = sc->sc_dev.dv_unit;
21855139Storek ifp->if_name = "le";
21955139Storek ifp->if_mtu = ETHERMTU;
22055139Storek ifp->if_init = leinit;
22155139Storek ifp->if_ioctl = leioctl;
22255139Storek ifp->if_output = ether_output;
22355139Storek ifp->if_start = lestart;
22455139Storek ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
22555139Storek #ifdef IFF_NOTRAILERS
22655139Storek /* XXX still compile when the blasted things are gone... */
22755139Storek ifp->if_flags |= IFF_NOTRAILERS;
22855139Storek #endif
22955139Storek #if NBPFILTER > 0
23055139Storek bpfattach(&sc->sc_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
23155139Storek #endif
23255139Storek if_attach(ifp);
23359215Storek
23459215Storek #define SAME_LANCE(bp, sa) \
23559215Storek ((bp->val[0] == sa->sa_slot && bp->val[1] == sa->sa_offset) || \
23659215Storek (bp->val[0] == -1 && bp->val[1] == sc->sc_dev.dv_unit))
23759215Storek
23859215Storek bp = sa->sa_ra.ra_bp;
23959215Storek if (bp != NULL && strcmp(bp->name, "le") == 0 && SAME_LANCE(bp, sa))
24059215Storek bootdv = &sc->sc_dev;
24155139Storek }
24255139Storek
24355139Storek /*
24455139Storek * Setup the logical address filter
24555139Storek */
24655139Storek void
lesetladrf(sc)24755139Storek lesetladrf(sc)
24855139Storek register struct le_softc *sc;
24955139Storek {
25055139Storek register volatile struct lereg2 *ler2 = sc->sc_r2;
25155139Storek register struct ifnet *ifp = &sc->sc_if;
25255139Storek register struct ether_multi *enm;
25359215Storek register u_char *cp, c;
25455139Storek register u_long crc;
25555139Storek register int i, len;
25655139Storek struct ether_multistep step;
25755139Storek
25855139Storek /*
25955139Storek * Set up multicast address filter by passing all multicast
26055139Storek * addresses through a crc generator, and then using the high
26155139Storek * order 6 bits as a index into the 64 bit logical address
26255139Storek * filter. The high order two bits select the word, while the
26355139Storek * rest of the bits select the bit within the word.
26455139Storek */
26555139Storek
26655139Storek ler2->ler2_ladrf[0] = 0;
26755139Storek ler2->ler2_ladrf[1] = 0;
268*64777Storek ler2->ler2_ladrf[2] = 0;
269*64777Storek ler2->ler2_ladrf[3] = 0;
27055139Storek ifp->if_flags &= ~IFF_ALLMULTI;
27155139Storek ETHER_FIRST_MULTI(step, &sc->sc_ac, enm);
27255139Storek while (enm != NULL) {
27355139Storek if (bcmp((caddr_t)&enm->enm_addrlo,
27459215Storek (caddr_t)&enm->enm_addrhi, sizeof(enm->enm_addrlo)) != 0) {
27555139Storek /*
27655139Storek * We must listen to a range of multicast
27755139Storek * addresses. For now, just accept all
27855139Storek * multicasts, rather than trying to set only
27955139Storek * those filter bits needed to match the range.
28055139Storek * (At this time, the only use of address
28155139Storek * ranges is for IP multicast routing, for
28255139Storek * which the range is big enough to require all
28355139Storek * bits set.)
28455139Storek */
285*64777Storek ler2->ler2_ladrf[0] = 0xffff;
286*64777Storek ler2->ler2_ladrf[1] = 0xffff;
287*64777Storek ler2->ler2_ladrf[2] = 0xffff;
288*64777Storek ler2->ler2_ladrf[3] = 0xffff;
28955139Storek ifp->if_flags |= IFF_ALLMULTI;
29055139Storek return;
29155139Storek }
29255139Storek
29359215Storek /*
29459215Storek * One would think, given the AM7990 document's polynomial
29559215Storek * of 0x04c11db6, that this should be 0x6db88320 (the bit
29659215Storek * reversal of the AMD value), but that is not right. See
29759215Storek * the BASIC listing: bit 0 (our bit 31) must then be set.
29859215Storek */
29955139Storek cp = (unsigned char *)&enm->enm_addrlo;
30055139Storek crc = 0xffffffff;
30159215Storek for (len = 6; --len >= 0;) {
30259215Storek c = *cp++;
30355139Storek for (i = 0; i < 8; i++) {
30455139Storek if ((c & 0x01) ^ (crc & 0x01)) {
30555139Storek crc >>= 1;
30655139Storek crc = crc ^ 0xedb88320;
30759215Storek } else
30855139Storek crc >>= 1;
30955139Storek c >>= 1;
31055139Storek }
31155139Storek }
31255139Storek /* Just want the 6 most significant bits. */
31355139Storek crc = crc >> 26;
31455139Storek
31555139Storek /* Turn on the corresponding bit in the filter. */
316*64777Storek ler2->ler2_ladrf[crc >> 4] |= 1 << (crc & 0xf);
31755139Storek
31855139Storek ETHER_NEXT_MULTI(step, enm);
31955139Storek }
32055139Storek }
32155139Storek
32255139Storek void
lereset(dev)32355139Storek lereset(dev)
32455139Storek struct device *dev;
32555139Storek {
32655139Storek register struct le_softc *sc = (struct le_softc *)dev;
32755139Storek register volatile struct lereg1 *ler1 = sc->sc_r1;
32855139Storek register volatile struct lereg2 *ler2 = sc->sc_r2;
32955139Storek register int i, a, timo, stat;
33055139Storek
33155139Storek #if NBPFILTER > 0
33255139Storek if (sc->sc_if.if_flags & IFF_PROMISC)
33355139Storek ler2->ler2_mode = LE_MODE_NORMAL | LE_MODE_PROM;
33455139Storek else
33555139Storek #endif
33655139Storek ler2->ler2_mode = LE_MODE_NORMAL;
33755139Storek ler1->ler1_rap = LE_CSR0;
33855139Storek ler1->ler1_rdp = LE_C0_STOP;
33955139Storek
34055139Storek /* Setup the logical address filter */
34155139Storek lesetladrf(sc);
34255139Storek
34355139Storek /* init receive and transmit rings */
34455139Storek for (i = 0; i < LERBUF; i++) {
34555139Storek a = LANCE_ADDR(&ler2->ler2_rbuf[i][0]);
34655139Storek ler2->ler2_rmd[i].rmd0 = a;
34755139Storek ler2->ler2_rmd[i].rmd1_hadr = a >> 16;
34855139Storek ler2->ler2_rmd[i].rmd1_bits = LE_R1_OWN;
34955139Storek ler2->ler2_rmd[i].rmd2 = -LEMTU;
35055139Storek ler2->ler2_rmd[i].rmd3 = 0;
35155139Storek }
35255139Storek for (i = 0; i < LETBUF; i++) {
35355139Storek a = LANCE_ADDR(&ler2->ler2_tbuf[i][0]);
35455139Storek ler2->ler2_tmd[i].tmd0 = a;
35555139Storek ler2->ler2_tmd[i].tmd1_hadr = a >> 16;
35655139Storek ler2->ler2_tmd[i].tmd1_bits = 0;
35755139Storek ler2->ler2_tmd[i].tmd2 = 0;
35855139Storek ler2->ler2_tmd[i].tmd3 = 0;
35955139Storek }
36055139Storek
36155139Storek bzero(&ler2->ler2_rbuf[0][0], (LERBUF + LETBUF) * LEMTU);
36255139Storek /* lance will stuff packet into receive buffer 0 next */
36355139Storek sc->sc_rmd = 0;
36455139Storek
36555139Storek /* tell the chip where to find the initialization block */
36655139Storek a = LANCE_ADDR(&ler2->ler2_mode);
36755139Storek ler1->ler1_rap = LE_CSR1;
36855139Storek ler1->ler1_rdp = a;
36955139Storek ler1->ler1_rap = LE_CSR2;
37055139Storek ler1->ler1_rdp = a >> 16;
37155139Storek ler1->ler1_rap = LE_CSR3;
37255139Storek ler1->ler1_rdp = LE_C3_BSWP | LE_C3_ACON | LE_C3_BCON;
37355139Storek ler1->ler1_rap = LE_CSR0;
37455139Storek ler1->ler1_rdp = LE_C0_INIT;
37555139Storek timo = 100000;
37655139Storek while (((stat = ler1->ler1_rdp) & (LE_C0_ERR | LE_C0_IDON)) == 0) {
37755139Storek if (--timo == 0) {
37855139Storek printf("%s: init timeout, stat=%b\n",
37955139Storek sc->sc_dev.dv_xname, stat, LE_C0_BITS);
38055139Storek break;
38155139Storek }
38255139Storek }
38355139Storek if (stat & LE_C0_ERR)
38455139Storek printf("%s: init failed, stat=%b\n",
38555139Storek sc->sc_dev.dv_xname, stat, LE_C0_BITS);
38655139Storek else
38755139Storek ler1->ler1_rdp = LE_C0_IDON; /* clear IDON */
38855139Storek ler1->ler1_rdp = LE_C0_STRT | LE_C0_INEA;
38955139Storek sc->sc_if.if_flags &= ~IFF_OACTIVE;
39055139Storek }
39155139Storek
39255139Storek /*
39355139Storek * Initialization of interface
39455139Storek */
39555139Storek int
leinit(unit)39655139Storek leinit(unit)
39755139Storek int unit;
39855139Storek {
39955139Storek register struct le_softc *sc = lecd.cd_devs[unit];
40055139Storek register struct ifnet *ifp = &sc->sc_if;
40155139Storek register int s;
40255139Storek
40355139Storek /* not yet, if address still unknown */
40455139Storek if (ifp->if_addrlist == (struct ifaddr *)0)
40555139Storek return (0);
40655139Storek if ((ifp->if_flags & IFF_RUNNING) == 0) {
40755139Storek s = splimp();
40855139Storek ifp->if_flags |= IFF_RUNNING;
409*64777Storek lereset(&sc->sc_dev);
41055139Storek lestart(ifp);
41155139Storek splx(s);
41255139Storek }
41355139Storek return (0);
41455139Storek }
41555139Storek
41655139Storek /*
41755139Storek * Start output on interface. Get another datagram to send
41855139Storek * off of the interface queue, and copy it to the interface
41955139Storek * before starting the output.
42055139Storek */
42155139Storek int
lestart(ifp)42255139Storek lestart(ifp)
42355139Storek register struct ifnet *ifp;
42455139Storek {
42555139Storek register struct le_softc *sc = lecd.cd_devs[ifp->if_unit];
42655139Storek register volatile struct letmd *tmd;
42755139Storek register struct mbuf *m;
42855139Storek register int len;
42955139Storek
43055139Storek if ((sc->sc_if.if_flags & IFF_RUNNING) == 0)
43155139Storek return (0);
43255139Storek IF_DEQUEUE(&sc->sc_if.if_snd, m);
43355139Storek if (m == 0)
43455139Storek return (0);
43555139Storek len = leput(sc->sc_r2->ler2_tbuf[0], m);
43655139Storek #if NBPFILTER > 0
43755139Storek /*
43855139Storek * If bpf is listening on this interface, let it
43955139Storek * see the packet before we commit it to the wire.
44055139Storek */
44155139Storek if (sc->sc_bpf)
44255139Storek bpf_tap(sc->sc_bpf, sc->sc_r2->ler2_tbuf[0], len);
44355139Storek #endif
44455139Storek
44555139Storek #ifdef PACKETSTATS
44655139Storek if (len <= LEMTU)
44755139Storek lexpacketsizes[len]++;
44855139Storek #endif
44955139Storek tmd = sc->sc_r2->ler2_tmd;
45055139Storek tmd->tmd3 = 0;
45155139Storek tmd->tmd2 = -len;
45255139Storek tmd->tmd1_bits = LE_T1_OWN | LE_T1_STP | LE_T1_ENP;
45355139Storek sc->sc_if.if_flags |= IFF_OACTIVE;
45455139Storek return (0);
45555139Storek }
45655139Storek
45755139Storek int
leintr(dev)45855139Storek leintr(dev)
45955139Storek register void *dev;
46055139Storek {
46155139Storek register struct le_softc *sc = dev;
46255139Storek register volatile struct lereg1 *ler1 = sc->sc_r1;
46355139Storek register int csr0;
46455139Storek
46555139Storek csr0 = ler1->ler1_rdp;
46655139Storek if ((csr0 & LE_C0_INTR) == 0)
46755139Storek return (0);
46859215Storek sc->sc_intrcnt.ev_count++;
46955139Storek
47055139Storek if (csr0 & LE_C0_ERR) {
47159215Storek sc->sc_errcnt.ev_count++;
47255139Storek leerror(sc, csr0);
47355139Storek if (csr0 & LE_C0_MERR) {
47455139Storek sc->sc_merr++;
475*64777Storek lereset(&sc->sc_dev);
47655139Storek return (1);
47755139Storek }
47855139Storek if (csr0 & LE_C0_BABL)
47955139Storek sc->sc_babl++;
48055139Storek if (csr0 & LE_C0_CERR)
48155139Storek sc->sc_cerr++;
48255139Storek if (csr0 & LE_C0_MISS)
48355139Storek sc->sc_miss++;
48455139Storek ler1->ler1_rdp = LE_C0_BABL|LE_C0_CERR|LE_C0_MISS|LE_C0_INEA;
48555139Storek }
48655139Storek if ((csr0 & LE_C0_RXON) == 0) {
48755139Storek sc->sc_rxoff++;
488*64777Storek lereset(&sc->sc_dev);
48955139Storek return (1);
49055139Storek }
49155139Storek if ((csr0 & LE_C0_TXON) == 0) {
49255139Storek sc->sc_txoff++;
493*64777Storek lereset(&sc->sc_dev);
49455139Storek return (1);
49555139Storek }
49655139Storek if (csr0 & LE_C0_RINT) {
49755139Storek /* interrupt is cleared in lerint */
49855139Storek lerint(sc);
49955139Storek }
50055139Storek if (csr0 & LE_C0_TINT) {
50155139Storek ler1->ler1_rdp = LE_C0_TINT|LE_C0_INEA;
50255139Storek lexint(sc);
50355139Storek }
50455139Storek return (1);
50555139Storek }
50655139Storek
50755139Storek /*
50855139Storek * Ethernet interface transmitter interrupt.
50955139Storek * Start another output if more data to send.
51055139Storek */
51155139Storek void
lexint(sc)51255139Storek lexint(sc)
51355139Storek register struct le_softc *sc;
51455139Storek {
51555139Storek register volatile struct letmd *tmd = sc->sc_r2->ler2_tmd;
51655139Storek
51755139Storek sc->sc_lestats.lexints++;
51855139Storek if ((sc->sc_if.if_flags & IFF_OACTIVE) == 0) {
51955139Storek sc->sc_xint++;
52055139Storek return;
52155139Storek }
52255139Storek if (tmd->tmd1_bits & LE_T1_OWN) {
52355139Storek sc->sc_xown++;
52455139Storek return;
52555139Storek }
52655139Storek if (tmd->tmd1_bits & LE_T1_ERR) {
52755139Storek err:
52855139Storek lexerror(sc);
52955139Storek sc->sc_if.if_oerrors++;
53055139Storek if (tmd->tmd3 & (LE_T3_BUFF|LE_T3_UFLO)) {
53155139Storek sc->sc_uflo++;
532*64777Storek lereset(&sc->sc_dev);
53355139Storek } else if (tmd->tmd3 & LE_T3_LCOL)
53455139Storek sc->sc_if.if_collisions++;
53555139Storek else if (tmd->tmd3 & LE_T3_RTRY)
53655139Storek sc->sc_if.if_collisions += 16;
53755139Storek }
53855139Storek else if (tmd->tmd3 & LE_T3_BUFF)
53955139Storek /* XXX documentation says BUFF not included in ERR */
54055139Storek goto err;
54155139Storek else if (tmd->tmd1_bits & LE_T1_ONE)
54255139Storek sc->sc_if.if_collisions++;
54355139Storek else if (tmd->tmd1_bits & LE_T1_MORE)
54455139Storek /* what is the real number? */
54555139Storek sc->sc_if.if_collisions += 2;
54655139Storek else
54755139Storek sc->sc_if.if_opackets++;
54855139Storek sc->sc_if.if_flags &= ~IFF_OACTIVE;
54955139Storek lestart(&sc->sc_if);
55055139Storek }
55155139Storek
55255139Storek #define LENEXTRMP \
55355139Storek if (++bix == LERBUF) bix = 0, rmd = sc->sc_r2->ler2_rmd; else ++rmd
55455139Storek
55555139Storek /*
55655139Storek * Ethernet interface receiver interrupt.
55755139Storek * If input error just drop packet.
55855139Storek * Decapsulate packet based on type and pass to type specific
55955139Storek * higher-level input routine.
56055139Storek */
56155139Storek void
lerint(sc)56255139Storek lerint(sc)
56355139Storek register struct le_softc *sc;
56455139Storek {
56555139Storek register int bix = sc->sc_rmd;
56655139Storek register volatile struct lermd *rmd = &sc->sc_r2->ler2_rmd[bix];
56755139Storek
56855139Storek sc->sc_lestats.lerints++;
56955139Storek /*
57055139Storek * Out of sync with hardware, should never happen?
57155139Storek */
57255139Storek if (rmd->rmd1_bits & LE_R1_OWN) {
57355139Storek do {
57455139Storek sc->sc_lestats.lerscans++;
57555139Storek LENEXTRMP;
57655139Storek } while ((rmd->rmd1_bits & LE_R1_OWN) && bix != sc->sc_rmd);
57755139Storek if (bix == sc->sc_rmd)
57855139Storek printf("%s: RINT with no buffer\n",
57955139Storek sc->sc_dev.dv_xname);
58055139Storek } else
58155139Storek sc->sc_lestats.lerhits++;
58255139Storek
58355139Storek /*
58455139Storek * Process all buffers with valid data
58555139Storek */
58655139Storek while ((rmd->rmd1_bits & LE_R1_OWN) == 0) {
58755139Storek int len = rmd->rmd3;
58855139Storek
58955139Storek /* Clear interrupt to avoid race condition */
59055139Storek sc->sc_r1->ler1_rdp = LE_C0_RINT|LE_C0_INEA;
59155139Storek
59255139Storek if (rmd->rmd1_bits & LE_R1_ERR) {
59355139Storek sc->sc_rmd = bix;
59455139Storek lererror(sc, "bad packet");
59555139Storek sc->sc_if.if_ierrors++;
59655139Storek } else if ((rmd->rmd1_bits & (LE_R1_STP|LE_R1_ENP)) !=
59755139Storek (LE_R1_STP|LE_R1_ENP)) {
59855139Storek /* XXX make a define for LE_R1_STP|LE_R1_ENP? */
59955139Storek /*
60055139Storek * Find the end of the packet so we can see how long
60155139Storek * it was. We still throw it away.
60255139Storek */
60355139Storek do {
60455139Storek sc->sc_r1->ler1_rdp = LE_C0_RINT|LE_C0_INEA;
60555139Storek rmd->rmd3 = 0;
60655139Storek rmd->rmd1_bits = LE_R1_OWN;
60755139Storek LENEXTRMP;
60855139Storek } while (!(rmd->rmd1_bits &
60955139Storek (LE_R1_OWN|LE_R1_ERR|LE_R1_STP|LE_R1_ENP)));
61055139Storek sc->sc_rmd = bix;
61155139Storek lererror(sc, "chained buffer");
61255139Storek sc->sc_rxlen++;
61355139Storek /*
61455139Storek * If search terminated without successful completion
61555139Storek * we reset the hardware (conservative).
61655139Storek */
61755139Storek if ((rmd->rmd1_bits &
61855139Storek (LE_R1_OWN|LE_R1_ERR|LE_R1_STP|LE_R1_ENP)) !=
61955139Storek LE_R1_ENP) {
620*64777Storek lereset(&sc->sc_dev);
62155139Storek return;
62255139Storek }
62355139Storek } else {
62455139Storek leread(sc, sc->sc_r2->ler2_rbuf[bix], len);
62555139Storek #ifdef PACKETSTATS
62655139Storek lerpacketsizes[len]++;
62755139Storek #endif
62855139Storek sc->sc_lestats.lerbufs++;
62955139Storek }
63055139Storek rmd->rmd3 = 0;
63155139Storek rmd->rmd1_bits = LE_R1_OWN;
63255139Storek LENEXTRMP;
63355139Storek }
63455139Storek sc->sc_rmd = bix;
63555139Storek }
63655139Storek
63755139Storek void
leread(sc,pkt,len)63855139Storek leread(sc, pkt, len)
63955139Storek register struct le_softc *sc;
64055139Storek char *pkt;
64155139Storek int len;
64255139Storek {
64355139Storek register struct ether_header *et;
64455139Storek register struct ifnet *ifp = &sc->sc_if;
64555139Storek struct mbuf *m;
64655139Storek struct ifqueue *inq;
64755139Storek int flags;
64855139Storek
64955139Storek ifp->if_ipackets++;
65055139Storek et = (struct ether_header *)pkt;
65155139Storek et->ether_type = ntohs((u_short)et->ether_type);
65255139Storek /* adjust input length to account for header and CRC */
65355139Storek len -= sizeof(struct ether_header) + 4;
65455139Storek
65555139Storek if (len <= 0) {
65655139Storek if (ledebug)
65755139Storek log(LOG_WARNING,
65855139Storek "%s: ierror(runt packet): from %s: len=%d\n",
65955139Storek sc->sc_dev.dv_xname,
66055139Storek ether_sprintf(et->ether_shost), len);
66155139Storek sc->sc_runt++;
66255139Storek ifp->if_ierrors++;
66355139Storek return;
66455139Storek }
66555139Storek
66655139Storek /* Setup mbuf flags we'll need later */
66755139Storek flags = 0;
66855139Storek if (bcmp((caddr_t)etherbroadcastaddr,
66955139Storek (caddr_t)et->ether_dhost, sizeof(etherbroadcastaddr)) == 0)
67055139Storek flags |= M_BCAST;
67155139Storek if (et->ether_dhost[0] & 1)
67255139Storek flags |= M_MCAST;
67355139Storek
67455139Storek #if NBPFILTER > 0
67555139Storek /*
67655139Storek * Check if there's a bpf filter listening on this interface.
67759215Storek * If so, hand off the raw packet to enet, then discard things
67859215Storek * not destined for us (but be sure to keep broadcast/multicast).
67955139Storek */
68055139Storek if (sc->sc_bpf) {
68155139Storek bpf_tap(sc->sc_bpf, pkt, len + sizeof(struct ether_header));
68259215Storek if ((flags & (M_BCAST | M_MCAST)) == 0 &&
68355139Storek bcmp(et->ether_dhost, sc->sc_addr,
68459215Storek sizeof(et->ether_dhost)) != 0)
68555139Storek return;
68655139Storek }
68755139Storek #endif
68855139Storek m = leget(pkt, len, 0, ifp);
68955139Storek if (m == 0)
69055139Storek return;
69155139Storek
69255139Storek /* XXX this code comes from ether_input() */
69355139Storek ifp->if_lastchange = time;
69455139Storek ifp->if_ibytes += m->m_pkthdr.len + sizeof (*et);
69555139Storek if (flags) {
69655139Storek m->m_flags |= flags;
69755139Storek ifp->if_imcasts++;
69855139Storek }
69955139Storek /* XXX end of code from ether_input() */
70055139Storek
70155139Storek switch (et->ether_type) {
70255139Storek
70355139Storek #ifdef INET
70455139Storek case ETHERTYPE_IP:
70555139Storek schednetisr(NETISR_IP);
70655139Storek inq = &ipintrq;
70755139Storek break;
70855139Storek
70955139Storek case ETHERTYPE_ARP:
71055139Storek schednetisr(NETISR_ARP);
71155139Storek inq = &arpintrq;
71255139Storek break;
71355139Storek #endif
71455139Storek #ifdef NS
71555139Storek case ETHERTYPE_NS:
71655139Storek schednetisr(NETISR_NS);
71755139Storek inq = &nsintrq;
71855139Storek break;
71955139Storek #endif
72055139Storek
72155139Storek #ifdef UTAHONLY
72255139Storek #ifdef APPLETALK
72355139Storek case ETHERTYPE_APPLETALK:
72455139Storek schednetisr(NETISR_DDP);
72555139Storek inq = &ddpintq;
72655139Storek break;
72755139Storek
72855139Storek case ETHERTYPE_AARP:
72955139Storek aarpinput(&sc->sc_ac, m);
73055139Storek return;
73155139Storek #endif
73255139Storek #endif
73355139Storek default:
73455139Storek m_freem(m);
73555139Storek return;
73655139Storek }
73755139Storek
73855139Storek if (IF_QFULL(inq)) {
73955139Storek IF_DROP(inq);
74055139Storek m_freem(m);
74155139Storek return;
74255139Storek }
74355139Storek IF_ENQUEUE(inq, m);
74455139Storek }
74555139Storek
74655139Storek /*
74755139Storek * Routine to copy from mbuf chain to transmit
74855139Storek * buffer in board local memory.
74955139Storek *
75055139Storek * ### this can be done by remapping in some cases
75155139Storek */
75255139Storek int
leput(lebuf,m)75355139Storek leput(lebuf, m)
75455139Storek register char *lebuf;
75555139Storek register struct mbuf *m;
75655139Storek {
75755139Storek register struct mbuf *mp;
75855139Storek register int len, tlen = 0;
75955139Storek
76055139Storek for (mp = m; mp; mp = mp->m_next) {
76155139Storek len = mp->m_len;
76255139Storek if (len == 0)
76355139Storek continue;
76455139Storek tlen += len;
76555139Storek bcopy(mtod(mp, char *), lebuf, len);
76655139Storek lebuf += len;
76755139Storek }
76855139Storek m_freem(m);
76955139Storek if (tlen < LEMINSIZE) {
77055139Storek bzero(lebuf, LEMINSIZE - tlen);
77155139Storek tlen = LEMINSIZE;
77255139Storek }
77355139Storek return (tlen);
77455139Storek }
77555139Storek
77655139Storek /*
77755139Storek * Routine to copy from board local memory into mbufs.
77855139Storek */
77955139Storek struct mbuf *
leget(lebuf,totlen,off0,ifp)78055139Storek leget(lebuf, totlen, off0, ifp)
78155139Storek char *lebuf;
78255139Storek int totlen, off0;
78355139Storek struct ifnet *ifp;
78455139Storek {
78555139Storek register struct mbuf *m;
78655139Storek struct mbuf *top = 0, **mp = ⊤
78755139Storek register int off = off0, len;
78855139Storek register char *cp;
78955139Storek char *epkt;
79055139Storek
79155139Storek lebuf += sizeof(struct ether_header);
79255139Storek cp = lebuf;
79355139Storek epkt = cp + totlen;
79455139Storek if (off) {
79555139Storek cp += off + 2 * sizeof(u_short);
79655139Storek totlen -= 2 * sizeof(u_short);
79755139Storek }
79855139Storek
79955139Storek MGETHDR(m, M_DONTWAIT, MT_DATA);
80055139Storek if (m == 0)
80155139Storek return (0);
80255139Storek m->m_pkthdr.rcvif = ifp;
80355139Storek m->m_pkthdr.len = totlen;
80455139Storek m->m_len = MHLEN;
80555139Storek
80655139Storek while (totlen > 0) {
80755139Storek if (top) {
80855139Storek MGET(m, M_DONTWAIT, MT_DATA);
80955139Storek if (m == 0) {
81055139Storek m_freem(top);
81155139Storek return (0);
81255139Storek }
81355139Storek m->m_len = MLEN;
81455139Storek }
81555139Storek len = min(totlen, epkt - cp);
81655139Storek if (len >= MINCLSIZE) {
81755139Storek MCLGET(m, M_DONTWAIT);
81855139Storek if (m->m_flags & M_EXT)
81955139Storek m->m_len = len = min(len, MCLBYTES);
82055139Storek else
82155139Storek len = m->m_len;
82255139Storek } else {
82355139Storek /*
82455139Storek * Place initial small packet/header at end of mbuf.
82555139Storek */
82655139Storek if (len < m->m_len) {
82755139Storek if (top == 0 && len + max_linkhdr <= m->m_len)
82855139Storek m->m_data += max_linkhdr;
82955139Storek m->m_len = len;
83055139Storek } else
83155139Storek len = m->m_len;
83255139Storek }
83355139Storek bcopy(cp, mtod(m, caddr_t), (unsigned)len);
83455139Storek cp += len;
83555139Storek *mp = m;
83655139Storek mp = &m->m_next;
83755139Storek totlen -= len;
83855139Storek if (cp == epkt)
83955139Storek cp = lebuf;
84055139Storek }
84155139Storek return (top);
84255139Storek }
84355139Storek
84455139Storek /*
84555139Storek * Process an ioctl request.
84655139Storek */
84755139Storek int
leioctl(ifp,cmd,data)84855139Storek leioctl(ifp, cmd, data)
84955139Storek register struct ifnet *ifp;
85055139Storek int cmd;
85155139Storek caddr_t data;
85255139Storek {
85355139Storek register struct ifaddr *ifa;
85455139Storek register struct le_softc *sc = lecd.cd_devs[ifp->if_unit];
85555139Storek register volatile struct lereg1 *ler1;
85655139Storek int s = splimp(), error = 0;
85755139Storek
85855139Storek switch (cmd) {
85955139Storek
86055139Storek case SIOCSIFADDR:
86155139Storek ifa = (struct ifaddr *)data;
86255139Storek ifp->if_flags |= IFF_UP;
86355139Storek switch (ifa->ifa_addr->sa_family) {
86455139Storek #ifdef INET
86555139Storek case AF_INET:
86655139Storek (void)leinit(ifp->if_unit); /* before arpwhohas */
86755139Storek ((struct arpcom *)ifp)->ac_ipaddr =
86855139Storek IA_SIN(ifa)->sin_addr;
86955139Storek arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr);
87055139Storek break;
87155139Storek #endif
87255139Storek #ifdef NS
87355139Storek case AF_NS:
87455139Storek {
87555139Storek register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
87655139Storek
87755139Storek if (ns_nullhost(*ina))
87855139Storek ina->x_host = *(union ns_host *)(sc->sc_addr);
87955139Storek else {
88055139Storek /*
88155139Storek * The manual says we can't change the address
88255139Storek * while the receiver is armed,
88355139Storek * so reset everything
88455139Storek */
88555139Storek ifp->if_flags &= ~IFF_RUNNING;
88655139Storek bcopy((caddr_t)ina->x_host.c_host,
88755139Storek (caddr_t)sc->sc_addr, sizeof(sc->sc_addr));
88855139Storek }
88955139Storek (void)leinit(ifp->if_unit); /* does le_setaddr() */
89055139Storek break;
89155139Storek }
89255139Storek #endif
89355139Storek default:
89455139Storek (void)leinit(ifp->if_unit);
89555139Storek break;
89655139Storek }
89755139Storek break;
89855139Storek
89955139Storek case SIOCSIFFLAGS:
90055139Storek ler1 = sc->sc_r1;
90155139Storek if ((ifp->if_flags & IFF_UP) == 0 &&
90255139Storek ifp->if_flags & IFF_RUNNING) {
90355139Storek ler1->ler1_rdp = LE_C0_STOP;
90455139Storek ifp->if_flags &= ~IFF_RUNNING;
90555139Storek } else if (ifp->if_flags & IFF_UP &&
90655139Storek (ifp->if_flags & IFF_RUNNING) == 0)
90755139Storek (void)leinit(ifp->if_unit);
90855139Storek /*
90955139Storek * If the state of the promiscuous bit changes, the interface
91055139Storek * must be reset to effect the change.
91155139Storek */
91255139Storek if (((ifp->if_flags ^ sc->sc_iflags) & IFF_PROMISC) &&
91355139Storek (ifp->if_flags & IFF_RUNNING)) {
91455139Storek sc->sc_iflags = ifp->if_flags;
915*64777Storek lereset(&sc->sc_dev);
91655139Storek lestart(ifp);
91755139Storek }
91855139Storek break;
91955139Storek
92055139Storek case SIOCADDMULTI:
92159215Storek error = ether_addmulti((struct ifreq *)data, &sc->sc_ac);
92259215Storek goto update_multicast;
92359215Storek
92455139Storek case SIOCDELMULTI:
92559215Storek error = ether_delmulti((struct ifreq *)data, &sc->sc_ac);
92659215Storek update_multicast:
92755139Storek if (error == ENETRESET) {
92855139Storek /*
92955139Storek * Multicast list has changed; set the hardware
93055139Storek * filter accordingly.
93155139Storek */
932*64777Storek lereset(&sc->sc_dev);
93355139Storek error = 0;
93455139Storek }
93555139Storek break;
93655139Storek
93755139Storek default:
93855139Storek error = EINVAL;
93955139Storek }
94055139Storek splx(s);
94155139Storek return (error);
94255139Storek }
94355139Storek
94455139Storek void
leerror(sc,stat)94555139Storek leerror(sc, stat)
94655139Storek register struct le_softc *sc;
94755139Storek int stat;
94855139Storek {
94955139Storek if (!ledebug)
95055139Storek return;
95155139Storek
95255139Storek /*
95355139Storek * Not all transceivers implement heartbeat
95455139Storek * so we only log CERR once.
95555139Storek */
95655139Storek if ((stat & LE_C0_CERR) && sc->sc_cerr)
95755139Storek return;
95855139Storek log(LOG_WARNING, "%s: error: stat=%b\n",
95955139Storek sc->sc_dev.dv_xname, stat, LE_C0_BITS);
96055139Storek }
96155139Storek
96255139Storek void
lererror(sc,msg)96355139Storek lererror(sc, msg)
96455139Storek register struct le_softc *sc;
96555139Storek char *msg;
96655139Storek {
96755139Storek register volatile struct lermd *rmd;
96855139Storek int len;
96955139Storek
97055139Storek if (!ledebug)
97155139Storek return;
97255139Storek
97355139Storek rmd = &sc->sc_r2->ler2_rmd[sc->sc_rmd];
97455139Storek len = rmd->rmd3;
97555139Storek log(LOG_WARNING, "%s: ierror(%s): from %s: buf=%d, len=%d, rmd1=%b\n",
97655139Storek sc->sc_dev.dv_xname, msg, len > 11 ?
97755139Storek ether_sprintf((u_char *)&sc->sc_r2->ler2_rbuf[sc->sc_rmd][6]) :
97855139Storek "unknown",
97955139Storek sc->sc_rmd, len, rmd->rmd1_bits, LE_R1_BITS);
98055139Storek }
98155139Storek
98255139Storek void
lexerror(sc)98355139Storek lexerror(sc)
98455139Storek register struct le_softc *sc;
98555139Storek {
98655139Storek register volatile struct letmd *tmd;
98755139Storek register int len, tmd3, tdr;
98855139Storek
98955139Storek if (!ledebug)
99055139Storek return;
99155139Storek
99255139Storek tmd = sc->sc_r2->ler2_tmd;
99355139Storek tmd3 = tmd->tmd3;
99455139Storek tdr = tmd3 & LE_T3_TDR_MASK;
99555139Storek len = -tmd->tmd2;
99655139Storek log(LOG_WARNING,
99755139Storek "%s: oerror: to %s: buf=%d, len=%d, tmd1=%b, tmd3=%b, tdr=%d (%d nsecs)\n",
99855139Storek sc->sc_dev.dv_xname, len > 5 ?
99955139Storek ether_sprintf((u_char *)&sc->sc_r2->ler2_tbuf[0][0]) : "unknown",
100055139Storek 0, len,
100155139Storek tmd->tmd1_bits, LE_T1_BITS,
100255139Storek tmd3, LE_T3_BITS, tdr, tdr * 100);
100355139Storek }
1004