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

📄 ether21140.c

📁 著名操作系统Plan 9的第三版的部分核心源代码。现在很难找到了。Plan 9是bell实验室开发的Unix后继者。
💻 C
📖 第 1 页 / 共 2 页
字号:
	return data & 0xFFFF;}static intsromr(Ctlr* ctlr, int r){	int i, op, data;	/*	 * This sequence for reading a 16-bit register 'r'	 * in the EEPROM is taken straight from Section	 * 7.4 of the 21140 Hardware Reference Manual.	 */	srmiiw(ctlr, Rd|Ss);	srmiiw(ctlr, Rd|Ss|Scs);	srmiiw(ctlr, Rd|Ss|Sclk|Scs);	srmiiw(ctlr, Rd|Ss);	op = 0x06;	for(i = 3-1; i >= 0; i--){		data = Rd|Ss|(((op>>i) & 0x01)<<2)|Scs;		srmiiw(ctlr, data);		srmiiw(ctlr, data|Sclk);		srmiiw(ctlr, data);	}	for(i = 6-1; i >= 0; i--){		data = Rd|Ss|(((r>>i) & 0x01)<<2)|Scs;		srmiiw(ctlr, data);		srmiiw(ctlr, data|Sclk);		srmiiw(ctlr, data);	}	data = 0;	for(i = 16-1; i >= 0; i--){		srmiiw(ctlr, Rd|Ss|Sclk|Scs);		if(csr32r(ctlr, 9) & Sdo)			data |= (1<<i);		srmiiw(ctlr, Rd|Ss|Scs);	}	srmiiw(ctlr, 0);	return data & 0xFFFF;}static char* mediatable[] = {	"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 */	0x03,					/* [8]  media code (100BASE-TX) */	0x1B,					/* [9]  general purpose port data */	0x6D, 0x00,				/* [10] command (LSB, MSB = 0x006D) */	0x00,					/* [8]  media code (10BASE-TX) */	0x0B,					/* [9]  general purpose port data */	0x9E, 0x00,				/* [10] command (LSB, MSB = 0x009E) */						/* 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 */	0x03,					/* [8]  media code (100BASE-TX) */	0x09,					/* [9]  general purpose port data */	0x6D, 0x00,				/* [10] command (LSB, MSB = 0x006D) */	0x00,					/* [8]  media code (10BASE-TX) */	0x00,					/* [9]  general purpose port data */	0x9E, 0x00,				/* [10] command (LSB, MSB = 0x009E) */};static uchar* sromtable[] = {	en1207,					/* Accton EN1207-COMBO */	ana6910fx,				/* Adaptec (Cogent) ANA-6910FX */	smc9332,				/* SMC 9332 */	0,};static voidsoftreset(Ctlr* ctlr){	csr32w(ctlr, 0, Swr);	microdelay(10);	csr32w(ctlr, 0, Rml|Cal16);	delay(1);}static intmediadetect(Ctlr* ctlr, uchar* leaf, uchar csr12){	int csr6, m, polarity, sense, timeo;	m = (leaf[3]<<8)|leaf[2];	csr6 = Sc|Mbo|Hbd|Ca|Sb|TrMODE;	if(m & 0x0001)		csr6 |= Ps;	if(m & 0x0010)		csr6 |= Ttm;	if(m & 0x0020)		csr6 |= Pcs;	if(m & 0x0040)		csr6 |= Scr;	switch(leaf[0]){	default:		if(!ctlr->fd)			break;		/*FALLTHROUGH*/	case 0x04:				/* 10BASE-TFD */	case 0x05:				/* 100BASE-TXFD */	case 0x08:				/* 100BASE-FXFD */		csr6 |= Fd;		break;	}	sense = 1<<((m & 0x000E)>>1);	if(m & 0x0080)		polarity = sense;	else		polarity = 0;	csr32w(ctlr, 6, csr6);	softreset(ctlr);	csr32w(ctlr, 12, Gpc|csr12);	delay(200);	csr32w(ctlr, 12, leaf[1]);	microdelay(10);	csr32w(ctlr, 6, csr6);	for(timeo = 0; timeo < 30; timeo++){		if((csr32r(ctlr, 12) & sense)^polarity){			DEBUG("timeo=%d CSR6=%uX CSR12=%uX m=%uX sense=%uX polarity=%uX\n",    				timeo, csr6, csr32r(ctlr, 12), m, sense, polarity);			return csr6;		}		delay(100);	}	DEBUG("timeo=%d CSR6=%uX CSR12=%uX m=%uX sense=%uX polarity=%uX\n",    		timeo, csr6, csr32r(ctlr, 12), m, sense, polarity);	return 0;}static voidscanphy(Ctlr* ctlr){	int index, number, oui;	number = 0;	for(index = 0; index < 32; index++){		if((oui = miir(ctlr, index, 2)) == -1 || oui == 0)			continue;		oui <<= 6;		oui |= miir(ctlr, index, 3)>>10;		DEBUG("phy%d: oui %uX reg1 %uX\n", index, oui, miir(ctlr, index, 1));		USED(oui);		ctlr->phy[number] = index;	}}static voidtype1(Ctlr* ctlr, uchar* block){	int anar, anlpar, phyad;	scanphy(ctlr);	/*	 * 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	 */	phyad = ctlr->phy[block[2]];	anar = miir(ctlr, phyad, 0x04);	anlpar = miir(ctlr, phyad, 0x05) & 0x03E0;	anar &= anlpar;print("anar = %uX %uX %uX %uX\n", anar, anlpar,  miir(ctlr, phyad, 0x00), miir(ctlr, phyad, 0x01));	ctlr->csr6 = Sc|Mbo|Hbd|Ps|Ca|Sb|TrMODE;	if(anar & 0x0100)		ctlr->csr6 |= Fd;	else if(anar & 0x0080)		;	else if(anar & 0x0040)		ctlr->csr6 |= Ttm|Fd;	else		ctlr->csr6 |= Ttm;}static intmedia(Ether* ether){	Ctlr *ctlr;	uchar *p, *block;	ushort m;	int csr6, i, k, len, medium;	ctlr = ether->ctlr;	/*	 * If it's a non-conforming card try to match the vendor ethernet	 * code and point p at a fake SROM table entry.	 */	if(ctlr->sromea == ctlr->srom){		p = nil;		for(i = 0; sromtable[i]; i++){			if(memcmp(sromtable[i], ctlr->sromea, 3) == 0){				p = &sromtable[i][4];				break;			}		}		if(p == nil)			return 0;	}	else		p = &ctlr->srom[(ctlr->srom[28]<<8)|ctlr->srom[27]];	medium = -1;	for(i = 0; i < ether->nopt; i++){		for(k = 0; k < nelem(mediatable); k++){			DEBUG("compare <%s> <%s>\n", mediatable[k], ether->opt[i]);			if(cistrcmp(mediatable[k], ether->opt[i]))				continue;			medium = k;			break;		}		switch(medium){		default:			ctlr->fd = 0;			break;		case 0x04:			/* 10BASE-TFD */		case 0x05:			/* 100BASE-TXFD */		case 0x08:			/* 100BASE-FXFD */			ctlr->fd = 1;			break;		}	}	m = (p[1]<<8)|p[0];	DEBUG("medium = %d, m = 0x%uX %uX %uX\n", medium, m, p[2], p[3]);	for(block = &p[4], k = p[3]; k > 0; k--, block += len){		DEBUG("block %uX %uX %uX %uX\n", block[0], block[1], block[2], block[3]);		if(block[0] & 0x80){			len = (block[0] & ~0x80)+1;			if(block[1] == 1)				type1(ctlr, block);			continue;		}		else			len = 4;		if(medium >= 0 && block[0] != medium)			continue;		if(m != 0x0800 && block[0] != (m & 0xFF))			continue;		/*		 * If full-duplex wasn't explicitly requested above,		 * don't attempt to to detect it.		 */		switch(block[0]){		default:			break;		case 0x04:			/* 10BASE-TFD */		case 0x05:			/* 100BASE-TXFD */		case 0x08:			/* 100BASE-FXFD */			if(!ctlr->fd)				continue;			break;		}		csr6 = mediadetect(ctlr, block, p[2]);		DEBUG("csr6 = %uX\n", csr6);		if(csr6){			ctlr->csr6 = csr6;			break;		}	}	if(ctlr->csr6){		if(!(ctlr->csr6 & Ps) || (ctlr->csr6 & Ttm))			return 10;		else			return 100;	}	return 0;}typedef struct Adapter {	int	port;	int	irq;	int	tbdf;} Adapter;static Block* adapter;static voiddec21140adapter(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;	DEBUG("port 0x%luX intl 0x%luX tbdf 0x%luX\n", port, irq, tbdf);	bp->next = *bpp;	*bpp = bp;}static voiddec21140pci(void){	Pcidev *p;	p = nil;	while(p = pcimatch(p, VendorID, DeviceID)){		/*		 * bar[0] is the I/O port register address and		 * bar[1] is the memory-mapped register address.		 */		dec21140adapter(&adapter, p->mem[0].bar & ~0x01, p->intl, p->tbdf);		pcisetbme(p);	}}static voiddetach(Ether* ether){	softreset(ether->ctlr);}intether21140reset(Ether* ether){	int i, port, x;	Block *bp, **bpp;	Adapter *ap;	Ctlr *ctlr;	uchar ea[Eaddrlen*2];	static int scandone;	if(scandone == 0){		dec21140pci();		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;		}	}	if(port == 0)		return -1;	/*	 * Allocate a controller structure and start to initialise it.	 */	ether->ctlr = malloc(sizeof(Ctlr));	ctlr = ether->ctlr;	ctlr->ctlrno = ether->ctlrno;	ctlr->type = ether->type;	ctlr->port = port;	/*	 * Soft-reset the controller and initialise bus mode.	 * Delay should be >= 50 PCI cycles (2×S @ 25MHz).	 * 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);	/*	 * 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.	 *	 * 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 16;	 *				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.	 */	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;	}	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;		}	}	memset(ea, 0, Eaddrlen);	if(memcmp(ea, ether->ea, Eaddrlen) == 0)		memmove(ether->ea, ctlr->sromea, Eaddrlen);	/*	 * Determine media.	 */	ctlr->mbps = media(ether);	/*	 * Initialise descriptor rings, ethernet address.	 */	ctlr->nrdr = Nrde;	ctlr->ntdr = Ntde;	ctlrinit(ctlr, ether->ea);	/*	 * 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 + -