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

1997/1011/pc/pci.c (diff list | history)

1997/0831/sys/src/9/pc/pci.c:28,331997/1011/sys/src/9/pc/pci.c:28,34 (short | long | prev | next)
1995/0725    
static int pcicfgmode = -1; 
1997/0327    
static int pcimaxdno; 
static Pcidev* pciroot; 
1997/1011    
static Pcidev* pcilist; 
1995/0725    
 
1997/0327    
static int pcicfgrw8(int, int, int, int); 
static int pcicfgrw16(int, int, int, int); 
1997/0831/sys/src/9/pc/pci.c:36,461997/1011/sys/src/9/pc/pci.c:37,49
1997/0327    
static int 
pciscan(int bno, Pcidev** list) 
1995/0725    
{ 
1997/1011    
	ulong v; 
1997/0327    
	Pcidev *p, *head, *tail; 
	int dno, fno, l, maxfno, maxubn, sbn, tbdf, ubn; 
1997/1011    
	int dno, fno, i, l, maxfno, maxubn, rno, sbn, tbdf, ubn; 
1997/0327    
 
	maxubn = bno; 
	head = tail = 0; 
1997/1011    
	head = nil; 
	tail = nil; 
1997/0412    
	for(dno = 0; dno <= pcimaxdno; dno++){ 
1997/0327    
		maxfno = 0; 
		for(fno = 0; fno <= maxfno; fno++){ 
1997/0831/sys/src/9/pc/pci.c:59,881997/1011/sys/src/9/pc/pci.c:62,91
1997/0327    
			p->tbdf = tbdf; 
			p->vid = l; 
			p->did = l>>16; 
			p->bar[0] = pcicfgrw32(tbdf, PciBAR0, 0, 1); 
			p->bar[1] = pcicfgrw32(tbdf, PciBAR1, 0, 1); 
1997/1011    
			p->list = pcilist; 
			pcilist = p; 
 
1997/0327    
			p->intl = pcicfgrw8(tbdf, PciINTL, 0, 1); 
1997/1011    
			p->ccru = pcicfgrw16(tbdf, PciCCRu, 0, 1); 
1997/0327    
 
			/* 
			 * Read the base and sub- class and if the device is 
			 * a bridge put it on a list of buses to be descended 
			 * later. 
			 * If it's not a bridge just add it to the tail of the 
			 * device list. 
			 */ 
			l = pcicfgrw16(tbdf, PciCCRu, 0, 1); 
			if(l == ((0x06<<8)|0x04)){ 
				if(head) 
					tail->next = p; 
				else 
					head = p; 
				tail = p; 
1997/1011    
			rno = PciBAR0 - 4; 
			for(i = 0; i < nelem(p->mem); i++) { 
				rno += 4; 
				p->mem[i].bar = pcicfgrw32(tbdf, rno, 0, 1); 
				if(i > 0 && p->ccru == ((0x06<<8)|0x04)) 
					continue; 
				pcicfgrw32(tbdf, rno, -1, 0); 
				v = pcicfgrw32(tbdf, rno, 0, 1); 
				pcicfgrw32(tbdf, rno, p->mem[i].bar, 0); 
				p->mem[i].size = -(v & ~0xF); 
1997/0327    
			} 
			else{ 
				*list = p; 
				list = &p->next; 
			} 
 
1997/1011    
			if(head != nil) 
				tail->link = p; 
			else 
				head = p; 
			tail = p; 
 
1997/0327    
			/* 
			 * If the device is a multi-function device adjust the 
			 * loop count so all possible functions are checked. 
1997/0831/sys/src/9/pc/pci.c:93,1121997/1011/sys/src/9/pc/pci.c:96,120
1997/0327    
		} 
	} 
 
1995/0725    
	/* 
1997/0327    
	 * If any bridges were found, recursively descend the tree. 
	 * The end result will be a single list of all devices in ascending 
	 * bus number order. 
1995/0725    
	 */ 
1997/0327    
	for(p = head; p; p = head){ 
1997/1011    
	*list = head; 
	for(p = head; p != nil; p = p->link){ 
1997/0327    
		/* 
		 * Take the primary bridge device off the bridge list 
		 * and link to the end of the final device list. 
1997/1011    
		 * Find bridges and recursively descend the tree. 
		 * Special case the Intel 82454GX Host-to-PCI bridge, 
		 * there can be two of them. 
		 * Otherwise, only descend PCI-to-PCI bridges. 
1997/0327    
		 */ 
		head = p->next; 
		p->next = 0; 
		*list = p; 
		list = &p->next; 
1997/1011    
		if(p->ccru == ((0x06<<8)|0) && p->vid == 0x8086 && p->did == 0x84C4){ 
			tbdf = p->tbdf; 
			if((sbn = pcicfgrw8(tbdf, 0x4A, 0, 1)) == 0) 
				continue; 
			ubn = pcicfgrw8(tbdf, 0x4B, 0, 1); 
			maxubn = ubn; 
			pciscan(sbn, &p->bridge); 
			continue; 
		} 
		if(p->ccru != ((0x06<<8)|0x04)) 
			continue; 
1995/0725    
 
1997/0327    
		/* 
		 * If the secondary or subordinate bus number is not initialised 
1997/0831/sys/src/9/pc/pci.c:133,1451997/1011/sys/src/9/pc/pci.c:141,153
1997/0327    
			l = (MaxUBN<<16)|(sbn<<8)|bno; 
			pcicfgrw32(tbdf, PciPBN, l, 0); 
			pcicfgrw16(tbdf, PciSPSR, 0xFFFF, 0); 
			maxubn = pciscan(sbn, list); 
1997/1011    
			maxubn = pciscan(sbn, &p->bridge); 
1997/0327    
			l = (maxubn<<16)|(sbn<<8)|bno; 
			pcicfgrw32(tbdf, PciPBN, l, 0); 
		} 
		else{ 
			maxubn = ubn; 
			pciscan(sbn, list); 
1997/1011    
			pciscan(sbn, &p->bridge); 
1997/0327    
		} 
1995/0725    
	} 
 
1997/0831/sys/src/9/pc/pci.c:348,3741997/1011/sys/src/9/pc/pci.c:356,391
1997/0327    
	pcicfgrw32(pcidev->tbdf, rno, data, 0); 
} 
 
Pcidev* 
pcimatch(Pcidev* previous, int vid, int did) 
1997/1011    
ulong 
pcibarsize(Pcidev* p, int rno) 
1997/0327    
{ 
	Pcidev *p; 
1997/1011    
	ulong v, size; 
1997/0327    
 
1997/1011    
	v = pcicfgrw32(p->tbdf, rno, 0, 1); 
	pcicfgrw32(p->tbdf, rno, 0xFFFFFFF0, 0); 
	size = pcicfgrw32(p->tbdf, rno, 0, 1); 
	pcicfgrw32(p->tbdf, rno, v, 0); 
 
	return -(size & ~0x0F); 
} 
 
Pcidev* 
pcimatch(Pcidev* prev, int vid, int did) 
{ 
1995/0726    
	if(pcicfgmode == -1) 
1997/0327    
		pcicfginit(); 
1995/0726    
 
1997/0327    
	if(previous == 0) 
		previous = pciroot; 
1997/1011    
	if(prev == nil) 
		prev = pcilist; 
1997/0327    
	else 
		previous = previous->next; 
1997/1011    
		prev = prev->list; 
1997/0327    
 
1997/0831    
	for(p = previous; p; p = p->next) { 
1997/0327    
		if(p->vid != vid) 
1995/0721    
			continue; 
1997/0327    
		if(did == 0 || p->did == did) 
1997/1011    
	while(prev != nil) { 
		if(prev->vid == vid && (did == 0 || prev->did == did)) 
1997/0327    
			break; 
1997/1011    
		prev = prev->list; 
1995/0721    
	} 
1997/0327    
                 
	return p; 
1997/1011    
	return prev; 
1997/0327    
} 
 
void 
1997/0831/sys/src/9/pc/pci.c:380,3881997/1011/sys/src/9/pc/pci.c:397,435
1997/0327    
	if(pcicfgmode == -1) 
		pcicfginit(); 
 
	for(p = pciroot; p; p = p->next){ 
1997/1011    
	for(p = pcilist; p != nil; p = p->list){ 
1997/0327    
		pcr = pcicfgr16(p, PciPSR); 
		pcicfgw16(p, PciPSR, pcr & ~0x04); 
1997/1011    
	} 
} 
 
void 
pcihinv(Pcidev* p) 
{ 
	int i; 
	Pcidev *t; 
 
	if(p == nil) { 
		p = pciroot; 
		print("bus dev type vid  did  memory\n"); 
	} 
	for(t = p; t != nil; t = t->link) { 
		print("%d  %2d/%d %.4ux %.4ux %.4ux ", 
			BUSBNO(t->tbdf), BUSDNO(t->tbdf), BUSFNO(t->tbdf), 
			t->ccru, t->vid, t->did); 
 
		for(i = 0; i < nelem(p->mem); i++) { 
			if(t->mem[i].size == 0) 
				continue; 
			print("%d:%.8lux %d ", i, 
				t->mem[i].bar, t->mem[i].size); 
		} 
		print("\n"); 
	} 
	while(p != nil) { 
		if(p->bridge != nil) 
			pcihinv(p->bridge); 
		p = p->link; 
1997/0327    
	} 
} 
 


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