瀏覽代碼

Kernel: Add MSIxInfo struct to PCI DeviceIdentifier

Add a struct named MSIxInfo that stores all the relevant MSIx
information as a part of PCI DeviceIdentifier struct.

Populate the MSIx struct during the PCI device init. As the
DeviceIdentifier struct need to populate MSIx info, don't mark
DeviceIdentifier as const in the PCI::Device class.
Pankaj Raghav 2 年之前
父節點
當前提交
d0fbaf790a
共有 4 個文件被更改,包括 39 次插入1 次删除
  1. 25 0
      Kernel/Bus/PCI/Definitions.h
  2. 1 0
      Kernel/Bus/PCI/Device.cpp
  3. 1 1
      Kernel/Bus/PCI/Device.h
  4. 12 0
      Kernel/Bus/PCI/DeviceIdentifier.cpp

+ 25 - 0
Kernel/Bus/PCI/Definitions.h

@@ -79,6 +79,9 @@ static constexpr size_t mmio_device_space_size = 4096;
 static constexpr u16 none_value = 0xffff;
 static constexpr u16 none_value = 0xffff;
 static constexpr size_t memory_range_per_bus = mmio_device_space_size * to_underlying(Limits::MaxFunctionsPerDevice) * to_underlying(Limits::MaxDevicesPerBus);
 static constexpr size_t memory_range_per_bus = mmio_device_space_size * to_underlying(Limits::MaxFunctionsPerDevice) * to_underlying(Limits::MaxDevicesPerBus);
 static constexpr u32 bar_address_mask = 0xfffffff0;
 static constexpr u32 bar_address_mask = 0xfffffff0;
+static constexpr u16 msix_control_table_mask = 0x07ff;
+static constexpr u8 msix_table_bir_mask = 0x7;
+static constexpr u16 msix_table_offset_mask = 0xfff8;
 
 
 // Taken from https://pcisig.com/sites/default/files/files/PCI_Code-ID_r_1_11__v24_Jan_2019.pdf
 // Taken from https://pcisig.com/sites/default/files/files/PCI_Code-ID_r_1_11__v24_Jan_2019.pdf
 enum class ClassID {
 enum class ClassID {
@@ -319,6 +322,22 @@ protected:
     Vector<Capability> m_capabilities;
     Vector<Capability> m_capabilities;
 };
 };
 
 
+class MSIxInfo {
+public:
+    MSIxInfo(u16 table_size, u8 table_bar, u32 table_offset)
+        : table_size(table_size)
+        , table_bar(table_bar)
+        , table_offset(table_offset)
+    {
+    }
+
+    MSIxInfo() = default;
+
+    u16 table_size {};
+    u8 table_bar {};
+    u32 table_offset {};
+};
+
 class DeviceIdentifier
 class DeviceIdentifier
     : public RefCounted<DeviceIdentifier>
     : public RefCounted<DeviceIdentifier>
     , public EnumerableDeviceIdentifier {
     , public EnumerableDeviceIdentifier {
@@ -327,6 +346,11 @@ class DeviceIdentifier
 public:
 public:
     static ErrorOr<NonnullRefPtr<DeviceIdentifier>> from_enumerable_identifier(EnumerableDeviceIdentifier const& other_identifier);
     static ErrorOr<NonnullRefPtr<DeviceIdentifier>> from_enumerable_identifier(EnumerableDeviceIdentifier const& other_identifier);
 
 
+    void initialize();
+    bool is_msix_capable() const { return m_msix_info.table_size > 0; }
+    u8 get_msix_table_bar() const { return m_msix_info.table_bar; }
+    u32 get_msix_table_offset() const { return m_msix_info.table_offset; }
+
     Spinlock<LockRank::None>& operation_lock() { return m_operation_lock; }
     Spinlock<LockRank::None>& operation_lock() { return m_operation_lock; }
     Spinlock<LockRank::None>& operation_lock() const { return m_operation_lock; }
     Spinlock<LockRank::None>& operation_lock() const { return m_operation_lock; }
 
 
@@ -349,6 +373,7 @@ private:
     }
     }
 
 
     mutable Spinlock<LockRank::None> m_operation_lock;
     mutable Spinlock<LockRank::None> m_operation_lock;
+    MSIxInfo m_msix_info {};
 };
 };
 
 
 class Domain;
 class Domain;

+ 1 - 0
Kernel/Bus/PCI/Device.cpp

@@ -13,6 +13,7 @@ namespace Kernel::PCI {
 Device::Device(DeviceIdentifier const& pci_identifier)
 Device::Device(DeviceIdentifier const& pci_identifier)
     : m_pci_identifier(pci_identifier)
     : m_pci_identifier(pci_identifier)
 {
 {
+    m_pci_identifier->initialize();
 }
 }
 
 
 bool Device::is_msi_capable() const
 bool Device::is_msi_capable() const

+ 1 - 1
Kernel/Bus/PCI/Device.h

@@ -38,7 +38,7 @@ protected:
     explicit Device(DeviceIdentifier const& pci_identifier);
     explicit Device(DeviceIdentifier const& pci_identifier);
 
 
 private:
 private:
-    NonnullRefPtr<DeviceIdentifier const> const m_pci_identifier;
+    NonnullRefPtr<DeviceIdentifier> const m_pci_identifier;
 };
 };
 
 
 template<typename... Parameters>
 template<typename... Parameters>

+ 12 - 0
Kernel/Bus/PCI/DeviceIdentifier.cpp

@@ -17,4 +17,16 @@ ErrorOr<NonnullRefPtr<DeviceIdentifier>> DeviceIdentifier::from_enumerable_ident
     return adopt_nonnull_ref_or_enomem(new (nothrow) DeviceIdentifier(other_identifier));
     return adopt_nonnull_ref_or_enomem(new (nothrow) DeviceIdentifier(other_identifier));
 }
 }
 
 
+void DeviceIdentifier::initialize()
+{
+    for (auto cap : capabilities()) {
+        if (cap.id() == PCI::Capabilities::ID::MSIX) {
+            auto msix_bir_bar = (cap.read8(4) & msix_table_bir_mask);
+            auto msix_bir_offset = (cap.read32(4) & msix_table_offset_mask);
+            auto msix_count = (cap.read16(2) & msix_control_table_mask) + 1;
+            m_msix_info = MSIxInfo(msix_count, msix_bir_bar, msix_bir_offset);
+        }
+    }
+}
+
 }
 }