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

📄 etherigbe.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 3 页
字号:
enum {	CMrdtr,};static Cmdtab igbectlmsg[] = {	CMrdtr,	"rdtr",	2,};static longigbectl(Ether* edev, void* buf, long n){	int v;	char *p;	Ctlr *ctlr;	Cmdbuf *cb;	Cmdtab *ct;	if((ctlr = edev->ctlr) == nil)		error(Enonexist);	cb = parsecmd(buf, n);	if(waserror()){		free(cb);		nexterror();	}	ct = lookupcmd(cb, igbectlmsg, nelem(igbectlmsg));	switch(ct->index){	case CMrdtr:		v = strtol(cb->f[1], &p, 0);		if(v < 0 || p == cb->f[1] || v > 0xFFFF)			error(Ebadarg);		ctlr->rdtr = v;;		csr32w(ctlr, Rdtr, Fpd|v);		break;	}	free(cb);	poperror();	return n;}static voidigbepromiscuous(void* arg, int on){	int rctl;	Ctlr *ctlr;	Ether *edev;	edev = arg;	ctlr = edev->ctlr;	rctl = csr32r(ctlr, Rctl);	rctl &= ~MoMASK;	rctl |= Mo47b36;	if(on)		rctl |= Upe|Mpe;	else		rctl &= ~(Upe|Mpe);	csr32w(ctlr, Rctl, rctl);}static voidigbemulticast(void* arg, uchar* addr, int on){	int bit, x;	Ctlr *ctlr;	Ether *edev;	edev = arg;	ctlr = edev->ctlr;	x = addr[5]>>1;	bit = ((addr[5] & 1)<<4)|(addr[4]>>4);	if(on)		ctlr->mta[x] |= 1<<bit;	else		ctlr->mta[x] &= ~(1<<bit);	csr32w(ctlr, Mta+x*4, ctlr->mta[x]);}static Block*igberballoc(void){	Block *bp;	ilock(&igberblock);	if((bp = igberbpool) != nil){		igberbpool = bp->next;		bp->next = nil;	}	iunlock(&igberblock);	return bp;}static voidigberbfree(Block* bp){	bp->rp = bp->lim - Rbsz;	bp->wp = bp->rp;	ilock(&igberblock);	bp->next = igberbpool;	igberbpool = bp;	iunlock(&igberblock);}static voidigbeim(Ctlr* ctlr, int im){	ilock(&ctlr->imlock);	ctlr->im |= im;	csr32w(ctlr, Ims, ctlr->im);	iunlock(&ctlr->imlock);}static intigbelim(void* ctlr){	return ((Ctlr*)ctlr)->lim != 0;}static voidigbelproc(void* arg){	Ctlr *ctlr;	Ether *edev;	MiiPhy *phy;	int ctrl, r;	edev = arg;	ctlr = edev->ctlr;	for(;;){		if(ctlr->mii == nil || ctlr->mii->curphy == nil)			continue;		/*		 * To do:		 *	logic to manage status change,		 *	this is incomplete but should work		 *	one time to set up the hardware.		 *		 *	MiiPhy.speed, etc. should be in Mii.		 */		if(miistatus(ctlr->mii) < 0)			//continue;			goto enable;		phy = ctlr->mii->curphy;		ctrl = csr32r(ctlr, Ctrl);		switch(ctlr->id){		case i82543gc:		case i82544ei:		default:			if(!(ctrl & Asde)){				ctrl &= ~(SspeedMASK|Ilos|Fd);				ctrl |= Frcdplx|Frcspd;				if(phy->speed == 1000)					ctrl |= Sspeed1000;				else if(phy->speed == 100)					ctrl |= Sspeed100;				if(phy->fd)					ctrl |= Fd;			}			break;		case i82540em:		case i82540eplp:		case i82547gi:		case i82541gi:		case i82541gi2:		case i82541pi:			break;		}		/*		 * Collision Distance.		 */		r = csr32r(ctlr, Tctl);		r &= ~ColdMASK;		if(phy->fd)			r |= 64<<ColdSHIFT;		else			r |= 512<<ColdSHIFT;		csr32w(ctlr, Tctl, r);		/*		 * Flow control.		 */		if(phy->rfc)			ctrl |= Rfce;		if(phy->tfc)			ctrl |= Tfce;		csr32w(ctlr, Ctrl, ctrl);enable:		ctlr->lim = 0;		igbeim(ctlr, Lsc);		ctlr->lsleep++;		sleep(&ctlr->lrendez, igbelim, ctlr);	}}static voidigbetxinit(Ctlr* ctlr){	int i, r;	Block *bp;	csr32w(ctlr, Tctl, (0x0F<<CtSHIFT)|Psp|(66<<ColdSHIFT));	switch(ctlr->id){	default:		r = 6;		break;	case i82543gc:	case i82544ei:	case i82547ei:	case i82540em:	case i82540eplp:	case i82541gi:	case i82541gi2:	case i82541pi:	case i82545gmc:	case i82546gb:	case i82546eb:	case i82547gi:		r = 8;		break;	}	csr32w(ctlr, Tipg, (6<<20)|(8<<10)|r);	csr32w(ctlr, Ait, 0);	csr32w(ctlr, Txdmac, 0);	csr32w(ctlr, Tdbal, PCIWADDR(ctlr->tdba));	csr32w(ctlr, Tdbah, 0);	csr32w(ctlr, Tdlen, ctlr->ntd*sizeof(Td));	ctlr->tdh = PREV(0, ctlr->ntd);	csr32w(ctlr, Tdh, 0);	ctlr->tdt = 0;	csr32w(ctlr, Tdt, 0);	for(i = 0; i < ctlr->ntd; i++){		if((bp = ctlr->tb[i]) != nil){			ctlr->tb[i] = nil;			freeb(bp);		}		memset(&ctlr->tdba[i], 0, sizeof(Td));	}	ctlr->tdfree = ctlr->ntd;	csr32w(ctlr, Tidv, 128);	r = (4<<WthreshSHIFT)|(4<<HthreshSHIFT)|(8<<PthreshSHIFT);	switch(ctlr->id){	default:		break;	case i82540em:	case i82540eplp:	case i82547gi:	case i82545gmc:	case i82546gb:	case i82546eb:	case i82541gi:	case i82541gi2:	case i82541pi:		r = csr32r(ctlr, Txdctl);		r &= ~WthreshMASK;		r |= Gran|(4<<WthreshSHIFT);		csr32w(ctlr, Tadv, 64);		break;	}	csr32w(ctlr, Txdctl, r);	r = csr32r(ctlr, Tctl);	r |= Ten;	csr32w(ctlr, Tctl, r);}static voidigbetransmit(Ether* edev){	Td *td;	Block *bp;	Ctlr *ctlr;	int tdh, tdt;	ctlr = edev->ctlr;	ilock(&ctlr->tlock);	/*	 * Free any completed packets	 */	tdh = ctlr->tdh;	while(NEXT(tdh, ctlr->ntd) != csr32r(ctlr, Tdh)){		if((bp = ctlr->tb[tdh]) != nil){			ctlr->tb[tdh] = nil;			freeb(bp);		}		memset(&ctlr->tdba[tdh], 0, sizeof(Td));		tdh = NEXT(tdh, ctlr->ntd);	}	ctlr->tdh = tdh;	/*	 * Try to fill the ring back up.	 */	tdt = ctlr->tdt;	while(NEXT(tdt, ctlr->ntd) != tdh){		if((bp = qget(edev->oq)) == nil)			break;		td = &ctlr->tdba[tdt];		td->addr[0] = PCIWADDR(bp->rp);		td->control = ((BLEN(bp) & LenMASK)<<LenSHIFT);		td->control |= Dext|Ifcs|Teop|DtypeDD;		ctlr->tb[tdt] = bp;		tdt = NEXT(tdt, ctlr->ntd);		if(NEXT(tdt, ctlr->ntd) == tdh){			td->control |= Rs;			ctlr->txdw++;			ctlr->tdt = tdt;			csr32w(ctlr, Tdt, tdt);			igbeim(ctlr, Txdw);			break;		}		ctlr->tdt = tdt;		csr32w(ctlr, Tdt, tdt);	}	iunlock(&ctlr->tlock);}static voidigbereplenish(Ctlr* ctlr){	Rd *rd;	int rdt;	Block *bp;	rdt = ctlr->rdt;	while(NEXT(rdt, ctlr->nrd) != ctlr->rdh){		rd = &ctlr->rdba[rdt];		if(ctlr->rb[rdt] == nil){			bp = igberballoc();			if(bp == nil){				iprint("no available buffers\n");				break;			}			ctlr->rb[rdt] = bp;			rd->addr[0] = PCIWADDR(bp->rp);			rd->addr[1] = 0;		}		coherence();		rd->status = 0;		rdt = NEXT(rdt, ctlr->nrd);		ctlr->rdfree++;	}	ctlr->rdt = rdt;	csr32w(ctlr, Rdt, rdt);}static voidigberxinit(Ctlr* ctlr){	int i;	Block *bp;	csr32w(ctlr, Rctl, Dpf|Bsize2048|Bam|RdtmsHALF);	csr32w(ctlr, Rdbal, PCIWADDR(ctlr->rdba));	csr32w(ctlr, Rdbah, 0);	csr32w(ctlr, Rdlen, ctlr->nrd*sizeof(Rd));	ctlr->rdh = 0;	csr32w(ctlr, Rdh, 0);	ctlr->rdt = 0;	csr32w(ctlr, Rdt, 0);	ctlr->rdtr = 0;	csr32w(ctlr, Rdtr, Fpd|0);	for(i = 0; i < ctlr->nrd; i++){		if((bp = ctlr->rb[i]) != nil){			ctlr->rb[i] = nil;			freeb(bp);		}	}	igbereplenish(ctlr);	switch(ctlr->id){	case i82540em:	case i82540eplp:	case i82541gi:	case i82541gi2:	case i82541pi:	case i82545gmc:	case i82546gb:	case i82546eb:	case i82547gi:		csr32w(ctlr, Radv, 64);		break;	}	csr32w(ctlr, Rxdctl, (8<<WthreshSHIFT)|(8<<HthreshSHIFT)|4);	/*	 * Enable checksum offload.	 */	csr32w(ctlr, Rxcsum, Tuofl|Ipofl|(ETHERHDRSIZE<<PcssSHIFT));}static intigberim(void* ctlr){	return ((Ctlr*)ctlr)->rim != 0;}static voidigberproc(void* arg){	Rd *rd;	Block *bp;	Ctlr *ctlr;	int r, rdh;	Ether *edev;	edev = arg;	ctlr = edev->ctlr;	igberxinit(ctlr);	r = csr32r(ctlr, Rctl);	r |= Ren;	csr32w(ctlr, Rctl, r);	for(;;){		ctlr->rim = 0;		igbeim(ctlr, Rxt0|Rxo|Rxdmt0|Rxseq);		ctlr->rsleep++;		sleep(&ctlr->rrendez, igberim, ctlr);		rdh = ctlr->rdh;		for(;;){			rd = &ctlr->rdba[rdh];			if(!(rd->status & Rdd))				break;			/*			 * Accept eop packets with no errors.			 * With no errors and the Ixsm bit set,			 * the descriptor status Tpcs and Ipcs bits give			 * an indication of whether the checksums were			 * calculated and valid.			 */			if((rd->status & Reop) && rd->errors == 0){				bp = ctlr->rb[rdh];				ctlr->rb[rdh] = nil;				bp->wp += rd->length;				bp->next = nil;				if(!(rd->status & Ixsm)){					ctlr->ixsm++;					if(rd->status & Ipcs){						/*						 * IP checksum calculated						 * (and valid as errors == 0).						 */						ctlr->ipcs++;						bp->flag |= Bipck;					}					if(rd->status & Tcpcs){						/*						 * TCP/UDP checksum calculated						 * (and valid as errors == 0).						 */						ctlr->tcpcs++;						bp->flag |= Btcpck|Budpck;					}					bp->checksum = rd->checksum;					bp->flag |= Bpktck;				}				etheriq(edev, bp, 1);			}			else if(ctlr->rb[rdh] != nil){				freeb(ctlr->rb[rdh]);				ctlr->rb[rdh] = nil;			}			memset(rd, 0, sizeof(Rd));			coherence();			ctlr->rdfree--;			rdh = NEXT(rdh, ctlr->nrd);		}		ctlr->rdh = rdh;		if(ctlr->rdfree < ctlr->nrd/2 || (ctlr->rim & Rxdmt0))			igbereplenish(ctlr);	}}static voidigbeattach(Ether* edev){	Block *bp;	Ctlr *ctlr;	char name[KNAMELEN];	ctlr = edev->ctlr;	qlock(&ctlr->alock);	if(ctlr->alloc != nil){		qunlock(&ctlr->alock);		return;	}	ctlr->nrd = ROUND(Nrd, 8);	ctlr->ntd = ROUND(Ntd, 8);	ctlr->alloc = malloc(ctlr->nrd*sizeof(Rd)+ctlr->ntd*sizeof(Td) + 127);	if(ctlr->alloc == nil){		qunlock(&ctlr->alock);		return;	}	ctlr->rdba = (Rd*)ROUNDUP((uintptr)ctlr->alloc, 128);	ctlr->tdba = (Td*)(ctlr->rdba+ctlr->nrd);	ctlr->rb = malloc(ctlr->nrd*sizeof(Block*));	ctlr->tb = malloc(ctlr->ntd*sizeof(Block*));	if(waserror()){		while(ctlr->nrb > 0){			bp = igberballoc();			bp->free = nil;			freeb(bp);			ctlr->nrb--;		}		free(ctlr->tb);		ctlr->tb = nil;		free(ctlr->rb);		ctlr->rb = nil;		free(ctlr->alloc);		ctlr->alloc = nil;		qunlock(&ctlr->alock);		nexterror();	}	for(ctlr->nrb = 0; ctlr->nrb < Nrb; ctlr->nrb++){		if((bp = allocb(Rbsz)) == nil)			break;		bp->free = igberbfree;		freeb(bp);	}	snprint(name, KNAMELEN, "#l%dlproc", edev->ctlrno);	kproc(name, igbelproc, edev);	snprint(name, KNAMELEN, "#l%drproc", edev->ctlrno);	kproc(name, igberproc, edev);	igbetxinit(ctlr);	qunlock(&ctlr->alock);	poperror();}static voidigbeinterrupt(Ureg*, void* arg){	Ctlr *ctlr;	Ether *edev;	int icr, im, txdw;	edev = arg;	ctlr = edev->ctlr;	ilock(&ctlr->imlock);	csr32w(ctlr, Imc, ~0);	im = ctlr->im;	txdw = 0;	while((icr = csr32r(ctlr, Icr) & ctlr->im) != 0){		if(icr & Lsc){			im &= ~Lsc;			ctlr->lim = icr & Lsc;			wakeup(&ctlr->lrendez);			ctlr->lintr++;		}		if(icr & (Rxt0|Rxo|Rxdmt0|Rxseq)){			im &= ~(Rxt0|Rxo|Rxdmt0|Rxseq);			ctlr->rim = icr & (Rxt0|Rxo|Rxdmt0|Rxseq);			wakeup(&ctlr->rrendez);			ctlr->rintr++;		}		if(icr & Txdw){			im &= ~Txdw;			txdw++;			ctlr->tintr++;		}	}	ctlr->im = im;	csr32w(ctlr, Ims, im);	iunlock(&ctlr->imlock);	if(txdw)		igbetransmit(edev);}static inti82543mdior(Ctlr* ctlr, int n){	int ctrl, data, i, r;	/*	 * Read n bits from the Management Data I/O Interface.	 */	ctrl = csr32r(ctlr, Ctrl);	r = (ctrl & ~Mddo)|Mdco;	data = 0;	for(i = n-1; i >= 0; i--){		if(csr32r(ctlr, Ctrl) & Mdd)			data |= (1<<i);		csr32w(ctlr, Ctrl, Mdc|r);		csr32w(ctlr, Ctrl, r);	}	csr32w(ctlr, Ctrl, ctrl);	return data;}static inti82543mdiow(Ctlr* ctlr, int bits, int n){	int ctrl, i, r;	/*	 * Write n bits to the Management Data I/O Interface.	 */	ctrl = csr32r(ctlr, Ctrl);	r = Mdco|Mddo|ctrl;	for(i = n-1; i >= 0; i--){		if(bits & (1<<i))			r |= Mdd;		else			r &= ~Mdd;		csr32w(ctlr, Ctrl, Mdc|r);		csr32w(ctlr, Ctrl, r);	}	csr32w(ctlr, Ctrl, ctrl);	return 0;}static inti82543miimir(Mii* mii, int pa, int ra){	int data;	Ctlr *ctlr;	ctlr = mii->ctlr;	/*	 * MII Management Interface Read.

⌨️ 快捷键说明

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