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

📄 ether2114x.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 3 页
字号:
	Ctlr *ctlr;	Des *des;	Msgbuf *mb;	int i;	uchar bi[Easize*2];	ctlr = ether->ctlr;	/*	 * Allocate and initialise the receive ring;	 * allocate and initialise the transmit ring;	 * unmask interrupts and start the transmit side;	 * create and post a setup packet to initialise	 * the physical ethernet address.	 */	ctlr->rdr = ialloc(ctlr->nrdr*sizeof(Des), 8*sizeof(ulong));	for(des = ctlr->rdr; des < &ctlr->rdr[ctlr->nrdr]; des++){		des->mb = mballoc(Rbsz, 0, Mbeth2);		des->status = Own;		des->control = Rbsz;		des->addr = PADDR(des->mb->data);	}	ctlr->rdr[ctlr->nrdr-1].control |= Er;	ctlr->rdrx = 0;	csr32w(ctlr, 3, PADDR(ctlr->rdr));	ctlr->tdr = ialloc(ctlr->ntdr*sizeof(Des), 8*sizeof(ulong));	ctlr->tdr[ctlr->ntdr-1].control |= Er;	ctlr->tdrh = 0;	ctlr->tdri = 0;	csr32w(ctlr, 4, PADDR(ctlr->tdr));	/*	 * Clear any bits in the Status Register (CSR5) as	 * the PNIC has a different reset value from a true 2114x.	 */	ctlr->mask = Nis|Ais|Fbe|Rwt|Rps|Ru|Ri|Unf|Tjt|Tps|Ti;	csr32w(ctlr, 5, ctlr->mask);	csr32w(ctlr, 7, ctlr->mask);	ctlr->csr6 |= St;	csr32w(ctlr, 6, ctlr->csr6);	for(i = 0; i < Easize/2; i++){		bi[i*4] = ether->ea[i*2];		bi[i*4+1] = ether->ea[i*2+1];		bi[i*4+2] = ether->ea[i*2+1];		bi[i*4+3] = ether->ea[i*2];	}	mb = mballoc(Easize*2*16, 0, Mbeth3);	memset(mb->data, 0xFF, sizeof(bi));	for(i = sizeof(bi); i < sizeof(bi)*16; i += sizeof(bi))		memmove(mb->data+i, bi, sizeof(bi));	mb->count = sizeof(bi)*16;	ctlr->setupmb = mb;	transmit(ether);}static voidcsr9w(Ctlr* ctlr, int data){	csr32w(ctlr, 9, data);	microdelay(1);}static intmiimdi(Ctlr* ctlr, int n){	int data, i;	/*	 * Read n bits from the MII Management Register.	 */	data = 0;	for(i = n-1; i >= 0; i--){		if(csr32r(ctlr, 9) & Mdi)			data |= (1<<i);		csr9w(ctlr, Mii|Mdc);		csr9w(ctlr, Mii);	}	csr9w(ctlr, 0);	return data;}static voidmiimdo(Ctlr* ctlr, int bits, int n){	int i, mdo;	/*	 * Write n bits to the MII Management Register.	 */	for(i = n-1; i >= 0; i--){		if(bits & (1<<i))			mdo = Mdo;		else			mdo = 0;		csr9w(ctlr, mdo);		csr9w(ctlr, mdo|Mdc);		csr9w(ctlr, mdo);	}}static intmiir(Ctlr* ctlr, int phyad, int regad){	int data, i;	if(ctlr->id == Pnic){		i = 1000;		csr32w(ctlr, 20, 0x60020000|(phyad<<23)|(regad<<18));		do{			microdelay(1);			data = csr32r(ctlr, 20);		}while((data & 0x80000000) && --i);		if(i == 0)			return -1;		return data & 0xFFFF;	}	/*	 * Preamble;	 * ST+OP+PHYAD+REGAD;	 * TA + 16 data bits.	 */	miimdo(ctlr, 0xFFFFFFFF, 32);	miimdo(ctlr, 0x1800|(phyad<<5)|regad, 14);	data = miimdi(ctlr, 18);	if(data & 0x10000)		return -1;	return data & 0xFFFF;}static voidmiiw(Ctlr* ctlr, int phyad, int regad, int data){	/*	 * Preamble;	 * ST+OP+PHYAD+REGAD+TA + 16 data bits;	 * Z.	 */	miimdo(ctlr, 0xFFFFFFFF, 32);	data &= 0xFFFF;	data |= (0x05<<(5+5+2+16))|(phyad<<(5+2+16))|(regad<<(2+16))|(0x02<<16);	miimdo(ctlr, data, 32);	csr9w(ctlr, Mdc);	csr9w(ctlr, 0);}static intsromr(Ctlr* ctlr, int r){	int i, op, data;	if(ctlr->id == Pnic){		i = 1000;		csr32w(ctlr, 19, 0x600|r);		do{			microdelay(1);			data = csr32r(ctlr, 19);		}while((data & 0x80000000) && --i);		return csr32r(ctlr, 9) & 0xFFFF;	}	/*	 * 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.	 */	csr9w(ctlr, Rd|Ss);	csr9w(ctlr, Rd|Ss|Scs);	csr9w(ctlr, Rd|Ss|Sclk|Scs);	csr9w(ctlr, Rd|Ss);	op = 0x06;	for(i = 3-1; i >= 0; i--){		data = Rd|Ss|(((op>>i) & 0x01)<<2)|Scs;		csr9w(ctlr, data);		csr9w(ctlr, data|Sclk);		csr9w(ctlr, data);	}	for(i = 6-1; i >= 0; i--){		data = Rd|Ss|(((r>>i) & 0x01)<<2)|Scs;		csr9w(ctlr, data);		csr9w(ctlr, data|Sclk);		csr9w(ctlr, data);	}	data = 0;	for(i = 16-1; i >= 0; i--){		csr9w(ctlr, Rd|Ss|Sclk|Scs);		if(csr32r(ctlr, 9) & Sdo)			data |= (1<<i);		csr9w(ctlr, Rd|Ss|Scs);	}	csr9w(ctlr, 0);	return data & 0xFFFF;}static voidsoftreset(Ctlr* ctlr){	/*	 * Soft-reset the controller and initialise bus mode.	 * Delay should be >= 50 PCI cycles (2×S @ 25MHz).	 */	csr32w(ctlr, 0, Swr);	microdelay(10);	csr32w(ctlr, 0, Rml|Cal16);	delay(1);}static inttype5block(Ctlr* ctlr, uchar* block){	int csr15, i, len;	/*	 * Reset or GPR sequence. Reset should be once only,	 * before the GPR sequence.	 * Note 'block' is not a pointer to the block head but	 * a pointer to the data in the block starting at the	 * reset length value so type5block can be used for the	 * sequences contained in type 1 and type 3 blocks.	 * The SROM docs state the 21140 type 5 block is the	 * same as that for the 21143, but the two controllers	 * use different registers and sequence-element lengths	 * so the 21140 code here is a guess for a real type 5	 * sequence.	 */	len = *block++;	if(ctlr->id != Tulip3){		for(i = 0; i < len; i++){			csr32w(ctlr, 12, *block);			block++;		}		return len;	}	for(i = 0; i < len; i++){		csr15 = *block++<<16;		csr15 |= *block++<<24;		csr32w(ctlr, 15, csr15);		debug("%8.8uX ", csr15);	}	return 2*len;}static inttypephylink(Ctlr* ctlr, uchar*){	int an, bmcr, bmsr, csr6, x;	/*	 * Fail if	 *	auto-negotiataion enabled but not complete;	 *	no valid link established.	 */	bmcr = miir(ctlr, ctlr->curphyad, Bmcr);	miir(ctlr, ctlr->curphyad, Bmsr);	bmsr = miir(ctlr, ctlr->curphyad, Bmsr);	debug("bmcr 0x%2.2uX bmsr 0x%2.2uX\n", bmcr, bmsr);	if(((bmcr & 0x1000) && !(bmsr & 0x0020)) || !(bmsr & 0x0004))		return 0;	if(bmcr & 0x1000){		an = miir(ctlr, ctlr->curphyad, Anar);		an &= miir(ctlr, ctlr->curphyad, Anlpar) & 0x3E0;		debug("an 0x%2.uX 0x%2.2uX 0x%2.2uX\n",	    		miir(ctlr, ctlr->curphyad, Anar),			miir(ctlr, ctlr->curphyad, Anlpar),			an);			if(an & 0x0100)			x = 0x4000;		else if(an & 0x0080)			x = 0x2000;		else if(an & 0x0040)			x = 0x1000;		else if(an & 0x0020)			x = 0x0800;		else			x = 0;	}	else if((bmcr & 0x2100) == 0x2100)		x = 0x4000;	else if(bmcr & 0x2000){		/*		 * If FD capable, force it if necessary.		 */		if((bmsr & 0x4000) && ctlr->fd){			miiw(ctlr, ctlr->curphyad, Bmcr, 0x2100);			x = 0x4000;		}		else			x = 0x2000;	}	else if(bmcr & 0x0100)		x = 0x1000;	else		x = 0x0800;	csr6 = Sc|Mbo|Hbd|Ps|Ca|Sb|TrMODE;	if(ctlr->fdx & x)		csr6 |= Fd;	if(ctlr->ttm & x)		csr6 |= Ttm;	debug("csr6 0x%8.8uX 0x%8.8uX 0x%8.8luX\n",		csr6, ctlr->csr6, csr32r(ctlr, 6));	if(csr6 != ctlr->csr6){		ctlr->csr6 = csr6;		csr32w(ctlr, 6, csr6);	}	return 1;}static inttypephymode(Ctlr* ctlr, uchar* block, int wait){	uchar *p;	int len, mc, nway, phyx, timeo;	if(DEBUG){		int i;		len = (block[0] & ~0x80)+1;		for(i = 0; i < len; i++)			debug("%2.2uX ", block[i]);		debug("\n");	}	if(block[1] == 1)		len = 1;	else if(block[1] == 3)		len = 2;	else		return -1;	/*	 * Snarf the media capabilities, nway advertisment,	 * FDX and TTM bitmaps.	 */	p = &block[5+len*block[3]+len*block[4+len*block[3]]];	mc = *p++;	mc |= *p++<<8;	nway = *p++;	nway |= *p++<<8;	ctlr->fdx = *p++;	ctlr->fdx |= *p++<<8;	ctlr->ttm = *p++;	ctlr->ttm |= *p<<8;	debug("mc %4.4uX nway %4.4uX fdx %4.4uX ttm %4.4uX\n",		mc, nway, ctlr->fdx, ctlr->ttm);	USED(mc);	phyx = block[2];	ctlr->curphyad = ctlr->phy[phyx];	ctlr->csr6 = 0;//Sc|Mbo|Hbd|Ps|Ca|Sb|TrMODE;	//csr32w(ctlr, 6, ctlr->csr6);	if(typephylink(ctlr, block))		return 0;	if(!(ctlr->phyreset & (1<<phyx))){		debug("reset seq: len %d: ", block[3]);		if(ctlr->type5block)			type5block(ctlr, &ctlr->type5block[2]);		else			type5block(ctlr, &block[4+len*block[3]]);		debug("\n");		ctlr->phyreset |= (1<<phyx);	}	/*	 * GPR sequence.	 */	debug("gpr seq: len %d: ", block[3]);	type5block(ctlr, &block[3]);	debug("\n");	ctlr->csr6 = 0;//Sc|Mbo|Hbd|Ps|Ca|Sb|TrMODE;	//csr32w(ctlr, 6, ctlr->csr6);	if(typephylink(ctlr, block))		return 0;	/*	 * Turn off auto-negotiation, set the auto-negotiation	 * advertisment register then start the auto-negotiation	 * process again.	 */	miiw(ctlr, ctlr->curphyad, Bmcr, 0);	miiw(ctlr, ctlr->curphyad, Anar, nway|1);	miiw(ctlr, ctlr->curphyad, Bmcr, 0x1000);	if(!wait)		return 0;	for(timeo = 0; timeo < 30; timeo++){		if(typephylink(ctlr, block))			return 0;		delay(100);	}	return -1;}static inttype0link(Ctlr* ctlr, uchar* block){	int m, polarity, sense;	m = (block[3]<<8)|block[2];	sense = 1<<((m & 0x000E)>>1);	if(m & 0x0080)		polarity = sense;	else		polarity = 0;	return (csr32r(ctlr, 12) & sense)^polarity;}static inttype0mode(Ctlr* ctlr, uchar* block, int wait){	int csr6, m, timeo;	csr6 = Sc|Mbo|Hbd|Ca|Sb|TrMODE;debug("type0: medium 0x%uX, fd %d: 0x%2.2uX 0x%2.2uX 0x%2.2uX 0x%2.2uX\n",    ctlr->medium, ctlr->fd, block[0], block[1], block[2], block[3]); 	switch(block[0]){	default:		break;	case 0x04:			/* 10BASE-TFD */	case 0x05:			/* 100BASE-TXFD */	case 0x08:			/* 100BASE-FXFD */		/*		 * Don't attempt full-duplex		 * unless explicitly requested.		 */		if(!ctlr->fd)			return -1;		csr6 |= Fd;		break;	}	m = (block[3]<<8)|block[2];	if(m & 0x0001)		csr6 |= Ps;	if(m & 0x0010)		csr6 |= Ttm;	if(m & 0x0020)		csr6 |= Pcs;	if(m & 0x0040)		csr6 |= Scr;	csr32w(ctlr, 12, block[1]);	microdelay(10);	csr32w(ctlr, 6, csr6);	ctlr->csr6 = csr6;	if(!wait)		return 0;	for(timeo = 0; timeo < 30; timeo++){		if(type0link(ctlr, block))			return 0;

⌨️ 快捷键说明

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