Skip to content

Commit

Permalink
Kernel/PCI: Cache more details about PCI devices when enumerating them
Browse files Browse the repository at this point in the history
There's no good reason to fetch these values each time we need them.
  • Loading branch information
supercomputer7 authored and awesomekling committed Sep 29, 2021
1 parent e22d9dc commit 82bb08a
Show file tree
Hide file tree
Showing 14 changed files with 85 additions and 41 deletions.
2 changes: 1 addition & 1 deletion Kernel/Bus/PCI/API.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ u8 read8(Address address, u32 field) { return Access::the().read8_field(address,
u16 read16(Address address, u32 field) { return Access::the().read16_field(address, field); }
u32 read32(Address address, u32 field) { return Access::the().read32_field(address, field); }

void enumerate(Function<void(Address, ID)> callback)
void enumerate(Function<void(Address, PhysicalID const&)> callback)
{
Access::the().fast_enumerate(callback);
}
Expand Down
2 changes: 1 addition & 1 deletion Kernel/Bus/PCI/API.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ u32 read32(Address address, u32 field);

ID get_id(PCI::Address);
bool is_io_space_enabled(Address);
void enumerate(Function<void(Address, ID)> callback);
void enumerate(Function<void(Address, PhysicalID const&)> callback);
void enable_interrupt_line(Address);
void disable_interrupt_line(Address);
u8 get_interrupt_line(Address);
Expand Down
13 changes: 10 additions & 3 deletions Kernel/Bus/PCI/Access.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,14 @@ UNMAP_AFTER_INIT void Access::enumerate_functions(int type, u8 bus, u8 device, u
Address address(0, bus, device, function);
auto read_type = (read8_field(address, PCI_CLASS) << 8u) | read8_field(address, PCI_SUBCLASS);
if (type == -1 || type == read_type) {
m_physical_ids.append(PhysicalID { address, { read16_field(address, PCI_VENDOR_ID), read16_field(address, PCI_DEVICE_ID) }, get_capabilities(address) });
PCI::ID id = { read16_field(address, PCI_VENDOR_ID), read16_field(address, PCI_DEVICE_ID) };
ClassCode class_code = read8_field(address, PCI_CLASS);
SubclassCode subclass_code = read8_field(address, PCI_SUBCLASS);
ProgrammingInterface prog_if = read8_field(address, PCI_PROG_IF);
RevisionID revision_id = read8_field(address, PCI_REVISION_ID);
SubsystemID subsystem_id = read16_field(address, PCI_SUBSYSTEM_ID);
SubsystemVendorID subsystem_vendor_id = read16_field(address, PCI_SUBSYSTEM_VENDOR_ID);
m_physical_ids.append(PhysicalID { address, id, revision_id, class_code, subclass_code, prog_if, subsystem_id, subsystem_vendor_id, get_capabilities(address) });
}

if (read_type == PCI_TYPE_BRIDGE && recursive && (!m_enumerated_buses.get(read8_field(address, PCI_SECONDARY_BUS)))) {
Expand Down Expand Up @@ -416,12 +423,12 @@ UNMAP_AFTER_INIT void Access::enumerate_bus(int type, u8 bus, bool recursive)
enumerate_device(type, bus, device, recursive);
}

void Access::fast_enumerate(Function<void(Address, ID)>& callback) const
void Access::fast_enumerate(Function<void(Address, PhysicalID const&)>& callback) const
{
MutexLocker locker(m_scan_lock);
VERIFY(!m_physical_ids.is_empty());
for (auto& physical_id : m_physical_ids) {
callback(physical_id.address(), physical_id.id());
callback(physical_id.address(), physical_id);
}
}

Expand Down
2 changes: 1 addition & 1 deletion Kernel/Bus/PCI/Access.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class Access {
static bool initialize_for_memory_access(PhysicalAddress mcfg_table);
static bool initialize_for_io_access();

void fast_enumerate(Function<void(Address, ID)>&) const;
void fast_enumerate(Function<void(Address, PhysicalID const&)>&) const;
void rescan_hardware();

static Access& the();
Expand Down
41 changes: 39 additions & 2 deletions Kernel/Bus/PCI/Definitions.h
Original file line number Diff line number Diff line change
Expand Up @@ -181,11 +181,25 @@ class Capability {
const u8 m_ptr;
};

TYPEDEF_DISTINCT_ORDERED_ID(u8, ClassCode);
TYPEDEF_DISTINCT_ORDERED_ID(u8, SubclassCode);
TYPEDEF_DISTINCT_ORDERED_ID(u8, ProgrammingInterface);
TYPEDEF_DISTINCT_ORDERED_ID(u8, RevisionID);
TYPEDEF_DISTINCT_ORDERED_ID(u16, SubsystemID);
TYPEDEF_DISTINCT_ORDERED_ID(u16, SubsystemVendorID);

class Access;
class PhysicalID {
public:
PhysicalID(Address address, ID id, Vector<Capability> capabilities)
PhysicalID(Address address, ID id, RevisionID revision_id, ClassCode class_code, SubclassCode subclass_code, ProgrammingInterface prog_if, SubsystemID subsystem_id, SubsystemVendorID subsystem_vendor_id, Vector<Capability> capabilities)
: m_address(address)
, m_id(id)
, m_revision_id(revision_id)
, m_class_code(class_code)
, m_subclass_code(subclass_code)
, m_prog_if(prog_if)
, m_subsystem_id(subsystem_id)
, m_subsystem_vendor_id(subsystem_vendor_id)
, m_capabilities(capabilities)
{
if constexpr (PCI_DEBUG) {
Expand All @@ -198,13 +212,36 @@ class PhysicalID {
const ID& id() const { return m_id; }
const Address& address() const { return m_address; }

RevisionID revision_id() const { return m_revision_id; }
ClassCode class_code() const { return m_class_code; }
SubclassCode subclass_code() const { return m_subclass_code; }
ProgrammingInterface prog_if() const { return m_prog_if; }
SubsystemID subsystem_id() const { return m_subsystem_id; }
SubsystemVendorID subsystem_vendor_id() const { return m_subsystem_vendor_id; }

void apply_subclass_code_change(Badge<Access>, SubclassCode new_subclass)
{
m_subclass_code = new_subclass;
}
void apply_prog_if_change(Badge<Access>, ProgrammingInterface new_progif)
{
m_prog_if = new_progif;
}

private:
Address m_address;
ID m_id;

RevisionID m_revision_id;
ClassCode m_class_code;
SubclassCode m_subclass_code;
ProgrammingInterface m_prog_if;
SubsystemID m_subsystem_id;
SubsystemVendorID m_subsystem_vendor_id;

Vector<Capability> m_capabilities;
};

class Access;
class Domain;
class Device;
}
Expand Down
4 changes: 2 additions & 2 deletions Kernel/Bus/PCI/Initializer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ UNMAP_AFTER_INIT void initialize()

PCI::PCIBusSysFSDirectory::initialize();

PCI::enumerate([&](const Address& address, ID id) {
dmesgln("{} {}", address, id);
PCI::enumerate([&](const Address& address, PhysicalID const& physical_id) {
dmesgln("{} {}", address, physical_id.id());
});
}

Expand Down
2 changes: 1 addition & 1 deletion Kernel/Bus/PCI/SysFSPCI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ UNMAP_AFTER_INIT void PCIBusSysFSDirectory::initialize()
UNMAP_AFTER_INIT PCIBusSysFSDirectory::PCIBusSysFSDirectory()
: SysFSDirectory("pci", SysFSComponentRegistry::the().buses_directory())
{
PCI::enumerate([&](const Address& address, ID) {
PCI::enumerate([&](const Address& address, PhysicalID const&) {
auto pci_device = PCI::PCIDeviceSysFSDirectory::create(*this, address);
m_components.append(pci_device);
});
Expand Down
14 changes: 7 additions & 7 deletions Kernel/Bus/USB/USBManagement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@ UNMAP_AFTER_INIT void USBManagement::enumerate_controllers()
if (kernel_command_line().disable_usb())
return;

PCI::enumerate([this](PCI::Address const& address, PCI::ID) {
if (!(PCI::get_class(address) == 0xc && PCI::get_subclass(address) == 0x3))
PCI::enumerate([this](PCI::Address const& address, PCI::PhysicalID const& physical_id) {
if (!(physical_id.class_code().value() == 0xc && physical_id.subclass_code().value() == 0x3))
return;
if (PCI::get_programming_interface(address) == 0x0) {
if (physical_id.prog_if().value() == 0x0) {
if (kernel_command_line().disable_uhci_controller())
return;

Expand All @@ -40,22 +40,22 @@ UNMAP_AFTER_INIT void USBManagement::enumerate_controllers()
return;
}

if (PCI::get_programming_interface(address) == 0x10) {
if (physical_id.prog_if().value() == 0x10) {
dmesgln("USBManagement: OHCI controller found at {} is not currently supported.", address);
return;
}

if (PCI::get_programming_interface(address) == 0x20) {
if (physical_id.prog_if().value() == 0x20) {
dmesgln("USBManagement: EHCI controller found at {} is not currently supported.", address);
return;
}

if (PCI::get_programming_interface(address) == 0x30) {
if (physical_id.prog_if().value() == 0x30) {
dmesgln("USBManagement: xHCI controller found at {} is not currently supported.", address);
return;
}

dmesgln("USBManagement: Unknown/unsupported controller at {} with programming interface 0x{:02x}", address, PCI::get_programming_interface(address));
dmesgln("USBManagement: Unknown/unsupported controller at {} with programming interface 0x{:02x}", address, physical_id.prog_if().value());
});
}

Expand Down
10 changes: 5 additions & 5 deletions Kernel/Bus/VirtIO/Device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,13 @@ UNMAP_AFTER_INIT void detect()
{
if (kernel_command_line().disable_virtio())
return;
PCI::enumerate([&](const PCI::Address& address, PCI::ID id) {
if (address.is_null() || id.is_null())
PCI::enumerate([&](const PCI::Address& address, PCI::PhysicalID const& physical_id) {
if (address.is_null() || physical_id.id().is_null())
return;
// TODO: We should also be checking that the device_id is in between 0x1000 - 0x107F inclusive
if (id.vendor_id != PCI::VendorID::VirtIO)
if (physical_id.id().vendor_id != PCI::VendorID::VirtIO)
return;
switch (id.device_id) {
switch (physical_id.id().device_id) {
case PCI::DeviceID::VirtIOConsole: {
auto& console = Console::must_create(address).leak_ref();
console.initialize();
Expand All @@ -40,7 +40,7 @@ UNMAP_AFTER_INIT void detect()
break;
}
default:
dbgln_if(VIRTIO_DEBUG, "VirtIO: Unknown VirtIO device with ID: {}", id.device_id);
dbgln_if(VIRTIO_DEBUG, "VirtIO: Unknown VirtIO device with ID: {}", physical_id.id().device_id);
break;
}
});
Expand Down
4 changes: 2 additions & 2 deletions Kernel/Devices/PCISerialDevice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@ static SerialDevice* s_the = nullptr;
UNMAP_AFTER_INIT void PCISerialDevice::detect()
{
size_t current_device_minor = 68;
PCI::enumerate([&](const PCI::Address& address, PCI::ID id) {
PCI::enumerate([&](const PCI::Address& address, PCI::PhysicalID const& physical_id) {
if (address.is_null())
return;

for (auto& board_definition : board_definitions) {
if (board_definition.device_id != id)
if (board_definition.device_id != physical_id.id())
continue;

auto bar_base = PCI::get_BAR(address, board_definition.pci_bar) & ~1;
Expand Down
16 changes: 8 additions & 8 deletions Kernel/GlobalProcessExposed.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -614,19 +614,19 @@ class ProcFSPCI final : public ProcFSGlobalInformation {
virtual KResult try_generate(KBufferBuilder& builder) override
{
JsonArraySerializer array { builder };
PCI::enumerate([&array](PCI::Address address, PCI::ID id) {
PCI::enumerate([&array](PCI::Address address, PCI::PhysicalID const& physical_id) {
auto obj = array.add_object();
obj.add("domain", address.domain());
obj.add("bus", address.bus());
obj.add("device", address.device());
obj.add("function", address.function());
obj.add("vendor_id", id.vendor_id);
obj.add("device_id", id.device_id);
obj.add("revision_id", PCI::get_revision_id(address));
obj.add("subclass", PCI::get_subclass(address));
obj.add("class", PCI::get_class(address));
obj.add("subsystem_id", PCI::get_subsystem_id(address));
obj.add("subsystem_vendor_id", PCI::get_subsystem_vendor_id(address));
obj.add("vendor_id", physical_id.id().vendor_id);
obj.add("device_id", physical_id.id().device_id);
obj.add("revision_id", physical_id.revision_id().value());
obj.add("subclass", physical_id.subclass_code().value());
obj.add("class", physical_id.class_code().value());
obj.add("subsystem_id", physical_id.subsystem_id().value());
obj.add("subsystem_vendor_id", physical_id.subsystem_vendor_id().value());
});
array.finish();
return KSuccess;
Expand Down
4 changes: 2 additions & 2 deletions Kernel/Graphics/GraphicsManagement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -179,13 +179,13 @@ UNMAP_AFTER_INIT bool GraphicsManagement::initialize()
dbgln("Forcing no initialization of framebuffer devices");
}

PCI::enumerate([&](const PCI::Address& address, PCI::ID id) {
PCI::enumerate([&](const PCI::Address& address, PCI::PhysicalID const& physical_id) {
// Note: Each graphics controller will try to set its native screen resolution
// upon creation. Later on, if we don't want to have framebuffer devices, a
// framebuffer console will take the control instead.
if (!is_vga_compatible_pci_device(address) && !is_display_controller_pci_device(address))
return;
determine_and_initialize_graphics_device(address, id);
determine_and_initialize_graphics_device(address, physical_id.id());
});

if (m_graphics_devices.is_empty()) {
Expand Down
4 changes: 2 additions & 2 deletions Kernel/Net/NetworkingManagement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,9 @@ UNMAP_AFTER_INIT RefPtr<NetworkAdapter> NetworkingManagement::determine_network_
bool NetworkingManagement::initialize()
{
if (!kernel_command_line().is_physical_networking_disabled()) {
PCI::enumerate([&](const PCI::Address& address, PCI::ID) {
PCI::enumerate([&](const PCI::Address& address, PCI::PhysicalID const& physical_id) {
// Note: PCI class 2 is the class of Network devices
if (PCI::get_class(address) != 0x02)
if (physical_id.class_code().value() != 0x02)
return;
if (auto adapter = determine_network_device(address); !adapter.is_null())
m_adapters.append(adapter.release_nonnull());
Expand Down
8 changes: 4 additions & 4 deletions Kernel/Storage/StorageManagement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,14 @@ UNMAP_AFTER_INIT void StorageManagement::enumerate_controllers(bool force_pio)
VERIFY(m_controllers.is_empty());
if (!kernel_command_line().disable_physical_storage()) {
if (kernel_command_line().is_ide_enabled()) {
PCI::enumerate([&](const PCI::Address& address, PCI::ID) {
if (PCI::get_class(address) == PCI_MASS_STORAGE_CLASS_ID && PCI::get_subclass(address) == PCI_IDE_CTRL_SUBCLASS_ID) {
PCI::enumerate([&](const PCI::Address& address, PCI::PhysicalID const& physical_id) {
if (physical_id.class_code().value() == PCI_MASS_STORAGE_CLASS_ID && physical_id.subclass_code().value() == PCI_IDE_CTRL_SUBCLASS_ID) {
m_controllers.append(IDEController::initialize(address, force_pio));
}
});
}
PCI::enumerate([&](const PCI::Address& address, PCI::ID) {
if (PCI::get_class(address) == PCI_MASS_STORAGE_CLASS_ID && PCI::get_subclass(address) == PCI_SATA_CTRL_SUBCLASS_ID && PCI::get_programming_interface(address) == PCI_AHCI_IF_PROGIF) {
PCI::enumerate([&](const PCI::Address& address, PCI::PhysicalID const& physical_id) {
if (physical_id.class_code().value() == PCI_MASS_STORAGE_CLASS_ID && physical_id.subclass_code().value() == PCI_SATA_CTRL_SUBCLASS_ID && physical_id.prog_if().value() == PCI_AHCI_IF_PROGIF) {
m_controllers.append(AHCIController::initialize(address));
}
});
Expand Down

0 comments on commit 82bb08a

Please sign in to comment.