ahci.h 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345
  1. #pragma once
  2. #include "../block_device.h"
  3. #include "../../pci/pci.h"
  4. /**
  5. * @brief 在SATA3.0规范中定义的Frame Information Structure类型
  6. *
  7. */
  8. typedef enum
  9. {
  10. FIS_TYPE_REG_H2D = 0x27, // Register FIS - host to device
  11. FIS_TYPE_REG_D2H = 0x34, // Register FIS - device to host
  12. FIS_TYPE_DMA_ACT = 0x39, // DMA activate FIS - device to host
  13. FIS_TYPE_DMA_SETUP = 0x41, // DMA setup FIS - bidirectional
  14. FIS_TYPE_DATA = 0x46, // Data FIS - bidirectional
  15. FIS_TYPE_BIST = 0x58, // BIST activate FIS - bidirectional
  16. FIS_TYPE_PIO_SETUP = 0x5F, // PIO setup FIS - device to host
  17. FIS_TYPE_DEV_BITS = 0xA1, // Set device bits FIS - device to host
  18. } FIS_TYPE;
  19. /**
  20. * @brief FIS_REG_H2D 被用于从主机向设备发送控制命令
  21. * 注意:reserved bit应当被清零
  22. */
  23. typedef struct tagFIS_REG_H2D
  24. {
  25. // DWORD 0
  26. uint8_t fis_type; // FIS_TYPE_REG_H2D
  27. uint8_t pmport : 4; // Port multiplier
  28. uint8_t rsv0 : 3; // Reserved
  29. uint8_t c : 1; // 1: Command, 0: Control
  30. uint8_t command; // Command register
  31. uint8_t featurel; // Feature register, 7:0
  32. // DWORD 1
  33. uint8_t lba0; // LBA low register, 7:0
  34. uint8_t lba1; // LBA mid register, 15:8
  35. uint8_t lba2; // LBA high register, 23:16
  36. uint8_t device; // Device register
  37. // DWORD 2
  38. uint8_t lba3; // LBA register, 31:24
  39. uint8_t lba4; // LBA register, 39:32
  40. uint8_t lba5; // LBA register, 47:40
  41. uint8_t featureh; // Feature register, 15:8
  42. // DWORD 3
  43. uint8_t countl; // Count register, 7:0
  44. uint8_t counth; // Count register, 15:8
  45. uint8_t icc; // Isochronous command completion
  46. uint8_t control; // Control register
  47. // DWORD 4
  48. uint8_t rsv1[4]; // Reserved
  49. } FIS_REG_H2D;
  50. // A device to host register FIS is used by the device to notify the host that some ATA register has changed.
  51. // It contains the updated task files such as status, error and other registers.
  52. typedef struct tagFIS_REG_D2H
  53. {
  54. // DWORD 0
  55. uint8_t fis_type; // FIS_TYPE_REG_D2H
  56. uint8_t pmport : 4; // Port multiplier
  57. uint8_t rsv0 : 2; // Reserved
  58. uint8_t i : 1; // Interrupt bit
  59. uint8_t rsv1 : 1; // Reserved
  60. uint8_t status; // Status register
  61. uint8_t error; // Error register
  62. // DWORD 1
  63. uint8_t lba0; // LBA low register, 7:0
  64. uint8_t lba1; // LBA mid register, 15:8
  65. uint8_t lba2; // LBA high register, 23:16
  66. uint8_t device; // Device register
  67. // DWORD 2
  68. uint8_t lba3; // LBA register, 31:24
  69. uint8_t lba4; // LBA register, 39:32
  70. uint8_t lba5; // LBA register, 47:40
  71. uint8_t rsv2; // Reserved
  72. // DWORD 3
  73. uint8_t countl; // Count register, 7:0
  74. uint8_t counth; // Count register, 15:8
  75. uint8_t rsv3[2]; // Reserved
  76. // DWORD 4
  77. uint8_t rsv4[4]; // Reserved
  78. } FIS_REG_D2H;
  79. // This FIS is used by the host or device to send data payload. The data size can be varied.
  80. typedef struct tagFIS_DATA
  81. {
  82. // DWORD 0
  83. uint8_t fis_type; // FIS_TYPE_DATA
  84. uint8_t pmport : 4; // Port multiplier
  85. uint8_t rsv0 : 4; // Reserved
  86. uint8_t rsv1[2]; // Reserved
  87. // DWORD 1 ~ N
  88. uint32_t data[1]; // Payload
  89. } FIS_DATA;
  90. // This FIS is used by the device to tell the host that it’s about to send or ready to receive a PIO data payload.
  91. typedef struct tagFIS_PIO_SETUP
  92. {
  93. // DWORD 0
  94. uint8_t fis_type; // FIS_TYPE_PIO_SETUP
  95. uint8_t pmport : 4; // Port multiplier
  96. uint8_t rsv0 : 1; // Reserved
  97. uint8_t d : 1; // Data transfer direction, 1 - device to host
  98. uint8_t i : 1; // Interrupt bit
  99. uint8_t rsv1 : 1;
  100. uint8_t status; // Status register
  101. uint8_t error; // Error register
  102. // DWORD 1
  103. uint8_t lba0; // LBA low register, 7:0
  104. uint8_t lba1; // LBA mid register, 15:8
  105. uint8_t lba2; // LBA high register, 23:16
  106. uint8_t device; // Device register
  107. // DWORD 2
  108. uint8_t lba3; // LBA register, 31:24
  109. uint8_t lba4; // LBA register, 39:32
  110. uint8_t lba5; // LBA register, 47:40
  111. uint8_t rsv2; // Reserved
  112. // DWORD 3
  113. uint8_t countl; // Count register, 7:0
  114. uint8_t counth; // Count register, 15:8
  115. uint8_t rsv3; // Reserved
  116. uint8_t e_status; // New value of status register
  117. // DWORD 4
  118. uint16_t tc; // Transfer count
  119. uint8_t rsv4[2]; // Reserved
  120. } FIS_PIO_SETUP;
  121. typedef struct tagFIS_DMA_SETUP
  122. {
  123. // DWORD 0
  124. uint8_t fis_type; // FIS_TYPE_DMA_SETUP
  125. uint8_t pmport : 4; // Port multiplier
  126. uint8_t rsv0 : 1; // Reserved
  127. uint8_t d : 1; // Data transfer direction, 1 - device to host
  128. uint8_t i : 1; // Interrupt bit
  129. uint8_t a : 1; // Auto-activate. Specifies if DMA Activate FIS is needed
  130. uint8_t rsved[2]; // Reserved
  131. // DWORD 1&2
  132. uint64_t DMAbufferID; // DMA Buffer Identifier. Used to Identify DMA buffer in host memory.
  133. // SATA Spec says host specific and not in Spec. Trying AHCI spec might work.
  134. // DWORD 3
  135. uint32_t rsvd; // More reserved
  136. // DWORD 4
  137. uint32_t DMAbufOffset; // Byte offset into buffer. First 2 bits must be 0
  138. // DWORD 5
  139. uint32_t TransferCount; // Number of bytes to transfer. Bit 0 must be 0
  140. // DWORD 6
  141. uint32_t resvd; // Reserved
  142. } FIS_DMA_SETUP;
  143. typedef volatile struct tagHBA_PORT
  144. {
  145. uint32_t clb; // 0x00, command list base address, 1K-byte aligned
  146. uint32_t clbu; // 0x04, command list base address upper 32 bits
  147. uint32_t fb; // 0x08, FIS base address, 256-byte aligned
  148. uint32_t fbu; // 0x0C, FIS base address upper 32 bits
  149. uint32_t is; // 0x10, interrupt status
  150. uint32_t ie; // 0x14, interrupt enable
  151. uint32_t cmd; // 0x18, command and status
  152. uint32_t rsv0; // 0x1C, Reserved
  153. uint32_t tfd; // 0x20, task file data
  154. uint32_t sig; // 0x24, signature
  155. uint32_t ssts; // 0x28, SATA status (SCR0:SStatus)
  156. uint32_t sctl; // 0x2C, SATA control (SCR2:SControl)
  157. uint32_t serr; // 0x30, SATA error (SCR1:SError)
  158. uint32_t sact; // 0x34, SATA active (SCR3:SActive)
  159. uint32_t ci; // 0x38, command issue
  160. uint32_t sntf; // 0x3C, SATA notification (SCR4:SNotification)
  161. uint32_t fbs; // 0x40, FIS-based switch control
  162. uint32_t rsv1[11]; // 0x44 ~ 0x6F, Reserved
  163. uint32_t vendor[4]; // 0x70 ~ 0x7F, vendor specific
  164. } HBA_PORT;
  165. typedef volatile struct tagHBA_MEM
  166. {
  167. // 0x00 - 0x2B, Generic Host Control
  168. uint32_t cap; // 0x00, Host capability
  169. uint32_t ghc; // 0x04, Global host control
  170. uint32_t is; // 0x08, Interrupt status
  171. uint32_t pi; // 0x0C, Port implemented
  172. uint32_t vs; // 0x10, Version
  173. uint32_t ccc_ctl; // 0x14, Command completion coalescing control
  174. uint32_t ccc_pts; // 0x18, Command completion coalescing ports
  175. uint32_t em_loc; // 0x1C, Enclosure management location
  176. uint32_t em_ctl; // 0x20, Enclosure management control
  177. uint32_t cap2; // 0x24, Host capabilities extended
  178. uint32_t bohc; // 0x28, BIOS/OS handoff control and status
  179. // 0x2C - 0x9F, Reserved
  180. uint8_t rsv[0xA0-0x2C];
  181. // 0xA0 - 0xFF, Vendor specific registers
  182. uint8_t vendor[0x100-0xA0];
  183. // 0x100 - 0x10FF, Port control registers
  184. HBA_PORT ports[1]; // 1 ~ 32
  185. } HBA_MEM;
  186. // There are four kinds of FIS which may be sent to the host by the device as indicated in the following structure declaration.
  187. //
  188. typedef volatile struct tagHBA_FIS
  189. {
  190. // 0x00
  191. FIS_DMA_SETUP dsfis; // DMA Setup FIS
  192. uint8_t pad0[4];
  193. // 0x20
  194. FIS_PIO_SETUP psfis; // PIO Setup FIS
  195. uint8_t pad1[12];
  196. // 0x40
  197. FIS_REG_D2H rfis; // Register – Device to Host FIS
  198. uint8_t pad2[4];
  199. // 0x58
  200. //FIS_DEV_BITS sdbfis; // Set Device Bit FIS
  201. // 0x60
  202. uint8_t ufis[64];
  203. // 0xA0
  204. uint8_t rsv[0x100-0xA0];
  205. } HBA_FIS;
  206. typedef struct tagHBA_CMD_HEADER
  207. {
  208. // DW0
  209. uint8_t cfl:5; // Command FIS length in DWORDS, 2 ~ 16
  210. uint8_t a:1; // ATAPI
  211. uint8_t w:1; // Write, 1: H2D, 0: D2H
  212. uint8_t p:1; // Prefetchable
  213. uint8_t r:1; // Reset
  214. uint8_t b:1; // BIST
  215. uint8_t c:1; // Clear busy upon R_OK
  216. uint8_t rsv0:1; // Reserved
  217. uint8_t pmp:4; // Port multiplier port
  218. uint16_t prdtl; // Physical region descriptor table length in entries
  219. // DW1
  220. volatile
  221. uint32_t prdbc; // Physical region descriptor byte count transferred
  222. // DW2, 3
  223. uint32_t ctba; // Command table descriptor base address
  224. uint32_t ctbau; // Command table descriptor base address upper 32 bits
  225. // DW4 - 7
  226. uint32_t rsv1[4]; // Reserved
  227. } HBA_CMD_HEADER;
  228. typedef struct tagHBA_PRDT_ENTRY
  229. {
  230. uint32_t dba; // Data base address
  231. uint32_t dbau; // Data base address upper 32 bits
  232. uint32_t rsv0; // Reserved
  233. // DW3
  234. uint32_t dbc:22; // Byte count, 4M max
  235. uint32_t rsv1:9; // Reserved
  236. uint32_t i:1; // Interrupt on completion
  237. } HBA_PRDT_ENTRY;
  238. typedef struct tagHBA_CMD_TBL
  239. {
  240. // 0x00
  241. uint8_t cfis[64]; // Command FIS
  242. // 0x40
  243. uint8_t acmd[16]; // ATAPI command, 12 or 16 bytes
  244. // 0x50
  245. uint8_t rsv[48]; // Reserved
  246. // 0x80
  247. HBA_PRDT_ENTRY prdt_entry[1]; // Physical region descriptor table entries, 0 ~ 65535
  248. } HBA_CMD_TBL;
  249. #define SATA_SIG_ATA 0x00000101 // SATA drive
  250. #define SATA_SIG_ATAPI 0xEB140101 // SATAPI drive
  251. #define SATA_SIG_SEMB 0xC33C0101 // Enclosure management bridge
  252. #define SATA_SIG_PM 0x96690101 // Port multiplier
  253. #define AHCI_DEV_NULL 0
  254. #define AHCI_DEV_SATA 1
  255. #define AHCI_DEV_SEMB 2
  256. #define AHCI_DEV_PM 3
  257. #define AHCI_DEV_SATAPI 4
  258. #define HBA_PORT_IPM_ACTIVE 1
  259. #define HBA_PORT_DET_PRESENT 3
  260. struct block_device_request_queue ahci_req_queue;
  261. /*
  262. struct block_device_operation ahci_operation =
  263. {
  264. .open = ahci_open,
  265. .close = ahci_close,
  266. .ioctl = ahci_ioctl,
  267. .transfer = ahci_transfer,
  268. };
  269. */
  270. /**
  271. * @brief 初始化ahci模块
  272. *
  273. */
  274. void ahci_init();