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

📄 ethervt6102.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
		ds = (Ds*)alloc;		alloc += ctlr->cls;		ds->control = Rdbsz;		ds->branch = PCIWADDR(alloc);		ds->bp = iallocb(Rdbsz+3);		if(ds->bp == nil)			error("vt6102: can't allocate receive ring\n");		ds->bp->rp = (uchar*)ROUNDUP((ulong)ds->bp->rp, 4);		ds->addr = PCIWADDR(ds->bp->rp);		ds->next = (Ds*)alloc;		ds->prev = prev;		prev = ds;		ds->status = Own;	}	prev->branch = 0;	prev->next = ctlr->rd;	prev->status = 0;	ctlr->rdh = ctlr->rd;	ctlr->td = (Ds*)alloc;	prev = ctlr->td + ctlr->ntd-1;	bounce = alloc + ctlr->ntd*ctlr->cls;	for(i = 0; i < ctlr->ntd; i++){		ds = (Ds*)alloc;		alloc += ctlr->cls;		ds->bounce = bounce;		bounce += Txcopy;		ds->next = (Ds*)alloc;		ds->prev = prev;		prev = ds;	}	prev->next = ctlr->td;	ctlr->tdh = ctlr->tdt = ctlr->td;	ctlr->tdused = 0;	ctlr->cr = Dpoll|Rdmd|Txon|Rxon|Strt;	/*Srci|Abti|Norbf|Pktrace|Ovfi|Udfi|Be|Ru|Tu|Txe|Rxe|Ptx|Prx*/	ctlr->imr = Abti|Norbf|Pktrace|Ovfi|Udfi|Be|Ru|Tu|Txe|Rxe|Ptx|Prx;	ilock(&ctlr->clock);	csr32w(ctlr, Rxdaddr, PCIWADDR(ctlr->rd));	csr32w(ctlr, Txdaddr, PCIWADDR(ctlr->td));	csr16w(ctlr, Isr, ~0);	csr16w(ctlr, Imr, ctlr->imr);	csr16w(ctlr, Cr, ctlr->cr);	iunlock(&ctlr->clock);	snprint(name, KNAMELEN, "#l%dlproc", edev->ctlrno);	kproc(name, vt6102lproc, edev);	qunlock(&ctlr->alock);	poperror();}static voidvt6102transmit(Ether* edev){	Block *bp;	Ctlr *ctlr;	Ds *ds, *next;	int control, i, o, prefix, size, tdused, timeo;	ctlr = edev->ctlr;	ilock(&ctlr->tlock);	/*	 * Free any completed packets	 */	ds = ctlr->tdh;	for(tdused = ctlr->tdused; tdused > 0; tdused--){		/*		 * For some errors the chip will turn the Tx engine		 * off. Wait for that to happen.		 * Could reset and re-init the chip here if it doesn't		 * play fair.		 * To do: adjust Tx FIFO threshold on underflow.		 */		if(ds->status & (Abt|Tbuff|Udf)){			for(timeo = 0; timeo < 1000; timeo++){				if(!(csr16r(ctlr, Cr) & Txon))					break;				microdelay(1);			}			ds->status = Own;			csr32w(ctlr, Txdaddr, PCIWADDR(ds));		}		if(ds->status & Own)			break;		ds->addr = 0;		ds->branch = 0;		if(ds->bp != nil){			freeb(ds->bp);			ds->bp = nil;		}		for(i = 0; i < Ntxstats-1; i++){			if(ds->status & (1<<i))				ctlr->txstats[i]++;		}		ctlr->txstats[i] += (ds->status & NcrMASK)>>NcrSHIFT;		ds = ds->next;	}	ctlr->tdh = ds;	/*	 * Try to fill the ring back up.	 */	ds = ctlr->tdt;	while(tdused < ctlr->ntd-2){		if((bp = qget(edev->oq)) == nil)			break;		tdused++;		size = BLEN(bp);		prefix = 0;		if(o = (((int)bp->rp) & 0x03)){			prefix = Txcopy-o;			if(prefix > size)				prefix = size;			memmove(ds->bounce, bp->rp, prefix);			ds->addr = PCIWADDR(ds->bounce);			bp->rp += prefix;			size -= prefix;		}		next = ds->next;		ds->branch = PCIWADDR(ds->next);		if(size){			if(prefix){				next->bp = bp;				next->addr = PCIWADDR(bp->rp);				next->branch = PCIWADDR(next->next);				next->control = Edp|Chain|((size<<TbsSHIFT) & TbsMASK);				control = Stp|Chain|((prefix<<TbsSHIFT) & TbsMASK);				next = next->next;				tdused++;				ctlr->tsplit++;			}			else{				ds->bp = bp;				ds->addr = PCIWADDR(bp->rp);				control = Edp|Stp|((size<<TbsSHIFT) & TbsMASK);				ctlr->taligned++;			}		}		else{			freeb(bp);			control = Edp|Stp|((prefix<<TbsSHIFT) & TbsMASK);			ctlr->tcopied++;		}		ds->control = control;		if(tdused >= ctlr->ntd-2){			ds->control |= Ic;			ctlr->txdw++;		}		coherence();		ds->status = Own;		ds = next;	}	ctlr->tdt = ds;	ctlr->tdused = tdused;	if(ctlr->tdused)		csr16w(ctlr, Cr, Tdmd|ctlr->cr);	iunlock(&ctlr->tlock);}static voidvt6102receive(Ether* edev){	Ds *ds;	Block *bp;	Ctlr *ctlr;	int i, len;	ctlr = edev->ctlr;	ds = ctlr->rdh;	while(!(ds->status & Own) && ds->status != 0){		if(ds->status & Rerr){			for(i = 0; i < Nrxstats; i++){				if(ds->status & (1<<i))					ctlr->rxstats[i]++;			}		}		else if(bp = iallocb(Rdbsz+3)){			len = ((ds->status & LengthMASK)>>LengthSHIFT)-4;			ds->bp->wp = ds->bp->rp+len;			etheriq(edev, ds->bp, 1);			bp->rp = (uchar*)ROUNDUP((ulong)bp->rp, 4);			ds->addr = PCIWADDR(bp->rp);			ds->bp = bp;		}		ds->control = Rdbsz;		ds->branch = 0;		ds->status = 0;		ds->prev->branch = PCIWADDR(ds);		coherence();		ds->prev->status = Own;		ds = ds->next;	}	ctlr->rdh = ds;	csr16w(ctlr, Cr, ctlr->cr);}static voidvt6102interrupt(Ureg*, void* arg){	Ctlr *ctlr;	Ether *edev;	int imr, isr, r, timeo;	edev = arg;	ctlr = edev->ctlr;	ilock(&ctlr->clock);	csr16w(ctlr, Imr, 0);	imr = ctlr->imr;	ctlr->intr++;	for(;;){		if((isr = csr16r(ctlr, Isr)) != 0)			csr16w(ctlr, Isr, isr);		if((isr & ctlr->imr) == 0)			break;					if(isr & Srci){			imr &= ~Srci;			ctlr->lwakeup = isr & Srci;			wakeup(&ctlr->lrendez);			isr &= ~Srci;			ctlr->lintr++;		}		if(isr & (Norbf|Pktrace|Ovfi|Ru|Rxe|Prx)){			vt6102receive(edev);			isr &= ~(Norbf|Pktrace|Ovfi|Ru|Rxe|Prx);			ctlr->rintr++;		}		if(isr & (Abti|Udfi|Tu|Txe|Ptx)){			if(isr & (Abti|Udfi|Tu)){				for(timeo = 0; timeo < 1000; timeo++){					if(!(csr16r(ctlr, Cr) & Txon))						break;					microdelay(1);				}				if((isr & Udfi) && ctlr->tft < CtftSAF){					ctlr->tft += 1<<CtftSHIFT;					r = csr8r(ctlr, Bcr1) & ~CtftMASK;					csr8w(ctlr, Bcr1, r|ctlr->tft);				}			}			vt6102transmit(edev);			isr &= ~(Abti|Udfi|Tu|Txe|Ptx);			ctlr->tintr++;		}		if(isr)			panic("vt6102: isr %4.4uX\n", isr);	}	ctlr->imr = imr;	csr16w(ctlr, Imr, ctlr->imr);	iunlock(&ctlr->clock);}static intvt6102miimicmd(Mii* mii, int pa, int ra, int cmd, int data){	Ctlr *ctlr;	int r, timeo;	ctlr = mii->ctlr;	csr8w(ctlr, Miicr, 0);	r = csr8r(ctlr, Phyadr);	csr8w(ctlr, Phyadr, (r & ~PhyadMASK)|pa);	csr8w(ctlr, Phyadr, pa);	csr8w(ctlr, Miiadr, ra);	if(cmd == Wcmd)		csr16w(ctlr, Miidata, data);	csr8w(ctlr, Miicr, cmd);	for(timeo = 0; timeo < 10000; timeo++){		if(!(csr8r(ctlr, Miicr) & cmd))			break;		microdelay(1);	}	if(timeo >= 10000)		return -1;	if(cmd == Wcmd)		return 0;	return csr16r(ctlr, Miidata);}static intvt6102miimir(Mii* mii, int pa, int ra){	return vt6102miimicmd(mii, pa, ra, Rcmd, 0);}static intvt6102miimiw(Mii* mii, int pa, int ra, int data){	return vt6102miimicmd(mii, pa, ra, Wcmd, data);}static intvt6102detach(Ctlr* ctlr){	int timeo;	/*	 * Soft reset the controller.	 */	csr16w(ctlr, Cr, Sfrst);	for(timeo = 0; timeo < 10000; timeo++){		if(!(csr16r(ctlr, Cr) & Sfrst))			break;		microdelay(1);	}	if(timeo >= 1000)		return -1;	return 0;}static intvt6102reset(Ctlr* ctlr){	MiiPhy *phy;	int i, r, timeo;	if(vt6102detach(ctlr) < 0)		return -1;	/*	 * Load the MAC address into the PAR[01]	 * registers.	 */	r = csr8r(ctlr, Eecsr);	csr8w(ctlr, Eecsr, Autold|r);	for(timeo = 0; timeo < 100; timeo++){		if(!(csr8r(ctlr, Cr) & Autold))			break;		microdelay(1);	}	if(timeo >= 100)		return -1;	for(i = 0; i < Eaddrlen; i++)		ctlr->par[i] = csr8r(ctlr, Par0+i);	/*	 * Configure DMA and Rx/Tx thresholds.	 * If the Rx/Tx threshold bits in Bcr[01] are 0 then	 * the thresholds are determined by Rcr/Tcr.	 */	r = csr8r(ctlr, Bcr0) & ~(CrftMASK|DmaMASK);	csr8w(ctlr, Bcr0, r|Crft64|Dma64);	r = csr8r(ctlr, Bcr1) & ~CtftMASK;	csr8w(ctlr, Bcr1, r|ctlr->tft);	r = csr8r(ctlr, Rcr) & ~(RrftMASK|Prom|Ar|Sep);	csr8w(ctlr, Rcr, r|Ab|Am);	r = csr8r(ctlr, Tcr) & ~(RtsfMASK|Ofset|Lb1|Lb0);	csr8w(ctlr, Tcr, r);	/*	 * Link management.	 */	if((ctlr->mii = malloc(sizeof(Mii))) == nil)		return -1;	ctlr->mii->mir = vt6102miimir;	ctlr->mii->miw = vt6102miimiw;	ctlr->mii->ctlr = ctlr;	if(mii(ctlr->mii, ~0) == 0 || (phy = ctlr->mii->curphy) == nil){		free(ctlr->mii);		ctlr->mii = nil;		return -1;	}	// print("oui %X phyno %d\n", phy->oui, phy->phyno);	USED(phy);	//miiane(ctlr->mii, ~0, ~0, ~0);	return 0;}static voidvt6102pci(void){	Pcidev *p;	Ctlr *ctlr;	int cls, port;	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 (0x3065<<16)|0x1106:	/* Rhine II */		case (0x3106<<16)|0x1106:	/* Rhine III */			break;		}		port = p->mem[0].bar & ~0x01;		if(ioalloc(port, p->mem[0].size, 0, "vt6102") < 0){			print("vt6102: port 0x%uX in use\n", port);			continue;		}		ctlr = malloc(sizeof(Ctlr));		ctlr->port = port;		ctlr->pcidev = p;		ctlr->id = (p->did<<16)|p->vid;		if((cls = pcicfgr8(p, PciCLS)) == 0 || cls == 0xFF)			cls = 0x10;		ctlr->cls = cls*4;		if(ctlr->cls < sizeof(Ds)){			print("vt6102: cls %d < sizeof(Ds)\n", ctlr->cls);			free(ctlr);			continue;		}		ctlr->tft = Ctft64;		if(vt6102reset(ctlr)){			free(ctlr);			continue;		}		pcisetbme(p);		if(vt6102ctlrhead != nil)			vt6102ctlrtail->next = ctlr;		else			vt6102ctlrhead = ctlr;		vt6102ctlrtail = ctlr;	}}static intvt6102pnp(Ether* edev){	Ctlr *ctlr;	if(vt6102ctlrhead == nil)		vt6102pci();	/*	 * Any adapter matches if no edev->port is supplied,	 * otherwise the ports must match.	 */	for(ctlr = vt6102ctlrhead; 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 = 100;	memmove(edev->ea, ctlr->par, Eaddrlen);	/*	 * Linkage to the generic ethernet driver.	 */	edev->attach = vt6102attach;	edev->transmit = vt6102transmit;	edev->interrupt = vt6102interrupt;	edev->ifstat = vt6102ifstat;	edev->ctl = nil;	edev->arg = edev;	edev->promiscuous = vt6102promiscuous;	edev->multicast = vt6102multicast;	return 0;}voidethervt6102link(void){	addethercard("vt6102", vt6102pnp);	addethercard("rhine", vt6102pnp);}

⌨️ 快捷键说明

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