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:
@@ -360,8 +360,9 @@ PCI::InitBus()
|
|||||||
|
|
||||||
if (fRootBus) {
|
if (fRootBus) {
|
||||||
DiscoverBus(fRootBus);
|
DiscoverBus(fRootBus);
|
||||||
RefreshDeviceInfo(fRootBus);
|
ConfigureBridges(fRootBus);
|
||||||
ClearDeviceStatus(fRootBus, false);
|
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
|
void
|
||||||
PCI::ClearDeviceStatus(PCIBus *bus, bool dumpStatus)
|
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) {
|
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",
|
kprintf("domain %u, bus %u, dev %2u, func %u, PCI device status 0x%04x\n",
|
||||||
dev->domain, dev->bus, dev->dev, dev->func, status);
|
dev->domain, dev->bus, dev->dev, dev->func, status);
|
||||||
if (status & (1 << 15))
|
if (status & (1 << 15))
|
||||||
@@ -688,7 +718,38 @@ PCI::ClearDeviceStatus(PCIBus *bus, bool dumpStatus)
|
|||||||
if (status & (1 << 8))
|
if (status & (1 << 8))
|
||||||
kprintf(" Master Data Parity Error\n");
|
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)
|
if (dev->child)
|
||||||
ClearDeviceStatus(dev->child, dumpStatus);
|
ClearDeviceStatus(dev->child, dumpStatus);
|
||||||
|
|||||||
@@ -101,6 +101,7 @@ class PCI {
|
|||||||
void ReadPciBasicInfo(PCIDev *dev);
|
void ReadPciBasicInfo(PCIDev *dev);
|
||||||
void ReadPciHeaderInfo(PCIDev *dev);
|
void ReadPciHeaderInfo(PCIDev *dev);
|
||||||
|
|
||||||
|
void ConfigureBridges(PCIBus *bus);
|
||||||
void RefreshDeviceInfo(PCIBus *bus);
|
void RefreshDeviceInfo(PCIBus *bus);
|
||||||
|
|
||||||
uint32 BarSize(uint32 bits, uint32 mask);
|
uint32 BarSize(uint32 bits, uint32 mask);
|
||||||
|
|||||||
Reference in New Issue
Block a user