141480Smckusick /* 241480Smckusick * Copyright (c) 1982, 1990 The Regents of the University of California. 341480Smckusick * All rights reserved. 441480Smckusick * 541480Smckusick * %sccs.include.redist.c% 641480Smckusick * 7*54719Ssklower * @(#)if_le.c 7.12 (Berkeley) 07/06/92 841480Smckusick */ 941480Smckusick 1041480Smckusick #include "le.h" 1141480Smckusick #if NLE > 0 1241480Smckusick 1347567Smccanne #include "bpfilter.h" 1447567Smccanne 1541480Smckusick /* 1641480Smckusick * AMD 7990 LANCE 1741480Smckusick * 18*54719Ssklower * This driver will accept tailer encapsulated packets even 1941480Smckusick * though it buys us nothing. The motivation was to avoid incompatibilities 2041480Smckusick * with VAXen, SUNs, and others that handle and benefit from them. 2141480Smckusick * This reasoning is dubious. 2241480Smckusick */ 2345788Sbostic #include "sys/param.h" 2453034Ssklower #include "sys/proc.h" 2545788Sbostic #include "sys/systm.h" 2645788Sbostic #include "sys/mbuf.h" 2745788Sbostic #include "sys/buf.h" 2845788Sbostic #include "sys/protosw.h" 2945788Sbostic #include "sys/socket.h" 3045788Sbostic #include "sys/syslog.h" 3145788Sbostic #include "sys/ioctl.h" 3245788Sbostic #include "sys/errno.h" 3341480Smckusick 3445788Sbostic #include "net/if.h" 3545788Sbostic #include "net/netisr.h" 3645788Sbostic #include "net/route.h" 3741480Smckusick 3841480Smckusick #ifdef INET 3945788Sbostic #include "netinet/in.h" 4045788Sbostic #include "netinet/in_systm.h" 4145788Sbostic #include "netinet/in_var.h" 4245788Sbostic #include "netinet/ip.h" 4345788Sbostic #include "netinet/if_ether.h" 4441480Smckusick #endif 4541480Smckusick 4641480Smckusick #ifdef NS 4745788Sbostic #include "netns/ns.h" 4845788Sbostic #include "netns/ns_if.h" 4941480Smckusick #endif 5041480Smckusick 5145788Sbostic #include "../include/cpu.h" 5245788Sbostic #include "../hp300/isr.h" 5345788Sbostic #include "../include/mtpr.h" 5453930Shibler #include "hp/dev/device.h" 5541480Smckusick #include "if_lereg.h" 5641480Smckusick 5747567Smccanne #if NBPFILTER > 0 5847567Smccanne #include "../net/bpf.h" 5947567Smccanne #include "../net/bpfdesc.h" 6047567Smccanne #endif 6147567Smccanne 6241480Smckusick /* offsets for: ID, REGS, MEM, NVRAM */ 6341480Smckusick int lestd[] = { 0, 0x4000, 0x8000, 0xC008 }; 6441480Smckusick 6541480Smckusick int leattach(); 6641480Smckusick struct driver ledriver = { 6741480Smckusick leattach, "le", 6841480Smckusick }; 6941480Smckusick 7041480Smckusick struct isr le_isr[NLE]; 7141480Smckusick int ledebug = 0; /* console error messages */ 7241480Smckusick 7341480Smckusick int leintr(), leinit(), leioctl(), lestart(), ether_output(); 7453034Ssklower struct mbuf *m_devget(); 7541480Smckusick extern struct ifnet loif; 7641480Smckusick 7741480Smckusick /* 7841480Smckusick * Ethernet software status per interface. 7941480Smckusick * 8041480Smckusick * Each interface is referenced by a network interface structure, 8141480Smckusick * le_if, which the routing code uses to locate the interface. 8241480Smckusick * This structure contains the output queue for the interface, its address, ... 8341480Smckusick */ 8441480Smckusick struct le_softc { 8541480Smckusick struct arpcom sc_ac; /* common Ethernet structures */ 8641480Smckusick #define sc_if sc_ac.ac_if /* network-visible interface */ 8741480Smckusick #define sc_addr sc_ac.ac_enaddr /* hardware Ethernet address */ 8841480Smckusick struct lereg0 *sc_r0; /* DIO registers */ 8941480Smckusick struct lereg1 *sc_r1; /* LANCE registers */ 9041480Smckusick struct lereg2 *sc_r2; /* dual-port RAM */ 9141480Smckusick int sc_rmd; /* predicted next rmd to process */ 9253930Shibler int sc_tmd; /* next available tmd */ 9353930Shibler int sc_txcnt; /* # of transmit buffers in use */ 9453930Shibler /* stats */ 9541480Smckusick int sc_runt; 9641480Smckusick int sc_jab; 9741480Smckusick int sc_merr; 9841480Smckusick int sc_babl; 9941480Smckusick int sc_cerr; 10041480Smckusick int sc_miss; 10153930Shibler int sc_rown; 10241480Smckusick int sc_xown; 10353930Shibler int sc_xown2; 10441480Smckusick int sc_uflo; 10541480Smckusick int sc_rxlen; 10641480Smckusick int sc_rxoff; 10741480Smckusick int sc_txoff; 10841480Smckusick int sc_busy; 10948771Smccanne short sc_iflags; 11041480Smckusick } le_softc[NLE]; 11141480Smckusick 11241480Smckusick /* access LANCE registers */ 11341480Smckusick #define LERDWR(cntl, src, dst) \ 11441480Smckusick do { \ 11541480Smckusick (dst) = (src); \ 11641480Smckusick } while (((cntl)->ler0_status & LE_ACK) == 0); 11741480Smckusick 11841480Smckusick /* 11941480Smckusick * Interface exists: make available by filling in network interface 12041480Smckusick * record. System will initialize the interface when it is ready 12141480Smckusick * to accept packets. 12241480Smckusick */ 12341480Smckusick leattach(hd) 12441480Smckusick struct hp_device *hd; 12541480Smckusick { 12641480Smckusick register struct lereg0 *ler0; 12741480Smckusick register struct lereg2 *ler2; 12841480Smckusick struct lereg2 *lemem = 0; 12941480Smckusick struct le_softc *le = &le_softc[hd->hp_unit]; 13041480Smckusick struct ifnet *ifp = &le->sc_if; 13141480Smckusick char *cp; 13241480Smckusick int i; 13341480Smckusick 13441480Smckusick ler0 = le->sc_r0 = (struct lereg0 *)(lestd[0] + (int)hd->hp_addr); 13541480Smckusick le->sc_r1 = (struct lereg1 *)(lestd[1] + (int)hd->hp_addr); 13641480Smckusick ler2 = le->sc_r2 = (struct lereg2 *)(lestd[2] + (int)hd->hp_addr); 13741480Smckusick if (ler0->ler0_id != LEID) 13841480Smckusick return(0); 13941480Smckusick le_isr[hd->hp_unit].isr_intr = leintr; 14041480Smckusick hd->hp_ipl = le_isr[hd->hp_unit].isr_ipl = LE_IPL(ler0->ler0_status); 14141480Smckusick le_isr[hd->hp_unit].isr_arg = hd->hp_unit; 14241480Smckusick ler0->ler0_id = 0xFF; 14341480Smckusick DELAY(100); 14441480Smckusick 14541480Smckusick /* 14641480Smckusick * Read the ethernet address off the board, one nibble at a time. 14741480Smckusick */ 14841480Smckusick cp = (char *)(lestd[3] + (int)hd->hp_addr); 14941480Smckusick for (i = 0; i < sizeof(le->sc_addr); i++) { 15041480Smckusick le->sc_addr[i] = (*++cp & 0xF) << 4; 15141480Smckusick cp++; 15241480Smckusick le->sc_addr[i] |= *++cp & 0xF; 15341480Smckusick cp++; 15441480Smckusick } 15541480Smckusick printf("le%d: hardware address %s\n", hd->hp_unit, 15641480Smckusick ether_sprintf(le->sc_addr)); 15741480Smckusick 15841480Smckusick /* 15941480Smckusick * Setup for transmit/receive 16041480Smckusick */ 16141480Smckusick ler2->ler2_mode = LE_MODE; 162*54719Ssklower ler2->ler2_ladrf[0] = 0; 163*54719Ssklower ler2->ler2_ladrf[1] = 0; 16441480Smckusick ler2->ler2_rlen = LE_RLEN; 16541480Smckusick ler2->ler2_rdra = (int)lemem->ler2_rmd; 16641480Smckusick ler2->ler2_tlen = LE_TLEN; 16741480Smckusick ler2->ler2_tdra = (int)lemem->ler2_tmd; 16841480Smckusick isrlink(&le_isr[hd->hp_unit]); 16941480Smckusick ler0->ler0_status = LE_IE; 17041480Smckusick 17141480Smckusick ifp->if_unit = hd->hp_unit; 17241480Smckusick ifp->if_name = "le"; 17341480Smckusick ifp->if_mtu = ETHERMTU; 17441480Smckusick ifp->if_init = leinit; 17541480Smckusick ifp->if_ioctl = leioctl; 17641480Smckusick ifp->if_output = ether_output; 17741480Smckusick ifp->if_start = lestart; 178*54719Ssklower #ifdef MULTICAST 179*54719Ssklower ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; 180*54719Ssklower #else 18141480Smckusick ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX; 182*54719Ssklower #endif 18347567Smccanne #if NBPFILTER > 0 184*54719Ssklower bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header)); 18547567Smccanne #endif 18641480Smckusick if_attach(ifp); 18741480Smckusick return (1); 18841480Smckusick } 18941480Smckusick 190*54719Ssklower #ifdef MULTICAST 191*54719Ssklower /* 192*54719Ssklower * Setup the logical address filter 193*54719Ssklower */ 194*54719Ssklower void 195*54719Ssklower lesetladrf(sc) 196*54719Ssklower register struct le_softc *sc; 197*54719Ssklower { 198*54719Ssklower register volatile struct lereg2 *ler2 = sc->sc_r2; 199*54719Ssklower register struct ifnet *ifp = &sc->sc_if; 200*54719Ssklower register struct ether_multi *enm; 201*54719Ssklower register u_char *cp; 202*54719Ssklower register u_long crc; 203*54719Ssklower register u_long c; 204*54719Ssklower register int i, len; 205*54719Ssklower struct ether_multistep step; 206*54719Ssklower 207*54719Ssklower /* 208*54719Ssklower * Set up multicast address filter by passing all multicast 209*54719Ssklower * addresses through a crc generator, and then using the high 210*54719Ssklower * order 6 bits as a index into the 64 bit logical address 211*54719Ssklower * filter. The high order two bits select the word, while the 212*54719Ssklower * rest of the bits select the bit within the word. 213*54719Ssklower */ 214*54719Ssklower 215*54719Ssklower ler2->ler2_ladrf[0] = 0; 216*54719Ssklower ler2->ler2_ladrf[1] = 0; 217*54719Ssklower ifp->if_flags &= ~IFF_ALLMULTI; 218*54719Ssklower ETHER_FIRST_MULTI(step, &sc->sc_ac, enm); 219*54719Ssklower while (enm != NULL) { 220*54719Ssklower if (bcmp((caddr_t)&enm->enm_addrlo, 221*54719Ssklower (caddr_t)&enm->enm_addrhi, sizeof(enm->enm_addrlo)) == 0) { 222*54719Ssklower /* 223*54719Ssklower * We must listen to a range of multicast 224*54719Ssklower * addresses. For now, just accept all 225*54719Ssklower * multicasts, rather than trying to set only 226*54719Ssklower * those filter bits needed to match the range. 227*54719Ssklower * (At this time, the only use of address 228*54719Ssklower * ranges is for IP multicast routing, for 229*54719Ssklower * which the range is big enough to require all 230*54719Ssklower * bits set.) 231*54719Ssklower */ 232*54719Ssklower ler2->ler2_ladrf[0] = 0xffffffff; 233*54719Ssklower ler2->ler2_ladrf[1] = 0xffffffff; 234*54719Ssklower ifp->if_flags |= IFF_ALLMULTI; 235*54719Ssklower return; 236*54719Ssklower } 237*54719Ssklower 238*54719Ssklower cp = (unsigned char *)&enm->enm_addrlo; 239*54719Ssklower c = *cp; 240*54719Ssklower crc = 0xffffffff; 241*54719Ssklower len = 6; 242*54719Ssklower while (len-- > 0) { 243*54719Ssklower c = *cp; 244*54719Ssklower for (i = 0; i < 8; i++) { 245*54719Ssklower if ((c & 0x01) ^ (crc & 0x01)) { 246*54719Ssklower crc >>= 1; 247*54719Ssklower crc = crc ^ 0xedb88320; 248*54719Ssklower } 249*54719Ssklower else 250*54719Ssklower crc >>= 1; 251*54719Ssklower c >>= 1; 252*54719Ssklower } 253*54719Ssklower cp++; 254*54719Ssklower } 255*54719Ssklower /* Just want the 6 most significant bits. */ 256*54719Ssklower crc = crc >> 26; 257*54719Ssklower 258*54719Ssklower /* Turn on the corresponding bit in the filter. */ 259*54719Ssklower ler2->ler2_ladrf[crc >> 5] |= 1 << (crc & 0x1f); 260*54719Ssklower 261*54719Ssklower ETHER_NEXT_MULTI(step, enm); 262*54719Ssklower } 263*54719Ssklower } 264*54719Ssklower #endif 265*54719Ssklower 26650816Ssklower ledrinit(ler2, le) 26741480Smckusick register struct lereg2 *ler2; 26850816Ssklower register struct le_softc *le; 26941480Smckusick { 27041480Smckusick register struct lereg2 *lemem = 0; 27141480Smckusick register int i; 27241480Smckusick 27350816Ssklower ler2->ler2_padr[0] = le->sc_addr[1]; 27450816Ssklower ler2->ler2_padr[1] = le->sc_addr[0]; 27550816Ssklower ler2->ler2_padr[2] = le->sc_addr[3]; 27650816Ssklower ler2->ler2_padr[3] = le->sc_addr[2]; 27750816Ssklower ler2->ler2_padr[4] = le->sc_addr[5]; 27850816Ssklower ler2->ler2_padr[5] = le->sc_addr[4]; 27941480Smckusick for (i = 0; i < LERBUF; i++) { 28041480Smckusick ler2->ler2_rmd[i].rmd0 = (int)lemem->ler2_rbuf[i]; 28141480Smckusick ler2->ler2_rmd[i].rmd1 = LE_OWN; 28241480Smckusick ler2->ler2_rmd[i].rmd2 = -LEMTU; 28341480Smckusick ler2->ler2_rmd[i].rmd3 = 0; 28441480Smckusick } 28541480Smckusick for (i = 0; i < LETBUF; i++) { 28641480Smckusick ler2->ler2_tmd[i].tmd0 = (int)lemem->ler2_tbuf[i]; 28741480Smckusick ler2->ler2_tmd[i].tmd1 = 0; 28841480Smckusick ler2->ler2_tmd[i].tmd2 = 0; 28941480Smckusick ler2->ler2_tmd[i].tmd3 = 0; 29041480Smckusick } 291*54719Ssklower /* Setup the logical address filter */ 292*54719Ssklower #ifdef MULTICAST 293*54719Ssklower lesetladrf(le); 294*54719Ssklower #else 295*54719Ssklower ler2->ler2_ladrf[0] = 0; 296*54719Ssklower ler2->ler2_ladrf[1] = 0; 297*54719Ssklower #endif 29841480Smckusick } 29941480Smckusick 30041480Smckusick lereset(unit) 30141480Smckusick register int unit; 30241480Smckusick { 30341480Smckusick register struct le_softc *le = &le_softc[unit]; 30441480Smckusick register struct lereg0 *ler0 = le->sc_r0; 30541480Smckusick register struct lereg1 *ler1 = le->sc_r1; 30641480Smckusick register struct lereg2 *lemem = 0; 30741480Smckusick register int timo = 100000; 30841480Smckusick register int stat; 30941480Smckusick 31041480Smckusick #ifdef lint 31141480Smckusick stat = unit; 31241480Smckusick #endif 31347567Smccanne #if NBPFILTER > 0 31447567Smccanne if (le->sc_if.if_flags & IFF_PROMISC) 31547567Smccanne /* set the promiscuous bit */ 31647567Smccanne le->sc_r2->ler2_mode = LE_MODE|0x8000; 31747567Smccanne else 31847567Smccanne le->sc_r2->ler2_mode = LE_MODE; 31947567Smccanne #endif 32041480Smckusick LERDWR(ler0, LE_CSR0, ler1->ler1_rap); 32141480Smckusick LERDWR(ler0, LE_STOP, ler1->ler1_rdp); 32250816Ssklower ledrinit(le->sc_r2, le); 32353930Shibler le->sc_rmd = le->sc_tmd = 0; 32441480Smckusick LERDWR(ler0, LE_CSR1, ler1->ler1_rap); 32541480Smckusick LERDWR(ler0, (int)&lemem->ler2_mode, ler1->ler1_rdp); 32641480Smckusick LERDWR(ler0, LE_CSR2, ler1->ler1_rap); 32741480Smckusick LERDWR(ler0, 0, ler1->ler1_rdp); 32841480Smckusick LERDWR(ler0, LE_CSR0, ler1->ler1_rap); 32941480Smckusick LERDWR(ler0, LE_INIT, ler1->ler1_rdp); 33041480Smckusick do { 33141480Smckusick if (--timo == 0) { 33241480Smckusick printf("le%d: init timeout, stat = 0x%x\n", 33341480Smckusick unit, stat); 33441480Smckusick break; 33541480Smckusick } 33641480Smckusick LERDWR(ler0, ler1->ler1_rdp, stat); 33741480Smckusick } while ((stat & LE_IDON) == 0); 33841480Smckusick LERDWR(ler0, LE_STOP, ler1->ler1_rdp); 33941480Smckusick LERDWR(ler0, LE_CSR3, ler1->ler1_rap); 34041480Smckusick LERDWR(ler0, LE_BSWP, ler1->ler1_rdp); 34141480Smckusick LERDWR(ler0, LE_CSR0, ler1->ler1_rap); 34241480Smckusick LERDWR(ler0, LE_STRT | LE_INEA, ler1->ler1_rdp); 34341480Smckusick le->sc_if.if_flags &= ~IFF_OACTIVE; 34453930Shibler le->sc_txcnt = 0; 34541480Smckusick } 34641480Smckusick 34741480Smckusick /* 34841480Smckusick * Initialization of interface 34941480Smckusick */ 35041480Smckusick leinit(unit) 35141480Smckusick int unit; 35241480Smckusick { 35353034Ssklower register struct ifnet *ifp = &le_softc[unit].sc_if; 35453034Ssklower register struct ifaddr *ifa; 35541480Smckusick int s; 35641480Smckusick 35741480Smckusick /* not yet, if address still unknown */ 35853034Ssklower for (ifa = ifp->if_addrlist;; ifa = ifa->ifa_next) 35953034Ssklower if (ifa == 0) 36053034Ssklower return; 36153034Ssklower else if (ifa->ifa_addr && ifa->ifa_addr->sa_family != AF_LINK) 36253034Ssklower break; 36341480Smckusick if ((ifp->if_flags & IFF_RUNNING) == 0) { 36441480Smckusick s = splimp(); 36541480Smckusick ifp->if_flags |= IFF_RUNNING; 36641480Smckusick lereset(unit); 36741480Smckusick (void) lestart(ifp); 36841480Smckusick splx(s); 36941480Smckusick } 37041480Smckusick } 37141480Smckusick 37241480Smckusick /* 37341480Smckusick * Start output on interface. Get another datagram to send 37441480Smckusick * off of the interface queue, and copy it to the interface 37541480Smckusick * before starting the output. 37641480Smckusick */ 37741480Smckusick lestart(ifp) 37841480Smckusick struct ifnet *ifp; 37941480Smckusick { 38041480Smckusick register struct le_softc *le = &le_softc[ifp->if_unit]; 38141480Smckusick register struct letmd *tmd; 38241480Smckusick register struct mbuf *m; 38341480Smckusick int len; 38441480Smckusick 38541480Smckusick if ((le->sc_if.if_flags & IFF_RUNNING) == 0) 38641480Smckusick return (0); 38753930Shibler tmd = &le->sc_r2->ler2_tmd[le->sc_tmd]; 38853930Shibler do { 38953930Shibler if (tmd->tmd1 & LE_OWN) { 39053930Shibler le->sc_xown2++; 39153930Shibler return (0); 39253930Shibler } 39353930Shibler IF_DEQUEUE(&le->sc_if.if_snd, m); 39453930Shibler if (m == 0) 39553930Shibler return (0); 39653930Shibler len = leput(le->sc_r2->ler2_tbuf[le->sc_tmd], m); 39747567Smccanne #if NBPFILTER > 0 39853930Shibler /* 39953930Shibler * If bpf is listening on this interface, let it 40053930Shibler * see the packet before we commit it to the wire. 40153930Shibler */ 402*54719Ssklower if (ifp->if_bpf) 403*54719Ssklower bpf_tap(ifp->if_bpf, le->sc_r2->ler2_tbuf[le->sc_tmd], 40453930Shibler len); 40547567Smccanne #endif 40653930Shibler 40753930Shibler tmd->tmd3 = 0; 40853930Shibler tmd->tmd2 = -len; 40953034Ssklower tmd->tmd1 = LE_OWN | LE_STP | LE_ENP; 41053930Shibler if (++le->sc_tmd == LETBUF) { 41153930Shibler le->sc_tmd = 0; 41253930Shibler tmd = le->sc_r2->ler2_tmd; 41353930Shibler } else 41453930Shibler tmd++; 41553930Shibler } while (++le->sc_txcnt < LETBUF); 41653930Shibler le->sc_if.if_flags |= IFF_OACTIVE; 41741480Smckusick return (0); 41841480Smckusick } 41941480Smckusick 42041480Smckusick leintr(unit) 42141480Smckusick register int unit; 42241480Smckusick { 42341480Smckusick register struct le_softc *le = &le_softc[unit]; 42441480Smckusick register struct lereg0 *ler0 = le->sc_r0; 42541480Smckusick register struct lereg1 *ler1; 42641480Smckusick register int stat; 42741480Smckusick 42841480Smckusick if ((ler0->ler0_status & LE_IR) == 0) 42941480Smckusick return(0); 43041480Smckusick if (ler0->ler0_status & LE_JAB) { 43141480Smckusick le->sc_jab++; 43241480Smckusick lereset(unit); 43341480Smckusick return(1); 43441480Smckusick } 43541480Smckusick ler1 = le->sc_r1; 43641480Smckusick LERDWR(ler0, ler1->ler1_rdp, stat); 43741480Smckusick if (stat & LE_SERR) { 43841480Smckusick leerror(unit, stat); 43941480Smckusick if (stat & LE_MERR) { 44041480Smckusick le->sc_merr++; 44141480Smckusick lereset(unit); 44241480Smckusick return(1); 44341480Smckusick } 44441480Smckusick if (stat & LE_BABL) 44541480Smckusick le->sc_babl++; 44641480Smckusick if (stat & LE_CERR) 44741480Smckusick le->sc_cerr++; 44841480Smckusick if (stat & LE_MISS) 44941480Smckusick le->sc_miss++; 45041480Smckusick LERDWR(ler0, LE_BABL|LE_CERR|LE_MISS|LE_INEA, ler1->ler1_rdp); 45141480Smckusick } 45241480Smckusick if ((stat & LE_RXON) == 0) { 45341480Smckusick le->sc_rxoff++; 45441480Smckusick lereset(unit); 45541480Smckusick return(1); 45641480Smckusick } 45741480Smckusick if ((stat & LE_TXON) == 0) { 45841480Smckusick le->sc_txoff++; 45941480Smckusick lereset(unit); 46041480Smckusick return(1); 46141480Smckusick } 46253930Shibler if (stat & LE_RINT) 46341480Smckusick lerint(unit); 46453930Shibler if (stat & LE_TINT) 46541480Smckusick lexint(unit); 46641480Smckusick return(1); 46741480Smckusick } 46841480Smckusick 46941480Smckusick /* 47041480Smckusick * Ethernet interface transmitter interrupt. 47141480Smckusick * Start another output if more data to send. 47241480Smckusick */ 47341480Smckusick lexint(unit) 47441480Smckusick register int unit; 47541480Smckusick { 47641480Smckusick register struct le_softc *le = &le_softc[unit]; 47750823Ssklower register struct letmd *tmd; 47853930Shibler int i, gotone = 0; 47941480Smckusick 48053930Shibler do { 48153930Shibler if ((i = le->sc_tmd - le->sc_txcnt) < 0) 48253930Shibler i += LETBUF; 48353930Shibler tmd = &le->sc_r2->ler2_tmd[i]; 48453930Shibler if (tmd->tmd1 & LE_OWN) { 48553930Shibler if (gotone) 48653930Shibler break; 48753930Shibler le->sc_xown++; 48853930Shibler return; 48941480Smckusick } 49053930Shibler 49153930Shibler /* clear interrupt */ 49253930Shibler LERDWR(le->sc_r0, LE_TINT|LE_INEA, le->sc_r1->ler1_rdp); 49353930Shibler 49453930Shibler /* XXX documentation says BUFF not included in ERR */ 49553930Shibler if ((tmd->tmd1 & LE_ERR) || (tmd->tmd3 & LE_TBUFF)) { 49653930Shibler lexerror(unit); 49753930Shibler le->sc_if.if_oerrors++; 49853930Shibler if (tmd->tmd3 & (LE_TBUFF|LE_UFLO)) { 49953930Shibler le->sc_uflo++; 50053930Shibler lereset(unit); 50153930Shibler } else if (tmd->tmd3 & LE_LCOL) 50253930Shibler le->sc_if.if_collisions++; 50353930Shibler else if (tmd->tmd3 & LE_RTRY) 50453930Shibler le->sc_if.if_collisions += 16; 50553930Shibler } else if (tmd->tmd1 & LE_ONE) 50641480Smckusick le->sc_if.if_collisions++; 50753930Shibler else if (tmd->tmd1 & LE_MORE) 50853930Shibler /* what is the real number? */ 50953930Shibler le->sc_if.if_collisions += 2; 51053930Shibler else 51153930Shibler le->sc_if.if_opackets++; 51253930Shibler gotone++; 51353930Shibler } while (--le->sc_txcnt > 0); 51441480Smckusick le->sc_if.if_flags &= ~IFF_OACTIVE; 51541480Smckusick (void) lestart(&le->sc_if); 51641480Smckusick } 51741480Smckusick 51841480Smckusick #define LENEXTRMP \ 51941480Smckusick if (++bix == LERBUF) bix = 0, rmd = le->sc_r2->ler2_rmd; else ++rmd 52041480Smckusick 52141480Smckusick /* 52241480Smckusick * Ethernet interface receiver interrupt. 52341480Smckusick * If input error just drop packet. 52441480Smckusick * Decapsulate packet based on type and pass to type specific 52541480Smckusick * higher-level input routine. 52641480Smckusick */ 52741480Smckusick lerint(unit) 52841480Smckusick int unit; 52941480Smckusick { 53041480Smckusick register struct le_softc *le = &le_softc[unit]; 53141480Smckusick register int bix = le->sc_rmd; 53241480Smckusick register struct lermd *rmd = &le->sc_r2->ler2_rmd[bix]; 53341480Smckusick 53441480Smckusick /* 53541480Smckusick * Out of sync with hardware, should never happen? 53641480Smckusick */ 53741480Smckusick if (rmd->rmd1 & LE_OWN) { 53853930Shibler le->sc_rown++; 53941480Smckusick LERDWR(le->sc_r0, LE_RINT|LE_INEA, le->sc_r1->ler1_rdp); 54041480Smckusick return; 54141480Smckusick } 54241480Smckusick 54341480Smckusick /* 54441480Smckusick * Process all buffers with valid data 54541480Smckusick */ 54641480Smckusick while ((rmd->rmd1 & LE_OWN) == 0) { 54741480Smckusick int len = rmd->rmd3; 54841480Smckusick 54941480Smckusick /* Clear interrupt to avoid race condition */ 55041480Smckusick LERDWR(le->sc_r0, LE_RINT|LE_INEA, le->sc_r1->ler1_rdp); 55141480Smckusick 55241480Smckusick if (rmd->rmd1 & LE_ERR) { 55341480Smckusick le->sc_rmd = bix; 55441480Smckusick lererror(unit, "bad packet"); 55541480Smckusick le->sc_if.if_ierrors++; 55641480Smckusick } else if ((rmd->rmd1 & (LE_STP|LE_ENP)) != (LE_STP|LE_ENP)) { 55741480Smckusick /* 55841480Smckusick * Find the end of the packet so we can see how long 55941480Smckusick * it was. We still throw it away. 56041480Smckusick */ 56141480Smckusick do { 56241480Smckusick LERDWR(le->sc_r0, LE_RINT|LE_INEA, 56341480Smckusick le->sc_r1->ler1_rdp); 56441480Smckusick rmd->rmd3 = 0; 56541480Smckusick rmd->rmd1 = LE_OWN; 56641480Smckusick LENEXTRMP; 56741480Smckusick } while (!(rmd->rmd1 & (LE_OWN|LE_ERR|LE_STP|LE_ENP))); 56841480Smckusick le->sc_rmd = bix; 56941480Smckusick lererror(unit, "chained buffer"); 57041480Smckusick le->sc_rxlen++; 57141480Smckusick /* 57241480Smckusick * If search terminated without successful completion 57341480Smckusick * we reset the hardware (conservative). 57441480Smckusick */ 57541480Smckusick if ((rmd->rmd1 & (LE_OWN|LE_ERR|LE_STP|LE_ENP)) != 57641480Smckusick LE_ENP) { 57741480Smckusick lereset(unit); 57841480Smckusick return; 57941480Smckusick } 58041480Smckusick } else 58141480Smckusick leread(unit, le->sc_r2->ler2_rbuf[bix], len); 58241480Smckusick rmd->rmd3 = 0; 58341480Smckusick rmd->rmd1 = LE_OWN; 58441480Smckusick LENEXTRMP; 58541480Smckusick } 58641480Smckusick le->sc_rmd = bix; 58741480Smckusick } 58841480Smckusick 58941480Smckusick leread(unit, buf, len) 59041480Smckusick int unit; 59141480Smckusick char *buf; 59241480Smckusick int len; 59341480Smckusick { 59441480Smckusick register struct le_softc *le = &le_softc[unit]; 59541480Smckusick register struct ether_header *et; 59641480Smckusick struct mbuf *m; 597*54719Ssklower int off, resid, flags; 59841480Smckusick 59941480Smckusick le->sc_if.if_ipackets++; 60041480Smckusick et = (struct ether_header *)buf; 60141480Smckusick et->ether_type = ntohs((u_short)et->ether_type); 60241480Smckusick /* adjust input length to account for header and CRC */ 60341480Smckusick len = len - sizeof(struct ether_header) - 4; 60441480Smckusick 60541480Smckusick #define ledataaddr(et, off, type) ((type)(((caddr_t)((et)+1)+(off)))) 60641480Smckusick if (et->ether_type >= ETHERTYPE_TRAIL && 60741480Smckusick et->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) { 60841480Smckusick off = (et->ether_type - ETHERTYPE_TRAIL) * 512; 60941480Smckusick if (off >= ETHERMTU) 61041480Smckusick return; /* sanity */ 61141480Smckusick et->ether_type = ntohs(*ledataaddr(et, off, u_short *)); 61241480Smckusick resid = ntohs(*(ledataaddr(et, off+2, u_short *))); 61341480Smckusick if (off + resid > len) 61441480Smckusick return; /* sanity */ 61541480Smckusick len = off + resid; 61641480Smckusick } else 61741480Smckusick off = 0; 61841480Smckusick 61941480Smckusick if (len <= 0) { 62041480Smckusick if (ledebug) 62141480Smckusick log(LOG_WARNING, 62241480Smckusick "le%d: ierror(runt packet): from %s: len=%d\n", 62341480Smckusick unit, ether_sprintf(et->ether_shost), len); 62441480Smckusick le->sc_runt++; 62541480Smckusick le->sc_if.if_ierrors++; 62641480Smckusick return; 62741480Smckusick } 628*54719Ssklower flags = 0; 629*54719Ssklower if (bcmp((caddr_t)etherbroadcastaddr, 630*54719Ssklower (caddr_t)et->ether_dhost, sizeof(etherbroadcastaddr)) == 0) 631*54719Ssklower flags |= M_BCAST; 632*54719Ssklower if (et->ether_dhost[0] & 1) 633*54719Ssklower flags |= M_MCAST; 634*54719Ssklower 63547567Smccanne #if NBPFILTER > 0 63647567Smccanne /* 63747567Smccanne * Check if there's a bpf filter listening on this interface. 638*54719Ssklower * If so, hand off the raw packet to enet. 63947567Smccanne */ 640*54719Ssklower if (le->sc_if.if_bpf) { 641*54719Ssklower bpf_tap(le->sc_if.if_bpf, buf, len + sizeof(struct ether_header)); 642*54719Ssklower 643*54719Ssklower /* 644*54719Ssklower * Keep the packet if it's a broadcast or has our 645*54719Ssklower * physical ethernet address (or if we support 646*54719Ssklower * multicast and it's one). 647*54719Ssklower */ 648*54719Ssklower if ( 649*54719Ssklower #ifdef MULTICAST 650*54719Ssklower (flags & (M_BCAST | M_MCAST)) == 0 && 651*54719Ssklower #else 652*54719Ssklower (flags & M_BCAST) == 0 && 65347567Smccanne #endif 654*54719Ssklower bcmp(et->ether_dhost, le->sc_addr, 655*54719Ssklower sizeof(et->ether_dhost)) != 0) 656*54719Ssklower return; 657*54719Ssklower } 65850816Ssklower #endif 65950816Ssklower /* 66041480Smckusick * Pull packet off interface. Off is nonzero if packet 66153034Ssklower * has trailing header; m_devget will then force this header 66241480Smckusick * information to be at the front, but we still have to drop 66341480Smckusick * the type and length which are at the front of any trailer data. 66441480Smckusick */ 66553034Ssklower m = m_devget((char *)(et + 1), len, off, &le->sc_if, 0); 666*54719Ssklower m->m_flags |= flags; 66741480Smckusick if (m == 0) 66841480Smckusick return; 66941480Smckusick ether_input(&le->sc_if, et, m); 67041480Smckusick } 67141480Smckusick 67241480Smckusick /* 67341480Smckusick * Routine to copy from mbuf chain to transmit 67441480Smckusick * buffer in board local memory. 67541480Smckusick */ 67641480Smckusick leput(lebuf, m) 67741480Smckusick register char *lebuf; 67841480Smckusick register struct mbuf *m; 67941480Smckusick { 68041480Smckusick register struct mbuf *mp; 68141480Smckusick register int len, tlen = 0; 68241480Smckusick 68341480Smckusick for (mp = m; mp; mp = mp->m_next) { 68441480Smckusick len = mp->m_len; 68541480Smckusick if (len == 0) 68641480Smckusick continue; 68741480Smckusick tlen += len; 68841480Smckusick bcopy(mtod(mp, char *), lebuf, len); 68941480Smckusick lebuf += len; 69041480Smckusick } 69141480Smckusick m_freem(m); 69241480Smckusick if (tlen < LEMINSIZE) { 69341480Smckusick bzero(lebuf, LEMINSIZE - tlen); 69441480Smckusick tlen = LEMINSIZE; 69541480Smckusick } 69641480Smckusick return(tlen); 69741480Smckusick } 69841480Smckusick 69941480Smckusick /* 70041480Smckusick * Process an ioctl request. 70141480Smckusick */ 70241480Smckusick leioctl(ifp, cmd, data) 70341480Smckusick register struct ifnet *ifp; 70441480Smckusick int cmd; 70541480Smckusick caddr_t data; 70641480Smckusick { 70741480Smckusick register struct ifaddr *ifa = (struct ifaddr *)data; 70841480Smckusick struct le_softc *le = &le_softc[ifp->if_unit]; 70941480Smckusick struct lereg1 *ler1 = le->sc_r1; 71041480Smckusick int s = splimp(), error = 0; 71141480Smckusick 71241480Smckusick switch (cmd) { 71341480Smckusick 71441480Smckusick case SIOCSIFADDR: 71541480Smckusick ifp->if_flags |= IFF_UP; 71641480Smckusick switch (ifa->ifa_addr->sa_family) { 71741480Smckusick #ifdef INET 71841480Smckusick case AF_INET: 71941480Smckusick leinit(ifp->if_unit); /* before arpwhohas */ 72041480Smckusick ((struct arpcom *)ifp)->ac_ipaddr = 72141480Smckusick IA_SIN(ifa)->sin_addr; 72241480Smckusick arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr); 72341480Smckusick break; 72441480Smckusick #endif 72541480Smckusick #ifdef NS 72641480Smckusick case AF_NS: 72741480Smckusick { 72841480Smckusick register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr); 72941480Smckusick 73041480Smckusick if (ns_nullhost(*ina)) 73141480Smckusick ina->x_host = *(union ns_host *)(le->sc_addr); 73241480Smckusick else { 73341480Smckusick /* 73441480Smckusick * The manual says we can't change the address 73541480Smckusick * while the receiver is armed, 73641480Smckusick * so reset everything 73741480Smckusick */ 73841480Smckusick ifp->if_flags &= ~IFF_RUNNING; 73950816Ssklower LERDWR(le->sc_r0, LE_STOP, ler1->ler1_rdp); 74041480Smckusick bcopy((caddr_t)ina->x_host.c_host, 74141480Smckusick (caddr_t)le->sc_addr, sizeof(le->sc_addr)); 74241480Smckusick } 74341480Smckusick leinit(ifp->if_unit); /* does le_setaddr() */ 74441480Smckusick break; 74541480Smckusick } 74641480Smckusick #endif 74741480Smckusick default: 74841480Smckusick leinit(ifp->if_unit); 74941480Smckusick break; 75041480Smckusick } 75141480Smckusick break; 75241480Smckusick 75341480Smckusick case SIOCSIFFLAGS: 75441480Smckusick if ((ifp->if_flags & IFF_UP) == 0 && 75541480Smckusick ifp->if_flags & IFF_RUNNING) { 75641480Smckusick LERDWR(le->sc_r0, LE_STOP, ler1->ler1_rdp); 75741480Smckusick ifp->if_flags &= ~IFF_RUNNING; 75841480Smckusick } else if (ifp->if_flags & IFF_UP && 75941480Smckusick (ifp->if_flags & IFF_RUNNING) == 0) 76041480Smckusick leinit(ifp->if_unit); 76148771Smccanne /* 76248771Smccanne * If the state of the promiscuous bit changes, the interface 76348771Smccanne * must be reset to effect the change. 76448771Smccanne */ 76548771Smccanne if (((ifp->if_flags ^ le->sc_iflags) & IFF_PROMISC) && 76648771Smccanne (ifp->if_flags & IFF_RUNNING)) { 76748771Smccanne le->sc_iflags = ifp->if_flags; 76848771Smccanne lereset(ifp->if_unit); 76948771Smccanne lestart(ifp); 77048771Smccanne } 77141480Smckusick break; 77241480Smckusick 773*54719Ssklower #ifdef MULTICAST 774*54719Ssklower case SIOCADDMULTI: 775*54719Ssklower case SIOCDELMULTI: 776*54719Ssklower /* Update our multicast list */ 777*54719Ssklower error = (cmd == SIOCADDMULTI) ? 778*54719Ssklower ether_addmulti((struct ifreq *)data, &le->sc_ac) : 779*54719Ssklower ether_delmulti((struct ifreq *)data, &le->sc_ac); 780*54719Ssklower 781*54719Ssklower if (error == ENETRESET) { 782*54719Ssklower /* 783*54719Ssklower * Multicast list has changed; set the hardware 784*54719Ssklower * filter accordingly. 785*54719Ssklower */ 786*54719Ssklower lereset(ifp->if_unit); 787*54719Ssklower error = 0; 788*54719Ssklower } 789*54719Ssklower break; 790*54719Ssklower #endif 79141480Smckusick default: 79241480Smckusick error = EINVAL; 79341480Smckusick } 79441480Smckusick splx(s); 79541480Smckusick return (error); 79641480Smckusick } 79741480Smckusick 79841480Smckusick leerror(unit, stat) 79941480Smckusick int unit; 80041480Smckusick int stat; 80141480Smckusick { 80241480Smckusick if (!ledebug) 80341480Smckusick return; 80441480Smckusick 80541480Smckusick /* 80641480Smckusick * Not all transceivers implement heartbeat 80741480Smckusick * so we only log CERR once. 80841480Smckusick */ 80941480Smckusick if ((stat & LE_CERR) && le_softc[unit].sc_cerr) 81041480Smckusick return; 81141480Smckusick log(LOG_WARNING, 81241480Smckusick "le%d: error: stat=%b\n", unit, 81341480Smckusick stat, 81441480Smckusick "\20\20ERR\17BABL\16CERR\15MISS\14MERR\13RINT\12TINT\11IDON\10INTR\07INEA\06RXON\05TXON\04TDMD\03STOP\02STRT\01INIT"); 81541480Smckusick } 81641480Smckusick 81741480Smckusick lererror(unit, msg) 81841480Smckusick int unit; 81941480Smckusick char *msg; 82041480Smckusick { 82141480Smckusick register struct le_softc *le = &le_softc[unit]; 82241480Smckusick register struct lermd *rmd; 82341480Smckusick int len; 82441480Smckusick 82541480Smckusick if (!ledebug) 82641480Smckusick return; 82741480Smckusick 82841480Smckusick rmd = &le->sc_r2->ler2_rmd[le->sc_rmd]; 82941480Smckusick len = rmd->rmd3; 83041480Smckusick log(LOG_WARNING, 83141480Smckusick "le%d: ierror(%s): from %s: buf=%d, len=%d, rmd1=%b\n", 83241480Smckusick unit, msg, 83352420Smckusick len > 11 ? 83452420Smckusick ether_sprintf((u_char *)&le->sc_r2->ler2_rbuf[le->sc_rmd][6]) : 83552420Smckusick "unknown", 83641480Smckusick le->sc_rmd, len, 83741480Smckusick rmd->rmd1, 83841480Smckusick "\20\20OWN\17ERR\16FRAM\15OFLO\14CRC\13RBUF\12STP\11ENP"); 83941480Smckusick } 84041480Smckusick 84141480Smckusick lexerror(unit) 84241480Smckusick int unit; 84341480Smckusick { 84441480Smckusick register struct le_softc *le = &le_softc[unit]; 84541480Smckusick register struct letmd *tmd; 84641480Smckusick int len; 84741480Smckusick 84841480Smckusick if (!ledebug) 84941480Smckusick return; 85041480Smckusick 85141480Smckusick tmd = le->sc_r2->ler2_tmd; 85241480Smckusick len = -tmd->tmd2; 85341480Smckusick log(LOG_WARNING, 85441480Smckusick "le%d: oerror: to %s: buf=%d, len=%d, tmd1=%b, tmd3=%b\n", 85541480Smckusick unit, 85652420Smckusick len > 5 ? 85752420Smckusick ether_sprintf((u_char *)&le->sc_r2->ler2_tbuf[0][0]) : 85852420Smckusick "unknown", 85941480Smckusick 0, len, 86041480Smckusick tmd->tmd1, 86141480Smckusick "\20\20OWN\17ERR\16RES\15MORE\14ONE\13DEF\12STP\11ENP", 86241480Smckusick tmd->tmd3, 86341480Smckusick "\20\20BUFF\17UFLO\16RES\15LCOL\14LCAR\13RTRY"); 86441480Smckusick } 86541480Smckusick #endif 866