mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-04-21 20:15:17 +00:00
Kernel/PCI: Fix support of multiple PCI host controllers enumeration
First scan PCI bus 0. Find any device on that bus, and if it's a PCI-to-PCI bridge, recursively scan it too. Then try to 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 scanning starting from bus 0, we might find them in this scanning.
This commit is contained in:
parent
c6ffee7f18
commit
07474b4349
Notes:
sideshowbarker
2024-07-18 17:37:30 +09:00
Author: https://github.com/supercomputer7 Commit: https://github.com/SerenityOS/serenity/commit/07474b43491 Pull-request: https://github.com/SerenityOS/serenity/pull/7340 Issue: https://github.com/SerenityOS/serenity/issues/7334 Reviewed-by: https://github.com/bgianfo Reviewed-by: https://github.com/boricj
3 changed files with 24 additions and 11 deletions
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue