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

📄 ether82557.c

📁 著名操作系统Plan 9的第三版的部分核心源代码。现在很难找到了。Plan 9是bell实验室开发的Unix后继者。
💻 C
📖 第 1 页 / 共 2 页
字号:
	ctlr->rfdl = 0;	ctlr->rfd[0].field |= RfdS;	ctlr->rfdx = 2;	memmove(ctlr->configdata, configdata, sizeof(configdata));}static intmiir(Ctlr* ctlr, int phyadd, int regadd){	int mcr, timo;	csr32w(ctlr, Mcr, MDIread|(phyadd<<21)|(regadd<<16));	mcr = 0;	for(timo = 64; timo; timo--){		mcr = csr32r(ctlr, Mcr);		if(mcr & MDIready)			break;		microdelay(1);	}	if(mcr & MDIready)		return mcr & 0xFFFF;	return -1;}static intmiiw(Ctlr* ctlr, int phyadd, int regadd, int data){	int mcr, timo;	csr32w(ctlr, Mcr, MDIwrite|(phyadd<<21)|(regadd<<16)|(data & 0xFFFF));	mcr = 0;	for(timo = 64; timo; timo--){		mcr = csr32r(ctlr, Mcr);		if(mcr & MDIready)			break;		microdelay(1);	}	if(mcr & MDIready)		return 0;	return -1;}static inthy93c46r(Ctlr* ctlr, int r){	int i, op, data;	/*	 * Hyundai HY93C46 or equivalent serial EEPROM.	 * This sequence for reading a 16-bit register 'r'	 * in the EEPROM is taken straight from Section	 * 2.3.4.2 of the Intel 82557 User's Guide.	 */	csr16w(ctlr, Ecr, EEcs);	op = EEstart|EEread;	for(i = 2; i >= 0; i--){		data = (((op>>i) & 0x01)<<2)|EEcs;		csr16w(ctlr, Ecr, data);		csr16w(ctlr, Ecr, data|EEsk);		microdelay(1);		csr16w(ctlr, Ecr, data);		microdelay(1);	}	for(i = EEaddrsz-1; i >= 0; i--){		data = (((r>>i) & 0x01)<<2)|EEcs;		csr16w(ctlr, Ecr, data);		csr16w(ctlr, Ecr, data|EEsk);		microdelay(1);		csr16w(ctlr, Ecr, data);		microdelay(1);		if((csr16r(ctlr, Ecr) & EEdo) == 0)			break;	}	data = 0;	for(i = 15; i >= 0; i--){		csr16w(ctlr, Ecr, EEcs|EEsk);		microdelay(1);		if(csr16r(ctlr, Ecr) & EEdo)			data |= (1<<i);		csr16w(ctlr, Ecr, EEcs);		microdelay(1);	}	csr16w(ctlr, Ecr, 0);	return data;}typedef struct Adapter {	int	port;	int	irq;	int	tbdf;} Adapter;static Block* adapter;static voidi82557adapter(Block** bpp, int port, int irq, int tbdf){	Block *bp;	Adapter *ap;	bp = allocb(sizeof(Adapter));	ap = (Adapter*)bp->rp;	ap->port = port;	ap->irq = irq;	ap->tbdf = tbdf;	bp->next = *bpp;	*bpp = bp;}static voidi82557pci(void){	Pcidev *p;	p = nil;	while(p = pcimatch(p, 0x8086, 0x1229)){		/*		 * bar[0] is the memory-mapped register address (4KB),		 * bar[1] is the I/O port register address (32 bytes) and		 * bar[2] is for the flash ROM (1MB).		 */		i82557adapter(&adapter, p->mem[1].bar & ~0x01, p->intl, p->tbdf);		pcisetbme(p);	}}static voiddetach(Ether* ether){	Ctlr *ctlr;	ctlr = ether->ctlr;	csr32w(ctlr, Port, 0);	delay(1);	while(csr8r(ctlr, CommandR))		;}static intscanphy(Ctlr* ctlr){	int i, oui, x;	for(i = 0; i < 32; i++){		if((oui = miir(ctlr, i, 2)) == -1 || oui == 0 || oui == 0xFFFF)			continue;		oui <<= 6;		x = miir(ctlr, i, 3);		oui |= x>>10;		//print("phy%d: oui %uX reg1 %uX\n", i, oui, miir(ctlr, i, 1));		if(oui == 0xAA00)			ctlr->eeprom[6] = 0x07<<8;		else if(oui == 0x80017){			if(x & 0x01)				ctlr->eeprom[6] = 0x0A<<8;			else				ctlr->eeprom[6] = 0x04<<8;		}		return i;	}	return -1;}inti82557reset(Ether* ether){	int anar, anlpar, bmcr, bmsr, force, i, phyaddr, port, x;	unsigned short sum;	Block *bp, **bpp;	Adapter *ap;	uchar ea[Eaddrlen];	Ctlr *ctlr;	Cb *cb;	static int scandone;	if(scandone == 0){		i82557pci();		scandone = 1;	}	/*	 * Any adapter matches if no ether->port is supplied,	 * otherwise the ports must match.	 */	port = 0;	bpp = &adapter;	for(bp = *bpp; bp; bp = bp->next){		ap = (Adapter*)bp->rp;		if(ether->port == 0 || ether->port == ap->port){			port = ap->port;			ether->irq = ap->irq;			ether->tbdf = ap->tbdf;			*bpp = bp->next;			freeb(bp);			break;		}		bpp = &bp->next;	}	if(port == 0)		return -1;	/*	 * Allocate a controller structure and start to initialise it.	 * Perform a software reset after which need to ensure busmastering	 * is still enabled. The EtherExpress PRO/100B appears to leave	 * the PCI configuration alone (see the 'To do' list above) so punt	 * for now.	 * Load the RUB and CUB registers for linear addressing (0).	 */	ether->ctlr = malloc(sizeof(Ctlr));	ctlr = ether->ctlr;	ctlr->ctlrno = ether->ctlrno;	ctlr->type = ether->type;	ctlr->port = port;	csr32w(ctlr, Port, 0);	delay(1);	while(csr8r(ctlr, CommandR))		;	csr32w(ctlr, Pointer, 0);	csr8w(ctlr, CommandR, LoadRUB);	while(csr8r(ctlr, CommandR))		;	csr8w(ctlr, CommandR, LoadCUB);	/*	 * Initialise the action and receive frame areas.	 */	ctlrinit(ctlr);	/*	 * Read the EEPROM.	 */	sum = 0;	for(i = 0; i < 0x40; i++){		x = hy93c46r(ctlr, i);		ctlr->eeprom[i] = x;		sum += x;	}	if(sum != 0xBABA)		print("#l%d: EEPROM checksum - 0x%4.4uX\n", ether->ctlrno, sum);	/*	 * Eeprom[6] indicates whether there is a PHY and whether	 * it's not 10Mb-only, in which case use the given PHY address	 * to set any PHY specific options and determine the speed.	 * Unfortunately, sometimes the EEPROM is blank except for	 * the ether address and checksum; in this case look at the	 * controller type and if 0 scan for the first PHY and try to	 * use that.	 * If no PHY, assume 82503 (serial) operation.	 */	if((ctlr->eeprom[6] & 0x1F00) && !(ctlr->eeprom[6] & 0x8000))		phyaddr = ctlr->eeprom[6] & 0x00FF;	else if(!(ctlr->eeprom[5] & 0xFF00))		phyaddr = scanphy(ctlr);	else		phyaddr = -1;	if(phyaddr >= 0){		/*		 * Resolve the highest common ability of the two		 * link partners. In descending order:		 *	0x0100		100BASE-TX Full Duplex		 *	0x0200		100BASE-T4		 *	0x0080		100BASE-TX		 *	0x0040		10BASE-T Full Duplex		 *	0x0020		10BASE-T		 */		anar = miir(ctlr, phyaddr, 0x04);		anlpar = miir(ctlr, phyaddr, 0x05) & 0x03E0;		anar &= anlpar;		bmcr = 0;		if(anar & 0x380)			bmcr = 0x2000;		if(anar & 0x0140)			bmcr |= 0x0100;		switch((ctlr->eeprom[6]>>8) & 0x001F){		case 0x04:				/* DP83840 */		case 0x0A:				/* DP83840A */			/*			 * The DP83840[A] requires some tweaking for			 * reliable operation.			 * The manual says bit 10 should be unconditionally			 * set although it supposedly only affects full-duplex			 * operation (an & 0x0140).			 */			x = miir(ctlr, phyaddr, 0x17) & ~0x0520;			x |= 0x0420;			for(i = 0; i < ether->nopt; i++){				if(cistrcmp(ether->opt[i], "congestioncontrol"))					continue;				x |= 0x0100;				break;			}			miiw(ctlr, phyaddr, 0x17, x);			/*			 * If the link partner can't autonegotiate, determine			 * the speed from elsewhere.			 */			if(anlpar == 0){				miir(ctlr, phyaddr, 0x01);				bmsr = miir(ctlr, phyaddr, 0x01);				x = miir(ctlr, phyaddr, 0x19);				if((bmsr & 0x0004) && !(x & 0x0040))					bmcr = 0x2000;			}			break;		case 0x07:				/* Intel 82555 */			/*			 * Auto-negotiation may fail if the other end is			 * a DP83840A and the cable is short.			 */			bmsr = miir(ctlr, phyaddr, 0x01);			if((miir(ctlr, phyaddr, 0) & 0x1000) && !(bmsr & 0x0020)){				miiw(ctlr, phyaddr, 0x1A, 0x2010);				x = miir(ctlr, phyaddr, 0);				miiw(ctlr, phyaddr, 0, 0x0200|x);				for(i = 0; i < 3000; i++){					delay(1);					if(miir(ctlr, phyaddr, 0x01) & 0x0020)						break;				}				miiw(ctlr, phyaddr, 0x1A, 0x2000);									anar = miir(ctlr, phyaddr, 0x04);				anlpar = miir(ctlr, phyaddr, 0x05) & 0x03E0;				anar &= anlpar;				bmcr = 0;				if(anar & 0x380)					bmcr = 0x2000;				if(anar & 0x0140)					bmcr |= 0x0100;			}			break;		}		/*		 * Force speed and duplex if no auto-negotiation.		 */		if(anlpar == 0){			force = 0;			for(i = 0; i < ether->nopt; i++){				if(cistrcmp(ether->opt[i], "fullduplex") == 0){					force = 1;					bmcr |= 0x0100;					ctlr->configdata[19] |= 0x40;				}				else if(cistrcmp(ether->opt[i], "speed") == 0){					force = 1;					x = strtol(&ether->opt[i][6], 0, 0);					if(x == 10)						bmcr &= ~0x2000;					else if(x == 100)						bmcr |= 0x2000;					else						force = 0;				}			}			if(force)				miiw(ctlr, phyaddr, 0x00, bmcr);		}		ctlr->configdata[8] = 1;		ctlr->configdata[15] &= ~0x80;	}	else{		ctlr->configdata[8] = 0;		ctlr->configdata[15] |= 0x80;	}	/*	 * Load the chip configuration	 */	configure(ether, 0);	/*	 * 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 with the Individual Address Setup command.	 */	memset(ea, 0, Eaddrlen);	if(memcmp(ea, ether->ea, Eaddrlen) == 0){		for(i = 0; i < Eaddrlen/2; i++){			x = ctlr->eeprom[i];			ether->ea[2*i] = x & 0xFF;			ether->ea[2*i+1] = (x>>8) & 0xFF;		}	}	bp = allocb(sizeof(Cb));	cb = (Cb*)bp->rp;	bp->wp += sizeof(Cb);	cb->command = CbIAS;	cb->link = NullPointer;	memmove(cb->data, ether->ea, Eaddrlen);	action(ctlr, bp);	/*	 * Linkage to the generic ethernet driver.	 */	ether->port = port;	ether->attach = attach;	ether->transmit = transmit;	ether->interrupt = interrupt;	ether->detach = detach;	return 0;}

⌨️ 快捷键说明

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