📄 if_ne.c
字号:
m0->m_off += sizeof (struct ether_header); m0->m_len -= sizeof (struct ether_header); /* * Subtract length of header from len */ len -= sizeof (struct ether_header); } /* * Bump up DECnet counters. Input packets for "netstat" include * ALL directed, multicast, and error inputs. For DECnet, only * error-free input packets are counted. */ sc->is_if.if_ipackets++; sc->ctrblk.est_bytercvd += len ; if (sc->ctrblk.est_blokrcvd != (unsigned) 0xffffffff) sc->ctrblk.est_blokrcvd++; if( eptr->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->is_ed), eptr, m, len, (swloop != NULL), (off != 0));}/* * Process an ioctl request */neioctl(ifp, cmd, data)register struct ifnet *ifp;int cmd;caddr_t data;{ register struct ne_softc *sc = &ne_softc[ifp->if_unit]; struct ifreq *ifr = (struct ifreq *)data; struct ifdevea *ifd = (struct ifdevea *)data; struct ctrreq *ctr = (struct ctrreq *)data; struct protosw *pr; struct ifaddr *ifa = (struct ifaddr *)data; NECSRS *csrpt = sc->ne_csrs; int s, i, error = 0 , j = -1, delay; s = splimp(); switch (cmd) { case SIOCENABLBACK: case SIOCDISABLBACK: if ( cmd == SIOCENABLBACK ) { if (nedebug>1) printf("SIOCENABLBACK "); mprintf("ne%d: internal loopback enable requested\n", ifp->if_unit); ifp->if_flags |= IFF_LOOPBACK; } else { if (nedebug>1) printf("SIOCDISABLBACK "); mprintf("ne%d: internal loopback disable requested\n", ifp->if_unit); ifp->if_flags &= ~IFF_LOOPBACK; } if ( ifp->if_flags & IFF_RUNNING ) { csrpt->csr6 = ~(NE_CSR6_SR | NE_CSR6_ST); /* * polling CSR5 <TS> and <RS> */ for (delay = 10000; delay && (csrpt->csr5 & (NE_TS_STP | NE_RS_STP)) ; delay--); neinit(ifp->if_unit); } break; case SIOCRPHYSADDR: /* * read default hardware address */ if (nedebug>1) printf("SIOCRPHYSADDR "); bcopy(sc->is_addr, ifd->current_pa, 6); for ( i = 0 ; i < 6 ; i++ ) ifd->default_pa[i] = sc->ne_narom[i * 4 ]; break; case SIOCSPHYSADDR: if (nedebug>1) printf("SIOCSPHYSADDR "); bcopy(ifr->ifr_addr.sa_data,sc->is_addr,6);#if NPACKETFILTER > 0 pfilt_newaddress(sc->is_ed.ess_enetunit, sc->is_addr);#endif NPACKETFILTER > 0 for ( i = 0; i < 6; i++ ) sc->ne_setup[0].setup_char[i] = sc->is_addr[i]; if (ifp->if_flags & IFF_RUNNING) { nesetup( sc,0 ); nestart( ifp->if_unit ); } else nesetup( sc, 0 ); break; case SIOCDELMULTI: case SIOCADDMULTI: if (cmd == SIOCDELMULTI) { if (nedebug>1) printf("SIOCDELMULTI "); for (i = 0; i < NMULTI - 1 ; i++) { if (bcmp(&sc->multi[i],ifr->ifr_addr.sa_data,MULTISIZE) == 0) { if (--sc->muse[i] == 0) bcopy(ne_multi,&sc->multi[i],MULTISIZE); if (neshowmulti) printf("%d deleted. \n",i); } } } else { if (nedebug>1) printf("SIOCADDDMULTI "); for (i = 0; i < NMULTI - 1 ; i++) { if (bcmp(&sc->multi[i],ifr->ifr_addr.sa_data,MULTISIZE) == 0) { sc->muse[i]++; if (neshowmulti) printf("already using index %d\n",i); goto done; } if (bcmp(&sc->multi[i],ne_multi,MULTISIZE) == 0) j = i; } /* * j is initialized to -1; if j > 0, then * represents the last valid unused location * in the multicast table. */ if (j == -1) { printf("ne%d: SIOCADDMULTI failed, multicast list full: %d\n",ifp->if_unit,NMULTI); error = ENOBUFS; goto done; } bcopy(ifr->ifr_addr.sa_data, &sc->multi[j], MULTISIZE); sc->muse[j]++; if (neshowmulti) printf("added index %d.\n", j); } for ( i = 0; i < 6; i++ ) sc->ne_setup[0].setup_char[i] = sc->is_addr[i]; if (ifp->if_flags & IFF_RUNNING) { nesetup( sc, 0 ); nestart ( ifp->if_unit ); } else nesetup( sc, 0 ); break; case SIOCRDCTRS: case SIOCRDZCTRS: if (nedebug>1) printf("SIOCRDCTRS "); ctr->ctr_ether = sc->ctrblk; ctr->ctr_type = CTR_ETHER; ctr->ctr_ether.est_seconds = (time.tv_sec - sc->ztime) > 0xfffe ? 0xffff : (time.tv_sec - sc->ztime); if (cmd == SIOCRDZCTRS) { if (nedebug>1) printf("SIOCRDZCTRS "); sc->ztime = time.tv_sec; bzero(&sc->ctrblk, sizeof(struct estat)); } break; case SIOCSIFADDR: if (nedebug>1) printf("SIOCSIFADDR "); ifp->if_flags |= IFF_UP; neinit(ifp->if_unit); switch(ifa->ifa_addr.sa_family) {#ifdef INET case AF_INET: ((struct arpcom *)ifp)->ac_ipaddr = IA_SIN(ifa)->sin_addr; arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr); break;#endif default: if (pr = iffamily_to_proto(ifa->ifa_addr.sa_family)) { error = (*pr->pr_ifioctl)(ifp, cmd, data); } break; } break;#ifdef IFF_PROMISC /* IFF_ALLMULTI and NPACKETFILTER, as well */ case SIOCSIFFLAGS: /* * Run a setup packet in case things have changed; * someone may be trying to turn on (or off) promiscuous * mode, for example. */ if (ifp->if_flags & IFF_RUNNING) { ifp->if_flags &= ~IFF_RUNNING; neinit( ifp->if_unit ); } break;#endif IFF_PROMISC default: error = EINVAL; }done: splx(s); return (error);}/* * Put an mbuf chain into the appropriate transmit mbuf */neput(sc, index, m)struct ne_softc *sc;int index;register struct mbuf *m;{ register caddr_t dp,bp; register int len = 0; struct mbuf *m0; m0 = m; bp = mtod(sc->tmbuf[index],caddr_t); while(m) { if (m->m_len != 0) { dp = mtod(m,caddr_t); bcopy(dp,bp,(unsigned)m->m_len); bp += m->m_len; len += m->m_len; } m = m->m_next; } if(len < MINDATA) { bzero(bp,MINDATA - len); len = MINDATA; } /* * save the mbuf chain pointer */ sc->smbuf[index]=m0;return(len);}/* * fill out the setup packet - the physical address will already be * presented in first row */nesetup(sc,flag)struct ne_softc *sc;int flag;{ register int i, j; /* * fill out the broadcast address to the rest of the entries * the first one will be the station address. The second one * will be all 1's * */ for( j=1; j <= 15 ; j ++ ) bcopy(ne_multi,&sc->ne_setup[j],6); /* * If there have multicast addresses, just fill in the rest of * setup frame. */ for( i = 0, j = 2 ; i < NMULTI - 2 ; i++) { if(bcmp(&sc->multi[i],ne_multi,6) != 0) { bcopy(&sc->multi[i],&sc->ne_setup[j],6); j++; } } sc->setupqueued++; if(flag) sc->ne_setup_ic = 1;} /* * Initialize a ring descriptor */neinitdesc(descp,m,type) register NEDESC *descp;register struct mbuf *m;int type;{ /* * Zero the descriptor */ bzero (descp, sizeof(NEDESC)); /* * Tie cluster mbuf to ring descriptor. Bump up m_off by 2 bytes * in order to satisfy NFS, which needs longword-aligned data. * (Otherwise, the 14 byte ethernet header would place the * data at a non-longword alignment. */ if(type) m->m_off +=2; /* +4 for CRC */ descp->ne_bsize = ETHERMTU + sizeof(struct ether_header) + 4; #ifdef vax descp->ne_bfaddr = svtopte(mtod(m,u_long *)); descp->ne_pg_off = (unsigned)dp&PGOFFSET; descp->ne_info = NE_VA;#else descp->ne_bfaddr = svtophy(mtod(m,u_long *)); descp->ne_info = 0; #endif return;}/* * Reset the SGEC chip, check the selftest, reallocate the mbuf */nereset(sc)struct ne_softc *sc;{ struct ifnet *ifp = &sc->is_if; int i; neresets++; /* * Stop network activity */ if (ifp->if_flags & IFF_RUNNING) ifp->if_flags &= ~(IFF_UP | IFF_RUNNING); if (nedebug) mprintf("nereset: reseted ne%d %d\n",ifp->if_unit,neresets); nesoftreset(sc,ifp->if_unit); nesetcsr0(sc,ifp->if_unit);#ifdef vax csrpt->csr7 = (u_long) mfpr(SBR);#endif /* * free up all the xmt mbufs */ for (i=0; i < sc->ntring; i++) { if(sc->tmbuf[i]) m_freem(sc->tmbuf[i]); sc->tmbuf[i] = (struct mbuf *)NULL; if(sc->smbuf[i]) m_freem(sc->smbuf[i]); sc->smbuf[i] = (struct mbuf *)NULL; } /* * free up all the rcv mbufs */ for (i=0; i < sc->nrring; i++) { if(sc->rmbuf[i]) m_freem(sc->rmbuf[i]); sc->rmbuf[i] = (struct mbuf *)NULL; } neinit(ifp->if_unit);} /* * Reset the SGEC chip, check the selftest result and initialize the * CSR1 */nesoftreset(sc,unit)struct ne_softc *sc;int unit;{ register NECSRS *csrpt = sc->ne_csrs; int delay; /* * Reset the SGEC chip * Wait up to 25ms for complete the reset * and initialization */ csrpt->csr6 = NE_CSR6_RE ; for(delay=100; !(csrpt->csr5 & NE_CSR5_ID) || delay < 0 ; delay--) DELAY(2500); if (!(csrpt->csr5 & NE_CSR5_ID)) { printf("ne%d : cannot reset the SGEC chip \n",unit); return(0); } /* * self test check routine * SGEC self test takes 25ms to complete after Hardware or software * reset */ if(!(csrpt->csr5 & NE_CSR5_SF )) return ((int)csrpt); /* selftest success */ else if(csrpt->csr5 & NE_SS_ROM) printf("ne%d : self test failed - ROM error\n",unit); else if(csrpt->csr5 & NE_SS_RAM) printf("ne%d : self test failed - RAM error\n",unit); else if(csrpt->csr5 & NE_SS_AFR) printf("ne%d : self test failed - Address Filter RAM error\n",unit); else if(csrpt->csr5 & NE_SS_TFF) printf("ne%d : self test failed - Transmit FIFO error\n",unit); else if(csrpt->csr5 & NE_SS_RFF) printf("ne%d : self test failed - Receive FIFO error\n",unit); else if(csrpt->csr5 & NE_SS_SLE) printf("ne%d : self test failed - Lookback error\n",unit); return(0);}/* * initialize the CSR0 with IPL, SA and IV */nesetcsr0(sc,unit)struct ne_softc *sc;int unit;{ u_long csr=sc->ne_initcsr; NECSRS *csrpt=sc->ne_csrs; int s,retry,csr0; s = splimp(); /* raise the ipl to disable other interrupt */ for (retry=5; (csr0 != sc->ne_initcsr) && (retry >= 0); retry--) { csrpt->csr0 = sc->ne_initcsr; wbflush(); csr0 = csrpt->csr0 ; } splx(s); if(csr0 != sc->ne_initcsr) { printf("ne %d : fail to write CSR0",unit); return(0); } else { /* check for the pending parrity error interrupt */ if( csrpt->csr5 & NE_CSR5_ME ) csrpt->csr5 = NE_CSR5_IS | NE_CSR5_ME ; return(csr); }}newatch(unit)int unit;{ register struct ne_softc *sc = &ne_softc[unit]; register struct ifnet *ifp = &sc->is_if; int s; s = splimp(); ifp->if_timer = 0; nereset(sc); splx(s);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -