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

📄 etherdp83820.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 3 页
字号:
		if(csr32r(ctlr, Mear) & Mdio)			data |= (1<<i);		csr32w(ctlr, Mear, Mdc|r);		csr32w(ctlr, Mear, r);	}	csr32w(ctlr, Mear, mear);	return data;}static voidmdiow(Ctlr* ctlr, int bits, int n){	int i, mear, r;	mear = csr32r(ctlr, Mear);	r = Mddir|(~Mdc & mear);	for(i = n-1; i >= 0; i--){		if(bits & (1<<i))			r |= Mdio;		else			r &= ~Mdio;		csr32w(ctlr, Mear, r);		csr32w(ctlr, Mear, Mdc|r);	}	csr32w(ctlr, Mear, mear);}static intdp83820miimir(Mii* mii, int pa, int ra){	int data;	Ctlr *ctlr;	ctlr = mii->ctlr;	/*	 * MII Management Interface Read.	 *	 * Preamble;	 * ST+OP+PA+RA;	 * LT + 16 data bits.	 */	mdiow(ctlr, 0xFFFFFFFF, 32);	mdiow(ctlr, 0x1800|(pa<<5)|ra, 14);	data = mdior(ctlr, 18);	if(data & 0x10000)		return -1;	return data & 0xFFFF;}static intdp83820miimiw(Mii* mii, int pa, int ra, int data){	Ctlr *ctlr;	ctlr = mii->ctlr;	/*	 * MII Management Interface Write.	 *	 * Preamble;	 * ST+OP+PA+RA+LT + 16 data bits;	 * Z.	 */	mdiow(ctlr, 0xFFFFFFFF, 32);	data &= 0xFFFF;	data |= (0x05<<(5+5+2+16))|(pa<<(5+2+16))|(ra<<(2+16))|(0x02<<16);	mdiow(ctlr, data, 32);	return data & 0xFFFF;	/* TODO: what's the caller expect here? */}/* * return free Block+buffer ready for input of up to MTU bytes. * desc->bp is also set to the return value. */static Block *dp83820rballoc(Desc* desc){	Block *bp;	if(desc->bp == nil){		ilock(&dp83820rblock);		if((bp = dp83820rbpool) == nil){			iunlock(&dp83820rblock);			desc->bp = nil;			desc->cmdsts = Own;			iprint("dp83820rballoc: out of buffers\n");			return nil;		}		dp83820rbpool = bp->next;		bp->next = nil;		iunlock(&dp83820rblock);		desc->bufptr = PCIWADDR(bp->rp);		desc->bp = bp;	}	else{		bp = desc->bp;		BLKRESET(bp);	}	coherence();	desc->cmdsts = Intr|Rbsz;	return bp;}/* should be called via freeb() */static voiddp83820rbfree(Block *bp){	BLKRESET(bp);	ilock(&dp83820rblock);	bp->next = dp83820rbpool;	dp83820rbpool = bp;	iunlock(&dp83820rblock);}static voiddp83820halt(Ctlr* ctlr){	int i, timeo;	ilock(&ctlr->ilock);	csr32w(ctlr, Imr, 0);	csr32w(ctlr, Ier, 0);	csr32w(ctlr, Cr, Rxd|Txd);	for(timeo = 0; timeo < 1000; timeo++){		if(!(csr32r(ctlr, Cr) & (Rxe|Txe)))			break;		microdelay(1);	}	csr32w(ctlr, Mibc, Frz);	iunlock(&ctlr->ilock);	if(ctlr->rd != nil){		for(i = 0; i < ctlr->nrd; i++){			if(ctlr->rd[i].bp == nil)				continue;			freeb(ctlr->rd[i].bp);			ctlr->rd[i].bp = nil;		}	}	if(ctlr->td != nil){		for(i = 0; i < ctlr->ntd; i++){			if(ctlr->td[i].bp == nil)				continue;			freeb(ctlr->td[i].bp);			ctlr->td[i].bp = nil;		}	}}static voiddp83820cfg(Ctlr* ctlr){	int cfg;	/*	 * Don't know how to deal with a TBI yet.	 */	if(ctlr->mii == nil) {		iprint("83820: got tbi, not phy\n");		return;	}	/*	 * The polarity of these bits is at the mercy	 * of the board designer.	 * The correct answer for all speed and duplex questions	 * should be to query the phy.	 */	cfg = csr32r(ctlr, Cfg);	if(!(cfg & Dupsts)){		ctlr->rxcfg |= Rxfd;		ctlr->txcfg |= Csi|Hbi;		iprint("83820: full duplex, ");	}	else{		ctlr->rxcfg &= ~Rxfd;		ctlr->txcfg &= ~(Csi|Hbi);		iprint("83820: half duplex, ");	}	csr32w(ctlr, Rxcfg, ctlr->rxcfg);	csr32w(ctlr, Txcfg, ctlr->txcfg);	switch(cfg & (Spdsts1000|Spdsts100)){	case Spdsts1000:		/* 100Mbps */	default:			/* 10Mbps */		ctlr->cfg &= ~Mode1000;		if ((cfg & (Spdsts1000|Spdsts100)) == Spdsts1000)			iprint("100Mb/s\n");		else			iprint("10Mb/s\n");		break;	case Spdsts100:			/* 1Gbps */		ctlr->cfg |= Mode1000;		iprint("1Gb/s\n");		break;	}	csr32w(ctlr, Cfg, ctlr->cfg);}static voiddp83820init(Ether* edev){	int i;	Ctlr *ctlr;	Desc *desc;	uchar *alloc;	ctlr = edev->ctlr;	dp83820halt(ctlr);	/*	 * Receiver	 */	alloc = (uchar*)ROUNDUP((ulong)ctlr->alloc, 8);	ctlr->rd = (Desc*)alloc;	alloc += ctlr->nrd*sizeof(Desc);	memset(ctlr->rd, 0, ctlr->nrd*sizeof(Desc));	ctlr->rdx = 0;	for(i = 0; i < ctlr->nrd; i++){		desc = &ctlr->rd[i];		desc->link = PCIWADDR(&ctlr->rd[NEXT(i, ctlr->nrd)]);		if(dp83820rballoc(desc) == nil) {			print("dp83820init: out of buffers\n");			continue;		}	}	csr32w(ctlr, Rxdphi, 0);	csr32w(ctlr, Rxdp, PCIWADDR(ctlr->rd));	for(i = 0; i < Eaddrlen; i += 2){		csr32w(ctlr, Rfcr, i);		csr32w(ctlr, Rfdr, (edev->ea[i+1]<<8)|edev->ea[i]);	}	/* for now, accept all multicast packets */	csr32w(ctlr, Rfcr, Rfen|Aab|Apm|Aam);	ctlr->rxcfg = Stripcrc|(((2*(ETHERMINTU+4))/8)<<RxdrthSHFT);	ctlr->imr |= Rxorn|Rxidle|Rxearly|Rxdesc|Rxok;	/*	 * Transmitter.	 */	ctlr->td = (Desc*)alloc;	memset(ctlr->td, 0, ctlr->ntd*sizeof(Desc));	ctlr->tdh = ctlr->tdt = ctlr->ntq = 0;	for(i = 0; i < ctlr->ntd; i++){		desc = &ctlr->td[i];		desc->link = PCIWADDR(&ctlr->td[NEXT(i, ctlr->ntd)]);	}	csr32w(ctlr, Txdphi, 0);	csr32w(ctlr, Txdp, PCIWADDR(ctlr->td));	ctlr->txcfg = Atp|(((2*(ETHERMINTU+4))/32)<<FlthSHFT)|((4096/32)<<TxdrthSHFT);	ctlr->imr |= Txurn|Txidle|Txdesc|Txok;	ilock(&ctlr->ilock);	dp83820cfg(ctlr);	csr32w(ctlr, Mibc, Aclr);	ctlr->imr |= Mib;	csr32w(ctlr, Imr, ctlr->imr);	/* try coalescing adjacent interrupts; use hold-off interval of 100µs */	csr32w(ctlr, Ihr, Ihctl|(1<<IhSHFT));	csr32w(ctlr, Ier, Ien);	csr32w(ctlr, Cr, Rxe|Txe);	iunlock(&ctlr->ilock);}/* multicast already on, don't need to do anything */static voidmulticast(void*, uchar*, int){}static voiddp83820attach(Ether* edev){	Block *bp;	Ctlr *ctlr;	ctlr = edev->ctlr;	qlock(&ctlr->alock);	if(ctlr->alloc != nil){		qunlock(&ctlr->alock);		return;	}	if(waserror()){err:		if(ctlr->mii != nil){			free(ctlr->mii);			ctlr->mii = nil;		}		if(ctlr->alloc != nil){			free(ctlr->alloc);			ctlr->alloc = nil;		}		qunlock(&ctlr->alock);		nexterror();	}	if(!(ctlr->cfg & Tbien)){		if((ctlr->mii = malloc(sizeof(Mii))) == nil)			error(Enomem);		ctlr->mii->ctlr = ctlr;		ctlr->mii->mir = dp83820miimir;		ctlr->mii->miw = dp83820miimiw;		if(mii(ctlr->mii, ~0) == 0)			error("no PHY");		ctlr->cfg |= Dupstsien|Lnkstsien|Spdstsien;		ctlr->imr |= Phy;	}	/* allocate all Descs */	ctlr->nrd = Nrd;	ctlr->nrb = Nrb;	ctlr->ntd = Ntd;	ctlr->alloc = mallocz((ctlr->nrd+ctlr->ntd)*sizeof(Desc) + 7, 0);	if(ctlr->alloc == nil)		error(Enomem);	/*	 * allocate receive Blocks+buffers, add all to receive Block+buffer pool	 */	for(ctlr->nrb = 0; ctlr->nrb < Nrb; ctlr->nrb++){		if((bp = iallocb(Rbsz)) == nil) {			print(		"dp83820attach: iallocb failed with %d rcv bufs allocated\n",				ctlr->nrb);			error(Enomem);		}#ifdef FS		bp->flags |= Mbrcvbuf;#endif		bp->free = dp83820rbfree;	/* to be called via freeb() */		dp83820rbfree(bp);	}	/* attaches a receive Block+buffer to each receive Desc */	dp83820init(edev);	qunlock(&ctlr->alock);	poperror();}static voiddp83820transmit(Ether* edev){	Block *bp;	Ctlr *ctlr;	Desc *desc;	int cmdsts, r, x;	ctlr = edev->ctlr;	ilock(&ctlr->tlock);	bp = nil;	for(x = ctlr->tdh; ctlr->ntq; x = NEXT(x, ctlr->ntd)){		desc = &ctlr->td[x];		if((cmdsts = desc->cmdsts) & Own)			break;		if(!(cmdsts & Ok)){			if(cmdsts & Ec)				ctlr->ec++;			if(cmdsts & Owc)				ctlr->owc++;			if(cmdsts & Ed)				ctlr->ed++;			if(cmdsts & Crs)				ctlr->crs++;			if(cmdsts & Tfu)				ctlr->tfu++;			if(cmdsts & Txa)				ctlr->txa++;#ifndef FS			edev->oerrs++;#endif		}		desc->bp->next = bp;	/* chain transmitted Blocks together */		bp = desc->bp;		desc->bp = nil;		/* unlink them from Descs */		ctlr->ntq--;	}	/* free Blocks+buffers comprising the packets just sent */	ctlr->tdh = x;	if(bp != nil)		freeblist(bp);	x = ctlr->tdt;	while(ctlr->ntq < (ctlr->ntd-1)){		bp = etheroq(edev);	/* get head of transmit q */		if(bp == nil)			break;		desc = &ctlr->td[x];		desc->bufptr = PCIWADDR(bp->rp);		desc->bp = bp;		/* attach to Desc */		ctlr->ntq++;		coherence();		desc->cmdsts = Own|Intr|BLEN(bp);	/* fire! */		x = NEXT(x, ctlr->ntd);	}	if (ctlr->ntq >= ctlr->ntd-1)		iprint("83820: xmit q full, Ntd=%d\n", Ntd);	if(x != ctlr->tdt){		ctlr->tdt = x;		r = csr32r(ctlr, Cr);		csr32w(ctlr, Cr, Txe|r);	}	iunlock(&ctlr->tlock);}static voiddp83820interrupt(Ureg*, void* arg){	Block *bp;	Ctlr *ctlr;	Desc *desc;	Ether *edev;	int cmdsts, i, isr, r, x, rcvd = 0;	edev = arg;	ctlr = edev->ctlr;

⌨️ 快捷键说明

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