Configure all PCI-PCI bridges to report errors rather than masquerade

them, which would lead to undetected data corruption.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@25550 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Marcus Overhagen 2008-05-18 21:17:29 +00:00
parent 016ce5dd54
commit 63f68729a8
2 changed files with 66 additions and 4 deletions

View File

@ -360,8 +360,9 @@ PCI::InitBus()
if (fRootBus) {
DiscoverBus(fRootBus);
RefreshDeviceInfo(fRootBus);
ConfigureBridges(fRootBus);
ClearDeviceStatus(fRootBus, false);
RefreshDeviceInfo(fRootBus);
}
}
@ -660,6 +661,33 @@ PCI::FixupDevices(int domain, uint8 bus)
}
void
PCI::ConfigureBridges(PCIBus *bus)
{
for (PCIDev *dev = bus->child; dev; dev = dev->next) {
if (dev->info.class_base == PCI_bridge && dev->info.class_sub == PCI_pci) {
uint16 bridgeControlOld = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_bridge_control, 2);
uint16 bridgeControlNew = bridgeControlOld;
// Enable: Parity Error Response, SERR, Master Abort Mode, Discard Timer SERR
// Clear: Discard Timer Status
bridgeControlNew |= (1 << 0) | (1 << 1) | (1 << 5) | (1 << 10) | (1 << 11);
// Set discard timer to 2^15 PCI clocks
bridgeControlNew &= ~((1 << 8) | (1 << 9));
WritePciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_bridge_control, 2, bridgeControlNew);
bridgeControlNew = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_bridge_control, 2);
dprintf("PCI: dom %u, bus %u, dev %2u, func %u, changed PCI bridge control from 0x%04x to 0x%04x\n",
dev->domain, dev->bus, dev->dev, dev->func, bridgeControlOld, bridgeControlNew);
}
if (dev->child)
ConfigureBridges(dev->child);
}
if (bus->next)
ConfigureBridges(bus->next);
}
void
PCI::ClearDeviceStatus(PCIBus *bus, bool dumpStatus)
{
@ -670,9 +698,11 @@ PCI::ClearDeviceStatus(PCIBus *bus, bool dumpStatus)
}
for (PCIDev *dev = bus->child; dev; dev = dev->next) {
uint16 status = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_status, 2);
if (dumpStatus) {
// Clear and dump PCI device status
uint16 status = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_status, 2);
WritePciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_status, 2, status);
if (dumpStatus) {
kprintf("domain %u, bus %u, dev %2u, func %u, PCI device status 0x%04x\n",
dev->domain, dev->bus, dev->dev, dev->func, status);
if (status & (1 << 15))
@ -688,7 +718,38 @@ PCI::ClearDeviceStatus(PCIBus *bus, bool dumpStatus)
if (status & (1 << 8))
kprintf(" Master Data Parity Error\n");
}
WritePciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_status, 2, status);
if (dev->info.class_base == PCI_bridge && dev->info.class_sub == PCI_pci) {
// Clear and dump PCI bridge secondary status
uint16 secondaryStatus = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_secondary_status, 2);
WritePciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_secondary_status, 2, secondaryStatus);
if (dumpStatus) {
kprintf("PCI bridge secondary status 0x%04x\n", secondaryStatus);
if (secondaryStatus & (1 << 15))
kprintf(" Detected Parity Error\n");
if (secondaryStatus & (1 << 14))
kprintf(" Received System Error\n");
if (secondaryStatus & (1 << 13))
kprintf(" Received Master-Abort\n");
if (secondaryStatus & (1 << 12))
kprintf(" Received Target-Abort\n");
if (secondaryStatus & (1 << 11))
kprintf(" Signalled Target-Abort\n");
if (secondaryStatus & (1 << 8))
kprintf(" Data Parity Reported\n");
}
// Clear and dump the discard-timer error bit located in bridge-control register
uint16 bridgeControl = ReadPciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_bridge_control, 2);
WritePciConfig(dev->domain, dev->bus, dev->dev, dev->func, PCI_bridge_control, 2, bridgeControl);
if (dumpStatus) {
kprintf("PCI bridge control 0x%04x\n", bridgeControl);
if (bridgeControl & (1 << 10)) {
kprintf(" bridge-control: Discard Timer Error\n");
}
}
}
if (dev->child)
ClearDeviceStatus(dev->child, dumpStatus);

View File

@ -101,6 +101,7 @@ class PCI {
void ReadPciBasicInfo(PCIDev *dev);
void ReadPciHeaderInfo(PCIDev *dev);
void ConfigureBridges(PCIBus *bus);
void RefreshDeviceInfo(PCIBus *bus);
uint32 BarSize(uint32 bits, uint32 mask);