📄 if_le.c
字号:
boff = sizeof (struct ether_header); resid = totlen; } } return (top);}/* * Process an ioctl request. */leioctl(ifp, cmd, data) register struct ifnet *ifp; int cmd; caddr_t data;{ register struct ifaddr *ifa = (struct ifaddr *)data; struct le_softc *le = &le_softc[ifp->if_unit]; volatile struct lereg1 *ler1 = le->sc_r1; int s, error = 0; s = splnet(); switch (cmd) { case SIOCSIFADDR: ifp->if_flags |= IFF_UP; switch (ifa->ifa_addr->sa_family) {#ifdef INET case AF_INET: leinit(ifp->if_unit); /* before arpwhohas */ ((struct arpcom *)ifp)->ac_ipaddr = IA_SIN(ifa)->sin_addr; arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr); break;#endif#ifdef NS case AF_NS: { register struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr); if (ns_nullhost(*ina)) ina->x_host = *(union ns_host *)(le->sc_addr); else { /* * The manual says we can't change the address * while the receiver is armed, * so reset everything */ ifp->if_flags &= ~IFF_RUNNING; LEWREG(LE_STOP, ler1->ler1_rdp); bcopy((caddr_t)ina->x_host.c_host, (caddr_t)le->sc_addr, sizeof(le->sc_addr)); } leinit(ifp->if_unit); /* does le_setaddr() */ break; }#endif default: leinit(ifp->if_unit); break; } break;#if defined (CCITT) && defined (LLC) case SIOCSIFCONF_X25: ifp->if_flags |= IFF_UP; ifa->ifa_rtrequest = cons_rtrequest; error = x25_llcglue(PRC_IFUP, ifa->ifa_addr); if (error == 0) leinit(ifp->if_unit); break;#endif /* CCITT && LLC */ case SIOCSIFFLAGS: if ((ifp->if_flags & IFF_UP) == 0 && ifp->if_flags & IFF_RUNNING) { LEWREG(LE_STOP, ler1->ler1_rdp); ifp->if_flags &= ~IFF_RUNNING; } else if (ifp->if_flags & IFF_UP && (ifp->if_flags & IFF_RUNNING) == 0) leinit(ifp->if_unit); /* * If the state of the promiscuous bit changes, the interface * must be reset to effect the change. */ if (((ifp->if_flags ^ le->sc_iflags) & IFF_PROMISC) && (ifp->if_flags & IFF_RUNNING)) { le->sc_iflags = ifp->if_flags; lereset(ifp->if_unit); lestart(ifp); } break;#ifdef MULTICAST case SIOCADDMULTI: case SIOCDELMULTI: /* Update our multicast list */ error = (cmd == SIOCADDMULTI) ? ether_addmulti((struct ifreq *)data, &le->sc_ac) : ether_delmulti((struct ifreq *)data, &le->sc_ac); if (error == ENETRESET) { /* * Multicast list has changed; set the hardware * filter accordingly. */ lereset(ifp->if_unit); error = 0; } break;#endif default: error = EINVAL; } splx(s); return (error);}leerror(unit, stat) int unit; int stat;{ if (!ledebug) return; /* * Not all transceivers implement heartbeat * so we only log CERR once. */ if ((stat & LE_CERR) && le_softc[unit].sc_cerr) return; log(LOG_WARNING, "le%d: error: stat=%b\n", unit, stat, "\20\20ERR\17BABL\16CERR\15MISS\14MERR\13RINT\12TINT\11IDON\10INTR\07INEA\06RXON\05TXON\04TDMD\03STOP\02STRT\01INIT");}lererror(unit, msg) int unit; char *msg;{ register struct le_softc *le = &le_softc[unit]; register volatile void *rmd; u_char eaddr[6]; int len; if (!ledebug) return; rmd = LER2_RMDADDR(le->sc_r2, le->sc_rmd); len = LER2V_rmd3(rmd); if (len > 11) (*le->sc_copyfrombuf)(LER2_RBUFADDR(le->sc_r2, le->sc_rmd), 6, eaddr, 6); log(LOG_WARNING, "le%d: ierror(%s): from %s: buf=%d, len=%d, rmd1=%b\n", unit, msg, len > 11 ? ether_sprintf(eaddr) : "unknown", le->sc_rmd, len, LER2V_rmd1(rmd), "\20\20OWN\17ERR\16FRAM\15OFLO\14CRC\13RBUF\12STP\11ENP");}lexerror(unit) int unit;{ register struct le_softc *le = &le_softc[unit]; register volatile void *tmd; u_char eaddr[6]; int len; if (!ledebug) return; tmd = LER2_TMDADDR(le->sc_r2, 0); len = -LER2V_tmd2(tmd); if (len > 5) (*le->sc_copyfrombuf)(LER2_TBUFADDR(le->sc_r2, 0), 0, eaddr, 6); log(LOG_WARNING, "le%d: oerror: to %s: buf=%d, len=%d, tmd1=%b, tmd3=%b\n", unit, len > 5 ? ether_sprintf(eaddr) : "unknown", 0, len, LER2V_tmd1(tmd), "\20\20OWN\17ERR\16RES\15MORE\14ONE\13DEF\12STP\11ENP", LER2V_tmd3(tmd), "\20\20BUFF\17UFLO\16RES\15LCOL\14LCAR\13RTRY");}/* * Write a lance register port, reading it back to ensure success. This seems * to be necessary during initialization, since the chip appears to be a bit * pokey sometimes. */static voidlewritereg(regptr, val) register volatile u_short *regptr; register u_short val;{ register int i = 0; while (*regptr != val) { *regptr = val; MachEmptyWriteBuffer(); if (++i > 10000) { printf("le: Reg did not settle (to x%x): x%x\n", val, *regptr); return; } DELAY(100); }}/* * Routines for accessing the transmit and receive buffers. Unfortunately, * CPU addressing of these buffers is done in one of 3 ways: * - contiguous (for the 3max and turbochannel option card) * - gap2, which means shorts (2 bytes) interspersed with short (2 byte) * spaces (for the pmax) * - gap16, which means 16bytes interspersed with 16byte spaces * for buffers which must begin on a 32byte boundary (for 3min and maxine) * The buffer offset is the logical byte offset, assuming contiguous storage. */voidcopytobuf_contig(from, lebuf, boff, len) char *from; volatile void *lebuf; int boff; int len;{ /* * Just call bcopy() to do the work. */ bcopy(from, ((char *)lebuf) + boff, len);}voidcopyfrombuf_contig(lebuf, boff, to, len) volatile void *lebuf; int boff; char *to; int len;{ /* * Just call bcopy() to do the work. */ bcopy(((char *)lebuf) + boff, to, len);}voidbzerobuf_contig(lebuf, boff, len) volatile void *lebuf; int boff; int len;{ /* * Just let bzero() do the work */ bzero(((char *)lebuf) + boff, len);}/* * For the pmax the buffer consists of shorts (2 bytes) interspersed with * short (2 byte) spaces and must be accessed with halfword load/stores. * (don't worry about doing an extra byte) */voidcopytobuf_gap2(from, lebuf, boff, len) register char *from; volatile void *lebuf; int boff; register int len;{ register volatile u_short *bptr; register int xfer; if (boff & 0x1) { /* handle unaligned first byte */ bptr = ((volatile u_short *)lebuf) + (boff - 1); *bptr = (*from++ << 8) | (*bptr & 0xff); bptr += 2; len--; } else bptr = ((volatile u_short *)lebuf) + boff; if ((unsigned)from & 0x1) { while (len > 1) { *bptr = (from[1] << 8) | (from[0] & 0xff); bptr += 2; from += 2; len -= 2; } } else { /* optimize for aligned transfers */ xfer = (int)((unsigned)len & ~0x1); CopyToBuffer((u_short *)from, bptr, xfer); bptr += xfer; from += xfer; len -= xfer; } if (len == 1) *bptr = (u_short)*from;}voidcopyfrombuf_gap2(lebuf, boff, to, len) volatile void *lebuf; int boff; register char *to; register int len;{ register volatile u_short *bptr; register u_short tmp; register int xfer; if (boff & 0x1) { /* handle unaligned first byte */ bptr = ((volatile u_short *)lebuf) + (boff - 1); *to++ = (*bptr >> 8) & 0xff; bptr += 2; len--; } else bptr = ((volatile u_short *)lebuf) + boff; if ((unsigned)to & 0x1) { while (len > 1) { tmp = *bptr; *to++ = tmp & 0xff; *to++ = (tmp >> 8) & 0xff; bptr += 2; len -= 2; } } else { /* optimize for aligned transfers */ xfer = (int)((unsigned)len & ~0x1); CopyFromBuffer(bptr, to, xfer); bptr += xfer; to += xfer; len -= xfer; } if (len == 1) *to = *bptr & 0xff;}voidbzerobuf_gap2(lebuf, boff, len) volatile void *lebuf; int boff; int len;{ register volatile u_short *bptr; if ((unsigned)boff & 0x1) { bptr = ((volatile u_short *)lebuf) + (boff - 1); *bptr &= 0xff; bptr += 2; len--; } else bptr = ((volatile u_short *)lebuf) + boff; while (len > 0) { *bptr = 0; bptr += 2; len -= 2; }}/* * For the 3min and maxine, the buffers are in main memory filled in with * 16byte blocks interspersed with 16byte spaces. */voidcopytobuf_gap16(from, lebuf, boff, len) register char *from; volatile void *lebuf; int boff; register int len;{ register char *bptr; register int xfer; bptr = ((char *)lebuf) + ((boff << 1) & ~0x1f); boff &= 0xf; xfer = min(len, 16 - boff); while (len > 0) { bcopy(from, ((char *)bptr) + boff, xfer); from += xfer; bptr += 32; boff = 0; len -= xfer; xfer = min(len, 16); }}voidcopyfrombuf_gap16(lebuf, boff, to, len) volatile void *lebuf; int boff; register char *to; register int len;{ register char *bptr; register int xfer; bptr = ((char *)lebuf) + ((boff << 1) & ~0x1f); boff &= 0xf; xfer = min(len, 16 - boff); while (len > 0) { bcopy(((char *)bptr) + boff, to, xfer); to += xfer; bptr += 32; boff = 0; len -= xfer; xfer = min(len, 16); }}voidbzerobuf_gap16(lebuf, boff, len) volatile void *lebuf; int boff; register int len;{ register char *bptr; register int xfer; bptr = ((char *)lebuf) + ((boff << 1) & ~0x1f); boff &= 0xf; xfer = min(len, 16 - boff); while (len > 0) { bzero(((char *)bptr) + boff, xfer); bptr += 32; boff = 0; len -= xfer; xfer = min(len, 16); }}#endif /* NLE */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -