added basic MSI and PCI capabilities support

This commit is contained in:
aiju 2011-05-16 00:35:16 +00:00
parent 318a980c63
commit fe668572ff
5 changed files with 65 additions and 2 deletions

View file

@ -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);
}

View file

@ -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*);

View file

@ -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 */
};

View file

@ -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

View file

@ -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;
}