shithub: riscv

Download patch

ref: fe668572ff7b8c8968f78bd9173d7d1c6e624a23
parent: 318a980c63b8e65ae6c791c88a84937fbf7e5937
author: aiju <[email protected]>
date: Sun May 15 20:35:16 EDT 2011

added basic MSI and PCI capabilities support

--- a/sys/src/9/pc/etherbcm.c
+++ b/sys/src/9/pc/etherbcm.c
@@ -547,8 +547,7 @@
 	csr32(ctlr, MACHash+12) = -1;
 	for(i = 0; i < 8; i++) csr32(ctlr, ReceiveRules + 8 * i) = 0;
 	csr32(ctlr, ReceiveRulesConfiguration) = 1 << 3;
-	csr32(ctlr, MSIMode) &= ~Enable;
-	while(csr32(ctlr, MSIMode) & Enable);
+	csr32(ctlr, MSIMode) |= Enable;
 	csr32(ctlr, MiscHostCtl) &= ~(MaskPCIInt | ClearIntA);
 }
 
--- a/sys/src/9/pc/fns.h
+++ b/sys/src/9/pc/fns.h
@@ -124,6 +124,7 @@
 uchar	pciipin(Pcidev*, uchar);
 Pcidev* pcimatch(Pcidev*, int, int);
 Pcidev* pcimatchtbdf(int);
+int	pcinextcap(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
@@ -112,6 +112,7 @@
 	PciBAR0		= 0x10,		/* base address */
 	PciBAR1		= 0x14,
 
+	PciCAP		= 0x34,		/* capabilities pointer */
 	PciINTL		= 0x3C,		/* interrupt line */
 	PciINTP		= 0x3D,		/* interrupt pin */
 };
--- a/sys/src/9/pc/mp.c
+++ b/sys/src/9/pc/mp.c
@@ -838,10 +838,61 @@
 	return -1;
 }
 
+enum {
+	MSICtrl = 0x02, /* message control register (16 bit) */
+	MSIAddr = 0x04, /* message address register (64 bit) */
+	MSIData = 0x0C, /* message data register (16 bit) */
+};
+
+static int
+msiintrenable(Vctl *v)
+{
+	int tbdf, vno, cap, cpu;
+	Pcidev *pci;
+
+	if(getconf("*msi") == nil)
+		return -1;
+	tbdf = v->tbdf;
+	if(tbdf == BUSUNKNOWN || BUSTYPE(tbdf) != BusPCI)
+		return -1;
+	pci = pcimatchtbdf(tbdf);
+	if(pci == nil) {
+		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;
+	}
+	
+	vno = VectorAPIC + (incref(&mpvnoref)-1)*8;
+	if(vno > MaxVectorAPIC) {
+		print("msiintrenable: vno %d\n", vno);
+		return -1;
+	}
+	cpu = mpintrcpu();
+	pcicfgw32(pci, cap + MSIAddr, (0xFEE << 20) | (cpu << 12));
+	pcicfgw32(pci, cap + MSIAddr + 4, 0);
+	pcicfgw16(pci, cap + MSIData, vno | (1<<14));
+	pcicfgw16(pci, cap + MSICtrl, 1);
+	print("msiintrenable: success with tbdf %.8x, vector %d, cpu %d\n", tbdf, vno, cpu);
+	v->isr = lapicisr;
+	v->eoi = lapiceoi;
+	return vno;
+}
+
 int
 mpintrenable(Vctl* v)
 {
 	int irq, tbdf, vno;
+
+	vno = msiintrenable(v);
+	if(vno != -1)
+		return vno;
 
 	/*
 	 * If the bus is known, try it.
--- a/sys/src/9/pc/pci.c
+++ b/sys/src/9/pc/pci.c
@@ -1486,3 +1486,14 @@
 
 	return ostate;
 }
+
+int
+pcinextcap(Pcidev *pci, int offset)
+{
+	if(offset == 0) {
+		if((pcicfgr16(pci, PciPSR) & (1<<4)) == 0)
+			return 0; /* no capabilities */
+		offset = PciCAP-1;
+	}
+	return pcicfgr8(pci, offset+1) & ~3;
+}