diff options
| author | aiju <aiju@phicode.de> | 2011-05-16 00:35:16 +0000 |
|---|---|---|
| committer | aiju <aiju@phicode.de> | 2011-05-16 00:35:16 +0000 |
| commit | fe668572ff7b8c8968f78bd9173d7d1c6e624a23 (patch) | |
| tree | d58b903cb39a409ae4e06bac7fd8aba8e54dabba | |
| parent | 318a980c63b8e65ae6c791c88a84937fbf7e5937 (diff) | |
| download | plan9front-fe668572ff7b8c8968f78bd9173d7d1c6e624a23.tar.xz | |
added basic MSI and PCI capabilities support
| -rw-r--r-- | sys/src/9/pc/etherbcm.c | 3 | ||||
| -rw-r--r-- | sys/src/9/pc/fns.h | 1 | ||||
| -rw-r--r-- | sys/src/9/pc/io.h | 1 | ||||
| -rw-r--r-- | sys/src/9/pc/mp.c | 51 | ||||
| -rw-r--r-- | sys/src/9/pc/pci.c | 11 |
5 files changed, 65 insertions, 2 deletions
diff --git a/sys/src/9/pc/etherbcm.c b/sys/src/9/pc/etherbcm.c index 48963c247..2be054e60 100644 --- a/sys/src/9/pc/etherbcm.c +++ b/sys/src/9/pc/etherbcm.c @@ -547,8 +547,7 @@ bcminit(Ether *edev) 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); } diff --git a/sys/src/9/pc/fns.h b/sys/src/9/pc/fns.h index bce829162..4af1813e8 100644 --- a/sys/src/9/pc/fns.h +++ b/sys/src/9/pc/fns.h @@ -124,6 +124,7 @@ void pcihinv(Pcidev*); 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*); diff --git a/sys/src/9/pc/io.h b/sys/src/9/pc/io.h index ba2399b7a..eb8dac7e8 100644 --- a/sys/src/9/pc/io.h +++ b/sys/src/9/pc/io.h @@ -112,6 +112,7 @@ enum { /* type 0 & type 1 pre-defined header */ PciBAR0 = 0x10, /* base address */ PciBAR1 = 0x14, + PciCAP = 0x34, /* capabilities pointer */ PciINTL = 0x3C, /* interrupt line */ PciINTP = 0x3D, /* interrupt pin */ }; diff --git a/sys/src/9/pc/mp.c b/sys/src/9/pc/mp.c index ee094341b..77ac729ec 100644 --- a/sys/src/9/pc/mp.c +++ b/sys/src/9/pc/mp.c @@ -838,11 +838,62 @@ mpintrenablex(Vctl* v, int tbdf) 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. * BUSUNKNOWN is given both by [E]ISA devices and by diff --git a/sys/src/9/pc/pci.c b/sys/src/9/pc/pci.c index 1443a31dc..6ad5d3663 100644 --- a/sys/src/9/pc/pci.c +++ b/sys/src/9/pc/pci.c @@ -1486,3 +1486,14 @@ pcisetpms(Pcidev* p, int state) 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; +} |
