Browse Source

Kernel: Add MSIInfo struct to PCI DeviceIdentifier

Add a struct named MSIInfo that stores all the relevant MSI
information as a part of PCI DeviceIdentifier struct.
Populate the MSI struct during the PCI device init.
Pankaj Raghav 2 years ago
parent
commit
09b5cefd43
2 changed files with 30 additions and 2 deletions
  1. 21 1
      Kernel/Bus/PCI/Definitions.h
  2. 9 1
      Kernel/Bus/PCI/DeviceIdentifier.cpp

+ 21 - 1
Kernel/Bus/PCI/Definitions.h

@@ -79,10 +79,12 @@ static constexpr size_t mmio_device_space_size = 4096;
 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 u32 bar_address_mask = 0xfffffff0;
+static constexpr u8 msi_control_offset = 2;
+static constexpr u16 msi_address_format_mask = 0x80;
+static constexpr u8 msi_mmc_format_mask = 0xe;
 static constexpr u16 msix_control_table_mask = 0x07ff;
 static constexpr u8 msix_table_bir_mask = 0x7;
 static constexpr u16 msix_table_offset_mask = 0xfff8;
-static constexpr u8 msi_control_offset = 2;
 static constexpr u16 msix_control_enable = 0x8000;
 
 // Taken from https://pcisig.com/sites/default/files/files/PCI_Code-ID_r_1_11__v24_Jan_2019.pdf
@@ -340,6 +342,20 @@ public:
     u32 table_offset {};
 };
 
+class MSIInfo {
+public:
+    MSIInfo(bool message_address_64_bit_support, u8 count)
+        : message_address_64_bit_format(message_address_64_bit_support)
+        , count(count)
+    {
+    }
+
+    MSIInfo() = default;
+
+    bool message_address_64_bit_format { false };
+    u8 count {};
+};
+
 class DeviceIdentifier
     : public RefCounted<DeviceIdentifier>
     , public EnumerableDeviceIdentifier {
@@ -353,6 +369,9 @@ public:
     u8 get_msix_table_bar() const { return m_msix_info.table_bar; }
     u32 get_msix_table_offset() const { return m_msix_info.table_offset; }
 
+    bool is_msi_capable() const { return m_msi_info.count > 0; }
+    bool is_msi_64bit_address_format() { return m_msi_info.message_address_64_bit_format; };
+
     Spinlock<LockRank::None>& operation_lock() { return m_operation_lock; }
     Spinlock<LockRank::None>& operation_lock() const { return m_operation_lock; }
 
@@ -376,6 +395,7 @@ private:
 
     mutable Spinlock<LockRank::None> m_operation_lock;
     MSIxInfo m_msix_info {};
+    MSIInfo m_msi_info {};
 };
 
 class Domain;

+ 9 - 1
Kernel/Bus/PCI/DeviceIdentifier.cpp

@@ -26,7 +26,15 @@ void DeviceIdentifier::initialize()
             auto msix_count = (cap.read16(2) & msix_control_table_mask) + 1;
             m_msix_info = MSIxInfo(msix_count, msix_bir_bar, msix_bir_offset);
         }
+
+        if (cap.id() == PCI::Capabilities::ID::MSI) {
+            bool message_address_64_bit_format = (cap.read8(msi_control_offset) & msi_address_format_mask);
+            u8 count = 1;
+            u8 mme_count = (cap.read8(msi_control_offset) & msi_mmc_format_mask) >> 1;
+            if (mme_count)
+                count = mme_count;
+            m_msi_info = MSIInfo(message_address_64_bit_format, count);
+        }
     }
 }
-
 }