shithub: riscv

Download patch

ref: 1d58cb8832bd8ab7dd6e0fb94f32cfd0f145c8a4
parent: 69ef714c5cd695b620f1a6a70e5ec19d8331069a
author: cinap_lenrek <[email protected]>
date: Fri Feb 10 19:49:39 EST 2012

pci: add pcicap

--- a/sys/src/9/pc/fns.h
+++ b/sys/src/9/pc/fns.h
@@ -128,7 +128,7 @@
 uchar	pciipin(Pcidev*, uchar);
 Pcidev* pcimatch(Pcidev*, int, int);
 Pcidev* pcimatchtbdf(int);
-int	pcinextcap(Pcidev*, int);
+int	pcicap(Pcidev*, int);
 void	pcireset(void);
 int	pciscan(int, Pcidev**);
 void	pcisetbme(Pcidev*);
--- a/sys/src/9/pc/io.h
+++ b/sys/src/9/pc/io.h
@@ -216,6 +216,23 @@
 	PciCBLMBAR	= 0x44,		/* legacy mode base address */
 };
 
+/* capabilities */
+enum {
+        PciCapPMG       = 0x01,         /* power management */
+        PciCapAGP       = 0x02,
+        PciCapVPD       = 0x03,         /* vital product data */
+        PciCapSID       = 0x04,         /* slot id */
+        PciCapMSI       = 0x05,
+        PciCapCHS       = 0x06,         /* compact pci hot swap */
+        PciCapPCIX      = 0x07,
+        PciCapHTC       = 0x08,         /* hypertransport irq conf */
+        PciCapVND       = 0x09,         /* vendor specific information */
+        PciCapPCIe      = 0x10,
+        PciCapMSIX      = 0x11,
+        PciCapSATA      = 0x12,
+        PciCapHSW       = 0x0c,         /* hot swap */
+};
+
 typedef struct Pcisiz Pcisiz;
 struct Pcisiz
 {
--- a/sys/src/9/pc/mp.c
+++ b/sys/src/9/pc/mp.c
@@ -906,15 +906,9 @@
 		print("msiintrenable: could not find Pcidev for tbdf %.8x\n", tbdf);
 		return -1;
 	}
-	cap = 0;
-	for(;;) {
-		cap = pcinextcap(pci, cap);
-		if(cap == 0)
-			return -1;
-		if(pcicfgr8(pci, cap) == 0x05) /* MSI block */
-			break;
-	}
-	
+	cap = pcicap(pci, PciCapMSI);
+	if(cap < 0)
+		return -1;
 	vno = allocvector();
 	cpu = mpintrcpu();
 	ok64 = (pcicfgr16(pci, cap + MSICtrl) & (1<<7)) != 0;
--- a/sys/src/9/pc/pci.c
+++ b/sys/src/9/pc/pci.c
@@ -1402,53 +1402,46 @@
 	pcicfgw16(p, PciPCR, p->pcr);
 }
 
-static int
-pcigetpmrb(Pcidev* p)
+int
+pcicap(Pcidev *p, int cap)
 {
-	int ptr;
+        int i, c, off;
 
-	if(p->pmrb != 0)
-		return p->pmrb;
-	p->pmrb = -1;
+        /* status register bit 4 has capabilities */
+        if((pcicfgr16(p, PciPSR) & 1<<4) == 0)
+                return -1;      
+        switch(pcicfgr8(p, PciHDT) & 0x7F){
+        default:
+                return -1;
+        case 0:                         /* etc */
+        case 1:                         /* pci to pci bridge */
+                off = 0x34;
+                break;
+        case 2:                         /* cardbus bridge */
+                off = 0x14;
+                break;
+        }
+        for(i = 48; i--;){
+                off = pcicfgr8(p, off);
+                if(off < 0x40 || (off & 3))
+                        break;
+                off &= ~3;
+                c = pcicfgr8(p, off);
+                if(c == 0xff)
+                        break;
+                if(c == cap)
+                        return off;
+                off++;
+        }
+        return -1;
+}
 
-	/*
-	 * If there are no extended capabilities implemented,
-	 * (bit 4 in the status register) assume there's no standard
-	 * power management method.
-	 * Find the capabilities pointer based on PCI header type.
-	 */
-	if(!(pcicfgr16(p, PciPSR) & 0x0010))
-		return -1;
-	switch(pcicfgr8(p, PciHDT)){
-	default:
-		return -1;
-	case 0:					/* all other */
-	case 1:					/* PCI to PCI bridge */
-		ptr = 0x34;
-		break;
-	case 2:					/* CardBus bridge */
-		ptr = 0x14;
-		break;
-	}
-	ptr = pcicfgr32(p, ptr);
-
-	while(ptr != 0){
-		/*
-		 * Check for validity.
-		 * Can't be in standard header and must be double
-		 * word aligned.
-		 */
-		if(ptr < 0x40 || (ptr & ~0xFC))
-			return -1;
-		if(pcicfgr8(p, ptr) == 0x01){
-			p->pmrb = ptr;
-			return ptr;
-		}
-
-		ptr = pcicfgr8(p, ptr+1);
-	}
-
-	return -1;
+static int
+pcigetpmrb(Pcidev* p)
+{
+        if(p->pmrb != 0)
+                return p->pmrb;
+        return p->pmrb = pcicap(p, PciCapPMG);
 }
 
 int