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*59215Storek * @(#)if_le.c 7.3 (Berkeley) 04/20/93 855139Storek * 9*59215Storek * from: $Header: if_le.c,v 1.23 93/04/21 02:39:38 torek Exp $ 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 */ 93*59215Storek struct evcnt sc_intrcnt; /* # of interrupts, per le */ 94*59215Storek 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 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; 160*59215Storek register struct bootpath *bp; 16155139Storek register int a, pri; 16255139Storek #define ISQUADALIGN(a) ((((long) a) & 0x3) == 0) 16355139Storek 16455139Storek /* XXX the following declarations should be elsewhere */ 16555139Storek extern void myetheraddr(u_char *); 16655139Storek extern caddr_t dvma_malloc(size_t); 16755139Storek 16855139Storek if (sa->sa_ra.ra_nintr != 1) { 16955139Storek printf(": expected 1 interrupt, got %d\n", sa->sa_ra.ra_nintr); 17055139Storek return; 17155139Storek } 17255139Storek pri = sa->sa_ra.ra_intr[0].int_pri; 17355139Storek printf(" pri %d", pri); 17455139Storek sc->sc_r1 = (volatile struct lereg1 *) 17555139Storek mapiodev(sa->sa_ra.ra_paddr, sizeof(struct lereg1)); 17655139Storek ler2 = sc->sc_r2 = (volatile struct lereg2 *) 17755139Storek dvma_malloc(sizeof(struct lereg2)); 17855139Storek if (!ISQUADALIGN(ler2)) 17955139Storek printf("? not quad aligned (0x%x)\n", ler2); 18055139Storek 18155139Storek myetheraddr(sc->sc_addr); 18255139Storek printf(": hardware address %s\n", ether_sprintf(sc->sc_addr)); 18355139Storek 18455139Storek /* 18555139Storek * Setup for transmit/receive 18655139Storek * 18755139Storek * According to Van, some versions of the Lance only use this 18855139Storek * address to receive packets; it doesn't put them in 18955139Storek * output packets. We'll want to make sure that lestart() 19055139Storek * installs the address. 19155139Storek */ 19255139Storek ler2->ler2_padr[0] = sc->sc_addr[1]; 19355139Storek ler2->ler2_padr[1] = sc->sc_addr[0]; 19455139Storek ler2->ler2_padr[2] = sc->sc_addr[3]; 19555139Storek ler2->ler2_padr[3] = sc->sc_addr[2]; 19655139Storek ler2->ler2_padr[4] = sc->sc_addr[5]; 19755139Storek ler2->ler2_padr[5] = sc->sc_addr[4]; 19855139Storek a = LANCE_ADDR(&ler2->ler2_rmd); 19955139Storek if (!ISQUADALIGN(a)) 20055139Storek printf("rdra not quad aligned (0x%x)\n", a); 20155139Storek ler2->ler2_rlen = LE_RLEN | (a >> 16); 20255139Storek ler2->ler2_rdra = a; 20355139Storek a = LANCE_ADDR(&ler2->ler2_tmd); 20455139Storek if (!ISQUADALIGN(a)) 20555139Storek printf("tdra not quad aligned (0x%x)\n", a); 20655139Storek ler2->ler2_tlen = LE_TLEN | (a >> 16); 20755139Storek ler2->ler2_tdra = a; 20855139Storek 20955139Storek /* 21055139Storek * Link into sbus, and establish interrupt handler. 21155139Storek */ 21255139Storek sc->sc_sd.sd_reset = lereset; 21355139Storek sbus_establish(&sc->sc_sd, &sc->sc_dev); 21455139Storek sc->sc_ih.ih_fun = leintr; 21555139Storek sc->sc_ih.ih_arg = sc; 21655139Storek intr_establish(pri, &sc->sc_ih); 21755139Storek 218*59215Storek /* 219*59215Storek * Set up event counters. 220*59215Storek */ 221*59215Storek evcnt_attach(&sc->sc_dev, "intr", &sc->sc_intrcnt); 222*59215Storek evcnt_attach(&sc->sc_dev, "errs", &sc->sc_errcnt); 223*59215Storek 22455139Storek ifp->if_unit = sc->sc_dev.dv_unit; 22555139Storek ifp->if_name = "le"; 22655139Storek ifp->if_mtu = ETHERMTU; 22755139Storek ifp->if_init = leinit; 22855139Storek ifp->if_ioctl = leioctl; 22955139Storek ifp->if_output = ether_output; 23055139Storek ifp->if_start = lestart; 23155139Storek ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 23255139Storek #ifdef IFF_NOTRAILERS 23355139Storek /* XXX still compile when the blasted things are gone... */ 23455139Storek ifp->if_flags |= IFF_NOTRAILERS; 23555139Storek #endif 23655139Storek #if NBPFILTER > 0 23755139Storek bpfattach(&sc->sc_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header)); 23855139Storek #endif 23955139Storek if_attach(ifp); 240*59215Storek 241*59215Storek #define SAME_LANCE(bp, sa) \ 242*59215Storek ((bp->val[0] == sa->sa_slot && bp->val[1] == sa->sa_offset) || \ 243*59215Storek (bp->val[0] == -1 && bp->val[1] == sc->sc_dev.dv_unit)) 244*59215Storek 245*59215Storek bp = sa->sa_ra.ra_bp; 246*59215Storek if (bp != NULL && strcmp(bp->name, "le") == 0 && SAME_LANCE(bp, sa)) 247*59215Storek bootdv = &sc->sc_dev; 24855139Storek } 24955139Storek 25055139Storek /* 25155139Storek * Setup the logical address filter 25255139Storek */ 25355139Storek void 25455139Storek lesetladrf(sc) 25555139Storek register struct le_softc *sc; 25655139Storek { 25755139Storek register volatile struct lereg2 *ler2 = sc->sc_r2; 25855139Storek register struct ifnet *ifp = &sc->sc_if; 25955139Storek register struct ether_multi *enm; 260*59215Storek register u_char *cp, c; 26155139Storek register u_long crc; 26255139Storek register int i, len; 26355139Storek struct ether_multistep step; 26455139Storek 26555139Storek /* 26655139Storek * Set up multicast address filter by passing all multicast 26755139Storek * addresses through a crc generator, and then using the high 26855139Storek * order 6 bits as a index into the 64 bit logical address 26955139Storek * filter. The high order two bits select the word, while the 27055139Storek * rest of the bits select the bit within the word. 27155139Storek */ 27255139Storek 27355139Storek ler2->ler2_ladrf[0] = 0; 27455139Storek ler2->ler2_ladrf[1] = 0; 27555139Storek ifp->if_flags &= ~IFF_ALLMULTI; 27655139Storek ETHER_FIRST_MULTI(step, &sc->sc_ac, enm); 27755139Storek while (enm != NULL) { 27855139Storek if (bcmp((caddr_t)&enm->enm_addrlo, 279*59215Storek (caddr_t)&enm->enm_addrhi, sizeof(enm->enm_addrlo)) != 0) { 28055139Storek /* 28155139Storek * We must listen to a range of multicast 28255139Storek * addresses. For now, just accept all 28355139Storek * multicasts, rather than trying to set only 28455139Storek * those filter bits needed to match the range. 28555139Storek * (At this time, the only use of address 28655139Storek * ranges is for IP multicast routing, for 28755139Storek * which the range is big enough to require all 28855139Storek * bits set.) 28955139Storek */ 29055139Storek ler2->ler2_ladrf[0] = 0xffffffff; 29155139Storek ler2->ler2_ladrf[1] = 0xffffffff; 29255139Storek ifp->if_flags |= IFF_ALLMULTI; 29355139Storek return; 29455139Storek } 29555139Storek 296*59215Storek /* 297*59215Storek * One would think, given the AM7990 document's polynomial 298*59215Storek * of 0x04c11db6, that this should be 0x6db88320 (the bit 299*59215Storek * reversal of the AMD value), but that is not right. See 300*59215Storek * the BASIC listing: bit 0 (our bit 31) must then be set. 301*59215Storek */ 30255139Storek cp = (unsigned char *)&enm->enm_addrlo; 30355139Storek crc = 0xffffffff; 304*59215Storek for (len = 6; --len >= 0;) { 305*59215Storek c = *cp++; 30655139Storek for (i = 0; i < 8; i++) { 30755139Storek if ((c & 0x01) ^ (crc & 0x01)) { 30855139Storek crc >>= 1; 30955139Storek crc = crc ^ 0xedb88320; 310*59215Storek } else 31155139Storek crc >>= 1; 31255139Storek c >>= 1; 31355139Storek } 31455139Storek } 31555139Storek /* Just want the 6 most significant bits. */ 31655139Storek crc = crc >> 26; 31755139Storek 31855139Storek /* Turn on the corresponding bit in the filter. */ 31955139Storek ler2->ler2_ladrf[crc >> 5] |= 1 << (crc & 0x1f); 32055139Storek 32155139Storek ETHER_NEXT_MULTI(step, enm); 32255139Storek } 32355139Storek } 32455139Storek 32555139Storek void 32655139Storek lereset(dev) 32755139Storek struct device *dev; 32855139Storek { 32955139Storek register struct le_softc *sc = (struct le_softc *)dev; 33055139Storek register volatile struct lereg1 *ler1 = sc->sc_r1; 33155139Storek register volatile struct lereg2 *ler2 = sc->sc_r2; 33255139Storek register int i, a, timo, stat; 33355139Storek 33455139Storek #if NBPFILTER > 0 33555139Storek if (sc->sc_if.if_flags & IFF_PROMISC) 33655139Storek ler2->ler2_mode = LE_MODE_NORMAL | LE_MODE_PROM; 33755139Storek else 33855139Storek #endif 33955139Storek ler2->ler2_mode = LE_MODE_NORMAL; 34055139Storek ler1->ler1_rap = LE_CSR0; 34155139Storek ler1->ler1_rdp = LE_C0_STOP; 34255139Storek 34355139Storek /* Setup the logical address filter */ 34455139Storek lesetladrf(sc); 34555139Storek 34655139Storek /* init receive and transmit rings */ 34755139Storek a = LANCE_ADDR(&ler2->ler2_rbuf[0][0]); 34855139Storek if (!ISQUADALIGN(a)) 34955139Storek printf("rbuf not quad aligned (0x%x)\n", a); 35055139Storek for (i = 0; i < LERBUF; i++) { 35155139Storek a = LANCE_ADDR(&ler2->ler2_rbuf[i][0]); 35255139Storek ler2->ler2_rmd[i].rmd0 = a; 35355139Storek ler2->ler2_rmd[i].rmd1_hadr = a >> 16; 35455139Storek ler2->ler2_rmd[i].rmd1_bits = LE_R1_OWN; 35555139Storek ler2->ler2_rmd[i].rmd2 = -LEMTU; 35655139Storek ler2->ler2_rmd[i].rmd3 = 0; 35755139Storek } 35855139Storek a = LANCE_ADDR(&ler2->ler2_tbuf[0][0]); 35955139Storek if (!ISQUADALIGN(a)) 36055139Storek printf("tbuf not quad aligned (0x%x)\n", a); 36155139Storek for (i = 0; i < LETBUF; i++) { 36255139Storek a = LANCE_ADDR(&ler2->ler2_tbuf[i][0]); 36355139Storek ler2->ler2_tmd[i].tmd0 = a; 36455139Storek ler2->ler2_tmd[i].tmd1_hadr = a >> 16; 36555139Storek ler2->ler2_tmd[i].tmd1_bits = 0; 36655139Storek ler2->ler2_tmd[i].tmd2 = 0; 36755139Storek ler2->ler2_tmd[i].tmd3 = 0; 36855139Storek } 36955139Storek 37055139Storek bzero(&ler2->ler2_rbuf[0][0], (LERBUF + LETBUF) * LEMTU); 37155139Storek /* lance will stuff packet into receive buffer 0 next */ 37255139Storek sc->sc_rmd = 0; 37355139Storek 37455139Storek /* tell the chip where to find the initialization block */ 37555139Storek a = LANCE_ADDR(&ler2->ler2_mode); 37655139Storek ler1->ler1_rap = LE_CSR1; 37755139Storek ler1->ler1_rdp = a; 37855139Storek ler1->ler1_rap = LE_CSR2; 37955139Storek ler1->ler1_rdp = a >> 16; 38055139Storek ler1->ler1_rap = LE_CSR3; 38155139Storek ler1->ler1_rdp = LE_C3_BSWP | LE_C3_ACON | LE_C3_BCON; 38255139Storek ler1->ler1_rap = LE_CSR0; 38355139Storek ler1->ler1_rdp = LE_C0_INIT; 38455139Storek timo = 100000; 38555139Storek while (((stat = ler1->ler1_rdp) & (LE_C0_ERR | LE_C0_IDON)) == 0) { 38655139Storek if (--timo == 0) { 38755139Storek printf("%s: init timeout, stat=%b\n", 38855139Storek sc->sc_dev.dv_xname, stat, LE_C0_BITS); 38955139Storek break; 39055139Storek } 39155139Storek } 39255139Storek if (stat & LE_C0_ERR) 39355139Storek printf("%s: init failed, stat=%b\n", 39455139Storek sc->sc_dev.dv_xname, stat, LE_C0_BITS); 39555139Storek else 39655139Storek ler1->ler1_rdp = LE_C0_IDON; /* clear IDON */ 39755139Storek ler1->ler1_rdp = LE_C0_STRT | LE_C0_INEA; 39855139Storek sc->sc_if.if_flags &= ~IFF_OACTIVE; 39955139Storek } 40055139Storek 40155139Storek /* 40255139Storek * Initialization of interface 40355139Storek */ 40455139Storek int 40555139Storek leinit(unit) 40655139Storek int unit; 40755139Storek { 40855139Storek register struct le_softc *sc = lecd.cd_devs[unit]; 40955139Storek register struct ifnet *ifp = &sc->sc_if; 41055139Storek register int s; 41155139Storek 41255139Storek /* not yet, if address still unknown */ 41355139Storek if (ifp->if_addrlist == (struct ifaddr *)0) 41455139Storek return (0); 41555139Storek if ((ifp->if_flags & IFF_RUNNING) == 0) { 41655139Storek s = splimp(); 41755139Storek ifp->if_flags |= IFF_RUNNING; 41855139Storek lereset((struct device *)sc); 41955139Storek lestart(ifp); 42055139Storek splx(s); 42155139Storek } 42255139Storek return (0); 42355139Storek } 42455139Storek 42555139Storek /* 42655139Storek * Start output on interface. Get another datagram to send 42755139Storek * off of the interface queue, and copy it to the interface 42855139Storek * before starting the output. 42955139Storek */ 43055139Storek int 43155139Storek lestart(ifp) 43255139Storek register struct ifnet *ifp; 43355139Storek { 43455139Storek register struct le_softc *sc = lecd.cd_devs[ifp->if_unit]; 43555139Storek register volatile struct letmd *tmd; 43655139Storek register struct mbuf *m; 43755139Storek register int len; 43855139Storek 43955139Storek if ((sc->sc_if.if_flags & IFF_RUNNING) == 0) 44055139Storek return (0); 44155139Storek IF_DEQUEUE(&sc->sc_if.if_snd, m); 44255139Storek if (m == 0) 44355139Storek return (0); 44455139Storek len = leput(sc->sc_r2->ler2_tbuf[0], m); 44555139Storek #if NBPFILTER > 0 44655139Storek /* 44755139Storek * If bpf is listening on this interface, let it 44855139Storek * see the packet before we commit it to the wire. 44955139Storek */ 45055139Storek if (sc->sc_bpf) 45155139Storek bpf_tap(sc->sc_bpf, sc->sc_r2->ler2_tbuf[0], len); 45255139Storek #endif 45355139Storek 45455139Storek #ifdef PACKETSTATS 45555139Storek if (len <= LEMTU) 45655139Storek lexpacketsizes[len]++; 45755139Storek #endif 45855139Storek tmd = sc->sc_r2->ler2_tmd; 45955139Storek tmd->tmd3 = 0; 46055139Storek tmd->tmd2 = -len; 46155139Storek tmd->tmd1_bits = LE_T1_OWN | LE_T1_STP | LE_T1_ENP; 46255139Storek sc->sc_if.if_flags |= IFF_OACTIVE; 46355139Storek return (0); 46455139Storek } 46555139Storek 46655139Storek int 46755139Storek leintr(dev) 46855139Storek register void *dev; 46955139Storek { 47055139Storek register struct le_softc *sc = dev; 47155139Storek register volatile struct lereg1 *ler1 = sc->sc_r1; 47255139Storek register int csr0; 47355139Storek 47455139Storek csr0 = ler1->ler1_rdp; 47555139Storek if ((csr0 & LE_C0_INTR) == 0) 47655139Storek return (0); 477*59215Storek sc->sc_intrcnt.ev_count++; 47855139Storek 47955139Storek if (csr0 & LE_C0_ERR) { 480*59215Storek sc->sc_errcnt.ev_count++; 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. 686*59215Storek * If so, hand off the raw packet to enet, then discard things 687*59215Storek * not destined for us (but be sure to keep broadcast/multicast). 68855139Storek */ 68955139Storek if (sc->sc_bpf) { 69055139Storek bpf_tap(sc->sc_bpf, pkt, len + sizeof(struct ether_header)); 691*59215Storek if ((flags & (M_BCAST | M_MCAST)) == 0 && 69255139Storek bcmp(et->ether_dhost, sc->sc_addr, 693*59215Storek sizeof(et->ether_dhost)) != 0) 69455139Storek return; 69555139Storek } 69655139Storek #endif 69755139Storek m = leget(pkt, len, 0, ifp); 69855139Storek if (m == 0) 69955139Storek return; 70055139Storek 70155139Storek /* XXX this code comes from ether_input() */ 70255139Storek ifp->if_lastchange = time; 70355139Storek ifp->if_ibytes += m->m_pkthdr.len + sizeof (*et); 70455139Storek if (flags) { 70555139Storek m->m_flags |= flags; 70655139Storek ifp->if_imcasts++; 70755139Storek } 70855139Storek /* XXX end of code from ether_input() */ 70955139Storek 71055139Storek switch (et->ether_type) { 71155139Storek 71255139Storek #ifdef INET 71355139Storek case ETHERTYPE_IP: 71455139Storek schednetisr(NETISR_IP); 71555139Storek inq = &ipintrq; 71655139Storek break; 71755139Storek 71855139Storek case ETHERTYPE_ARP: 71955139Storek schednetisr(NETISR_ARP); 72055139Storek inq = &arpintrq; 72155139Storek break; 72255139Storek #endif 72355139Storek #ifdef NS 72455139Storek case ETHERTYPE_NS: 72555139Storek schednetisr(NETISR_NS); 72655139Storek inq = &nsintrq; 72755139Storek break; 72855139Storek #endif 72955139Storek 73055139Storek #ifdef UTAHONLY 73155139Storek #ifdef APPLETALK 73255139Storek case ETHERTYPE_APPLETALK: 73355139Storek schednetisr(NETISR_DDP); 73455139Storek inq = &ddpintq; 73555139Storek break; 73655139Storek 73755139Storek case ETHERTYPE_AARP: 73855139Storek aarpinput(&sc->sc_ac, m); 73955139Storek return; 74055139Storek #endif 74155139Storek #endif 74255139Storek default: 74355139Storek m_freem(m); 74455139Storek return; 74555139Storek } 74655139Storek 74755139Storek if (IF_QFULL(inq)) { 74855139Storek IF_DROP(inq); 74955139Storek m_freem(m); 75055139Storek return; 75155139Storek } 75255139Storek IF_ENQUEUE(inq, m); 75355139Storek } 75455139Storek 75555139Storek /* 75655139Storek * Routine to copy from mbuf chain to transmit 75755139Storek * buffer in board local memory. 75855139Storek * 75955139Storek * ### this can be done by remapping in some cases 76055139Storek */ 76155139Storek int 76255139Storek leput(lebuf, m) 76355139Storek register char *lebuf; 76455139Storek register struct mbuf *m; 76555139Storek { 76655139Storek register struct mbuf *mp; 76755139Storek register int len, tlen = 0; 76855139Storek 76955139Storek for (mp = m; mp; mp = mp->m_next) { 77055139Storek len = mp->m_len; 77155139Storek if (len == 0) 77255139Storek continue; 77355139Storek tlen += len; 77455139Storek bcopy(mtod(mp, char *), lebuf, len); 77555139Storek lebuf += len; 77655139Storek } 77755139Storek m_freem(m); 77855139Storek if (tlen < LEMINSIZE) { 77955139Storek bzero(lebuf, LEMINSIZE - tlen); 78055139Storek tlen = LEMINSIZE; 78155139Storek } 78255139Storek return (tlen); 78355139Storek } 78455139Storek 78555139Storek /* 78655139Storek * Routine to copy from board local memory into mbufs. 78755139Storek */ 78855139Storek struct mbuf * 78955139Storek leget(lebuf, totlen, off0, ifp) 79055139Storek char *lebuf; 79155139Storek int totlen, off0; 79255139Storek struct ifnet *ifp; 79355139Storek { 79455139Storek register struct mbuf *m; 79555139Storek struct mbuf *top = 0, **mp = ⊤ 79655139Storek register int off = off0, len; 79755139Storek register char *cp; 79855139Storek char *epkt; 79955139Storek 80055139Storek lebuf += sizeof(struct ether_header); 80155139Storek cp = lebuf; 80255139Storek epkt = cp + totlen; 80355139Storek if (off) { 80455139Storek cp += off + 2 * sizeof(u_short); 80555139Storek totlen -= 2 * sizeof(u_short); 80655139Storek } 80755139Storek 80855139Storek MGETHDR(m, M_DONTWAIT, MT_DATA); 80955139Storek if (m == 0) 81055139Storek return (0); 81155139Storek m->m_pkthdr.rcvif = ifp; 81255139Storek m->m_pkthdr.len = totlen; 81355139Storek m->m_len = MHLEN; 81455139Storek 81555139Storek while (totlen > 0) { 81655139Storek if (top) { 81755139Storek MGET(m, M_DONTWAIT, MT_DATA); 81855139Storek if (m == 0) { 81955139Storek m_freem(top); 82055139Storek return (0); 82155139Storek } 82255139Storek m->m_len = MLEN; 82355139Storek } 82455139Storek len = min(totlen, epkt - cp); 82555139Storek if (len >= MINCLSIZE) { 82655139Storek MCLGET(m, M_DONTWAIT); 82755139Storek if (m->m_flags & M_EXT) 82855139Storek m->m_len = len = min(len, MCLBYTES); 82955139Storek else 83055139Storek len = m->m_len; 83155139Storek } else { 83255139Storek /* 83355139Storek * Place initial small packet/header at end of mbuf. 83455139Storek */ 83555139Storek if (len < m->m_len) { 83655139Storek if (top == 0 && len + max_linkhdr <= m->m_len) 83755139Storek m->m_data += max_linkhdr; 83855139Storek m->m_len = len; 83955139Storek } else 84055139Storek len = m->m_len; 84155139Storek } 84255139Storek bcopy(cp, mtod(m, caddr_t), (unsigned)len); 84355139Storek cp += len; 84455139Storek *mp = m; 84555139Storek mp = &m->m_next; 84655139Storek totlen -= len; 84755139Storek if (cp == epkt) 84855139Storek cp = lebuf; 84955139Storek } 85055139Storek return (top); 85155139Storek } 85255139Storek 85355139Storek /* 85455139Storek * Process an ioctl request. 85555139Storek */ 85655139Storek int 85755139Storek leioctl(ifp, cmd, data) 85855139Storek register struct ifnet *ifp; 85955139Storek int cmd; 86055139Storek caddr_t data; 86155139Storek { 86255139Storek register struct ifaddr *ifa; 86355139Storek register struct le_softc *sc = lecd.cd_devs[ifp->if_unit]; 86455139Storek register volatile struct lereg1 *ler1; 86555139Storek int s = splimp(), error = 0; 86655139Storek 86755139Storek switch (cmd) { 86855139Storek 86955139Storek case SIOCSIFADDR: 87055139Storek ifa = (struct ifaddr *)data; 87155139Storek ifp->if_flags |= IFF_UP; 87255139Storek switch (ifa->ifa_addr->sa_family) { 87355139Storek #ifdef INET 87455139Storek case AF_INET: 87555139Storek (void)leinit(ifp->if_unit); /* before arpwhohas */ 87655139Storek ((struct arpcom *)ifp)->ac_ipaddr = 87755139Storek IA_SIN(ifa)->sin_addr; 87855139Storek arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr); 87955139Storek break; 88055139Storek #endif 88155139Storek #ifdef NS 88255139Storek case AF_NS: 88355139Storek { 88455139Storek register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr); 88555139Storek 88655139Storek if (ns_nullhost(*ina)) 88755139Storek ina->x_host = *(union ns_host *)(sc->sc_addr); 88855139Storek else { 88955139Storek /* 89055139Storek * The manual says we can't change the address 89155139Storek * while the receiver is armed, 89255139Storek * so reset everything 89355139Storek */ 89455139Storek ifp->if_flags &= ~IFF_RUNNING; 89555139Storek bcopy((caddr_t)ina->x_host.c_host, 89655139Storek (caddr_t)sc->sc_addr, sizeof(sc->sc_addr)); 89755139Storek } 89855139Storek (void)leinit(ifp->if_unit); /* does le_setaddr() */ 89955139Storek break; 90055139Storek } 90155139Storek #endif 90255139Storek default: 90355139Storek (void)leinit(ifp->if_unit); 90455139Storek break; 90555139Storek } 90655139Storek break; 90755139Storek 90855139Storek case SIOCSIFFLAGS: 90955139Storek ler1 = sc->sc_r1; 91055139Storek if ((ifp->if_flags & IFF_UP) == 0 && 91155139Storek ifp->if_flags & IFF_RUNNING) { 91255139Storek ler1->ler1_rdp = LE_C0_STOP; 91355139Storek ifp->if_flags &= ~IFF_RUNNING; 91455139Storek } else if (ifp->if_flags & IFF_UP && 91555139Storek (ifp->if_flags & IFF_RUNNING) == 0) 91655139Storek (void)leinit(ifp->if_unit); 91755139Storek /* 91855139Storek * If the state of the promiscuous bit changes, the interface 91955139Storek * must be reset to effect the change. 92055139Storek */ 92155139Storek if (((ifp->if_flags ^ sc->sc_iflags) & IFF_PROMISC) && 92255139Storek (ifp->if_flags & IFF_RUNNING)) { 92355139Storek sc->sc_iflags = ifp->if_flags; 92455139Storek lereset((struct device *)sc); 92555139Storek lestart(ifp); 92655139Storek } 92755139Storek break; 92855139Storek 92955139Storek case SIOCADDMULTI: 930*59215Storek error = ether_addmulti((struct ifreq *)data, &sc->sc_ac); 931*59215Storek goto update_multicast; 932*59215Storek 93355139Storek case SIOCDELMULTI: 934*59215Storek error = ether_delmulti((struct ifreq *)data, &sc->sc_ac); 935*59215Storek update_multicast: 93655139Storek if (error == ENETRESET) { 93755139Storek /* 93855139Storek * Multicast list has changed; set the hardware 93955139Storek * filter accordingly. 94055139Storek */ 94155139Storek lereset((struct device *)sc); 94255139Storek error = 0; 94355139Storek } 94455139Storek break; 94555139Storek 94655139Storek default: 94755139Storek error = EINVAL; 94855139Storek } 94955139Storek splx(s); 95055139Storek return (error); 95155139Storek } 95255139Storek 95355139Storek void 95455139Storek leerror(sc, stat) 95555139Storek register struct le_softc *sc; 95655139Storek int stat; 95755139Storek { 95855139Storek if (!ledebug) 95955139Storek return; 96055139Storek 96155139Storek /* 96255139Storek * Not all transceivers implement heartbeat 96355139Storek * so we only log CERR once. 96455139Storek */ 96555139Storek if ((stat & LE_C0_CERR) && sc->sc_cerr) 96655139Storek return; 96755139Storek log(LOG_WARNING, "%s: error: stat=%b\n", 96855139Storek sc->sc_dev.dv_xname, stat, LE_C0_BITS); 96955139Storek } 97055139Storek 97155139Storek void 97255139Storek lererror(sc, msg) 97355139Storek register struct le_softc *sc; 97455139Storek char *msg; 97555139Storek { 97655139Storek register volatile struct lermd *rmd; 97755139Storek int len; 97855139Storek 97955139Storek if (!ledebug) 98055139Storek return; 98155139Storek 98255139Storek rmd = &sc->sc_r2->ler2_rmd[sc->sc_rmd]; 98355139Storek len = rmd->rmd3; 98455139Storek log(LOG_WARNING, "%s: ierror(%s): from %s: buf=%d, len=%d, rmd1=%b\n", 98555139Storek sc->sc_dev.dv_xname, msg, len > 11 ? 98655139Storek ether_sprintf((u_char *)&sc->sc_r2->ler2_rbuf[sc->sc_rmd][6]) : 98755139Storek "unknown", 98855139Storek sc->sc_rmd, len, rmd->rmd1_bits, LE_R1_BITS); 98955139Storek } 99055139Storek 99155139Storek void 99255139Storek lexerror(sc) 99355139Storek register struct le_softc *sc; 99455139Storek { 99555139Storek register volatile struct letmd *tmd; 99655139Storek register int len, tmd3, tdr; 99755139Storek 99855139Storek if (!ledebug) 99955139Storek return; 100055139Storek 100155139Storek tmd = sc->sc_r2->ler2_tmd; 100255139Storek tmd3 = tmd->tmd3; 100355139Storek tdr = tmd3 & LE_T3_TDR_MASK; 100455139Storek len = -tmd->tmd2; 100555139Storek log(LOG_WARNING, 100655139Storek "%s: oerror: to %s: buf=%d, len=%d, tmd1=%b, tmd3=%b, tdr=%d (%d nsecs)\n", 100755139Storek sc->sc_dev.dv_xname, len > 5 ? 100855139Storek ether_sprintf((u_char *)&sc->sc_r2->ler2_tbuf[0][0]) : "unknown", 100955139Storek 0, len, 101055139Storek tmd->tmd1_bits, LE_T1_BITS, 101155139Storek tmd3, LE_T3_BITS, tdr, tdr * 100); 101255139Storek } 1013