154000Sfujita /* 255582Sfujita * Copyright (c) 1982, 1990 The Regents of the University of California. 354000Sfujita * All rights reserved. 454000Sfujita * 554000Sfujita * %sccs.include.redist.c% 654000Sfujita * 755582Sfujita * from: hp300/dev/if_le.c 7.12 (Berkeley) 7/6/92 855582Sfujita * 9*56519Sbostic * @(#)if_le.c 7.3 (Berkeley) 10/11/92 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 */ 25*56519Sbostic #include <sys/param.h> 26*56519Sbostic #include <sys/proc.h> 27*56519Sbostic #include <sys/systm.h> 28*56519Sbostic #include <sys/mbuf.h> 29*56519Sbostic #include <sys/buf.h> 30*56519Sbostic #include <sys/protosw.h> 31*56519Sbostic #include <sys/socket.h> 32*56519Sbostic #include <sys/syslog.h> 33*56519Sbostic #include <sys/ioctl.h> 34*56519Sbostic #include <sys/errno.h> 3554000Sfujita 36*56519Sbostic #include <net/if.h> 37*56519Sbostic #include <net/netisr.h> 38*56519Sbostic #include <net/route.h> 3954000Sfujita 4054000Sfujita #ifdef INET 41*56519Sbostic #include <netinet/in.h> 42*56519Sbostic #include <netinet/in_systm.h> 43*56519Sbostic #include <netinet/in_var.h> 44*56519Sbostic #include <netinet/ip.h> 45*56519Sbostic #include <netinet/if_ether.h> 4654000Sfujita #endif 4754000Sfujita 4854000Sfujita #ifdef NS 49*56519Sbostic #include <netns/ns.h> 50*56519Sbostic #include <netns/ns_if.h> 5154000Sfujita #endif 5254000Sfujita 53*56519Sbostic #include <machine/cpu.h> 54*56519Sbostic #include <machine/mtpr.h> 55*56519Sbostic #include <luna68k/dev/device.h> 56*56519Sbostic #include <luna68k/dev/if_lereg.h> 5754000Sfujita 5854000Sfujita #if NBPFILTER > 0 59*56519Sbostic #include <net/bpf.h> 60*56519Sbostic #include <net/bpfdesc.h> 6154000Sfujita #endif 6254000Sfujita 6354000Sfujita int leattach(); 6454000Sfujita struct driver ledriver = { 6554000Sfujita leattach, "le", 6654000Sfujita }; 6754000Sfujita 6854000Sfujita int ledebug = 0; /* console error messages */ 6954000Sfujita 7054000Sfujita int leintr(), leinit(), leioctl(), lestart(), ether_output(); 7154000Sfujita struct mbuf *m_devget(); 7254000Sfujita extern struct ifnet loif; 7354000Sfujita 7454000Sfujita /* 7554000Sfujita * Ethernet software status per interface. 7654000Sfujita * 7754000Sfujita * Each interface is referenced by a network interface structure, 7854000Sfujita * le_if, which the routing code uses to locate the interface. 7954000Sfujita * This structure contains the output queue for the interface, its address, ... 8054000Sfujita */ 8154000Sfujita struct le_softc { 8254000Sfujita struct arpcom sc_ac; /* common Ethernet structures */ 8354000Sfujita #define sc_if sc_ac.ac_if /* network-visible interface */ 8454000Sfujita #define sc_addr sc_ac.ac_enaddr /* hardware Ethernet address */ 8554000Sfujita struct lereg1 *sc_r1; /* LANCE registers */ 8654000Sfujita struct lereg2 *sc_r2; /* dual-port RAM */ 8754000Sfujita int sc_rmd; /* predicted next rmd to process */ 8855582Sfujita int sc_tmd; /* next available tmd */ 8955582Sfujita int sc_txcnt; /* # of transmit buffers in use */ 9055582Sfujita /* stats */ 9154000Sfujita int sc_runt; 9254000Sfujita int sc_jab; 9354000Sfujita int sc_merr; 9454000Sfujita int sc_babl; 9554000Sfujita int sc_cerr; 9654000Sfujita int sc_miss; 9755582Sfujita int sc_rown; 9854000Sfujita int sc_xown; 9955582Sfujita int sc_xown2; 10054000Sfujita int sc_uflo; 10154000Sfujita int sc_rxlen; 10254000Sfujita int sc_rxoff; 10354000Sfujita int sc_txoff; 10454000Sfujita int sc_busy; 10554000Sfujita short sc_iflags; 10654000Sfujita } le_softc[NLE]; 10754000Sfujita 10854000Sfujita /* access LANCE registers */ 10954000Sfujita #define LERDWR(cntl, src, dst) (dst) = (src) 11054000Sfujita 11154000Sfujita #define LE_IPL 3 11254000Sfujita 11354000Sfujita /* 11454000Sfujita * Interface exists: make available by filling in network interface 11554000Sfujita * record. System will initialize the interface when it is ready 11654000Sfujita * to accept packets. 11754000Sfujita */ 11854000Sfujita leattach(hd) 11954000Sfujita struct hp_device *hd; 12054000Sfujita { 12154000Sfujita register struct lereg2 *ler2; 12254000Sfujita struct lereg2 *lemem = (struct lereg2 *) 0; 12354000Sfujita struct le_softc *le = &le_softc[hd->hp_unit]; 12454000Sfujita struct ifnet *ifp = &le->sc_if; 12554000Sfujita char *cp; 12654000Sfujita int i; 12754000Sfujita 12854000Sfujita le->sc_r1 = (struct lereg1 *) hd->hp_addr; 12954000Sfujita ler2 = le->sc_r2 = (struct lereg2 *) 0x71000000; 13054000Sfujita 13154000Sfujita hd->hp_ipl = LE_IPL; 13254000Sfujita 13354000Sfujita /* 13454000Sfujita * Read the ethernet address off the board, one nibble at a time. 13554000Sfujita */ 13654000Sfujita #ifdef NOROM 13754000Sfujita cp = "00000a02456c"; 13854000Sfujita #else 13954000Sfujita cp = (char *) 0x4101FFE0; 14054000Sfujita #endif 14154000Sfujita for (i = 0; i < sizeof(le->sc_addr); i++) { 14254000Sfujita le->sc_addr[i] = (*cp < 'A' ? (*cp & 0xF) : (*cp & 0xF) + 9) << 4; 14354000Sfujita cp++; 14454000Sfujita le->sc_addr[i] |= (*cp < 'A' ? (*cp & 0xF) : (*cp & 0xF) + 9); 14554000Sfujita cp++; 14654000Sfujita } 14754000Sfujita printf("le%d: hardware address %s\n", hd->hp_unit, 14854000Sfujita ether_sprintf(le->sc_addr)); 14954000Sfujita 15054000Sfujita /* 15154000Sfujita * Setup for transmit/receive 15254000Sfujita */ 15354000Sfujita ler2->ler2_mode = LE_MODE; 15455582Sfujita ler2->ler2_ladrf[0] = 0; 15555582Sfujita ler2->ler2_ladrf[1] = 0; 15654000Sfujita ler2->ler2_rlen = LE_RLEN; 15754000Sfujita ler2->ler2_rdra = (int)lemem->ler2_rmd; 15854000Sfujita ler2->ler2_tlen = LE_TLEN; 15954000Sfujita ler2->ler2_tdra = (int)lemem->ler2_tmd; 16054000Sfujita 16154000Sfujita ifp->if_unit = hd->hp_unit; 16254000Sfujita ifp->if_name = "le"; 16354000Sfujita ifp->if_mtu = ETHERMTU; 16454000Sfujita ifp->if_init = leinit; 16554000Sfujita ifp->if_ioctl = leioctl; 16654000Sfujita ifp->if_output = ether_output; 16754000Sfujita ifp->if_start = lestart; 16855582Sfujita #ifdef MULTICAST 16955582Sfujita ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 17055582Sfujita #else 17154000Sfujita ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX; 17255582Sfujita #endif 17354000Sfujita #if NBPFILTER > 0 17455582Sfujita bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header)); 17554000Sfujita #endif 17654000Sfujita if_attach(ifp); 17754000Sfujita return (1); 17854000Sfujita } 17954000Sfujita 18055582Sfujita #ifdef MULTICAST 18155582Sfujita /* 18255582Sfujita * Setup the logical address filter 18355582Sfujita */ 18455582Sfujita void 18555582Sfujita lesetladrf(sc) 18655582Sfujita register struct le_softc *sc; 18755582Sfujita { 18855582Sfujita register volatile struct lereg2 *ler2 = sc->sc_r2; 18955582Sfujita register struct ifnet *ifp = &sc->sc_if; 19055582Sfujita register struct ether_multi *enm; 19155582Sfujita register u_char *cp; 19255582Sfujita register u_long crc; 19355582Sfujita register u_long c; 19455582Sfujita register int i, len; 19555582Sfujita struct ether_multistep step; 19655582Sfujita 19755582Sfujita /* 19855582Sfujita * Set up multicast address filter by passing all multicast 19955582Sfujita * addresses through a crc generator, and then using the high 20055582Sfujita * order 6 bits as a index into the 64 bit logical address 20155582Sfujita * filter. The high order two bits select the word, while the 20255582Sfujita * rest of the bits select the bit within the word. 20355582Sfujita */ 20455582Sfujita 20555582Sfujita ler2->ler2_ladrf[0] = 0; 20655582Sfujita ler2->ler2_ladrf[1] = 0; 20755582Sfujita ifp->if_flags &= ~IFF_ALLMULTI; 20855582Sfujita ETHER_FIRST_MULTI(step, &sc->sc_ac, enm); 20955582Sfujita while (enm != NULL) { 21055582Sfujita if (bcmp((caddr_t)&enm->enm_addrlo, 21155582Sfujita (caddr_t)&enm->enm_addrhi, sizeof(enm->enm_addrlo)) == 0) { 21255582Sfujita /* 21355582Sfujita * We must listen to a range of multicast 21455582Sfujita * addresses. For now, just accept all 21555582Sfujita * multicasts, rather than trying to set only 21655582Sfujita * those filter bits needed to match the range. 21755582Sfujita * (At this time, the only use of address 21855582Sfujita * ranges is for IP multicast routing, for 21955582Sfujita * which the range is big enough to require all 22055582Sfujita * bits set.) 22155582Sfujita */ 22255582Sfujita ler2->ler2_ladrf[0] = 0xffffffff; 22355582Sfujita ler2->ler2_ladrf[1] = 0xffffffff; 22455582Sfujita ifp->if_flags |= IFF_ALLMULTI; 22555582Sfujita return; 22655582Sfujita } 22755582Sfujita 22855582Sfujita cp = (unsigned char *)&enm->enm_addrlo; 22955582Sfujita c = *cp; 23055582Sfujita crc = 0xffffffff; 23155582Sfujita len = 6; 23255582Sfujita while (len-- > 0) { 23355582Sfujita c = *cp; 23455582Sfujita for (i = 0; i < 8; i++) { 23555582Sfujita if ((c & 0x01) ^ (crc & 0x01)) { 23655582Sfujita crc >>= 1; 23755582Sfujita crc = crc ^ 0xedb88320; 23855582Sfujita } 23955582Sfujita else 24055582Sfujita crc >>= 1; 24155582Sfujita c >>= 1; 24255582Sfujita } 24355582Sfujita cp++; 24455582Sfujita } 24555582Sfujita /* Just want the 6 most significant bits. */ 24655582Sfujita crc = crc >> 26; 24755582Sfujita 24855582Sfujita /* Turn on the corresponding bit in the filter. */ 24955582Sfujita ler2->ler2_ladrf[crc >> 5] |= 1 << (crc & 0x1f); 25055582Sfujita 25155582Sfujita ETHER_NEXT_MULTI(step, enm); 25255582Sfujita } 25355582Sfujita } 25455582Sfujita #endif 25555582Sfujita 25654000Sfujita ledrinit(ler2, le) 25754000Sfujita register struct lereg2 *ler2; 25854000Sfujita register struct le_softc *le; 25954000Sfujita { 26054000Sfujita register struct lereg2 *lemem = (struct lereg2 *) 0; 26154000Sfujita register int i; 26254000Sfujita 26354000Sfujita ler2->ler2_padr[0] = le->sc_addr[1]; 26454000Sfujita ler2->ler2_padr[1] = le->sc_addr[0]; 26554000Sfujita ler2->ler2_padr[2] = le->sc_addr[3]; 26654000Sfujita ler2->ler2_padr[3] = le->sc_addr[2]; 26754000Sfujita ler2->ler2_padr[4] = le->sc_addr[5]; 26854000Sfujita ler2->ler2_padr[5] = le->sc_addr[4]; 26954000Sfujita for (i = 0; i < LERBUF; i++) { 27054000Sfujita ler2->ler2_rmd[i].rmd0 = (int)lemem->ler2_rbuf[i]; 27154000Sfujita ler2->ler2_rmd[i].rmd1 = LE_OWN; 27254000Sfujita ler2->ler2_rmd[i].rmd2 = -LEMTU; 27354000Sfujita ler2->ler2_rmd[i].rmd3 = 0; 27454000Sfujita } 27554000Sfujita for (i = 0; i < LETBUF; i++) { 27654000Sfujita ler2->ler2_tmd[i].tmd0 = (int)lemem->ler2_tbuf[i]; 27754000Sfujita ler2->ler2_tmd[i].tmd1 = 0; 27854000Sfujita ler2->ler2_tmd[i].tmd2 = 0; 27954000Sfujita ler2->ler2_tmd[i].tmd3 = 0; 28054000Sfujita } 28155582Sfujita /* Setup the logical address filter */ 28255582Sfujita #ifdef MULTICAST 28355582Sfujita lesetladrf(le); 28455582Sfujita #else 28555582Sfujita ler2->ler2_ladrf[0] = 0; 28655582Sfujita ler2->ler2_ladrf[1] = 0; 28755582Sfujita #endif 28854000Sfujita } 28954000Sfujita 29054000Sfujita lereset(unit) 29154000Sfujita register int unit; 29254000Sfujita { 29354000Sfujita register struct le_softc *le = &le_softc[unit]; 29454000Sfujita register struct lereg1 *ler1 = le->sc_r1; 29554000Sfujita register struct lereg2 *lemem = (struct lereg2 *) 0; 29654000Sfujita register int timo = 100000; 29754000Sfujita register int stat; 29854000Sfujita 29954000Sfujita #ifdef lint 30054000Sfujita stat = unit; 30154000Sfujita #endif 30254000Sfujita #if NBPFILTER > 0 30354000Sfujita if (le->sc_if.if_flags & IFF_PROMISC) 30454000Sfujita /* set the promiscuous bit */ 30554000Sfujita le->sc_r2->ler2_mode = LE_MODE|0x8000; 30654000Sfujita else 30754000Sfujita le->sc_r2->ler2_mode = LE_MODE; 30854000Sfujita #endif 30954000Sfujita LERDWR(ler0, LE_CSR0, ler1->ler1_rap); 31054000Sfujita LERDWR(ler0, LE_STOP, ler1->ler1_rdp); 31154000Sfujita ledrinit(le->sc_r2, le); 31255582Sfujita le->sc_rmd = le->sc_tmd = 0; 31354000Sfujita LERDWR(ler0, LE_CSR1, ler1->ler1_rap); 31454000Sfujita LERDWR(ler0, (int)&lemem->ler2_mode, ler1->ler1_rdp); 31554000Sfujita LERDWR(ler0, LE_CSR2, ler1->ler1_rap); 31654000Sfujita LERDWR(ler0, 0, ler1->ler1_rdp); 31754000Sfujita LERDWR(ler0, LE_CSR0, ler1->ler1_rap); 31854000Sfujita LERDWR(ler0, LE_INIT, ler1->ler1_rdp); 31954000Sfujita do { 32054000Sfujita if (--timo == 0) { 32154000Sfujita printf("le%d: init timeout, stat = 0x%x\n", 32254000Sfujita unit, stat); 32354000Sfujita break; 32454000Sfujita } 32554000Sfujita LERDWR(ler0, ler1->ler1_rdp, stat); 32654000Sfujita } while ((stat & LE_IDON) == 0); 32754000Sfujita LERDWR(ler0, LE_STOP, ler1->ler1_rdp); 32854000Sfujita LERDWR(ler0, LE_CSR3, ler1->ler1_rap); 32954000Sfujita LERDWR(ler0, LE_BSWP, ler1->ler1_rdp); 33054000Sfujita LERDWR(ler0, LE_CSR0, ler1->ler1_rap); 33154000Sfujita LERDWR(ler0, LE_STRT | LE_INEA, ler1->ler1_rdp); 33254000Sfujita le->sc_if.if_flags &= ~IFF_OACTIVE; 33355582Sfujita le->sc_txcnt = 0; 33454000Sfujita } 33554000Sfujita 33654000Sfujita /* 33754000Sfujita * Initialization of interface 33854000Sfujita */ 33954000Sfujita leinit(unit) 34054000Sfujita int unit; 34154000Sfujita { 34254000Sfujita register struct ifnet *ifp = &le_softc[unit].sc_if; 34354000Sfujita register struct ifaddr *ifa; 34454000Sfujita int s; 34554000Sfujita 34654000Sfujita /* not yet, if address still unknown */ 34754000Sfujita for (ifa = ifp->if_addrlist;; ifa = ifa->ifa_next) 34854000Sfujita if (ifa == 0) 34954000Sfujita return; 35054000Sfujita else if (ifa->ifa_addr && ifa->ifa_addr->sa_family != AF_LINK) 35154000Sfujita break; 35254000Sfujita if ((ifp->if_flags & IFF_RUNNING) == 0) { 35354000Sfujita s = splimp(); 35454000Sfujita ifp->if_flags |= IFF_RUNNING; 35554000Sfujita lereset(unit); 35654000Sfujita (void) lestart(ifp); 35754000Sfujita splx(s); 35854000Sfujita } 35954000Sfujita } 36054000Sfujita 36154000Sfujita /* 36254000Sfujita * Start output on interface. Get another datagram to send 36354000Sfujita * off of the interface queue, and copy it to the interface 36454000Sfujita * before starting the output. 36554000Sfujita */ 36654000Sfujita lestart(ifp) 36754000Sfujita struct ifnet *ifp; 36854000Sfujita { 36954000Sfujita register struct le_softc *le = &le_softc[ifp->if_unit]; 37054000Sfujita register struct letmd *tmd; 37154000Sfujita register struct mbuf *m; 37254000Sfujita int len; 37354000Sfujita 37454000Sfujita if ((le->sc_if.if_flags & IFF_RUNNING) == 0) 37554000Sfujita return (0); 37655582Sfujita tmd = &le->sc_r2->ler2_tmd[le->sc_tmd]; 37755582Sfujita do { 37855582Sfujita if (tmd->tmd1 & LE_OWN) { 37955582Sfujita le->sc_xown2++; 38055582Sfujita return (0); 38155582Sfujita } 38255582Sfujita IF_DEQUEUE(&le->sc_if.if_snd, m); 38355582Sfujita if (m == 0) 38455582Sfujita return (0); 38555582Sfujita len = leput(le->sc_r2->ler2_tbuf[le->sc_tmd], m); 38654000Sfujita #if NBPFILTER > 0 38755582Sfujita /* 38855582Sfujita * If bpf is listening on this interface, let it 38955582Sfujita * see the packet before we commit it to the wire. 39055582Sfujita */ 39155582Sfujita if (ifp->if_bpf) 39255582Sfujita bpf_tap(ifp->if_bpf, le->sc_r2->ler2_tbuf[le->sc_tmd], 39355582Sfujita len); 39454000Sfujita #endif 39555582Sfujita 39655582Sfujita tmd->tmd3 = 0; 39755582Sfujita tmd->tmd2 = -len; 39854000Sfujita tmd->tmd1 = LE_OWN | LE_STP | LE_ENP; 39955582Sfujita if (++le->sc_tmd == LETBUF) { 40055582Sfujita le->sc_tmd = 0; 40155582Sfujita tmd = le->sc_r2->ler2_tmd; 40255582Sfujita } else 40355582Sfujita tmd++; 40455582Sfujita } while (++le->sc_txcnt < LETBUF); 40555582Sfujita le->sc_if.if_flags |= IFF_OACTIVE; 40654000Sfujita return (0); 40754000Sfujita } 40854000Sfujita 40954000Sfujita void 41054000Sfujita _leintr() 41154000Sfujita { 41254000Sfujita register int i; 41354000Sfujita 41454000Sfujita for (i = 0; i < NLE; i++) { 41554000Sfujita leintr(i); 41654000Sfujita } 41754000Sfujita } 41854000Sfujita 41954000Sfujita int 42054000Sfujita leintr(unit) 42154000Sfujita register int unit; 42254000Sfujita { 42354000Sfujita register struct le_softc *le = &le_softc[unit]; 42454000Sfujita register struct lereg1 *ler1; 42554000Sfujita register int stat; 42654000Sfujita 42754000Sfujita ler1 = le->sc_r1; 42854000Sfujita LERDWR(ler0, ler1->ler1_rdp, stat); 42954000Sfujita if (stat & LE_SERR) { 43054000Sfujita leerror(unit, stat); 43154000Sfujita if (stat & LE_MERR) { 43254000Sfujita le->sc_merr++; 43354000Sfujita lereset(unit); 43454000Sfujita return(1); 43554000Sfujita } 43654000Sfujita if (stat & LE_BABL) 43754000Sfujita le->sc_babl++; 43854000Sfujita if (stat & LE_CERR) 43954000Sfujita le->sc_cerr++; 44054000Sfujita if (stat & LE_MISS) 44154000Sfujita le->sc_miss++; 44254000Sfujita LERDWR(ler0, LE_BABL|LE_CERR|LE_MISS|LE_INEA, ler1->ler1_rdp); 44354000Sfujita } 44454000Sfujita if ((stat & LE_RXON) == 0) { 44554000Sfujita le->sc_rxoff++; 44654000Sfujita lereset(unit); 44754000Sfujita return(1); 44854000Sfujita } 44954000Sfujita if ((stat & LE_TXON) == 0) { 45054000Sfujita le->sc_txoff++; 45154000Sfujita lereset(unit); 45254000Sfujita return(1); 45354000Sfujita } 45455582Sfujita if (stat & LE_RINT) 45554000Sfujita lerint(unit); 45655582Sfujita if (stat & LE_TINT) 45754000Sfujita lexint(unit); 45854000Sfujita return(1); 45954000Sfujita } 46054000Sfujita 46154000Sfujita /* 46254000Sfujita * Ethernet interface transmitter interrupt. 46354000Sfujita * Start another output if more data to send. 46454000Sfujita */ 46554000Sfujita lexint(unit) 46654000Sfujita register int unit; 46754000Sfujita { 46854000Sfujita register struct le_softc *le = &le_softc[unit]; 46954000Sfujita register struct letmd *tmd; 47055582Sfujita int i, gotone = 0; 47154000Sfujita 47255582Sfujita do { 47355582Sfujita if ((i = le->sc_tmd - le->sc_txcnt) < 0) 47455582Sfujita i += LETBUF; 47555582Sfujita tmd = &le->sc_r2->ler2_tmd[i]; 47655582Sfujita if (tmd->tmd1 & LE_OWN) { 47755582Sfujita if (gotone) 47855582Sfujita break; 47955582Sfujita le->sc_xown++; 48055582Sfujita return; 48154000Sfujita } 48255582Sfujita 48355582Sfujita /* clear interrupt */ 48455582Sfujita LERDWR(le->sc_r0, LE_TINT|LE_INEA, le->sc_r1->ler1_rdp); 48555582Sfujita 48655582Sfujita /* XXX documentation says BUFF not included in ERR */ 48755582Sfujita if ((tmd->tmd1 & LE_ERR) || (tmd->tmd3 & LE_TBUFF)) { 48855582Sfujita lexerror(unit); 48955582Sfujita le->sc_if.if_oerrors++; 49055582Sfujita if (tmd->tmd3 & (LE_TBUFF|LE_UFLO)) { 49155582Sfujita le->sc_uflo++; 49255582Sfujita lereset(unit); 49355582Sfujita } else if (tmd->tmd3 & LE_LCOL) 49455582Sfujita le->sc_if.if_collisions++; 49555582Sfujita else if (tmd->tmd3 & LE_RTRY) 49655582Sfujita le->sc_if.if_collisions += 16; 49755582Sfujita } else if (tmd->tmd1 & LE_ONE) 49854000Sfujita le->sc_if.if_collisions++; 49955582Sfujita else if (tmd->tmd1 & LE_MORE) 50055582Sfujita /* what is the real number? */ 50155582Sfujita le->sc_if.if_collisions += 2; 50255582Sfujita else 50355582Sfujita le->sc_if.if_opackets++; 50455582Sfujita gotone++; 50555582Sfujita } while (--le->sc_txcnt > 0); 50654000Sfujita le->sc_if.if_flags &= ~IFF_OACTIVE; 50754000Sfujita (void) lestart(&le->sc_if); 50854000Sfujita } 50954000Sfujita 51054000Sfujita #define LENEXTRMP \ 51154000Sfujita if (++bix == LERBUF) bix = 0, rmd = le->sc_r2->ler2_rmd; else ++rmd 51254000Sfujita 51354000Sfujita /* 51454000Sfujita * Ethernet interface receiver interrupt. 51554000Sfujita * If input error just drop packet. 51654000Sfujita * Decapsulate packet based on type and pass to type specific 51754000Sfujita * higher-level input routine. 51854000Sfujita */ 51954000Sfujita lerint(unit) 52054000Sfujita int unit; 52154000Sfujita { 52254000Sfujita register struct le_softc *le = &le_softc[unit]; 52354000Sfujita register int bix = le->sc_rmd; 52454000Sfujita register struct lermd *rmd = &le->sc_r2->ler2_rmd[bix]; 52554000Sfujita 52654000Sfujita /* 52754000Sfujita * Out of sync with hardware, should never happen? 52854000Sfujita */ 52954000Sfujita if (rmd->rmd1 & LE_OWN) { 53055582Sfujita le->sc_rown++; 53154000Sfujita LERDWR(le->sc_r0, LE_RINT|LE_INEA, le->sc_r1->ler1_rdp); 53254000Sfujita return; 53354000Sfujita } 53454000Sfujita 53554000Sfujita /* 53654000Sfujita * Process all buffers with valid data 53754000Sfujita */ 53854000Sfujita while ((rmd->rmd1 & LE_OWN) == 0) { 53954000Sfujita int len = rmd->rmd3; 54054000Sfujita 54154000Sfujita /* Clear interrupt to avoid race condition */ 54254000Sfujita LERDWR(le->sc_r0, LE_RINT|LE_INEA, le->sc_r1->ler1_rdp); 54354000Sfujita 54454000Sfujita if (rmd->rmd1 & LE_ERR) { 54554000Sfujita le->sc_rmd = bix; 54654000Sfujita lererror(unit, "bad packet"); 54754000Sfujita le->sc_if.if_ierrors++; 54854000Sfujita } else if ((rmd->rmd1 & (LE_STP|LE_ENP)) != (LE_STP|LE_ENP)) { 54954000Sfujita /* 55054000Sfujita * Find the end of the packet so we can see how long 55154000Sfujita * it was. We still throw it away. 55254000Sfujita */ 55354000Sfujita do { 55454000Sfujita LERDWR(le->sc_r0, LE_RINT|LE_INEA, 55554000Sfujita le->sc_r1->ler1_rdp); 55654000Sfujita rmd->rmd3 = 0; 55754000Sfujita rmd->rmd1 = LE_OWN; 55854000Sfujita LENEXTRMP; 55954000Sfujita } while (!(rmd->rmd1 & (LE_OWN|LE_ERR|LE_STP|LE_ENP))); 56054000Sfujita le->sc_rmd = bix; 56154000Sfujita lererror(unit, "chained buffer"); 56254000Sfujita le->sc_rxlen++; 56354000Sfujita /* 56454000Sfujita * If search terminated without successful completion 56554000Sfujita * we reset the hardware (conservative). 56654000Sfujita */ 56754000Sfujita if ((rmd->rmd1 & (LE_OWN|LE_ERR|LE_STP|LE_ENP)) != 56854000Sfujita LE_ENP) { 56954000Sfujita lereset(unit); 57054000Sfujita return; 57154000Sfujita } 57254000Sfujita } else 57354000Sfujita leread(unit, le->sc_r2->ler2_rbuf[bix], len); 57454000Sfujita rmd->rmd3 = 0; 57554000Sfujita rmd->rmd1 = LE_OWN; 57654000Sfujita LENEXTRMP; 57754000Sfujita } 57854000Sfujita le->sc_rmd = bix; 57954000Sfujita } 58054000Sfujita 58154000Sfujita leread(unit, buf, len) 58254000Sfujita int unit; 58354000Sfujita char *buf; 58454000Sfujita int len; 58554000Sfujita { 58654000Sfujita register struct le_softc *le = &le_softc[unit]; 58754000Sfujita register struct ether_header *et; 58854000Sfujita struct mbuf *m; 58955582Sfujita int off, resid, flags; 59054000Sfujita 59154000Sfujita le->sc_if.if_ipackets++; 59254000Sfujita et = (struct ether_header *)buf; 59354000Sfujita et->ether_type = ntohs((u_short)et->ether_type); 59454000Sfujita /* adjust input length to account for header and CRC */ 59554000Sfujita len = len - sizeof(struct ether_header) - 4; 59654000Sfujita 59754000Sfujita #define ledataaddr(et, off, type) ((type)(((caddr_t)((et)+1)+(off)))) 59854000Sfujita if (et->ether_type >= ETHERTYPE_TRAIL && 59954000Sfujita et->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) { 60054000Sfujita off = (et->ether_type - ETHERTYPE_TRAIL) * 512; 60154000Sfujita if (off >= ETHERMTU) 60254000Sfujita return; /* sanity */ 60354000Sfujita et->ether_type = ntohs(*ledataaddr(et, off, u_short *)); 60454000Sfujita resid = ntohs(*(ledataaddr(et, off+2, u_short *))); 60554000Sfujita if (off + resid > len) 60654000Sfujita return; /* sanity */ 60754000Sfujita len = off + resid; 60854000Sfujita } else 60954000Sfujita off = 0; 61054000Sfujita 61154000Sfujita if (len <= 0) { 61254000Sfujita if (ledebug) 61354000Sfujita log(LOG_WARNING, 61454000Sfujita "le%d: ierror(runt packet): from %s: len=%d\n", 61554000Sfujita unit, ether_sprintf(et->ether_shost), len); 61654000Sfujita le->sc_runt++; 61754000Sfujita le->sc_if.if_ierrors++; 61854000Sfujita return; 61954000Sfujita } 62055582Sfujita flags = 0; 62155582Sfujita if (bcmp((caddr_t)etherbroadcastaddr, 62255582Sfujita (caddr_t)et->ether_dhost, sizeof(etherbroadcastaddr)) == 0) 62355582Sfujita flags |= M_BCAST; 62455582Sfujita if (et->ether_dhost[0] & 1) 62555582Sfujita flags |= M_MCAST; 62655582Sfujita 62754000Sfujita #if NBPFILTER > 0 62854000Sfujita /* 62954000Sfujita * Check if there's a bpf filter listening on this interface. 63055582Sfujita * If so, hand off the raw packet to enet. 63154000Sfujita */ 63255582Sfujita if (le->sc_if.if_bpf) { 63355582Sfujita bpf_tap(le->sc_if.if_bpf, buf, len + sizeof(struct ether_header)); 63455582Sfujita 63555582Sfujita /* 63655582Sfujita * Keep the packet if it's a broadcast or has our 63755582Sfujita * physical ethernet address (or if we support 63855582Sfujita * multicast and it's one). 63955582Sfujita */ 64055582Sfujita if ( 64155582Sfujita #ifdef MULTICAST 64255582Sfujita (flags & (M_BCAST | M_MCAST)) == 0 && 64355582Sfujita #else 64455582Sfujita (flags & M_BCAST) == 0 && 64554000Sfujita #endif 64655582Sfujita bcmp(et->ether_dhost, le->sc_addr, 64755582Sfujita sizeof(et->ether_dhost)) != 0) 64855582Sfujita return; 64955582Sfujita } 65054000Sfujita #endif 65154000Sfujita /* 65254000Sfujita * Pull packet off interface. Off is nonzero if packet 65354000Sfujita * has trailing header; m_devget will then force this header 65454000Sfujita * information to be at the front, but we still have to drop 65554000Sfujita * the type and length which are at the front of any trailer data. 65654000Sfujita */ 65754000Sfujita m = m_devget((char *)(et + 1), len, off, &le->sc_if, 0); 65855582Sfujita m->m_flags |= flags; 65954000Sfujita if (m == 0) 66054000Sfujita return; 66154000Sfujita ether_input(&le->sc_if, et, m); 66254000Sfujita } 66354000Sfujita 66454000Sfujita /* 66554000Sfujita * Routine to copy from mbuf chain to transmit 66654000Sfujita * buffer in board local memory. 66754000Sfujita */ 66854000Sfujita leput(lebuf, m) 66954000Sfujita register char *lebuf; 67054000Sfujita register struct mbuf *m; 67154000Sfujita { 67254000Sfujita register struct mbuf *mp; 67354000Sfujita register int len, tlen = 0; 67454000Sfujita 67554000Sfujita for (mp = m; mp; mp = mp->m_next) { 67654000Sfujita len = mp->m_len; 67754000Sfujita if (len == 0) 67854000Sfujita continue; 67954000Sfujita tlen += len; 68054000Sfujita bcopy(mtod(mp, char *), lebuf, len); 68154000Sfujita lebuf += len; 68254000Sfujita } 68354000Sfujita m_freem(m); 68454000Sfujita if (tlen < LEMINSIZE) { 68554000Sfujita bzero(lebuf, LEMINSIZE - tlen); 68654000Sfujita tlen = LEMINSIZE; 68754000Sfujita } 68854000Sfujita return(tlen); 68954000Sfujita } 69054000Sfujita 69154000Sfujita /* 69254000Sfujita * Process an ioctl request. 69354000Sfujita */ 69454000Sfujita leioctl(ifp, cmd, data) 69554000Sfujita register struct ifnet *ifp; 69654000Sfujita int cmd; 69754000Sfujita caddr_t data; 69854000Sfujita { 69954000Sfujita register struct ifaddr *ifa = (struct ifaddr *)data; 70054000Sfujita struct le_softc *le = &le_softc[ifp->if_unit]; 70154000Sfujita struct lereg1 *ler1 = le->sc_r1; 70254000Sfujita int s = splimp(), error = 0; 70354000Sfujita 70454000Sfujita switch (cmd) { 70554000Sfujita 70654000Sfujita case SIOCSIFADDR: 70754000Sfujita ifp->if_flags |= IFF_UP; 70854000Sfujita switch (ifa->ifa_addr->sa_family) { 70954000Sfujita #ifdef INET 71054000Sfujita case AF_INET: 71154000Sfujita leinit(ifp->if_unit); /* before arpwhohas */ 71254000Sfujita ((struct arpcom *)ifp)->ac_ipaddr = 71354000Sfujita IA_SIN(ifa)->sin_addr; 71454000Sfujita arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr); 71554000Sfujita break; 71654000Sfujita #endif 71754000Sfujita #ifdef NS 71854000Sfujita case AF_NS: 71954000Sfujita { 72054000Sfujita register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr); 72154000Sfujita 72254000Sfujita if (ns_nullhost(*ina)) 72354000Sfujita ina->x_host = *(union ns_host *)(le->sc_addr); 72454000Sfujita else { 72554000Sfujita /* 72654000Sfujita * The manual says we can't change the address 72754000Sfujita * while the receiver is armed, 72854000Sfujita * so reset everything 72954000Sfujita */ 73054000Sfujita ifp->if_flags &= ~IFF_RUNNING; 73154000Sfujita LERDWR(le->sc_r0, LE_STOP, ler1->ler1_rdp); 73254000Sfujita bcopy((caddr_t)ina->x_host.c_host, 73354000Sfujita (caddr_t)le->sc_addr, sizeof(le->sc_addr)); 73454000Sfujita } 73554000Sfujita leinit(ifp->if_unit); /* does le_setaddr() */ 73654000Sfujita break; 73754000Sfujita } 73854000Sfujita #endif 73954000Sfujita default: 74054000Sfujita leinit(ifp->if_unit); 74154000Sfujita break; 74254000Sfujita } 74354000Sfujita break; 74454000Sfujita 74554000Sfujita case SIOCSIFFLAGS: 74654000Sfujita if ((ifp->if_flags & IFF_UP) == 0 && 74754000Sfujita ifp->if_flags & IFF_RUNNING) { 74854000Sfujita LERDWR(le->sc_r0, LE_STOP, ler1->ler1_rdp); 74954000Sfujita ifp->if_flags &= ~IFF_RUNNING; 75054000Sfujita } else if (ifp->if_flags & IFF_UP && 75154000Sfujita (ifp->if_flags & IFF_RUNNING) == 0) 75254000Sfujita leinit(ifp->if_unit); 75354000Sfujita /* 75454000Sfujita * If the state of the promiscuous bit changes, the interface 75554000Sfujita * must be reset to effect the change. 75654000Sfujita */ 75754000Sfujita if (((ifp->if_flags ^ le->sc_iflags) & IFF_PROMISC) && 75854000Sfujita (ifp->if_flags & IFF_RUNNING)) { 75954000Sfujita le->sc_iflags = ifp->if_flags; 76054000Sfujita lereset(ifp->if_unit); 76154000Sfujita lestart(ifp); 76254000Sfujita } 76354000Sfujita break; 76454000Sfujita 76555582Sfujita #ifdef MULTICAST 76655582Sfujita case SIOCADDMULTI: 76755582Sfujita case SIOCDELMULTI: 76855582Sfujita /* Update our multicast list */ 76955582Sfujita error = (cmd == SIOCADDMULTI) ? 77055582Sfujita ether_addmulti((struct ifreq *)data, &le->sc_ac) : 77155582Sfujita ether_delmulti((struct ifreq *)data, &le->sc_ac); 77255582Sfujita 77355582Sfujita if (error == ENETRESET) { 77455582Sfujita /* 77555582Sfujita * Multicast list has changed; set the hardware 77655582Sfujita * filter accordingly. 77755582Sfujita */ 77855582Sfujita lereset(ifp->if_unit); 77955582Sfujita error = 0; 78055582Sfujita } 78155582Sfujita break; 78255582Sfujita #endif 78354000Sfujita default: 78454000Sfujita error = EINVAL; 78554000Sfujita } 78654000Sfujita splx(s); 78754000Sfujita return (error); 78854000Sfujita } 78954000Sfujita 79054000Sfujita leerror(unit, stat) 79154000Sfujita int unit; 79254000Sfujita int stat; 79354000Sfujita { 79454000Sfujita if (!ledebug) 79554000Sfujita return; 79654000Sfujita 79754000Sfujita /* 79854000Sfujita * Not all transceivers implement heartbeat 79954000Sfujita * so we only log CERR once. 80054000Sfujita */ 80154000Sfujita if ((stat & LE_CERR) && le_softc[unit].sc_cerr) 80254000Sfujita return; 80354000Sfujita log(LOG_WARNING, 80454000Sfujita "le%d: error: stat=%b\n", unit, 80554000Sfujita stat, 80654000Sfujita "\20\20ERR\17BABL\16CERR\15MISS\14MERR\13RINT\12TINT\11IDON\10INTR\07INEA\06RXON\05TXON\04TDMD\03STOP\02STRT\01INIT"); 80754000Sfujita } 80854000Sfujita 80954000Sfujita lererror(unit, msg) 81054000Sfujita int unit; 81154000Sfujita char *msg; 81254000Sfujita { 81354000Sfujita register struct le_softc *le = &le_softc[unit]; 81454000Sfujita register struct lermd *rmd; 81554000Sfujita int len; 81654000Sfujita 81754000Sfujita if (!ledebug) 81854000Sfujita return; 81954000Sfujita 82054000Sfujita rmd = &le->sc_r2->ler2_rmd[le->sc_rmd]; 82154000Sfujita len = rmd->rmd3; 82254000Sfujita log(LOG_WARNING, 82354000Sfujita "le%d: ierror(%s): from %s: buf=%d, len=%d, rmd1=%b\n", 82454000Sfujita unit, msg, 82554000Sfujita len > 11 ? 82654000Sfujita ether_sprintf((u_char *)&le->sc_r2->ler2_rbuf[le->sc_rmd][6]) : 82754000Sfujita "unknown", 82854000Sfujita le->sc_rmd, len, 82954000Sfujita rmd->rmd1, 83054000Sfujita "\20\20OWN\17ERR\16FRAM\15OFLO\14CRC\13RBUF\12STP\11ENP"); 83154000Sfujita } 83254000Sfujita 83354000Sfujita lexerror(unit) 83454000Sfujita int unit; 83554000Sfujita { 83654000Sfujita register struct le_softc *le = &le_softc[unit]; 83754000Sfujita register struct letmd *tmd; 83854000Sfujita int len; 83954000Sfujita 84054000Sfujita if (!ledebug) 84154000Sfujita return; 84254000Sfujita 84354000Sfujita tmd = le->sc_r2->ler2_tmd; 84454000Sfujita len = -tmd->tmd2; 84554000Sfujita log(LOG_WARNING, 84654000Sfujita "le%d: oerror: to %s: buf=%d, len=%d, tmd1=%b, tmd3=%b\n", 84754000Sfujita unit, 84854000Sfujita len > 5 ? 84954000Sfujita ether_sprintf((u_char *)&le->sc_r2->ler2_tbuf[0][0]) : 85054000Sfujita "unknown", 85154000Sfujita 0, len, 85254000Sfujita tmd->tmd1, 85354000Sfujita "\20\20OWN\17ERR\16RES\15MORE\14ONE\13DEF\12STP\11ENP", 85454000Sfujita tmd->tmd3, 85554000Sfujita "\20\20BUFF\17UFLO\16RES\15LCOL\14LCAR\13RTRY"); 85654000Sfujita } 85754000Sfujita #endif 858