📄 if_qe.c
字号:
return(0); if (totlen > MLEN) { MCLGET(m, p); if (p == 0) { m_freem(m); return(0); } } if (off) { /* crunch trailer */ off = totlen - off0; bcopy(cp, (mtod(m, caddr_t) + off), off0); cp += off0; bcopy(cp, mtod(m, caddr_t), off); } else { bcopy(cp, mtod(m, caddr_t), totlen); } m->m_len = totlen; return (m);#endif mips#ifdef vax while (totlen > 0) { MGET(m, M_DONTWAIT, MT_DATA); if (m == 0) goto bad; if (off) { len = totlen - off; cp = ifrw->ifrw_addr + ifu->ifu_hlen + off; } else len = totlen; if (len >= CLBYTES) { struct mbuf *p; struct pte *cpte, *ppte; int x, *ip, i, swt=2; caddr_t dp, tcp; MCLGET(m, p); if (p == 0) goto nopage; m->m_len = len; if((uba_hd[ifu->ifu_uban].uba_type & UBAUVI) || !pgaligned(cp)) goto copy; if(len > CLBYTES) swt = 4; /* * Switch pages mapped to Q-BUS with new page p, * as quick form of copy. Remap Q-BUS and invalidate. */ dp = mtod(m, caddr_t); tcp = cp; cpte = &kmempt[mtocl(cp)]; ppte = &kmempt[mtocl(p)]; x = btop(cp - ifrw->ifrw_addr); ip = (int *)&ifrw->ifrw_mr[x]; /* Keep pages contiguous */ for (i = 0; i < swt; i++) { struct pte t; t = *ppte; *ppte++ = *cpte; *cpte = t; *ip++ = cpte++->pg_pfnum|ifrw->ifrw_proto; mtpr(TBIS, tcp); tcp += NBPG; mtpr(TBIS, dp); dp += NBPG; } cp += len; goto nocopy; }nopage: m->m_len = MIN(MLEN, len); m->m_off = MMINOFF;copy: bcopy(cp, mtod(m, caddr_t), (unsigned)m->m_len); cp += m->m_len;nocopy: *mp = m; mp = &m->m_next; if (off) { /* sort of an ALGOL-W style for statement... */ off += m->m_len; if (off == totlen) { cp = ifrw->ifrw_addr + ifu->ifu_hlen; off = 0; totlen = off0; } } else totlen -= m->m_len; } return (top);bad: m_freem(top); return (0);#endif vax}/* * Map a chain of mbufs onto a network interface * in preparation for an i/o operation. * The argument chain of mbufs includes the local network * header which is copied to be in the mapped, aligned * i/o space. */int qe_showput = 0;qeput(ifu, n, m) struct qeuba *ifu; int n; register struct mbuf *m;{ register caddr_t cp; register struct ifxmt *ifxp; register struct ifrw *ifrw; register int i; int xswapd = 0; int x, cc, t; caddr_t dp; ifxp = &ifu->ifu_w[n]; ifrw = &ifxp->x_ifrw; cp = ifrw->ifrw_addr; ifxp->x_xtofree = m;#ifdef vax while (m) { dp = mtod(m, char *); if((uba_hd[ifu->ifu_uban].uba_type & UBAUVI) == 0 && claligned(cp) && claligned(dp) && m->m_len == CLBYTES) { struct pte *pte; int *ip; if(qe_showput) cprintf("qeput %x %x %d\n", cp, dp, m->m_len); pte = &kmempt[mtocl(dp)]; x = btop(cp - ifrw->ifrw_addr); ip = (int *)&ifrw->ifrw_mr[x]; for (i = 0; i < CLSIZE; i++) *ip++ = ifrw->ifrw_proto | pte++->pg_pfnum; xswapd |= 1 << (x>>(CLSHIFT-PGSHIFT)); cp += m->m_len; } else { if(qe_showput) cprintf("qeput_slow %x %x %d\n", cp, dp, m->m_len); bcopy(dp, cp, (unsigned)m->m_len); cp += m->m_len; } m = m->m_next; } /* * Pad out short transmits with NULL's */ if ((cc = cp - ifrw->ifrw_addr) < MINDATA) { bzero(cp, MINDATA - cc); cc = MINDATA; } /* * Xswapd is the set of clusters we just mapped out. Ifxp->x_xswapd * is the set of clusters mapped out from before. We compute * the number of clusters involved in this operation in x. * Clusters mapped out before and involved in this operation * should be unmapped so original pages will be accessed by the device. */ x = ((cc - ifu->ifu_hlen) + CLBYTES - 1) >> CLSHIFT; ifxp->x_xswapd &= ~xswapd; while (i = ffs(ifxp->x_xswapd)) { i--; if (i >= x) break; ifxp->x_xswapd &= ~(1<<i); i *= CLSIZE; for (t = 0; t < CLSIZE; t++) { ifrw->ifrw_mr[i] = ifxp->x_map[i]; i++; } } ifxp->x_xswapd |= xswapd;#endif vax/* use bcopy instead of swapping the page */ #ifdef mips while (m) { dp = mtod(m, char *); if(qe_showput) cprintf("qeput_slow %x %x %d\n", cp, dp, m->m_len); bcopy(dp, cp, (unsigned)m->m_len); cp += m->m_len; m = m->m_next; } /* * Pad out short transmits with NULL's */ if ((cc = cp - ifrw->ifrw_addr) < MINDATA) { bzero(cp, MINDATA - cc); cc = MINDATA; }#endif mips return (cc);}/* * Pass a packet to the higher levels. * We deal with the trailer protocol here. */qeread(sc, ifrw, len, swloop) register struct qe_softc *sc; struct ifrw *ifrw; int len; struct mbuf *swloop;{ struct ether_header *eh, swloop_eh,eh1; struct mbuf *m, *swloop_tmp1, *swloop_tmp2; struct protosw *pr; int off, resid; struct ifqueue *inq; static int qe_drop_no=0; /* * Deal with trailer protocol: if type is INET trailer * get true type from first 16-bit word past data. * Remember that type was trailer by setting off. */ if (swloop) { eh = mtod(swloop, struct ether_header *); swloop_eh = *eh; eh = &swloop_eh; if ( swloop->m_len > sizeof(struct ether_header)) m_adj(swloop, sizeof(struct ether_header)); else { MFREE(swloop, swloop_tmp1); if ( ! swloop_tmp1 ) return; else swloop = swloop_tmp1; } } eh = (struct ether_header *)ifrw->ifrw_addr; /* try to aviod the assignment problem due to instruction pipelines */ eh1 = *eh; eh1.ether_type = ntohs((u_short)eh->ether_type); eh = &eh1;#define qedataaddr(eh, off, type) ((type)(((caddr_t)((eh)+1)+(off)))) if ((eh->ether_type >= ETHERTYPE_TRAIL && eh->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) ) { off = (eh->ether_type - ETHERTYPE_TRAIL) * 512; if (off >= ETHERMTU) return; /* sanity */ if (swloop) { struct mbuf *mprev, *m0 = swloop;/* need to check this against off */ mprev = m0; while (swloop->m_next){/*real header at end of chain*/ mprev = swloop; swloop = swloop->m_next; } /* move to beginning of chain */ mprev->m_next = 0; swloop->m_next = m0; eh->ether_type = ntohs( *mtod(swloop, u_short *)); } else { eh->ether_type = ntohs(*(qedataaddr((struct ether_header *)ifrw->ifrw_addr,off, u_short *))); resid = ntohs(*(qedataaddr((struct ether_header *)ifrw->ifrw_addr,off+2, u_short *))); if (off + resid > len) return; /* sanity */ len = off + resid; } } else { off = 0; } if (len == 0) return; /* * Pull packet off interface. Off is nonzero if packet * has trailing header; qeget will then force this header * information to be at the front, but we still have to drop * the type and length which are at the front of any trailer data. */ if (swloop) { m = m_copy(swloop, 0, M_COPYALL); m_freem(swloop); } else { m = qeget(&sc->qeuba, ifrw, len, off); } if (m == 0) return; if (off) { m->m_off += 2 * sizeof (u_short); m->m_len -= 2 * sizeof (u_short); } /* * Bump up input packets and DECnet counters. Input packets for * "netstat" include ALL directed, multicast, and error inputs. * For DECnet, only error-free input packets are counted. See the * DEUNA User's Guide for a breakdown of the counters. */ sc->is_if.if_ipackets++; sc->ctrblk.est_bytercvd += len ; if (sc->ctrblk.est_blokrcvd != (unsigned) 0xffffffff) sc->ctrblk.est_blokrcvd++; if( eh->ether_dhost[0] & 1 ) { sc->ctrblk.est_mbytercvd += len ; if (sc->ctrblk.est_mblokrcvd != (unsigned) 0xffffffff) sc->ctrblk.est_mblokrcvd++; } /* Dispatch this packet */ net_read(&(sc->qe_ed), eh, m, len, (swloop != NULL), (off != 0));}/* * Watchdog timer routine. There is a condition in the hardware that * causes the board to lock up under heavy load. This routine detects * the hang up and restarts the device. */qewatch(){ register struct qe_softc *sc; register int i;#ifdef mips volatile struct qedevice *addr; /* dallas */#endif mips#ifdef vax register struct qedevice *addr; /* dallas */#endif vax register int s; /* dallas */ int inprogress=0; for( i=0 ; i<nNQE ; i++ ) { sc = qe_softc[i]; addr = sc->addr; /* dallas */ if( sc->timeout ) { if( ++sc->timeout > 3 ) { /* * Check for the reason the transmit timed out */ if( addr->qe_csr & QE_RL_INVALID) { /* * Transmit timed out because no recv * buffers available, so must now * process the recv ring. Set a fail * safe just in case we have been * here before, cleared in qetint(). */ if (sc->qe_rl_invalid) qerestart( sc ); else { ++sc->qe_rl_invalid; sc->timeout = 0; timeout( qewatch, 0, QE_TIMEO); s = splimp(); qerint( i ); splx( s ); } } else qerestart( sc ); } else inprogress++; } } if( inprogress ){ timeout(qewatch, 0, QE_TIMEO); qewatchrun++; } else qewatchrun=0;}/* * Restart for board lockup problem. */int qe_restarts;qerestart( sc ) register struct qe_softc *sc;{ register struct ifnet *ifp = &sc->is_if;#ifdef mips volatile struct qedevice *addr = sc->addr;#endif mips#ifdef vax register struct qedevice *addr = sc->addr;#endif vax register struct qe_ring *rp; register int i; register struct ifxmt *ifxp; int s; /* dallas */ qe_restarts++; s = splimp(); /* Raise our priority so when we reset it does not * interrupt us while we are fooling with the rings. */ addr->qe_csr = QE_RESET; sc->timeout = 0; qesetup( sc ); addr->qe_csr &= ~QE_RESET; for(i = 0, rp = sc->tring; i<nNXMT ; rp++, i++ ){ rp->qe_flag = rp->qe_status1 = QE_NOTYET; rp->qe_valid = 0; ifxp = &sc->qeuba.ifu_w[i]; if( ifxp->x_xtofree ) { m_freem( ifxp->x_xtofree ); ifxp->x_xtofree = 0; } } sc->nxmit = sc->otindex = sc->tindex = sc->rindex = 0; if ( ifp->if_flags & IFF_LOOPBACK ) addr->qe_csr = QE_RCV_ENABLE | QE_INT_ENABLE | QE_XMIT_INT | QE_RCV_INT | QE_ELOOP; else addr->qe_csr = QE_RCV_ENABLE | QE_INT_ENABLE | QE_XMIT_INT | QE_RCV_INT | QE_ILOOP; ifp->if_flags &= ~IFF_OACTIVE; addr->qe_rcvlist_lo = (short)sc->rringaddr; addr->qe_rcvlist_hi = (short)((int)sc->rringaddr >> 16); for( i = 0 ; sc != qe_softc[i] ; i++ ) ; qestart( i ); splx( s ); /* dallas */ if (qe_show_restarts) printf("qerestart: restarted qe%d %d\n", i, qe_restarts); else mprintf("qerestart: restarted qe%d %d\n", i, qe_restarts);}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -