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

📄 ethersaturn.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
#include "u.h"#include "../port/lib.h"#include "mem.h"#include "dat.h"#include "fns.h"#include "io.h"#include "../port/error.h"#include "../port/netif.h"#include "msaturn.h"#include "etherif.h"enum{	Etcr = Saturn + 0x0c00,	Etsr = Saturn + 0x0c02,	Ercr = Saturn + 0x0c04,	Ersr = Saturn + 0x0c06,	Eisr = Saturn + 0x0d04,	Eimr = Saturn + 0x0d06,	Emacaddr0 = Saturn + 0x0e02,	Miicr = Saturn + 0x0f02,	Miiwdr = Saturn + 0x0f04,	Miirdr = Saturn + 0x0f06,	Ethermem = 0xf2c00000,	Etherfsize = 0x2000,	Nrx = 14,	Ntx = 2,		// Nrx + Ntx must be 16	Ersr_rxfpmask = 0xf,	Ersr_rxevent = RBIT(0, ushort),	Etcr_txfpmask = 0xf,	Ercr_rxenab = RBIT(0, ushort),	Ercr_auienab = RBIT(2, ushort),	Etcr_txstart = RBIT(1, ushort),	Etcr_retries = 0xf<<8,	Ei_txecall = RBIT(0, ushort),	Ei_txretry = RBIT(2, ushort),	Ei_txdefer = RBIT(3, ushort),	Ei_txcrs = RBIT(4, ushort),	Ei_txdone = RBIT(5, ushort),	Ei_rxcrcerr = RBIT(8, ushort),	Ei_rxdrib = RBIT(9, ushort),	Ei_rxdone = RBIT(10, ushort),	Ei_rxshort = RBIT(11, ushort),	Ei_rxlong = RBIT(12, ushort),	Miicr_regshift = 6,	Miicr_read = RBIT(10, ushort),	Miicr_preambledis = RBIT(12, ushort),	Miicr_accack = RBIT(14, ushort),	Miicr_accbsy = RBIT(15, ushort),};typedef struct {	Lock;	int		txbusy;	int		txempty;	int		txfull;	int		ntx;			/* number of entries in transmit ring */	int		rxlast;	int		active;	ulong	interrupts;	/* statistics */	ulong	overflows;} Ctlr;static ushort*etcr=(ushort*)Etcr;static ushort*etsr=(ushort*)Etsr;static ushort*ercr=(ushort*)Ercr;static ushort*ersr=(ushort*)Ersr;static ushort*eimr=(ushort*)Eimr;static ushort*eisr=(ushort*)Eisr;static ushort*miicr=(ushort*)Miicr;static ushort*miirdr=(ushort*)Miirdr;static voidtxfill(Ether*ether, Ctlr*ctlr){	int len;	Block *b;	ushort*dst;	while(ctlr->ntx<Ntx){		if((b=qget(ether->oq)) == nil)			break;		len = BLEN(b);		dst = (ushort*)(Ethermem+(ctlr->txempty+Nrx)*Etherfsize);		*dst = len;		memmove(&dst[1], b->rp, len);		ctlr->ntx++;		ctlr->txempty++;		if(ctlr->txempty==Ntx)			ctlr->txempty = 0;		freeb(b);	}}static voidtxrestart(Ctlr*ctlr){	if(ctlr->ntx==0 || ctlr->txbusy)		return;	ctlr->txbusy = 1;	*etcr = Etcr_txstart|Etcr_retries|(ctlr->txfull+Nrx);}static void interrupt(Ureg*, void*);static voidtransmit(Ether*ether){	Ctlr *ctlr;	ctlr = ether->ctlr;	ilock(ctlr);	txfill(ether, ctlr);	txrestart(ctlr);	iunlock(ctlr);}static voidinterrupt(Ureg*, void*arg){	Ctlr*ctlr;	Ether*ether = arg;	Etherpkt*pkt;	ushort ie;	int rx, len;	Block *b;	ctlr = ether->ctlr;	if(!ctlr->active)		return;	/* not ours */	ctlr->interrupts++;	ilock(ctlr);	ie = *eisr;	*eisr = ie;	intack();	if(ie==0)		iprint("interrupt: no interrupt source?\n");	if(ie&Ei_txdone){		if((*etcr&Etcr_txstart)==0){			if(ctlr->txbusy){				ctlr->txbusy = 0;				ctlr->ntx--;				ctlr->txfull++;				if(ctlr->txfull==Ntx)					ctlr->txfull = 0;			}			txrestart(ctlr);			txfill(ether, ctlr);			txrestart(ctlr);		}		else			iprint("interrupt: bogus tx interrupt\n");		ie &= ~Ei_txdone;	}	if(ie&Ei_rxdone){		rx=*ersr&Ersr_rxfpmask;		while(ctlr->rxlast!=rx){			ctlr->rxlast++;			if(ctlr->rxlast >= Nrx)				ctlr->rxlast = 0;			pkt = (Etherpkt*)(Ethermem+ctlr->rxlast*Etherfsize);			len = *(ushort*)pkt;			if((b = iallocb(len+sizeof(ushort))) != nil){				memmove(b->wp, pkt, len+sizeof(ushort));				b->rp += sizeof(ushort);				b->wp = b->rp + len;				etheriq(ether, b, 1);			}else				ether->soverflows++;			rx=*ersr&Ersr_rxfpmask;		}		ie &= ~Ei_rxdone;	}	if(ie&Ei_txretry){		iprint("ethersaturn: txretry!\n");		ie &= ~Ei_txretry;		ctlr->txbusy = 0;		txrestart(ctlr);	}	ie &= ~Ei_txcrs;	if(ie)		iprint("interrupt: unhandled interrupts %.4uX\n", ie);	iunlock(ctlr);}static intreset(Ether* ether){	Ctlr*ctlr;	*ercr = 0;	ctlr = malloc(sizeof(*ctlr));	memset(ctlr, 0, sizeof(*ctlr));	ctlr->active = 1;	ether->ctlr = ctlr;	ether->transmit = transmit;	ether->interrupt = interrupt;	ether->irq = Vecether;	ether->arg = ether;	memmove(ether->ea, (ushort*)Emacaddr0, Eaddrlen);	*ercr = Ercr_rxenab|Ercr_auienab|(Nrx-1);	*eimr = Ei_rxdone|Ei_txretry|Ei_txdone;		iprint("reset: ercr %.4uX\n", *ercr);	return 0;}voidethersaturnlink(void){	addethercard("saturn", reset);}

⌨️ 快捷键说明

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