diff options
author | Liav A <liavalb@gmail.com> | 2020-12-18 17:37:51 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-12-21 00:19:21 +0100 |
commit | 85b4256d10633397516fa39fc3c41517c51ff63a (patch) | |
tree | 94e467e1f6ecd10085fa13e95ecc3ce76ba520a9 | |
parent | 9d10eb473d20fcee02d7e5976e50d92b2d05a7c3 (diff) | |
download | serenity-85b4256d10633397516fa39fc3c41517c51ff63a.zip |
PCI: Add list of capabilities for each device during first enumeration
-rw-r--r-- | Kernel/PCI/Access.cpp | 24 | ||||
-rw-r--r-- | Kernel/PCI/Definitions.h | 19 | ||||
-rw-r--r-- | Kernel/PCI/IOAccess.cpp | 2 | ||||
-rw-r--r-- | Kernel/PCI/MMIOAccess.cpp | 2 |
4 files changed, 44 insertions, 3 deletions
diff --git a/Kernel/PCI/Access.cpp b/Kernel/PCI/Access.cpp index 74efa8fbd4..3941b77dc6 100644 --- a/Kernel/PCI/Access.cpp +++ b/Kernel/PCI/Access.cpp @@ -129,6 +129,30 @@ void enumerate(Function<void(Address, ID)> callback) Access::the().enumerate(callback); } +Optional<u8> get_capabilities_pointer(Address address) +{ + if (PCI::read16(address, PCI_STATUS) & (1 << 4)) { + return PCI::read8(address, PCI_CAPABILITIES_POINTER); + } + return {}; +} + +Vector<Capability> get_capabilities(Address address) +{ + auto capabilities_pointer = PCI::get_capabilities_pointer(address); + if (!capabilities_pointer.has_value()) + return {}; + Vector<Capability> capabilities; + auto capability_pointer = capabilities_pointer.value(); + while (capability_pointer != 0) { + u16 capability_header = PCI::read16(address, capability_pointer); + u8 capability_id = capability_header & 0xff; + capability_pointer = capability_header >> 8; + capabilities.append({ capability_id, capability_pointer }); + } + return capabilities; +} + void raw_access(Address address, u32 field, size_t access_size, u32 value) { ASSERT(access_size != 0); diff --git a/Kernel/PCI/Definitions.h b/Kernel/PCI/Definitions.h index 1e29e3aac1..2733cd1c1f 100644 --- a/Kernel/PCI/Definitions.h +++ b/Kernel/PCI/Definitions.h @@ -30,6 +30,7 @@ #include <AK/LogStream.h> #include <AK/String.h> #include <AK/Types.h> +#include <AK/Vector.h> namespace Kernel { @@ -180,20 +181,33 @@ struct ChangeableAddress : public Address { } }; +struct Capability { + u8 m_id; + u8 m_next_pointer; +}; + class PhysicalID { public: - PhysicalID(Address address, ID id) + PhysicalID(Address address, ID id, Vector<Capability> capabilities) : m_address(address) , m_id(id) + , m_capabilities(capabilities) { +#ifdef PCI_DEBUG + for (auto capability : capabilities) { + dbg() << address << " has capbility " << capability.m_id; + } +#endif } + Vector<Capability> capabilities() const { return m_capabilities; } const ID& id() const { return m_id; } const Address& address() const { return m_address; } private: Address m_address; ID m_id; + Vector<Capability> m_capabilities; }; ID get_id(PCI::Address); @@ -215,8 +229,11 @@ 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); +PhysicalID get_physical_id(Address address); class Access; class MMIOAccess; diff --git a/Kernel/PCI/IOAccess.cpp b/Kernel/PCI/IOAccess.cpp index 8c565c303f..3be5f5e5ee 100644 --- a/Kernel/PCI/IOAccess.cpp +++ b/Kernel/PCI/IOAccess.cpp @@ -40,7 +40,7 @@ IOAccess::IOAccess() { klog() << "PCI: Using I/O instructions for PCI configuration space access"; enumerate_hardware([&](const Address& address, ID id) { - m_physical_ids.append({ address, id }); + m_physical_ids.append({ address, id, get_capabilities(address) }); }); } diff --git a/Kernel/PCI/MMIOAccess.cpp b/Kernel/PCI/MMIOAccess.cpp index 8fb27e6ae5..03b5b39dd9 100644 --- a/Kernel/PCI/MMIOAccess.cpp +++ b/Kernel/PCI/MMIOAccess.cpp @@ -122,7 +122,7 @@ MMIOAccess::MMIOAccess(PhysicalAddress p_mcfg) InterruptDisabler disabler; enumerate_hardware([&](const Address& address, ID id) { - m_physical_ids.append({ address, id }); + m_physical_ids.append({ address, id, get_capabilities(address) }); m_mapped_device_regions.append(make<DeviceConfigurationSpaceMapping>(address, m_segments.get(address.seg()).value())); #ifdef PCI_DEBUG dbg() << "PCI: Mapping device @ pci (" << String::format("%w", address.seg()) << ":" << String::format("%b", address.bus()) << ":" << String::format("%b", address.slot()) << "." << String::format("%b", address.function()) << ")" |