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

📄 ether2114x.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 3 页
字号:
		delay(100);	}	return -1;}static intmediaxx(Ether* ether, int wait){	Ctlr* ctlr;	uchar *block;	ctlr = ether->ctlr;	block = ctlr->infoblock[ctlr->curk];	if(block[0] & 0x80){		switch(block[1]){		default:			return -1;		case 0:			if(ctlr->medium >= 0 && block[2] != ctlr->medium)				return 0;/* need this test? */	if(ctlr->sct != 0x0800 && (ctlr->sct & 0x3F) != block[2])				return 0;			if(type0mode(ctlr, block+2, wait))				return 0;			break;		case 1:			if(typephymode(ctlr, block, wait))				return 0;			break;		case 3:			if(typephymode(ctlr, block, wait))				return 0;			break;		}	}	else{		if(ctlr->medium >= 0 && block[0] != ctlr->medium)			return 0;/* need this test? */if(ctlr->sct != 0x0800 && (ctlr->sct & 0x3F) != block[0])			return 0;		if(type0mode(ctlr, block, wait))			return 0;	}	if(ctlr->csr6){		if(!(ctlr->csr6 & Ps) || (ctlr->csr6 & Ttm))			return 10;		return 100;	}	return 0;}static intmedia(Ether* ether, int wait){	Ctlr* ctlr;	int k, mbps;	ctlr = ether->ctlr;	for(k = 0; k < ctlr->k; k++){		mbps = mediaxx(ether, wait);		if(mbps > 0)			return mbps;		if(ctlr->curk == 0)			ctlr->curk = ctlr->k-1;		else			ctlr->curk--;	}	return 0;}static char* mediatable[9] = {	"10BASE-T",				/* TP */	"10BASE-2",				/* BNC */	"10BASE-5",				/* AUI */	"100BASE-TX",	"10BASE-TFD",	"100BASE-TXFD",	"100BASE-T4",	"100BASE-FX",	"100BASE-FXFD",};static uchar en1207[] = {		/* Accton EN1207-COMBO */	0x00, 0x00, 0xE8,		/* [0]  vendor ethernet code */	0x00,				/* [3]  spare */	0x00, 0x08,			/* [4]  connection (LSB+MSB = 0x0800) */	0x1F,				/* [6]  general purpose control */	2,				/* [7]  block count */	0x00,				/* [8]  media code (10BASE-TX) */	0x0B,				/* [9]  general purpose port data */	0x9E, 0x00,			/* [10] command (LSB+MSB = 0x009E) */	0x03,				/* [8]  media code (100BASE-TX) */	0x1B,				/* [9]  general purpose port data */	0x6D, 0x00,			/* [10] command (LSB+MSB = 0x006D) */					/* There is 10BASE-2 as well, but... */};static uchar ana6910fx[] = {		/* Adaptec (Cogent) ANA-6910FX */	0x00, 0x00, 0x92,		/* [0]  vendor ethernet code */	0x00,				/* [3]  spare */	0x00, 0x08,			/* [4]  connection (LSB+MSB = 0x0800) */	0x3F,				/* [6]  general purpose control */	1,				/* [7]  block count */	0x07,				/* [8]  media code (100BASE-FX) */	0x03,				/* [9]  general purpose port data */	0x2D, 0x00			/* [10] command (LSB+MSB = 0x000D) */};static uchar smc9332[] = {		/* SMC 9332 */	0x00, 0x00, 0xC0,		/* [0]  vendor ethernet code */	0x00,				/* [3]  spare */	0x00, 0x08,			/* [4]  connection (LSB+MSB = 0x0800) */	0x1F,				/* [6]  general purpose control */	2,				/* [7]  block count */	0x00,				/* [8]  media code (10BASE-TX) */	0x00,				/* [9]  general purpose port data */	0x9E, 0x00,			/* [10] command (LSB+MSB = 0x009E) */	0x03,				/* [8]  media code (100BASE-TX) */	0x09,				/* [9]  general purpose port data */	0x6D, 0x00,			/* [10] command (LSB+MSB = 0x006D) */};static uchar* leaf21140[] = {	en1207,				/* Accton EN1207-COMBO */	ana6910fx,			/* Adaptec (Cogent) ANA-6910FX */	smc9332,			/* SMC 9332 */	nil,};/* * Copied to ctlr->srom at offset 20. */static uchar leafpnic[] = {	0x00, 0x00, 0x00, 0x00,		/* MAC address */	0x00, 0x00,	0x00,				/* controller 0 device number */	0x1E, 0x00,			/* controller 0 info leaf offset */	0x00,				/* reserved */	0x00, 0x08,			/* selected connection type */	0x00,				/* general purpose control */	0x01,				/* block count */	0x8C,				/* format indicator and count */	0x01,				/* block type */	0x00,				/* PHY number */	0x00,				/* GPR sequence length */	0x00,				/* reset sequence length */	0x00, 0x78,			/* media capabilities */	0xE0, 0x01,			/* Nway advertisment */	0x00, 0x50,			/* FDX bitmap */	0x00, 0x18,			/* TTM bitmap */};static intsrom(Ctlr* ctlr){	int i, k, oui, phy, x;	uchar *p;	/*	 * This is a partial decoding of the SROM format described in	 * 'Digital Semiconductor 21X4 Serial ROM Format, Version 4.05,	 * 2-Mar-98'. Only the 2114[03] are handled, support for other	 * controllers can be added as needed.	 */	for(i = 0; i < sizeof(ctlr->srom)/2; i++){		x = sromr(ctlr, i);		ctlr->srom[2*i] = x;		ctlr->srom[2*i+1] = x>>8;	}	/*	 * There are 2 SROM layouts:	 *	e.g. Digital EtherWORKS	station address at offset 20;	 *				this complies with the 21140A SROM	 *				application note from Digital;	 * 	e.g. SMC9332		station address at offset 0 followed by	 *				2 additional bytes, repeated at offset	 *				6; the 8 bytes are also repeated in	 *				reverse order at offset 8.	 * To check which it is, read the SROM and check for the repeating	 * patterns of the non-compliant cards; if that fails use the one at	 * offset 20.	 */	ctlr->sromea = ctlr->srom;	for(i = 0; i < 8; i++){		x = ctlr->srom[i];		if(x != ctlr->srom[15-i] || x != ctlr->srom[16+i]){			ctlr->sromea = &ctlr->srom[20];			break;		}	}	/*	 * Fake up the SROM for the PNIC.	 * It looks like a 21140 with a PHY.	 * The MAC address is byte-swapped in the orginal SROM data.	 */	if(ctlr->id == Pnic){		memmove(&ctlr->srom[20], leafpnic, sizeof(leafpnic));		for(i = 0; i < Easize; i += 2){			ctlr->srom[20+i] = ctlr->srom[i+1];			ctlr->srom[20+i+1] = ctlr->srom[i];		}	}	/*	 * Next, try to find the info leaf in the SROM for media detection.	 * If it's a non-conforming card try to match the vendor ethernet code	 * and point p at a fake info leaf with compact 21140 entries.	 */	if(ctlr->sromea == ctlr->srom){		p = nil;		for(i = 0; leaf21140[i] != nil; i++){			if(memcmp(leaf21140[i], ctlr->sromea, 3) == 0){				p = &leaf21140[i][4];				break;			}		}		if(p == nil)			return -1;	}	else		p = &ctlr->srom[(ctlr->srom[28]<<8)|ctlr->srom[27]];	/*	 * Set up the info needed for later media detection.	 * For the 21140, set the general-purpose mask in CSR12.	 * The info block entries are stored in order of increasing	 * precedence, so detection will work backwards through the	 * stored indexes into ctlr->srom.	 * If an entry is found which matches the selected connection	 * type, save the index. Otherwise, start at the last entry.	 * If any MII entries are found (type 1 and 3 blocks), scan	 * for PHYs.	 */	ctlr->leaf = p;	ctlr->sct = *p++;	ctlr->sct |= *p++<<8;	if(ctlr->id != Tulip3){		csr32w(ctlr, 12, Gpc|*p++);		delay(200);	}	ctlr->k = *p++;	if(ctlr->k >= nelem(ctlr->infoblock))		ctlr->k = nelem(ctlr->infoblock)-1;	ctlr->sctk = ctlr->k-1;	phy = 0;	for(k = 0; k < ctlr->k; k++){		ctlr->infoblock[k] = p;		/*		 * The RAMIX PMC665 has a badly-coded SROM,		 * hence the test for 21143 and type 3.		 */		if((*p & 0x80) || (ctlr->id == Tulip3 && *(p+1) == 3)){			*p |= 0x80;			if(*(p+1) == 1 || *(p+1) == 3)				phy = 1;			if(*(p+1) == 5)				ctlr->type5block = p;			p += (*p & ~0x80)+1;		}		else{			debug("type0: 0x%2.2uX 0x%2.2uX 0x%2.2uX 0x%2.2uX\n",				p[0], p[1], p[2], p[3]); 			if(ctlr->sct != 0x0800 && *p == (ctlr->sct & 0xFF))				ctlr->sctk = k;			p += 4;		}	}	ctlr->curk = ctlr->sctk;	debug("sct 0x%uX medium 0x%uX k %d curk %d phy %d\n",		ctlr->sct, ctlr->medium, ctlr->k, ctlr->curk, phy);	if(phy){		x = 0;		for(k = 0; k < nelem(ctlr->phy); k++){			if((oui = miir(ctlr, k, 2)) == -1 || oui == 0)				continue;			if(DEBUG){				oui = (oui & 0x3FF)<<6;				oui |= miir(ctlr, k, 3)>>10;				miir(ctlr, k, 1);				debug("phy%d: index %d oui %uX reg1 %uX\n",					x, k, oui, miir(ctlr, k, 1));				USED(oui);			}			ctlr->phy[x] = k;		}	}	ctlr->fd = 0;	ctlr->medium = -1;	return 0;}static voiddec2114xpci(void){	Ctlr *ctlr;	Pcidev *p;	int x;	p = nil;	while(p = pcimatch(p, 0, 0)){		if(p->ccru != ((0x02<<8)|0x00))			continue;		switch((p->did<<16)|p->vid){		default:			continue;		case Tulip3:			/* 21143 */			/*			 * Exit sleep mode.			 */			x = pcicfgr32(p, 0x40);			x &= ~0xc0000000;			pcicfgw32(p, 0x40, x);			/*FALLTHROUGH*/		case Pnic:			/* PNIC */		case Pnic2:			/* PNIC-II */		case Tulip0:			/* 21140 */			break;		}		/*		 * bar[0] is the I/O port register address and		 * bar[1] is the memory-mapped register address.		 */		ctlr = ialloc(sizeof(Ctlr), 0);		ctlr->port = p->mem[0].bar & ~0x01;		ctlr->pcidev = p;		ctlr->id = (p->did<<16)|p->vid;		/*		 * Some cards (e.g. ANA-6910FX) seem to need the Ps bit		 * set or they don't always work right after a hardware		 * reset.		 */		csr32w(ctlr, 6, Mbo|Ps);		softreset(ctlr);		if(srom(ctlr)){			//free(ctlr);			break;		}		switch(ctlr->id){		default:			break;		case Pnic:			/* PNIC */			/*			 * Turn off the jabber timer.			 */			csr32w(ctlr, 15, 0x00000001);			break;		}		if(ctlrhead != nil)			ctlrtail->next = ctlr;		else			ctlrhead = ctlr;		ctlrtail = ctlr;	}}intether21140reset(Ether* ether){	Ctlr *ctlr;	int i, x;	uchar ea[Easize];	static int scandone;	if(scandone == 0){		dec2114xpci();		scandone = 1;	}	/*	 * Any adapter matches if no ether->port is supplied,	 * otherwise the ports must match.	 */	for(ctlr = ctlrhead; ctlr != nil; ctlr = ctlr->next){		if(ctlr->active)			continue;		if(ether->port == 0 || ether->port == ctlr->port){			ctlr->active = 1;			break;		}	}	if(ctlr == nil)		return -1;	ether->ctlr = ctlr;	ether->port = ctlr->port;	ether->irq = ctlr->pcidev->intl;	ether->tbdf = ctlr->pcidev->tbdf;	/*	 * 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, Easize);	if(memcmp(ea, ether->ea, Easize) == 0)		memmove(ether->ea, ctlr->sromea, Easize);	/*	 * Look for a medium override in case there's no autonegotiation	 * (no MII) or the autonegotiation fails.	 */	for(i = 0; i < ether->nopt; i++){		if(cistrcmp(ether->opt[i], "FD") == 0){			ctlr->fd = 1;			continue;		}		for(x = 0; x < nelem(mediatable); x++){			debug("compare <%s> <%s>\n", mediatable[x],				ether->opt[i]);			if(cistrcmp(mediatable[x], ether->opt[i]))				continue;			ctlr->medium = x;				switch(ctlr->medium){			default:				ctlr->fd = 0;				break;				case 0x04:		/* 10BASE-TFD */			case 0x05:		/* 100BASE-TXFD */			case 0x08:		/* 100BASE-FXFD */				ctlr->fd = 1;				break;			}			break;		}	}	ether->mbps = media(ether, 1);	/*	 * Initialise descriptor rings, ethernet address.	 */	ctlr->nrdr = Nrde;	ctlr->ntdr = Ntde;	pcisetbme(ctlr->pcidev);	ctlrinit(ether);	/*	 * Linkage to the generic ethernet driver.	 */	ether->attach = attach;	ether->transmit = transmit;	ether->interrupt = interrupt;	return 0;}

⌨️ 快捷键说明

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