diff options
Diffstat (limited to 'Kernel')
-rw-r--r-- | Kernel/PCI/Access.cpp | 4 | ||||
-rw-r--r-- | Kernel/PCI/Access.h | 2 | ||||
-rw-r--r-- | Kernel/PCI/IOAccess.cpp | 29 |
3 files changed, 24 insertions, 11 deletions
diff --git a/Kernel/PCI/Access.cpp b/Kernel/PCI/Access.cpp index 39ff9eef4e..f16c2c480f 100644 --- a/Kernel/PCI/Access.cpp +++ b/Kernel/PCI/Access.cpp @@ -35,6 +35,7 @@ bool Access::is_initialized() } UNMAP_AFTER_INIT Access::Access() + : m_enumerated_buses(256, false) { s_access = this; } @@ -85,10 +86,11 @@ void Access::enumerate_functions(int type, u8 bus, u8 device, u8 function, Funct Address address(0, bus, device, function); if (type == -1 || type == early_read_type(address)) callback(address, { early_read16_field(address, PCI_VENDOR_ID), early_read16_field(address, PCI_DEVICE_ID) }); - if (early_read_type(address) == PCI_TYPE_BRIDGE && recursive) { + if (early_read_type(address) == PCI_TYPE_BRIDGE && recursive && (!m_enumerated_buses.get(early_read8_field(address, PCI_SECONDARY_BUS)))) { u8 secondary_bus = early_read8_field(address, PCI_SECONDARY_BUS); dbgln_if(PCI_DEBUG, "PCI: Found secondary bus: {}", secondary_bus); VERIFY(secondary_bus != bus); + m_enumerated_buses.set(secondary_bus, true); enumerate_bus(type, secondary_bus, callback, recursive); } } diff --git a/Kernel/PCI/Access.h b/Kernel/PCI/Access.h index 42dc14d95b..d2c12695c2 100644 --- a/Kernel/PCI/Access.h +++ b/Kernel/PCI/Access.h @@ -6,6 +6,7 @@ #pragma once +#include <AK/Bitmap.h> #include <AK/String.h> #include <AK/Vector.h> #include <Kernel/PCI/Definitions.h> @@ -49,6 +50,7 @@ protected: virtual ~Access() = default; Vector<PhysicalID> m_physical_ids; + Bitmap m_enumerated_buses; }; } diff --git a/Kernel/PCI/IOAccess.cpp b/Kernel/PCI/IOAccess.cpp index d2fc93defb..ebcc155d06 100644 --- a/Kernel/PCI/IOAccess.cpp +++ b/Kernel/PCI/IOAccess.cpp @@ -67,17 +67,26 @@ void IOAccess::write32_field(Address address, u32 field, u32 value) void IOAccess::enumerate_hardware(Function<void(Address, ID)> callback) { dbgln_if(PCI_DEBUG, "PCI: IO enumerating hardware"); - // Single PCI host controller. - if ((read8_field(Address(), PCI_HEADER_TYPE) & 0x80) == 0) { - enumerate_bus(-1, 0, callback, true); - return; - } - // Multiple PCI host controllers. - for (int bus = 0; bus < 256; ++bus) { - if (read16_field(Address(0, 0, 0, bus), PCI_VENDOR_ID) == PCI_NONE) - break; - enumerate_bus(-1, bus, callback, false); + // First scan bus 0. Find any device on that bus, and if it's a PCI-to-PCI + // bridge, recursively scan it too. + m_enumerated_buses.set(0, true); + enumerate_bus(-1, 0, callback, true); + + // Handle Multiple PCI host bridges on slot 0, device 0. + // If we happen to miss some PCI buses because they are not reachable through + // recursive PCI-to-PCI bridges starting from bus 0, we might find them here. + if ((read8_field(Address(), PCI_HEADER_TYPE) & 0x80) != 0) { + for (int bus = 1; bus < 256; ++bus) { + if (read16_field(Address(0, 0, 0, bus), PCI_VENDOR_ID) == PCI_NONE) + continue; + if (read16_field(Address(0, 0, 0, bus), PCI_CLASS) != 0x6) + continue; + if (m_enumerated_buses.get(bus)) + continue; + enumerate_bus(-1, bus, callback, false); + m_enumerated_buses.set(bus, true); + } } } |