1 #pragma once 2 3 #include <common/glib.h> 4 #include <DragonOS/stdint.h> 5 6 #define PORT_PCI_CONFIG_ADDRESS 0xcf8 7 #define PORT_PCI_CONFIG_DATA 0xcfc 8 9 // pci设备结构信息的链表 10 struct List *pci_device_structure_list = NULL; 11 12 /** 13 * @brief 初始化pci驱动 14 * 15 */ 16 void pci_init(); 17 18 // pci设备结构的通用标题字段 19 struct pci_device_structure_header_t 20 { 21 struct List list; 22 23 // 包含msix table地址的bar的mmio基地址 24 uint64_t msix_mmio_vaddr; 25 uint64_t msix_mmio_size; // msix映射长度 26 uint32_t msix_offset; // msix表的offset 27 uint16_t msix_table_size; // msix表的表项数量 28 29 // ==== 以下三个变量表示该结构体所处的位置 30 uint8_t bus; 31 uint8_t device; 32 uint8_t func; 33 34 uint16_t Vendor_ID; // 供应商ID 0xffff是一个无效值,在读取访问不存在的设备的配置空间寄存器时返回 35 uint16_t Device_ID; // 设备ID,标志特定设备 36 37 uint16_t Command; // 提供对设备生成和响应pci周期的能力的控制 向该寄存器写入0时,设备与pci总线断开除配置空间访问以外的所有连接 38 uint16_t Status; // 用于记录pci总线相关时间的状态信息寄存器 39 40 uint8_t RevisionID; // 修订ID,指定特定设备的修订标志符 41 uint8_t ProgIF; // 编程接口字节,一个只读寄存器,指定设备具有的寄存器级别的编程接口(如果有的话) 42 uint8_t SubClass; // 子类。指定设备执行的特定功能的只读寄存器 43 uint8_t Class_code; // 类代码,一个只读寄存器,指定设备执行的功能类型 44 45 uint8_t CacheLineSize; // 缓存线大小:以 32 位为单位指定系统缓存线大小。设备可以限制它可以支持的缓存线大小的数量,如果不支持的值写入该字段,设备将表现得好像写入了 0 值 46 uint8_t LatencyTimer; // 延迟计时器:以 PCI 总线时钟为单位指定延迟计时器。 47 uint8_t HeaderType; // 标头类型 a value of 0x0 specifies a general device, a value of 0x1 specifies a PCI-to-PCI bridge, and a value of 0x2 specifies a CardBus bridge. If bit 7 of this register is set, the device has multiple functions; otherwise, it is a single function device. 48 uint8_t BIST; // Represents that status and allows control of a devices BIST (built-in self test). 49 // Here is the layout of the BIST register: 50 // | bit7 | bit6 | Bits 5-4 | Bits 3-0 | 51 // | BIST Capable | Start BIST | Reserved | Completion Code | 52 // for more details, please visit https://wiki.osdev.org/PCI 53 }; 54 55 /** 56 * @brief 表头类型为0x0的pci设备结构 57 * 58 */ 59 struct pci_device_structure_general_device_t 60 { 61 struct pci_device_structure_header_t header; 62 uint32_t BAR0; 63 uint32_t BAR1; 64 uint32_t BAR2; 65 uint32_t BAR3; 66 uint32_t BAR4; 67 uint32_t BAR5; 68 uint32_t Cardbus_CIS_Pointer; // 指向卡信息结构,供在 CardBus 和 PCI 之间共享芯片的设备使用。 69 70 uint16_t Subsystem_Vendor_ID; 71 uint16_t Subsystem_ID; 72 73 uint32_t Expansion_ROM_base_address; 74 75 uint8_t Capabilities_Pointer; 76 uint8_t reserved0; 77 uint16_t reserved1; 78 79 uint32_t reserved2; 80 81 uint8_t Interrupt_Line; // 指定设备的中断引脚连接到系统中断控制器的哪个输入,并由任何使用中断引脚的设备实现。对于 x86 架构,此寄存器对应于 PIC IRQ 编号 0-15(而不是 I/O APIC IRQ 编号),并且值0xFF定义为无连接。 82 uint8_t Interrupt_PIN; // 指定设备使用的中断引脚。其中值为0x1INTA#、0x2INTB#、0x3INTC#、0x4INTD#,0x0表示设备不使用中断引脚。 83 uint8_t Min_Grant; // 一个只读寄存器,用于指定设备所需的突发周期长度(以 1/4 微秒为单位)(假设时钟速率为 33 MHz) 84 uint8_t Max_Latency; // 一个只读寄存器,指定设备需要多长时间访问一次 PCI 总线(以 1/4 微秒为单位)。 85 } __attribute__((packed)); 86 87 /** 88 * @brief 表头类型为0x1的pci设备结构(PCI to PCI Bridge) 89 * 90 */ 91 struct pci_device_structure_pci_to_pci_bridge_t 92 { 93 struct pci_device_structure_header_t header; 94 95 uint32_t BAR0; 96 uint32_t BAR1; 97 98 uint8_t Primary_Bus_Number; 99 uint8_t Secondary_Bus_Number; 100 uint8_t Subordinate_Bus_Number; 101 uint8_t Secondary_Latency_Timer; 102 103 uint8_t io_base; 104 uint8_t io_limit; 105 uint16_t Secondary_Status; 106 107 uint16_t Memory_Base; 108 uint16_t Memory_Limit; 109 110 uint16_t Prefetchable_Memory_Base; 111 uint16_t Prefetchable_Memory_Limit; 112 113 uint32_t Prefetchable_Base_Upper_32_Bits; 114 uint32_t Prefetchable_Limit_Upper_32_Bits; 115 116 uint16_t io_Base_Upper_16_Bits; 117 uint16_t io_Limit_Upper_16_Bits; 118 119 uint8_t Capability_Pointer; 120 uint8_t reserved0; 121 uint16_t reserved1; 122 123 uint32_t Expansion_ROM_base_address; 124 125 uint8_t Interrupt_Line; 126 uint8_t Interrupt_PIN; 127 uint16_t Bridge_Control; 128 129 } __attribute__((packed)); 130 131 /** 132 * @brief 表头类型为0x2的pci设备结构(PCI to CardBus Bridge) 133 * 134 */ 135 struct pci_device_structure_pci_to_cardbus_bridge_t 136 { 137 struct pci_device_structure_header_t header; 138 139 uint32_t CardBus_Socket_ExCa_base_address; 140 141 uint8_t Offset_of_capabilities_list; 142 uint8_t Reserved; 143 uint16_t Secondary_status; 144 145 uint8_t PCI_bus_number; 146 uint8_t CardBus_bus_number; 147 uint8_t Subordinate_bus_number; 148 uint8_t CardBus_latency_timer; 149 150 uint32_t Memory_Base_Address0; 151 uint32_t Memory_Limit0; 152 uint32_t Memory_Base_Address1; 153 uint32_t Memory_Limit1; 154 uint32_t IO_Base_Address0; 155 uint32_t IO_Limit0; 156 uint32_t IO_Base_Address1; 157 uint32_t IO_Limit1; 158 159 uint8_t Interrupt_Line; 160 uint8_t Interrupt_PIN; 161 uint16_t Bridge_Control; 162 163 uint16_t Subsystem_Device_ID; 164 uint16_t Subsystem_Vendor_ID; 165 166 uint32_t PC_Card_legacy_mode_base_address_16_bit; 167 168 } __attribute__((packed)); 169 170 /** 171 * @brief 从pci配置空间读取信息 172 * 173 * @param bus 总线号 174 * @param slot 插槽号 175 * @param func 功能号 176 * @param offset 字节偏移量 177 * @return uint 寄存器值 178 */ 179 uint32_t pci_read_config(uchar bus, uchar slot, uchar func, uchar offset); 180 181 /** 182 * @brief 向pci配置空间写入信息 183 * 184 * @param bus 总线号 185 * @param slot 设备号 186 * @param func 功能号 187 * @param offset 字节偏移量 188 * @return uint 寄存器值 189 */ 190 uint pci_write_config(uchar bus, uchar slot, uchar func, uchar offset, uint32_t data); 191 192 /** 193 * @brief 读取pci设备标头 194 * 195 * @param type 标头类型 196 * @param bus 总线号 197 * @param slot 插槽号 198 * @param func 功能号 199 * @return 返回的header的指针 200 */ 201 void *pci_read_header(int *type, uchar bus, uchar slot, uchar func, bool add_to_list); 202 203 /** 204 * @brief 扫描所有pci总线上的所有设备 205 * 206 */ 207 void pci_checkAllBuses(); 208 209 /** 210 * @brief 获取 device structure 211 * 212 * @param class_code 213 * @param sub_class 214 * @param res 返回的结果数组 215 */ 216 void pci_get_device_structure(uint8_t class_code, uint8_t sub_class, struct pci_device_structure_header_t *res[], uint32_t *count_res); 217 218 /** 219 * @brief 寻找符合指定类型的capability list 220 * 221 * @param pci_dev pci设备header 222 * @param cap_type c要寻找的capability类型 223 * @return uint64_t cap list的偏移量 224 */ 225 int32_t pci_enumerate_capability_list(struct pci_device_structure_header_t *pci_dev, uint32_t cap_type);