diff options
39 files changed, 871 insertions, 1086 deletions
diff --git a/Kernel/ACPI/Parser.cpp b/Kernel/ACPI/Parser.cpp index 8e1404440d..0a7fb3e10c 100644 --- a/Kernel/ACPI/Parser.cpp +++ b/Kernel/ACPI/Parser.cpp @@ -10,7 +10,7 @@ #include <Kernel/ACPI/Parser.h> #include <Kernel/Arch/PC/BIOS.h> #include <Kernel/Arch/x86/InterruptDisabler.h> -#include <Kernel/Bus/PCI/Access.h> +#include <Kernel/Bus/PCI/API.h> #include <Kernel/Debug.h> #include <Kernel/IO.h> #include <Kernel/Memory/TypedMapping.h> diff --git a/Kernel/Bus/PCI/API.cpp b/Kernel/Bus/PCI/API.cpp new file mode 100644 index 0000000000..7c50fbfe00 --- /dev/null +++ b/Kernel/Bus/PCI/API.cpp @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <Kernel/Bus/PCI/API.h> +#include <Kernel/Bus/PCI/Access.h> +#include <Kernel/Sections.h> + +namespace Kernel::PCI { + +void write8(Address address, u32 field, u8 value) { Access::the().write8_field(address, field, value); } +void write16(Address address, u32 field, u16 value) { Access::the().write16_field(address, field, value); } +void write32(Address address, u32 field, u32 value) { Access::the().write32_field(address, field, value); } +u8 read8(Address address, u32 field) { return Access::the().read8_field(address, field); } +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) +{ + Access::the().fast_enumerate(callback); +} + +PhysicalID get_physical_id(Address address) +{ + return Access::the().get_physical_id(address); +} + +ID get_id(Address address) +{ + return { read16(address, PCI_VENDOR_ID), read16(address, PCI_DEVICE_ID) }; +} + +void enable_io_space(Address address) +{ + write16(address, PCI_COMMAND, read16(address, PCI_COMMAND) | (1 << 0)); +} +void disable_io_space(Address address) +{ + write16(address, PCI_COMMAND, read16(address, PCI_COMMAND) & ~(1 << 0)); +} + +void enable_memory_space(Address address) +{ + write16(address, PCI_COMMAND, read16(address, PCI_COMMAND) | (1 << 1)); +} +void disable_memory_space(Address address) +{ + write16(address, PCI_COMMAND, read16(address, PCI_COMMAND) & ~(1 << 1)); +} +bool is_io_space_enabled(Address address) +{ + return (read16(address, PCI_COMMAND) & 1) != 0; +} + +void enable_interrupt_line(Address address) +{ + write16(address, PCI_COMMAND, read16(address, PCI_COMMAND) & ~(1 << 10)); +} + +void disable_interrupt_line(Address address) +{ + write16(address, PCI_COMMAND, read16(address, PCI_COMMAND) | 1 << 10); +} + +u8 get_interrupt_line(Address address) +{ + return read8(address, PCI_INTERRUPT_LINE); +} + +u32 get_BAR0(Address address) +{ + return read32(address, PCI_BAR0); +} + +u32 get_BAR1(Address address) +{ + return read32(address, PCI_BAR1); +} + +u32 get_BAR2(Address address) +{ + return read32(address, PCI_BAR2); +} + +u32 get_BAR3(Address address) +{ + return read16(address, PCI_BAR3); +} + +u32 get_BAR4(Address address) +{ + return read32(address, PCI_BAR4); +} + +u32 get_BAR5(Address address) +{ + return read32(address, PCI_BAR5); +} + +u32 get_BAR(Address address, u8 bar) +{ + VERIFY(bar <= 5); + switch (bar) { + case 0: + return get_BAR0(address); + case 1: + return get_BAR1(address); + case 2: + return get_BAR2(address); + case 3: + return get_BAR3(address); + case 4: + return get_BAR4(address); + case 5: + return get_BAR5(address); + default: + VERIFY_NOT_REACHED(); + } +} + +u8 get_revision_id(Address address) +{ + return read8(address, PCI_REVISION_ID); +} + +u8 get_subclass(Address address) +{ + return read8(address, PCI_SUBCLASS); +} + +u8 get_class(Address address) +{ + return read8(address, PCI_CLASS); +} + +u8 get_programming_interface(Address address) +{ + return read8(address, PCI_PROG_IF); +} + +u16 get_subsystem_id(Address address) +{ + return read16(address, PCI_SUBSYSTEM_ID); +} + +u16 get_subsystem_vendor_id(Address address) +{ + return read16(address, PCI_SUBSYSTEM_VENDOR_ID); +} + +void enable_bus_mastering(Address address) +{ + auto value = read16(address, PCI_COMMAND); + value |= (1 << 2); + value |= (1 << 0); + write16(address, PCI_COMMAND, value); +} + +void disable_bus_mastering(Address address) +{ + auto value = read16(address, PCI_COMMAND); + value &= ~(1 << 2); + value |= (1 << 0); + write16(address, PCI_COMMAND, value); +} + +size_t get_BAR_space_size(Address address, u8 bar_number) +{ + // See PCI Spec 2.3, Page 222 + VERIFY(bar_number < 6); + u8 field = (PCI_BAR0 + (bar_number << 2)); + u32 bar_reserved = read32(address, field); + write32(address, field, 0xFFFFFFFF); + u32 space_size = read32(address, field); + write32(address, field, bar_reserved); + space_size &= 0xfffffff0; + space_size = (~space_size) + 1; + return space_size; +} + +void raw_access(Address address, u32 field, size_t access_size, u32 value) +{ + VERIFY(access_size != 0); + if (access_size == 1) { + write8(address, field, value); + return; + } + if (access_size == 2) { + write16(address, field, value); + return; + } + if (access_size == 4) { + write32(address, field, value); + return; + } + VERIFY_NOT_REACHED(); +} + +u8 Capability::read8(u32 field) const +{ + return PCI::read8(m_address, m_ptr + field); +} + +u16 Capability::read16(u32 field) const +{ + return PCI::read16(m_address, m_ptr + field); +} + +u32 Capability::read32(u32 field) const +{ + return PCI::read32(m_address, m_ptr + field); +} + +void Capability::write8(u32 field, u8 value) +{ + PCI::write8(m_address, m_ptr + field, value); +} + +void Capability::write16(u32 field, u16 value) +{ + PCI::write16(m_address, m_ptr + field, value); +} + +void Capability::write32(u32 field, u32 value) +{ + PCI::write32(m_address, m_ptr + field, value); +} + +} diff --git a/Kernel/Bus/PCI/API.h b/Kernel/Bus/PCI/API.h new file mode 100644 index 0000000000..6d23a6e594 --- /dev/null +++ b/Kernel/Bus/PCI/API.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include <Kernel/Bus/PCI/Definitions.h> + +namespace Kernel::PCI { + +void write8(Address address, u32 field, u8 value); +void write16(Address address, u32 field, u16 value); +void write32(Address address, u32 field, u32 value); +u8 read8(Address address, u32 field); +u16 read16(Address address, u32 field); +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 enable_interrupt_line(Address); +void disable_interrupt_line(Address); +u8 get_interrupt_line(Address); +void raw_access(Address, u32, size_t, u32); +u32 get_BAR0(Address); +u32 get_BAR1(Address); +u32 get_BAR2(Address); +u32 get_BAR3(Address); +u32 get_BAR4(Address); +u32 get_BAR5(Address); +u32 get_BAR(Address address, u8 bar); +u8 get_revision_id(Address); +u8 get_programming_interface(Address); +u8 get_subclass(Address); +u8 get_class(Address); +u16 get_subsystem_id(Address); +u16 get_subsystem_vendor_id(Address); +size_t get_BAR_space_size(Address, u8); +void enable_bus_mastering(Address); +void disable_bus_mastering(Address); +void enable_io_space(Address); +void disable_io_space(Address); +void enable_memory_space(Address); +void disable_memory_space(Address); +PhysicalID get_physical_id(Address address); + +} diff --git a/Kernel/Bus/PCI/Access.cpp b/Kernel/Bus/PCI/Access.cpp index b99a58808a..018de241a4 100644 --- a/Kernel/Bus/PCI/Access.cpp +++ b/Kernel/Bus/PCI/Access.cpp @@ -4,23 +4,23 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include <AK/ByteReader.h> +#include <AK/HashTable.h> +#include <Kernel/ACPI/Definitions.h> +#include <Kernel/API/KResult.h> #include <Kernel/Bus/PCI/Access.h> -#include <Kernel/Bus/PCI/IOAccess.h> #include <Kernel/Debug.h> #include <Kernel/IO.h> +#include <Kernel/Memory/MemoryManager.h> +#include <Kernel/Memory/Region.h> #include <Kernel/Sections.h> -namespace Kernel { -namespace PCI { +namespace Kernel::PCI { -static Access* s_access; +#define PCI_MMIO_CONFIG_SPACE_SIZE 4096 +#define MEMORY_RANGE_PER_BUS (PCI_MMIO_CONFIG_SPACE_SIZE * PCI_MAX_FUNCTIONS_PER_DEVICE * PCI_MAX_DEVICES_PER_BUS) -inline void write8(Address address, u32 field, u8 value) { Access::the().write8_field(address, field, value); } -inline void write16(Address address, u32 field, u16 value) { Access::the().write16_field(address, field, value); } -inline void write32(Address address, u32 field, u32 value) { Access::the().write32_field(address, field, value); } -inline u8 read8(Address address, u32 field) { return Access::the().read8_field(address, field); } -inline u16 read16(Address address, u32 field) { return Access::the().read16_field(address, field); } -inline u32 read32(Address address, u32 field) { return Access::the().read32_field(address, field); } +static Access* s_access; Access& Access::the() { @@ -35,419 +35,407 @@ bool Access::is_initialized() return (s_access != nullptr); } -UNMAP_AFTER_INIT Access::Access() - : m_enumerated_buses(256, false) +UNMAP_AFTER_INIT bool Access::initialize_for_memory_access(PhysicalAddress mcfg_table) { - s_access = this; -} + if (Access::is_initialized()) + return false; -PhysicalID Access::get_physical_id(Address address) const -{ - for (auto physical_id : m_physical_ids) { - if (physical_id.address().seg() == address.seg() - && physical_id.address().bus() == address.bus() - && physical_id.address().device() == address.device() - && physical_id.address().function() == address.function()) { - return physical_id; - } - } - VERIFY_NOT_REACHED(); + InterruptDisabler disabler; + auto* access = new Access(Access::AccessType::Memory); + if (!access->scan_pci_domains(mcfg_table)) + return false; + access->rescan_hardware(); + dbgln_if(PCI_DEBUG, "PCI: MMIO access initialised."); + return true; } -u8 Access::early_read8_field(Address address, u32 field) +UNMAP_AFTER_INIT bool Access::scan_pci_domains(PhysicalAddress mcfg_table) { - dbgln_if(PCI_DEBUG, "PCI: Early reading 8-bit field {:#08x} for {}", field, address); - IO::out32(PCI_ADDRESS_PORT, address.io_address_for_field(field)); - return IO::in8(PCI_VALUE_PORT + (field & 3)); -} + auto checkup_region_or_error = MM.allocate_kernel_region(mcfg_table.page_base(), (PAGE_SIZE * 2), "PCI MCFG Checkup", Memory::Region::Access::ReadWrite); + if (checkup_region_or_error.is_error()) + return false; + dbgln_if(PCI_DEBUG, "PCI: Checking MCFG Table length to choose the correct mapping size"); + auto* sdt = (ACPI::Structures::SDTHeader*)checkup_region_or_error.value()->vaddr().offset(mcfg_table.offset_in_page()).as_ptr(); + u32 length = sdt->length; + u8 revision = sdt->revision; -u16 Access::early_read16_field(Address address, u32 field) -{ - dbgln_if(PCI_DEBUG, "PCI: Early reading 16-bit field {:#08x} for {}", field, address); - IO::out32(PCI_ADDRESS_PORT, address.io_address_for_field(field)); - return IO::in16(PCI_VALUE_PORT + (field & 2)); -} + dbgln("PCI: MCFG, length: {}, revision: {}", length, revision); -u32 Access::early_read32_field(Address address, u32 field) -{ - dbgln_if(PCI_DEBUG, "PCI: Early reading 32-bit field {:#08x} for {}", field, address); - IO::out32(PCI_ADDRESS_PORT, address.io_address_for_field(field)); - return IO::in32(PCI_VALUE_PORT); -} + auto mcfg_region_or_error = MM.allocate_kernel_region(mcfg_table.page_base(), Memory::page_round_up(length) + PAGE_SIZE, "PCI Parsing MCFG", Memory::Region::Access::ReadWrite); + if (mcfg_region_or_error.is_error()) + return false; + auto& mcfg = *(ACPI::Structures::MCFG*)mcfg_region_or_error.value()->vaddr().offset(mcfg_table.offset_in_page()).as_ptr(); + dbgln_if(PCI_DEBUG, "PCI: Checking MCFG @ {}, {}", VirtualAddress(&mcfg), mcfg_table); + for (u32 index = 0; index < ((mcfg.header.length - sizeof(ACPI::Structures::MCFG)) / sizeof(ACPI::Structures::PCI_MMIO_Descriptor)); index++) { + u8 start_bus = mcfg.descriptors[index].start_pci_bus; + u8 end_bus = mcfg.descriptors[index].end_pci_bus; + u32 lower_addr = mcfg.descriptors[index].base_addr; -u16 Access::early_read_type(Address address) -{ - dbgln_if(PCI_DEBUG, "PCI: Early reading type for {}", address); - return (early_read8_field(address, PCI_CLASS) << 8u) | early_read8_field(address, PCI_SUBCLASS); -} - -UNMAP_AFTER_INIT void Access::enumerate_functions(int type, u8 bus, u8 device, u8 function, Function<void(Address, ID)>& callback, bool recursive) -{ - dbgln_if(PCI_DEBUG, "PCI: Enumerating function type={}, bus={}, device={}, function={}", type, bus, device, function); - 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 && (!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); + auto result = m_domains.set(index, { PhysicalAddress(lower_addr), start_bus, end_bus }); + VERIFY(result == AK::HashSetResult::InsertedNewEntry); + dmesgln("PCI: New PCI domain @ {}, PCI buses ({}-{})", PhysicalAddress { lower_addr }, start_bus, end_bus); } + VERIFY(m_domains.contains(0)); + dmesgln("PCI: MMIO domain: {}", m_domains.size()); + return true; } -UNMAP_AFTER_INIT void Access::enumerate_device(int type, u8 bus, u8 device, Function<void(Address, ID)>& callback, bool recursive) +UNMAP_AFTER_INIT bool Access::initialize_for_io_access() { - dbgln_if(PCI_DEBUG, "PCI: Enumerating device type={}, bus={}, device={}", type, bus, device); - Address address(0, bus, device, 0); - if (early_read16_field(address, PCI_VENDOR_ID) == PCI_NONE) - return; - enumerate_functions(type, bus, device, 0, callback, recursive); - if (!(early_read8_field(address, PCI_HEADER_TYPE) & 0x80)) - return; - for (u8 function = 1; function < 8; ++function) { - Address address(0, bus, device, function); - if (early_read16_field(address, PCI_VENDOR_ID) != PCI_NONE) - enumerate_functions(type, bus, device, function, callback, recursive); + if (Access::is_initialized()) { + return false; } + auto* access = new Access(Access::AccessType::IO); + access->rescan_hardware(); + dbgln_if(PCI_DEBUG, "PCI: IO access initialised."); + return true; } -UNMAP_AFTER_INIT void Access::enumerate_bus(int type, u8 bus, Function<void(Address, ID)>& callback, bool recursive) -{ - dbgln_if(PCI_DEBUG, "PCI: Enumerating bus type={}, bus={}", type, bus); - for (u8 device = 0; device < 32; ++device) - enumerate_device(type, bus, device, callback, recursive); -} - -void Access::enumerate(Function<void(Address, ID)>& callback) const -{ - for (auto& physical_id : m_physical_ids) { - callback(physical_id.address(), physical_id.id()); - } -} - -void enumerate(Function<void(Address, ID)> callback) -{ - Access::the().enumerate(callback); -} - -UNMAP_AFTER_INIT Optional<u8> get_capabilities_pointer(Address address) -{ - dbgln_if(PCI_DEBUG, "PCI: Getting capabilities pointer for {}", address); - if (PCI::read16(address, PCI_STATUS) & (1 << 4)) { - dbgln_if(PCI_DEBUG, "PCI: Found capabilities pointer for {}", address); - return PCI::read8(address, PCI_CAPABILITIES_POINTER); - } - dbgln_if(PCI_DEBUG, "PCI: No capabilities pointer for {}", address); - return {}; -} - -PhysicalID get_physical_id(Address address) +UNMAP_AFTER_INIT Access::Access(AccessType access_type) + : m_enumerated_buses(256, false) + , m_access_type(access_type) { - return Access::the().get_physical_id(address); + if (access_type == AccessType::IO) + dmesgln("PCI: Using I/O instructions for PCI configuration space access"); + else + dmesgln("PCI: Using memory access for PCI configuration space accesses"); + s_access = this; } -UNMAP_AFTER_INIT Vector<Capability> get_capabilities(Address address) +Optional<PhysicalAddress> Access::determine_memory_mapped_bus_base_address(u32 domain, u8 bus) const { - dbgln_if(PCI_DEBUG, "PCI: Getting capabilities for {}", address); - auto capabilities_pointer = PCI::get_capabilities_pointer(address); - if (!capabilities_pointer.has_value()) { - dbgln_if(PCI_DEBUG, "PCI: No capabilities for {}", address); + auto chosen_domain = m_domains.get(domain); + if (!chosen_domain.has_value()) return {}; - } - Vector<Capability> capabilities; - auto capability_pointer = capabilities_pointer.value(); - while (capability_pointer != 0) { - dbgln_if(PCI_DEBUG, "PCI: Reading in capability at {:#02x} for {}", capability_pointer, address); - u16 capability_header = PCI::read16(address, capability_pointer); - u8 capability_id = capability_header & 0xff; - capabilities.append({ address, capability_id, capability_pointer }); - capability_pointer = capability_header >> 8; - } - return capabilities; + if (!(chosen_domain.value().start_bus() <= bus && bus <= chosen_domain.value().end_bus())) + return {}; + return chosen_domain.value().paddr().offset(MEMORY_RANGE_PER_BUS * (bus - chosen_domain.value().start_bus())); } -void raw_access(Address address, u32 field, size_t access_size, u32 value) +void Access::map_bus_region(u32 domain, u8 bus) { - VERIFY(access_size != 0); - if (access_size == 1) { - write8(address, field, value); - return; - } - if (access_size == 2) { - write16(address, field, value); - return; - } - if (access_size == 4) { - write32(address, field, value); + VERIFY(m_access_lock.is_locked()); + if (m_mapped_bus == bus && m_mapped_bus_region) return; - } - VERIFY_NOT_REACHED(); -} - -ID get_id(Address address) -{ - return { read16(address, PCI_VENDOR_ID), read16(address, PCI_DEVICE_ID) }; + auto bus_base_address = determine_memory_mapped_bus_base_address(domain, bus); + // FIXME: Find a way to propagate error from here. + if (!bus_base_address.has_value()) + VERIFY_NOT_REACHED(); + auto region_or_error = MM.allocate_kernel_region(bus_base_address.value(), MEMORY_RANGE_PER_BUS, "PCI ECAM", Memory::Region::Access::ReadWrite); + // FIXME: Find a way to propagate error from here. + if (region_or_error.is_error()) + VERIFY_NOT_REACHED(); + m_mapped_bus_region = region_or_error.release_value(); + m_mapped_bus = bus; + dbgln_if(PCI_DEBUG, "PCI: New PCI ECAM Mapped region for bus {} @ {} {}", bus, m_mapped_bus_region->vaddr(), m_mapped_bus_region->physical_page(0)->paddr()); } -void enable_io_space(Address address) -{ - write16(address, PCI_COMMAND, read16(address, PCI_COMMAND) | (1 << 0)); -} -void disable_io_space(Address address) +VirtualAddress Access::get_device_configuration_memory_mapped_space(Address address) { - write16(address, PCI_COMMAND, read16(address, PCI_COMMAND) & ~(1 << 0)); + VERIFY(m_access_lock.is_locked()); + dbgln_if(PCI_DEBUG, "PCI: Getting device configuration space for {}", address); + map_bus_region(address.domain(), address.bus()); + return m_mapped_bus_region->vaddr().offset(PCI_MMIO_CONFIG_SPACE_SIZE * address.function() + (PCI_MMIO_CONFIG_SPACE_SIZE * PCI_MAX_FUNCTIONS_PER_DEVICE) * address.device()); } -void enable_memory_space(Address address) +u8 Access::io_read8_field(Address address, u32 field) { - write16(address, PCI_COMMAND, read16(address, PCI_COMMAND) | (1 << 1)); + MutexLocker lock(m_access_lock); + dbgln_if(PCI_DEBUG, "PCI: IO Reading 8-bit field {:#08x} for {}", field, address); + IO::out32(PCI_ADDRESS_PORT, address.io_address_for_field(field)); + return IO::in8(PCI_VALUE_PORT + (field & 3)); } -void disable_memory_space(Address address) +u16 Access::io_read16_field(Address address, u32 field) { - write16(address, PCI_COMMAND, read16(address, PCI_COMMAND) & ~(1 << 1)); + MutexLocker lock(m_access_lock); + dbgln_if(PCI_DEBUG, "PCI: IO Reading 16-bit field {:#08x} for {}", field, address); + IO::out32(PCI_ADDRESS_PORT, address.io_address_for_field(field)); + return IO::in16(PCI_VALUE_PORT + (field & 2)); } -bool is_io_space_enabled(Address address) +u32 Access::io_read32_field(Address address, u32 field) { - return (read16(address, PCI_COMMAND) & 1) != 0; + MutexLocker lock(m_access_lock); + dbgln_if(PCI_DEBUG, "PCI: IO Reading 32-bit field {:#08x} for {}", field, address); + IO::out32(PCI_ADDRESS_PORT, address.io_address_for_field(field)); + return IO::in32(PCI_VALUE_PORT); } - -void enable_interrupt_line(Address address) +void Access::io_write8_field(Address address, u32 field, u8 value) { - write16(address, PCI_COMMAND, read16(address, PCI_COMMAND) & ~(1 << 10)); + MutexLocker lock(m_access_lock); + dbgln_if(PCI_DEBUG, "PCI: IO Writing to 8-bit field {:#08x}, value={:#02x} for {}", field, value, address); + IO::out32(PCI_ADDRESS_PORT, address.io_address_for_field(field)); + IO::out8(PCI_VALUE_PORT + (field & 3), value); } - -void disable_interrupt_line(Address address) +void Access::io_write16_field(Address address, u32 field, u16 value) { - write16(address, PCI_COMMAND, read16(address, PCI_COMMAND) | 1 << 10); + MutexLocker lock(m_access_lock); + dbgln_if(PCI_DEBUG, "PCI: IO Writing to 16-bit field {:#08x}, value={:#02x} for {}", field, value, address); + IO::out32(PCI_ADDRESS_PORT, address.io_address_for_field(field)); + IO::out16(PCI_VALUE_PORT + (field & 2), value); } - -u8 get_interrupt_line(Address address) +void Access::io_write32_field(Address address, u32 field, u32 value) { - return read8(address, PCI_INTERRUPT_LINE); + MutexLocker lock(m_access_lock); + dbgln_if(PCI_DEBUG, "PCI: IO Writing to 32-bit field {:#08x}, value={:#02x} for {}", field, value, address); + IO::out32(PCI_ADDRESS_PORT, address.io_address_for_field(field)); + IO::out32(PCI_VALUE_PORT, value); } -u32 get_BAR0(Address address) +u8 Access::memory_read8_field(Address address, u32 field) { - return read32(address, PCI_BAR0); + MutexLocker lock(m_access_lock); + VERIFY(field <= 0xfff); + dbgln_if(PCI_DEBUG, "PCI: MMIO Reading 8-bit field {:#08x} for {}", field, address); + return *((volatile u8*)(get_device_configuration_memory_mapped_space(address).get() + (field & 0xfff))); } - -u32 get_BAR1(Address address) +u16 Access::memory_read16_field(Address address, u32 field) { - return read32(address, PCI_BAR1); + MutexLocker lock(m_access_lock); + VERIFY(field < 0xfff); + dbgln_if(PCI_DEBUG, "PCI: MMIO Reading 16-bit field {:#08x} for {}", field, address); + u16 data = 0; + ByteReader::load<u16>(get_device_configuration_memory_mapped_space(address).offset(field & 0xfff).as_ptr(), data); + return data; } - -u32 get_BAR2(Address address) +u32 Access::memory_read32_field(Address address, u32 field) { - return read32(address, PCI_BAR2); + MutexLocker lock(m_access_lock); + VERIFY(field <= 0xffc); + dbgln_if(PCI_DEBUG, "PCI: MMIO Reading 32-bit field {:#08x} for {}", field, address); + u32 data = 0; + ByteReader::load<u32>(get_device_configuration_memory_mapped_space(address).offset(field & 0xfff).as_ptr(), data); + return data; } - -u32 get_BAR3(Address address) +void Access::memory_write8_field(Address address, u32 field, u8 value) { - return read16(address, PCI_BAR3); + MutexLocker lock(m_access_lock); + VERIFY(field <= 0xfff); + dbgln_if(PCI_DEBUG, "PCI: MMIO Writing 8-bit field {:#08x}, value={:#02x} for {}", field, value, address); + *((volatile u8*)(get_device_configuration_memory_mapped_space(address).get() + (field & 0xfff))) = value; } - -u32 get_BAR4(Address address) +void Access::memory_write16_field(Address address, u32 field, u16 value) { - return read32(address, PCI_BAR4); + MutexLocker lock(m_access_lock); + VERIFY(field < 0xfff); + dbgln_if(PCI_DEBUG, "PCI: MMIO Writing 16-bit field {:#08x}, value={:#02x} for {}", field, value, address); + ByteReader::store<u16>(get_device_configuration_memory_mapped_space(address).offset(field & 0xfff).as_ptr(), value); } - -u32 get_BAR5(Address address) +void Access::memory_write32_field(Address address, u32 field, u32 value) { - return read32(address, PCI_BAR5); + MutexLocker lock(m_access_lock); + VERIFY(field <= 0xffc); + dbgln_if(PCI_DEBUG, "PCI: MMIO Writing 32-bit field {:#08x}, value={:#02x} for {}", field, value, address); + ByteReader::store<u32>(get_device_configuration_memory_mapped_space(address).offset(field & 0xfff).as_ptr(), value); } -u32 get_BAR(Address address, u8 bar) +void Access::write8_field(Address address, u32 field, u8 value) { - VERIFY(bar <= 5); - switch (bar) { - case 0: - return get_BAR0(address); - case 1: - return get_BAR1(address); - case 2: - return get_BAR2(address); - case 3: - return get_BAR3(address); - case 4: - return get_BAR4(address); - case 5: - return get_BAR5(address); - default: - VERIFY_NOT_REACHED(); + switch (m_access_type) { + case AccessType::IO: + io_write8_field(address, field, value); + return; + case AccessType::Memory: + memory_write8_field(address, field, value); + return; } + VERIFY_NOT_REACHED(); } - -u8 get_revision_id(Address address) -{ - return read8(address, PCI_REVISION_ID); -} - -u8 get_subclass(Address address) -{ - return read8(address, PCI_SUBCLASS); -} - -u8 get_class(Address address) -{ - return read8(address, PCI_CLASS); -} - -u8 get_programming_interface(Address address) -{ - return read8(address, PCI_PROG_IF); -} - -u16 get_subsystem_id(Address address) -{ - return read16(address, PCI_SUBSYSTEM_ID); -} - -u16 get_subsystem_vendor_id(Address address) -{ - return read16(address, PCI_SUBSYSTEM_VENDOR_ID); -} - -void enable_bus_mastering(Address address) +void Access::write16_field(Address address, u32 field, u16 value) { - auto value = read16(address, PCI_COMMAND); - value |= (1 << 2); - value |= (1 << 0); - write16(address, PCI_COMMAND, value); -} - -void disable_bus_mastering(Address address) -{ - auto value = read16(address, PCI_COMMAND); - value &= ~(1 << 2); - value |= (1 << 0); - write16(address, PCI_COMMAND, value); -} - -size_t get_BAR_space_size(Address address, u8 bar_number) -{ - // See PCI Spec 2.3, Page 222 - VERIFY(bar_number < 6); - u8 field = (PCI_BAR0 + (bar_number << 2)); - u32 bar_reserved = read32(address, field); - write32(address, field, 0xFFFFFFFF); - u32 space_size = read32(address, field); - write32(address, field, bar_reserved); - space_size &= 0xfffffff0; - space_size = (~space_size) + 1; - return space_size; + switch (m_access_type) { + case AccessType::IO: + io_write16_field(address, field, value); + return; + case AccessType::Memory: + memory_write16_field(address, field, value); + return; + } + VERIFY_NOT_REACHED(); } - -u8 Capability::read8(u32 field) const +void Access::write32_field(Address address, u32 field, u32 value) { - return PCI::read8(m_address, m_ptr + field); + switch (m_access_type) { + case AccessType::IO: + io_write32_field(address, field, value); + return; + case AccessType::Memory: + memory_write32_field(address, field, value); + return; + } + VERIFY_NOT_REACHED(); } -u16 Capability::read16(u32 field) const +u8 Access::read8_field(Address address, u32 field) { - return PCI::read16(m_address, m_ptr + field); + switch (m_access_type) { + case AccessType::IO: + return io_read8_field(address, field); + case AccessType::Memory: + return memory_read8_field(address, field); + } + VERIFY_NOT_REACHED(); } - -u32 Capability::read32(u32 field) const +u16 Access::read16_field(Address address, u32 field) { - return PCI::read32(m_address, m_ptr + field); + switch (m_access_type) { + case AccessType::IO: + return io_read16_field(address, field); + case AccessType::Memory: + return memory_read16_field(address, field); + } + VERIFY_NOT_REACHED(); } - -void Capability::write8(u32 field, u8 value) +u32 Access::read32_field(Address address, u32 field) { - PCI::write8(m_address, m_ptr + field, value); + switch (m_access_type) { + case AccessType::IO: + return io_read32_field(address, field); + case AccessType::Memory: + return memory_read32_field(address, field); + } + VERIFY_NOT_REACHED(); } -void Capability::write16(u32 field, u16 value) -{ - PCI::write16(m_address, m_ptr + field, value); -} +UNMAP_AFTER_INIT void Access::rescan_hardware() +{ + MutexLocker locker(m_scan_lock); + VERIFY(m_physical_ids.is_empty()); + if (m_access_type == AccessType::IO) { + dbgln_if(PCI_DEBUG, "PCI: IO enumerating hardware"); + + // 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, 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, false); + m_enumerated_buses.set(bus, true); + } + } + return; + } + VERIFY(m_access_type == AccessType::Memory); + + for (u32 domain = 0; domain < m_domains.size(); domain++) { + dbgln_if(PCI_DEBUG, "PCI: Scan memory mapped domain {}", domain); + // Single PCI host controller. + if ((read8_field(Address(domain), PCI_HEADER_TYPE) & 0x80) == 0) { + enumerate_bus(-1, 0, true); + return; + } -void Capability::write32(u32 field, u32 value) -{ - PCI::write32(m_address, m_ptr + field, value); + // Multiple PCI host controllers. + for (u8 function = 0; function < 8; ++function) { + if (read16_field(Address(domain, 0, 0, function), PCI_VENDOR_ID) == PCI_NONE) + break; + enumerate_bus(-1, function, false); + } + } } -UNMAP_AFTER_INIT NonnullRefPtr<PCIDeviceSysFSDirectory> PCIDeviceSysFSDirectory::create(const SysFSDirectory& parent_directory, Address address) +UNMAP_AFTER_INIT Optional<u8> Access::get_capabilities_pointer(Address address) { - return adopt_ref(*new (nothrow) PCIDeviceSysFSDirectory(parent_directory, address)); + dbgln_if(PCI_DEBUG, "PCI: Getting capabilities pointer for {}", address); + if (read16_field(address, PCI_STATUS) & (1 << 4)) { + dbgln_if(PCI_DEBUG, "PCI: Found capabilities pointer for {}", address); + return read8_field(address, PCI_CAPABILITIES_POINTER); + } + dbgln_if(PCI_DEBUG, "PCI: No capabilities pointer for {}", address); + return {}; } -UNMAP_AFTER_INIT PCIDeviceSysFSDirectory::PCIDeviceSysFSDirectory(const SysFSDirectory& parent_directory, Address address) - : SysFSDirectory(String::formatted("{:04x}:{:02x}:{:02x}.{}", address.seg(), address.bus(), address.device(), address.function()), parent_directory) - , m_address(address) +UNMAP_AFTER_INIT Vector<Capability> Access::get_capabilities(Address address) { - m_components.append(PCIDeviceAttributeSysFSComponent::create("vendor", *this, PCI_VENDOR_ID, 2)); - m_components.append(PCIDeviceAttributeSysFSComponent::create("device_id", *this, PCI_DEVICE_ID, 2)); - m_components.append(PCIDeviceAttributeSysFSComponent::create("class", *this, PCI_CLASS, 1)); - m_components.append(PCIDeviceAttributeSysFSComponent::create("subclass", *this, PCI_SUBCLASS, 1)); - m_components.append(PCIDeviceAttributeSysFSComponent::create("revision", *this, PCI_REVISION_ID, 1)); - m_components.append(PCIDeviceAttributeSysFSComponent::create("progif", *this, PCI_PROG_IF, 1)); - m_components.append(PCIDeviceAttributeSysFSComponent::create("subsystem_vendor", *this, PCI_SUBSYSTEM_VENDOR_ID, 2)); - m_components.append(PCIDeviceAttributeSysFSComponent::create("subsystem_id", *this, PCI_SUBSYSTEM_ID, 2)); + dbgln_if(PCI_DEBUG, "PCI: Getting capabilities for {}", address); + auto capabilities_pointer = get_capabilities_pointer(address); + if (!capabilities_pointer.has_value()) { + dbgln_if(PCI_DEBUG, "PCI: No capabilities for {}", address); + return {}; + } + Vector<Capability> capabilities; + auto capability_pointer = capabilities_pointer.value(); + while (capability_pointer != 0) { + dbgln_if(PCI_DEBUG, "PCI: Reading in capability at {:#02x} for {}", capability_pointer, address); + u16 capability_header = read16_field(address, capability_pointer); + u8 capability_id = capability_header & 0xff; + capabilities.append({ address, capability_id, capability_pointer }); + capability_pointer = capability_header >> 8; + } + return capabilities; } -UNMAP_AFTER_INIT void PCIBusSysFSDirectory::initialize() +UNMAP_AFTER_INIT void Access::enumerate_functions(int type, u8 bus, u8 device, u8 function, bool recursive) { - auto pci_directory = adopt_ref(*new (nothrow) PCIBusSysFSDirectory()); - SysFSComponentRegistry::the().register_new_component(pci_directory); -} + dbgln_if(PCI_DEBUG, "PCI: Enumerating function type={}, bus={}, device={}, function={}", type, bus, device, function); + 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) }); + } -UNMAP_AFTER_INIT PCIBusSysFSDirectory::PCIBusSysFSDirectory() - : SysFSDirectory("pci", SysFSComponentRegistry::the().root_directory()) -{ - PCI::enumerate([&](const Address& address, ID) { - auto pci_device = PCI::PCIDeviceSysFSDirectory::create(*this, address); - m_components.append(pci_device); - }); + if (read_type == PCI_TYPE_BRIDGE && recursive && (!m_enumerated_buses.get(read8_field(address, PCI_SECONDARY_BUS)))) { + u8 secondary_bus = 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, recursive); + } } -NonnullRefPtr<PCIDeviceAttributeSysFSComponent> PCIDeviceAttributeSysFSComponent::create(String name, const PCIDeviceSysFSDirectory& device, size_t offset, size_t field_bytes_width) +UNMAP_AFTER_INIT void Access::enumerate_device(int type, u8 bus, u8 device, bool recursive) { - return adopt_ref(*new (nothrow) PCIDeviceAttributeSysFSComponent(name, device, offset, field_bytes_width)); + dbgln_if(PCI_DEBUG, "PCI: Enumerating device type={}, bus={}, device={}", type, bus, device); + Address address(0, bus, device, 0); + if (read16_field(address, PCI_VENDOR_ID) == PCI_NONE) + return; + enumerate_functions(type, bus, device, 0, recursive); + if (!(read8_field(address, PCI_HEADER_TYPE) & 0x80)) + return; + for (u8 function = 1; function < 8; ++function) { + Address address(0, bus, device, function); + if (read16_field(address, PCI_VENDOR_ID) != PCI_NONE) + enumerate_functions(type, bus, device, function, recursive); + } } -PCIDeviceAttributeSysFSComponent::PCIDeviceAttributeSysFSComponent(String name, const PCIDeviceSysFSDirectory& device, size_t offset, size_t field_bytes_width) - : SysFSComponent(name) - , m_device(device) - , m_offset(offset) - , m_field_bytes_width(field_bytes_width) +UNMAP_AFTER_INIT void Access::enumerate_bus(int type, u8 bus, bool recursive) { + dbgln_if(PCI_DEBUG, "PCI: Enumerating bus type={}, bus={}", type, bus); + for (u8 device = 0; device < 32; ++device) + enumerate_device(type, bus, device, recursive); } -KResultOr<size_t> PCIDeviceAttributeSysFSComponent::read_bytes(off_t offset, size_t count, UserOrKernelBuffer& buffer, FileDescription*) const +void Access::fast_enumerate(Function<void(Address, ID)>& callback) const { - auto blob = try_to_generate_buffer(); - if (!blob) - return KResult(EFAULT); - - if ((size_t)offset >= blob->size()) - return KSuccess; - - ssize_t nread = min(static_cast<off_t>(blob->size() - offset), static_cast<off_t>(count)); - if (!buffer.write(blob->data() + offset, nread)) - return KResult(EFAULT); - return nread; + 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()); + } } -OwnPtr<KBuffer> PCIDeviceAttributeSysFSComponent::try_to_generate_buffer() const +PhysicalID Access::get_physical_id(Address address) const { - String value; - switch (m_field_bytes_width) { - case 1: - value = String::formatted("{:#x}", PCI::read8(m_device->address(), m_offset)); - break; - case 2: - value = String::formatted("{:#x}", PCI::read16(m_device->address(), m_offset)); - break; - case 4: - value = String::formatted("{:#x}", PCI::read32(m_device->address(), m_offset)); - break; - default: - VERIFY_NOT_REACHED(); + for (auto physical_id : m_physical_ids) { + if (physical_id.address().domain() == address.domain() + && physical_id.address().bus() == address.bus() + && physical_id.address().device() == address.device() + && physical_id.address().function() == address.function()) { + return physical_id; + } } - - return KBuffer::try_create_with_bytes(value.substring_view(0).bytes()); -} + VERIFY_NOT_REACHED(); } + } diff --git a/Kernel/Bus/PCI/Access.h b/Kernel/Bus/PCI/Access.h index 6d1b3fc3eb..c0993f927b 100644 --- a/Kernel/Bus/PCI/Access.h +++ b/Kernel/Bus/PCI/Access.h @@ -14,77 +14,72 @@ namespace Kernel::PCI { -class PCIBusSysFSDirectory final : public SysFSDirectory { +class Access { public: - static void initialize(); - -private: - PCIBusSysFSDirectory(); -}; + enum class AccessType { + IO, + Memory, + }; -class PCIDeviceSysFSDirectory final : public SysFSDirectory { public: - static NonnullRefPtr<PCIDeviceSysFSDirectory> create(const SysFSDirectory&, Address); - const Address& address() const { return m_address; } + static bool initialize_for_memory_access(PhysicalAddress mcfg_table); + static bool initialize_for_io_access(); -private: - PCIDeviceSysFSDirectory(const SysFSDirectory&, Address); - - Address m_address; -}; - -class PCIDeviceAttributeSysFSComponent : public SysFSComponent { -public: - static NonnullRefPtr<PCIDeviceAttributeSysFSComponent> create(String name, const PCIDeviceSysFSDirectory& device, size_t offset, size_t field_bytes_width); - - virtual KResultOr<size_t> read_bytes(off_t, size_t, UserOrKernelBuffer&, FileDescription*) const override; - virtual ~PCIDeviceAttributeSysFSComponent() {}; - -protected: - virtual OwnPtr<KBuffer> try_to_generate_buffer() const; - PCIDeviceAttributeSysFSComponent(String name, const PCIDeviceSysFSDirectory& device, size_t offset, size_t field_bytes_width); - NonnullRefPtr<PCIDeviceSysFSDirectory> m_device; - size_t m_offset; - size_t m_field_bytes_width; -}; - -class Access { -public: - void enumerate(Function<void(Address, ID)>&) const; - - void enumerate_bus(int type, u8 bus, Function<void(Address, ID)>&, bool recursive); - void enumerate_functions(int type, u8 bus, u8 device, u8 function, Function<void(Address, ID)>& callback, bool recursive); - void enumerate_device(int type, u8 bus, u8 device, Function<void(Address, ID)>& callback, bool recursive); + void fast_enumerate(Function<void(Address, ID)>&) const; + void rescan_hardware(); static Access& the(); static bool is_initialized(); - virtual uint32_t segment_count() const = 0; - virtual uint8_t segment_start_bus(u32 segment) const = 0; - virtual uint8_t segment_end_bus(u32 segment) const = 0; - - virtual void write8_field(Address address, u32 field, u8 value) = 0; - virtual void write16_field(Address address, u32 field, u16 value) = 0; - virtual void write32_field(Address address, u32 field, u32 value) = 0; - - virtual u8 read8_field(Address address, u32 field) = 0; - virtual u16 read16_field(Address address, u32 field) = 0; - virtual u32 read32_field(Address address, u32 field) = 0; + void write8_field(Address address, u32 field, u8 value); + void write16_field(Address address, u32 field, u16 value); + void write32_field(Address address, u32 field, u32 value); + u8 read8_field(Address address, u32 field); + u16 read16_field(Address address, u32 field); + u32 read32_field(Address address, u32 field); PhysicalID get_physical_id(Address address) const; -protected: - virtual void enumerate_hardware(Function<void(Address, ID)>) = 0; - - u8 early_read8_field(Address address, u32 field); - u16 early_read16_field(Address address, u32 field); - u32 early_read32_field(Address address, u32 field); - u16 early_read_type(Address address); - - Access(); - virtual ~Access() = default; - - Vector<PhysicalID> m_physical_ids; +private: + void enumerate_bus(int type, u8 bus, bool recursive); + void enumerate_functions(int type, u8 bus, u8 device, u8 function, bool recursive); + void enumerate_device(int type, u8 bus, u8 device, bool recursive); + + explicit Access(AccessType); + bool scan_pci_domains(PhysicalAddress mcfg); + Vector<Capability> get_capabilities(Address); + Optional<u8> get_capabilities_pointer(Address address); + + // IO access (legacy) operations + u8 io_read8_field(Address address, u32 field); + u16 io_read16_field(Address address, u32 field); + u32 io_read32_field(Address address, u32 field); + void io_write8_field(Address address, u32, u8); + void io_write16_field(Address address, u32, u16); + void io_write32_field(Address address, u32, u32); + u16 io_read_type(Address address); + + // Memory-mapped access operations + void map_bus_region(u32 domain, u8 bus); + u8 memory_read8_field(Address address, u32 field); + u16 memory_read16_field(Address address, u32 field); + u32 memory_read32_field(Address address, u32 field); + void memory_write8_field(Address address, u32, u8); + void memory_write16_field(Address address, u32, u16); + void memory_write32_field(Address address, u32, u32); + u16 memory_read_type(Address address); + VirtualAddress get_device_configuration_memory_mapped_space(Address address); + Optional<PhysicalAddress> determine_memory_mapped_bus_base_address(u32 domain, u8 bus) const; + + // Data-members for accessing Memory mapped PCI devices' configuration spaces + u8 m_mapped_bus { 0 }; + OwnPtr<Memory::Region> m_mapped_bus_region; + HashMap<u32, PCI::Domain> m_domains; + + // General Data-members + mutable Mutex m_access_lock; + mutable Mutex m_scan_lock; Bitmap m_enumerated_buses; + AccessType m_access_type; + Vector<PhysicalID> m_physical_ids; }; - } diff --git a/Kernel/Bus/PCI/Definitions.h b/Kernel/Bus/PCI/Definitions.h index f3f3660f4b..cb2e67b119 100644 --- a/Kernel/Bus/PCI/Definitions.h +++ b/Kernel/Bus/PCI/Definitions.h @@ -75,18 +75,37 @@ struct ID { } }; +class Domain { +public: + Domain() = delete; + Domain(PhysicalAddress base_address, u8 start_bus, u8 end_bus) + : m_base_addr(base_address) + , m_start_bus(start_bus) + , m_end_bus(end_bus) + { + } + u8 start_bus() const { return m_start_bus; } + u8 end_bus() const { return m_end_bus; } + PhysicalAddress paddr() const { return m_base_addr; } + +private: + PhysicalAddress m_base_addr; + u8 m_start_bus; + u8 m_end_bus; +}; + struct Address { public: Address() = default; - Address(u16 seg) - : m_seg(seg) + Address(u32 domain) + : m_domain(domain) , m_bus(0) , m_device(0) , m_function(0) { } - Address(u16 seg, u8 bus, u8 device, u8 function) - : m_seg(seg) + Address(u32 domain, u8 bus, u8 device, u8 function) + : m_domain(domain) , m_bus(bus) , m_device(device) , m_function(function) @@ -94,7 +113,7 @@ public: } Address(const Address& address) - : m_seg(address.seg()) + : m_domain(address.domain()) , m_bus(address.bus()) , m_device(address.device()) , m_function(address.function()) @@ -114,14 +133,14 @@ public: { if (this == &other) return true; - return m_seg == other.m_seg && m_bus == other.m_bus && m_device == other.m_device && m_function == other.m_function; + return m_domain == other.m_domain && m_bus == other.m_bus && m_device == other.m_device && m_function == other.m_function; } bool operator!=(const Address& other) const { return !(*this == other); } - u16 seg() const { return m_seg; } + u16 domain() const { return m_domain; } u8 bus() const { return m_bus; } u8 device() const { return m_device; } u8 function() const { return m_function; } @@ -131,47 +150,13 @@ public: return 0x80000000u | (m_bus << 16u) | (m_device << 11u) | (m_function << 8u) | (field & 0xfc); } -protected: - u32 m_seg { 0 }; +private: + u32 m_domain { 0 }; u8 m_bus { 0 }; u8 m_device { 0 }; u8 m_function { 0 }; }; -struct ChangeableAddress : public Address { - ChangeableAddress() - : Address(0) - { - } - explicit ChangeableAddress(u16 seg) - : Address(seg) - { - } - ChangeableAddress(u16 seg, u8 bus, u8 device, u8 function) - : Address(seg, bus, device, function) - { - } - void set_seg(u16 seg) { m_seg = seg; } - void set_bus(u8 bus) { m_bus = bus; } - void set_device(u8 device) { m_device = device; } - void set_function(u8 function) { m_function = function; } - bool operator==(const Address& address) - { - if (m_seg == address.seg() && m_bus == address.bus() && m_device == address.device() && m_function == address.function()) - return true; - else - return false; - } - const ChangeableAddress& operator=(const Address& address) - { - set_seg(address.seg()); - set_bus(address.bus()); - set_device(address.device()); - set_function(address.function()); - return *this; - } -}; - class Capability { public: Capability(const Address& address, u8 id, u8 ptr) @@ -219,42 +204,8 @@ private: Vector<Capability> m_capabilities; }; -ID get_id(PCI::Address); -bool is_io_space_enabled(Address); -void enumerate(Function<void(Address, ID)> callback); -void enable_interrupt_line(Address); -void disable_interrupt_line(Address); -u8 get_interrupt_line(Address); -void raw_access(Address, u32, size_t, u32); -u32 get_BAR0(Address); -u32 get_BAR1(Address); -u32 get_BAR2(Address); -u32 get_BAR3(Address); -u32 get_BAR4(Address); -u32 get_BAR5(Address); -u32 get_BAR(Address address, u8 bar); -u8 get_revision_id(Address); -u8 get_programming_interface(Address); -u8 get_subclass(Address); -u8 get_class(Address); -u16 get_subsystem_id(Address); -u16 get_subsystem_vendor_id(Address); -size_t get_BAR_space_size(Address, u8); -Optional<u8> get_capabilities_pointer(Address); -Vector<Capability> get_capabilities(Address); -void enable_bus_mastering(Address); -void disable_bus_mastering(Address); -void enable_io_space(Address); -void disable_io_space(Address); -void enable_memory_space(Address); -void disable_memory_space(Address); -PhysicalID get_physical_id(Address address); - class Access; -class MMIOAccess; -class WindowedMMIOAccess; -class IOAccess; -class MMIOSegment; +class Domain; class Device; } @@ -266,7 +217,7 @@ struct AK::Formatter<Kernel::PCI::Address> : Formatter<FormatString> { { return Formatter<FormatString>::format( builder, - "PCI [{:04x}:{:02x}:{:02x}:{:02x}]", value.seg(), value.bus(), value.device(), value.function()); + "PCI [{:04x}:{:02x}:{:02x}:{:02x}]", value.domain(), value.bus(), value.device(), value.function()); } }; diff --git a/Kernel/Bus/PCI/Device.cpp b/Kernel/Bus/PCI/Device.cpp index 739336d014..e371f16ffb 100644 --- a/Kernel/Bus/PCI/Device.cpp +++ b/Kernel/Bus/PCI/Device.cpp @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include <Kernel/Bus/PCI/API.h> #include <Kernel/Bus/PCI/Device.h> namespace Kernel { diff --git a/Kernel/Bus/PCI/IOAccess.cpp b/Kernel/Bus/PCI/IOAccess.cpp deleted file mode 100644 index 37beb6db22..0000000000 --- a/Kernel/Bus/PCI/IOAccess.cpp +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (c) 2020, Liav A. <liavalb@hotmail.co.il> - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include <Kernel/Bus/PCI/IOAccess.h> -#include <Kernel/Debug.h> -#include <Kernel/IO.h> -#include <Kernel/Sections.h> - -namespace Kernel { -namespace PCI { - -UNMAP_AFTER_INIT void IOAccess::initialize() -{ - if (!Access::is_initialized()) { - new IOAccess(); - dbgln_if(PCI_DEBUG, "PCI: IO access initialised."); - } -} - -UNMAP_AFTER_INIT IOAccess::IOAccess() -{ - dmesgln("PCI: Using I/O instructions for PCI configuration space access"); - enumerate_hardware([&](const Address& address, ID id) { - m_physical_ids.append({ address, id, get_capabilities(address) }); - }); -} - -u8 IOAccess::read8_field(Address address, u32 field) -{ - dbgln_if(PCI_DEBUG, "PCI: IO Reading 8-bit field {:#08x} for {}", field, address); - return Access::early_read8_field(address, field); -} - -u16 IOAccess::read16_field(Address address, u32 field) -{ - dbgln_if(PCI_DEBUG, "PCI: IO Reading 16-bit field {:#08x} for {}", field, address); - return Access::early_read16_field(address, field); -} - -u32 IOAccess::read32_field(Address address, u32 field) -{ - dbgln_if(PCI_DEBUG, "PCI: IO Reading 32-bit field {:#08x} for {}", field, address); - return Access::early_read32_field(address, field); -} - -void IOAccess::write8_field(Address address, u32 field, u8 value) -{ - dbgln_if(PCI_DEBUG, "PCI: IO Writing to 8-bit field {:#08x}, value={:#02x} for {}", field, value, address); - IO::out32(PCI_ADDRESS_PORT, address.io_address_for_field(field)); - IO::out8(PCI_VALUE_PORT + (field & 3), value); -} -void IOAccess::write16_field(Address address, u32 field, u16 value) -{ - dbgln_if(PCI_DEBUG, "PCI: IO Writing to 16-bit field {:#08x}, value={:#02x} for {}", field, value, address); - IO::out32(PCI_ADDRESS_PORT, address.io_address_for_field(field)); - IO::out16(PCI_VALUE_PORT + (field & 2), value); -} -void IOAccess::write32_field(Address address, u32 field, u32 value) -{ - dbgln_if(PCI_DEBUG, "PCI: IO Writing to 32-bit field {:#08x}, value={:#02x} for {}", field, value, address); - IO::out32(PCI_ADDRESS_PORT, address.io_address_for_field(field)); - IO::out32(PCI_VALUE_PORT, value); -} - -void IOAccess::enumerate_hardware(Function<void(Address, ID)> callback) -{ - dbgln_if(PCI_DEBUG, "PCI: IO enumerating hardware"); - - // 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); - } - } -} - -} -} diff --git a/Kernel/Bus/PCI/IOAccess.h b/Kernel/Bus/PCI/IOAccess.h deleted file mode 100644 index 52033e3e6e..0000000000 --- a/Kernel/Bus/PCI/IOAccess.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2020, Liav A. <liavalb@hotmail.co.il> - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include <Kernel/Bus/PCI/Access.h> - -namespace Kernel { -namespace PCI { - -class IOAccess final : public PCI::Access { -public: - static void initialize(); - -protected: - IOAccess(); - -private: - virtual void enumerate_hardware(Function<void(Address, ID)>) override; - virtual uint32_t segment_count() const override { return 1; }; - virtual void write8_field(Address address, u32, u8) override final; - virtual void write16_field(Address address, u32, u16) override final; - virtual void write32_field(Address address, u32, u32) override final; - virtual u8 read8_field(Address address, u32) override; - virtual u16 read16_field(Address address, u32) override; - virtual u32 read32_field(Address address, u32) override; - - virtual uint8_t segment_start_bus(u32) const override { return 0x0; } - virtual uint8_t segment_end_bus(u32) const override { return 0xFF; } -}; - -} -} diff --git a/Kernel/Bus/PCI/Initializer.cpp b/Kernel/Bus/PCI/Initializer.cpp index ffcf449a64..4754ca3ff9 100644 --- a/Kernel/Bus/PCI/Initializer.cpp +++ b/Kernel/Bus/PCI/Initializer.cpp @@ -5,10 +5,10 @@ */ #include <Kernel/ACPI/Parser.h> -#include <Kernel/Bus/PCI/IOAccess.h> +#include <Kernel/Bus/PCI/API.h> +#include <Kernel/Bus/PCI/Access.h> #include <Kernel/Bus/PCI/Initializer.h> -#include <Kernel/Bus/PCI/MMIOAccess.h> -#include <Kernel/Bus/PCI/WindowedMMIOAccess.h> +#include <Kernel/Bus/PCI/SysFSPCI.h> #include <Kernel/CommandLine.h> #include <Kernel/IO.h> #include <Kernel/Panic.h> @@ -38,15 +38,16 @@ UNMAP_AFTER_INIT void initialize() auto boot_determined = kernel_command_line().pci_access_level(); switch (detect_optimal_access_type(boot_determined)) { - case PCIAccessLevel::MappingPerDevice: - WindowedMMIOAccess::initialize(ACPI::Parser::the()->find_table("MCFG")); + case PCIAccessLevel::MemoryAddressing: { + auto success = Access::initialize_for_memory_access(ACPI::Parser::the()->find_table("MCFG")); + VERIFY(success); break; - case PCIAccessLevel::MappingPerBus: - MMIOAccess::initialize(ACPI::Parser::the()->find_table("MCFG")); - break; - case PCIAccessLevel::IOAddressing: - IOAccess::initialize(); + } + case PCIAccessLevel::IOAddressing: { + auto success = Access::initialize_for_io_access(); + VERIFY(success); break; + } default: VERIFY_NOT_REACHED(); } diff --git a/Kernel/Bus/PCI/MMIOAccess.cpp b/Kernel/Bus/PCI/MMIOAccess.cpp deleted file mode 100644 index 9730c54143..0000000000 --- a/Kernel/Bus/PCI/MMIOAccess.cpp +++ /dev/null @@ -1,215 +0,0 @@ -/* - * Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il> - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include <AK/ByteReader.h> -#include <AK/Optional.h> -#include <Kernel/Arch/x86/InterruptDisabler.h> -#include <Kernel/Bus/PCI/MMIOAccess.h> -#include <Kernel/Debug.h> -#include <Kernel/Memory/MemoryManager.h> -#include <Kernel/Sections.h> - -namespace Kernel { -namespace PCI { - -#define MEMORY_RANGE_PER_BUS (PCI_MMIO_CONFIG_SPACE_SIZE * PCI_MAX_FUNCTIONS_PER_DEVICE * PCI_MAX_DEVICES_PER_BUS) - -u32 MMIOAccess::segment_count() const -{ - return m_segments.size(); -} - -u8 MMIOAccess::segment_start_bus(u32 seg) const -{ - auto segment = m_segments.get(seg); - VERIFY(segment.has_value()); - return segment.value().get_start_bus(); -} - -u8 MMIOAccess::segment_end_bus(u32 seg) const -{ - auto segment = m_segments.get(seg); - VERIFY(segment.has_value()); - return segment.value().get_end_bus(); -} - -PhysicalAddress MMIOAccess::determine_memory_mapped_bus_region(u32 segment, u8 bus) const -{ - VERIFY(bus >= segment_start_bus(segment) && bus <= segment_end_bus(segment)); - auto seg = m_segments.get(segment); - VERIFY(seg.has_value()); - return seg.value().get_paddr().offset(MEMORY_RANGE_PER_BUS * (bus - seg.value().get_start_bus())); -} - -UNMAP_AFTER_INIT void MMIOAccess::initialize(PhysicalAddress mcfg) -{ - if (!Access::is_initialized()) { - new MMIOAccess(mcfg); - dbgln_if(PCI_DEBUG, "PCI: MMIO access initialised."); - } -} - -UNMAP_AFTER_INIT MMIOAccess::MMIOAccess(PhysicalAddress p_mcfg) - : m_mcfg(p_mcfg) -{ - dmesgln("PCI: Using MMIO for PCI configuration space access"); - - auto checkup_region = MM.allocate_kernel_region(p_mcfg.page_base(), (PAGE_SIZE * 2), "PCI MCFG Checkup", Memory::Region::Access::ReadWrite).release_value(); - dbgln_if(PCI_DEBUG, "PCI: Checking MCFG Table length to choose the correct mapping size"); - auto* sdt = (ACPI::Structures::SDTHeader*)checkup_region->vaddr().offset(p_mcfg.offset_in_page()).as_ptr(); - u32 length = sdt->length; - u8 revision = sdt->revision; - - dbgln("PCI: MCFG, length: {}, revision: {}", length, revision); - checkup_region->unmap(); - - auto mcfg_region = MM.allocate_kernel_region(p_mcfg.page_base(), Memory::page_round_up(length) + PAGE_SIZE, "PCI Parsing MCFG", Memory::Region::Access::ReadWrite).release_value(); - - auto& mcfg = *(ACPI::Structures::MCFG*)mcfg_region->vaddr().offset(p_mcfg.offset_in_page()).as_ptr(); - dbgln_if(PCI_DEBUG, "PCI: Checking MCFG @ {}, {}", VirtualAddress(&mcfg), PhysicalAddress(p_mcfg.get())); - - for (u32 index = 0; index < ((mcfg.header.length - sizeof(ACPI::Structures::MCFG)) / sizeof(ACPI::Structures::PCI_MMIO_Descriptor)); index++) { - u8 start_bus = mcfg.descriptors[index].start_pci_bus; - u8 end_bus = mcfg.descriptors[index].end_pci_bus; - u32 lower_addr = mcfg.descriptors[index].base_addr; - - m_segments.set(index, { PhysicalAddress(lower_addr), start_bus, end_bus }); - dmesgln("PCI: New PCI segment @ {}, PCI buses ({}-{})", PhysicalAddress { lower_addr }, start_bus, end_bus); - } - mcfg_region->unmap(); - dmesgln("PCI: MMIO segments: {}", m_segments.size()); - - InterruptDisabler disabler; - VERIFY(m_segments.contains(0)); - - // Note: we need to map this region before enumerating the hardware and adding - // PCI::PhysicalID objects to the vector, because get_capabilities calls - // PCI::read16 which will need this region to be mapped. - u8 start_bus = m_segments.get(0).value().get_start_bus(); - m_mapped_region = MM.allocate_kernel_region(determine_memory_mapped_bus_region(0, start_bus), MEMORY_RANGE_PER_BUS, "PCI ECAM", Memory::Region::Access::ReadWrite).release_value(); - m_mapped_bus = start_bus; - dbgln_if(PCI_DEBUG, "PCI: First PCI ECAM Mapped region for starting bus {} @ {} {}", start_bus, m_mapped_region->vaddr(), m_mapped_region->physical_page(0)->paddr()); - - enumerate_hardware([&](const Address& address, ID id) { - m_physical_ids.append({ address, id, get_capabilities(address) }); - }); -} -void MMIOAccess::map_bus_region(u32 segment, u8 bus) -{ - VERIFY(m_access_lock.is_locked()); - if (m_mapped_bus == bus) - return; - m_mapped_region = MM.allocate_kernel_region(determine_memory_mapped_bus_region(segment, bus), MEMORY_RANGE_PER_BUS, "PCI ECAM", Memory::Region::Access::ReadWrite).release_value(); - m_mapped_bus = bus; - dbgln_if(PCI_DEBUG, "PCI: New PCI ECAM Mapped region for bus {} @ {} {}", bus, m_mapped_region->vaddr(), m_mapped_region->physical_page(0)->paddr()); -} - -VirtualAddress MMIOAccess::get_device_configuration_space(Address address) -{ - VERIFY(m_access_lock.is_locked()); - dbgln_if(PCI_DEBUG, "PCI: Getting device configuration space for {}", address); - map_bus_region(address.seg(), address.bus()); - return m_mapped_region->vaddr().offset(PCI_MMIO_CONFIG_SPACE_SIZE * address.function() + (PCI_MMIO_CONFIG_SPACE_SIZE * PCI_MAX_FUNCTIONS_PER_DEVICE) * address.device()); -} - -u8 MMIOAccess::read8_field(Address address, u32 field) -{ - SpinlockLocker lock(m_access_lock); - VERIFY(field <= 0xfff); - dbgln_if(PCI_DEBUG, "PCI: MMIO Reading 8-bit field {:#08x} for {}", field, address); - return *((volatile u8*)(get_device_configuration_space(address).get() + (field & 0xfff))); -} - -u16 MMIOAccess::read16_field(Address address, u32 field) -{ - SpinlockLocker lock(m_access_lock); - VERIFY(field < 0xfff); - dbgln_if(PCI_DEBUG, "PCI: MMIO Reading 16-bit field {:#08x} for {}", field, address); - u16 data = 0; - ByteReader::load<u16>(get_device_configuration_space(address).offset(field & 0xfff).as_ptr(), data); - return data; -} - -u32 MMIOAccess::read32_field(Address address, u32 field) -{ - SpinlockLocker lock(m_access_lock); - VERIFY(field <= 0xffc); - dbgln_if(PCI_DEBUG, "PCI: MMIO Reading 32-bit field {:#08x} for {}", field, address); - u32 data = 0; - ByteReader::load<u32>(get_device_configuration_space(address).offset(field & 0xfff).as_ptr(), data); - return data; -} - -void MMIOAccess::write8_field(Address address, u32 field, u8 value) -{ - SpinlockLocker lock(m_access_lock); - VERIFY(field <= 0xfff); - dbgln_if(PCI_DEBUG, "PCI: MMIO Writing 8-bit field {:#08x}, value={:#02x} for {}", field, value, address); - *((volatile u8*)(get_device_configuration_space(address).get() + (field & 0xfff))) = value; -} -void MMIOAccess::write16_field(Address address, u32 field, u16 value) -{ - SpinlockLocker lock(m_access_lock); - VERIFY(field < 0xfff); - dbgln_if(PCI_DEBUG, "PCI: MMIO Writing 16-bit field {:#08x}, value={:#02x} for {}", field, value, address); - ByteReader::store<u16>(get_device_configuration_space(address).offset(field & 0xfff).as_ptr(), value); -} -void MMIOAccess::write32_field(Address address, u32 field, u32 value) -{ - SpinlockLocker lock(m_access_lock); - VERIFY(field <= 0xffc); - dbgln_if(PCI_DEBUG, "PCI: MMIO Writing 32-bit field {:#08x}, value={:#02x} for {}", field, value, address); - ByteReader::store<u32>(get_device_configuration_space(address).offset(field & 0xfff).as_ptr(), value); -} - -void MMIOAccess::enumerate_hardware(Function<void(Address, ID)> callback) -{ - for (u16 seg = 0; seg < m_segments.size(); seg++) { - dbgln_if(PCI_DEBUG, "PCI: Enumerating Memory mapped IO segment {}", seg); - // Single PCI host controller. - if ((early_read8_field(Address(seg), PCI_HEADER_TYPE) & 0x80) == 0) { - enumerate_bus(-1, 0, callback, true); - return; - } - - // Multiple PCI host controllers. - for (u8 function = 0; function < 8; ++function) { - if (early_read16_field(Address(seg, 0, 0, function), PCI_VENDOR_ID) == PCI_NONE) - break; - enumerate_bus(-1, function, callback, false); - } - } -} - -MMIOAccess::MMIOSegment::MMIOSegment(PhysicalAddress segment_base_addr, u8 start_bus, u8 end_bus) - : m_base_addr(segment_base_addr) - , m_start_bus(start_bus) - , m_end_bus(end_bus) -{ -} - -u8 MMIOAccess::MMIOSegment::get_start_bus() const -{ - return m_start_bus; -} - -u8 MMIOAccess::MMIOSegment::get_end_bus() const -{ - return m_end_bus; -} - -size_t MMIOAccess::MMIOSegment::get_size() const -{ - return (PCI_MMIO_CONFIG_SPACE_SIZE * PCI_MAX_FUNCTIONS_PER_DEVICE * PCI_MAX_DEVICES_PER_BUS * (get_end_bus() - get_start_bus())); -} - -PhysicalAddress MMIOAccess::MMIOSegment::get_paddr() const -{ - return m_base_addr; -} - -} -} diff --git a/Kernel/Bus/PCI/MMIOAccess.h b/Kernel/Bus/PCI/MMIOAccess.h deleted file mode 100644 index f9ef6792d4..0000000000 --- a/Kernel/Bus/PCI/MMIOAccess.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il> - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include <AK/HashMap.h> -#include <AK/NonnullOwnPtrVector.h> -#include <AK/OwnPtr.h> -#include <AK/Types.h> -#include <Kernel/ACPI/Definitions.h> -#include <Kernel/Bus/PCI/Access.h> -#include <Kernel/Locking/Spinlock.h> -#include <Kernel/Memory/AnonymousVMObject.h> -#include <Kernel/Memory/PhysicalRegion.h> -#include <Kernel/Memory/Region.h> -#include <Kernel/Memory/VMObject.h> - -namespace Kernel { -namespace PCI { - -#define PCI_MMIO_CONFIG_SPACE_SIZE 4096 - -class MMIOAccess : public Access { -public: - class MMIOSegment { - public: - MMIOSegment(PhysicalAddress, u8, u8); - u8 get_start_bus() const; - u8 get_end_bus() const; - size_t get_size() const; - PhysicalAddress get_paddr() const; - - private: - PhysicalAddress m_base_addr; - u8 m_start_bus; - u8 m_end_bus; - }; - static void initialize(PhysicalAddress mcfg); - -private: - PhysicalAddress determine_memory_mapped_bus_region(u32 segment, u8 bus) const; - void map_bus_region(u32, u8); - VirtualAddress get_device_configuration_space(Address address); - Spinlock m_access_lock; - u8 m_mapped_bus { 0 }; - OwnPtr<Memory::Region> m_mapped_region; - -protected: - explicit MMIOAccess(PhysicalAddress mcfg); - - virtual u32 segment_count() const override; - virtual void enumerate_hardware(Function<void(Address, ID)>) override; - virtual void write8_field(Address address, u32, u8) override; - virtual void write16_field(Address address, u32, u16) override; - virtual void write32_field(Address address, u32, u32) override; - virtual u8 read8_field(Address address, u32) override; - virtual u16 read16_field(Address address, u32) override; - virtual u32 read32_field(Address address, u32) override; - - virtual u8 segment_start_bus(u32) const override; - virtual u8 segment_end_bus(u32) const override; - - PhysicalAddress m_mcfg; - HashMap<u16, MMIOSegment> m_segments; -}; - -} -} diff --git a/Kernel/Bus/PCI/SysFSPCI.cpp b/Kernel/Bus/PCI/SysFSPCI.cpp new file mode 100644 index 0000000000..ff90776cd5 --- /dev/null +++ b/Kernel/Bus/PCI/SysFSPCI.cpp @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <Kernel/Bus/PCI/API.h> +#include <Kernel/Bus/PCI/Access.h> +#include <Kernel/Bus/PCI/SysFSPCI.h> +#include <Kernel/Debug.h> +#include <Kernel/IO.h> +#include <Kernel/Sections.h> + +namespace Kernel::PCI { + +UNMAP_AFTER_INIT NonnullRefPtr<PCIDeviceSysFSDirectory> PCIDeviceSysFSDirectory::create(const SysFSDirectory& parent_directory, Address address) +{ + return adopt_ref(*new (nothrow) PCIDeviceSysFSDirectory(parent_directory, address)); +} + +UNMAP_AFTER_INIT PCIDeviceSysFSDirectory::PCIDeviceSysFSDirectory(const SysFSDirectory& parent_directory, Address address) + : SysFSDirectory(String::formatted("{:04x}:{:02x}:{:02x}.{}", address.domain(), address.bus(), address.device(), address.function()), parent_directory) + , m_address(address) +{ + m_components.append(PCIDeviceAttributeSysFSComponent::create("vendor", *this, PCI_VENDOR_ID, 2)); + m_components.append(PCIDeviceAttributeSysFSComponent::create("device_id", *this, PCI_DEVICE_ID, 2)); + m_components.append(PCIDeviceAttributeSysFSComponent::create("class", *this, PCI_CLASS, 1)); + m_components.append(PCIDeviceAttributeSysFSComponent::create("subclass", *this, PCI_SUBCLASS, 1)); + m_components.append(PCIDeviceAttributeSysFSComponent::create("revision", *this, PCI_REVISION_ID, 1)); + m_components.append(PCIDeviceAttributeSysFSComponent::create("progif", *this, PCI_PROG_IF, 1)); + m_components.append(PCIDeviceAttributeSysFSComponent::create("subsystem_vendor", *this, PCI_SUBSYSTEM_VENDOR_ID, 2)); + m_components.append(PCIDeviceAttributeSysFSComponent::create("subsystem_id", *this, PCI_SUBSYSTEM_ID, 2)); +} + +UNMAP_AFTER_INIT void PCIBusSysFSDirectory::initialize() +{ + auto pci_directory = adopt_ref(*new (nothrow) PCIBusSysFSDirectory()); + SysFSComponentRegistry::the().register_new_component(pci_directory); +} + +UNMAP_AFTER_INIT PCIBusSysFSDirectory::PCIBusSysFSDirectory() + : SysFSDirectory("pci", SysFSComponentRegistry::the().root_directory()) +{ + PCI::enumerate([&](const Address& address, ID) { + auto pci_device = PCI::PCIDeviceSysFSDirectory::create(*this, address); + m_components.append(pci_device); + }); +} + +NonnullRefPtr<PCIDeviceAttributeSysFSComponent> PCIDeviceAttributeSysFSComponent::create(String name, const PCIDeviceSysFSDirectory& device, size_t offset, size_t field_bytes_width) +{ + return adopt_ref(*new (nothrow) PCIDeviceAttributeSysFSComponent(name, device, offset, field_bytes_width)); +} + +PCIDeviceAttributeSysFSComponent::PCIDeviceAttributeSysFSComponent(String name, const PCIDeviceSysFSDirectory& device, size_t offset, size_t field_bytes_width) + : SysFSComponent(name) + , m_device(device) + , m_offset(offset) + , m_field_bytes_width(field_bytes_width) +{ +} + +KResultOr<size_t> PCIDeviceAttributeSysFSComponent::read_bytes(off_t offset, size_t count, UserOrKernelBuffer& buffer, FileDescription*) const +{ + auto blob = try_to_generate_buffer(); + if (!blob) + return KResult(EFAULT); + + if ((size_t)offset >= blob->size()) + return KSuccess; + + ssize_t nread = min(static_cast<off_t>(blob->size() - offset), static_cast<off_t>(count)); + if (!buffer.write(blob->data() + offset, nread)) + return KResult(EFAULT); + return nread; +} + +OwnPtr<KBuffer> PCIDeviceAttributeSysFSComponent::try_to_generate_buffer() const +{ + String value; + switch (m_field_bytes_width) { + case 1: + value = String::formatted("{:#x}", PCI::read8(m_device->address(), m_offset)); + break; + case 2: + value = String::formatted("{:#x}", PCI::read16(m_device->address(), m_offset)); + break; + case 4: + value = String::formatted("{:#x}", PCI::read32(m_device->address(), m_offset)); + break; + default: + VERIFY_NOT_REACHED(); + } + + return KBuffer::try_create_with_bytes(value.substring_view(0).bytes()); +} +} diff --git a/Kernel/Bus/PCI/SysFSPCI.h b/Kernel/Bus/PCI/SysFSPCI.h new file mode 100644 index 0000000000..c32eb094c5 --- /dev/null +++ b/Kernel/Bus/PCI/SysFSPCI.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include <AK/Bitmap.h> +#include <AK/String.h> +#include <AK/Vector.h> +#include <Kernel/Bus/PCI/Definitions.h> +#include <Kernel/FileSystem/SysFS.h> + +namespace Kernel::PCI { + +class PCIBusSysFSDirectory final : public SysFSDirectory { +public: + static void initialize(); + +private: + PCIBusSysFSDirectory(); +}; + +class PCIDeviceSysFSDirectory final : public SysFSDirectory { +public: + static NonnullRefPtr<PCIDeviceSysFSDirectory> create(const SysFSDirectory&, Address); + const Address& address() const { return m_address; } + +private: + PCIDeviceSysFSDirectory(const SysFSDirectory&, Address); + + Address m_address; +}; + +class PCIDeviceAttributeSysFSComponent : public SysFSComponent { +public: + static NonnullRefPtr<PCIDeviceAttributeSysFSComponent> create(String name, const PCIDeviceSysFSDirectory& device, size_t offset, size_t field_bytes_width); + + virtual KResultOr<size_t> read_bytes(off_t, size_t, UserOrKernelBuffer&, FileDescription*) const override; + virtual ~PCIDeviceAttributeSysFSComponent() {}; + +protected: + virtual OwnPtr<KBuffer> try_to_generate_buffer() const; + PCIDeviceAttributeSysFSComponent(String name, const PCIDeviceSysFSDirectory& device, size_t offset, size_t field_bytes_width); + NonnullRefPtr<PCIDeviceSysFSDirectory> m_device; + size_t m_offset; + size_t m_field_bytes_width; +}; + +} diff --git a/Kernel/Bus/PCI/WindowedMMIOAccess.cpp b/Kernel/Bus/PCI/WindowedMMIOAccess.cpp deleted file mode 100644 index 79e405b0af..0000000000 --- a/Kernel/Bus/PCI/WindowedMMIOAccess.cpp +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (c) 2020-2021, Liav A. <liavalb@hotmail.co.il> - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include <AK/ByteReader.h> -#include <AK/Optional.h> -#include <AK/StringView.h> -#include <Kernel/Arch/x86/InterruptDisabler.h> -#include <Kernel/Bus/PCI/WindowedMMIOAccess.h> -#include <Kernel/Debug.h> -#include <Kernel/Memory/MemoryManager.h> -#include <Kernel/Sections.h> - -namespace Kernel { -namespace PCI { - -UNMAP_AFTER_INIT DeviceConfigurationSpaceMapping::DeviceConfigurationSpaceMapping(Address device_address, const MMIOAccess::MMIOSegment& mmio_segment) - : m_device_address(device_address) - , m_mapped_region(MM.allocate_kernel_region(Memory::page_round_up(PCI_MMIO_CONFIG_SPACE_SIZE), "PCI MMIO Device Access", Memory::Region::Access::ReadWrite).release_value()) -{ - PhysicalAddress segment_lower_addr = mmio_segment.get_paddr(); - PhysicalAddress device_physical_mmio_space = segment_lower_addr.offset( - PCI_MMIO_CONFIG_SPACE_SIZE * m_device_address.function() + (PCI_MMIO_CONFIG_SPACE_SIZE * PCI_MAX_FUNCTIONS_PER_DEVICE) * m_device_address.device() + (PCI_MMIO_CONFIG_SPACE_SIZE * PCI_MAX_FUNCTIONS_PER_DEVICE * PCI_MAX_DEVICES_PER_BUS) * (m_device_address.bus() - mmio_segment.get_start_bus())); - m_mapped_region->physical_page_slot(0) = Memory::PhysicalPage::create(device_physical_mmio_space, Memory::MayReturnToFreeList::No); - m_mapped_region->remap(); -} - -UNMAP_AFTER_INIT void WindowedMMIOAccess::initialize(PhysicalAddress mcfg) -{ - if (!Access::is_initialized()) { - new WindowedMMIOAccess(mcfg); - dbgln_if(PCI_DEBUG, "PCI: MMIO access initialised."); - } -} - -UNMAP_AFTER_INIT WindowedMMIOAccess::WindowedMMIOAccess(PhysicalAddress p_mcfg) - : MMIOAccess(p_mcfg) -{ - dmesgln("PCI: Using MMIO (mapping per device) for PCI configuration space access"); - - InterruptDisabler disabler; - - enumerate_hardware([&](const Address& address, ID) { - m_mapped_device_regions.append(make<DeviceConfigurationSpaceMapping>(address, m_segments.get(address.seg()).value())); - }); -} - -Optional<VirtualAddress> WindowedMMIOAccess::get_device_configuration_space(Address address) -{ - dbgln_if(PCI_DEBUG, "PCI: Getting device configuration space for {}", address); - for (auto& mapping : m_mapped_device_regions) { - auto checked_address = mapping.address(); - dbgln_if(PCI_DEBUG, "PCI Device Configuration Space Mapping: Check if {} was requested", checked_address); - if (address.seg() == checked_address.seg() - && address.bus() == checked_address.bus() - && address.device() == checked_address.device() - && address.function() == checked_address.function()) { - dbgln_if(PCI_DEBUG, "PCI Device Configuration Space Mapping: Found {}", checked_address); - return mapping.vaddr(); - } - } - - dbgln_if(PCI_DEBUG, "PCI: No device configuration space found for {}", address); - return {}; -} - -u8 WindowedMMIOAccess::read8_field(Address address, u32 field) -{ - InterruptDisabler disabler; - VERIFY(field <= 0xfff); - dbgln_if(PCI_DEBUG, "PCI: MMIO Reading 8-bit field {:#08x} for {}", field, address); - return *((u8*)(get_device_configuration_space(address).value().get() + (field & 0xfff))); -} - -u16 WindowedMMIOAccess::read16_field(Address address, u32 field) -{ - InterruptDisabler disabler; - VERIFY(field < 0xfff); - dbgln_if(PCI_DEBUG, "PCI: MMIO Reading 16-bit field {:#08x} for {}", field, address); - u16 data = 0; - ByteReader::load<u16>(get_device_configuration_space(address).value().offset(field & 0xfff).as_ptr(), data); - return data; -} - -u32 WindowedMMIOAccess::read32_field(Address address, u32 field) -{ - InterruptDisabler disabler; - VERIFY(field <= 0xffc); - dbgln_if(PCI_DEBUG, "PCI: MMIO Reading 32-bit field {:#08x} for {}", field, address); - u32 data = 0; - ByteReader::load<u32>(get_device_configuration_space(address).value().offset(field & 0xfff).as_ptr(), data); - return data; -} - -void WindowedMMIOAccess::write8_field(Address address, u32 field, u8 value) -{ - InterruptDisabler disabler; - VERIFY(field <= 0xfff); - dbgln_if(PCI_DEBUG, "PCI: MMIO Writing 8-bit field {:#08x}, value={:#02x} for {}", field, value, address); - *((u8*)(get_device_configuration_space(address).value().get() + (field & 0xfff))) = value; -} -void WindowedMMIOAccess::write16_field(Address address, u32 field, u16 value) -{ - InterruptDisabler disabler; - VERIFY(field < 0xfff); - dbgln_if(PCI_DEBUG, "PCI: MMIO Writing 16-bit field {:#08x}, value={:#02x} for {}", field, value, address); - ByteReader::store<u16>(get_device_configuration_space(address).value().offset(field & 0xfff).as_ptr(), value); -} -void WindowedMMIOAccess::write32_field(Address address, u32 field, u32 value) -{ - InterruptDisabler disabler; - VERIFY(field <= 0xffc); - dbgln_if(PCI_DEBUG, "PCI: MMIO Writing 32-bit field {:#08x}, value={:#02x} for {}", field, value, address); - ByteReader::store<u32>(get_device_configuration_space(address).value().offset(field & 0xfff).as_ptr(), value); -} - -} -} diff --git a/Kernel/Bus/PCI/WindowedMMIOAccess.h b/Kernel/Bus/PCI/WindowedMMIOAccess.h deleted file mode 100644 index 0f4a51b5b7..0000000000 --- a/Kernel/Bus/PCI/WindowedMMIOAccess.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2020-2021, Liav A. <liavalb@hotmail.co.il> - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include <AK/HashMap.h> -#include <AK/NonnullOwnPtrVector.h> -#include <AK/OwnPtr.h> -#include <AK/Types.h> -#include <Kernel/ACPI/Definitions.h> -#include <Kernel/Bus/PCI/Access.h> -#include <Kernel/Bus/PCI/MMIOAccess.h> -#include <Kernel/Memory/AnonymousVMObject.h> -#include <Kernel/Memory/PhysicalRegion.h> -#include <Kernel/Memory/Region.h> -#include <Kernel/Memory/VMObject.h> - -namespace Kernel { -namespace PCI { - -class DeviceConfigurationSpaceMapping { -public: - DeviceConfigurationSpaceMapping(Address, const MMIOAccess::MMIOSegment&); - VirtualAddress vaddr() const { return m_mapped_region->vaddr(); }; - PhysicalAddress paddr() const { return m_mapped_region->physical_page(0)->paddr(); } - const Address& address() const { return m_device_address; }; - -private: - Address m_device_address; - NonnullOwnPtr<Memory::Region> m_mapped_region; -}; - -class WindowedMMIOAccess final : public MMIOAccess { -public: - static void initialize(PhysicalAddress mcfg); - -private: - explicit WindowedMMIOAccess(PhysicalAddress mcfg); - virtual void write8_field(Address address, u32, u8) override; - virtual void write16_field(Address address, u32, u16) override; - virtual void write32_field(Address address, u32, u32) override; - virtual u8 read8_field(Address address, u32) override; - virtual u16 read16_field(Address address, u32) override; - virtual u32 read32_field(Address address, u32) override; - - Optional<VirtualAddress> get_device_configuration_space(Address address); - NonnullOwnPtrVector<DeviceConfigurationSpaceMapping> m_mapped_device_regions; -}; - -} -} diff --git a/Kernel/Bus/USB/UHCI/UHCIController.cpp b/Kernel/Bus/USB/UHCI/UHCIController.cpp index b538b67a6d..9f8aa6a5e6 100644 --- a/Kernel/Bus/USB/UHCI/UHCIController.cpp +++ b/Kernel/Bus/USB/UHCI/UHCIController.cpp @@ -6,6 +6,7 @@ */ #include <AK/Platform.h> +#include <Kernel/Bus/PCI/API.h> #include <Kernel/Bus/USB/UHCI/UHCIController.h> #include <Kernel/Bus/USB/USBRequest.h> #include <Kernel/Debug.h> diff --git a/Kernel/Bus/USB/USBManagement.cpp b/Kernel/Bus/USB/USBManagement.cpp index 1b6c889fef..2486abc200 100644 --- a/Kernel/Bus/USB/USBManagement.cpp +++ b/Kernel/Bus/USB/USBManagement.cpp @@ -5,7 +5,7 @@ */ #include <AK/Singleton.h> -#include <Kernel/Bus/PCI/Access.h> +#include <Kernel/Bus/PCI/API.h> #include <Kernel/Bus/USB/SysFSUSB.h> #include <Kernel/Bus/USB/UHCI/UHCIController.h> #include <Kernel/Bus/USB/USBManagement.h> diff --git a/Kernel/Bus/VirtIO/Device.cpp b/Kernel/Bus/VirtIO/Device.cpp index 3089c9d722..aef08c126d 100644 --- a/Kernel/Bus/VirtIO/Device.cpp +++ b/Kernel/Bus/VirtIO/Device.cpp @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include <Kernel/Bus/PCI/API.h> #include <Kernel/Bus/PCI/IDs.h> #include <Kernel/Bus/VirtIO/Console.h> #include <Kernel/Bus/VirtIO/Device.h> diff --git a/Kernel/CMakeLists.txt b/Kernel/CMakeLists.txt index 94de737dac..41e13f95a4 100644 --- a/Kernel/CMakeLists.txt +++ b/Kernel/CMakeLists.txt @@ -27,11 +27,10 @@ set(KERNEL_SOURCES Arch/PC/BIOS.cpp Arch/x86/SmapDisabler.h Bus/PCI/Access.cpp + Bus/PCI/API.cpp Bus/PCI/Device.cpp - Bus/PCI/IOAccess.cpp - Bus/PCI/MMIOAccess.cpp Bus/PCI/Initializer.cpp - Bus/PCI/WindowedMMIOAccess.cpp + Bus/PCI/SysFSPCI.cpp Bus/USB/SysFSUSB.cpp Bus/USB/UHCI/UHCIController.cpp Bus/USB/UHCI/UHCIRootHub.cpp diff --git a/Kernel/CommandLine.cpp b/Kernel/CommandLine.cpp index 5eed0bd8b0..890603d576 100644 --- a/Kernel/CommandLine.cpp +++ b/Kernel/CommandLine.cpp @@ -114,9 +114,7 @@ UNMAP_AFTER_INIT PCIAccessLevel CommandLine::pci_access_level() const { auto value = lookup("pci_ecam"sv).value_or("off"sv); if (value == "on"sv) - return PCIAccessLevel::MappingPerBus; - if (value == "per-device"sv) - return PCIAccessLevel::MappingPerDevice; + return PCIAccessLevel::MemoryAddressing; if (value == "off"sv) return PCIAccessLevel::IOAddressing; PANIC("Unknown PCI ECAM setting: {}", value); diff --git a/Kernel/CommandLine.h b/Kernel/CommandLine.h index 9e0f31c28b..ac22043cdc 100644 --- a/Kernel/CommandLine.h +++ b/Kernel/CommandLine.h @@ -33,8 +33,7 @@ enum class AcpiFeatureLevel { enum class PCIAccessLevel { IOAddressing, - MappingPerBus, - MappingPerDevice, + MemoryAddressing, }; enum class AHCIResetMode { diff --git a/Kernel/Devices/PCISerialDevice.cpp b/Kernel/Devices/PCISerialDevice.cpp index 4ade853fee..0dceb028b0 100644 --- a/Kernel/Devices/PCISerialDevice.cpp +++ b/Kernel/Devices/PCISerialDevice.cpp @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include <Kernel/Bus/PCI/API.h> #include <Kernel/Devices/PCISerialDevice.h> #include <Kernel/Sections.h> diff --git a/Kernel/GlobalProcessExposed.cpp b/Kernel/GlobalProcessExposed.cpp index 5c3459f47d..e1025c2764 100644 --- a/Kernel/GlobalProcessExposed.cpp +++ b/Kernel/GlobalProcessExposed.cpp @@ -9,7 +9,7 @@ #include <Kernel/Arch/x86/CPU.h> #include <Kernel/Arch/x86/InterruptDisabler.h> #include <Kernel/Arch/x86/ProcessorInfo.h> -#include <Kernel/Bus/PCI/Access.h> +#include <Kernel/Bus/PCI/API.h> #include <Kernel/CommandLine.h> #include <Kernel/ConsoleDevice.h> #include <Kernel/Devices/HID/HIDManagement.h> @@ -615,7 +615,7 @@ private: JsonArraySerializer array { builder }; PCI::enumerate([&array](PCI::Address address, PCI::ID id) { auto obj = array.add_object(); - obj.add("seg", address.seg()); + obj.add("domain", address.domain()); obj.add("bus", address.bus()); obj.add("device", address.device()); obj.add("function", address.function()); diff --git a/Kernel/Graphics/Bochs/GraphicsAdapter.cpp b/Kernel/Graphics/Bochs/GraphicsAdapter.cpp index abf84c7dc3..177192a90d 100644 --- a/Kernel/Graphics/Bochs/GraphicsAdapter.cpp +++ b/Kernel/Graphics/Bochs/GraphicsAdapter.cpp @@ -6,7 +6,7 @@ #include <AK/Atomic.h> #include <AK/Checked.h> -#include <Kernel/Bus/PCI/Access.h> +#include <Kernel/Bus/PCI/API.h> #include <Kernel/Bus/PCI/IDs.h> #include <Kernel/Debug.h> #include <Kernel/Graphics/Bochs/GraphicsAdapter.h> diff --git a/Kernel/Graphics/GraphicsManagement.cpp b/Kernel/Graphics/GraphicsManagement.cpp index 2455cd74bf..d90af78e5e 100644 --- a/Kernel/Graphics/GraphicsManagement.cpp +++ b/Kernel/Graphics/GraphicsManagement.cpp @@ -5,6 +5,7 @@ */ #include <AK/Singleton.h> +#include <Kernel/Bus/PCI/API.h> #include <Kernel/Bus/PCI/IDs.h> #include <Kernel/CommandLine.h> #include <Kernel/Graphics/Bochs/GraphicsAdapter.h> diff --git a/Kernel/Graphics/Intel/NativeGraphicsAdapter.cpp b/Kernel/Graphics/Intel/NativeGraphicsAdapter.cpp index 6955e7e0dd..e7e29a6d25 100644 --- a/Kernel/Graphics/Intel/NativeGraphicsAdapter.cpp +++ b/Kernel/Graphics/Intel/NativeGraphicsAdapter.cpp @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include <Kernel/Bus/PCI/API.h> #include <Kernel/Graphics/Console/ContiguousFramebufferConsole.h> #include <Kernel/Graphics/Definitions.h> #include <Kernel/Graphics/GraphicsManagement.h> diff --git a/Kernel/Graphics/VirtIOGPU/GraphicsAdapter.cpp b/Kernel/Graphics/VirtIOGPU/GraphicsAdapter.cpp index 7e17d83304..f2d1e74757 100644 --- a/Kernel/Graphics/VirtIOGPU/GraphicsAdapter.cpp +++ b/Kernel/Graphics/VirtIOGPU/GraphicsAdapter.cpp @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include <Kernel/Bus/PCI/API.h> #include <Kernel/Bus/PCI/IDs.h> #include <Kernel/Graphics/Console/GenericFramebufferConsole.h> #include <Kernel/Graphics/GraphicsManagement.h> diff --git a/Kernel/Net/E1000ENetworkAdapter.cpp b/Kernel/Net/E1000ENetworkAdapter.cpp index e5677d3aae..f559304238 100644 --- a/Kernel/Net/E1000ENetworkAdapter.cpp +++ b/Kernel/Net/E1000ENetworkAdapter.cpp @@ -5,6 +5,7 @@ */ #include <AK/MACAddress.h> +#include <Kernel/Bus/PCI/API.h> #include <Kernel/Bus/PCI/IDs.h> #include <Kernel/Net/E1000ENetworkAdapter.h> #include <Kernel/Sections.h> diff --git a/Kernel/Net/E1000NetworkAdapter.cpp b/Kernel/Net/E1000NetworkAdapter.cpp index b6492354f7..d562be7bcc 100644 --- a/Kernel/Net/E1000NetworkAdapter.cpp +++ b/Kernel/Net/E1000NetworkAdapter.cpp @@ -5,6 +5,7 @@ */ #include <AK/MACAddress.h> +#include <Kernel/Bus/PCI/API.h> #include <Kernel/Bus/PCI/IDs.h> #include <Kernel/Debug.h> #include <Kernel/Net/E1000NetworkAdapter.h> diff --git a/Kernel/Net/NE2000NetworkAdapter.cpp b/Kernel/Net/NE2000NetworkAdapter.cpp index 98b551f3d4..d7ba71096f 100644 --- a/Kernel/Net/NE2000NetworkAdapter.cpp +++ b/Kernel/Net/NE2000NetworkAdapter.cpp @@ -5,6 +5,7 @@ */ #include <AK/MACAddress.h> +#include <Kernel/Bus/PCI/API.h> #include <Kernel/Debug.h> #include <Kernel/IO.h> #include <Kernel/Net/NE2000NetworkAdapter.h> diff --git a/Kernel/Net/NetworkingManagement.cpp b/Kernel/Net/NetworkingManagement.cpp index e1aada237e..efcaad102b 100644 --- a/Kernel/Net/NetworkingManagement.cpp +++ b/Kernel/Net/NetworkingManagement.cpp @@ -5,6 +5,7 @@ */ #include <AK/Singleton.h> +#include <Kernel/Bus/PCI/API.h> #include <Kernel/CommandLine.h> #include <Kernel/IO.h> #include <Kernel/Memory/AnonymousVMObject.h> diff --git a/Kernel/Net/RTL8139NetworkAdapter.cpp b/Kernel/Net/RTL8139NetworkAdapter.cpp index be2ab32e26..c9f9d5e786 100644 --- a/Kernel/Net/RTL8139NetworkAdapter.cpp +++ b/Kernel/Net/RTL8139NetworkAdapter.cpp @@ -5,6 +5,7 @@ */ #include <AK/MACAddress.h> +#include <Kernel/Bus/PCI/API.h> #include <Kernel/Debug.h> #include <Kernel/IO.h> #include <Kernel/Net/RTL8139NetworkAdapter.h> diff --git a/Kernel/Net/RTL8168NetworkAdapter.cpp b/Kernel/Net/RTL8168NetworkAdapter.cpp index 6aba5ee6e1..ac46ef0379 100644 --- a/Kernel/Net/RTL8168NetworkAdapter.cpp +++ b/Kernel/Net/RTL8168NetworkAdapter.cpp @@ -5,6 +5,7 @@ */ #include <AK/MACAddress.h> +#include <Kernel/Bus/PCI/API.h> #include <Kernel/Bus/PCI/IDs.h> #include <Kernel/Debug.h> #include <Kernel/Net/RTL8168NetworkAdapter.h> diff --git a/Kernel/Storage/AHCIController.cpp b/Kernel/Storage/AHCIController.cpp index cf3037e691..d037639ca1 100644 --- a/Kernel/Storage/AHCIController.cpp +++ b/Kernel/Storage/AHCIController.cpp @@ -8,6 +8,7 @@ #include <AK/OwnPtr.h> #include <AK/RefPtr.h> #include <AK/Types.h> +#include <Kernel/Bus/PCI/API.h> #include <Kernel/Memory/MemoryManager.h> #include <Kernel/Storage/AHCIController.h> #include <Kernel/Storage/SATADiskDevice.h> diff --git a/Kernel/Storage/BMIDEChannel.cpp b/Kernel/Storage/BMIDEChannel.cpp index 74ed34ff91..dbebb611cd 100644 --- a/Kernel/Storage/BMIDEChannel.cpp +++ b/Kernel/Storage/BMIDEChannel.cpp @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include <Kernel/Bus/PCI/API.h> #include <Kernel/Sections.h> #include <Kernel/Storage/ATA.h> #include <Kernel/Storage/BMIDEChannel.h> diff --git a/Kernel/Storage/IDEController.cpp b/Kernel/Storage/IDEController.cpp index 6471996a94..599f619e4e 100644 --- a/Kernel/Storage/IDEController.cpp +++ b/Kernel/Storage/IDEController.cpp @@ -7,6 +7,7 @@ #include <AK/OwnPtr.h> #include <AK/RefPtr.h> #include <AK/Types.h> +#include <Kernel/Bus/PCI/API.h> #include <Kernel/FileSystem/ProcFS.h> #include <Kernel/Sections.h> #include <Kernel/Storage/BMIDEChannel.h> diff --git a/Kernel/Storage/StorageManagement.cpp b/Kernel/Storage/StorageManagement.cpp index 6fbb8999af..8053a93e1a 100644 --- a/Kernel/Storage/StorageManagement.cpp +++ b/Kernel/Storage/StorageManagement.cpp @@ -5,6 +5,7 @@ */ #include <AK/UUID.h> +#include <Kernel/Bus/PCI/API.h> #include <Kernel/Bus/PCI/Access.h> #include <Kernel/CommandLine.h> #include <Kernel/Devices/BlockDevice.h> diff --git a/Userland/Utilities/lspci.cpp b/Userland/Utilities/lspci.cpp index 63453f2c1f..67bd6adc80 100644 --- a/Userland/Utilities/lspci.cpp +++ b/Userland/Utilities/lspci.cpp @@ -70,7 +70,7 @@ int main(int argc, char** argv) VERIFY(json.has_value()); json.value().as_array().for_each([db, format](auto& value) { auto& dev = value.as_object(); - auto seg = dev.get("seg").to_u32(); + auto domain = dev.get("domain").to_u32(); auto bus = dev.get("bus").to_u32(); auto device = dev.get("device").to_u32(); auto function = dev.get("function").to_u32(); @@ -97,7 +97,7 @@ int main(int argc, char** argv) if (class_name.is_empty()) class_name = String::formatted("{:02x}{:02x}", class_id, subclass_id); - outln(format, seg, bus, device, function, class_name, vendor_name, device_name, revision_id); + outln(format, domain, bus, device, function, class_name, vendor_name, device_name, revision_id); }); return 0; |