ether2114x.c

来自「著名操作系统Plan 9的第三版的部分核心源代码。现在很难找到了。Plan 9是」· C语言 代码 · 共 1,437 行 · 第 1/3 页

C
1,437
字号
		 *	the threshold upwards;		 *	free any transmitted buffers and try to		 *	top-up the ring.		 */		if(status & Unf){			ctlr->unf++;			ilock(&ctlr->lock);			csr32w(ctlr, 6, ctlr->csr6 & ~St);			switch(ctlr->csr6 & Tr){			case Tr128:				len = Tr256;				break;			case Tr256:				len = Tr512;				break;			case Tr512:				len = Tr1024;				break;			default:			case Tr1024:				len = Sf;				break;			}			ctlr->csr6 = (ctlr->csr6 & ~Tr)|len;			csr32w(ctlr, 6, ctlr->csr6);			iunlock(&ctlr->lock);			csr32w(ctlr, 5, Tps);			status &= ~(Unf|Tps);		}		ilock(&ctlr->tlock);		while(ctlr->ntq){			des = &ctlr->tdr[ctlr->tdri];			if(des->status & Own)				break;			if(des->status & Es){				if(des->status & Uf)					ctlr->uf++;				if(des->status & Ec)					ctlr->ec++;				if(des->status & Lc)					ctlr->lc++;				if(des->status & Nc)					ctlr->nc++;				if(des->status & Lo)					ctlr->lo++;				if(des->status & To)					ctlr->to++;				ether->oerrs++;			}			freeb(des->bp);			des->control &= Er;			ctlr->ntq--;			ctlr->tdri = NEXT(ctlr->tdri, ctlr->ntdr);		}		txstart(ether);		iunlock(&ctlr->tlock);		/*		 * Anything left not catered for?		 */		if(status)			panic("#l%d: status %8.8uX\n", ether->ctlrno, status);	}}static voidctlrinit(Ether* ether){	Ctlr *ctlr;	Des *des;	Block *bp;	int i;	uchar bi[Eaddrlen*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 = malloc(ctlr->nrdr*sizeof(Des));	for(des = ctlr->rdr; des < &ctlr->rdr[ctlr->nrdr]; des++){		des->bp = allocb(ROUNDUP(sizeof(Etherpkt)+4, 4));		des->status = Own;		des->control = ROUNDUP(sizeof(Etherpkt)+4, 4);		des->addr = PADDR(des->bp->rp);	}	ctlr->rdr[ctlr->nrdr-1].control |= Er;	ctlr->rdrx = 0;	csr32w(ctlr, 3, PADDR(ctlr->rdr));	ctlr->tdr = xspanalloc(ctlr->ntdr*sizeof(Des), 8*sizeof(ulong), 0);	ctlr->tdr[ctlr->ntdr-1].control |= Er;	ctlr->tdrh = 0;	ctlr->tdri = 0;	csr32w(ctlr, 4, PADDR(ctlr->tdr));	ctlr->mask = Nis|Ais|Fbe|Rwt|Rps|Ru|Ri|Unf|Tjt|Tps|Ti;	csr32w(ctlr, 7, ctlr->mask);	ctlr->csr6 |= St;	csr32w(ctlr, 6, ctlr->csr6);	for(i = 0; i < Eaddrlen/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];	}	bp = allocb(Eaddrlen*2*16);	memset(bp->rp, 0xFF, sizeof(bi));	for(i = sizeof(bi); i < sizeof(bi)*16; i += sizeof(bi))		memmove(bp->rp+i, bi, sizeof(bi));	bp->wp += sizeof(bi)*16;	ctlr->setupbp = bp;	ether->oq = qopen(256*1024, 1, 0, 0);	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;	/*	 * 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;	/*	 * 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->pcidev->did == 0x0009){		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;

⌨️ 快捷键说明

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