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

📄 ether8390.c

📁 著名操作系统Plan 9的第三版的部分核心源代码。现在很难找到了。Plan 9是bell实验室开发的Unix后继者。
💻 C
📖 第 1 页 / 共 2 页
字号:
		/*		 * If it's a good packet read it in to the software buffer.		 * If the packet wraps round the hardware ring, read it in		 * two pieces.		 */		if((hdr.status & (Fo|Fae|Crce|Prxok)) == Prxok && (bp = iallocb(len))){			p = bp->rp;			bp->wp = p+len;			data += sizeof(Hdr);			if((data+len) >= ctlr->pstop*Dp8390BufSz){				count = ctlr->pstop*Dp8390BufSz - data;				if(ctlr->ram)					memmove(p, (void*)(ether->mem+data), count);				else					_dp8390read(ctlr, p, data, count);				p += count;				data = ctlr->pstart*Dp8390BufSz;				len -= count;			}			if(len){				if(ctlr->ram)					memmove(p, (void*)(ether->mem+data), len);				else					_dp8390read(ctlr, p, data, len);			}			/*			 * Copy the packet to whoever wants it.			 */			etheriq(ether, bp, 1);		}		/*		 * Finished with this packet, update the		 * hardware and software ring pointers.		 */		ctlr->nxtpkt = hdr.next;		hdr.next--;		if(hdr.next < ctlr->pstart)			hdr.next = ctlr->pstop-1;		regw(ctlr, Bnry, hdr.next);	}}static voidtxstart(Ether* ether){	int len;	Dp8390 *ctlr;	Block *bp;	uchar minpkt[ETHERMINTU], *rp;	ctlr = ether->ctlr;	/*	 * This routine is called both from the top level and from interrupt	 * level and expects to be called with ctlr already locked.	 */	if(ctlr->txbusy)		return;	bp = qget(ether->oq);	if(bp == nil)		return;	/*	 * Make sure the packet is of minimum length;	 * copy it to the card's memory by the appropriate means;	 * start the transmission.	 */	len = BLEN(bp);	rp = bp->rp;	if(len < ETHERMINTU){		rp = minpkt;		memmove(rp, bp->rp, len);		memset(rp+len, 0, ETHERMINTU-len);		len = ETHERMINTU;	}	if(ctlr->ram)		memmove((void*)(ether->mem+ctlr->tstart*Dp8390BufSz), rp, len);	else		dp8390write(ctlr, ctlr->tstart*Dp8390BufSz, rp, len);	freeb(bp);	regw(ctlr, Tbcr0, len & 0xFF);	regw(ctlr, Tbcr1, (len>>8) & 0xFF);	regw(ctlr, Cr, Page0|RdABORT|Txp|Sta);	ether->outpackets++;	ctlr->txbusy = 1;}static voidtransmit(Ether* ether){	Dp8390 *ctlr;	ctlr = ether->ctlr;	ilock(ctlr);	txstart(ether);	iunlock(ctlr);}static voidoverflow(Ether *ether){	Dp8390 *ctlr;	uchar txp;	int resend;	ctlr = ether->ctlr;	/*	 * The following procedure is taken from the DP8390[12D] datasheet,	 * it seems pretty adamant that this is what has to be done.	 */	txp = regr(ctlr, Cr) & Txp;	regw(ctlr, Cr, Page0|RdABORT|Stp);	delay(2);	regw(ctlr, Rbcr0, 0);	regw(ctlr, Rbcr1, 0);	resend = 0;	if(txp && (regr(ctlr, Isr) & (Txe|Ptx)) == 0)		resend = 1;	regw(ctlr, Tcr, LpbkNIC);	regw(ctlr, Cr, Page0|RdABORT|Sta);	receive(ether);	regw(ctlr, Isr, Ovw);	regw(ctlr, Tcr, LpbkNORMAL);	if(resend)		regw(ctlr, Cr, Page0|RdABORT|Txp|Sta);}static voidinterrupt(Ureg*, void* arg){	Ether *ether;	Dp8390 *ctlr;	uchar isr, r;	ether = arg;	ctlr = ether->ctlr;	/*	 * While there is something of interest,	 * clear all the interrupts and process.	 */	ilock(ctlr);	regw(ctlr, Imr, 0x00);	while(isr = (regr(ctlr, Isr) & (Cnt|Ovw|Txe|Rxe|Ptx|Prx))){		if(isr & Ovw){			overflow(ether);			regw(ctlr, Isr, Ovw);			ether->overflows++;		}		/*		 * Packets have been received.		 * Take a spin round the ring.		 */		if(isr & (Rxe|Prx)){			receive(ether);			regw(ctlr, Isr, Rxe|Prx);		}		/*		 * A packet completed transmission, successfully or		 * not. Start transmission on the next buffered packet,		 * and wake the output routine.		 */		if(isr & (Txe|Ptx)){			r = regr(ctlr, Tsr);			if((isr & Txe) && (r & (Cdh|Fu|Crs|Abt))){				print("dp8390: Tsr#%2.2ux|", r);				ether->oerrs++;			}			regw(ctlr, Isr, Txe|Ptx);			if(isr & Ptx)				ether->outpackets++;			ctlr->txbusy = 0;			txstart(ether);		}		if(isr & Cnt){			ether->frames += regr(ctlr, Cntr0);			ether->crcs += regr(ctlr, Cntr1);			ether->buffs += regr(ctlr, Cntr2);			regw(ctlr, Isr, Cnt);		}	}	regw(ctlr, Imr, Cnt|Ovw|Txe|Rxe|Ptx|Prx);	iunlock(ctlr);}static uchar allmar[8] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };static voidsetfilter(Ether *ether, Dp8390 *ctlr){	uchar r, cr;	int i;	uchar *mar;	r = Ab;	mar = 0;	if(ether->prom){		r |= Pro|Am;		mar = allmar;	} else if(ether->nmaddr){		r |= Am;		mar = ctlr->mar;	}	if(mar){		cr = regr(ctlr, Cr) & ~Txp;		regw(ctlr, Cr, Page1|(~(Ps1|Ps0) & cr));		for(i = 0; i < 8; i++)			regw(ctlr, Mar0+i, *(mar++));		regw(ctlr, Cr, cr);	}	regw(ctlr, Rcr, r);}static voidpromiscuous(void *arg, int ){	Ether *ether;	Dp8390 *ctlr;	ether = arg;	ctlr = ether->ctlr;	ilock(ctlr);	setfilter(ether, ctlr);	iunlock(ctlr);}static voidsetbit(Dp8390 *ctlr, int bit, int on){	int i, h;	i = bit/8;	h = bit%8;	if(on){		if(++(ctlr->mref[bit]) == 1)			ctlr->mar[i] |= 1<<h;	} else {		if(--(ctlr->mref[bit]) <= 0){			ctlr->mref[bit] = 0;			ctlr->mar[i] &= ~(1<<h);		}	}}static uchar reverse[64];static voidmulticast(void* arg, uchar *addr, int on){	Ether *ether;	Dp8390 *ctlr;	int i;	ulong h;	ether = arg;	ctlr = ether->ctlr;	if(reverse[1] == 0){		for(i = 0; i < 64; i++)			reverse[i] = ((i&1)<<5) | ((i&2)<<3) | ((i&4)<<1)					| ((i&8)>>1) | ((i&16)>>3) | ((i&32)>>5);	}	/*	 *  change filter bits	 */	h = ethercrc(addr, 6);	ilock(ctlr);	setbit(ctlr, reverse[h&0x3f], on);	setfilter(ether, ctlr);	iunlock(ctlr);}static voidattach(Ether* ether){	Dp8390 *ctlr;	uchar r;	ctlr = ether->ctlr;	/*	 * Enable the chip for transmit/receive.	 * The init routine leaves the chip in monitor	 * mode. Clear the missed-packet counter, it	 * increments while in monitor mode.	 * Sometimes there's an interrupt pending at this	 * point but there's nothing in the Isr, so	 * any pending interrupts are cleared and the	 * mask of acceptable interrupts is enabled here.	 */	r = Ab;	if(ether->prom)		r |= Pro;	if(ether->nmaddr)		r |= Am;	ilock(ctlr);	regw(ctlr, Isr, 0xFF);	regw(ctlr, Imr, Cnt|Ovw|Txe|Rxe|Ptx|Prx);	regw(ctlr, Rcr, r);	r = regr(ctlr, Cntr2);	regw(ctlr, Tcr, LpbkNORMAL);	iunlock(ctlr);	USED(r);}static voiddisable(Dp8390* ctlr){	int timo;	/*	 * Stop the chip. Set the Stp bit and wait for the chip	 * to finish whatever was on its tiny mind before it sets	 * the Rst bit.	 * The timeout is needed because there may not be a real	 * chip there if this is called when probing for a device	 * at boot.	 */	regw(ctlr, Cr, Page0|RdABORT|Stp);	regw(ctlr, Rbcr0, 0);	regw(ctlr, Rbcr1, 0);	for(timo = 10000; (regr(ctlr, Isr) & Rst) == 0 && timo; timo--)			;}intdp8390reset(Ether* ether){	Dp8390 *ctlr;	ctlr = ether->ctlr;	/*	 * This is the initialisation procedure described	 * as 'mandatory' in the datasheet, with references	 * to the 3C503 technical reference manual.	 */ 	disable(ctlr);	if(ctlr->width != 1)		regw(ctlr, Dcr, Ft4WORD|Ls|Wts);	else		regw(ctlr, Dcr, Ft4WORD|Ls);	regw(ctlr, Rbcr0, 0);	regw(ctlr, Rbcr1, 0);	regw(ctlr, Tcr, LpbkNIC);	regw(ctlr, Rcr, Mon);	/*	 * Init the ring hardware and software ring pointers.	 * Can't initialise ethernet address as it may not be	 * known yet.	 */	ringinit(ctlr);	regw(ctlr, Tpsr, ctlr->tstart);	/*	 * Clear any pending interrupts and mask then all off.	 */	regw(ctlr, Isr, 0xFF);	regw(ctlr, Imr, 0);	/*	 * Leave the chip initialised,	 * but in monitor mode.	 */	regw(ctlr, Cr, Page0|RdABORT|Sta);	/*	 * Set up the software configuration.	 */	ether->attach = attach;	ether->transmit = transmit;	ether->interrupt = interrupt;	ether->ifstat = 0;	ether->promiscuous = promiscuous;	ether->multicast = multicast;	ether->arg = ether;	return 0;}

⌨️ 快捷键说明

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