Prechádzať zdrojové kódy

PCI: Add list of capabilities for each device during first enumeration

Liav A 4 rokov pred
rodič
commit
85b4256d10

+ 24 - 0
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);

+ 18 - 1
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;

+ 1 - 1
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) });
     });
 }
 

+ 1 - 1
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()) << ")"