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

📄 etherigbe.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 4 页
字号:
		r &= ~0x0F00;		r |= 0x0100;			/* 1x downshift */		miimiw(ctlr->mii, 20, r);		miireset(ctlr->mii);		p = 0;		if(ctlr->txcw & TxcwPs)			p |= AnaP;		if(ctlr->txcw & TxcwAs)			p |= AnaAP;		miiane(ctlr->mii, ~0, p, ~0);		break;	}	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 */			loop = strtol(p+1, &lp, 0)-1;			lp--;			if(p == lp)				loop = 7;			p = lp;			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(50);	}	if(loop >= 0)		return -1;	return r;}static intat93c46r(Ctlr* ctlr){	ushort sum;	char rop[20];	int addr, areq, bits, data, eecd, i;	eecd = csr32r(ctlr, Eecd);	if(eecd & Spi){		print("igbe: SPI EEPROM access not implemented\n");		return 0;	}	if(eecd & (Eeszaddr|Eesz256))		bits = 8;	else		bits = 6;	sum = 0;	switch(ctlr->id){	default:		areq = 0;		break;	case i82541gi:	case i82547gi:	case i82540em:	case i82540eplp:	case i82541pi:	case i82541gi2:	case i82545gmc:	case i82546gb:	case i82546eb:		areq = 1;		csr32w(ctlr, Eecd, eecd|Areq);		for(i = 0; i < 1000; i++){			if((eecd = csr32r(ctlr, Eecd)) & Agnt)				break;			microdelay(5);		}		if(!(eecd & Agnt)){			print("igbe: not granted EEPROM access\n");			goto release;		}		break;	}	snprint(rop, sizeof(rop), "S :%dDCc;", bits+3);	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, rop, (0x06<<bits)|addr) != 0){			print("igbe: can't set EEPROM address 0x%2.2X\n", addr);			goto release;		}		data = at93c46io(ctlr, ":16COc;", 0);		at93c46io(ctlr, "sic", 0);		ctlr->eeprom[addr] = data;		sum += data;	}release:	if(areq)		csr32w(ctlr, Eecd, eecd & ~Areq);	return sum;}static intigbedetach(Ctlr* ctlr){	int r, timeo;	if (ctlr == nil)		return -1;	/*	 * 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.	 *	 * The alpha needs the rest of this routine to run at splhi	 * or else the card interrupts and resets the processor.  Don't know	 * why.  Since the alpha isn't important any more, let's ignore that.	 */	csr32w(ctlr, Imc, ~0);	csr32w(ctlr, Rctl, 0);	csr32w(ctlr, Tctl, 0);	delay(10);		/* was 10 then 100 */	csr32w(ctlr, Ctrl, Devrst);	delay(1);		/* was 100 */	for(timeo = 0; timeo < 1000; timeo++){		if(!(csr32r(ctlr, Ctrl) & Devrst))			break;		delay(1);	}	if(csr32r(ctlr, Ctrl) & Devrst)		return -1;	r = csr32r(ctlr, Ctrlext);	csr32w(ctlr, Ctrlext, r|Eerst);	delay(1);	for(timeo = 0; timeo < 1000; timeo++){		if(!(csr32r(ctlr, Ctrlext) & Eerst))			break;		delay(1);	}	if(csr32r(ctlr, Ctrlext) & Eerst)		return -1;	switch(ctlr->id){	default:		break;	case i82540em:	case i82540eplp:	case i82541gi:	case i82541pi:	case i82547gi:	case i82541gi2:	case i82545gmc:	case i82546gb:	case i82546eb:		r = csr32r(ctlr, Manc);		r &= ~Arpen;		csr32w(ctlr, Manc, r);		break;	}	csr32w(ctlr, Imc, ~0);	delay(1);		/* was 100 */	for(timeo = 0; timeo < 1000; timeo++){		if(!csr32r(ctlr, Icr))			break;		delay(1);	}	if(csr32r(ctlr, Icr))		return -1;	return 0;}static voidigbeshutdown(Ether* ether){	igbedetach(ether->ctlr);}intetherigbereset(Ctlr* ctlr){	int ctrl, i, pause, r, swdpio, txcw;	if(igbedetach(ctlr))		return -1;	/*	 * Read the EEPROM, validate the checksum	 * then get the device back to a power-on state.	 */	if((r = at93c46r(ctlr)) != 0xBABA){		print("igbe: bad EEPROM checksum - 0x%4.4uX\n", r);		return -1;	}	/*	 * Snarf and 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).	 */	if ((ctlr->id == i82546gb || ctlr->id == i82546eb) && BUSFNO(ctlr->pcidev->tbdf) == 1)		ctlr->eeprom[Ea+2] += 0x100;	// second interface	for(i = Ea; i < Eaddrlen/2; i++){if(i == Ea && ctlr->id == i82541gi && ctlr->eeprom[i] == 0xFFFF)    ctlr->eeprom[i] = 0xD000;		ctlr->ra[2*i] = ctlr->eeprom[i];		ctlr->ra[2*i+1] = ctlr->eeprom[i]>>8;	}	r = (ctlr->ra[3]<<24)|(ctlr->ra[2]<<16)|(ctlr->ra[1]<<8)|ctlr->ra[0];	csr32w(ctlr, Ral, r);	r = 0x80000000|(ctlr->ra[5]<<8)|ctlr->ra[4];	csr32w(ctlr, Rah, r);	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.	 */	memset(ctlr->mta, 0, sizeof(ctlr->mta));	for(i = 0; i < 128; i++)		csr32w(ctlr, Mta+i*4, 0);	/*	 * Just in case the Eerst didn't load the defaults	 * (doesn't appear to fully on the 8243GC), do it manually.	 */	if (ctlr->id == i82543gc) {	// 82543		txcw = csr32r(ctlr, Txcw);		txcw &= ~(TxcwAne|TxcwPauseMASK|TxcwFd);		ctrl = csr32r(ctlr, Ctrl);		ctrl &= ~(SwdpioloMASK|Frcspd|Ilos|Lrst|Fd);		if(ctlr->eeprom[Icw1] & 0x0400){			ctrl |= Fd;			txcw |= TxcwFd;		}		if(ctlr->eeprom[Icw1] & 0x0200)			ctrl |= Lrst;		if(ctlr->eeprom[Icw1] & 0x0010)			ctrl |= Ilos;		if(ctlr->eeprom[Icw1] & 0x0800)			ctrl |= Frcspd;		swdpio = (ctlr->eeprom[Icw1] & 0x01E0)>>5;		ctrl |= swdpio<<SwdpioloSHIFT;		csr32w(ctlr, Ctrl, ctrl);		ctrl = csr32r(ctlr, Ctrlext);		ctrl &= ~(Ips|SwdpiohiMASK);		swdpio = (ctlr->eeprom[Icw2] & 0x00F0)>>4;		if(ctlr->eeprom[Icw1] & 0x1000)			ctrl |= Ips;		ctrl |= swdpio<<SwdpiohiSHIFT;		csr32w(ctlr, Ctrlext, ctrl);		if(ctlr->eeprom[Icw2] & 0x0800)			txcw |= TxcwAne;		pause = (ctlr->eeprom[Icw2] & 0x3000)>>12;		txcw |= pause<<TxcwPauseSHIFT;		switch(pause){		default:			ctlr->fcrtl = 0x00002000;			ctlr->fcrth = 0x00004000;			txcw |= TxcwAs|TxcwPs;			break;		case 0:			ctlr->fcrtl = 0x00002000;			ctlr->fcrth = 0x00004000;			break;		case 2:			ctlr->fcrtl = 0;			ctlr->fcrth = 0;			txcw |= TxcwAs;			break;		}		ctlr->txcw = txcw;		csr32w(ctlr, Txcw, txcw);	}	/*	 * 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);	if(!(csr32r(ctlr, Status) & Tbimode) && igbemii(ctlr) < 0)		return -1;	return 0;}static voidigbepci(void){	int cls;	Pcidev *p;	Ctlr *ctlr;	void *mem;	p = nil;	while(p = pcimatch(p, 0, 0)){		/* ccru is a short in the FS kernel, thus the cast to uchar */		if(p->ccrb != 0x02 ||#ifdef FS		    (uchar)#endif		    p->ccru != 0)			continue;		switch((p->did<<16)|p->vid){		default:			continue;		case i82543gc:		case i82544ei:		case i82547ei:		case i82540em:		case i82540eplp:		case i82541gi:		case i82547gi:		case i82541gi2:		case i82541pi:		case i82545gmc:		case i82546gb:		case i82546eb:			break;		}		/* cast for FS */		mem = (void *)vmap(p->mem[0].bar & ~0x0F, p->mem[0].size);		if(mem == nil){			print("igbe: can't map %8.8luX\n", p->mem[0].bar);			continue;		}		/*		 * from etherga620.c:		 * If PCI Write-and-Invalidate is enabled set the max write DMA		 * value to the host cache-line size (32 on Pentium or later).		 */		if(p->pcr & MemWrInv){			cls = pcicfgr8(p, PciCLS) * 4;			if(cls != CACHELINESZ)				pcicfgw8(p, PciCLS, CACHELINESZ/4);		}		cls = pcicfgr8(p, PciCLS);		switch(cls){			default:				print("igbe: unexpected CLS - %d bytes\n",					cls*sizeof(long));				break;			case 0x00:			case 0xFF:				/* alphapc 164lx returns 0 */				print("igbe: unusable PciCLS: %d, using %d longs\n",					cls, CACHELINESZ/sizeof(long));				cls = CACHELINESZ/sizeof(long);				pcicfgw8(p, PciCLS, cls);				break;			case 0x08:			case 0x10:				break;		}		ctlr = malloc(sizeof(Ctlr));		if (ctlr == nil)			panic("ibgepci: no mem");		ctlr->port = p->mem[0].bar & ~0x0F;		ctlr->pcidev = p;		ctlr->id = (p->did<<16)|p->vid;		ctlr->cls = cls*4;		ctlr->nic = mem;		if(etherigbereset(ctlr)){			free(ctlr);			continue;		}		pcisetbme(p);		if(igbectlrhead != nil)			igbectlrtail->next = ctlr;		else			igbectlrhead = ctlr;		igbectlrtail = ctlr;	}}intigbepnp(Ether* edev){	Ctlr *ctlr;	if(igbectlrhead == nil)		igbepci();	/*	 * Any adapter matches if no edev->port is supplied,	 * otherwise the ports must match.	 */	for(ctlr = igbectlrhead; 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;	memmove(edev->ea, ctlr->ra, Eaddrlen);	/*	 * Linkage to the generic ethernet driver.	 */	edev->attach = igbeattach;	edev->transmit = igbetransmit;	edev->interrupt = igbeinterrupt;#ifndef FS	edev->ifstat = igbeifstat;	edev->ctl = igbectl;	edev->arg = edev;	edev->promiscuous = igbepromiscuous;	edev->shutdown = igbeshutdown;	edev->multicast = igbemulticast;#endif	return 0;}#ifndef FSvoidetherigbebothlink(void){	addethercard("i82543", igbepnp);	addethercard("igbe", igbepnp);}#endif

⌨️ 快捷键说明

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