added basic MSI and PCI capabilities support
This commit is contained in:
parent
318a980c63
commit
fe668572ff
5 changed files with 65 additions and 2 deletions
|
@ -547,8 +547,7 @@ bcminit(Ether *edev)
|
||||||
csr32(ctlr, MACHash+12) = -1;
|
csr32(ctlr, MACHash+12) = -1;
|
||||||
for(i = 0; i < 8; i++) csr32(ctlr, ReceiveRules + 8 * i) = 0;
|
for(i = 0; i < 8; i++) csr32(ctlr, ReceiveRules + 8 * i) = 0;
|
||||||
csr32(ctlr, ReceiveRulesConfiguration) = 1 << 3;
|
csr32(ctlr, ReceiveRulesConfiguration) = 1 << 3;
|
||||||
csr32(ctlr, MSIMode) &= ~Enable;
|
csr32(ctlr, MSIMode) |= Enable;
|
||||||
while(csr32(ctlr, MSIMode) & Enable);
|
|
||||||
csr32(ctlr, MiscHostCtl) &= ~(MaskPCIInt | ClearIntA);
|
csr32(ctlr, MiscHostCtl) &= ~(MaskPCIInt | ClearIntA);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -124,6 +124,7 @@ void pcihinv(Pcidev*);
|
||||||
uchar pciipin(Pcidev*, uchar);
|
uchar pciipin(Pcidev*, uchar);
|
||||||
Pcidev* pcimatch(Pcidev*, int, int);
|
Pcidev* pcimatch(Pcidev*, int, int);
|
||||||
Pcidev* pcimatchtbdf(int);
|
Pcidev* pcimatchtbdf(int);
|
||||||
|
int pcinextcap(Pcidev*, int);
|
||||||
void pcireset(void);
|
void pcireset(void);
|
||||||
int pciscan(int, Pcidev**);
|
int pciscan(int, Pcidev**);
|
||||||
void pcisetbme(Pcidev*);
|
void pcisetbme(Pcidev*);
|
||||||
|
|
|
@ -112,6 +112,7 @@ enum { /* type 0 & type 1 pre-defined header */
|
||||||
PciBAR0 = 0x10, /* base address */
|
PciBAR0 = 0x10, /* base address */
|
||||||
PciBAR1 = 0x14,
|
PciBAR1 = 0x14,
|
||||||
|
|
||||||
|
PciCAP = 0x34, /* capabilities pointer */
|
||||||
PciINTL = 0x3C, /* interrupt line */
|
PciINTL = 0x3C, /* interrupt line */
|
||||||
PciINTP = 0x3D, /* interrupt pin */
|
PciINTP = 0x3D, /* interrupt pin */
|
||||||
};
|
};
|
||||||
|
|
|
@ -838,11 +838,62 @@ mpintrenablex(Vctl* v, int tbdf)
|
||||||
return -1;
|
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
|
int
|
||||||
mpintrenable(Vctl* v)
|
mpintrenable(Vctl* v)
|
||||||
{
|
{
|
||||||
int irq, tbdf, vno;
|
int irq, tbdf, vno;
|
||||||
|
|
||||||
|
vno = msiintrenable(v);
|
||||||
|
if(vno != -1)
|
||||||
|
return vno;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the bus is known, try it.
|
* If the bus is known, try it.
|
||||||
* BUSUNKNOWN is given both by [E]ISA devices and by
|
* BUSUNKNOWN is given both by [E]ISA devices and by
|
||||||
|
|
|
@ -1486,3 +1486,14 @@ pcisetpms(Pcidev* p, int state)
|
||||||
|
|
||||||
return ostate;
|
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…
Add table
Add a link
Reference in a new issue