154000Sfujita /* 255582Sfujita * Copyright (c) 1982, 1990 The Regents of the University of California. 354000Sfujita * All rights reserved. 454000Sfujita * 554000Sfujita * %sccs.include.redist.c% 654000Sfujita * 7*58694Sakito * from: hp300/dev/if_le.c 7.16 (Berkeley) 3/11/93 855582Sfujita * 9*58694Sakito * @(#)if_le.c 7.5 (Berkeley) 03/17/93 1054000Sfujita */ 1154000Sfujita 1254000Sfujita #include "le.h" 1354000Sfujita #if NLE > 0 1454000Sfujita 1554000Sfujita #include "bpfilter.h" 1654000Sfujita 1754000Sfujita /* 1854000Sfujita * AMD 7990 LANCE 1954000Sfujita * 2055582Sfujita * This driver will accept tailer encapsulated packets even 2154000Sfujita * though it buys us nothing. The motivation was to avoid incompatibilities 2254000Sfujita * with VAXen, SUNs, and others that handle and benefit from them. 2354000Sfujita * This reasoning is dubious. 2454000Sfujita */ 2556519Sbostic #include <sys/param.h> 2656519Sbostic #include <sys/proc.h> 2756519Sbostic #include <sys/systm.h> 2856519Sbostic #include <sys/mbuf.h> 2956519Sbostic #include <sys/buf.h> 3056519Sbostic #include <sys/protosw.h> 3156519Sbostic #include <sys/socket.h> 3256519Sbostic #include <sys/syslog.h> 3356519Sbostic #include <sys/ioctl.h> 3456519Sbostic #include <sys/errno.h> 3554000Sfujita 3656519Sbostic #include <net/if.h> 3756519Sbostic #include <net/netisr.h> 3856519Sbostic #include <net/route.h> 3954000Sfujita 4054000Sfujita #ifdef INET 4156519Sbostic #include <netinet/in.h> 4256519Sbostic #include <netinet/in_systm.h> 4356519Sbostic #include <netinet/in_var.h> 4456519Sbostic #include <netinet/ip.h> 4556519Sbostic #include <netinet/if_ether.h> 4654000Sfujita #endif 4754000Sfujita 4854000Sfujita #ifdef NS 4956519Sbostic #include <netns/ns.h> 5056519Sbostic #include <netns/ns_if.h> 5154000Sfujita #endif 5254000Sfujita 5357525Sakito #if defined (CCITT) && defined (LLC) 5457525Sakito #include <sys/socketvar.h> 5557525Sakito #include <netccitt/x25.h> 5657525Sakito extern llc_ctlinput(), cons_rtrequest(); 5757525Sakito #endif 5857525Sakito 5956519Sbostic #include <machine/cpu.h> 6056519Sbostic #include <machine/mtpr.h> 6156519Sbostic #include <luna68k/dev/device.h> 6256519Sbostic #include <luna68k/dev/if_lereg.h> 6354000Sfujita 6454000Sfujita #if NBPFILTER > 0 6556519Sbostic #include <net/bpf.h> 6656519Sbostic #include <net/bpfdesc.h> 6754000Sfujita #endif 6854000Sfujita 6954000Sfujita int leattach(); 7054000Sfujita struct driver ledriver = { 7154000Sfujita leattach, "le", 7254000Sfujita }; 7354000Sfujita 7454000Sfujita int ledebug = 0; /* console error messages */ 7554000Sfujita 7657525Sakito int leintr(), leinit(), leioctl(), lestart(), ether_output(), lereset(); 7754000Sfujita struct mbuf *m_devget(); 7854000Sfujita extern struct ifnet loif; 7954000Sfujita 8054000Sfujita /* 8154000Sfujita * Ethernet software status per interface. 8254000Sfujita * 8354000Sfujita * Each interface is referenced by a network interface structure, 8454000Sfujita * le_if, which the routing code uses to locate the interface. 8554000Sfujita * This structure contains the output queue for the interface, its address, ... 8654000Sfujita */ 8754000Sfujita struct le_softc { 8854000Sfujita struct arpcom sc_ac; /* common Ethernet structures */ 8954000Sfujita #define sc_if sc_ac.ac_if /* network-visible interface */ 9054000Sfujita #define sc_addr sc_ac.ac_enaddr /* hardware Ethernet address */ 9154000Sfujita struct lereg1 *sc_r1; /* LANCE registers */ 9254000Sfujita struct lereg2 *sc_r2; /* dual-port RAM */ 9354000Sfujita int sc_rmd; /* predicted next rmd to process */ 9455582Sfujita int sc_tmd; /* next available tmd */ 9555582Sfujita int sc_txcnt; /* # of transmit buffers in use */ 9655582Sfujita /* stats */ 9754000Sfujita int sc_runt; 9854000Sfujita int sc_jab; 9954000Sfujita int sc_merr; 10054000Sfujita int sc_babl; 10154000Sfujita int sc_cerr; 10254000Sfujita int sc_miss; 10355582Sfujita int sc_rown; 10454000Sfujita int sc_xown; 10555582Sfujita int sc_xown2; 10654000Sfujita int sc_uflo; 10754000Sfujita int sc_rxlen; 10854000Sfujita int sc_rxoff; 10954000Sfujita int sc_txoff; 11054000Sfujita int sc_busy; 11154000Sfujita short sc_iflags; 11254000Sfujita } le_softc[NLE]; 11354000Sfujita 11454000Sfujita /* access LANCE registers */ 11554000Sfujita #define LERDWR(cntl, src, dst) (dst) = (src) 11654000Sfujita 11754000Sfujita #define LE_IPL 3 11854000Sfujita 11954000Sfujita /* 12054000Sfujita * Interface exists: make available by filling in network interface 12154000Sfujita * record. System will initialize the interface when it is ready 12254000Sfujita * to accept packets. 12354000Sfujita */ 12454000Sfujita leattach(hd) 12554000Sfujita struct hp_device *hd; 12654000Sfujita { 12754000Sfujita register struct lereg2 *ler2; 12854000Sfujita struct lereg2 *lemem = (struct lereg2 *) 0; 12954000Sfujita struct le_softc *le = &le_softc[hd->hp_unit]; 13054000Sfujita struct ifnet *ifp = &le->sc_if; 13154000Sfujita char *cp; 13254000Sfujita int i; 13354000Sfujita 13454000Sfujita le->sc_r1 = (struct lereg1 *) hd->hp_addr; 13554000Sfujita ler2 = le->sc_r2 = (struct lereg2 *) 0x71000000; 13654000Sfujita 13754000Sfujita hd->hp_ipl = LE_IPL; 13854000Sfujita 13954000Sfujita /* 14054000Sfujita * Read the ethernet address off the board, one nibble at a time. 14154000Sfujita */ 14254000Sfujita #ifdef NOROM 14354000Sfujita cp = "00000a02456c"; 14454000Sfujita #else 14554000Sfujita cp = (char *) 0x4101FFE0; 14654000Sfujita #endif 14754000Sfujita for (i = 0; i < sizeof(le->sc_addr); i++) { 14854000Sfujita le->sc_addr[i] = (*cp < 'A' ? (*cp & 0xF) : (*cp & 0xF) + 9) << 4; 14954000Sfujita cp++; 15054000Sfujita le->sc_addr[i] |= (*cp < 'A' ? (*cp & 0xF) : (*cp & 0xF) + 9); 15154000Sfujita cp++; 15254000Sfujita } 15354000Sfujita printf("le%d: hardware address %s\n", hd->hp_unit, 15454000Sfujita ether_sprintf(le->sc_addr)); 15554000Sfujita 15654000Sfujita /* 15754000Sfujita * Setup for transmit/receive 15854000Sfujita */ 15954000Sfujita ler2->ler2_mode = LE_MODE; 16055582Sfujita ler2->ler2_ladrf[0] = 0; 16155582Sfujita ler2->ler2_ladrf[1] = 0; 16254000Sfujita ler2->ler2_rlen = LE_RLEN; 16354000Sfujita ler2->ler2_rdra = (int)lemem->ler2_rmd; 16454000Sfujita ler2->ler2_tlen = LE_TLEN; 16554000Sfujita ler2->ler2_tdra = (int)lemem->ler2_tmd; 16654000Sfujita 16754000Sfujita ifp->if_unit = hd->hp_unit; 16854000Sfujita ifp->if_name = "le"; 16954000Sfujita ifp->if_mtu = ETHERMTU; 17054000Sfujita ifp->if_init = leinit; 17157525Sakito ifp->if_reset = lereset; 17254000Sfujita ifp->if_ioctl = leioctl; 17354000Sfujita ifp->if_output = ether_output; 17454000Sfujita ifp->if_start = lestart; 17555582Sfujita #ifdef MULTICAST 17655582Sfujita ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 17755582Sfujita #else 17854000Sfujita ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX; 17955582Sfujita #endif 18054000Sfujita #if NBPFILTER > 0 18155582Sfujita bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header)); 18254000Sfujita #endif 18354000Sfujita if_attach(ifp); 18454000Sfujita return (1); 18554000Sfujita } 18654000Sfujita 18755582Sfujita #ifdef MULTICAST 18855582Sfujita /* 18955582Sfujita * Setup the logical address filter 19055582Sfujita */ 19155582Sfujita void 19255582Sfujita lesetladrf(sc) 19355582Sfujita register struct le_softc *sc; 19455582Sfujita { 19555582Sfujita register volatile struct lereg2 *ler2 = sc->sc_r2; 19655582Sfujita register struct ifnet *ifp = &sc->sc_if; 19755582Sfujita register struct ether_multi *enm; 19855582Sfujita register u_char *cp; 19955582Sfujita register u_long crc; 20055582Sfujita register u_long c; 20155582Sfujita register int i, len; 20255582Sfujita struct ether_multistep step; 20355582Sfujita 20455582Sfujita /* 20555582Sfujita * Set up multicast address filter by passing all multicast 20655582Sfujita * addresses through a crc generator, and then using the high 20755582Sfujita * order 6 bits as a index into the 64 bit logical address 20855582Sfujita * filter. The high order two bits select the word, while the 20955582Sfujita * rest of the bits select the bit within the word. 21055582Sfujita */ 21155582Sfujita 21255582Sfujita ler2->ler2_ladrf[0] = 0; 21355582Sfujita ler2->ler2_ladrf[1] = 0; 21455582Sfujita ifp->if_flags &= ~IFF_ALLMULTI; 21555582Sfujita ETHER_FIRST_MULTI(step, &sc->sc_ac, enm); 21655582Sfujita while (enm != NULL) { 21755582Sfujita if (bcmp((caddr_t)&enm->enm_addrlo, 21855582Sfujita (caddr_t)&enm->enm_addrhi, sizeof(enm->enm_addrlo)) == 0) { 21955582Sfujita /* 22055582Sfujita * We must listen to a range of multicast 22155582Sfujita * addresses. For now, just accept all 22255582Sfujita * multicasts, rather than trying to set only 22355582Sfujita * those filter bits needed to match the range. 22455582Sfujita * (At this time, the only use of address 22555582Sfujita * ranges is for IP multicast routing, for 22655582Sfujita * which the range is big enough to require all 22755582Sfujita * bits set.) 22855582Sfujita */ 22955582Sfujita ler2->ler2_ladrf[0] = 0xffffffff; 23055582Sfujita ler2->ler2_ladrf[1] = 0xffffffff; 23155582Sfujita ifp->if_flags |= IFF_ALLMULTI; 23255582Sfujita return; 23355582Sfujita } 23455582Sfujita 23555582Sfujita cp = (unsigned char *)&enm->enm_addrlo; 23655582Sfujita c = *cp; 23755582Sfujita crc = 0xffffffff; 23855582Sfujita len = 6; 23955582Sfujita while (len-- > 0) { 24055582Sfujita c = *cp; 24155582Sfujita for (i = 0; i < 8; i++) { 24255582Sfujita if ((c & 0x01) ^ (crc & 0x01)) { 24355582Sfujita crc >>= 1; 24455582Sfujita crc = crc ^ 0xedb88320; 24555582Sfujita } 24655582Sfujita else 24755582Sfujita crc >>= 1; 24855582Sfujita c >>= 1; 24955582Sfujita } 25055582Sfujita cp++; 25155582Sfujita } 25255582Sfujita /* Just want the 6 most significant bits. */ 25355582Sfujita crc = crc >> 26; 25455582Sfujita 25555582Sfujita /* Turn on the corresponding bit in the filter. */ 25655582Sfujita ler2->ler2_ladrf[crc >> 5] |= 1 << (crc & 0x1f); 25755582Sfujita 25855582Sfujita ETHER_NEXT_MULTI(step, enm); 25955582Sfujita } 26055582Sfujita } 26155582Sfujita #endif 26255582Sfujita 26354000Sfujita ledrinit(ler2, le) 26454000Sfujita register struct lereg2 *ler2; 26554000Sfujita register struct le_softc *le; 26654000Sfujita { 26754000Sfujita register struct lereg2 *lemem = (struct lereg2 *) 0; 26854000Sfujita register int i; 26954000Sfujita 27054000Sfujita ler2->ler2_padr[0] = le->sc_addr[1]; 27154000Sfujita ler2->ler2_padr[1] = le->sc_addr[0]; 27254000Sfujita ler2->ler2_padr[2] = le->sc_addr[3]; 27354000Sfujita ler2->ler2_padr[3] = le->sc_addr[2]; 27454000Sfujita ler2->ler2_padr[4] = le->sc_addr[5]; 27554000Sfujita ler2->ler2_padr[5] = le->sc_addr[4]; 27654000Sfujita for (i = 0; i < LERBUF; i++) { 27754000Sfujita ler2->ler2_rmd[i].rmd0 = (int)lemem->ler2_rbuf[i]; 27854000Sfujita ler2->ler2_rmd[i].rmd1 = LE_OWN; 27954000Sfujita ler2->ler2_rmd[i].rmd2 = -LEMTU; 28054000Sfujita ler2->ler2_rmd[i].rmd3 = 0; 28154000Sfujita } 28254000Sfujita for (i = 0; i < LETBUF; i++) { 28354000Sfujita ler2->ler2_tmd[i].tmd0 = (int)lemem->ler2_tbuf[i]; 28454000Sfujita ler2->ler2_tmd[i].tmd1 = 0; 28554000Sfujita ler2->ler2_tmd[i].tmd2 = 0; 28654000Sfujita ler2->ler2_tmd[i].tmd3 = 0; 28754000Sfujita } 28855582Sfujita /* Setup the logical address filter */ 28955582Sfujita #ifdef MULTICAST 29055582Sfujita lesetladrf(le); 29155582Sfujita #else 29255582Sfujita ler2->ler2_ladrf[0] = 0; 29355582Sfujita ler2->ler2_ladrf[1] = 0; 29455582Sfujita #endif 29554000Sfujita } 29654000Sfujita 29754000Sfujita lereset(unit) 29854000Sfujita register int unit; 29954000Sfujita { 30054000Sfujita register struct le_softc *le = &le_softc[unit]; 30154000Sfujita register struct lereg1 *ler1 = le->sc_r1; 30254000Sfujita register struct lereg2 *lemem = (struct lereg2 *) 0; 30354000Sfujita register int timo = 100000; 30454000Sfujita register int stat; 30554000Sfujita 30654000Sfujita #ifdef lint 30754000Sfujita stat = unit; 30854000Sfujita #endif 30954000Sfujita #if NBPFILTER > 0 31054000Sfujita if (le->sc_if.if_flags & IFF_PROMISC) 31154000Sfujita /* set the promiscuous bit */ 31254000Sfujita le->sc_r2->ler2_mode = LE_MODE|0x8000; 31354000Sfujita else 31454000Sfujita le->sc_r2->ler2_mode = LE_MODE; 31554000Sfujita #endif 31654000Sfujita LERDWR(ler0, LE_CSR0, ler1->ler1_rap); 31754000Sfujita LERDWR(ler0, LE_STOP, ler1->ler1_rdp); 31854000Sfujita ledrinit(le->sc_r2, le); 31955582Sfujita le->sc_rmd = le->sc_tmd = 0; 32054000Sfujita LERDWR(ler0, LE_CSR1, ler1->ler1_rap); 32154000Sfujita LERDWR(ler0, (int)&lemem->ler2_mode, ler1->ler1_rdp); 32254000Sfujita LERDWR(ler0, LE_CSR2, ler1->ler1_rap); 32354000Sfujita LERDWR(ler0, 0, ler1->ler1_rdp); 32454000Sfujita LERDWR(ler0, LE_CSR0, ler1->ler1_rap); 32554000Sfujita LERDWR(ler0, LE_INIT, ler1->ler1_rdp); 32654000Sfujita do { 32754000Sfujita if (--timo == 0) { 32854000Sfujita printf("le%d: init timeout, stat = 0x%x\n", 32954000Sfujita unit, stat); 33054000Sfujita break; 33154000Sfujita } 33254000Sfujita LERDWR(ler0, ler1->ler1_rdp, stat); 33354000Sfujita } while ((stat & LE_IDON) == 0); 33454000Sfujita LERDWR(ler0, LE_STOP, ler1->ler1_rdp); 33554000Sfujita LERDWR(ler0, LE_CSR3, ler1->ler1_rap); 33654000Sfujita LERDWR(ler0, LE_BSWP, ler1->ler1_rdp); 33754000Sfujita LERDWR(ler0, LE_CSR0, ler1->ler1_rap); 33854000Sfujita LERDWR(ler0, LE_STRT | LE_INEA, ler1->ler1_rdp); 33954000Sfujita le->sc_if.if_flags &= ~IFF_OACTIVE; 34055582Sfujita le->sc_txcnt = 0; 34154000Sfujita } 34254000Sfujita 34354000Sfujita /* 34454000Sfujita * Initialization of interface 34554000Sfujita */ 34654000Sfujita leinit(unit) 34754000Sfujita int unit; 34854000Sfujita { 34954000Sfujita register struct ifnet *ifp = &le_softc[unit].sc_if; 35054000Sfujita register struct ifaddr *ifa; 35154000Sfujita int s; 35254000Sfujita 35354000Sfujita /* not yet, if address still unknown */ 35454000Sfujita for (ifa = ifp->if_addrlist;; ifa = ifa->ifa_next) 35554000Sfujita if (ifa == 0) 35654000Sfujita return; 35754000Sfujita else if (ifa->ifa_addr && ifa->ifa_addr->sa_family != AF_LINK) 35854000Sfujita break; 35954000Sfujita if ((ifp->if_flags & IFF_RUNNING) == 0) { 36054000Sfujita s = splimp(); 36154000Sfujita ifp->if_flags |= IFF_RUNNING; 36254000Sfujita lereset(unit); 36354000Sfujita (void) lestart(ifp); 36454000Sfujita splx(s); 36554000Sfujita } 36654000Sfujita } 36754000Sfujita 36854000Sfujita /* 36954000Sfujita * Start output on interface. Get another datagram to send 37054000Sfujita * off of the interface queue, and copy it to the interface 37154000Sfujita * before starting the output. 37254000Sfujita */ 37354000Sfujita lestart(ifp) 37454000Sfujita struct ifnet *ifp; 37554000Sfujita { 37654000Sfujita register struct le_softc *le = &le_softc[ifp->if_unit]; 37754000Sfujita register struct letmd *tmd; 37854000Sfujita register struct mbuf *m; 37954000Sfujita int len; 38054000Sfujita 38154000Sfujita if ((le->sc_if.if_flags & IFF_RUNNING) == 0) 38254000Sfujita return (0); 38355582Sfujita tmd = &le->sc_r2->ler2_tmd[le->sc_tmd]; 38455582Sfujita do { 38555582Sfujita if (tmd->tmd1 & LE_OWN) { 38655582Sfujita le->sc_xown2++; 38755582Sfujita return (0); 38855582Sfujita } 38955582Sfujita IF_DEQUEUE(&le->sc_if.if_snd, m); 39055582Sfujita if (m == 0) 39155582Sfujita return (0); 39255582Sfujita len = leput(le->sc_r2->ler2_tbuf[le->sc_tmd], m); 39354000Sfujita #if NBPFILTER > 0 39455582Sfujita /* 39555582Sfujita * If bpf is listening on this interface, let it 39655582Sfujita * see the packet before we commit it to the wire. 39755582Sfujita */ 39855582Sfujita if (ifp->if_bpf) 39955582Sfujita bpf_tap(ifp->if_bpf, le->sc_r2->ler2_tbuf[le->sc_tmd], 40055582Sfujita len); 40154000Sfujita #endif 40255582Sfujita 40355582Sfujita tmd->tmd3 = 0; 40455582Sfujita tmd->tmd2 = -len; 40554000Sfujita tmd->tmd1 = LE_OWN | LE_STP | LE_ENP; 40655582Sfujita if (++le->sc_tmd == LETBUF) { 40755582Sfujita le->sc_tmd = 0; 40855582Sfujita tmd = le->sc_r2->ler2_tmd; 40955582Sfujita } else 41055582Sfujita tmd++; 41155582Sfujita } while (++le->sc_txcnt < LETBUF); 41255582Sfujita le->sc_if.if_flags |= IFF_OACTIVE; 41354000Sfujita return (0); 41454000Sfujita } 41554000Sfujita 41654000Sfujita void 41754000Sfujita _leintr() 41854000Sfujita { 41954000Sfujita register int i; 42054000Sfujita 42154000Sfujita for (i = 0; i < NLE; i++) { 42254000Sfujita leintr(i); 42354000Sfujita } 42454000Sfujita } 42554000Sfujita 42654000Sfujita int 42754000Sfujita leintr(unit) 42854000Sfujita register int unit; 42954000Sfujita { 43054000Sfujita register struct le_softc *le = &le_softc[unit]; 43154000Sfujita register struct lereg1 *ler1; 43254000Sfujita register int stat; 43354000Sfujita 43454000Sfujita ler1 = le->sc_r1; 43554000Sfujita LERDWR(ler0, ler1->ler1_rdp, stat); 43654000Sfujita if (stat & LE_SERR) { 43754000Sfujita leerror(unit, stat); 43854000Sfujita if (stat & LE_MERR) { 43954000Sfujita le->sc_merr++; 44054000Sfujita lereset(unit); 44154000Sfujita return(1); 44254000Sfujita } 44354000Sfujita if (stat & LE_BABL) 44454000Sfujita le->sc_babl++; 44554000Sfujita if (stat & LE_CERR) 44654000Sfujita le->sc_cerr++; 44754000Sfujita if (stat & LE_MISS) 44854000Sfujita le->sc_miss++; 44954000Sfujita LERDWR(ler0, LE_BABL|LE_CERR|LE_MISS|LE_INEA, ler1->ler1_rdp); 45054000Sfujita } 45154000Sfujita if ((stat & LE_RXON) == 0) { 45254000Sfujita le->sc_rxoff++; 45354000Sfujita lereset(unit); 45454000Sfujita return(1); 45554000Sfujita } 45654000Sfujita if ((stat & LE_TXON) == 0) { 45754000Sfujita le->sc_txoff++; 45854000Sfujita lereset(unit); 45954000Sfujita return(1); 46054000Sfujita } 46155582Sfujita if (stat & LE_RINT) 46254000Sfujita lerint(unit); 46355582Sfujita if (stat & LE_TINT) 46454000Sfujita lexint(unit); 46554000Sfujita return(1); 46654000Sfujita } 46754000Sfujita 46854000Sfujita /* 46954000Sfujita * Ethernet interface transmitter interrupt. 47054000Sfujita * Start another output if more data to send. 47154000Sfujita */ 47254000Sfujita lexint(unit) 47354000Sfujita register int unit; 47454000Sfujita { 47554000Sfujita register struct le_softc *le = &le_softc[unit]; 47654000Sfujita register struct letmd *tmd; 47755582Sfujita int i, gotone = 0; 47854000Sfujita 47955582Sfujita do { 48055582Sfujita if ((i = le->sc_tmd - le->sc_txcnt) < 0) 48155582Sfujita i += LETBUF; 48255582Sfujita tmd = &le->sc_r2->ler2_tmd[i]; 48355582Sfujita if (tmd->tmd1 & LE_OWN) { 48455582Sfujita if (gotone) 48555582Sfujita break; 48655582Sfujita le->sc_xown++; 48755582Sfujita return; 48854000Sfujita } 48955582Sfujita 49055582Sfujita /* clear interrupt */ 49155582Sfujita LERDWR(le->sc_r0, LE_TINT|LE_INEA, le->sc_r1->ler1_rdp); 49255582Sfujita 49355582Sfujita /* XXX documentation says BUFF not included in ERR */ 49455582Sfujita if ((tmd->tmd1 & LE_ERR) || (tmd->tmd3 & LE_TBUFF)) { 49555582Sfujita lexerror(unit); 49655582Sfujita le->sc_if.if_oerrors++; 49755582Sfujita if (tmd->tmd3 & (LE_TBUFF|LE_UFLO)) { 49855582Sfujita le->sc_uflo++; 49955582Sfujita lereset(unit); 50055582Sfujita } else if (tmd->tmd3 & LE_LCOL) 50155582Sfujita le->sc_if.if_collisions++; 50255582Sfujita else if (tmd->tmd3 & LE_RTRY) 50355582Sfujita le->sc_if.if_collisions += 16; 50455582Sfujita } else if (tmd->tmd1 & LE_ONE) 50554000Sfujita le->sc_if.if_collisions++; 50655582Sfujita else if (tmd->tmd1 & LE_MORE) 50755582Sfujita /* what is the real number? */ 50855582Sfujita le->sc_if.if_collisions += 2; 50955582Sfujita else 51055582Sfujita le->sc_if.if_opackets++; 51155582Sfujita gotone++; 51255582Sfujita } while (--le->sc_txcnt > 0); 51354000Sfujita le->sc_if.if_flags &= ~IFF_OACTIVE; 51454000Sfujita (void) lestart(&le->sc_if); 51554000Sfujita } 51654000Sfujita 51754000Sfujita #define LENEXTRMP \ 51854000Sfujita if (++bix == LERBUF) bix = 0, rmd = le->sc_r2->ler2_rmd; else ++rmd 51954000Sfujita 52054000Sfujita /* 52154000Sfujita * Ethernet interface receiver interrupt. 52254000Sfujita * If input error just drop packet. 52354000Sfujita * Decapsulate packet based on type and pass to type specific 52454000Sfujita * higher-level input routine. 52554000Sfujita */ 52654000Sfujita lerint(unit) 52754000Sfujita int unit; 52854000Sfujita { 52954000Sfujita register struct le_softc *le = &le_softc[unit]; 53054000Sfujita register int bix = le->sc_rmd; 53154000Sfujita register struct lermd *rmd = &le->sc_r2->ler2_rmd[bix]; 53254000Sfujita 53354000Sfujita /* 53454000Sfujita * Out of sync with hardware, should never happen? 53554000Sfujita */ 53654000Sfujita if (rmd->rmd1 & LE_OWN) { 53755582Sfujita le->sc_rown++; 53854000Sfujita LERDWR(le->sc_r0, LE_RINT|LE_INEA, le->sc_r1->ler1_rdp); 53954000Sfujita return; 54054000Sfujita } 54154000Sfujita 54254000Sfujita /* 54354000Sfujita * Process all buffers with valid data 54454000Sfujita */ 54554000Sfujita while ((rmd->rmd1 & LE_OWN) == 0) { 54654000Sfujita int len = rmd->rmd3; 54754000Sfujita 54854000Sfujita /* Clear interrupt to avoid race condition */ 54954000Sfujita LERDWR(le->sc_r0, LE_RINT|LE_INEA, le->sc_r1->ler1_rdp); 55054000Sfujita 55154000Sfujita if (rmd->rmd1 & LE_ERR) { 55254000Sfujita le->sc_rmd = bix; 55354000Sfujita lererror(unit, "bad packet"); 55454000Sfujita le->sc_if.if_ierrors++; 55554000Sfujita } else if ((rmd->rmd1 & (LE_STP|LE_ENP)) != (LE_STP|LE_ENP)) { 55654000Sfujita /* 55754000Sfujita * Find the end of the packet so we can see how long 55854000Sfujita * it was. We still throw it away. 55954000Sfujita */ 56054000Sfujita do { 56154000Sfujita LERDWR(le->sc_r0, LE_RINT|LE_INEA, 56254000Sfujita le->sc_r1->ler1_rdp); 56354000Sfujita rmd->rmd3 = 0; 56454000Sfujita rmd->rmd1 = LE_OWN; 56554000Sfujita LENEXTRMP; 56654000Sfujita } while (!(rmd->rmd1 & (LE_OWN|LE_ERR|LE_STP|LE_ENP))); 56754000Sfujita le->sc_rmd = bix; 56854000Sfujita lererror(unit, "chained buffer"); 56954000Sfujita le->sc_rxlen++; 57054000Sfujita /* 57154000Sfujita * If search terminated without successful completion 57254000Sfujita * we reset the hardware (conservative). 57354000Sfujita */ 57454000Sfujita if ((rmd->rmd1 & (LE_OWN|LE_ERR|LE_STP|LE_ENP)) != 57554000Sfujita LE_ENP) { 57654000Sfujita lereset(unit); 57754000Sfujita return; 57854000Sfujita } 57954000Sfujita } else 58054000Sfujita leread(unit, le->sc_r2->ler2_rbuf[bix], len); 58154000Sfujita rmd->rmd3 = 0; 58254000Sfujita rmd->rmd1 = LE_OWN; 58354000Sfujita LENEXTRMP; 58454000Sfujita } 58554000Sfujita le->sc_rmd = bix; 58654000Sfujita } 58754000Sfujita 58854000Sfujita leread(unit, buf, len) 58954000Sfujita int unit; 59054000Sfujita char *buf; 59154000Sfujita int len; 59254000Sfujita { 59354000Sfujita register struct le_softc *le = &le_softc[unit]; 59454000Sfujita register struct ether_header *et; 59554000Sfujita struct mbuf *m; 59655582Sfujita int off, resid, flags; 59754000Sfujita 59854000Sfujita le->sc_if.if_ipackets++; 59954000Sfujita et = (struct ether_header *)buf; 60054000Sfujita et->ether_type = ntohs((u_short)et->ether_type); 60154000Sfujita /* adjust input length to account for header and CRC */ 60254000Sfujita len = len - sizeof(struct ether_header) - 4; 60354000Sfujita 60454000Sfujita #define ledataaddr(et, off, type) ((type)(((caddr_t)((et)+1)+(off)))) 60554000Sfujita if (et->ether_type >= ETHERTYPE_TRAIL && 60654000Sfujita et->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) { 60754000Sfujita off = (et->ether_type - ETHERTYPE_TRAIL) * 512; 60854000Sfujita if (off >= ETHERMTU) 60954000Sfujita return; /* sanity */ 61054000Sfujita et->ether_type = ntohs(*ledataaddr(et, off, u_short *)); 61154000Sfujita resid = ntohs(*(ledataaddr(et, off+2, u_short *))); 61254000Sfujita if (off + resid > len) 61354000Sfujita return; /* sanity */ 61454000Sfujita len = off + resid; 61554000Sfujita } else 61654000Sfujita off = 0; 61754000Sfujita 61854000Sfujita if (len <= 0) { 61954000Sfujita if (ledebug) 62054000Sfujita log(LOG_WARNING, 62154000Sfujita "le%d: ierror(runt packet): from %s: len=%d\n", 62254000Sfujita unit, ether_sprintf(et->ether_shost), len); 62354000Sfujita le->sc_runt++; 62454000Sfujita le->sc_if.if_ierrors++; 62554000Sfujita return; 62654000Sfujita } 62755582Sfujita flags = 0; 62855582Sfujita if (bcmp((caddr_t)etherbroadcastaddr, 62955582Sfujita (caddr_t)et->ether_dhost, sizeof(etherbroadcastaddr)) == 0) 63055582Sfujita flags |= M_BCAST; 63155582Sfujita if (et->ether_dhost[0] & 1) 63255582Sfujita flags |= M_MCAST; 63355582Sfujita 63454000Sfujita #if NBPFILTER > 0 63554000Sfujita /* 63654000Sfujita * Check if there's a bpf filter listening on this interface. 63755582Sfujita * If so, hand off the raw packet to enet. 63854000Sfujita */ 63955582Sfujita if (le->sc_if.if_bpf) { 64055582Sfujita bpf_tap(le->sc_if.if_bpf, buf, len + sizeof(struct ether_header)); 64155582Sfujita 64255582Sfujita /* 64355582Sfujita * Keep the packet if it's a broadcast or has our 64455582Sfujita * physical ethernet address (or if we support 64555582Sfujita * multicast and it's one). 64655582Sfujita */ 64755582Sfujita if ( 64855582Sfujita #ifdef MULTICAST 64955582Sfujita (flags & (M_BCAST | M_MCAST)) == 0 && 65055582Sfujita #else 65155582Sfujita (flags & M_BCAST) == 0 && 65254000Sfujita #endif 65355582Sfujita bcmp(et->ether_dhost, le->sc_addr, 65455582Sfujita sizeof(et->ether_dhost)) != 0) 65555582Sfujita return; 65655582Sfujita } 65754000Sfujita #endif 65854000Sfujita /* 65954000Sfujita * Pull packet off interface. Off is nonzero if packet 66054000Sfujita * has trailing header; m_devget will then force this header 66154000Sfujita * information to be at the front, but we still have to drop 66254000Sfujita * the type and length which are at the front of any trailer data. 66354000Sfujita */ 66454000Sfujita m = m_devget((char *)(et + 1), len, off, &le->sc_if, 0); 66554000Sfujita if (m == 0) 66654000Sfujita return; 667*58694Sakito m->m_flags |= flags; 66854000Sfujita ether_input(&le->sc_if, et, m); 66954000Sfujita } 67054000Sfujita 67154000Sfujita /* 67254000Sfujita * Routine to copy from mbuf chain to transmit 67354000Sfujita * buffer in board local memory. 67454000Sfujita */ 67554000Sfujita leput(lebuf, m) 67654000Sfujita register char *lebuf; 67754000Sfujita register struct mbuf *m; 67854000Sfujita { 67954000Sfujita register struct mbuf *mp; 68054000Sfujita register int len, tlen = 0; 68154000Sfujita 68254000Sfujita for (mp = m; mp; mp = mp->m_next) { 68354000Sfujita len = mp->m_len; 68454000Sfujita if (len == 0) 68554000Sfujita continue; 68654000Sfujita tlen += len; 68754000Sfujita bcopy(mtod(mp, char *), lebuf, len); 68854000Sfujita lebuf += len; 68954000Sfujita } 69054000Sfujita m_freem(m); 69154000Sfujita if (tlen < LEMINSIZE) { 69254000Sfujita bzero(lebuf, LEMINSIZE - tlen); 69354000Sfujita tlen = LEMINSIZE; 69454000Sfujita } 69554000Sfujita return(tlen); 69654000Sfujita } 69754000Sfujita 69854000Sfujita /* 69954000Sfujita * Process an ioctl request. 70054000Sfujita */ 70154000Sfujita leioctl(ifp, cmd, data) 70254000Sfujita register struct ifnet *ifp; 70354000Sfujita int cmd; 70454000Sfujita caddr_t data; 70554000Sfujita { 70654000Sfujita register struct ifaddr *ifa = (struct ifaddr *)data; 70754000Sfujita struct le_softc *le = &le_softc[ifp->if_unit]; 70854000Sfujita struct lereg1 *ler1 = le->sc_r1; 70954000Sfujita int s = splimp(), error = 0; 71054000Sfujita 71154000Sfujita switch (cmd) { 71254000Sfujita 71354000Sfujita case SIOCSIFADDR: 71454000Sfujita ifp->if_flags |= IFF_UP; 71554000Sfujita switch (ifa->ifa_addr->sa_family) { 71654000Sfujita #ifdef INET 71754000Sfujita case AF_INET: 71854000Sfujita leinit(ifp->if_unit); /* before arpwhohas */ 71954000Sfujita ((struct arpcom *)ifp)->ac_ipaddr = 72054000Sfujita IA_SIN(ifa)->sin_addr; 72154000Sfujita arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr); 72254000Sfujita break; 72354000Sfujita #endif 72454000Sfujita #ifdef NS 72554000Sfujita case AF_NS: 72654000Sfujita { 72754000Sfujita register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr); 72854000Sfujita 72954000Sfujita if (ns_nullhost(*ina)) 73054000Sfujita ina->x_host = *(union ns_host *)(le->sc_addr); 73154000Sfujita else { 73254000Sfujita /* 73354000Sfujita * The manual says we can't change the address 73454000Sfujita * while the receiver is armed, 73554000Sfujita * so reset everything 73654000Sfujita */ 73754000Sfujita ifp->if_flags &= ~IFF_RUNNING; 73854000Sfujita LERDWR(le->sc_r0, LE_STOP, ler1->ler1_rdp); 73954000Sfujita bcopy((caddr_t)ina->x_host.c_host, 74054000Sfujita (caddr_t)le->sc_addr, sizeof(le->sc_addr)); 74154000Sfujita } 74254000Sfujita leinit(ifp->if_unit); /* does le_setaddr() */ 74354000Sfujita break; 74454000Sfujita } 74554000Sfujita #endif 74654000Sfujita default: 74754000Sfujita leinit(ifp->if_unit); 74854000Sfujita break; 74954000Sfujita } 75054000Sfujita break; 75154000Sfujita 75257525Sakito #if defined (CCITT) && defined (LLC) 75357525Sakito case SIOCSIFCONF_X25: 75457525Sakito ifp -> if_flags |= IFF_UP; 75557525Sakito ifa -> ifa_rtrequest = cons_rtrequest; 75657525Sakito error = x25_llcglue(PRC_IFUP, ifa -> ifa_addr); 75757525Sakito if (error == 0) 75857525Sakito leinit(ifp -> if_unit); 75957525Sakito break; 76057525Sakito #endif /* CCITT && LLC */ 76157525Sakito 76257525Sakito 76354000Sfujita case SIOCSIFFLAGS: 76454000Sfujita if ((ifp->if_flags & IFF_UP) == 0 && 76554000Sfujita ifp->if_flags & IFF_RUNNING) { 76654000Sfujita LERDWR(le->sc_r0, LE_STOP, ler1->ler1_rdp); 76754000Sfujita ifp->if_flags &= ~IFF_RUNNING; 76854000Sfujita } else if (ifp->if_flags & IFF_UP && 76954000Sfujita (ifp->if_flags & IFF_RUNNING) == 0) 77054000Sfujita leinit(ifp->if_unit); 77154000Sfujita /* 77254000Sfujita * If the state of the promiscuous bit changes, the interface 77354000Sfujita * must be reset to effect the change. 77454000Sfujita */ 77554000Sfujita if (((ifp->if_flags ^ le->sc_iflags) & IFF_PROMISC) && 77654000Sfujita (ifp->if_flags & IFF_RUNNING)) { 77754000Sfujita le->sc_iflags = ifp->if_flags; 77854000Sfujita lereset(ifp->if_unit); 77954000Sfujita lestart(ifp); 78054000Sfujita } 78154000Sfujita break; 78254000Sfujita 78355582Sfujita #ifdef MULTICAST 78455582Sfujita case SIOCADDMULTI: 78555582Sfujita case SIOCDELMULTI: 78655582Sfujita /* Update our multicast list */ 78755582Sfujita error = (cmd == SIOCADDMULTI) ? 78855582Sfujita ether_addmulti((struct ifreq *)data, &le->sc_ac) : 78955582Sfujita ether_delmulti((struct ifreq *)data, &le->sc_ac); 79055582Sfujita 79155582Sfujita if (error == ENETRESET) { 79255582Sfujita /* 79355582Sfujita * Multicast list has changed; set the hardware 79455582Sfujita * filter accordingly. 79555582Sfujita */ 79655582Sfujita lereset(ifp->if_unit); 79755582Sfujita error = 0; 79855582Sfujita } 79955582Sfujita break; 80055582Sfujita #endif 80154000Sfujita default: 80254000Sfujita error = EINVAL; 80354000Sfujita } 80454000Sfujita splx(s); 80554000Sfujita return (error); 80654000Sfujita } 80754000Sfujita 80854000Sfujita leerror(unit, stat) 80954000Sfujita int unit; 81054000Sfujita int stat; 81154000Sfujita { 81254000Sfujita if (!ledebug) 81354000Sfujita return; 81454000Sfujita 81554000Sfujita /* 81654000Sfujita * Not all transceivers implement heartbeat 81754000Sfujita * so we only log CERR once. 81854000Sfujita */ 81954000Sfujita if ((stat & LE_CERR) && le_softc[unit].sc_cerr) 82054000Sfujita return; 82154000Sfujita log(LOG_WARNING, 82254000Sfujita "le%d: error: stat=%b\n", unit, 82354000Sfujita stat, 82454000Sfujita "\20\20ERR\17BABL\16CERR\15MISS\14MERR\13RINT\12TINT\11IDON\10INTR\07INEA\06RXON\05TXON\04TDMD\03STOP\02STRT\01INIT"); 82554000Sfujita } 82654000Sfujita 82754000Sfujita lererror(unit, msg) 82854000Sfujita int unit; 82954000Sfujita char *msg; 83054000Sfujita { 83154000Sfujita register struct le_softc *le = &le_softc[unit]; 83254000Sfujita register struct lermd *rmd; 83354000Sfujita int len; 83454000Sfujita 83554000Sfujita if (!ledebug) 83654000Sfujita return; 83754000Sfujita 83854000Sfujita rmd = &le->sc_r2->ler2_rmd[le->sc_rmd]; 83954000Sfujita len = rmd->rmd3; 84054000Sfujita log(LOG_WARNING, 84154000Sfujita "le%d: ierror(%s): from %s: buf=%d, len=%d, rmd1=%b\n", 84254000Sfujita unit, msg, 84354000Sfujita len > 11 ? 84454000Sfujita ether_sprintf((u_char *)&le->sc_r2->ler2_rbuf[le->sc_rmd][6]) : 84554000Sfujita "unknown", 84654000Sfujita le->sc_rmd, len, 84754000Sfujita rmd->rmd1, 84854000Sfujita "\20\20OWN\17ERR\16FRAM\15OFLO\14CRC\13RBUF\12STP\11ENP"); 84954000Sfujita } 85054000Sfujita 85154000Sfujita lexerror(unit) 85254000Sfujita int unit; 85354000Sfujita { 85454000Sfujita register struct le_softc *le = &le_softc[unit]; 85554000Sfujita register struct letmd *tmd; 85654000Sfujita int len; 85754000Sfujita 85854000Sfujita if (!ledebug) 85954000Sfujita return; 86054000Sfujita 86154000Sfujita tmd = le->sc_r2->ler2_tmd; 86254000Sfujita len = -tmd->tmd2; 86354000Sfujita log(LOG_WARNING, 86454000Sfujita "le%d: oerror: to %s: buf=%d, len=%d, tmd1=%b, tmd3=%b\n", 86554000Sfujita unit, 86654000Sfujita len > 5 ? 86754000Sfujita ether_sprintf((u_char *)&le->sc_r2->ler2_tbuf[0][0]) : 86854000Sfujita "unknown", 86954000Sfujita 0, len, 87054000Sfujita tmd->tmd1, 87154000Sfujita "\20\20OWN\17ERR\16RES\15MORE\14ONE\13DEF\12STP\11ENP", 87254000Sfujita tmd->tmd3, 87354000Sfujita "\20\20BUFF\17UFLO\16RES\15LCOL\14LCAR\13RTRY"); 87454000Sfujita } 87554000Sfujita #endif 876