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

📄 etherdp83820.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
			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)			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]);	}	csr32w(ctlr, Rfcr, Rfen|Aab|Aam|Apm);	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);}static voiddp83820attach(Ether* edev){	Block *bp;	Ctlr *ctlr;	ctlr = edev->ctlr;	qlock(&ctlr->alock);	if(ctlr->alloc != nil){		qunlock(&ctlr->alock);		return;	}	if(waserror()){		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;	}	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);	for(ctlr->nrb = 0; ctlr->nrb < Nrb; ctlr->nrb++){		if((bp = allocb(Rbsz)) == nil)			break;		bp->free = dp83820rbfree;		dp83820rbfree(bp);	}	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++;			edev->oerrs++;		}		desc->bp->next = bp;		bp = desc->bp;		desc->bp = nil;		ctlr->ntq--;	}	ctlr->tdh = x;	if(bp != nil)		freeblist(bp);	x = ctlr->tdt;	while(ctlr->ntq < (ctlr->ntd-1)){		if((bp = qget(edev->oq)) == nil)			break;		desc = &ctlr->td[x];		desc->bufptr = PCIWADDR(bp->rp);		desc->bp = bp;		ctlr->ntq++;		coherence();		desc->cmdsts = Own|Intr|BLEN(bp);		x = NEXT(x, ctlr->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;	edev = arg;	ctlr = edev->ctlr;	for(isr = csr32r(ctlr, Isr); isr & ctlr->imr; isr = csr32r(ctlr, Isr)){		if(isr & (Rxorn|Rxidle|Rxearly|Rxerr|Rxdesc|Rxok)){			x = ctlr->rdx;			desc = &ctlr->rd[x];			while((cmdsts = desc->cmdsts) & Own){				if((cmdsts & Ok) && desc->bp != nil){					bp = desc->bp;					desc->bp = nil;					bp->wp += cmdsts & SizeMASK;					etheriq(edev, bp, 1);				}				//else if(!(cmdsts & Ok)){				//	iprint("dp83820: rx %8.8uX:", cmdsts);				//	bp = desc->bp;				//	for(i = 0; i < 20; i++)				//		iprint(" %2.2uX", bp->rp[i]);				//	iprint("\n");				//}				dp83820rballoc(desc);				x = NEXT(x, ctlr->nrd);				desc = &ctlr->rd[x];			}			ctlr->rdx = x;			if(isr & Rxidle){				r = csr32r(ctlr, Cr);				csr32w(ctlr, Cr, Rxe|r);				ctlr->rxidle++;			}			isr &= ~(Rxorn|Rxidle|Rxearly|Rxerr|Rxdesc|Rxok);		}		if(isr & Txurn){			x = (ctlr->txcfg & TxdrthMASK)>>TxdrthSHFT;			r = (ctlr->txcfg & FlthMASK)>>FlthSHFT;			if(x < ((TxdrthMASK)>>TxdrthSHFT)			&& x < (2048/32 - r)){				ctlr->txcfg &= ~TxdrthMASK;				x++;				ctlr->txcfg |= x<<TxdrthSHFT;				csr32w(ctlr, Txcfg, ctlr->txcfg);			}		}		if(isr & (Txurn|Txidle|Txdesc|Txok)){			dp83820transmit(edev);			isr &= ~(Txurn|Txidle|Txdesc|Txok);		}		if(isr & Mib){			for(i = 0; i < Nmibd; i++){				r = csr32r(ctlr, Mibd+(i*sizeof(int)));				ctlr->mibd[i] += r & 0xFFFF;			}			isr &= ~Mib;		}		if((isr & Phy) && ctlr->mii != nil){			ctlr->mii->mir(ctlr->mii, 1, Bmsr);			print("phy: cfg %8.8uX bmsr %4.4uX\n",				csr32r(ctlr, Cfg),				ctlr->mii->mir(ctlr->mii, 1, Bmsr));			dp83820cfg(ctlr);			isr &= ~Phy;		}		if(isr)			iprint("dp83820: isr %8.8uX\n", isr);	}}static longdp83820ifstat(Ether* edev, void* a, long n, ulong offset){	char *p;	Ctlr *ctlr;	int i, l, r;	ctlr = edev->ctlr;	edev->crcs = ctlr->mibd[Mibd+(1*sizeof(int))];	edev->frames = ctlr->mibd[Mibd+(3*sizeof(int))];	edev->buffs = ctlr->mibd[Mibd+(5*sizeof(int))];	edev->overflows = ctlr->mibd[Mibd+(2*sizeof(int))];	if(n == 0)		return 0;	p = malloc(READSTR);	l = 0;	for(i = 0; i < Nmibd; i++){		r = csr32r(ctlr, Mibd+(i*sizeof(int)));		ctlr->mibd[i] += r & 0xFFFF;		if(ctlr->mibd[i] != 0 && dp83820mibs[i] != nil)			l += snprint(p+l, READSTR-l, "%s: %ud %ud\n",				dp83820mibs[i], ctlr->mibd[i], r);	}	l += snprint(p+l, READSTR-l, "rxidle %d\n", ctlr->rxidle);	l += snprint(p+l, READSTR-l, "ec %d\n", ctlr->ec);	l += snprint(p+l, READSTR-l, "owc %d\n", ctlr->owc);	l += snprint(p+l, READSTR-l, "ed %d\n", ctlr->ed);	l += snprint(p+l, READSTR-l, "crs %d\n", ctlr->crs);	l += snprint(p+l, READSTR-l, "tfu %d\n", ctlr->tfu);	l += snprint(p+l, READSTR-l, "txa %d\n", ctlr->txa);	l += snprint(p+l, READSTR, "rom:");	for(i = 0; i < 0x10; i++){		if(i && ((i & 0x07) == 0))			l += snprint(p+l, READSTR-l, "\n    ");		l += snprint(p+l, READSTR-l, " %4.4uX", ctlr->eeprom[i]);	}	l += snprint(p+l, READSTR-l, "\n");	if(ctlr->mii != nil && ctlr->mii->curphy != nil){		l += snprint(p+l, READSTR, "phy:");		for(i = 0; i < NMiiPhyr; i++){			if(i && ((i & 0x07) == 0))				l += snprint(p+l, READSTR-l, "\n    ");			r = miimir(ctlr->mii, i);			l += snprint(p+l, READSTR-l, " %4.4uX", r);		}		snprint(p+l, READSTR-l, "\n");	}	n = readstr(offset, a, n, p);	free(p);	return n;}static voiddp83820promiscuous(void* arg, int on){	USED(arg, on);}/* multicast already on, don't need to do anything */static voiddp83820multicast(void*, uchar*, int){}static intatc93c46r(Ctlr* ctlr, int address){	int data, i, mear, r, size;	/*	 * Analog Technology, Inc. ATC93C46	 * or equivalent serial EEPROM.	 */	mear = csr32r(ctlr, Mear);	mear &= ~(Eesel|Eeclk|Eedo|Eedi);	r = Eesel|mear;reread:	csr32w(ctlr, Mear, r);	data = 0x06;	for(i = 3-1; i >= 0; i--){		if(data & (1<<i))			r |= Eedi;		else			r &= ~Eedi;		csr32w(ctlr, Mear, r);		csr32w(ctlr, Mear, Eeclk|r);		microdelay(1);		csr32w(ctlr, Mear, r);		microdelay(1);	}	/*	 * First time through must work out the EEPROM size.	 */	if((size = ctlr->eepromsz) == 0)		size = 8;	for(size = size-1; size >= 0; size--){		if(address & (1<<size))			r |= Eedi;		else			r &= ~Eedi;		csr32w(ctlr, Mear, r);		microdelay(1);		csr32w(ctlr, Mear, Eeclk|r);		microdelay(1);		csr32w(ctlr, Mear, r);		microdelay(1);		if(!(csr32r(ctlr, Mear) & Eedo))			break;	}	r &= ~Eedi;	data = 0;	for(i = 16-1; i >= 0; i--){		csr32w(ctlr, Mear, Eeclk|r);		microdelay(1);		if(csr32r(ctlr, Mear) & Eedo)			data |= (1<<i);		csr32w(ctlr, Mear, r);		microdelay(1);	}	csr32w(ctlr, Mear, mear);	if(ctlr->eepromsz == 0){		ctlr->eepromsz = 8-size;		ctlr->eeprom = malloc((1<<ctlr->eepromsz)*sizeof(ushort));		goto reread;	}	return data;}static intdp83820reset(Ctlr* ctlr){	int i, r;	unsigned char sum;	/*	 * Soft reset the controller;	 * read the EEPROM to get the initial settings	 * of the Cfg and Gpior bits which should be cleared by	 * the reset.	 */	csr32w(ctlr, Cr, Rst);	delay(1);	while(csr32r(ctlr, Cr) & Rst)		delay(1);	atc93c46r(ctlr, 0);	if(ctlr->eeprom == nil)		return -1;	sum = 0;	for(i = 0; i < 0x0E; i++){		r = atc93c46r(ctlr, i);		ctlr->eeprom[i] = r;		sum += r;		sum += r>>8;	}	if(sum != 0){		print("dp83820reset: bad EEPROM checksum\n");		return -1;	}#ifdef notdef	csr32w(ctlr, Gpior, ctlr->eeprom[4]);	cfg = Extstsen|Exd;	r = csr32r(ctlr, Cfg);	if(ctlr->eeprom[5] & 0x0001)		cfg |= Ext125;	if(ctlr->eeprom[5] & 0x0002)		cfg |= M64addren;	if((ctlr->eeprom[5] & 0x0004) && (r & Pci64det))		cfg |= Data64en;	if(ctlr->eeprom[5] & 0x0008)		cfg |= T64addren;	if(!(pcicfgr16(ctlr->pcidev, PciPCR) & 0x10))		cfg |= Mwidis;	if(ctlr->eeprom[5] & 0x0020)		cfg |= Mrmdis;	if(ctlr->eeprom[5] & 0x0080)		cfg |= Mode1000;	if(ctlr->eeprom[5] & 0x0200)		cfg |= Tbien|Mode1000;	/*	 * What about RO bits we might have destroyed with Rst?	 * What about Exd, Tmrtest, Extstsen, Pintctl?	 * Why does it think it has detected a 64-bit bus when	 * it hasn't?	 */#else	//r = csr32r(ctlr, Cfg);	//r &= ~(Mode1000|T64addren|Data64en|M64addren);	//csr32w(ctlr, Cfg, r);	//csr32w(ctlr, Cfg, 0x2000);#endif /* notdef */	ctlr->cfg = csr32r(ctlr, Cfg);print("cfg %8.8uX pcicfg %8.8uX\n", ctlr->cfg, pcicfgr32(ctlr->pcidev, PciPCR));	ctlr->cfg &= ~(T64addren|Data64en|M64addren);	csr32w(ctlr, Cfg, ctlr->cfg);	csr32w(ctlr, Mibc, Aclr|Frz);	return 0;}static voiddp83820pci(void){	void *mem;	Pcidev *p;	Ctlr *ctlr;	p = nil;	while(p = pcimatch(p, 0, 0)){		if(p->ccrb != 0x02 || p->ccru != 0)			continue;		switch((p->did<<16)|p->vid){		default:			continue;		case (0x0022<<16)|0x100B:	/* DP83820 (Gig-NIC) */			break;		}		mem = vmap(p->mem[1].bar & ~0x0F, p->mem[1].size);		if(mem == 0){			print("DP83820: can't map %8.8luX\n", p->mem[1].bar);			continue;		}		ctlr = malloc(sizeof(Ctlr));		ctlr->port = p->mem[1].bar & ~0x0F;		ctlr->pcidev = p;		ctlr->id = (p->did<<16)|p->vid;		ctlr->nic = mem;		if(dp83820reset(ctlr)){			free(ctlr);			continue;		}		pcisetbme(p);		if(dp83820ctlrhead != nil)			dp83820ctlrtail->next = ctlr;		else			dp83820ctlrhead = ctlr;		dp83820ctlrtail = ctlr;	}}static intdp83820pnp(Ether* edev){	int i;	Ctlr *ctlr;	uchar ea[Eaddrlen];	if(dp83820ctlrhead == nil)		dp83820pci();	/*	 * Any adapter matches if no edev->port is supplied,	 * otherwise the ports must match.	 */	for(ctlr = dp83820ctlrhead; ctlr != nil; ctlr = ctlr->next){		if(ctlr->active)			continue;		if(edev->port == 0 || edev->port == ctlr->port){			ctlr->active = 1;			break;		}	}	if(ctlr == nil)		return -1;	edev->ctlr = ctlr;	edev->port = ctlr->port;	edev->irq = ctlr->pcidev->intl;	edev->tbdf = ctlr->pcidev->tbdf;	edev->mbps = 1000;	/*	 * Check if the adapter's station address is to be overridden.	 * If not, read it from the EEPROM and set in ether->ea prior to	 * loading the station address in the hardware.	 */	memset(ea, 0, Eaddrlen);	if(memcmp(ea, edev->ea, Eaddrlen) == 0){		for(i = 0; i < Eaddrlen/2; i++){			edev->ea[2*i] = ctlr->eeprom[0x0C-i];			edev->ea[2*i+1] = ctlr->eeprom[0x0C-i]>>8;		}	}	edev->attach = dp83820attach;	edev->transmit = dp83820transmit;	edev->interrupt = dp83820interrupt;	edev->ifstat = dp83820ifstat;	edev->arg = edev;	edev->promiscuous = dp83820promiscuous;	edev->multicast = dp83820multicast;//	edev->shutdown = dp83820shutdown;	return 0;}voidetherdp83820link(void){	addethercard("DP83820", dp83820pnp);}

⌨️ 快捷键说明

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