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

📄 etherigbe.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 4 页
字号:
igbereplenish(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("igbereplenish: 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(PROCARG(void *arg)){	Rd *rd;	Block *bp;	Ctlr *ctlr;	int r, rdh;	Ether *edev;	edev = GETARG(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;				INCRPTR(bp, 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++;#ifndef FS						bp->flag |= Bipck;#endif					}					if(rd->status & Tcpcs){						/*						 * TCP/UDP checksum calculated						 * (and valid as errors == 0).						 */						ctlr->tcpcs++;#ifndef FS						bp->flag |= Btcpck|Budpck;#endif					}#ifndef FS					bp->checksum = rd->checksum;					bp->flag |= Bpktck;#endif				}				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 (ctlr->tb == nil)		panic("igbeattach: no mem");	if(waserror()){		while(ctlr->nrb > 0){			bp = igberballoc();			if (bp == nil)				panic("igbeattach: no mem for rcv bufs");			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;#ifdef FS		bp->flags |= Mbrcvbuf;#endif		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.	 *	 * Preamble;	 * ST+OP+PHYAD+REGAD;	 * TA + 16 data bits.	 */	i82543mdiow(ctlr, 0xFFFFFFFF, 32);	i82543mdiow(ctlr, 0x1800|(pa<<5)|ra, 14);	data = i82543mdior(ctlr, 18);	if(data & 0x10000)		return -1;	return data & 0xFFFF;}static inti82543miimiw(Mii* mii, int pa, int ra, int data){	Ctlr *ctlr;	ctlr = mii->ctlr;	/*	 * MII Management Interface Write.	 *	 * Preamble;	 * ST+OP+PHYAD+REGAD+TA + 16 data bits;	 * Z.	 */	i82543mdiow(ctlr, 0xFFFFFFFF, 32);	data &= 0xFFFF;	data |= (0x05<<(5+5+2+16))|(pa<<(5+2+16))|(ra<<(2+16))|(0x02<<16);	i82543mdiow(ctlr, data, 32);	return 0;}static intigbemiimir(Mii* mii, int pa, int ra){	Ctlr *ctlr;	int mdic, timo;	ctlr = mii->ctlr;	csr32w(ctlr, Mdic, MDIrop|(pa<<MDIpSHIFT)|(ra<<MDIrSHIFT));	mdic = 0;	for(timo = 64; timo; timo--){		mdic = csr32r(ctlr, Mdic);		if(mdic & (MDIe|MDIready))			break;		microdelay(1);	}	if((mdic & (MDIe|MDIready)) == MDIready)		return mdic & 0xFFFF;	return -1;}static intigbemiimiw(Mii* mii, int pa, int ra, int data){	Ctlr *ctlr;	int mdic, timo;	ctlr = mii->ctlr;	data &= MDIdMASK;	csr32w(ctlr, Mdic, MDIwop|(pa<<MDIpSHIFT)|(ra<<MDIrSHIFT)|data);	mdic = 0;	for(timo = 64; timo; timo--){		mdic = csr32r(ctlr, Mdic);		if(mdic & (MDIe|MDIready))			break;		microdelay(1);	}	if((mdic & (MDIe|MDIready)) == MDIready)		return 0;	return -1;}static intigbemii(Ctlr* ctlr){	MiiPhy *phy;	int ctrl, p, r;	r = csr32r(ctlr, Status);	if(r & Tbimode)		return -1;	if((ctlr->mii = malloc(sizeof(Mii))) == nil)		return -1;	ctlr->mii->ctlr = ctlr;	ctrl = csr32r(ctlr, Ctrl);	ctrl |= Slu;	switch(ctlr->id){	case i82543gc:		ctrl |= Frcdplx|Frcspd;		csr32w(ctlr, Ctrl, ctrl);		/*		 * The reset pin direction (Mdro) should already		 * be set from the EEPROM load.		 * If it's not set this configuration is unexpected		 * so bail.		 */		r = csr32r(ctlr, Ctrlext);		if(!(r & Mdro))			return -1;		csr32w(ctlr, Ctrlext, r);		delay(20);		r = csr32r(ctlr, Ctrlext);		r &= ~Mdr;		csr32w(ctlr, Ctrlext, r);		delay(20);		r = csr32r(ctlr, Ctrlext);		r |= Mdr;		csr32w(ctlr, Ctrlext, r);		delay(20);		ctlr->mii->mir = i82543miimir;		ctlr->mii->miw = i82543miimiw;		break;	case i82544ei:	case i82547ei:	case i82540em:	case i82540eplp:	case i82547gi:	case i82541gi:	case i82541gi2:	case i82541pi:	case i82545gmc:	case i82546gb:	case i82546eb:		ctrl &= ~(Frcdplx|Frcspd);		csr32w(ctlr, Ctrl, ctrl);		ctlr->mii->mir = igbemiimir;		ctlr->mii->miw = igbemiimiw;		break;	default:		free(ctlr->mii);		ctlr->mii = nil;		return -1;	}	if(mii(ctlr->mii, ~0) == 0 || (phy = ctlr->mii->curphy) == nil){		free(ctlr->mii);		ctlr->mii = nil;		return -1;	}	USED(phy);	// print("oui %X phyno %d\n", phy->oui, phy->phyno);	/*	 * 8254X-specific PHY registers not in 802.3:	 *	0x10	PHY specific control	 *	0x14	extended PHY specific control	 * Set appropriate values then reset the PHY to have	 * changes noted.	 */	switch(ctlr->id){	case i82547gi:	case i82541gi:	case i82541gi2:	case i82541pi:	case i82545gmc:	case i82546gb:	case i82546eb:		break;	default:		r = miimir(ctlr->mii, 16);		r |= 0x0800;			/* assert CRS on Tx */		r |= 0x0060;			/* auto-crossover all speeds */		r |= 0x0002;			/* polarity reversal enabled */		miimiw(ctlr->mii, 16, r);		r = miimir(ctlr->mii, 20);		r |= 0x0070;			/* +25MHz clock */

⌨️ 快捷键说明

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