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

📄 ethervgbe.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
		freeb(block);		if(ctlr->debugflags & DumpTx)			print("vgbe: Block[%03d]:%#p has been freed\n", i, block);	}	ctlr->tx_count -= count;	if(ctlr->debugflags & DumpTx)		print("vgbe: tx_eof: done [count=%d]\n", count);	iunlock(&ctlr->tx_lock);	if(ctlr->tx_count)		wiob(ctlr, TxCsrS, TxCsr_Wakeup);}static voidvgbeinterrupt(Ureg *, void* arg){	Ether* edev;	Ctlr* ctlr;	ulong status;	edev = (Ether *) arg;	if(edev == nil)		return;	ctlr = edev->ctlr;	if(ctlr == nil)		return;	/* Mask interrupts. */	wiol(ctlr, Imr, 0);	status = riol(ctlr, Isr);	if(status == 0xffff)		goto end;	/* acknowledge */	if(status)		wiol(ctlr, Isr, status);	if((status & Isr_Mask) == 0)		goto end;	ctlr->stats.intr++;	if(ctlr->debugflags & DumpIntr)		if(ctlr->debugcount){			print("vgbe: irq: status = %#08ulx\n", status);			vgbedumpisr(status);			ctlr->debugcount--;		}	if(status & Isr_RxComplete)		vgberxeof(edev);	if(status & Isr_TxComplete0)		vgbetxeof(edev);	if(status & Isr_Stopped)		print("vgbe: irq: software shutdown complete\n");	if(status & Isr_RxFifoOvflow)		print("vgbe: irq: RX FIFO overflow\n");	if(status & Isr_PhyIntr)		print("vgbe: irq: PHY interrupt\n");	if(status & Isr_LinkStatus)		print("vgbe: irq: link status change\n");	if(status & Isr_RxNoDesc)		print("vgbe: irq: ran out of Rx descriptors\n");	if(status & Isr_RxDmaStall){		print("vgbe: irq: Rx DMA stall\n");		wiol(ctlr, Cr3C, Cr3_IntMask);		return;	}	if(status & Isr_TxDmaStall){		print("vgbe: irq: Tx DMA stall\n");		wiol(ctlr, Cr3C, Cr3_IntMask);		return;	}end:	/* Unmask interrupts. */	wiol(ctlr, Imr, ~0);}static voidvgbetransmit(Ether* edev){	Block* block;	Ctlr* ctlr;	int i, index, start, count;	TxDesc* desc;	ulong status, length;	ctlr = edev->ctlr;	ilock(&ctlr->tx_lock);	start = riow(ctlr, TxDscIdx);	if(ctlr->debugflags & DumpTx)		print("vgbe: transmit (start=%d)\n", start);	/* find empty slot */	for(count = 0, i = 0; i < TxCount; i++){		index = (i + start) % TxCount;		if(ctlr->tx_blocks[index])			continue;		desc = &ctlr->tx_ring[index];		status = le32toh(desc->status);		if(status & TxDesc_Status_Own)			continue;		block = qget(edev->oq);		if(block == nil)			break;		count++;		length = BLEN(block);		if(ctlr->debugflags & DumpTx)			print("vgbe: Tx-Desc[%03d] Block:%#p, addr=%#08ulx, len:%ld\n", index, block,				PCIWADDR(block->rp), length);		ctlr->tx_blocks[index] = block;		/* Initialize Tx descriptor. */		desc->status = htole32((length<<16)|TxDesc_Status_Own);		desc->control = htole32(TxDesc_Control_Intr|TxDesc_Control_Normal|((1+1)<<28));		desc->frags[0].addr_lo = htole32((ulong) PCIWADDR(block->rp));		desc->frags[0].addr_hi = htole16(0);		desc->frags[0].length = htole16(length);	}	ctlr->tx_count += count;	if(ctlr->debugflags & DumpTx)		print("vgbe: transmit: done [count=%d]\n", count);	iunlock(&ctlr->tx_lock);	if(ctlr->tx_count)		wiob(ctlr, TxCsrS, TxCsr_Wakeup);	if(count == 0)		print("vgbe: transmit: no Tx entry available\n");}static voidvgbeattach(Ether* edev){	Ctlr* ctlr;	RxDesc* rxdesc;	TxDesc* txdesc;	int i;	ctlr = edev->ctlr;	lock(&ctlr->init_lock);	if(ctlr->inited){		unlock(&ctlr->init_lock);		return;	}//	print("vgbe: attach\n");	/* Allocate Rx ring.  (TODO: Alignment ?) */	rxdesc = mallocalign(RxCount* sizeof(RxDesc), 256, 0, 0);	if(rxdesc == nil){		print("vgbe: unable to alloc Rx ring\n");		unlock(&ctlr->init_lock);		return;	}	ctlr->rx_ring = rxdesc;	/* Allocate Rx blocks, initialize Rx ring. */	for(i = 0; i < RxCount; i++)		vgbenewrx(ctlr, i);	/* Init Rx MAC. */	wiob(ctlr, RxControl,		RxControl_MultiCast|RxControl_BroadCast|RxControl_UniCast);	wiob(ctlr, RxConfig, RxConfig_VlanOpt0);	/* Load Rx ring. */	wiol(ctlr, RxDescLo, (ulong) PCIWADDR(rxdesc));	wiow(ctlr, RxNum, RxCount - 1);	wiow(ctlr, RxDscIdx, 0);	wiow(ctlr, RxResCnt, RxCount);	/* Allocate Tx ring. */	txdesc = mallocalign(TxCount* sizeof(TxDesc), 256, 0, 0);	if(txdesc == nil){		print("vgbe: unable to alloc Tx ring\n");		unlock(&ctlr->init_lock);		return;	}	ctlr->tx_ring = txdesc;	/* Init DMAs */	wiob(ctlr, DmaCfg0, 4);	/* Init Tx MAC. */	wiob(ctlr, TxControl, 0);	wiob(ctlr, TxConfig, TxConfig_NonBlk|TxConfig_ArbPrio);	/* Load Tx ring. */	wiol(ctlr, TxDescLo, (ulong) PCIWADDR(txdesc));	wiow(ctlr, TxNum, TxCount - 1);	wiow(ctlr, TxDscIdx, 0);	/* Enable Xon/Xoff */	wiob(ctlr, Cr2S, 0xb|Cr2_XonEnable);	/* Enable Rx queue */	wiob(ctlr, RxCsrS, RxCsr_RunQueue);	/* Enable Tx queue */	wiob(ctlr, TxCsrS, TxCsr_RunQueue);	/* Done */	ctlr->inited = 1;	unlock(&ctlr->init_lock);	/* Enable interrupts */	wiol(ctlr, Isr, 0xffffffff);	wiob(ctlr, Cr3S, Cr3_IntMask);	/* Wake up Rx queue */	wiob(ctlr, RxCsrS, RxCsr_Wakeup);}static voidvgbereset(Ctlr* ctlr){//	MiiPhy* phy;	int timeo, i;//	print("vgbe: reset\n");	/* Soft reset the controller. */	wiob(ctlr, Cr1S, Cr1_reset);	for(timeo = 0; timeo < Timeout; timeo++)		if((riob(ctlr, Cr1S) & Cr1_reset) == 0)			break;	if(timeo >= Timeout){		print("vgbe: softreset timeout\n");		return;	}	/* Reload eeprom. */	siob(ctlr, Eecsr, Eecsr_Autold);	for(timeo = 0; timeo < Timeout; timeo++)		if((riob(ctlr, Eecsr) & Eecsr_Autold) == 0)			break;	if(timeo >= Timeout){		print("vgbe: eeprom reload timeout\n");		return;	}	/* Load the MAC address. */	for(i = 0; i < Eaddrlen; i++)		ctlr->ea[i] = riob(ctlr, EthAddr+i);	/* Initialize interrupts. */	wiol(ctlr, Isr, 0xffffffff);	wiol(ctlr, Imr, 0xffffffff);	/* Disable interrupts. */	wiol(ctlr, Cr3C, Cr3_IntMask);	/* 32 bits addresses only. (TODO: 64 bits ?) */	wiol(ctlr, TxDescHi, 0);	wiow(ctlr, DataBufHi, 0);	/* Enable MAC (turning off Rx/Tx engines for the moment). */	wiob(ctlr, Cr0C, Cr0_Stop|Cr0_EnableRx|Cr0_EnableTx);	wiob(ctlr, Cr0S, Cr0_Start);	/* Initialize Rx engine. */	wiow(ctlr, RxCsrC, RxCsr_RunQueue);	/* Initialize Tx engine. */	wiow(ctlr, TxCsrC, TxCsr_RunQueue);	/* Enable Rx/Tx engines. */	wiob(ctlr, Cr0S, Cr0_EnableRx|Cr0_EnableTx);	/* Initialize link management. */	ctlr->mii = malloc(sizeof(Mii));	if(ctlr->mii == nil){		print("vgbe: unable to alloc Mii\n");		return;	}	ctlr->mii->mir = vgbemiir;	ctlr->mii->miw = vgbemiiw;	ctlr->mii->ctlr = ctlr;	if(mii(ctlr->mii, 1<<1) == 0){		print("vgbe: no phy found\n");		return;	}//	phy = ctlr->mii->curphy;//	print("vgbe: phy:oui %#x\n", phy->oui);}static voidvgbepci(void){	Pcidev* pdev;//	print("vgbe: pci\n");	pdev = nil;	while(pdev = pcimatch(pdev, 0, 0)){		Ctlr* ctlr;		int port, size;		if(pdev->ccrb != 0x02 || pdev->ccru != 0)			continue;		switch((pdev->did<<16) | pdev->vid){		default:			continue;		case (0x3119<<16)|0x1106:	/* VIA Velocity (VT6122) */			break;		}		if((pdev->pcr & 1) == 0){			print("vgbe: io not enabled [pcr=%#lux]\n", (ulong)pdev->pcr);			continue;		}		pcisetbme(pdev);		pcisetpms(pdev, 0);		port = pdev->mem[0].bar;		size = pdev->mem[0].size;		if((port & 1) == 0){			print("vgbe: bar[0]=%#x is not io\n", port);			continue;		}		if(port > 0xff00){			print("vgbe: invalid port %#ux\n", port);			continue;		}		port &= 0xfffe;		if(size != 256){			print("vgbe: invalid io size: %d\n", size);			continue;		}		if(ioalloc(port, size, 0, "vge") < 0){			print("vgbe: port %#ux already in use\n", port);			continue;		}		ctlr = malloc(sizeof(Ctlr));		if(ctlr == nil){			print("vgbe: unable to alloc Ctlr\n");			iofree(port);			continue;		}		ctlr->pdev = pdev;		ctlr->port = port;		ctlr->inited = 0;		if(vgbehead != nil)			vgbetail->link = ctlr;		else			vgbehead = ctlr;		vgbetail = ctlr;	}}static longvgbectl(Ether* edev, void* buf, long n){	Cmdbuf* cb;	Ctlr* ctlr;	ulong index;	char* rptr;	RxDesc* rd;	TxDesc* td;	uchar* p;	ctlr = edev->ctlr;	cb = parsecmd(buf, n);	if(waserror()){		free(cb);		nexterror();	}	if(cistrcmp(cb->f[0], "reset") == 0){		vgbereset(ctlr);		wiob(ctlr, Cr3S, Cr3_IntMask);		wiob(ctlr, RxCsrS, RxCsr_RunQueue);		wiob(ctlr, RxCsrS, RxCsr_Wakeup);	}	else if(cistrcmp(cb->f[0], "dumpintr") == 0){		if(cb->nf < 2)			error(Ecmdargs);		if(cistrcmp(cb->f[1], "on") == 0){			ctlr->debugflags |= DumpIntr;			ctlr->debugcount = ~0;		}		else if(cistrcmp(cb->f[1], "off") == 0)			ctlr->debugflags &= ~DumpIntr;		else{			ulong count;			char* rptr;			count = strtoul(cb->f[1], &rptr, 0);			if(rptr == cb->f[1])				error("invalid control request");			ctlr->debugflags |= DumpIntr;			ctlr->debugcount = count;			print("vgbe: debugcount set to %uld\n", count);		}	}	else if(cistrcmp(cb->f[0], "dumprx") == 0){		if(cb->nf < 2)			error(Ecmdargs);		if(cistrcmp(cb->f[1], "on") == 0)			ctlr->debugflags |= DumpRx;		else if(cistrcmp(cb->f[1], "off") == 0)			ctlr->debugflags &= ~DumpRx;		else{			index = strtoul(cb->f[1], &rptr, 0);			if((rptr == cb->f[1]) || (index >= RxCount))				error("invalid control request");			rd = &ctlr->rx_ring[index];			print("vgbe: DumpRx[%03uld] status=%#08ulx ctl=%#08ulx len=%#04ux bytes\n",				index, rd->status, rd->control, rd->length);		}	}	else if(cistrcmp(cb->f[0], "dumptx") == 0){		if(cb->nf < 2)			error(Ecmdargs);		if(cistrcmp(cb->f[1], "on") == 0)			ctlr->debugflags |= DumpTx;		else if(cistrcmp(cb->f[1], "off") == 0)			ctlr->debugflags &= ~DumpTx;		else{			index = strtoul(cb->f[1], &rptr, 0);			if((rptr == cb->f[1]) || (index >= TxCount))				error("invalid control request");			td = &ctlr->tx_ring[index];			print("vgbe: DumpTx[%03uld] status=%#08ulx ctl=%#08ulx len=%#04ux bytes",				index, td->status, td->control, td->frags[0].length);			p = (uchar*)td;			for(index = 0; index < sizeof(TxDesc); index++){				if((index % 16) == 0)					print("\nvgbe: ");				else					print(" ");				print("%#02x", p[index]);			}		}	}	else if(cistrcmp(cb->f[0], "dumpall") == 0){		if(cb->nf < 2)			error(Ecmdargs);		if(cistrcmp(cb->f[1], "on") == 0){			ctlr->debugflags = ~0;			ctlr->debugcount = ~0;		}		else if(cistrcmp(cb->f[1], "off") == 0)			ctlr->debugflags = 0;		else error("invalid control request");	}	else		error(Ebadctl);	free(cb);	poperror();	return n;}static voidvgbepromiscuous(void* arg, int on){	USED(arg, on);}/* multicast already on, don't need to do anything */static voidvgbemulticast(void*, uchar*, int){}static intvgbepnp(Ether* edev){	Ctlr* ctlr;//	print("vgbe: pnp\n");	if(vgbehead == nil)		vgbepci();	for(ctlr = vgbehead; ctlr != nil; ctlr = ctlr->link){		if(ctlr->active)			continue;		if(edev->port == 0 || edev->port == ctlr->port){			ctlr->active = 1;			break;		}	}	if(ctlr == nil)		return -1;	vgbereset(ctlr);	edev->ctlr = ctlr;	edev->port = ctlr->port;	edev->irq = ctlr->pdev->intl;	edev->tbdf = ctlr->pdev->tbdf;	edev->mbps = 1000;	memmove(edev->ea, ctlr->ea, Eaddrlen);	edev->attach = vgbeattach;	edev->transmit = vgbetransmit;	edev->interrupt = vgbeinterrupt;	edev->ifstat = vgbeifstat;//	edev->promiscuous = vgbepromiscuous;	edev->multicast = vgbemulticast;//	edev->shutdown = vgbeshutdown;	edev->ctl = vgbectl;	edev->arg = edev;	return 0;}voidethervgbelink(void){	addethercard("vgbe", vgbepnp);}

⌨️ 快捷键说明

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