summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLiav A <liavalb@gmail.com>2020-12-18 17:37:51 +0200
committerAndreas Kling <kling@serenityos.org>2020-12-21 00:19:21 +0100
commit85b4256d10633397516fa39fc3c41517c51ff63a (patch)
tree94e467e1f6ecd10085fa13e95ecc3ce76ba520a9
parent9d10eb473d20fcee02d7e5976e50d92b2d05a7c3 (diff)
downloadserenity-85b4256d10633397516fa39fc3c41517c51ff63a.zip
PCI: Add list of capabilities for each device during first enumeration
-rw-r--r--Kernel/PCI/Access.cpp24
-rw-r--r--Kernel/PCI/Definitions.h19
-rw-r--r--Kernel/PCI/IOAccess.cpp2
-rw-r--r--Kernel/PCI/MMIOAccess.cpp2
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()) << ")"