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

📄 ether82543gc.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 3 页
字号:
{	Ctlr *ctlr;	Ether *edev;	int icr;	edev = arg;	ctlr = edev->ctlr;	while((icr = csr32r(ctlr, Icr) & ctlr->im) != 0){		/*		 * Link status changed.		 */		if(icr & (Lsc|Rxseq))			linkintr(ctlr);		/*		 * Process recv buffers.		 */		gc82543recv(edev, icr);		/*		 * Refill transmit ring and free packets.		 */		gc82543transmit(edev);	}}static intgc82543init(Ether* edev){	int csr, i;	Block *bp;	Ctlr *ctlr;	ctlr = edev->ctlr;	/*	 * Allocate private buffer pool to use for receiving packets.	 */	ilock(&freelistlock);	if (ctlr->freehead == nil){		for(i = 0; i < Nblocks; i++){			bp = iallocb(SBLOCKSIZE);			if(bp != nil){				bp->next = freeShortHead;				bp->free = freegc82543short;				freeShortHead = bp;			}			else{				print("82543gc: no memory\n");				break;			}		}		ctlr->freehead = &freeShortHead;	}	iunlock(&freelistlock);	/*	 * Set up the receive addresses.	 * There are 16 addresses. The first should be the MAC address.	 * The others are cleared and not marked valid (MS bit of Rah).	 */	csr = (edev->ea[3]<<24)|(edev->ea[2]<<16)|(edev->ea[1]<<8)|edev->ea[0];	csr32w(ctlr, Ral, csr);	csr = 0x80000000|(edev->ea[5]<<8)|edev->ea[4];	csr32w(ctlr, Rah, csr);	for(i = 1; i < 16; i++){		csr32w(ctlr, Ral+i*8, 0);		csr32w(ctlr, Rah+i*8, 0);	}	/*	 * Clear the Multicast Table Array.	 * It's a 4096 bit vector accessed as 128 32-bit registers.	 */	for(i = 0; i < 128; i++)		csr32w(ctlr, Mta+i*4, 0);	gc82543txinit(ctlr);	gc82543rxinit(ctlr);	return 0;}static intat93c46io(Ctlr* ctlr, char* op, int data){	char *lp, *p;	int i, loop, eecd, r;	eecd = csr32r(ctlr, Eecd);	r = 0;	loop = -1;	lp = nil;	for(p = op; *p != '\0'; p++){		switch(*p){		default:			return -1;		case ' ':			continue;		case ':':			/* start of loop */			if(lp != nil){				if(p != (lp+1) || loop != 7)					return -1;				lp = p;				loop = 15;				continue;			}			lp = p;			loop = 7;			continue;		case ';':			/* end of loop */			if(lp == nil)				return -1;			loop--;			if(loop >= 0)				p = lp;			else				lp = nil;			continue;		case 'C':			/* assert clock */			eecd |= Sk;			break;		case 'c':			/* deassert clock */			eecd &= ~Sk;			break;		case 'D':			/* next bit in 'data' byte */			if(loop < 0)				return -1;			if(data & (1<<loop))				eecd |= Di;			else				eecd &= ~Di;			break;		case 'O':			/* collect data output */			i = (csr32r(ctlr, Eecd) & Do) != 0;			if(loop >= 0)				r |= (i<<loop);			else				r = i;			continue;		case 'I':			/* assert data input */			eecd |= Di;			break;		case 'i':			/* deassert data input */			eecd &= ~Di;			break;		case 'S':			/* enable chip select */			eecd |= Cs;			break;		case 's':			/* disable chip select */			eecd &= ~Cs;			break;		}		csr32w(ctlr, Eecd, eecd);		microdelay(1);	}	if(loop >= 0)		return -1;	return r;}static intat93c46r(Ctlr* ctlr){	ushort sum;	int addr, data;	sum = 0;	for(addr = 0; addr < 0x40; addr++){		/*		 * Read a word at address 'addr' from the Atmel AT93C46		 * 3-Wire Serial EEPROM or compatible. The EEPROM access is		 * controlled by 4 bits in Eecd. See the AT93C46 datasheet		 * for protocol details.		 */		if(at93c46io(ctlr, "S ICc :DCc;", (0x02<<6)|addr) != 0)			break;		data = at93c46io(ctlr, "::COc;", 0);		at93c46io(ctlr, "sic", 0);		ctlr->eeprom[addr] = data;		sum += data;	}	return sum;}static voidgc82543detach(Ctlr* ctlr){	/*	 * Perform a device reset to get the chip back to the	 * power-on state, followed by an EEPROM reset to read	 * the defaults for some internal registers.	 */	csr32w(ctlr, Imc, ~0);	csr32w(ctlr, Rctl, 0);	csr32w(ctlr, Tctl, 0);	delay(10);	csr32w(ctlr, Ctrl, Devrst);	while(csr32r(ctlr, Ctrl) & Devrst)		;	csr32w(ctlr, Ctrlext, Eerst);	while(csr32r(ctlr, Ctrlext) & Eerst)		;	csr32w(ctlr, Imc, ~0);	while(csr32r(ctlr, Icr))		;}static voidgc82543checklink(Ctlr* ctlr){	int ctrl, status, rxcw;	ctrl = csr32r(ctlr, Ctrl);	status = csr32r(ctlr, Status);	rxcw = csr32r(ctlr, Rxcw);	if(!(status & Lu)){		if(!(ctrl & (Swdpin1|Slu)) && !(rxcw & Rxconfig)){			csr32w(ctlr, Txcw, ctlr->txcw & ~Ane);			ctrl |= (Slu|Fd);			if(ctlr->txcw & As)				ctrl |= Rfce;			if(ctlr->txcw & Ps)				ctrl |= Tfce;			csr32w(ctlr, Ctrl, ctrl);		}	}	else if((ctrl & Slu) && (rxcw & Rxconfig)){		csr32w(ctlr, Txcw, ctlr->txcw);		ctrl &= ~(Slu|Fd);		csr32w(ctlr, Ctrl, ctrl);	}}static voidgc82543shutdown(Ether* ether){	gc82543detach(ether->ctlr);}static intgc82543reset(Ctlr* ctlr){	int ctl;	int te;	/*	 * Read the EEPROM, validate the checksum	 * then get the device back to a power-on state.	 */	if(at93c46r(ctlr) != 0xBABA)		return -1;	gc82543detach(ctlr);	te = ctlr->eeprom[Icw2];	if((te & 0x3000) == 0){		ctlr->fcrtl = 0x00002000;		ctlr->fcrth = 0x00004000;		ctlr->txcw = Ane|TxcwFd;	}	else if((te & 0x3000) == 0x2000){		ctlr->fcrtl = 0;		ctlr->fcrth = 0;		ctlr->txcw = Ane|TxcwFd|As;	}	else{		ctlr->fcrtl = 0x00002000;		ctlr->fcrth = 0x00004000;		ctlr->txcw = Ane|TxcwFd|As|Ps;	}	csr32w(ctlr, Txcw, ctlr->txcw);	csr32w(ctlr, Ctrlext, (te & 0x00f0)<<4);	csr32w(ctlr, Tctl, csr32r(ctlr, Tctl)|(64<<ColdSHIFT));	te = ctlr->eeprom[Icw1];	ctl = ((te & 0x01E0)<<17)|(te & 0x0010)<<3;	csr32w(ctlr, Ctrl, ctl);	delay(10);	/*	 * Flow control - values from the datasheet.	 */	csr32w(ctlr, Fcal, 0x00C28001);	csr32w(ctlr, Fcah, 0x00000100);	csr32w(ctlr, Fct, 0x00008808);	csr32w(ctlr, Fcttv, 0x00000100);	csr32w(ctlr, Fcrtl, ctlr->fcrtl);	csr32w(ctlr, Fcrth, ctlr->fcrth);	ctlr->im = Lsc;	gc82543checklink(ctlr);	return 0;}static voidgc82543watchdog(void* arg){	Ether *edev;	Ctlr *ctlr;	edev = arg;	for(;;){		tsleep(&up->sleep, return0, 0, 1000);		ctlr = edev->ctlr;		if(ctlr == nil){			print("%s: exiting\n", up->text);			pexit("disabled", 0);		}		gc82543checklink(ctlr);		gc82543replenish(ctlr);	}}static voidgc82543pci(void){	int cls;	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){		case (0x1000<<16)|0x8086:	/* LSI L2A1157 (82542) */		case (0x1004<<16)|0x8086:	/* Intel PRO/1000 T */		case (0x1008<<16)|0x8086:	/* Intel PRO/1000 XT */		default:			continue;		case (0x1001<<16)|0x8086:	/* Intel PRO/1000 F */			break;		}		mem = vmap(p->mem[0].bar & ~0x0F, p->mem[0].size);		if(mem == 0){			print("gc82543: can't map %8.8luX\n", p->mem[0].bar);			continue;		}		cls = pcicfgr8(p, PciCLS);		switch(cls){			case 0x00:			case 0xFF:				print("82543gc: unusable cache line size\n");				continue;			case 0x08:				break;			default:				print("82543gc: cache line size %d, expected 32\n",					cls*4);		}		ctlr = malloc(sizeof(Ctlr));		ctlr->port = p->mem[0].bar & ~0x0F;		ctlr->pcidev = p;		ctlr->id = (p->did<<16)|p->vid;		ctlr->nic = mem;		if(gc82543reset(ctlr)){			free(ctlr);			continue;		}		if(gc82543ctlrhead != nil)			gc82543ctlrtail->next = ctlr;		else			gc82543ctlrhead = ctlr;		gc82543ctlrtail = ctlr;	}}static intgc82543pnp(Ether* edev){	int i;	Ctlr *ctlr;	uchar ea[Eaddrlen];	if(gc82543ctlrhead == nil)		gc82543pci();	/*	 * Any adapter matches if no edev->port is supplied,	 * otherwise the ports must match.	 */	for(ctlr = gc82543ctlrhead; 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 = Ea; i < Eaddrlen/2; i++){			edev->ea[2*i] = ctlr->eeprom[i];			edev->ea[2*i+1] = ctlr->eeprom[i]>>8;		}	}	gc82543init(edev);	/*	 * Linkage to the generic ethernet driver.	 */	edev->attach = gc82543attach;	edev->transmit = gc82543transmit;	edev->interrupt = gc82543interrupt;	edev->ifstat = gc82543ifstat;	edev->shutdown = gc82543shutdown;	edev->ctl = gc82543ctl;	edev->arg = edev;	edev->promiscuous = gc82543promiscuous;	edev->multicast = gc82543multicast;	return 0;}voidether82543gclink(void){	addethercard("82543GC", gc82543pnp);}

⌨️ 快捷键说明

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