From f5831806ff93ba5970ba4b96e8a4cb5a38116bcc Mon Sep 17 00:00:00 2001 From: Marcus Overhagen Date: Fri, 16 May 2008 22:17:21 +0000 Subject: [PATCH] Added a "pcistatus" command to KDL that prints and clears the PCI device status register. Also clear the status register during init. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@25523 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/add-ons/kernel/bus_managers/pci/pci.cpp | 49 +++++++++++++++++++++ src/add-ons/kernel/bus_managers/pci/pci.h | 2 + 2 files changed, 51 insertions(+) diff --git a/src/add-ons/kernel/bus_managers/pci/pci.cpp b/src/add-ons/kernel/bus_managers/pci/pci.cpp index b71093331a..14a5ea189c 100644 --- a/src/add-ons/kernel/bus_managers/pci/pci.cpp +++ b/src/add-ons/kernel/bus_managers/pci/pci.cpp @@ -248,6 +248,13 @@ write_io(int argc, char **argv) } +static int +pcistatus(int argc, char **argv) +{ + sPCI->ClearDeviceStatus(NULL, true); + return 0; +} + // #pragma mark bus manager init/uninit status_t @@ -282,6 +289,8 @@ pci_init(void) sPCI->InitDomainData(); sPCI->InitBus(); + add_debugger_command("pcistatus", &pcistatus, "dump and clear pci device status registers"); + return B_OK; } @@ -352,6 +361,7 @@ PCI::InitBus() if (fRootBus) { DiscoverBus(fRootBus); RefreshDeviceInfo(fRootBus); + ClearDeviceStatus(fRootBus, false); } } @@ -650,6 +660,45 @@ PCI::FixupDevices(int domain, uint8 bus) } +void +PCI::ClearDeviceStatus(PCIBus *bus, bool dumpStatus) +{ + if (!bus) { + if (!fRootBus) + return; + bus = fRootBus; + } + + 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) { + + 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)) + kprintf(" Detected Parity Error\n"); + if (status & (1 << 14)) + kprintf(" Signalled System Error\n"); + if (status & (1 << 13)) + kprintf(" Received Master-Abort\n"); + if (status & (1 << 12)) + kprintf(" Received Target-Abort\n"); + if (status & (1 << 11)) + kprintf(" Signalled Target-Abort\n"); + 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->child) + ClearDeviceStatus(dev->child, dumpStatus); + } + + if (bus->next) + ClearDeviceStatus(bus->next, dumpStatus); +} + + void PCI::DiscoverBus(PCIBus *bus) { diff --git a/src/add-ons/kernel/bus_managers/pci/pci.h b/src/add-ons/kernel/bus_managers/pci/pci.h index 089ce4f260..8fe7534623 100644 --- a/src/add-ons/kernel/bus_managers/pci/pci.h +++ b/src/add-ons/kernel/bus_managers/pci/pci.h @@ -83,6 +83,8 @@ class PCI { status_t ResolveVirtualBus(uint8 virtualBus, int *domain, uint8 *bus); + void ClearDeviceStatus(PCIBus *bus, bool dumpStatus); + private: void EnumerateBus(int domain, uint8 bus, uint8 *subordinate_bus = NULL);