154000Sfujita /*
2*63192Sbostic * Copyright (c) 1982, 1990, 1993
3*63192Sbostic * The Regents of the University of California. All rights reserved.
454000Sfujita *
554000Sfujita * %sccs.include.redist.c%
654000Sfujita *
758694Sakito * from: hp300/dev/if_le.c 7.16 (Berkeley) 3/11/93
855582Sfujita *
9*63192Sbostic * @(#)if_le.c 8.1 (Berkeley) 06/10/93
1054000Sfujita */
1154000Sfujita
1254000Sfujita #include "le.h"
1354000Sfujita #if NLE > 0
1454000Sfujita
1554000Sfujita #include "bpfilter.h"
1654000Sfujita
1754000Sfujita /*
1854000Sfujita * AMD 7990 LANCE
1954000Sfujita *
2055582Sfujita * This driver will accept tailer encapsulated packets even
2154000Sfujita * though it buys us nothing. The motivation was to avoid incompatibilities
2254000Sfujita * with VAXen, SUNs, and others that handle and benefit from them.
2354000Sfujita * This reasoning is dubious.
2454000Sfujita */
2556519Sbostic #include <sys/param.h>
2656519Sbostic #include <sys/proc.h>
2756519Sbostic #include <sys/systm.h>
2856519Sbostic #include <sys/mbuf.h>
2956519Sbostic #include <sys/buf.h>
3056519Sbostic #include <sys/protosw.h>
3156519Sbostic #include <sys/socket.h>
3256519Sbostic #include <sys/syslog.h>
3356519Sbostic #include <sys/ioctl.h>
3456519Sbostic #include <sys/errno.h>
3554000Sfujita
3656519Sbostic #include <net/if.h>
3756519Sbostic #include <net/netisr.h>
3856519Sbostic #include <net/route.h>
3954000Sfujita
4054000Sfujita #ifdef INET
4156519Sbostic #include <netinet/in.h>
4256519Sbostic #include <netinet/in_systm.h>
4356519Sbostic #include <netinet/in_var.h>
4456519Sbostic #include <netinet/ip.h>
4556519Sbostic #include <netinet/if_ether.h>
4654000Sfujita #endif
4754000Sfujita
4854000Sfujita #ifdef NS
4956519Sbostic #include <netns/ns.h>
5056519Sbostic #include <netns/ns_if.h>
5154000Sfujita #endif
5254000Sfujita
5357525Sakito #if defined (CCITT) && defined (LLC)
5457525Sakito #include <sys/socketvar.h>
5557525Sakito #include <netccitt/x25.h>
5657525Sakito extern llc_ctlinput(), cons_rtrequest();
5757525Sakito #endif
5857525Sakito
5956519Sbostic #include <machine/cpu.h>
6056519Sbostic #include <machine/mtpr.h>
6156519Sbostic #include <luna68k/dev/device.h>
6256519Sbostic #include <luna68k/dev/if_lereg.h>
6354000Sfujita
6454000Sfujita #if NBPFILTER > 0
6556519Sbostic #include <net/bpf.h>
6656519Sbostic #include <net/bpfdesc.h>
6754000Sfujita #endif
6854000Sfujita
6954000Sfujita int leattach();
7054000Sfujita struct driver ledriver = {
7154000Sfujita leattach, "le",
7254000Sfujita };
7354000Sfujita
7454000Sfujita int ledebug = 0; /* console error messages */
7554000Sfujita
7657525Sakito int leintr(), leinit(), leioctl(), lestart(), ether_output(), lereset();
7754000Sfujita struct mbuf *m_devget();
7854000Sfujita extern struct ifnet loif;
7954000Sfujita
8054000Sfujita /*
8154000Sfujita * Ethernet software status per interface.
8254000Sfujita *
8354000Sfujita * Each interface is referenced by a network interface structure,
8454000Sfujita * le_if, which the routing code uses to locate the interface.
8554000Sfujita * This structure contains the output queue for the interface, its address, ...
8654000Sfujita */
8754000Sfujita struct le_softc {
8854000Sfujita struct arpcom sc_ac; /* common Ethernet structures */
8954000Sfujita #define sc_if sc_ac.ac_if /* network-visible interface */
9054000Sfujita #define sc_addr sc_ac.ac_enaddr /* hardware Ethernet address */
9154000Sfujita struct lereg1 *sc_r1; /* LANCE registers */
9254000Sfujita struct lereg2 *sc_r2; /* dual-port RAM */
9354000Sfujita int sc_rmd; /* predicted next rmd to process */
9455582Sfujita int sc_tmd; /* next available tmd */
9555582Sfujita int sc_txcnt; /* # of transmit buffers in use */
9655582Sfujita /* stats */
9754000Sfujita int sc_runt;
9854000Sfujita int sc_jab;
9954000Sfujita int sc_merr;
10054000Sfujita int sc_babl;
10154000Sfujita int sc_cerr;
10254000Sfujita int sc_miss;
10355582Sfujita int sc_rown;
10454000Sfujita int sc_xown;
10555582Sfujita int sc_xown2;
10654000Sfujita int sc_uflo;
10754000Sfujita int sc_rxlen;
10854000Sfujita int sc_rxoff;
10954000Sfujita int sc_txoff;
11054000Sfujita int sc_busy;
11154000Sfujita short sc_iflags;
11254000Sfujita } le_softc[NLE];
11354000Sfujita
11454000Sfujita /* access LANCE registers */
11554000Sfujita #define LERDWR(cntl, src, dst) (dst) = (src)
11654000Sfujita
11754000Sfujita #define LE_IPL 3
11854000Sfujita
11954000Sfujita /*
12054000Sfujita * Interface exists: make available by filling in network interface
12154000Sfujita * record. System will initialize the interface when it is ready
12254000Sfujita * to accept packets.
12354000Sfujita */
12454000Sfujita leattach(hd)
12554000Sfujita struct hp_device *hd;
12654000Sfujita {
12754000Sfujita register struct lereg2 *ler2;
12854000Sfujita struct lereg2 *lemem = (struct lereg2 *) 0;
12954000Sfujita struct le_softc *le = &le_softc[hd->hp_unit];
13054000Sfujita struct ifnet *ifp = &le->sc_if;
13154000Sfujita char *cp;
13254000Sfujita int i;
13354000Sfujita
13454000Sfujita le->sc_r1 = (struct lereg1 *) hd->hp_addr;
13554000Sfujita ler2 = le->sc_r2 = (struct lereg2 *) 0x71000000;
13654000Sfujita
13754000Sfujita hd->hp_ipl = LE_IPL;
13854000Sfujita
13954000Sfujita /*
14054000Sfujita * Read the ethernet address off the board, one nibble at a time.
14154000Sfujita */
14254000Sfujita #ifdef NOROM
14354000Sfujita cp = "00000a02456c";
14454000Sfujita #else
14559942Sakito #if defined(LUNA2)
14659942Sakito if (machineid == LUNA_II) {
14759942Sakito static char rom_data[128];
14859942Sakito volatile u_int *from = (u_int *)0xf1000004;
14959942Sakito for (i = 0; i < 128; i++) {
15059942Sakito *from = (i * 2) << 16;
15159942Sakito rom_data[i] |= (*from >> 12) & 0xf0;
15259942Sakito *from = (i * 2 + 1) << 16;
15359942Sakito rom_data[i] |= (*from >> 16) & 0xf;
15459942Sakito }
15559942Sakito cp =&rom_data[6]; /* ETHER0 must be here */
15659942Sakito /* one port only now XXX */
15759942Sakito } else
15854000Sfujita #endif
15959942Sakito {
16059942Sakito cp = (char *) 0x4101FFE0;
16159942Sakito }
16259942Sakito #endif
16354000Sfujita for (i = 0; i < sizeof(le->sc_addr); i++) {
16454000Sfujita le->sc_addr[i] = (*cp < 'A' ? (*cp & 0xF) : (*cp & 0xF) + 9) << 4;
16554000Sfujita cp++;
16654000Sfujita le->sc_addr[i] |= (*cp < 'A' ? (*cp & 0xF) : (*cp & 0xF) + 9);
16754000Sfujita cp++;
16854000Sfujita }
16954000Sfujita printf("le%d: hardware address %s\n", hd->hp_unit,
17054000Sfujita ether_sprintf(le->sc_addr));
17154000Sfujita
17254000Sfujita /*
17354000Sfujita * Setup for transmit/receive
17454000Sfujita */
17554000Sfujita ler2->ler2_mode = LE_MODE;
17655582Sfujita ler2->ler2_ladrf[0] = 0;
17755582Sfujita ler2->ler2_ladrf[1] = 0;
17854000Sfujita ler2->ler2_rlen = LE_RLEN;
17954000Sfujita ler2->ler2_rdra = (int)lemem->ler2_rmd;
18054000Sfujita ler2->ler2_tlen = LE_TLEN;
18154000Sfujita ler2->ler2_tdra = (int)lemem->ler2_tmd;
18254000Sfujita
18354000Sfujita ifp->if_unit = hd->hp_unit;
18454000Sfujita ifp->if_name = "le";
18554000Sfujita ifp->if_mtu = ETHERMTU;
18654000Sfujita ifp->if_init = leinit;
18757525Sakito ifp->if_reset = lereset;
18854000Sfujita ifp->if_ioctl = leioctl;
18954000Sfujita ifp->if_output = ether_output;
19054000Sfujita ifp->if_start = lestart;
19155582Sfujita #ifdef MULTICAST
19255582Sfujita ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
19355582Sfujita #else
19454000Sfujita ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX;
19555582Sfujita #endif
19654000Sfujita #if NBPFILTER > 0
19755582Sfujita bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
19854000Sfujita #endif
19954000Sfujita if_attach(ifp);
20054000Sfujita return (1);
20154000Sfujita }
20254000Sfujita
20355582Sfujita #ifdef MULTICAST
20455582Sfujita /*
20555582Sfujita * Setup the logical address filter
20655582Sfujita */
20755582Sfujita void
lesetladrf(sc)20855582Sfujita lesetladrf(sc)
20955582Sfujita register struct le_softc *sc;
21055582Sfujita {
21155582Sfujita register volatile struct lereg2 *ler2 = sc->sc_r2;
21255582Sfujita register struct ifnet *ifp = &sc->sc_if;
21355582Sfujita register struct ether_multi *enm;
21455582Sfujita register u_char *cp;
21555582Sfujita register u_long crc;
21655582Sfujita register u_long c;
21755582Sfujita register int i, len;
21855582Sfujita struct ether_multistep step;
21955582Sfujita
22055582Sfujita /*
22155582Sfujita * Set up multicast address filter by passing all multicast
22255582Sfujita * addresses through a crc generator, and then using the high
22355582Sfujita * order 6 bits as a index into the 64 bit logical address
22455582Sfujita * filter. The high order two bits select the word, while the
22555582Sfujita * rest of the bits select the bit within the word.
22655582Sfujita */
22755582Sfujita
22855582Sfujita ler2->ler2_ladrf[0] = 0;
22955582Sfujita ler2->ler2_ladrf[1] = 0;
23055582Sfujita ifp->if_flags &= ~IFF_ALLMULTI;
23155582Sfujita ETHER_FIRST_MULTI(step, &sc->sc_ac, enm);
23255582Sfujita while (enm != NULL) {
23355582Sfujita if (bcmp((caddr_t)&enm->enm_addrlo,
23455582Sfujita (caddr_t)&enm->enm_addrhi, sizeof(enm->enm_addrlo)) == 0) {
23555582Sfujita /*
23655582Sfujita * We must listen to a range of multicast
23755582Sfujita * addresses. For now, just accept all
23855582Sfujita * multicasts, rather than trying to set only
23955582Sfujita * those filter bits needed to match the range.
24055582Sfujita * (At this time, the only use of address
24155582Sfujita * ranges is for IP multicast routing, for
24255582Sfujita * which the range is big enough to require all
24355582Sfujita * bits set.)
24455582Sfujita */
24555582Sfujita ler2->ler2_ladrf[0] = 0xffffffff;
24655582Sfujita ler2->ler2_ladrf[1] = 0xffffffff;
24755582Sfujita ifp->if_flags |= IFF_ALLMULTI;
24855582Sfujita return;
24955582Sfujita }
25055582Sfujita
25155582Sfujita cp = (unsigned char *)&enm->enm_addrlo;
25255582Sfujita c = *cp;
25355582Sfujita crc = 0xffffffff;
25455582Sfujita len = 6;
25555582Sfujita while (len-- > 0) {
25655582Sfujita c = *cp;
25755582Sfujita for (i = 0; i < 8; i++) {
25855582Sfujita if ((c & 0x01) ^ (crc & 0x01)) {
25955582Sfujita crc >>= 1;
26055582Sfujita crc = crc ^ 0xedb88320;
26155582Sfujita }
26255582Sfujita else
26355582Sfujita crc >>= 1;
26455582Sfujita c >>= 1;
26555582Sfujita }
26655582Sfujita cp++;
26755582Sfujita }
26855582Sfujita /* Just want the 6 most significant bits. */
26955582Sfujita crc = crc >> 26;
27055582Sfujita
27155582Sfujita /* Turn on the corresponding bit in the filter. */
27255582Sfujita ler2->ler2_ladrf[crc >> 5] |= 1 << (crc & 0x1f);
27355582Sfujita
27455582Sfujita ETHER_NEXT_MULTI(step, enm);
27555582Sfujita }
27655582Sfujita }
27755582Sfujita #endif
27855582Sfujita
ledrinit(ler2,le)27954000Sfujita ledrinit(ler2, le)
28054000Sfujita register struct lereg2 *ler2;
28154000Sfujita register struct le_softc *le;
28254000Sfujita {
28354000Sfujita register struct lereg2 *lemem = (struct lereg2 *) 0;
28454000Sfujita register int i;
28554000Sfujita
28654000Sfujita ler2->ler2_padr[0] = le->sc_addr[1];
28754000Sfujita ler2->ler2_padr[1] = le->sc_addr[0];
28854000Sfujita ler2->ler2_padr[2] = le->sc_addr[3];
28954000Sfujita ler2->ler2_padr[3] = le->sc_addr[2];
29054000Sfujita ler2->ler2_padr[4] = le->sc_addr[5];
29154000Sfujita ler2->ler2_padr[5] = le->sc_addr[4];
29254000Sfujita for (i = 0; i < LERBUF; i++) {
29354000Sfujita ler2->ler2_rmd[i].rmd0 = (int)lemem->ler2_rbuf[i];
29454000Sfujita ler2->ler2_rmd[i].rmd1 = LE_OWN;
29554000Sfujita ler2->ler2_rmd[i].rmd2 = -LEMTU;
29654000Sfujita ler2->ler2_rmd[i].rmd3 = 0;
29754000Sfujita }
29854000Sfujita for (i = 0; i < LETBUF; i++) {
29954000Sfujita ler2->ler2_tmd[i].tmd0 = (int)lemem->ler2_tbuf[i];
30054000Sfujita ler2->ler2_tmd[i].tmd1 = 0;
30154000Sfujita ler2->ler2_tmd[i].tmd2 = 0;
30254000Sfujita ler2->ler2_tmd[i].tmd3 = 0;
30354000Sfujita }
30455582Sfujita /* Setup the logical address filter */
30555582Sfujita #ifdef MULTICAST
30655582Sfujita lesetladrf(le);
30755582Sfujita #else
30855582Sfujita ler2->ler2_ladrf[0] = 0;
30955582Sfujita ler2->ler2_ladrf[1] = 0;
31055582Sfujita #endif
31154000Sfujita }
31254000Sfujita
lereset(unit)31354000Sfujita lereset(unit)
31454000Sfujita register int unit;
31554000Sfujita {
31654000Sfujita register struct le_softc *le = &le_softc[unit];
31754000Sfujita register struct lereg1 *ler1 = le->sc_r1;
31854000Sfujita register struct lereg2 *lemem = (struct lereg2 *) 0;
31954000Sfujita register int timo = 100000;
32054000Sfujita register int stat;
32154000Sfujita
32254000Sfujita #ifdef lint
32354000Sfujita stat = unit;
32454000Sfujita #endif
32554000Sfujita #if NBPFILTER > 0
32654000Sfujita if (le->sc_if.if_flags & IFF_PROMISC)
32754000Sfujita /* set the promiscuous bit */
32854000Sfujita le->sc_r2->ler2_mode = LE_MODE|0x8000;
32954000Sfujita else
33054000Sfujita le->sc_r2->ler2_mode = LE_MODE;
33154000Sfujita #endif
33254000Sfujita LERDWR(ler0, LE_CSR0, ler1->ler1_rap);
33354000Sfujita LERDWR(ler0, LE_STOP, ler1->ler1_rdp);
33454000Sfujita ledrinit(le->sc_r2, le);
33555582Sfujita le->sc_rmd = le->sc_tmd = 0;
33654000Sfujita LERDWR(ler0, LE_CSR1, ler1->ler1_rap);
33754000Sfujita LERDWR(ler0, (int)&lemem->ler2_mode, ler1->ler1_rdp);
33854000Sfujita LERDWR(ler0, LE_CSR2, ler1->ler1_rap);
33954000Sfujita LERDWR(ler0, 0, ler1->ler1_rdp);
34054000Sfujita LERDWR(ler0, LE_CSR0, ler1->ler1_rap);
34154000Sfujita LERDWR(ler0, LE_INIT, ler1->ler1_rdp);
34254000Sfujita do {
34354000Sfujita if (--timo == 0) {
34454000Sfujita printf("le%d: init timeout, stat = 0x%x\n",
34554000Sfujita unit, stat);
34654000Sfujita break;
34754000Sfujita }
34854000Sfujita LERDWR(ler0, ler1->ler1_rdp, stat);
34954000Sfujita } while ((stat & LE_IDON) == 0);
35054000Sfujita LERDWR(ler0, LE_STOP, ler1->ler1_rdp);
35154000Sfujita LERDWR(ler0, LE_CSR3, ler1->ler1_rap);
35254000Sfujita LERDWR(ler0, LE_BSWP, ler1->ler1_rdp);
35354000Sfujita LERDWR(ler0, LE_CSR0, ler1->ler1_rap);
35454000Sfujita LERDWR(ler0, LE_STRT | LE_INEA, ler1->ler1_rdp);
35554000Sfujita le->sc_if.if_flags &= ~IFF_OACTIVE;
35655582Sfujita le->sc_txcnt = 0;
35754000Sfujita }
35854000Sfujita
35954000Sfujita /*
36054000Sfujita * Initialization of interface
36154000Sfujita */
leinit(unit)36254000Sfujita leinit(unit)
36354000Sfujita int unit;
36454000Sfujita {
36554000Sfujita register struct ifnet *ifp = &le_softc[unit].sc_if;
36654000Sfujita register struct ifaddr *ifa;
36754000Sfujita int s;
36854000Sfujita
36954000Sfujita /* not yet, if address still unknown */
37054000Sfujita for (ifa = ifp->if_addrlist;; ifa = ifa->ifa_next)
37154000Sfujita if (ifa == 0)
37254000Sfujita return;
37354000Sfujita else if (ifa->ifa_addr && ifa->ifa_addr->sa_family != AF_LINK)
37454000Sfujita break;
37554000Sfujita if ((ifp->if_flags & IFF_RUNNING) == 0) {
37654000Sfujita s = splimp();
37754000Sfujita ifp->if_flags |= IFF_RUNNING;
37854000Sfujita lereset(unit);
37954000Sfujita (void) lestart(ifp);
38054000Sfujita splx(s);
38154000Sfujita }
38254000Sfujita }
38354000Sfujita
38454000Sfujita /*
38554000Sfujita * Start output on interface. Get another datagram to send
38654000Sfujita * off of the interface queue, and copy it to the interface
38754000Sfujita * before starting the output.
38854000Sfujita */
38954000Sfujita lestart(ifp)
39054000Sfujita struct ifnet *ifp;
39154000Sfujita {
39254000Sfujita register struct le_softc *le = &le_softc[ifp->if_unit];
39354000Sfujita register struct letmd *tmd;
39454000Sfujita register struct mbuf *m;
39554000Sfujita int len;
39654000Sfujita
39754000Sfujita if ((le->sc_if.if_flags & IFF_RUNNING) == 0)
39854000Sfujita return (0);
39955582Sfujita tmd = &le->sc_r2->ler2_tmd[le->sc_tmd];
40055582Sfujita do {
40155582Sfujita if (tmd->tmd1 & LE_OWN) {
40255582Sfujita le->sc_xown2++;
40355582Sfujita return (0);
40455582Sfujita }
40555582Sfujita IF_DEQUEUE(&le->sc_if.if_snd, m);
40655582Sfujita if (m == 0)
40755582Sfujita return (0);
40855582Sfujita len = leput(le->sc_r2->ler2_tbuf[le->sc_tmd], m);
40954000Sfujita #if NBPFILTER > 0
41055582Sfujita /*
41155582Sfujita * If bpf is listening on this interface, let it
41255582Sfujita * see the packet before we commit it to the wire.
41355582Sfujita */
41455582Sfujita if (ifp->if_bpf)
41555582Sfujita bpf_tap(ifp->if_bpf, le->sc_r2->ler2_tbuf[le->sc_tmd],
41655582Sfujita len);
41754000Sfujita #endif
41855582Sfujita
41955582Sfujita tmd->tmd3 = 0;
42055582Sfujita tmd->tmd2 = -len;
42154000Sfujita tmd->tmd1 = LE_OWN | LE_STP | LE_ENP;
42255582Sfujita if (++le->sc_tmd == LETBUF) {
42355582Sfujita le->sc_tmd = 0;
42455582Sfujita tmd = le->sc_r2->ler2_tmd;
42555582Sfujita } else
42655582Sfujita tmd++;
42755582Sfujita } while (++le->sc_txcnt < LETBUF);
42855582Sfujita le->sc_if.if_flags |= IFF_OACTIVE;
42954000Sfujita return (0);
43054000Sfujita }
43154000Sfujita
43254000Sfujita void
_leintr()43354000Sfujita _leintr()
43454000Sfujita {
43554000Sfujita register int i;
43654000Sfujita
43754000Sfujita for (i = 0; i < NLE; i++) {
43854000Sfujita leintr(i);
43954000Sfujita }
44054000Sfujita }
44154000Sfujita
44254000Sfujita int
leintr(unit)44354000Sfujita leintr(unit)
44454000Sfujita register int unit;
44554000Sfujita {
44654000Sfujita register struct le_softc *le = &le_softc[unit];
44754000Sfujita register struct lereg1 *ler1;
44854000Sfujita register int stat;
44954000Sfujita
45054000Sfujita ler1 = le->sc_r1;
45154000Sfujita LERDWR(ler0, ler1->ler1_rdp, stat);
45254000Sfujita if (stat & LE_SERR) {
45354000Sfujita leerror(unit, stat);
45454000Sfujita if (stat & LE_MERR) {
45554000Sfujita le->sc_merr++;
45654000Sfujita lereset(unit);
45754000Sfujita return(1);
45854000Sfujita }
45954000Sfujita if (stat & LE_BABL)
46054000Sfujita le->sc_babl++;
46154000Sfujita if (stat & LE_CERR)
46254000Sfujita le->sc_cerr++;
46354000Sfujita if (stat & LE_MISS)
46454000Sfujita le->sc_miss++;
46554000Sfujita LERDWR(ler0, LE_BABL|LE_CERR|LE_MISS|LE_INEA, ler1->ler1_rdp);
46654000Sfujita }
46754000Sfujita if ((stat & LE_RXON) == 0) {
46854000Sfujita le->sc_rxoff++;
46954000Sfujita lereset(unit);
47054000Sfujita return(1);
47154000Sfujita }
47254000Sfujita if ((stat & LE_TXON) == 0) {
47354000Sfujita le->sc_txoff++;
47454000Sfujita lereset(unit);
47554000Sfujita return(1);
47654000Sfujita }
47755582Sfujita if (stat & LE_RINT)
47854000Sfujita lerint(unit);
47955582Sfujita if (stat & LE_TINT)
48054000Sfujita lexint(unit);
48154000Sfujita return(1);
48254000Sfujita }
48354000Sfujita
48454000Sfujita /*
48554000Sfujita * Ethernet interface transmitter interrupt.
48654000Sfujita * Start another output if more data to send.
48754000Sfujita */
lexint(unit)48854000Sfujita lexint(unit)
48954000Sfujita register int unit;
49054000Sfujita {
49154000Sfujita register struct le_softc *le = &le_softc[unit];
49254000Sfujita register struct letmd *tmd;
49355582Sfujita int i, gotone = 0;
49454000Sfujita
49555582Sfujita do {
49655582Sfujita if ((i = le->sc_tmd - le->sc_txcnt) < 0)
49755582Sfujita i += LETBUF;
49855582Sfujita tmd = &le->sc_r2->ler2_tmd[i];
49955582Sfujita if (tmd->tmd1 & LE_OWN) {
50055582Sfujita if (gotone)
50155582Sfujita break;
50255582Sfujita le->sc_xown++;
50355582Sfujita return;
50454000Sfujita }
50555582Sfujita
50655582Sfujita /* clear interrupt */
50755582Sfujita LERDWR(le->sc_r0, LE_TINT|LE_INEA, le->sc_r1->ler1_rdp);
50855582Sfujita
50955582Sfujita /* XXX documentation says BUFF not included in ERR */
51055582Sfujita if ((tmd->tmd1 & LE_ERR) || (tmd->tmd3 & LE_TBUFF)) {
51155582Sfujita lexerror(unit);
51255582Sfujita le->sc_if.if_oerrors++;
51355582Sfujita if (tmd->tmd3 & (LE_TBUFF|LE_UFLO)) {
51455582Sfujita le->sc_uflo++;
51555582Sfujita lereset(unit);
51655582Sfujita } else if (tmd->tmd3 & LE_LCOL)
51755582Sfujita le->sc_if.if_collisions++;
51855582Sfujita else if (tmd->tmd3 & LE_RTRY)
51955582Sfujita le->sc_if.if_collisions += 16;
52055582Sfujita } else if (tmd->tmd1 & LE_ONE)
52154000Sfujita le->sc_if.if_collisions++;
52255582Sfujita else if (tmd->tmd1 & LE_MORE)
52355582Sfujita /* what is the real number? */
52455582Sfujita le->sc_if.if_collisions += 2;
52555582Sfujita else
52655582Sfujita le->sc_if.if_opackets++;
52755582Sfujita gotone++;
52855582Sfujita } while (--le->sc_txcnt > 0);
52954000Sfujita le->sc_if.if_flags &= ~IFF_OACTIVE;
53054000Sfujita (void) lestart(&le->sc_if);
53154000Sfujita }
53254000Sfujita
53354000Sfujita #define LENEXTRMP \
53454000Sfujita if (++bix == LERBUF) bix = 0, rmd = le->sc_r2->ler2_rmd; else ++rmd
53554000Sfujita
53654000Sfujita /*
53754000Sfujita * Ethernet interface receiver interrupt.
53854000Sfujita * If input error just drop packet.
53954000Sfujita * Decapsulate packet based on type and pass to type specific
54054000Sfujita * higher-level input routine.
54154000Sfujita */
lerint(unit)54254000Sfujita lerint(unit)
54354000Sfujita int unit;
54454000Sfujita {
54554000Sfujita register struct le_softc *le = &le_softc[unit];
54654000Sfujita register int bix = le->sc_rmd;
54754000Sfujita register struct lermd *rmd = &le->sc_r2->ler2_rmd[bix];
54854000Sfujita
54954000Sfujita /*
55054000Sfujita * Out of sync with hardware, should never happen?
55154000Sfujita */
55254000Sfujita if (rmd->rmd1 & LE_OWN) {
55355582Sfujita le->sc_rown++;
55454000Sfujita LERDWR(le->sc_r0, LE_RINT|LE_INEA, le->sc_r1->ler1_rdp);
55554000Sfujita return;
55654000Sfujita }
55754000Sfujita
55854000Sfujita /*
55954000Sfujita * Process all buffers with valid data
56054000Sfujita */
56154000Sfujita while ((rmd->rmd1 & LE_OWN) == 0) {
56254000Sfujita int len = rmd->rmd3;
56354000Sfujita
56454000Sfujita /* Clear interrupt to avoid race condition */
56554000Sfujita LERDWR(le->sc_r0, LE_RINT|LE_INEA, le->sc_r1->ler1_rdp);
56654000Sfujita
56754000Sfujita if (rmd->rmd1 & LE_ERR) {
56854000Sfujita le->sc_rmd = bix;
56954000Sfujita lererror(unit, "bad packet");
57054000Sfujita le->sc_if.if_ierrors++;
57154000Sfujita } else if ((rmd->rmd1 & (LE_STP|LE_ENP)) != (LE_STP|LE_ENP)) {
57254000Sfujita /*
57354000Sfujita * Find the end of the packet so we can see how long
57454000Sfujita * it was. We still throw it away.
57554000Sfujita */
57654000Sfujita do {
57754000Sfujita LERDWR(le->sc_r0, LE_RINT|LE_INEA,
57854000Sfujita le->sc_r1->ler1_rdp);
57954000Sfujita rmd->rmd3 = 0;
58054000Sfujita rmd->rmd1 = LE_OWN;
58154000Sfujita LENEXTRMP;
58254000Sfujita } while (!(rmd->rmd1 & (LE_OWN|LE_ERR|LE_STP|LE_ENP)));
58354000Sfujita le->sc_rmd = bix;
58454000Sfujita lererror(unit, "chained buffer");
58554000Sfujita le->sc_rxlen++;
58654000Sfujita /*
58754000Sfujita * If search terminated without successful completion
58854000Sfujita * we reset the hardware (conservative).
58954000Sfujita */
59054000Sfujita if ((rmd->rmd1 & (LE_OWN|LE_ERR|LE_STP|LE_ENP)) !=
59154000Sfujita LE_ENP) {
59254000Sfujita lereset(unit);
59354000Sfujita return;
59454000Sfujita }
59554000Sfujita } else
59654000Sfujita leread(unit, le->sc_r2->ler2_rbuf[bix], len);
59754000Sfujita rmd->rmd3 = 0;
59854000Sfujita rmd->rmd1 = LE_OWN;
59954000Sfujita LENEXTRMP;
60054000Sfujita }
60154000Sfujita le->sc_rmd = bix;
60254000Sfujita }
60354000Sfujita
leread(unit,buf,len)60454000Sfujita leread(unit, buf, len)
60554000Sfujita int unit;
60654000Sfujita char *buf;
60754000Sfujita int len;
60854000Sfujita {
60954000Sfujita register struct le_softc *le = &le_softc[unit];
61054000Sfujita register struct ether_header *et;
61154000Sfujita struct mbuf *m;
61255582Sfujita int off, resid, flags;
61354000Sfujita
61454000Sfujita le->sc_if.if_ipackets++;
61554000Sfujita et = (struct ether_header *)buf;
61654000Sfujita et->ether_type = ntohs((u_short)et->ether_type);
61754000Sfujita /* adjust input length to account for header and CRC */
61854000Sfujita len = len - sizeof(struct ether_header) - 4;
61954000Sfujita
62054000Sfujita #define ledataaddr(et, off, type) ((type)(((caddr_t)((et)+1)+(off))))
62154000Sfujita if (et->ether_type >= ETHERTYPE_TRAIL &&
62254000Sfujita et->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) {
62354000Sfujita off = (et->ether_type - ETHERTYPE_TRAIL) * 512;
62454000Sfujita if (off >= ETHERMTU)
62554000Sfujita return; /* sanity */
62654000Sfujita et->ether_type = ntohs(*ledataaddr(et, off, u_short *));
62754000Sfujita resid = ntohs(*(ledataaddr(et, off+2, u_short *)));
62854000Sfujita if (off + resid > len)
62954000Sfujita return; /* sanity */
63054000Sfujita len = off + resid;
63154000Sfujita } else
63254000Sfujita off = 0;
63354000Sfujita
63454000Sfujita if (len <= 0) {
63554000Sfujita if (ledebug)
63654000Sfujita log(LOG_WARNING,
63754000Sfujita "le%d: ierror(runt packet): from %s: len=%d\n",
63854000Sfujita unit, ether_sprintf(et->ether_shost), len);
63954000Sfujita le->sc_runt++;
64054000Sfujita le->sc_if.if_ierrors++;
64154000Sfujita return;
64254000Sfujita }
64355582Sfujita flags = 0;
64455582Sfujita if (bcmp((caddr_t)etherbroadcastaddr,
64555582Sfujita (caddr_t)et->ether_dhost, sizeof(etherbroadcastaddr)) == 0)
64655582Sfujita flags |= M_BCAST;
64755582Sfujita if (et->ether_dhost[0] & 1)
64855582Sfujita flags |= M_MCAST;
64955582Sfujita
65054000Sfujita #if NBPFILTER > 0
65154000Sfujita /*
65254000Sfujita * Check if there's a bpf filter listening on this interface.
65355582Sfujita * If so, hand off the raw packet to enet.
65454000Sfujita */
65555582Sfujita if (le->sc_if.if_bpf) {
65655582Sfujita bpf_tap(le->sc_if.if_bpf, buf, len + sizeof(struct ether_header));
65755582Sfujita
65855582Sfujita /*
65955582Sfujita * Keep the packet if it's a broadcast or has our
66055582Sfujita * physical ethernet address (or if we support
66155582Sfujita * multicast and it's one).
66255582Sfujita */
66355582Sfujita if (
66455582Sfujita #ifdef MULTICAST
66555582Sfujita (flags & (M_BCAST | M_MCAST)) == 0 &&
66655582Sfujita #else
66755582Sfujita (flags & M_BCAST) == 0 &&
66854000Sfujita #endif
66955582Sfujita bcmp(et->ether_dhost, le->sc_addr,
67055582Sfujita sizeof(et->ether_dhost)) != 0)
67155582Sfujita return;
67255582Sfujita }
67354000Sfujita #endif
67454000Sfujita /*
67554000Sfujita * Pull packet off interface. Off is nonzero if packet
67654000Sfujita * has trailing header; m_devget will then force this header
67754000Sfujita * information to be at the front, but we still have to drop
67854000Sfujita * the type and length which are at the front of any trailer data.
67954000Sfujita */
68054000Sfujita m = m_devget((char *)(et + 1), len, off, &le->sc_if, 0);
68154000Sfujita if (m == 0)
68254000Sfujita return;
68358694Sakito m->m_flags |= flags;
68454000Sfujita ether_input(&le->sc_if, et, m);
68554000Sfujita }
68654000Sfujita
68754000Sfujita /*
68854000Sfujita * Routine to copy from mbuf chain to transmit
68954000Sfujita * buffer in board local memory.
69054000Sfujita */
leput(lebuf,m)69154000Sfujita leput(lebuf, m)
69254000Sfujita register char *lebuf;
69354000Sfujita register struct mbuf *m;
69454000Sfujita {
69554000Sfujita register struct mbuf *mp;
69654000Sfujita register int len, tlen = 0;
69754000Sfujita
69854000Sfujita for (mp = m; mp; mp = mp->m_next) {
69954000Sfujita len = mp->m_len;
70054000Sfujita if (len == 0)
70154000Sfujita continue;
70254000Sfujita tlen += len;
70354000Sfujita bcopy(mtod(mp, char *), lebuf, len);
70454000Sfujita lebuf += len;
70554000Sfujita }
70654000Sfujita m_freem(m);
70754000Sfujita if (tlen < LEMINSIZE) {
70854000Sfujita bzero(lebuf, LEMINSIZE - tlen);
70954000Sfujita tlen = LEMINSIZE;
71054000Sfujita }
71154000Sfujita return(tlen);
71254000Sfujita }
71354000Sfujita
71454000Sfujita /*
71554000Sfujita * Process an ioctl request.
71654000Sfujita */
leioctl(ifp,cmd,data)71754000Sfujita leioctl(ifp, cmd, data)
71854000Sfujita register struct ifnet *ifp;
71954000Sfujita int cmd;
72054000Sfujita caddr_t data;
72154000Sfujita {
72254000Sfujita register struct ifaddr *ifa = (struct ifaddr *)data;
72354000Sfujita struct le_softc *le = &le_softc[ifp->if_unit];
72454000Sfujita struct lereg1 *ler1 = le->sc_r1;
72554000Sfujita int s = splimp(), error = 0;
72654000Sfujita
72754000Sfujita switch (cmd) {
72854000Sfujita
72954000Sfujita case SIOCSIFADDR:
73054000Sfujita ifp->if_flags |= IFF_UP;
73154000Sfujita switch (ifa->ifa_addr->sa_family) {
73254000Sfujita #ifdef INET
73354000Sfujita case AF_INET:
73454000Sfujita leinit(ifp->if_unit); /* before arpwhohas */
73554000Sfujita ((struct arpcom *)ifp)->ac_ipaddr =
73654000Sfujita IA_SIN(ifa)->sin_addr;
73754000Sfujita arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr);
73854000Sfujita break;
73954000Sfujita #endif
74054000Sfujita #ifdef NS
74154000Sfujita case AF_NS:
74254000Sfujita {
74354000Sfujita register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
74454000Sfujita
74554000Sfujita if (ns_nullhost(*ina))
74654000Sfujita ina->x_host = *(union ns_host *)(le->sc_addr);
74754000Sfujita else {
74854000Sfujita /*
74954000Sfujita * The manual says we can't change the address
75054000Sfujita * while the receiver is armed,
75154000Sfujita * so reset everything
75254000Sfujita */
75354000Sfujita ifp->if_flags &= ~IFF_RUNNING;
75454000Sfujita LERDWR(le->sc_r0, LE_STOP, ler1->ler1_rdp);
75554000Sfujita bcopy((caddr_t)ina->x_host.c_host,
75654000Sfujita (caddr_t)le->sc_addr, sizeof(le->sc_addr));
75754000Sfujita }
75854000Sfujita leinit(ifp->if_unit); /* does le_setaddr() */
75954000Sfujita break;
76054000Sfujita }
76154000Sfujita #endif
76254000Sfujita default:
76354000Sfujita leinit(ifp->if_unit);
76454000Sfujita break;
76554000Sfujita }
76654000Sfujita break;
76754000Sfujita
76857525Sakito #if defined (CCITT) && defined (LLC)
76957525Sakito case SIOCSIFCONF_X25:
77057525Sakito ifp -> if_flags |= IFF_UP;
77157525Sakito ifa -> ifa_rtrequest = cons_rtrequest;
77257525Sakito error = x25_llcglue(PRC_IFUP, ifa -> ifa_addr);
77357525Sakito if (error == 0)
77457525Sakito leinit(ifp -> if_unit);
77557525Sakito break;
77657525Sakito #endif /* CCITT && LLC */
77757525Sakito
77857525Sakito
77954000Sfujita case SIOCSIFFLAGS:
78054000Sfujita if ((ifp->if_flags & IFF_UP) == 0 &&
78154000Sfujita ifp->if_flags & IFF_RUNNING) {
78254000Sfujita LERDWR(le->sc_r0, LE_STOP, ler1->ler1_rdp);
78354000Sfujita ifp->if_flags &= ~IFF_RUNNING;
78454000Sfujita } else if (ifp->if_flags & IFF_UP &&
78554000Sfujita (ifp->if_flags & IFF_RUNNING) == 0)
78654000Sfujita leinit(ifp->if_unit);
78754000Sfujita /*
78854000Sfujita * If the state of the promiscuous bit changes, the interface
78954000Sfujita * must be reset to effect the change.
79054000Sfujita */
79154000Sfujita if (((ifp->if_flags ^ le->sc_iflags) & IFF_PROMISC) &&
79254000Sfujita (ifp->if_flags & IFF_RUNNING)) {
79354000Sfujita le->sc_iflags = ifp->if_flags;
79454000Sfujita lereset(ifp->if_unit);
79554000Sfujita lestart(ifp);
79654000Sfujita }
79754000Sfujita break;
79854000Sfujita
79955582Sfujita #ifdef MULTICAST
80055582Sfujita case SIOCADDMULTI:
80155582Sfujita case SIOCDELMULTI:
80255582Sfujita /* Update our multicast list */
80355582Sfujita error = (cmd == SIOCADDMULTI) ?
80455582Sfujita ether_addmulti((struct ifreq *)data, &le->sc_ac) :
80555582Sfujita ether_delmulti((struct ifreq *)data, &le->sc_ac);
80655582Sfujita
80755582Sfujita if (error == ENETRESET) {
80855582Sfujita /*
80955582Sfujita * Multicast list has changed; set the hardware
81055582Sfujita * filter accordingly.
81155582Sfujita */
81255582Sfujita lereset(ifp->if_unit);
81355582Sfujita error = 0;
81455582Sfujita }
81555582Sfujita break;
81655582Sfujita #endif
81754000Sfujita default:
81854000Sfujita error = EINVAL;
81954000Sfujita }
82054000Sfujita splx(s);
82154000Sfujita return (error);
82254000Sfujita }
82354000Sfujita
leerror(unit,stat)82454000Sfujita leerror(unit, stat)
82554000Sfujita int unit;
82654000Sfujita int stat;
82754000Sfujita {
82854000Sfujita if (!ledebug)
82954000Sfujita return;
83054000Sfujita
83154000Sfujita /*
83254000Sfujita * Not all transceivers implement heartbeat
83354000Sfujita * so we only log CERR once.
83454000Sfujita */
83554000Sfujita if ((stat & LE_CERR) && le_softc[unit].sc_cerr)
83654000Sfujita return;
83754000Sfujita log(LOG_WARNING,
83854000Sfujita "le%d: error: stat=%b\n", unit,
83954000Sfujita stat,
84054000Sfujita "\20\20ERR\17BABL\16CERR\15MISS\14MERR\13RINT\12TINT\11IDON\10INTR\07INEA\06RXON\05TXON\04TDMD\03STOP\02STRT\01INIT");
84154000Sfujita }
84254000Sfujita
lererror(unit,msg)84354000Sfujita lererror(unit, msg)
84454000Sfujita int unit;
84554000Sfujita char *msg;
84654000Sfujita {
84754000Sfujita register struct le_softc *le = &le_softc[unit];
84854000Sfujita register struct lermd *rmd;
84954000Sfujita int len;
85054000Sfujita
85154000Sfujita if (!ledebug)
85254000Sfujita return;
85354000Sfujita
85454000Sfujita rmd = &le->sc_r2->ler2_rmd[le->sc_rmd];
85554000Sfujita len = rmd->rmd3;
85654000Sfujita log(LOG_WARNING,
85754000Sfujita "le%d: ierror(%s): from %s: buf=%d, len=%d, rmd1=%b\n",
85854000Sfujita unit, msg,
85954000Sfujita len > 11 ?
86054000Sfujita ether_sprintf((u_char *)&le->sc_r2->ler2_rbuf[le->sc_rmd][6]) :
86154000Sfujita "unknown",
86254000Sfujita le->sc_rmd, len,
86354000Sfujita rmd->rmd1,
86454000Sfujita "\20\20OWN\17ERR\16FRAM\15OFLO\14CRC\13RBUF\12STP\11ENP");
86554000Sfujita }
86654000Sfujita
lexerror(unit)86754000Sfujita lexerror(unit)
86854000Sfujita int unit;
86954000Sfujita {
87054000Sfujita register struct le_softc *le = &le_softc[unit];
87154000Sfujita register struct letmd *tmd;
87254000Sfujita int len;
87354000Sfujita
87454000Sfujita if (!ledebug)
87554000Sfujita return;
87654000Sfujita
87754000Sfujita tmd = le->sc_r2->ler2_tmd;
87854000Sfujita len = -tmd->tmd2;
87954000Sfujita log(LOG_WARNING,
88054000Sfujita "le%d: oerror: to %s: buf=%d, len=%d, tmd1=%b, tmd3=%b\n",
88154000Sfujita unit,
88254000Sfujita len > 5 ?
88354000Sfujita ether_sprintf((u_char *)&le->sc_r2->ler2_tbuf[0][0]) :
88454000Sfujita "unknown",
88554000Sfujita 0, len,
88654000Sfujita tmd->tmd1,
88754000Sfujita "\20\20OWN\17ERR\16RES\15MORE\14ONE\13DEF\12STP\11ENP",
88854000Sfujita tmd->tmd3,
88954000Sfujita "\20\20BUFF\17UFLO\16RES\15LCOL\14LCAR\13RTRY");
89054000Sfujita }
89154000Sfujita #endif
892