⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 if_ln.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 5 页
字号:
	}	/* set STOP to clear INIT and IDON (and everything else) */	sc->ln_rdp = LN_STOP;	return( sizeof(struct ln_initb));} /* * Interface exists: make available by filling in network interface * record.  System will initialize the interface when it is ready * to accept packets. */lnattach(ui) 	struct uba_device *ui;{	register struct ln_softc *sc = ln_softc[ui->ui_unit];	register struct ifnet *ifp = &sc->is_if;	register int i;	register struct sockaddr_in *sin;        /* Initialize the lock. */        lockinit(&sc->lk_ln_softc, &lock_device15_d);	ifp->if_unit = ui->ui_unit;	ifp->if_name = "ln";	ifp->lk_softc = &sc->lk_ln_softc;	ifp->if_mtu = ETHERMTU;	ifp->if_type = IFT_ETHER;	ifp->if_flags |= IFF_BROADCAST | IFF_DYNPROTO | IFF_NOTRAILERS;	((struct arpcom *)ifp)->ac_ipaddr.s_addr = 0;	/*	 * Read the address from the prom and save it.	 */	for ( i=0 ; i<6 ; i++ ) {		sc->is_addr[i] = (u_char)((sc->ln_narom[i] >> sc->lnsw->ln_na_align) & 0xff);	}		sin = (struct sockaddr_in *)&ifp->if_addr;	sin->sin_family = AF_INET;	ifp->if_init = lninit;	ifp->if_output = net_output;	ifp->if_start = lnstart;	ifp->if_ioctl = lnioctl;	ifp->if_timer = 0;	ifp->if_watchdog = lnwatch; 	ifp->if_reset = 0;        ifp->d_affinity = ALLCPU;       /* SMP */	bcopy("DEC LANCE Ethernet Interface", ifp->if_version, 28);	ifp->if_version[28] = '\0';	printf("ln%d: %s, hardware address: %s \n", ui->ui_unit,		ifp->if_version,ether_sprintf(sc->is_addr));	#if NPACKETFILTER > 0        attachpfilter(&(sc->is_ed));#endif NPACKETFILTER > 0	if_attach(ifp);}/* * Initialization of interface and allocation of mbufs for receive ring */lninit(unit)	int unit;{	register struct ln_softc *sc = ln_softc[unit];	register struct ln_initb *initb = &sc->ln_initb;	register struct lnsw *lnsw = sc->lnsw;	register struct ifnet *ifp = &sc->is_if;	int i,k;	/* address not known */	if (ifp->if_addrlist == (struct ifaddr *)0)		return;	if (ifp->if_flags & IFF_RUNNING)		return;	/*	 * We only nail down our buffer addresses on the very	 * first call, then don't relinquish them again.	 */        k = splimp();        smp_lock(&sc->lk_ln_softc, LK_RETRY);	sc->callno++;	/*	 * Init the buffer descriptors and	 * indexes for each of the lists.	 */	for ( i = 0 ; i < nLNNRCV ; i++ ) {		lnsw->lninitdesc (sc, sc->rring[i], &sc->rlbuf[i],			    (sc->callno == 1) ? LNALLOC : LNNOALLOC, i);		/* give away rring */		lnsw->ln_setflag(sc->rring[i], LN_OWN);	}	for ( i = 0 ; i < nLNNXMT ; i++ ) {		lninitdesc (sc, sc->tring[i], &sc->tlbuf[i],			    (sc->callno == 1) ? LNALLOC : LNNOALLOC);	}	sc->nxmit = sc->otindex = sc->tindex = sc->rindex = 0;	/*	 * Take the interface out of reset, program the vector, 	 * enable interrupts, and tell the world we are up.	 */        /* s=splimp(); */  /* SMP */	sc->ln_rap = LN_CSR0;	if ( (ifp->if_flags & IFF_LOOPBACK)	   && (initb->ln_mode & LN_LOOP) == 0) {		/* if not in loopback mode, do loopback */		initb->ln_mode &= ~LN_INTL;		initb->ln_mode |= LN_LOOP;                smp_unlock(&sc->lk_ln_softc);		lnrestart(ifp);		lninit(ifp->if_unit);		splx(k);		return;	}	/* start the Lance; enable interrupts, etc */	sc->ln_rdp = (LN_START | LN_INEA);	ifp->if_flags |= IFF_RUNNING;	ifp->if_flags &= ~IFF_OACTIVE;	lnstart( unit );	sc->ztime = time.tv_sec;        smp_unlock(&sc->lk_ln_softc);	splx(k);} /* * Ethernet interface interrupt processor */lnintr(unit)	int unit;{	register struct ln_softc *sc = ln_softc[unit];	register struct ifnet *ifp;	register int s, oldcsr;	ifp = &sc->is_if;	s = splimp();	/*	 * If a set-1-to-reset bit is 1, then writing a 1	 * back into the csr register will clear that bit.	 * This is OK; the intent is to clear the csr of all	 * errors/interrupts and then process the saved bits	 * in the old csr. We grab the "ln_flag" byte out of	 * the ring entry to check the ownership bit FIRST,	 * then grab the "ln_flag2" short word later to eliminate	 * a timing window in which the LANCE may update the	 * "ln_flag" before updating "ln_flag2".	 */	oldcsr = sc->ln_rdp;		/* save the old csr */	oldcsr &= ~LN_INEA;	/* clear interrupt enable */#ifdef mips	if(cpu == DS_5000) {  /* work around for R3000 bug */		rdpptr=	(volatile unsigned long *)&sc->ln_rdp;		*rdpptr = oldcsr;	}	else #endif		sc->ln_rdp = oldcsr;	sc->ln_rdp = LN_INEA;	/* set interrupt enable */	/*	 * check error bits	 */	if ( oldcsr & LN_ERR ) {		if (oldcsr & LN_MISS) {			/*			 * LN_MISS is signaled when the LANCE receiver			 * loses a packet because it doesn't own a			 * receive descriptor. Rev. D LANCE chips, which			 * are no longer used, require a chip reset as			 * described below.			 */			lnmisscnt++;			if (lndebug)				mprintf("ln%d: missed packet (MISS)\n",unit);			if(sc->ctrblk.est_sysbuf != 0xffff)				sc->ctrblk.est_sysbuf++;			/* This is a toss-up.  We don't increment			 * data overrun here because it's most likely			 * the host's fault that packets were missed.			 * No way to tell from here whether the LANCE			 * is at fault.			 *			if (sc->ctrblk.est_overrun != 0xffff)				sc->ctrblk.est_overrun++;			 */		}		if (oldcsr & LN_CERR) {			if (sc->ctrblk.est_collis != 0xffff)				sc->ctrblk.est_collis++;		}		if (oldcsr & LN_BABL) {			lnbablcnt++;			if (lndebug)			    mprintf("ln%d: transmitter timeout (BABL)\n",unit);		}		if (oldcsr & LN_MERR) {			lnmerrcnt++;			/* warn the user (printf on the terminal) */			mprintf("ln%d: memory error (MERR) \n", unit);			if (((oldcsr & LN_RXON) == 0)			    || ((oldcsr & LN_TXON) == 0)) {				lnrestart(ifp);				lninit(ifp->if_unit);				splx(s);				return;			}		}	}	if ( oldcsr & LN_RINT )		lnrint( unit );		/* check for lance dma memory read error, happens on xmit only 	 * disables DMA, times out lance, interrupts processor	 */	if (sc->lnsw->ln_dma) {	        caddr_t pa;		struct tc_memerr_status status;		if ( *(u_int *)(sc->siraddr) & BIT16SET) { 		        pa = (caddr_t)((*(u_int *)(sc->ldpaddr)) >> 3);			printf("ln%d: dma memory read error \n", unit);			status.pa = pa;			status.va = 0;			status.log = TC_LOG_MEMERR;			status.blocksize = 4;			tc_isolate_memerr(&status);   			*(u_int *)(sc->siraddr) &= ~BIT16SET;   			*(u_int *)(sc->ssraddr) |= BIT16SET;			lnrestart(ifp);			lninit(ifp->if_unit);			lndmareaderr++;			splx(s);			return;		}	}	if ( oldcsr & LN_TINT )		lntint( unit );	if (oldcsr == (LN_INTR|LN_RXON|LN_TXON))		mprintf("ln%d: stray interrupt\n",unit);	splx(s);} /* * Ethernet interface transmit interrupt. */lntint(unit)	int unit;{	register struct ln_softc *sc = ln_softc[unit];	register int index;	register int i;	register struct ln_ring *rp = &sc->ln_ring;	register struct lnsw *lnsw = sc->lnsw;	struct mbuf *mp, *mp0;	struct ifnet *ifp = &sc->is_if;	struct ether_header *eh;	short len;	/*	 * While we haven't caught up to current transmit index,	 * AND the buffer is ours, AND there are still transmits	 * which haven't been pulled off the ring yet, proceed	 * around the ring in search of the last packet. We grab	 * the "ln_flag" byte out of the ring entry to check the	 * ownership bit FIRST, then grab the "ln_flag2" short	 * word later to eliminate a timing window in which the	 * LANCE may update the "ln_flag" before updating "ln_flag2".	 */        smp_lock(&sc->lk_ln_softc, LK_RETRY);	lnsw->ln_cpyin(sc, sc->tring[sc->otindex], &rp->ln_flag,		       sizeof(u_char), (u_long)&rp->ln_flag - (u_long)rp);	while ( (sc->otindex != sc->tindex)	 && !(rp->ln_flag & LN_OWN)	 && sc->nxmit > 0 ) {		index = sc->otindex;		/*		 * Found last buffer in the packet		 * (hence a valid string of descriptors)		 * so free things up.		 */		mp = sc->tmbuf[index];		sc->tmbuf[index] = (struct mbuf *)NULL;		/* increment old index pointer, if it catches up		 * with current index pointer, we will break out		 * of the loop.  Otherwise, go around again		 * looking for next end-of-packet cycle.		 */		if (!(--sc->nxmit)) {			ifp->if_timer = 0;			ifp->if_flags &= ~IFF_OACTIVE;		}		sc->is_if.if_opackets++;		lnsw->ln_cpyin(sc, sc->tring[sc->otindex], &rp->ln_flag2,			       sizeof(u_short), (u_long)&rp->ln_flag2 - (u_long)rp);		/*		 * DECnet statistics		 */		/* exactly one collision? */		if ((rp->ln_flag & LN_ONE) && !(rp->ln_flag2 & LN_LCOL)) {			sc->is_if.if_collisions++;			if (sc->ctrblk.est_single != (unsigned)0xffffffff)				sc->ctrblk.est_single++;		/* more than one collision? */		} else if (rp->ln_flag & LN_MORE) {			sc->is_if.if_collisions += 2;			if (sc->ctrblk.est_multiple != (unsigned)0xffffffff)				sc->ctrblk.est_multiple++;		}		/*		 * Check for transmission errors.		 * This assumes that transmission errors		 * are always reported in the last packet.		 */		if (rp->ln_flag & LN_RT_ERR) {			sc->is_if.if_oerrors++;			if (sc->ctrblk.est_sendfail != 0xffff) {				sc->ctrblk.est_sendfail++;				if (rp->ln_flag2 & LN_RTRY) {					/* excessive collisions */					if (lndebug) mprintf("ln%d: excessive collisions (RTRY)\n",unit);					sc->ctrblk.est_sendfail_bm |= 1;				}				if (rp->ln_flag2 & LN_LCOL) {					if (lndebug) mprintf("ln%d: late transmit collision (LCOL)\n",unit);					; /* not implemented */				}				if (rp->ln_flag2 & LN_LCAR) {					if (lndebug) mprintf("ln%d: lost carrier during transmit (LCAR)\n",unit);					sc->ctrblk.est_sendfail_bm |= 2;				}				if (rp->ln_flag2 & LN_UFLO) {					if (lndebug) mprintf("ln%d: packet truncated (UFLO)\n,unit");				}				if (rp->ln_flag2 & LN_TBUFF) {					if (lndebug) mprintf("ln%d: transmit buffer error (BUFF)\n,unit");				}			}			/*			 * Restart chip if transmitter got turned off			 * due to transmit errors: UFLO, TBUFF or RTRY.			 */			if (rp->ln_flag2 & (LN_UFLO | LN_TBUFF | LN_RTRY)) {                                smp_unlock(&sc->lk_ln_softc);				/*				 * Need to free mp here, since we've				 * already destroyed its copy in the				 * "tmbuf" list.				 */				m_freem(mp);				lnrestart(ifp);				lninit(ifp->if_unit);				return;			}			m_freem(mp);		} else {			/*			 * If this was a broadcast packet or if the			 * interface is in COPYALL mode, loop it			 * back, otherwise just free the packet.			 */			if (mp) {				eh = mtod( mp, struct ether_header *);				for (i=0; (i < 6) && (eh->ether_dhost[i] == 0xff); i++)					; /*nop*/				if ( (i == 6) ||				   (ifp->if_flags & IFF_PFCOPYALL)) {					for ( mp0 = mp, len=0 ; mp0 ; mp0 = mp0->m_next ) {						len += mp0->m_len;					}					/* Bump up DECnet statistics */					if(eh->ether_dhost[0] & 1) {						sc->ctrblk.est_mbytesent += len;						if (sc->ctrblk.est_mbloksent != (unsigned) 0xffffffff)							sc->ctrblk.est_mbloksent++;					}					lnread( sc, 0, len, mp, 0 );				} else {					m_freem( mp );				}			}		}		/*		 * Init the buffer descriptor		 */		lninitdesc(sc, sc->tring[index], &sc->tlbuf[index], LNNOALLOC);		sc->otindex = ++index % nLNNXMT;		lnsw->ln_cpyin(sc, sc->tring[sc->otindex],&rp->ln_flag,			       sizeof(u_char), (u_long)&rp->ln_flag - (u_long)rp); /* for the next time thru while */	}	/*	 * Dequeue next transmit request, if any.	 */	if (!(ifp->if_flags & IFF_OACTIVE))		lnstart( unit );        smp_unlock(&sc->lk_ln_softc);} /* * Ethernet interface receiver interrupt. * If can't determine length from type, then have to drop packet.   * Othewise decapsulate packet based on type and pass to type specific  * higher-level input routine. */lnrint(unit)	int unit;{	register struct ln_softc *sc = ln_softc[unit];	register struct ln_ring *rp = &sc->ln_ring;	register struct lnsw *lnsw = sc->lnsw;	register int index, len;	register struct ifnet *ifp = &sc->is_if;	int first;	u_char flag;	/* saved status flag */	int ring_cnt;#ifdef lint	unit = unit;#endif	/*	 * Traverse the receive ring looking for packets to pass back.	 * The search is complete when we find a descriptor that is in	 * use (owned by Lance). 	 */        smp_lock(&sc->lk_ln_softc, LK_RETRY);	lnsw->ln_cpyin(sc, sc->rring[sc->rindex],&rp->ln_flag,		       sizeof(u_char),(u_long)&rp->ln_flag - (u_long)rp);	for ( ; !(rp->ln_flag & LN_OWN);	      sc->rindex = ++index % nLNNRCV, 	lnsw->ln_cpyin(sc, sc->rring[sc->rindex],&rp->ln_flag,		       sizeof(u_char), (u_long)&rp->ln_flag - (u_long)rp)) {		first = index = sc->rindex;				/*		 * If not the start of a packet, error		 */		if ( !(rp->ln_flag & LN_STP)) {			if (lndebug) {				mprintf("ln%d: recv: start of packet expected #%d, flag=%02x\n",		unit, index,(rp->ln_flag&0xff));			}			lnsw->ln_setflag(sc->rring[first], LN_OWN);                	smp_unlock(&sc->lk_ln_softc);			lnrestart(ifp);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -