summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Kernel/ACPI/Parser.cpp2
-rw-r--r--Kernel/Bus/PCI/API.cpp231
-rw-r--r--Kernel/Bus/PCI/API.h49
-rw-r--r--Kernel/Bus/PCI/Access.cpp648
-rw-r--r--Kernel/Bus/PCI/Access.h117
-rw-r--r--Kernel/Bus/PCI/Definitions.h109
-rw-r--r--Kernel/Bus/PCI/Device.cpp1
-rw-r--r--Kernel/Bus/PCI/IOAccess.cpp95
-rw-r--r--Kernel/Bus/PCI/IOAccess.h36
-rw-r--r--Kernel/Bus/PCI/Initializer.cpp21
-rw-r--r--Kernel/Bus/PCI/MMIOAccess.cpp215
-rw-r--r--Kernel/Bus/PCI/MMIOAccess.h71
-rw-r--r--Kernel/Bus/PCI/SysFSPCI.cpp97
-rw-r--r--Kernel/Bus/PCI/SysFSPCI.h51
-rw-r--r--Kernel/Bus/PCI/WindowedMMIOAccess.cpp120
-rw-r--r--Kernel/Bus/PCI/WindowedMMIOAccess.h54
-rw-r--r--Kernel/Bus/USB/UHCI/UHCIController.cpp1
-rw-r--r--Kernel/Bus/USB/USBManagement.cpp2
-rw-r--r--Kernel/Bus/VirtIO/Device.cpp1
-rw-r--r--Kernel/CMakeLists.txt5
-rw-r--r--Kernel/CommandLine.cpp4
-rw-r--r--Kernel/CommandLine.h3
-rw-r--r--Kernel/Devices/PCISerialDevice.cpp1
-rw-r--r--Kernel/GlobalProcessExposed.cpp4
-rw-r--r--Kernel/Graphics/Bochs/GraphicsAdapter.cpp2
-rw-r--r--Kernel/Graphics/GraphicsManagement.cpp1
-rw-r--r--Kernel/Graphics/Intel/NativeGraphicsAdapter.cpp1
-rw-r--r--Kernel/Graphics/VirtIOGPU/GraphicsAdapter.cpp1
-rw-r--r--Kernel/Net/E1000ENetworkAdapter.cpp1
-rw-r--r--Kernel/Net/E1000NetworkAdapter.cpp1
-rw-r--r--Kernel/Net/NE2000NetworkAdapter.cpp1
-rw-r--r--Kernel/Net/NetworkingManagement.cpp1
-rw-r--r--Kernel/Net/RTL8139NetworkAdapter.cpp1
-rw-r--r--Kernel/Net/RTL8168NetworkAdapter.cpp1
-rw-r--r--Kernel/Storage/AHCIController.cpp1
-rw-r--r--Kernel/Storage/BMIDEChannel.cpp1
-rw-r--r--Kernel/Storage/IDEController.cpp1
-rw-r--r--Kernel/Storage/StorageManagement.cpp1
-rw-r--r--Userland/Utilities/lspci.cpp4
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;