Browse Source

new: msi_desc

fslongjin 2 years ago
parent
commit
7ca8f42c17
4 changed files with 63 additions and 15 deletions
  1. 0 2
      kernel/Makefile
  2. 10 9
      kernel/driver/pci/msi.c
  3. 44 3
      kernel/driver/pci/msi.h
  4. 9 1
      kernel/driver/usb/xhci/xhci.c

+ 0 - 2
kernel/Makefile

@@ -63,8 +63,6 @@ kernel: head.o main.o $(OBJ_LIST)
     		cd ..;\
 	done
 
-	
-
 
 clean: 
 	rm -rf $(GARBAGE)

+ 10 - 9
kernel/driver/pci/msi.c

@@ -13,7 +13,6 @@
  */
 #define pci_get_arch_msi_message_data(vector, processor, edge_trigger, assert) ((uint32_t)((vector & 0xff) | (edge_trigger == 1 ? 0 : (1 << 15)) | ((assert == 0) ? 0 : (1 << 14))))
 
-
 /**
  * @brief 启用 Message Signaled Interrupts
  *
@@ -25,9 +24,10 @@
  *
  * @return 返回码
  */
-int pci_enable_msi(void *header, uint8_t vector, uint32_t processor, uint8_t edge_trigger, uint8_t assert)
+// int pci_enable_msi(void *header, uint8_t vector, uint32_t processor, uint8_t edge_trigger, uint8_t assert)
+int pci_enable_msi(struct msi_desc_t *msi_desc)
 {
-    struct pci_device_structure_header_t *ptr = (struct pci_device_structure_header_t *)header;
+    struct pci_device_structure_header_t *ptr = msi_desc->pci_dev;
     uint32_t cap_ptr;
     uint32_t tmp;
     uint16_t message_control;
@@ -36,8 +36,8 @@ int pci_enable_msi(void *header, uint8_t vector, uint32_t processor, uint8_t edg
     {
     case 0x00: // general device
         if (!(ptr->Status & 0x10))
-            return E_NOT_SUPPORT_MSI;    
-        
+            return E_NOT_SUPPORT_MSI;
+
         cap_ptr = ((struct pci_device_structure_general_device_t *)ptr)->Capabilities_Pointer;
 
         tmp = pci_read_config(ptr->bus, ptr->device, ptr->func, cap_ptr); // 读取cap+0x0处的值
@@ -47,14 +47,15 @@ int pci_enable_msi(void *header, uint8_t vector, uint32_t processor, uint8_t edg
             return E_NOT_SUPPORT_MSI;
 
         // 写入message address
-        message_addr = pci_get_arch_msi_message_address(processor); // 获取message address
+        message_addr = pci_get_arch_msi_message_address(msi_desc->processor); // 获取message address
         pci_write_config(ptr->bus, ptr->device, ptr->func, cap_ptr + 0x4, (uint32_t)(message_addr & 0xffffffff));
 
         if (message_control & (1 << 7)) // 64位
             pci_write_config(ptr->bus, ptr->device, ptr->func, cap_ptr + 0x8, (uint32_t)((message_addr >> 32) & 0xffffffff));
 
         // 写入message data
-        tmp = pci_get_arch_msi_message_data(vector, processor, edge_trigger, assert);
+
+        tmp = pci_get_arch_msi_message_data(msi_desc->irq_num, msi_desc->processor, msi_desc->edge_trigger, msi_desc->assert);
         if (message_control & (1 << 7)) // 64位
             pci_write_config(ptr->bus, ptr->device, ptr->func, cap_ptr + 0xc, tmp);
         else
@@ -80,14 +81,14 @@ int pci_enable_msi(void *header, uint8_t vector, uint32_t processor, uint8_t edg
             return E_NOT_SUPPORT_MSI;
 
         // 写入message address
-        message_addr = pci_get_arch_msi_message_address(processor); // 获取message address
+        message_addr = pci_get_arch_msi_message_address(msi_desc->processor); // 获取message address
         pci_write_config(ptr->bus, ptr->device, ptr->func, cap_ptr + 0x4, (uint32_t)(message_addr & 0xffffffff));
 
         if (message_control & (1 << 7)) // 64位
             pci_write_config(ptr->bus, ptr->device, ptr->func, cap_ptr + 0x8, (uint32_t)((message_addr >> 32) & 0xffffffff));
 
         // 写入message data
-        tmp = pci_get_arch_msi_message_data(vector, processor, edge_trigger, assert);
+        tmp = pci_get_arch_msi_message_data(msi_desc->irq_num, msi_desc->processor, msi_desc->edge_trigger, msi_desc->assert);
         if (message_control & (1 << 7)) // 64位
             pci_write_config(ptr->bus, ptr->device, ptr->func, cap_ptr + 0xc, tmp);
         else

+ 44 - 3
kernel/driver/pci/msi.h

@@ -1,19 +1,60 @@
 #pragma once
 #include <common/glib.h>
 
+/**
+ * @brief msi消息内容结构体
+ *
+ */
+struct msi_msg_t
+{
+    uint32_t address_lo;
+    uint32_t address_hi;
+    uint32_t data;
+};
+struct pci_msi_desc_t
+{
+    union
+    {
+        uint32_t msi_mask;  // [PCI MSI]   MSI cached mask bits
+        uint32_t msix_ctrl; // [PCI MSI-X] MSI-X cached per vector control bits
+    };
+
+    struct
+    {
+        uint8_t is_msix : 1;  // [PCI MSI/X] True if MSI-X
+        uint8_t can_mask : 1; // [PCI MSI/X] Masking supported?
+        uint8_t is_64 : 1;    // [PCI MSI/X] Address size: 0=32bit 1=64bit
+    } msi_attribute;
+};
+
+/**
+ * @brief msi描述符
+ *
+ */
+struct msi_desc_t
+{
+    uint16_t irq_num;                              // 中断向量号
+    uint16_t processor;                            // 定向投递的处理器
+    uint16_t edge_trigger;                         // 是否边缘触发
+    uint16_t assert;                               // 是否高电平触发
+    struct pci_device_structure_header_t *pci_dev; // 对应的pci设备的结构体
+    struct msi_msg_t msg;                          // msi消息
+    uint16_t msi_index;                            // msi描述符的index
+    struct pci_msi_desc_t pci;                         // 与pci相关的msi描述符数据
+};
 
 /**
  * @brief 启用 Message Signaled Interrupts
- * 
+ *
  * @param header 设备header
  * @param vector 中断向量号
  * @param processor 要投递到的处理器
  * @param edge_trigger 是否边缘触发
  * @param assert 是否高电平触发
- * 
+ *
  * @return 返回码
  */
-int pci_enable_msi(void * header, uint8_t vector, uint32_t processor, uint8_t edge_trigger, uint8_t assert);
+int pci_enable_msi(struct msi_desc_t * msi_desc);
 
 /**
  * @brief 禁用指定设备的msi

+ 9 - 1
kernel/driver/usb/xhci/xhci.c

@@ -557,8 +557,16 @@ uint64_t xhci_hc_irq_install(uint64_t irq_num, void *arg)
         return -EINVAL;
 
     struct xhci_hc_irq_install_info_t *info = (struct xhci_hc_irq_install_info_t *)arg;
+    struct msi_desc_t msi_desc;
+    memset(&msi_desc, 0, sizeof(struct msi_desc_t));
+
+    msi_desc.pci_dev = (struct pci_device_structure_header_t*)xhci_hc[cid].pci_dev_hdr;
+    msi_desc.assert = info->assert;
+    msi_desc.edge_trigger = info->edge_trigger;
+    msi_desc.processor = info->processor;
+    msi_desc.pci.msi_attribute.is_64 = 1;
     // todo: QEMU是使用msix的,因此要先在pci中实现msix
-    int retval = pci_enable_msi(xhci_hc[cid].pci_dev_hdr, irq_num, info->processor, info->edge_trigger, info->assert);
+    int retval = pci_enable_msi(&msi_desc);
     kdebug("pci retval = %d", retval);
     kdebug("xhci irq %d installed.", irq_num);
     return 0;