pc, pc64: add pcienable() and pcidisable() functions
pcienable() puts a device in fully powered on state and does some missing initialization that UEFI might have skipped such as I/O and Memory requests being disabled. pcidisable() is ment to shutdown the device, but currently just disables dma to prevent accidents.
This commit is contained in:
parent
4e4f2aca32
commit
4d7c195804
|
@ -147,6 +147,8 @@ void pcisetbme(Pcidev*);
|
|||
void pcisetioe(Pcidev*);
|
||||
void pcisetmwi(Pcidev*);
|
||||
int pcisetpms(Pcidev*, int);
|
||||
void pcienable(Pcidev*);
|
||||
void pcidisable(Pcidev*);
|
||||
void pcmcisread(PCMslot*);
|
||||
int pcmcistuple(int, int, int, void*, int);
|
||||
PCMmap* pcmmap(int, ulong, int, int);
|
||||
|
|
|
@ -1560,3 +1560,68 @@ pcinextcap(Pcidev *pci, int offset)
|
|||
}
|
||||
return pcicfgr8(pci, offset+1) & ~3;
|
||||
}
|
||||
|
||||
void
|
||||
pcienable(Pcidev *p)
|
||||
{
|
||||
uint pcr;
|
||||
int i;
|
||||
|
||||
if(p == nil)
|
||||
return;
|
||||
|
||||
pcienable(p->parent);
|
||||
|
||||
switch(pcisetpms(p, 0)){
|
||||
case 1:
|
||||
print("pcienable %T: wakeup from D1\n", p->tbdf);
|
||||
break;
|
||||
case 2:
|
||||
print("pcienable %T: wakeup from D2\n", p->tbdf);
|
||||
if(p->bridge != nil)
|
||||
delay(100); /* B2: minimum delay 50ms */
|
||||
else
|
||||
delay(1); /* D2: minimum delay 200µs */
|
||||
break;
|
||||
case 3:
|
||||
print("pcienable %T: wakeup from D3\n", p->tbdf);
|
||||
delay(100); /* D3: minimum delay 50ms */
|
||||
|
||||
/* restore registers */
|
||||
for(i = 0; i < 6; i++)
|
||||
pcicfgw32(p, PciBAR0+i*4, p->mem[i].bar);
|
||||
pcicfgw8(p, PciINTL, p->intl);
|
||||
pcicfgw8(p, PciLTR, p->ltr);
|
||||
pcicfgw8(p, PciCLS, p->cls);
|
||||
pcicfgw16(p, PciPCR, p->pcr);
|
||||
break;
|
||||
}
|
||||
|
||||
if(p->bridge != nil)
|
||||
pcr = IOen|MEMen|MASen;
|
||||
else {
|
||||
pcr = 0;
|
||||
for(i = 0; i < 6; i++){
|
||||
if(p->mem[i].size == 0)
|
||||
continue;
|
||||
if(p->mem[i].bar & 1)
|
||||
pcr |= IOen;
|
||||
else
|
||||
pcr |= MEMen;
|
||||
}
|
||||
}
|
||||
|
||||
if((p->pcr & pcr) != pcr){
|
||||
print("pcienable %T: pcr %ux->%ux\n", p->tbdf, p->pcr, p->pcr|pcr);
|
||||
p->pcr |= pcr;
|
||||
pcicfgrw32(p->tbdf, PciPCR, 0xFFFF0000|p->pcr, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
pcidisable(Pcidev *p)
|
||||
{
|
||||
if(p == nil)
|
||||
return;
|
||||
pciclrbme(p);
|
||||
}
|
||||
|
|
|
@ -146,6 +146,8 @@ void pcisetbme(Pcidev*);
|
|||
void pcisetioe(Pcidev*);
|
||||
void pcisetmwi(Pcidev*);
|
||||
int pcisetpms(Pcidev*, int);
|
||||
void pcienable(Pcidev*);
|
||||
void pcidisable(Pcidev*);
|
||||
void pcmcisread(PCMslot*);
|
||||
int pcmcistuple(int, int, int, void*, int);
|
||||
PCMmap* pcmmap(int, ulong, int, int);
|
||||
|
|
Loading…
Reference in a new issue