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