From db3749ece4a13c32eede0b7452a16d793575584c Mon Sep 17 00:00:00 2001 From: fslongjin Date: Mon, 21 Mar 2022 23:44:17 +0800 Subject: [PATCH] =?UTF-8?q?:new:=20=E9=80=92=E5=BD=92=E6=9E=9A=E4=B8=BEpci?= =?UTF-8?q?=E6=80=BB=E7=BA=BF=E4=B8=8A=E7=9A=84=E8=AE=BE=E5=A4=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .vscode/settings.json | 66 +++++++++++- kernel/driver/pci/pci.c | 230 ++++++++++++++++++++++++++++++++++------ kernel/driver/pci/pci.h | 18 +++- 3 files changed, 276 insertions(+), 38 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 005e4ca6..88adf437 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -21,7 +21,71 @@ "mouse.h": "c", "keyboard.h": "c", "apic.h": "c", - "ps2_keyboard.h": "c" + "ps2_keyboard.h": "c", + "algorithm": "c", + "array": "c", + "atomic": "c", + "*.tcc": "c", + "bitset": "c", + "cassert": "c", + "cctype": "c", + "cerrno": "c", + "cfloat": "c", + "chrono": "c", + "climits": "c", + "clocale": "c", + "cmath": "c", + "codecvt": "c", + "condition_variable": "c", + "cstdarg": "c", + "cstddef": "c", + "cstdint": "c", + "cstdio": "c", + "cstdlib": "c", + "cstring": "c", + "ctime": "c", + "cwchar": "c", + "cwctype": "c", + "deque": "c", + "exception": "c", + "forward_list": "c", + "functional": "c", + "iterator": "c", + "list": "c", + "map": "c", + "memory": "c", + "memory_resource": "c", + "numeric": "c", + "optional": "c", + "random": "c", + "ratio": "c", + "set": "c", + "string": "c", + "string_view": "c", + "system_error": "c", + "tuple": "c", + "type_traits": "c", + "unordered_map": "c", + "utility": "c", + "vector": "c", + "fstream": "c", + "initializer_list": "c", + "ios": "c", + "iosfwd": "c", + "istream": "c", + "limits": "c", + "locale": "c", + "mutex": "c", + "new": "c", + "ostream": "c", + "queue": "c", + "sstream": "c", + "stdexcept": "c", + "streambuf": "c", + "thread": "c", + "cinttypes": "c", + "cstdbool": "c", + "typeinfo": "c" }, "C_Cpp.errorSquiggles": "Enabled" } \ No newline at end of file diff --git a/kernel/driver/pci/pci.c b/kernel/driver/pci/pci.c index f1f5937d..351559e8 100644 --- a/kernel/driver/pci/pci.c +++ b/kernel/driver/pci/pci.c @@ -1,5 +1,28 @@ #include "pci.h" #include "../../common/kprint.h" +#include "../../mm/slab.h" + +static uint count_device_list = 0; + +/** + * @brief 将设备信息结构体加到链表里面 + * + */ +#define ADD_DEVICE_STRUCT_TO_LIST(ret) \ + do \ + { \ + if (count_device_list > 0) \ + { \ + ++count_device_list; \ + list_add(pci_device_structure_list, &ret->header->list); \ + } \ + else \ + { \ + ++count_device_list; \ + list_init(&ret->header->list); \ + pci_device_structure_list = &ret->header->list; \ + } \ + } while (0) /** * @brief 从pci配置空间读取信息 @@ -152,13 +175,13 @@ static void pci_read_pci_to_cardbus_bridge_header(struct pci_device_structure_pc header->IO_Limit1 = pci_read_config(bus, slot, func, 0x38); tmp32 = pci_read_config(bus, slot, func, 0x3c); - header->Interrupt_Line = tmp32&0xff; - header->Interrupt_PIN = (tmp32>>8)&0xff; - header->Bridge_Control = (tmp32>>16)&0xffff; - + header->Interrupt_Line = tmp32 & 0xff; + header->Interrupt_PIN = (tmp32 >> 8) & 0xff; + header->Bridge_Control = (tmp32 >> 16) & 0xffff; + tmp32 = pci_read_config(bus, slot, func, 0x40); - header->Subsystem_Device_ID = tmp32&0xffff; - header->Subsystem_Vendor_ID = (tmp32>>16)&0xffff; + header->Subsystem_Device_ID = tmp32 & 0xffff; + header->Subsystem_Vendor_ID = (tmp32 >> 16) & 0xffff; header->PC_Card_legacy_mode_base_address_16_bit = pci_read_config(bus, slot, func, 0x44); } @@ -170,68 +193,209 @@ static void pci_read_pci_to_cardbus_bridge_header(struct pci_device_structure_pc * @param bus 总线号 * @param slot 插槽号 * @param func 功能号 + * @param add_to_list 添加到链表 * @return 返回的header */ -void *pci_read_header(int *type, uchar bus, uchar slot, uchar func) +void *pci_read_header(int *type, uchar bus, uchar slot, uchar func, bool add_to_list) { - struct pci_device_structure_header_t common_header; + struct pci_device_structure_header_t *common_header = (struct pci_device_structure_header_t *)kmalloc(sizeof(struct pci_device_structure_header_t), 0); + uint32_t tmp32; // 先读取公共header tmp32 = pci_read_config(bus, slot, func, 0x0); - common_header.Vendor_ID = tmp32 & 0xffff; - common_header.Device_ID = (tmp32 >> 16) & 0xffff; + common_header->Vendor_ID = tmp32 & 0xffff; + common_header->Device_ID = (tmp32 >> 16) & 0xffff; tmp32 = pci_read_config(bus, slot, func, 0x4); - common_header.Command = tmp32 & 0xffff; - common_header.Status = (tmp32 >> 16) & 0xffff; + common_header->Command = tmp32 & 0xffff; + common_header->Status = (tmp32 >> 16) & 0xffff; tmp32 = pci_read_config(bus, slot, func, 0x8); - common_header.RevisionID = tmp32 & 0xff; - common_header.ProgIF = (tmp32 >> 8) & 0xff; - common_header.SubClass = (tmp32 >> 16) & 0xff; - common_header.Class_code = (tmp32 >> 24) & 0xff; + common_header->RevisionID = tmp32 & 0xff; + common_header->ProgIF = (tmp32 >> 8) & 0xff; + common_header->SubClass = (tmp32 >> 16) & 0xff; + common_header->Class_code = (tmp32 >> 24) & 0xff; tmp32 = pci_read_config(bus, slot, func, 0xc); - common_header.CacheLineSize = tmp32 & 0xff; - common_header.LatencyTimer = (tmp32 >> 8) & 0xff; - common_header.HeaderType = (tmp32 >> 16) & 0xff; - common_header.BIST = (tmp32 >> 24) & 0xff; + common_header->CacheLineSize = tmp32 & 0xff; + common_header->LatencyTimer = (tmp32 >> 8) & 0xff; + common_header->HeaderType = (tmp32 >> 16) & 0xff; + common_header->BIST = (tmp32 >> 24) & 0xff; // 根据公共头部,判断该结构所属的类型 - switch (common_header.Vendor_ID) + switch (common_header->Vendor_ID) { case 0xFFFF: // 设备不可用 *type = E_DEVICE_INVALID; + kfree(common_header); return NULL; break; case 0x0: // general device - struct pci_device_structure_general_device_t ret; - ret.header = common_header; - pci_read_general_device_header(&ret, bus, slot, func); + struct pci_device_structure_general_device_t *ret = (struct pci_device_structure_general_device_t *)kmalloc(sizeof(struct pci_device_structure_general_device_t), 0); + + ret->header = common_header; + pci_read_general_device_header(ret, bus, slot, func); + if (add_to_list) + ADD_DEVICE_STRUCT_TO_LIST(ret); + *type = 0x0; - return &ret; + return ret; break; case 0x1: - struct pci_device_structure_pci_to_pci_bridge_t ret; - ret.header = common_header; + struct pci_device_structure_pci_to_pci_bridge_t *ret = (struct pci_device_structure_pci_to_pci_bridge_t *)kmalloc(sizeof(struct pci_device_structure_pci_to_pci_bridge_t), 0); + ret->header = common_header; + pci_read_pci_to_pci_bridge_header(ret, bus, slot, func); + if (add_to_list) + ADD_DEVICE_STRUCT_TO_LIST(ret); + *type = 0x1; - pci_read_pci_to_pci_bridge_header(&ret, bus, slot, func); - return &ret; + return ret; break; case 0x2: - struct pci_device_structure_pci_to_cardbus_bridge_t ret; - ret.header = common_header; + struct pci_device_structure_pci_to_cardbus_bridge_t *ret = (struct pci_device_structure_pci_to_cardbus_bridge_t *)kmalloc(sizeof(struct pci_device_structure_pci_to_cardbus_bridge_t), 0); + ret->header = common_header; + pci_read_pci_to_cardbus_bridge_header(ret, bus, slot, func); + if (add_to_list) + ADD_DEVICE_STRUCT_TO_LIST(ret); + *type = 0x2; - pci_read_pci_to_cardbus_bridge_header(&ret, bus, slot, func); - return &ret; + return ret; break; default: // 错误的头类型 这里不应该被执行 kBUG("PCI->pci_read_header(): Invalid header type."); *type = E_WRONG_HEADER_TYPE; + kfree(common_header); return NULL; break; } } +static void pci_checkFunction(uint8_t bus, uint8_t device, uint8_t function) +{ + int header_type; + struct pci_device_structure_header_t *header; + void *raw_header = pci_read_header(&header_type, 0, 0, 0, true); + + if (header_type == E_WRONG_HEADER_TYPE) + { + kBUG("pci_checkFunction(): wrong header type!"); + // 此处内存已经在read header函数里面释放,不用重复释放 + return; + } + header = ((struct pci_device_structure_general_device_t *)raw_header)->header; + + if ((header->Class_code == 0x6) && (header->SubClass == 0x4)) + { + uint8_t SecondaryBus = ((struct pci_device_structure_pci_to_pci_bridge_t *)raw_header)->Secondary_Bus_Number; + pci_checkBus(SecondaryBus); + } + + kfree(header); + kfree(raw_header); +} + +static void pci_checkDevice(uint8_t bus, uint8_t device) +{ + int header_type; + void *raw_header; + struct pci_device_structure_header_t *header; + raw_header = pci_read_header(&header_type, bus, device, 0, false); + if (header_type == E_WRONG_HEADER_TYPE) + { + // 此处内存已经在read header函数里面释放,不用重复释放 + kBUG("pci_checkDevice(): wrong header type!"); + return; + } + header = ((struct pci_device_structure_general_device_t *)raw_header)->header; + uint16_t vendorID = header->Vendor_ID; + + if (vendorID == 0xffff) // 设备不存在 + { + kfree(header); + kfree(raw_header); + return; + } + pci_checkFunction(bus, device, 0); + + header_type = header->HeaderType; + if ((header_type & 0x80) != 0) + { + // 这是一个多function的设备,因此查询剩余的function + for (uint8_t func = 1; func < 8; ++func) + { + struct pci_device_structure_header_t *tmp_header; + void *tmp_raw_header; + tmp_raw_header = pci_read_header(&header_type, bus, device, func, false); + tmp_header = ((struct pci_device_structure_general_device_t *)tmp_raw_header)->header; + + pci_checkFunction(bus, device, func); + + // 释放内存 + kfree(tmp_header); + kfree(tmp_raw_header); + } + } + + kfree(header); + kfree(raw_header); +} + +static void pci_checkBus(uint8_t bus) +{ + for (uint8_t device = 0; device < 32; ++device) + pci_checkDevice(bus, device); +} + +/** + * @brief 扫描所有pci总线上的所有设备 + * + */ +void pci_checkAllBuses() +{ + int header_type; + void *raw_header; + struct pci_device_structure_header_t *header; + raw_header = pci_read_header(&header_type, 0, 0, 0, false); + + if (header_type == E_WRONG_HEADER_TYPE) + { + kBUG("pci_checkAllBuses(): wrong header type!"); + // 此处内存已经在read header函数里面释放,不用重复释放 + return; + } + header = ((struct pci_device_structure_general_device_t *)raw_header)->header; + + header_type = header->HeaderType; + + if ((header_type & 0x80) == 0) // Single pci host controller + { + pci_checkBus(0); + } + else + { + // Multiple PCI host controller + // 那么总线0,设备0,功能1则是总线1的pci主机控制器,以此类推 + void *tmp_raw_header; + struct pci_device_structure_header_t *tmp_header; + for (uint8_t func = 0; func < 8; ++func) + { + tmp_raw_header = pci_read_header(&header_type, 0, 0, func, false); + tmp_header = ((struct pci_device_structure_general_device_t *)tmp_raw_header)->header; + if (header->Vendor_ID != 0xffff) // @todo 这里的判断条件可能有点问题 + { + kfree(tmp_header); + kfree(tmp_raw_header); + break; + } + + pci_checkBus(func); + + kfree(tmp_header); + kfree(tmp_raw_header); + } + } + kfree(header); + kfree(raw_header); +} void pci_init() { diff --git a/kernel/driver/pci/pci.h b/kernel/driver/pci/pci.h index ace1a115..9a11ef18 100644 --- a/kernel/driver/pci/pci.h +++ b/kernel/driver/pci/pci.h @@ -9,6 +9,9 @@ #define E_DEVICE_INVALID -1 #define E_WRONG_HEADER_TYPE -2 +// pci设备结构信息的链表 +struct List * pci_device_structure_list = NULL; + /** * @brief 初始化pci驱动 * @@ -18,6 +21,7 @@ void pci_init(); // pci设备结构的通用标题字段 struct pci_device_structure_header_t { + struct List list; uint16_t Vendor_ID; // 供应商ID 0xffff是一个无效值,在读取访问不存在的设备的配置空间寄存器时返回 uint16_t Device_ID; // 设备ID,标志特定设备 @@ -45,7 +49,7 @@ struct pci_device_structure_header_t */ struct pci_device_structure_general_device_t { - struct pci_device_structure_header_t header; + struct pci_device_structure_header_t *header; uint32_t BAR0; uint32_t BAR1; uint32_t BAR2; @@ -77,7 +81,7 @@ struct pci_device_structure_general_device_t */ struct pci_device_structure_pci_to_pci_bridge_t { - struct pci_device_structure_header_t header; + struct pci_device_structure_header_t *header; uint32_t BAR0; uint32_t BAR1; @@ -122,7 +126,7 @@ struct pci_device_structure_pci_to_pci_bridge_t */ struct pci_device_structure_pci_to_cardbus_bridge_t { - struct pci_device_structure_header_t header; + struct pci_device_structure_header_t *header; uint32_t CardBus_Socket_ExCa_base_address; @@ -176,4 +180,10 @@ uint pci_read_config(uchar bus, uchar slot, uchar func, uchar offset); * @param func 功能号 * @return 返回的header的指针 */ -void* pci_read_header(int *type, uchar bus, uchar slot, uchar func); \ No newline at end of file +void* pci_read_header(int *type, uchar bus, uchar slot, uchar func, bool add_to_list); + +/** + * @brief 扫描所有pci总线上的所有设备 + * + */ +void pci_checkAllBuses(); \ No newline at end of file