added basic MSI and PCI capabilities support
This commit is contained in:
parent
318a980c63
commit
fe668572ff
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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*);
|
||||
|
|
|
@ -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 */
|
||||
};
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue