plan 9 kernel history: overview | file list | diff list

2001/0403/alphapc/ether2114x.c (diff list | history)

2000/0401/sys/src/9/alphapc/ether2114x.c:19,452001/0403/sys/src/9/alphapc/ether2114x.c:19,48 (short | long | prev | next)
1999/0422    
 
#include "etherif.h" 
 
#define DEBUG		0 
2001/0403    
#define DEBUG		(1) 
1999/0422    
#define debug		if(DEBUG)print 
 
enum { 
	Nrde		= 64, 
	Ntde		= 64, 
2000/0125    
                 
	Rxbufsz		= ROUNDUP(sizeof(Etherpkt)+4, 4), 
1999/0422    
}; 
 
2001/0403    
#define Rbsz		ROUNDUP(sizeof(Etherpkt)+4, 4) 
 
1999/0422    
enum {					/* CRS0 - Bus Mode */ 
	Swr		= 0x00000001,	/* Software Reset */ 
	Bar		= 0x00000002,	/* Bus Arbitration */ 
	Dsl		= 0x0000007C,	/* Descriptor Skip Length (field) */ 
2001/0403    
	DslMASK		= 0x0000007C,	/* Descriptor Skip Length */ 
	DslSHIFT	= 2, 
1999/0422    
	Ble		= 0x00000080,	/* Big/Little Endian */ 
	Pbl		= 0x00003F00,	/* Programmable Burst Length (field) */ 
2001/0403    
	PblMASK		= 0x00003F00,	/* Programmable Burst Length (field) */ 
	PblSHIFT	= 8, 
1999/0422    
	Cal		= 0x0000C000,	/* Cache Alignment (field) */ 
	Cal8		= 0x00004000,	/* 8 longword boundary alignment */ 
	Cal16		= 0x00008000,	/* 16 longword boundary alignment */ 
	Cal32		= 0x0000C000,	/* 32 longword boundary alignment */ 
	Tap		= 0x000E0000,	/* Transmit Automatic Polling (field) */ 
2001/0403    
	TapMASK		= 0x000E0000,	/* Transmit Automatic Polling */ 
	TapSHIFT	= 17, 
1999/0422    
	Dbo		= 0x00100000,	/* Descriptor Byte Ordering Mode */ 
	Rml		= 0x00200000,	/* Read Multiple */ 
};  
2000/0401/sys/src/9/alphapc/ether2114x.c:183,1882001/0403/sys/src/9/alphapc/ether2114x.c:186,198
1999/0422    
	Aner		= 6,		/* Auto-Negotiation Expansion */ 
}; 
 
2001/0403    
enum {					/* Variants */ 
	Tulip0		= (0x0009<<16)|0x1011, 
	Tulip3		= (0x0019<<16)|0x1011, 
	Pnic		= (0x0002<<16)|0x11AD, 
	Pnic2		= (0xC115<<16)|0x11AD, 
}; 
 
1999/0422    
typedef struct Ctlr Ctlr; 
typedef struct Ctlr { 
	int	port; 
2000/0401/sys/src/9/alphapc/ether2114x.c:189,1942001/0403/sys/src/9/alphapc/ether2114x.c:199,205
1999/0422    
	Pcidev*	pcidev; 
	Ctlr*	next; 
	int	active; 
2001/0403    
	int	id;			/* (pcidev->did<<16)|pcidev->vid */ 
1999/0422    
 
	uchar	srom[128]; 
	uchar*	sromea;			/* MAC address */ 
2000/0401/sys/src/9/alphapc/ether2114x.c:457,4632001/0403/sys/src/9/alphapc/ether2114x.c:468,474
1999/0422    
					if(des->status & De) 
						ctlr->de++; 
				} 
2000/0125    
				else if(bp = iallocb(Rxbufsz)){ 
2001/0403    
				else if(bp = iallocb(Rbsz)){ 
1999/0422    
					len = ((des->status & Fl)>>16)-4; 
					des->bp->wp = des->bp->rp+len; 
					etheriq(ether, des->bp, 1); 
2000/0401/sys/src/9/alphapc/ether2114x.c:466,4722001/0403/sys/src/9/alphapc/ether2114x.c:477,483
1999/0422    
				} 
 
				des->control &= Er; 
2000/0125    
				des->control |= Rxbufsz; 
2001/0403    
				des->control |= Rbsz; 
1999/0422    
				coherence(); 
				des->status = Own; 
 
2000/0401/sys/src/9/alphapc/ether2114x.c:566,5762001/0403/sys/src/9/alphapc/ether2114x.c:577,587
1999/0422    
	 * create and post a setup packet to initialise 
	 * the physical ethernet address. 
	 */ 
2000/0125    
	ctlr->rdr = xspanalloc(ctlr->nrdr*sizeof(Des), 8*sizeof(ulong), 0); 
2001/0403    
	ctlr->rdr = malloc(ctlr->nrdr*sizeof(Des)); 
1999/0422    
	for(des = ctlr->rdr; des < &ctlr->rdr[ctlr->nrdr]; des++){ 
2000/0125    
		des->bp = allocb(Rxbufsz); 
2001/0403    
		des->bp = allocb(Rbsz); 
1999/0422    
		des->status = Own; 
2000/0125    
		des->control = Rxbufsz; 
2001/0403    
		des->control = Rbsz; 
1999/0423    
		des->addr = PCIWADDR(des->bp->rp); 
1999/0422    
	} 
	ctlr->rdr[ctlr->nrdr-1].control |= Er; 
2000/0401/sys/src/9/alphapc/ether2114x.c:583,5892001/0403/sys/src/9/alphapc/ether2114x.c:594,605
1999/0422    
	ctlr->tdri = 0; 
1999/0423    
	csr32w(ctlr, 4, PCIWADDR(ctlr->tdr)); 
1999/0422    
 
2001/0403    
	/* 
	 * Clear any bits in the Status Register (CSR5) as 
	 * the PNIC has a different reset value from a true 2114x. 
	 */ 
1999/0422    
	ctlr->mask = Nis|Ais|Fbe|Rwt|Rps|Ru|Ri|Unf|Tjt|Tps|Ti; 
2001/0403    
	csr32w(ctlr, 5, ctlr->mask); 
1999/0422    
	csr32w(ctlr, 7, ctlr->mask); 
	ctlr->csr6 |= St; 
	csr32w(ctlr, 6, ctlr->csr6); 
2000/0401/sys/src/9/alphapc/ether2114x.c:654,6612001/0403/sys/src/9/alphapc/ether2114x.c:670,690
1999/0422    
static int 
miir(Ctlr* ctlr, int phyad, int regad) 
{ 
	int data; 
2001/0403    
	int data, i; 
1999/0422    
 
2001/0403    
	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; 
	} 
 
1999/0422    
	/* 
	 * Preamble; 
	 * ST+OP+PHYAD+REGAD; 
2000/0401/sys/src/9/alphapc/ether2114x.c:692,6972001/0403/sys/src/9/alphapc/ether2114x.c:721,737
1999/0422    
{ 
	int i, op, data; 
 
2001/0403    
	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; 
	} 
 
1999/0422    
	/* 
	 * This sequence for reading a 16-bit register 'r' 
	 * in the EEPROM is taken straight from Section 
2000/0401/sys/src/9/alphapc/ether2114x.c:739,7452001/0403/sys/src/9/alphapc/ether2114x.c:779,785
1999/0422    
	 */ 
	csr32w(ctlr, 0, Swr); 
	microdelay(10); 
	csr32w(ctlr, 0, Rml|Cal16); 
2001/0403    
	csr32w(ctlr, 0, Rml|Cal16|(32<<PblSHIFT)); 
1999/0422    
	delay(1); 
} 
 
2000/0401/sys/src/9/alphapc/ether2114x.c:762,7682001/0403/sys/src/9/alphapc/ether2114x.c:802,808
1999/0422    
	 * sequence. 
	 */ 
	len = *block++; 
	if(ctlr->pcidev->did == 0x0009){ 
2001/0403    
	if(ctlr->id != Tulip3){ 
1999/0422    
		for(i = 0; i < len; i++){ 
			csr32w(ctlr, 12, *block); 
			block++; 
2000/0401/sys/src/9/alphapc/ether2114x.c:817,8242001/0403/sys/src/9/alphapc/ether2114x.c:857,873
1999/0422    
	} 
	else if((bmcr & 0x2100) == 0x2100) 
		x = 0x4000; 
	else if(bmcr & 0x2000) 
		x = 0x2000; 
2001/0403    
	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; 
	} 
1999/0422    
	else if(bmcr & 0x0100) 
		x = 0x1000; 
	else 
2000/0401/sys/src/9/alphapc/ether2114x.c:949,9552001/0403/sys/src/9/alphapc/ether2114x.c:998,1005
1999/0422    
{ 
	int csr6, m, timeo; 
 
	csr6 = Sc|Mbo|Hbd|Ca|Sb|TrMODE; 
2001/0403    
//	csr6 = Sc|Mbo|Hbd|Ca|Sb|TrMODE; 
	csr6 = Mbo|Hbd|Sb|TrMODE; 
1999/0422    
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]){ 
2000/0401/sys/src/9/alphapc/ether2114x.c:1132,11372001/0403/sys/src/9/alphapc/ether2114x.c:1182,1211
1999/0422    
	nil, 
}; 
 
2001/0403    
/* 
 * 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 */ 
}; 
 
1999/0422    
static int 
srom(Ctlr* ctlr) 
{ 
2000/0401/sys/src/9/alphapc/ether2114x.c:1173,11782001/0403/sys/src/9/alphapc/ether2114x.c:1247,1265
1999/0422    
	} 
 
	/* 
2001/0403    
	 * 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 < Eaddrlen; i += 2){ 
			ctlr->srom[20+i] = ctlr->srom[i+1]; 
			ctlr->srom[20+i+1] = ctlr->srom[i]; 
		} 
	} 
 
	/* 
1999/0422    
	 * 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. 
2000/0401/sys/src/9/alphapc/ether2114x.c:1205,12112001/0403/sys/src/9/alphapc/ether2114x.c:1292,1298
1999/0422    
	ctlr->leaf = p; 
	ctlr->sct = *p++; 
	ctlr->sct |= *p++<<8; 
	if(ctlr->pcidev->did == 0x0009){ 
2001/0403    
	if(ctlr->id != Tulip3){ 
1999/0422    
		csr32w(ctlr, 12, Gpc|*p++); 
		delay(200); 
	} 
2000/0401/sys/src/9/alphapc/ether2114x.c:1220,12262001/0403/sys/src/9/alphapc/ether2114x.c:1307,1313
1999/0422    
		 * The RAMIX PMC665 has a badly-coded SROM, 
		 * hence the test for 21143 and type 3. 
		 */ 
		if((*p & 0x80) || (ctlr->pcidev->did == 0x0019 && *(p+1) == 3)){ 
2001/0403    
		if((*p & 0x80) || (ctlr->id == Tulip3 && *(p+1) == 3)){ 
1999/0422    
			*p |= 0x80; 
			if(*(p+1) == 1 || *(p+1) == 3) 
				phy = 1; 
2000/0401/sys/src/9/alphapc/ether2114x.c:1271,12822001/0403/sys/src/9/alphapc/ether2114x.c:1358,1371
1999/0422    
	int x; 
 
	p = nil; 
	while(p = pcimatch(p, 0x1011, 0)){ 
		switch(p->did){ 
2001/0403    
	while(p = pcimatch(p, 0, 0)){ 
		if(p->ccrb != 0x02 || p->ccru != 0) 
			continue; 
		switch((p->did<<16)|p->vid){ 
1999/0422    
		default: 
			continue; 
 
		case 0x0019:		/* 21143 */ 
2001/0403    
		case Tulip3:			/* 21143 */ 
1999/0422    
			/* 
			 * Exit sleep mode. 
			 */ 
2000/0401/sys/src/9/alphapc/ether2114x.c:1285,12912001/0403/sys/src/9/alphapc/ether2114x.c:1374,1382
1999/0422    
			pcicfgw32(p, 0x40, x); 
			/*FALLTHROUGH*/ 
 
		case 0x0009:		/* 21140 */ 
2001/0403    
		case Pnic:			/* PNIC */ 
		case Pnic2:			/* PNIC-II */ 
		case Tulip0:			/* 21140 */ 
1999/0422    
			break; 
		} 
 
2000/0401/sys/src/9/alphapc/ether2114x.c:1296,13042001/0403/sys/src/9/alphapc/ether2114x.c:1387,1396
1999/0422    
		ctlr = malloc(sizeof(Ctlr)); 
		ctlr->port = p->mem[0].bar & ~0x01; 
		ctlr->pcidev = p; 
2001/0403    
		ctlr->id = (p->did<<16)|p->vid; 
1999/0422    
 
2000/0401    
		if(ioalloc(ctlr->port, p->mem[0].size, 0, "dec2114x") < 0){ 
			print("dec2114x: port %d in use\n", ctlr->port); 
2001/0403    
			print("dec2114x: port 0x%uX in use\n", ctlr->port); 
2000/0401    
			free(ctlr); 
			continue; 
		} 
2000/0401/sys/src/9/alphapc/ether2114x.c:1312,13182001/0403/sys/src/9/alphapc/ether2114x.c:1404,1423
1999/0422    
		softreset(ctlr); 
 
		if(srom(ctlr)){ 
2001/0403    
			iofree(ctlr->port); 
1999/0422    
			free(ctlr); 
2001/0403    
			continue; 
		} 
 
		switch(ctlr->id){ 
		default: 
//			break; 
// 
//		case Pnic:			/* PNIC */ 
			/* 
			 * Turn off the jabber timer. 
			 */ 
			csr32w(ctlr, 15, 0x00000001); 
1999/0422    
			break; 
		} 
 
2000/0401/sys/src/9/alphapc/ether2114x.c:1424,14282001/0403/sys/src/9/alphapc/ether2114x.c:1529,1534
1999/0422    
void 
ether2114xlink(void) 
{ 
2001/0403    
	addethercard("21140",  reset); 
1999/0507    
	addethercard("2114x",  reset); 
1999/0422    
} 


source code copyright © 1990-2005 Lucent Technologies; see license
Plan 9 distribution
comments to russ cox (rsc@swtch.com)