shithub: riscv

Download patch

ref: d9b80de6d55e351697b06c9096229ad6c4391278
parent: a0a1082dbf2dec847bd4ab70a49e1aabf56f9f34
author: taruti <[email protected]>
date: Fri May 27 06:49:18 EDT 2011

Scan PCI via kernel in aux/vga

--- a/sys/src/cmd/aux/vga/pci.c
+++ b/sys/src/cmd/aux/vga/pci.c
@@ -28,38 +28,59 @@
 static Pcidev* pcilist;
 static Pcidev* pcitail;
 
-static int pcicfgrw32(int, int, int, int);
 
-static int
-pciscan(int bno, Pcidev** list)
+static void
+pcicfginit(void)
 {
-	ulong v;
-	Pcidev *p, *head, *tail;
-	int dno, fno, i, hdt, l, maxfno, maxubn, rno, sbn, tbdf, ubn;
+	Dir *d;
+	int fd, i, j, n, bno, dno, fno;
+	char buf[1024], *s;
+	Pcidev *p;
 
-	maxubn = bno;
-	head = nil;
-	tail = nil;
-	for(dno = 0; dno <= pcimaxdno; dno++){
-		maxfno = 0;
-		for(fno = 0; fno <= maxfno; fno++){
-			/*
-			 * For this possible device, form the bus+device+function
-			 * triplet needed to address it and try to read the vendor
-			 * and device ID. If successful, allocate a device struct
-			 * and start to fill it in with some useful information from
-			 * the device's configuration space.
-			 */
-			tbdf = MKBUS(BusPCI, bno, dno, fno);
-			l = pcicfgrw32(tbdf, PciVID, 0, 1);
-			if(l == 0xFFFFFFFF || l == 0)
-				continue;
+	pcicfgmode = 0x666;
+	trace("pcicfginit\n");
+	fd = open("#$/pci", OREAD);
+	if(fd < 0)
+		return;
+	if((n = dirreadall(fd, &d)) < 0)
+		return;
+	close(fd);
+	
+	for(i=0; i<n; i++) {
+		int nl = strlen(d[i].name);
+		if(d[i].name[nl-3] == 'r' && d[i].name[nl-2] == 'a'  && d[i].name[nl-1] == 'w' ) {
+			trace("pci device %s\n",d[i].name);
+			sprint(buf, "#$/pci/%s", d[i].name);
+			if((fd = open(buf, OREAD)) < 0)
+				return;
+			if((read(fd, buf, 0x30)) <= 0)
+				return;
+			close(fd);
+			
+			bno = strtoul(d[i].name, &s, 10);
+			dno = strtoul(s+1, &s, 10);
+			fno = strtoul(s+1, nil, 10);
+			trace("\t-> %d %d %d\n",bno, dno, fno);
 			p = mallocz(sizeof(*p), 1);
-			p->tbdf = tbdf;
-			p->vid = l;
-			p->did = l>>16;
-			p->rid = pcicfgr8(p, PciRID);	
-
+			p->tbdf = MKBUS(BusPCI, bno, dno, fno);
+			p->vid = *(ulong*)(buf);
+			p->did = *(ushort*)(buf+2);
+			p->rid  = *(uchar*)(buf+PciRID);
+			p->intl = *(uchar*)(buf+PciINTL);
+			p->ccru = *(ushort*)(buf+PciCCRu);
+			
+			int rno = PciBAR0 - 4;
+			for(j = 0; j < nelem(p->mem); j++){
+				rno += 4;
+				p->mem[j].bar = pcicfgr32(p, rno);
+				pcicfgw32(p, rno, -1);
+				ulong v = pcicfgr32(p, rno);
+				pcicfgw32(p, rno, p->mem[i].bar);
+				p->mem[j].size = -(v & ~0xF);
+				trace("\t->mem[%d] = %p %d\n", j, p->mem[j].bar, p->mem[j].size);
+			}
+				
+	
 			if(pcilist != nil)
 				pcitail->list = p;
 			else
@@ -66,145 +87,9 @@
 				pcilist = p;
 			pcitail = p;
 
-			p->intl = pcicfgr8(p, PciINTL);
-			p->ccru = pcicfgr16(p, PciCCRu);
 
-			/*
-			 * If the device is a multi-function device adjust the
-			 * loop count so all possible functions are checked.
-			 */
-			hdt = pcicfgr8(p, PciHDT);
-			if(hdt & 0x80)
-				maxfno = MaxFNO;
-
-			/*
-			 * If appropriate, read the base address registers
-			 * and work out the sizes.
-			 */
-			switch(p->ccru>>8){
-
-			case 0x01:		/* mass storage controller */
-			case 0x02:		/* network controller */
-			case 0x03:		/* display controller */
-			case 0x04:		/* multimedia device */
-			case 0x07:		/* simple communication controllers */
-			case 0x08:		/* base system peripherals */
-			case 0x09:		/* input devices */
-			case 0x0A:		/* docking stations */
-			case 0x0B:		/* processors */
-			case 0x0C:		/* serial bus controllers */
-				if((hdt & 0x7F) != 0)
-					break;
-				rno = PciBAR0 - 4;
-				for(i = 0; i < nelem(p->mem); i++){
-					rno += 4;
-					p->mem[i].bar = pcicfgr32(p, rno);
-					pcicfgw32(p, rno, -1);
-					v = pcicfgr32(p, rno);
-					pcicfgw32(p, rno, p->mem[i].bar);
-					p->mem[i].size = -(v & ~0xF);
-				}
-				break;
-
-			case 0x00:
-			case 0x05:		/* memory controller */
-			case 0x06:		/* bridge device */
-			default:
-				break;
-			}
-
-			if(head != nil)
-				tail->link = p;
-			else
-				head = p;
-			tail = p;
-		}
-	}
-
-	*list = head;
-	for(p = head; p != nil; p = p->link){
-		/*
-		 * Find PCI-PCI bridges and recursively descend the tree.
-		 */
-		if(p->ccru != ((0x06<<8)|0x04))
-			continue;
-
-		/*
-		 * If the secondary or subordinate bus number is not initialised
-		 * try to do what the PCI BIOS should have done and fill in the
-		 * numbers as the tree is descended. On the way down the subordinate
-		 * bus number is set to the maximum as it's not known how many
-		 * buses are behind this one; the final value is set on the way
-		 * back up.
-		 */
-		sbn = pcicfgr8(p, PciSBN);
-		ubn = pcicfgr8(p, PciUBN);
-		if(sbn == 0 || ubn == 0){
-			sbn = maxubn+1;
-			/*
-			 * Make sure memory, I/O and master enables are off,
-			 * set the primary, secondary and subordinate bus numbers
-			 * and clear the secondary status before attempting to
-			 * scan the secondary bus.
-			 *
-			 * Initialisation of the bridge should be done here.
-			 */
-			pcicfgw32(p, PciPCR, 0xFFFF0000);
-			l = (MaxUBN<<16)|(sbn<<8)|bno;
-			pcicfgw32(p, PciPBN, l);
-			pcicfgw16(p, PciSPSR, 0xFFFF);
-			maxubn = pciscan(sbn, &p->bridge);
-			l = (maxubn<<16)|(sbn<<8)|bno;
-			pcicfgw32(p, PciPBN, l);
-		}
-		else{
-			maxubn = ubn;
-			pciscan(sbn, &p->bridge);
-		}
-	}
-
-	return maxubn;
-}
-
-static void
-pcicfginit(void)
-{
-#ifdef kernel
-	char *p;
-#endif /* kernel */
-	int bno;
-	Pcidev **list;
-
-	if(pcicfgmode == -1){
-		/*
-		 * Try to determine which PCI configuration mode is implemented.
-		 * Mode2 uses a byte at 0xCF8 and another at 0xCFA; Mode1 uses
-		 * a DWORD at 0xCF8 and another at 0xCFC and will pass through
-		 * any non-DWORD accesses as normal I/O cycles. There shouldn't be
-		 * a device behind these addresses so if Mode2 accesses fail try
-		 * for Mode1 (which is preferred, Mode2 is deprecated).
-		 */
-		outportb(PciCSE, 0);
-		if(inportb(PciCSE) == 0){
-			pcicfgmode = 2;
-			pcimaxdno = 15;
-		}
-		else{
-			outportl(PciADDR, 0);
-			if(inportl(PciADDR) == 0){
-				pcicfgmode = 1;
-				pcimaxdno = 31;
-			}
-		}
-	
-		if(pcicfgmode > 0){
-			list = &pciroot;
-			for(bno = 0; bno < 256; bno++){
-				bno = pciscan(bno, list);
-				while(*list)
-					list = &(*list)->link;
-			}
-				
+			trace("\t-> did=%X vid=%X rid=%X intl=%d ccru=%X\n",p->did, p->vid, p->rid,p->intl, p->ccru);
+			
 		}
 	}
 }