pci.h 7.4 KB

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