diff --git a/.vscode/settings.json b/.vscode/settings.json index 97f00e33..c84e9508 100644 --- a/.vscode/settings.json +++ b/.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": "" diff --git a/kernel/arch/x86_64/Makefile b/kernel/arch/x86_64/Makefile index fb2830f7..0234eef0 100644 --- a/kernel/arch/x86_64/Makefile +++ b/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 + diff --git a/kernel/arch/x86_64/ia64_msi.c b/kernel/arch/x86_64/ia64_msi.c new file mode 100644 index 00000000..647ee4bb --- /dev/null +++ b/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); +} \ No newline at end of file diff --git a/kernel/arch/x86_64/ia64_msi.h b/kernel/arch/x86_64/ia64_msi.h new file mode 100644 index 00000000..43dd1567 --- /dev/null +++ b/kernel/arch/x86_64/ia64_msi.h @@ -0,0 +1,11 @@ +#pragma once + +#include + +/** + * @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); \ No newline at end of file diff --git a/kernel/driver/pci/msi.c b/kernel/driver/pci/msi.c index d85a8b51..9172a166 100644 --- a/kernel/driver/pci/msi.c +++ b/kernel/driver/pci/msi.c @@ -1,17 +1,14 @@ #include "msi.h" #include "pci.h" +#include /** - * @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) + + // 先尝试获取msi-x,若不存在,则获取msi capability + if (msi_desc->pci.msi_attribute.is_msix) { - 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; + 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,7 +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); + 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 @@ -65,48 +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 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); - 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 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; } diff --git a/kernel/driver/pci/pci.c b/kernel/driver/pci/pci.c index c0dd3eda..e2ad0fed 100644 --- a/kernel/driver/pci/pci.c +++ b/kernel/driver/pci/pci.c @@ -2,6 +2,7 @@ #include #include #include +#include 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; + } } \ No newline at end of file diff --git a/kernel/driver/pci/pci.h b/kernel/driver/pci/pci.h index 5bf417b2..65992a17 100644 --- a/kernel/driver/pci/pci.h +++ b/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); \ No newline at end of file diff --git a/kernel/driver/usb/xhci/xhci.c b/kernel/driver/usb/xhci/xhci.c index 5b465a16..39d98aaa 100644 --- a/kernel/driver/usb/xhci/xhci.c +++ b/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);