Browse Source

:wrench: 将enable msi的部分更新为使用msi_desc来完成

fslongjin 2 years ago
parent
commit
2b0b727893

+ 2 - 1
.vscode/settings.json

@@ -109,7 +109,8 @@
         "slab.h": "c",
         "boot_info.h": "c",
         "pci.h": "c",
-        "time.h": "c"
+        "time.h": "c",
+        "ia64_msi.h": "c"
     },
     "C_Cpp.errorSquiggles": "Enabled",
     "esbonio.sphinx.confDir": ""

+ 4 - 1
kernel/arch/x86_64/Makefile

@@ -1,7 +1,10 @@
 CFLAGS += -I .
 
-all: x86_64_ipi.o
+all: x86_64_ipi.o ia64_msi.o
 
 x86_64_ipi.o: x86_64_ipi.c
 	gcc $(CFLAGS) -c x86_64_ipi.c -o x86_64_ipi.o
 
+ia64_msi.o: ia64_msi.c
+	gcc $(CFLAGS) -c ia64_msi.c -o ia64_msi.o
+

+ 27 - 0
kernel/arch/x86_64/ia64_msi.c

@@ -0,0 +1,27 @@
+#include "ia64_msi.h"
+
+/**
+ * @brief 生成架构相关的msi的message address
+ *
+ */
+#define ia64_pci_get_arch_msi_message_address(processor) ((0xfee00000UL | (processor << 12)))
+
+/**
+ * @brief 生成架构相关的message data
+ *
+ */
+#define ia64_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 生成msi消息
+ * 
+ * @param msi_desc msi描述符
+ * @return struct msi_msg_t* msi消息指针(在描述符内)
+ */
+struct msi_msg_t *msi_arch_get_msg(struct msi_desc_t *msi_desc)
+{
+    msi_desc->msg.address_hi = 0;
+    msi_desc->msg.address_lo = ia64_pci_get_arch_msi_message_address(msi_desc->processor);
+    msi_desc->msg.data = ia64_pci_get_arch_msi_message_data(msi_desc->irq_num, msi_desc->processor, msi_desc->edge_trigger, msi_desc->assert);
+    return &(msi_desc->msg);
+}

+ 11 - 0
kernel/arch/x86_64/ia64_msi.h

@@ -0,0 +1,11 @@
+#pragma once
+
+#include <driver/pci/msi.h>
+
+/**
+ * @brief 生成msi消息
+ * 
+ * @param msi_desc msi描述符
+ * @return struct msi_msg_t* msi消息指针(在描述符内)
+ */
+struct msi_msg_t *msi_arch_get_msg(struct msi_desc_t *msi_desc);

+ 45 - 74
kernel/driver/pci/msi.c

@@ -1,17 +1,14 @@
 #include "msi.h"
 #include "pci.h"
+#include <common/errno.h>
 
 /**
- * @brief 生成架构相关的msi的message address
+ * @brief 生成msi消息
  *
+ * @param msi_desc msi描述符
+ * @return struct msi_msg_t* msi消息指针(在描述符内)
  */
-#define pci_get_arch_msi_message_address(processor) ((uint64_t)(0xfee00000UL | (processor << 12)))
-
-/**
- * @brief 生成架构相关的message data
- *
- */
-#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))))
+extern struct msi_msg_t *msi_arch_get_msg(struct msi_desc_t *msi_desc);
 
 /**
  * @brief 启用 Message Signaled Interrupts
@@ -24,7 +21,6 @@
  *
  * @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)
 {
     struct pci_device_structure_header_t *ptr = msi_desc->pci_dev;
@@ -32,22 +28,39 @@ int pci_enable_msi(struct msi_desc_t *msi_desc)
     uint32_t tmp;
     uint16_t message_control;
     uint64_t message_addr;
-    switch (ptr->HeaderType)
-    {
-    case 0x00: // general device
-        if (!(ptr->Status & 0x10))
-            return E_NOT_SUPPORT_MSI;
 
-        cap_ptr = ((struct pci_device_structure_general_device_t *)ptr)->Capabilities_Pointer;
+    // 先尝试获取msi-x,若不存在,则获取msi capability
+    if (msi_desc->pci.msi_attribute.is_msix)
+    {
+        cap_ptr = pci_enumerate_capability_list(ptr, 0x11);
+        if (((int32_t)cap_ptr) < 0)
+        {
+            cap_ptr = pci_enumerate_capability_list(ptr, 0x05);
+            if (((int32_t)cap_ptr) < 0)
+                return -ENOSYS;
+            msi_desc->pci.msi_attribute.is_msix = 0;
+        }
+    }
+    else
+    {
+        cap_ptr = pci_enumerate_capability_list(ptr, 0x05);
+        if (((int32_t)cap_ptr) < 0)
+            return -ENOSYS;
+        msi_desc->pci.msi_attribute.is_msix = 0;
+    }
+    // 获取msi消息
+    msi_arch_get_msg(msi_desc);
 
+    if (msi_desc->pci.msi_attribute.is_msix)
+    {
+    }
+    else
+    {
         tmp = pci_read_config(ptr->bus, ptr->device, ptr->func, cap_ptr); // 读取cap+0x0处的值
         message_control = (tmp >> 16) & 0xffff;
 
-        if (tmp & 0xff != 0x5)
-            return E_NOT_SUPPORT_MSI;
-
         // 写入message address
-        message_addr = pci_get_arch_msi_message_address(msi_desc->processor); // 获取message address
+        message_addr = ((((uint64_t)msi_desc->msg.address_hi) << 32) | msi_desc->msg.address_lo); // 获取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位
@@ -55,40 +68,7 @@ int pci_enable_msi(struct msi_desc_t *msi_desc)
 
         // 写入message data
 
-        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
-            pci_write_config(ptr->bus, ptr->device, ptr->func, cap_ptr + 0x8, tmp);
-
-        // 使能msi
-        tmp = pci_read_config(ptr->bus, ptr->device, ptr->func, cap_ptr); // 读取cap+0x0处的值
-        tmp |= (1 << 16);
-        pci_write_config(ptr->bus, ptr->device, ptr->func, cap_ptr, tmp);
-
-        break;
-
-    case 0x01: // pci to pci bridge
-        if (!(ptr->Status & 0x10))
-            return E_NOT_SUPPORT_MSI;
-        cap_ptr = ((struct pci_device_structure_pci_to_pci_bridge_t *)ptr)->Capability_Pointer;
-
-        tmp = pci_read_config(ptr->bus, ptr->device, ptr->func, cap_ptr); // 读取cap+0x0处的值
-
-        message_control = (tmp >> 16) & 0xffff;
-
-        if (tmp & 0xff != 0x5)
-            return E_NOT_SUPPORT_MSI;
-
-        // 写入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(msi_desc->irq_num, msi_desc->processor, msi_desc->edge_trigger, msi_desc->assert);
+        tmp = msi_desc->msg.data;
         if (message_control & (1 << 7)) // 64位
             pci_write_config(ptr->bus, ptr->device, ptr->func, cap_ptr + 0xc, tmp);
         else
@@ -98,15 +78,6 @@ int pci_enable_msi(struct msi_desc_t *msi_desc)
         tmp = pci_read_config(ptr->bus, ptr->device, ptr->func, cap_ptr); // 读取cap+0x0处的值
         tmp |= (1 << 16);
         pci_write_config(ptr->bus, ptr->device, ptr->func, cap_ptr, tmp);
-
-        break;
-    case 0x02: // pci to card bus bridge
-        return E_NOT_SUPPORT_MSI;
-        break;
-
-    default: // 不应该到达这里
-        return E_WRONG_HEADER_TYPE;
-        break;
     }
 
     return 0;
@@ -128,13 +99,13 @@ int pci_start_msi(void *header)
     {
     case 0x00: // general device
         if (!(ptr->Status & 0x10))
-            return E_NOT_SUPPORT_MSI;
+            return -ENOSYS;
         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处的值
 
         if (tmp & 0xff != 0x5)
-            return E_NOT_SUPPORT_MSI;
+            return -ENOSYS;
 
         // 使能msi
         tmp = pci_read_config(ptr->bus, ptr->device, ptr->func, cap_ptr); // 读取cap+0x0处的值
@@ -145,13 +116,13 @@ int pci_start_msi(void *header)
 
     case 0x01: // pci to pci bridge
         if (!(ptr->Status & 0x10))
-            return E_NOT_SUPPORT_MSI;
+            return -ENOSYS;
         cap_ptr = ((struct pci_device_structure_pci_to_pci_bridge_t *)ptr)->Capability_Pointer;
 
         tmp = pci_read_config(ptr->bus, ptr->device, ptr->func, cap_ptr); // 读取cap+0x0处的值
 
         if (tmp & 0xff != 0x5)
-            return E_NOT_SUPPORT_MSI;
+            return -ENOSYS;
 
         //使能msi
         tmp = pci_read_config(ptr->bus, ptr->device, ptr->func, cap_ptr); // 读取cap+0x0处的值
@@ -160,11 +131,11 @@ int pci_start_msi(void *header)
 
         break;
     case 0x02: // pci to card bus bridge
-        return E_NOT_SUPPORT_MSI;
+        return -ENOSYS;
         break;
 
     default: // 不应该到达这里
-        return E_WRONG_HEADER_TYPE;
+        return -EINVAL;
         break;
     }
 
@@ -186,13 +157,13 @@ int pci_disable_msi(void *header)
     {
     case 0x00: // general device
         if (!(ptr->Status & 0x10))
-            return E_NOT_SUPPORT_MSI;
+            return -ENOSYS;
         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处的值
 
         if (tmp & 0xff != 0x5)
-            return E_NOT_SUPPORT_MSI;
+            return -ENOSYS;
 
         // 禁用msi
         tmp = pci_read_config(ptr->bus, ptr->device, ptr->func, cap_ptr); // 读取cap+0x0处的值
@@ -203,13 +174,13 @@ int pci_disable_msi(void *header)
 
     case 0x01: // pci to pci bridge
         if (!(ptr->Status & 0x10))
-            return E_NOT_SUPPORT_MSI;
+            return -ENOSYS;
         cap_ptr = ((struct pci_device_structure_pci_to_pci_bridge_t *)ptr)->Capability_Pointer;
 
         tmp = pci_read_config(ptr->bus, ptr->device, ptr->func, cap_ptr); // 读取cap+0x0处的值
 
         if (tmp & 0xff != 0x5)
-            return E_NOT_SUPPORT_MSI;
+            return -ENOSYS;
 
         //禁用msi
         tmp = pci_read_config(ptr->bus, ptr->device, ptr->func, cap_ptr); // 读取cap+0x0处的值
@@ -218,11 +189,11 @@ int pci_disable_msi(void *header)
 
         break;
     case 0x02: // pci to card bus bridge
-        return E_NOT_SUPPORT_MSI;
+        return -ENOSYS;
         break;
 
     default: // 不应该到达这里
-        return E_WRONG_HEADER_TYPE;
+        return -EINVAL;
         break;
     }
 

+ 53 - 9
kernel/driver/pci/pci.c

@@ -2,6 +2,7 @@
 #include <common/kprint.h>
 #include <mm/slab.h>
 #include <debug/bug.h>
+#include <common/errno.h>
 
 static uint count_device_list = 0;
 static void pci_checkBus(uint8_t bus);
@@ -257,7 +258,7 @@ void *pci_read_header(int *type, uchar bus, uchar slot, uchar func, bool add_to_
     void *ret;
     if (common_header->Vendor_ID == 0xffff)
     {
-        *type = E_DEVICE_INVALID;
+        *type = -ENXIO;
         kfree(common_header);
         return NULL;
     }
@@ -295,7 +296,7 @@ void *pci_read_header(int *type, uchar bus, uchar slot, uchar func, bool add_to_
         break;
     default: // 错误的头类型 这里不应该被执行
         // kerror("PCI->pci_read_header(): Invalid header type.");
-        *type = E_WRONG_HEADER_TYPE;
+        *type = -EINVAL;
         // kerror("vendor id=%#010lx", common_header->Vendor_ID);
         // kerror("header type = %d", common_header->HeaderType);
         kfree(common_header);
@@ -308,7 +309,7 @@ static void pci_checkFunction(uint8_t bus, uint8_t device, uint8_t function)
     int header_type;
     struct pci_device_structure_header_t *header = pci_read_header(&header_type, bus, device, function, true);
 
-    if (header_type == E_WRONG_HEADER_TYPE)
+    if (header_type == -EINVAL)
     {
         // kerror("pci_checkFunction(): wrong header type!");
         //  此处内存已经在read header函数里面释放,不用重复释放
@@ -328,15 +329,15 @@ static int pci_checkDevice(uint8_t bus, uint8_t device)
     int header_type;
 
     struct pci_device_structure_header_t *header = pci_read_header(&header_type, bus, device, 0, false);
-    if (header_type == E_WRONG_HEADER_TYPE)
+    if (header_type == -EINVAL)
     {
         // 此处内存已经在read header函数里面释放,不用重复释放
-        return E_WRONG_HEADER_TYPE;
+        return -EINVAL;
     }
-    if (header_type == E_DEVICE_INVALID)
+    if (header_type == -ENXIO)
     {
         // kerror("DEVICE INVALID");
-        return E_DEVICE_INVALID;
+        return -ENXIO;
     }
 
     uint16_t vendorID = header->Vendor_ID;
@@ -344,7 +345,7 @@ static int pci_checkDevice(uint8_t bus, uint8_t device)
     if (vendorID == 0xffff) // 设备不存在
     {
         kfree(header);
-        return E_DEVICE_INVALID;
+        return -ENXIO;
     }
     pci_checkFunction(bus, device, 0);
 
@@ -388,7 +389,7 @@ void pci_checkAllBuses()
     int header_type;
     struct pci_device_structure_header_t *header = pci_read_header(&header_type, 0, 0, 0, false);
 
-    if (header_type == E_WRONG_HEADER_TYPE)
+    if (header_type == EINVAL)
     {
         kBUG("pci_checkAllBuses(): wrong header type!");
         // 此处内存已经在read header函数里面释放,不用重复释放
@@ -493,4 +494,47 @@ void pci_get_device_structure(uint8_t class_code, uint8_t sub_class, struct pci_
         }
         ptr = container_of(list_next(&(ptr->list)), struct pci_device_structure_header_t, list);
     }
+}
+
+/**
+ * @brief 寻找符合指定类型的capability list
+ *
+ * @param pci_dev pci设备header
+ * @param cap_type c要寻找的capability类型
+ * @return uint64_t cap list的偏移量
+ */
+uint32_t pci_enumerate_capability_list(struct pci_device_structure_header_t *pci_dev, int cap_type)
+{
+    uint32_t cap_offset;
+    switch (pci_dev->HeaderType)
+    {
+    case 0x00:
+
+        cap_offset = ((struct pci_device_structure_general_device_t *)pci_dev)->Capabilities_Pointer;
+        break;
+
+    case 0x10:
+        cap_offset = ((struct pci_device_structure_pci_to_pci_bridge_t *)pci_dev)->Capability_Pointer;
+        break;
+    default:
+        // 不支持
+        return -ENOSYS;
+    }
+    uint32_t tmp;
+    while (1)
+    {
+        tmp = pci_read_config(pci_dev->bus, pci_dev->device, pci_dev->func, cap_offset);
+        if (tmp & 0xff != cap_type)
+        {
+            if ((tmp & 0xff00) >> 8)
+            {
+                cap_offset = (tmp & 0xff00);
+                continue;
+            }
+            else
+                return -ENOSYS;
+        }
+
+        return cap_offset;
+    }
 }

+ 9 - 3
kernel/driver/pci/pci.h

@@ -6,9 +6,6 @@
 #define PORT_PCI_CONFIG_ADDRESS 0xcf8
 #define PORT_PCI_CONFIG_DATA 0xcfc
 
-#define E_DEVICE_INVALID -1
-#define E_WRONG_HEADER_TYPE -2
-#define E_NOT_SUPPORT_MSI -3    // 设备不支持msi
 
 // pci设备结构信息的链表
 struct List * pci_device_structure_list = NULL;
@@ -215,3 +212,12 @@ void pci_checkAllBuses();
  * @param res 返回的结果数组
  */
 void pci_get_device_structure(uint8_t class_code, uint8_t sub_class, struct pci_device_structure_header_t* res[], uint32_t* count_res);
+
+/**
+ * @brief 寻找符合指定类型的capability list
+ *
+ * @param pci_dev pci设备header
+ * @param cap_type c要寻找的capability类型
+ * @return uint64_t cap list的偏移量
+ */
+uint32_t pci_enumerate_capability_list(struct pci_device_structure_header_t *pci_dev, int cap_type);

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

@@ -565,7 +565,7 @@ uint64_t xhci_hc_irq_install(uint64_t irq_num, void *arg)
     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
+    // todo: QEMU是使用msix的,因此要先在pci中实现msix  
     int retval = pci_enable_msi(&msi_desc);
     kdebug("pci retval = %d", retval);
     kdebug("xhci irq %d installed.", irq_num);