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

📄 etherigbe.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 3 页
字号:
		r &= ~Mdr;		csr32w(ctlr, Ctrlext, r);		delay(20);		r = csr32r(ctlr, Ctrlext);		r |= Mdr;		csr32w(ctlr, Ctrlext, r);		delay(20);		ctlr->mii->mir = i82543miimir;		ctlr->mii->miw = i82543miimiw;		break;	case i82544ei:	case i82547ei:	case i82540em:	case i82540eplp:	case i82547gi:	case i82541gi:	case i82541pi:	case i82546gb:	case i82546eb:		ctrl &= ~(Frcdplx|Frcspd);		csr32w(ctlr, Ctrl, ctrl);		ctlr->mii->mir = igbemiimir;		ctlr->mii->miw = igbemiimiw;		break;	default:		free(ctlr->mii);		ctlr->mii = nil;		return -1;	}	if(mii(ctlr->mii, ~0) == 0 || (phy = ctlr->mii->curphy) == nil){		if (0)			print("phy trouble: phy = 0x%lux\n", (ulong)phy);		free(ctlr->mii);		ctlr->mii = nil;		return -1;	}	print("oui %X phyno %d\n", phy->oui, phy->phyno);	/*	 * 8254X-specific PHY registers not in 802.3:	 *	0x10	PHY specific control	 *	0x14	extended PHY specific control	 * Set appropriate values then reset the PHY to have	 * changes noted.	 */	switch(ctlr->id){	case i82547gi:	case i82541gi:	case i82541pi:	case i82546gb:	case i82546eb:		break;	default:		r = miimir(ctlr->mii, 16);		r |= 0x0800;			/* assert CRS on Tx */		r |= 0x0060;			/* auto-crossover all speeds */		r |= 0x0002;			/* polarity reversal enabled */		miimiw(ctlr->mii, 16, r);		r = miimir(ctlr->mii, 20);		r |= 0x0070;			/* +25MHz clock */		r &= ~0x0F00;		r |= 0x0100;			/* 1x downshift */		miimiw(ctlr->mii, 20, r);		miireset(ctlr->mii);		break;	}	p = 0;	if(ctlr->txcw & TxcwPs)		p |= AnaP;	if(ctlr->txcw & TxcwAs)		p |= AnaAP;	miiane(ctlr->mii, ~0, p, ~0);	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 i82540em:	case i82540eplp:	case i82541gi:	case i82541pi:	case i82547gi:	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;		if(addr && ((addr & 0x07) == 0))			print("\n");		print(" %4.4ux", data);	}	print("\n");release:	if(areq)		csr32w(ctlr, Eecd, eecd & ~Areq);	return sum;}static voiddetach(Ctlr *ctlr){	int r;	/*	 * 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(20);	csr32w(ctlr, Ctrl, Devrst);	/* apparently needed on multi-GHz processors to avoid infinite loops */	delay(1);	while(csr32r(ctlr, Ctrl) & Devrst)		;	csr32w(ctlr, Ctrlext, Eerst | csr32r(ctlr, Ctrlext));	delay(1);	while(csr32r(ctlr, Ctrlext) & Eerst)		;	switch(ctlr->id){	default:		break;	case i82540em:	case i82540eplp:	case i82541gi:	case i82541pi:	case i82547gi:	case i82546gb:	case i82546eb:		r = csr32r(ctlr, Manc);		r &= ~Arpen;		csr32w(ctlr, Manc, r);		break;	}	csr32w(ctlr, Imc, ~0);	delay(1);	while(csr32r(ctlr, Icr))		;}static voidigbedetach(Ether *edev){	detach(edev->ctlr);}static voidigbeshutdown(Ether* ether){print("igbeshutdown\n");	igbedetach(ether);}static intigbereset(Ctlr* ctlr){	int ctrl, i, pause, r, swdpio, txcw;	detach(ctlr);	/*	 * Read the EEPROM, validate the checksum	 * then get the device back to a power-on state.	 */	r = at93c46r(ctlr);	/* zero return means no SPI EEPROM access */	if (r != 0 && r != 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) {		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);	ilock(&ctlr->imlock);	csr32w(ctlr, Imc, ~0);	ctlr->im = Lsc;	csr32w(ctlr, Ims, ctlr->im);	iunlock(&ctlr->imlock);	if(!(csr32r(ctlr, Status) & Tbimode) && igbemii(ctlr) < 0) {		print("igbe: igbemii failed\n");		return -1;	}	return 0;}static voidigbepci(void){	int port, cls;	Pcidev *p;	Ctlr *ctlr;	static int first = 1;	if (first)		first = 0;	else		return;	p = nil;	while(p = pcimatch(p, 0, 0)){		if(p->ccrb != 0x02 || p->ccru != 0)			continue;		switch((p->did<<16)|p->vid){		case i82542:		default:			continue;		case (0x1001<<16)|0x8086:	/* Intel PRO/1000 F */			break;		case i82543gc:		case i82544ei:		case i82547ei:		case i82540em:		case i82540eplp:		case i82547gi:		case i82541gi:		case i82541pi:		case i82546gb:		case i82546eb:			break;		}		/* the 82547EI is on the CSA bus, whatever that is */		port = upamalloc(p->mem[0].bar & ~0x0F, p->mem[0].size, 0);		if(port == 0){			print("igbe: can't map %d @ 0x%8.8luX\n",				p->mem[0].size, 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));		ctlr->port = port;		ctlr->pcidev = p;		ctlr->id = (p->did<<16)|p->vid;		ctlr->cls = cls*4;		ctlr->nic = KADDR(ctlr->port);print("status0 %8.8uX\n", csr32r(ctlr, Status));		if(igbereset(ctlr)){			free(ctlr);			continue;		}print("status1 %8.8uX\n", csr32r(ctlr, Status));		pcisetbme(p);		if(ctlrhead != nil)			ctlrtail->next = ctlr;		else			ctlrhead = ctlr;		ctlrtail = ctlr;	}}intigbepnp(Ether* edev){	int i;	Ctlr *ctlr;	uchar ea[Eaddrlen];	if(ctlrhead == nil)		igbepci();	/*	 * Any adapter matches if no edev->port is supplied,	 * otherwise the ports must match.	 */	for(ctlr = ctlrhead; 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[i];			edev->ea[2*i+1] = ctlr->eeprom[i]>>8;		}	}	igbeinit(edev);	/*	 * Linkage to the generic ethernet driver.	 */	edev->attach = igbeattach;	edev->transmit = igbetransmit;	edev->interrupt = igbeinterrupt;	edev->detach = igbedetach;	return 0;}

⌨️ 快捷键说明

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