📄 if_ne.c
字号:
return; } tlen = neput(sc,index,m); rp->ne_info |= NE_TFS | NE_TLS ; } rp->ne_bsize = tlen; rp->ne_own = NE_OWN; sc->nxmit++; sc->is_if.if_flags |= IFF_OACTIVE; csrpt->csr1 = NE_CSR1_PD; wbflush(); sc->is_if.if_timer = 5; } } /* * Ethernet interface interrup processor */neintr(unit) int unit;{ register struct ne_softc *sc = &ne_softc[unit]; register struct ifnet *ifp = &sc->is_if; register u_long csr; u_long csr6; NECSRS *csrpt = sc->ne_csrs; int s; s = splimp(); csr =csrpt->csr5; /* save the old csr5 */ csrpt->csr5 = csr; /* clear the csr5 */ wbflush(); if ( csr & NE_CSR5_TW ) { netbablcnt++; if(nedebug) mprintf("ne%d: transmit timeout (TW)\n",unit); /* reset the chip */ nereset(sc); splx(s); return; } if ( csr & NE_CSR5_RU ) { /* Receive Buffer Unavailable. * When set, indicateds that the next descriptor * on the receive list is owned by the host. * That means a packet was lost */ nemisscnt++; if(nedebug) mprintf("ne%d: missed packet (Receiv Buffer Unavailable)",unit); if(sc->ctrblk.est_sysbuf != 0xffff) sc->ctrblk.est_sysbuf++; /* Do not need to poll the receive. The SGEC will turn * on the receive running state when next frame arrive */ } if ( csr & NE_CSR5_ME ) { /* * Memory Error * It happened when any one of followings occur: * 1) host memory problem * 2) Parity error detected on an host to SGEC * CSR write or SGEC read from memory */ nemerrcnt++; mprintf("ne%d: memory error (MERR) \n", unit); nereset(sc); splx(s); return; } if ( csr & NE_CSR5_RI ) nerint(unit); if ( csr & NE_CSR5_TI ) netint(unit); splx(s);}/* * Ethernet interface transmit interrupt */netint(unit) int unit;{ register struct ne_softc *sc = &ne_softc[unit]; register int index = sc->otindex; register int i; register NEDESC *rp= &sc->tring[sc->otindex]; register u_long status; struct mbuf *mp,*mp0; struct ether_header *eh; NECSRS *csrpt = sc->ne_csrs; int nNENXMT = sc->ntring; struct ifnet *ifp = &sc->is_if; int ccount; short tlen; while ( (sc->otindex != sc->tindex) && ( rp->ne_own != NE_OWN ) && sc->nxmit > 0 ) { status = rp->ne_flag; tlen = rp->ne_bsize; /* * Found last buffer in the packet * (hence a valid string of descriptors) * so free things up. */ mp = sc->smbuf[index]; sc->smbuf[index] = (struct mbuf *)NULL; if(!(--sc->nxmit)) { ifp->if_timer=0; sc->is_if.if_flags &= ~IFF_OACTIVE; } if(!(rp->ne_info & NE_DT_TSET)) { /* not a setup packet */ /* * Network statistics */ sc->is_if.if_opackets++; ccount = (status & NE_CC) >> 3; if(ccount && !(status & NE_LC)) { sc->is_if.if_collisions += ccount; /* * Decnet statistics */ if (ccount) { /* collision happened */ if(ccount == 1) { if (sc->ctrblk.est_single != (unsigned)0xffffffff) sc->ctrblk.est_single++; } else /* more than one */ if(sc->ctrblk.est_multiple != (unsigned)0xffffffff); sc->ctrblk.est_multiple++; } } if(status & NE_DE) if (sc->ctrblk.est_deferred != (unsigned) 0xffffffff) sc->ctrblk.est_deferred++; /* Heartbeat Fail */ if((status & NE_HF) && !(status & NE_UF)) if (sc->ctrblk.est_collis != 0xffff) sc->ctrblk.est_collis++; /* * Check for transmission errors */ if(status & NE_ES) { sc->is_if.if_oerrors++; if (sc->ctrblk.est_sendfail != 0xffff) { sc->ctrblk.est_sendfail++; if (status & NE_EC ) {/* Excessive Collisions */ if (nedebug) mprintf("ne%d: excseeive collision (EC)\n",unit); sc->ctrblk.est_sendfail_bm |= 1; } if (status & NE_LC && !(status & NE_UF)) { if (nedebug) mprintf("ne%d: late transmit collision (LC)\n",unit); sc->ctrblk.est_sendfail_bm |= 2; ; /* not implemented */ } if (status & (NE_NC | NE_LO) ) { /* no carrier */ if (nedebug) mprintf("ne%d: no carrier or lost carrier (LO or NC)\n",unit); sc->ctrblk.est_sendfail_bm |= 4; } if (status & NE_UF ) {/* Underflow error */ if (nedebug) mprintf("ne%d: underflow error (UF)\n",unit); } if (status & NE_TLE ) {/* Length error */ if (nedebug) mprintf("ne%d: transmit buffer length error (LE)\n",unit); } } m_freem(mp); } else { /* * Accumulate statistics for DECnet */ if ((sc->ctrblk.est_bytesent + tlen) > sc->ctrblk.est_bytesent) sc->ctrblk.est_bytesent += tlen; if (sc->ctrblk.est_bloksent != (unsigned)0xffffffff) sc->ctrblk.est_bloksent++; /* * If this was a broadcast packet or if we * are in COPYALL mode, loop it back. * We will not free this buffer. * This buffer will be reused. */ if (mp) { eh = mtod( mp, struct ether_header *); if ((!(bcmp(eh->ether_dhost,ne_multi,6))) || (sc->is_if.if_flags & IFF_PFCOPYALL)) { for(mp0 = mp ,tlen=0; mp0 ;mp0 =mp0->m_next) { tlen += mp0->m_len; } neread(sc,0,mp,index,tlen); } else m_freem( mp ); } } } else { /* this is a setup frame */ if ( status & NE_SETUP_SE ) { printf("ne%d: setup frame buffer size error ( should be 128 bytes ) \n ",unit); neinit(unit); } } /* * Init the buffer descriptor */ neinitdesc(&sc->tring[index],sc->tmbuf[index],0); sc->otindex = index = ++index % nNENXMT; rp = (NEDESC *) &sc->tring[index]; } /* * Dequeue next transmit request */ if (sc->nxmit > 0 && (sc->tring[sc->otindex].ne_own == NE_OWN )) { csrpt->csr1 = NE_CSR1_PD; wbflush(); } if (!(ifp->if_flags & IFF_OACTIVE)) nestart( unit );}/* * Ethernet interface receiver interrupt. */nerint(unit) int unit;{ register struct ne_softc *sc = &ne_softc[unit]; register NEDESC *rp; register int index; register struct ifnet *ifp = &sc->is_if; register int first; int nNENRCV = sc->nrring; int rlen; /* * Traverse the receive ring looking for packets to pass back. * The search is complete when we find a descriptor not in use ( * which means own by SGEC ). */ rp = &sc->rring[sc->rindex]; for (index = sc->rindex; !(rp->ne_own & NE_OWN) ; rp = &sc->rring[index]) { /* * We don't need to check the chained packet. * The SGEC will filter out those chained packet by * setting the CSR6 DC bit on. The RDES0<FS,LS> will * always be set */ if(!(rp->ne_flag & NE_ES)) { /* valid descriptor */ struct mbuf *m1; /* * If can not allocate a cluster mbuf for switch, just * drop this packet */ NEMCLGET(m1); if(m1 == 0) { nenolmbuf++; /* * already bumpped up 2 bytes */ neinitdesc(rp,sc->rmbuf[index],0); } else { rlen = rp->ne_com & 0x00007fff ;#ifdef mips clean_dcache(PHYS_TO_K0(rp->ne_bfaddr),rlen);#endif mips neread(sc,rp,(struct mbuf *)0,index,rlen); neinitdesc(rp,m1,1); sc->rmbuf[index]=m1; } /* * Else not a good packet, check for errors */ } else { sc->is_if.if_ierrors++; if(nedebug) mprintf("ne%d: recv err %02x\n",unit,rp->ne_flag&0xff); if(sc->ctrblk.est_recvfail != 0xffff) { sc->ctrblk.est_recvfail++; if(rp->ne_flag & NE_OF) { /* overflow */ sc->ctrblk.est_recvfail_bm |=4 ;#if NPACKETFILTER > 0 sc->is_ed.ess_missed++;#endif NPACKETFILTER > 0 } if(rp->ne_flag & NE_CE ) { /* CRC error */ if(rp->ne_flag & NE_DB ) /* Block check error */ sc->ctrblk.est_recvfail_bm |=1 ; else /* Frame error */ sc->ctrblk.est_recvfail_bm |=2 ; } if(rp->ne_flag & NE_CS) { /* Collision seen */ sc->ctrblk.est_recvfail_bm |=2 ; } if(rp->ne_flag & NE_RTL) { /* Frame too long */ sc->ctrblk.est_recvfail_bm |=4 ; } if((rp->ne_flag & NE_RF) && !(rp->ne_flag & NE_OF)) { /* Runt Frame - will only receive if */ /* CSRT6 <PB> is set. Meaningless if */ /* RDES0<OF> is set */ sc->ctrblk.est_recvfail_bm |=4 ; } if(rp->ne_flag & NE_RLE ) { /* length error */ ; } neinitdesc(rp,sc->rmbuf[index],0); } } rp->ne_own = NE_OWN; sc->rindex = index = ++index % nNENRCV; }} /* * Pass a packet to the higher levels. * We deal with the trailer protocol */neread(sc,dp,swloop,index,rlen)register struct ne_softc *sc;register NEDESC *dp;int index,rlen;struct mbuf *swloop;{ register struct ether_header *eptr, eh; struct mbuf *m, *swloop_tmp1; int off,resid,len; struct ifqueue *inq; /* * 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) { eptr = mtod(swloop, struct ether_header *); eh = *eptr; eptr = &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; } } else { m = sc->rmbuf[index]; m->m_len = len = rlen - 4; /* CRC */ eptr = mtod(m, struct ether_header *); eh = *eptr; eptr = &eh; } eptr->ether_type = ntohs((u_short)eptr->ether_type); if ((eptr->ether_type >= ETHERTYPE_TRAIL && eptr->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER)) { off = (eptr->ether_type - ETHERTYPE_TRAIL) * 512 + sizeof(struct ether_header); if (off >= ETHERMTU) return; /* sanity */ if (swloop) { struct mbuf *mprev, *m0 = swloop; 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; eptr->ether_type = ntohs( *mtod(swloop, u_short *)); } else { eptr->ether_type = ntohs(*(short *)(mtod(m, caddr_t) + off)); resid = ntohs(*(short *)(mtod(m, caddr_t) + off +2)); if (off + resid > m->m_len) return; /* sanity */ } } else { off = 0; } /* * Pull packet off interface. (In the case of NE, only need * to allocate another mbuf to switch the old one ) * Off is nonzero if packet has trailing header; * this routine 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); if (m == 0) return; len = m_length(m); } else { struct mbuf *m0 = m; if (off) { int nbytes; int cnt = resid; struct mbuf *n; struct mbuf **mp = &m; while (cnt > 0) { MGET(n,M_DONTWAIT,MT_DATA); if (n == 0) { m_freem(m); nenosmbuf++; return; } nbytes = MIN(MLEN,cnt); bcopy((mtod(m, caddr_t) + off), mtod(n, caddr_t), nbytes); n->m_len = nbytes; off += nbytes; cnt -= nbytes; *mp = n; mp = &n->m_next; } *mp = m0; m0->m_len -= resid; /* strip out the trailer header */ m->m_off += 2 * sizeof (u_short); m->m_len -= 2 * sizeof (u_short); } /* * Trim off ethernet header */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -