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

📄 ether8390.c

📁 著名操作系统Plan 9的第三版的部分核心源代码。现在很难找到了。Plan 9是bell实验室开发的Unix后继者。
💻 C
📖 第 1 页 / 共 2 页
字号:
}static voidreceive(Ether* ether){	Dp8390 *ctlr;	uchar curr, *p;	Hdr hdr;	ulong count, data, len;	RingBuf *ring;	ctlr = ether->ctlr;	for(curr = getcurr(ctlr); ctlr->nxtpkt != curr; curr = getcurr(ctlr)){		data = ctlr->nxtpkt*Dp8390BufSz;		if(ctlr->ram)			memmove(&hdr, (void*)(ether->mem+data), sizeof(Hdr));		else			_dp8390read(ctlr, &hdr, data, sizeof(Hdr));		/*		 * Don't believe the upper byte count, work it		 * out from the software next-page pointer and		 * the current next-page pointer.		 */		if(hdr.next > ctlr->nxtpkt)			len = hdr.next - ctlr->nxtpkt - 1;		else			len = (ctlr->pstop-ctlr->nxtpkt) + (hdr.next-ctlr->pstart) - 1;		if(hdr.len0 > (Dp8390BufSz-sizeof(Hdr)))			len--;		len = ((len<<8)|hdr.len0)-4;		/*		 * Chip is badly scrogged, reinitialise the ring.		 */		if(hdr.next < ctlr->pstart || hdr.next >= ctlr->pstop		  || len < 60 || len > sizeof(Etherpkt)){			print("dp8390: H#%2.2ux#%2.2ux#%2.2ux#%2.2ux,%lud\n",				hdr.status, hdr.next, hdr.len0, hdr.len1, len);			regw(ctlr, Cr, Page0|RdABORT|Stp);			ringinit(ctlr);			regw(ctlr, Cr, Page0|RdABORT|Sta);			return;		}		/*		 * 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.		 */		ring = &ether->rb[ether->ri];		if((hdr.status & (Fo|Fae|Crce|Prxok)) == Prxok && ring->owner == Interface){			p = ring->pkt;			ring->len = 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.			 */			ring->owner = Host;			ether->ri = NEXT(ether->ri, ether->nrb);		}		/*		 * 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;	RingBuf *ring;	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(ether->tbusy)		return;	ring = &ether->tb[ether->ti];	if(ring->owner != Interface)		return;	/*	 * Make sure the packet is of minimum length;	 * copy it to the card's memory by the appropriate means;	 * start the transmission.	 */	len = ring->len;	rp = ring->pkt;	if(len < ETHERMINTU){		rp = minpkt;		memmove(rp, ring->pkt, 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);	regw(ctlr, Tbcr0, len & 0xFF);	regw(ctlr, Tbcr1, (len>>8) & 0xFF);	regw(ctlr, Cr, Page0|RdABORT|Txp|Sta);	ether->tbusy = 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;	RingBuf *ring;	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);		}		/*		 * 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);			}			regw(ctlr, Isr, Txe|Ptx);			ring = &ether->tb[ether->ti];			ring->owner = Host;			ether->ti = NEXT(ether->ti, ether->ntb);			ether->tbusy = 0;			txstart(ether);		}		if(isr & Cnt){			regr(ctlr, Cntr0);			regr(ctlr, Cntr1);			regr(ctlr, Cntr2);			regw(ctlr, Isr, Cnt);		}	}	regw(ctlr, Imr, Cnt|Ovw|Txe|Rxe|Ptx|Prx);	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;	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 voiddetach(Ether* ether){	int timo;	Dp8390 *ctlr;	/*	 * 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.	 */	ctlr = ether->ctlr;	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.	 */ 	detach(ether);	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->detach = detach;	return 0;}

⌨️ 快捷键说明

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