📄 if_ace.c
字号:
if ((eistat & (RCS_ROVRN | RCS_RCRC | RCS_RODD)) || len < ET_MINLEN || len > ET_MAXLEN+CRC_SIZE) { if (eistat & RCS_ROVRN) is->is_stats.rx_overruns++; if (eistat & RCS_RCRC) is->is_stats.rx_crc_errors++; if (eistat & RCS_RODD) is->is_stats.rx_align_errors++; if (len < ET_MINLEN) is->is_stats.rx_underruns++; if (len > ET_MAXLEN+CRC_SIZE) is->is_stats.rx_overruns++; is->is_if.if_ierrors++; rxseg->rx_csr = 0; return; } else is->is_stats.rx_datagrams++; ace = (struct ether_header *)rxseg->rx_data; len -= sizeof (struct ether_header); /* * Deal with trailer protocol: if type is trailer * get true type from first 16-bit word past data. * Remember that type was trailer by setting off. */ ace->ether_type = ntohs((u_short)ace->ether_type);#define acedataaddr(ace, off, type) \ ((type)(((caddr_t)(((char *)ace)+sizeof (struct ether_header))+(off)))) if (ace->ether_type >= ETHERTYPE_TRAIL && ace->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) { off = (ace->ether_type - ETHERTYPE_TRAIL) * 512; if (off >= ETHERMTU) goto setup; /* sanity */ ace->ether_type = ntohs(*acedataaddr(ace, off, u_short *)); resid = ntohs(*(acedataaddr(ace, off+2, u_short *))); if (off + resid > len) goto setup; /* sanity */ len = off + resid; } else off = 0; if (len == 0) goto setup; /* * Pull packet off interface. Off is nonzero if packet * has trailing header; aceget will then force this header * information to be at the front. */ m = aceget((u_char *)rxseg->rx_data, len, off, &is->is_if); if (m) ether_input(&is->is_if, ace, m);setup: rxseg->rx_csr = 0; goto again;}/* * Routine to copy from mbuf chain to transmit buffer on the VERSAbus * If packet size is less than the minimum legal size, * the buffer is expanded. We probably should zero out the extra * bytes for security, but that would slow things down. */aceput(txbuf, m) char *txbuf; struct mbuf *m;#ifdef notdef{ register u_char *bp, *mcp; register short *s1, *s2; register u_int len; register struct mbuf *mp; int total; total = mp->m_pkthdr.len; bp = (u_char *)txbuf; for (mp = m; mp; mp = mp->m_next) { len = mp->m_len; if (len == 0) continue; mcp = mtod(mp, u_char *); if (((int)mcp & 01) && ((int)bp & 01)) { /* source & destination at odd addresses */ movob(bp++, *mcp++); --len; } if (len > 1 && (((int)mcp & 01)==0) && (((int)bp & 01)==0)) { int l = len & 1; s1 = (short *)bp; s2 = (short *)mcp; len >>= 1; /* count # of shorts */ while (len-- != 0) movow(s1++, *s2++); len = l; /* # remaining bytes */ bp = (u_char *)s1; mcp = (u_char *)s2; } while (len-- != 0) movob(bp++, *mcp++); } m_freem(m); return (total);}#else{ register u_char *bp, *mcp; register short *s1, *s2; register u_int len; register struct mbuf *mp; int total; total = 0; bp = (u_char *)txbuf; for (mp = m; (mp); mp = mp->m_next) { len = mp->m_len; if (len == 0) continue; total += len; mcp = mtod(mp, u_char *); if (((int)mcp & 01) && ((int)bp & 01)) { /* source & destination at odd addresses */ movob(bp++, *mcp++); --len; } if (len > 1 && (((int)mcp & 01)==0) && (((int)bp & 01)==0)) { register u_int l; s1 = (short *)bp; s2 = (short *)mcp; l = len >> 1; /* count # of shorts */ while (l-- != 0) movow(s1++, *s2++); len &= 1; /* # remaining bytes */ bp = (u_char *)s1; mcp = (u_char *)s2; } while (len-- != 0) movob(bp++, *mcp++); } m_freem(m); return (total);}#endif/* * Routine to copy from VERSAbus memory into mbufs. * * Warning: This makes the fairly safe assumption that * mbufs have even lengths. */struct mbuf *aceget(rxbuf, totlen, off, ifp) u_char *rxbuf; int totlen, off; struct ifnet *ifp;{ register u_char *cp, *mcp; register struct mbuf *m; register int tlen; struct mbuf *top = 0, **mp = ⊤ int len; u_char *packet_end; rxbuf += sizeof (struct ether_header); cp = rxbuf; packet_end = cp + totlen; if (off) { off += 2 * sizeof(u_short); totlen -= 2 * sizeof(u_short); cp = rxbuf + off; } MGETHDR(m, M_DONTWAIT, MT_DATA); if (m == 0) return (0); m->m_pkthdr.rcvif = ifp; m->m_pkthdr.len = totlen; m->m_len = MHLEN; while (totlen > 0) { if (top) { MGET(m, M_DONTWAIT, MT_DATA); if (m == 0) { m_freem(top); return (0); } m->m_len = MLEN; } len = min(totlen, (packet_end - cp)); if (len >= MINCLSIZE) { MCLGET(m, M_DONTWAIT); if (m->m_flags & M_EXT) m->m_len = len = min(len, MCLBYTES); else len = m->m_len; } else { /* * Place initial small packet/header at end of mbuf. */ if (len < m->m_len) { if (top == 0 && len + max_linkhdr <= m->m_len) m->m_data += max_linkhdr; m->m_len = len; } else len = m->m_len; } mcp = mtod(m, u_char *); /*bcopy((caddr_t)cp, (caddr_t)mcp, len);*/ /*cp += len; mcp += len;*/ tlen = len; if (((int)mcp & 01) && ((int)cp & 01)) { /* source & destination at odd addresses */ *mcp++ = *cp++; --tlen; } if (tlen > 1 && (((int)mcp&01) == 0) && (((int)cp&01) == 0)) { register short *s1, *s2; register int l; s1 = (short *)mcp; s2 = (short *)cp; l = tlen >> 1; /* count # of shorts */ while (l-- > 0) /* copy shorts */ *s1++ = *s2++; tlen &= 1; /* # remaining bytes */ mcp = (u_char *)s1; cp = (u_char *)s2; } while (tlen-- > 0) *mcp++ = *cp++; *mp = m; mp = &m->m_next; totlen -= len; if (cp == packet_end) cp = rxbuf; } return (top);}/* backoff table masks */short random_mask_tbl[16] = { 0x0040, 0x00c0, 0x01c0, 0x03c0, 0x07c0, 0x0fc0, 0x1fc0, 0x3fc0, 0x7fc0, 0xffc0, 0xffc0, 0xffc0, 0xffc0, 0xffc0, 0xffc0, 0xffc0};acebakoff(is, txseg, retries) struct ace_softc *is; struct tx_segment *txseg; register int retries;{ register short *pBakNum, random_num; short *pMask; pMask = &random_mask_tbl[0]; pBakNum = &txseg->tx_backoff[0]; while (--retries >= 0) { random_num = (is->is_currnd = (is->is_currnd * 18741)-13849); random_num &= *pMask++; *pBakNum++ = random_num ^ (short)(0xff00 | 0x00fc); }}/* * Process an ioctl request. */aceioctl(ifp, cmd, data) register struct ifnet *ifp; int cmd; caddr_t data;{ register struct ifaddr *ifa = (struct ifaddr *)data; struct acedevice *addr; int s = splimp(), error = 0; switch (cmd) { case SIOCSIFADDR: ifp->if_flags |= IFF_UP; switch (ifa->ifa_addr->sa_family) {#ifdef INET case AF_INET: aceinit(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: { struct ns_addr *ina = &IA_SNS(ifa)->sns_addr; struct ace_softc *is = &ace_softc[ifp->if_unit]; if (!ns_nullhost(*ina)) { ifp->if_flags &= ~IFF_RUNNING; addr = (struct acedevice *) aceinfo[ifp->if_unit]->ui_addr; movow(&addr->csr, CSR_RESET); DELAY(10000); /* set station address & copy addr to arp */ acesetaddr(ifp->if_unit, addr, ina->x_host.c_host); } else ina->x_host = *(union ns_host *)is->is_addr; aceinit(ifp->if_unit); break; }#endif default: aceinit(ifp->if_unit); break; } break; case SIOCSIFFLAGS: if ((ifp->if_flags&IFF_UP) == 0 && ifp->if_flags&IFF_RUNNING) { addr = (struct acedevice *) (aceinfo[ifp->if_unit]->ui_addr); movow(&addr->csr, CSR_RESET); ifp->if_flags &= ~IFF_RUNNING; } else if (ifp->if_flags&IFF_UP && (ifp->if_flags&IFF_RUNNING) == 0) aceinit(ifp->if_unit); break; default: error = EINVAL; } splx(s); return (error);}/* * Set the on-board station address, then read it back * to initialize the address used by ARP (among others). */acesetaddr(unit, addr, station) short unit; struct acedevice *addr; u_char *station;{ struct ace_softc *is = &ace_softc[unit]; register short *wp, i; for (wp = (short *)addr->station, i = 0; i < 6; i++) movow(wp++, ~*station++); for (wp = (short *)addr->station, i = 0; i < 6; i++) is->is_addr[i] = ~*wp++; printf("ace%d: hardware address %s\n", unit, ether_sprintf(is->is_addr));}/* * Setup the device for use. Initialize dual-ported memory, * backoff parameters, and various other software state. */acesetup(unit) int unit;{ register struct ace_softc *is = &ace_softc[unit]; register char *pData1; register short i; struct acedevice *addr; bzero(is->is_dpm, 16384*2); is->is_currnd = 49123; addr = (struct acedevice *)aceinfo[unit]->ui_addr; is->is_segboundry = (addr->segb >> 11) & 0xf; pData1 = is->is_dpm + (is->is_segboundry << 11); for (i = SEG_MAX + 1 - is->is_segboundry; --i >= 0;) { acebakoff(is, (struct tx_segment *)pData1, 15); pData1 += sizeof (struct tx_segment); } is->is_eictr = 0; is->is_eoctr = is->is_txnext = is->is_segboundry; bzero((char *)&is->is_stats, sizeof (is->is_stats));}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -