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