AHCI.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437
  1. /*
  2. * Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #pragma once
  7. #include <AK/Types.h>
  8. namespace Kernel::FIS {
  9. enum class Type : u8 {
  10. RegisterHostToDevice = 0x27,
  11. RegisterDeviceToHost = 0x34,
  12. DMAActivate = 0x39,
  13. DMASetup = 0x41,
  14. Data = 0x46,
  15. BISTActivate = 0x58,
  16. PIOSetup = 0x5F,
  17. SetDeviceBits = 0xA1
  18. };
  19. enum class DwordCount : size_t {
  20. RegisterHostToDevice = 5,
  21. RegisterDeviceToHost = 5,
  22. DMAActivate = 1,
  23. DMASetup = 7,
  24. PIOSetup = 5,
  25. SetDeviceBits = 2
  26. };
  27. enum HeaderAttributes : u8 {
  28. C = (1 << 7), /* Updates Command register */
  29. };
  30. struct [[gnu::packed]] Header {
  31. u8 fis_type;
  32. u8 port_muliplier;
  33. };
  34. }
  35. namespace Kernel::FIS::HostToDevice {
  36. struct [[gnu::packed]] Register {
  37. Header header;
  38. u8 command;
  39. u8 features_low;
  40. u8 lba_low[3];
  41. u8 device;
  42. u8 lba_high[3];
  43. u8 features_high;
  44. u16 count;
  45. u8 icc; /* Isochronous Command Completion */
  46. u8 control;
  47. u32 reserved;
  48. };
  49. };
  50. namespace Kernel::FIS::DeviceToHost {
  51. struct [[gnu::packed]] Register {
  52. Header header;
  53. u8 status;
  54. u8 error;
  55. u8 lba_low[3];
  56. u8 device;
  57. u8 lba_high[3];
  58. u8 reserved;
  59. u16 count;
  60. u8 reserved2[6];
  61. };
  62. struct [[gnu::packed]] SetDeviceBits {
  63. Header header;
  64. u8 status;
  65. u8 error;
  66. u32 protocol_specific;
  67. };
  68. struct [[gnu::packed]] DMAActivate {
  69. Header header;
  70. u16 reserved;
  71. };
  72. struct [[gnu::packed]] PIOSetup {
  73. Header header;
  74. u8 status;
  75. u8 error;
  76. u8 lba_low[3];
  77. u8 device;
  78. u8 lba_high[3];
  79. u8 reserved;
  80. u16 count;
  81. u8 reserved2;
  82. u8 e_status;
  83. u16 transfer_count;
  84. u16 reserved3;
  85. };
  86. }
  87. namespace Kernel::FIS::BiDirectional {
  88. struct [[gnu::packed]] Data {
  89. Header header;
  90. u16 reserved;
  91. u32 data[];
  92. };
  93. struct [[gnu::packed]] BISTActivate {
  94. };
  95. struct [[gnu::packed]] DMASetup {
  96. Header header;
  97. u16 reserved;
  98. u32 dma_buffer_identifier_low;
  99. u32 dma_buffer_identifier_high;
  100. u32 reserved2;
  101. u32 dma_buffer_offset;
  102. u32 dma_transfer_count;
  103. u32 reserved3;
  104. };
  105. }
  106. namespace Kernel::AHCI {
  107. class MaskedBitField {
  108. public:
  109. explicit MaskedBitField(volatile u32& bitfield_register)
  110. : m_bitfield(bitfield_register)
  111. , m_bit_mask(0xffffffff)
  112. {
  113. }
  114. MaskedBitField(volatile u32& bitfield_register, u32 bit_mask)
  115. : m_bitfield(bitfield_register)
  116. , m_bit_mask(bit_mask)
  117. {
  118. }
  119. void set_at(u8 index) const
  120. {
  121. VERIFY(((1u << index) & m_bit_mask) != 0);
  122. m_bitfield = m_bitfield | ((1u << index) & m_bit_mask);
  123. }
  124. void set_all() const
  125. {
  126. m_bitfield = m_bitfield | (0xffffffff & m_bit_mask);
  127. }
  128. bool is_set_at(u8 port_index) const
  129. {
  130. return m_bitfield & ((1u << port_index) & m_bit_mask);
  131. }
  132. bool is_zeroed() const
  133. {
  134. return (m_bitfield & m_bit_mask) == 0;
  135. }
  136. Vector<u8> to_vector() const
  137. {
  138. // FIXME: Add a sync mechanism!
  139. Vector<u8> indices;
  140. u32 bitfield = m_bitfield & m_bit_mask;
  141. for (size_t index = 0; index < 32; index++) {
  142. if (bitfield & 1) {
  143. indices.append(index);
  144. }
  145. bitfield >>= 1;
  146. }
  147. return indices;
  148. }
  149. u32 bit_mask() const { return m_bit_mask; };
  150. // Disable default implementations that would use surprising integer promotion.
  151. bool operator==(const MaskedBitField&) const = delete;
  152. bool operator<=(const MaskedBitField&) const = delete;
  153. bool operator>=(const MaskedBitField&) const = delete;
  154. bool operator<(const MaskedBitField&) const = delete;
  155. bool operator>(const MaskedBitField&) const = delete;
  156. private:
  157. volatile u32& m_bitfield;
  158. const u32 m_bit_mask;
  159. };
  160. enum Limits : u16 {
  161. MaxPorts = 32,
  162. MaxCommands = 32,
  163. MaxMultiplierConnectedPorts = 16,
  164. };
  165. enum CommandHeaderAttributes : u16 {
  166. C = (1 << 10), /* Clear Busy upon R_OK */
  167. P = (1 << 7), /* Prefetchable */
  168. W = (1 << 6), /* Write */
  169. A = (1 << 5), /* ATAPI */
  170. R = (1 << 8) /* Reset */
  171. };
  172. enum HBACapabilities : u32 {
  173. S64A = (u32)1 << 31, /* Supports 64-bit Addressing */
  174. SNCQ = 1 << 30, /* Supports Native Command Queuing */
  175. SSNTF = 1 << 29, /* Supports SNotification Register */
  176. SMPS = 1 << 28, /* Supports Mechanical Presence Switch */
  177. SSS = 1 << 27, /* Supports Staggered Spin-up */
  178. SALP = 1 << 26, /* Supports Aggressive Link Power Management */
  179. SAL = 1 << 25, /* Supports Activity LED */
  180. SCLO = 1 << 24, /* Supports Command List Override */
  181. SAM = 1 << 18, /* Supports AHCI mode only */
  182. SPM = 1 << 17, /* Supports Port Multiplier */
  183. FBSS = 1 << 16, /* FIS-based Switching Supported */
  184. PMD = 1 << 15, /* PIO Multiple DRQ Block */
  185. SSC = 1 << 14, /* Slumber State Capable */
  186. PSC = 1 << 13, /* Partial State Capable */
  187. CCCS = 1 << 7, /* Command Completion Coalescing Supported */
  188. EMS = 1 << 6, /* Enclosure Management Supported */
  189. SXS = 1 << 5 /* Supports External SATA */
  190. };
  191. enum HBACapabilitiesExtended : u32 {
  192. DESO = 1 << 5, /* DevSleep Entrance from Slumber Only */
  193. SADM = 1 << 4, /* Supports Aggressive Device Sleep Management */
  194. SDS = 1 << 3, /* Supports Device Sleep */
  195. APST = 1 << 2, /* Automatic Partial to Slumber Transitions */
  196. NVMP = 1 << 1, /* NVMHCI Present */
  197. BOH = 1 << 0, /* BIOS/OS Handoff */
  198. };
  199. // This structure is not defined by the AHCI spec, but is used within the code
  200. struct [[gnu::packed]] HBADefinedCapabilities {
  201. size_t ports_count { 1 };
  202. size_t max_command_list_entries_count { 1 };
  203. u8 interface_speed_generation { 1 };
  204. bool external_sata_supported : 1 { false };
  205. bool enclosure_management_supported : 1 { false };
  206. bool command_completion_coalescing_supported : 1 { false };
  207. bool partial_state_capable : 1 { false };
  208. bool slumber_state_capable : 1 { false };
  209. bool pio_multiple_drq_block : 1 { false };
  210. bool fis_based_switching_supported : 1 { false };
  211. bool port_multiplier_supported : 1 { false };
  212. bool ahci_mode_only : 1 { true };
  213. bool command_list_override_supported : 1 { false };
  214. bool activity_led_supported : 1 { false };
  215. bool aggressive_link_power_management_supported : 1 { false };
  216. bool staggered_spin_up_supported : 1 { false };
  217. bool mechanical_presence_switch_supported : 1 { false };
  218. bool snotification_register_supported : 1 { false };
  219. bool native_command_queuing_supported : 1 { false };
  220. bool addressing_64_bit_supported : 1 { false };
  221. bool bios_os_handoff : 1 { false };
  222. bool nvmhci_present : 1 { false };
  223. bool automatic_partial_to_slumber_transitions : 1 { false };
  224. bool device_sleep_supported : 1 { false };
  225. bool aggressive_device_sleep_management_supported : 1 { false };
  226. bool devsleep_entrance_from_slumber_only : 1 { false };
  227. };
  228. enum DeviceSignature : u32 {
  229. ATA = 0x00000101,
  230. ATAPI = 0xEB140101,
  231. EnclosureManagementBridge = 0xC33C0101,
  232. PortMultiplier = 0x96690101,
  233. Unconnected = 0xFFFFFFFF
  234. };
  235. enum class DeviceDetectionInitialization {
  236. NoActionRequested,
  237. PerformInterfaceInitializationSequence,
  238. DisableInterface
  239. };
  240. enum PortInterruptFlag : u32 {
  241. CPD = (u32)1 << 31, /* Cold Port Detect */
  242. TFE = 1 << 30, /* Task File Error */
  243. HBF = 1 << 29, /* Host Bus Fatal Error */
  244. HBD = 1 << 28, /* Host Bus Data Error */
  245. IF = 1 << 27, /* Interface Fatal Error */
  246. INF = 1 << 26, /* Interface Non-fatal Error */
  247. OF = 1 << 24, /* Overflow */
  248. IPM = 1 << 23, /* Incorrect Port Multiplier */
  249. PRC = 1 << 22, /* PhyRdy Change */
  250. DMP = 1 << 7, /* Device Mechanical Presence */
  251. PC = 1 << 6, /* Port Connect Change */
  252. DP = 1 << 5, /* Descriptor Processed */
  253. UF = 1 << 4, /* Unknown FIS */
  254. SDB = 1 << 3, /* Set Device FIS */
  255. DS = 1 << 2, /* DMA Setup FIS */
  256. PS = 1 << 1, /* PIO Setup FIS */
  257. DHR = 1 << 0 /* Device to Host Register FIS */
  258. };
  259. enum SErr : u32 {
  260. DIAG_X = 1 << 26, /* Exchanged */
  261. DIAG_F = 1 << 25, /* Unknown FIS Type */
  262. DIAG_T = 1 << 24, /* Transport state transition error */
  263. DIAG_S = 1 << 23, /* Link sequence error */
  264. DIAG_H = 1 << 22, /* Handshake error */
  265. DIAG_C = 1 << 21, /* CRC error */
  266. DIAG_D = 1 << 20, /* Disparity error */
  267. DIAG_B = 1 << 19, /* 10B to 8B decode error */
  268. DIAG_W = 1 << 18, /* Comm Wake */
  269. DIAG_I = 1 << 17, /* Phy Internal Error */
  270. DIAG_N = 1 << 16, /* PhyRdy Change */
  271. ERR_E = 1 << 11, /* Internal error */
  272. ERR_P = 1 << 10, /* Protocol error */
  273. ERR_C = 1 << 9, /* Persistent communication or data integrity error */
  274. ERR_T = 1 << 8, /* Transient data integrity error */
  275. ERR_M = 1 << 1, /* Received communications error */
  276. ERR_I = 1 << 0, /* Recovered data integrity error */
  277. };
  278. class PortInterruptStatusBitField {
  279. public:
  280. explicit PortInterruptStatusBitField(volatile u32& bitfield_register)
  281. : m_bitfield(bitfield_register)
  282. {
  283. }
  284. u32 raw_value() const { return m_bitfield; }
  285. bool is_set(PortInterruptFlag flag) const { return m_bitfield & (u32)flag; }
  286. void clear() { m_bitfield = 0xffffffff; }
  287. // Disable default implementations that would use surprising integer promotion.
  288. bool operator==(const MaskedBitField&) const = delete;
  289. bool operator<=(const MaskedBitField&) const = delete;
  290. bool operator>=(const MaskedBitField&) const = delete;
  291. bool operator<(const MaskedBitField&) const = delete;
  292. bool operator>(const MaskedBitField&) const = delete;
  293. private:
  294. volatile u32& m_bitfield;
  295. };
  296. class PortInterruptEnableBitField {
  297. public:
  298. explicit PortInterruptEnableBitField(volatile u32& bitfield_register)
  299. : m_bitfield(bitfield_register)
  300. {
  301. }
  302. u32 raw_value() const { return m_bitfield; }
  303. bool is_set(PortInterruptFlag flag) { return m_bitfield & (u32)flag; }
  304. void set_at(PortInterruptFlag flag) { m_bitfield = m_bitfield | static_cast<u32>(flag); }
  305. void clear() { m_bitfield = 0; }
  306. bool is_cleared() const { return m_bitfield == 0; }
  307. void set_all() { m_bitfield = 0xffffffff; }
  308. // Disable default implementations that would use surprising integer promotion.
  309. bool operator==(const MaskedBitField&) const = delete;
  310. bool operator<=(const MaskedBitField&) const = delete;
  311. bool operator>=(const MaskedBitField&) const = delete;
  312. bool operator<(const MaskedBitField&) const = delete;
  313. bool operator>(const MaskedBitField&) const = delete;
  314. private:
  315. volatile u32& m_bitfield;
  316. };
  317. struct [[gnu::packed]] PortRegisters {
  318. u32 clb; /* Port x Command List Base Address */
  319. u32 clbu; /* Port x Command List Base Address Upper 32-Bits */
  320. u32 fb; /* Port x FIS Base Address */
  321. u32 fbu; /* Port x FIS Base Address Upper 32-Bits */
  322. u32 is; /* Port x Interrupt Status */
  323. u32 ie; /* Port x Interrupt Enable */
  324. u32 cmd; /* Port x Command and Status */
  325. u32 reserved;
  326. u32 tfd; /* Port x Task File Data */
  327. u32 sig; /* Port x Signature */
  328. u32 ssts; /* Port x Serial ATA Status (SCR0: SStatus) */
  329. u32 sctl; /* Port x Serial ATA Control (SCR2: SControl) */
  330. u32 serr; /* Port x Serial ATA Error (SCR1: SError) */
  331. u32 sact; /* Port x Serial ATA Active (SCR3: SActive) */
  332. u32 ci; /* Port x Command Issue */
  333. u32 sntf; /* Port x Serial ATA Notification (SCR4: SNotification) */
  334. u32 fbs; /* Port x FIS-based Switching Control */
  335. u32 devslp; /* Port x Device Sleep */
  336. u8 reserved2[0x70 - 0x48];
  337. u8 vs[16]; /* Port x Vendor Specific */
  338. };
  339. struct [[gnu::packed]] GenericHostControl {
  340. u32 cap; /* Host Capabilities */
  341. u32 ghc; /* Global Host Control */
  342. u32 is; /* Interrupt Status */
  343. u32 pi; /* Ports Implemented */
  344. u32 version;
  345. u32 ccc_ctl; /* Command Completion Coalescing Control */
  346. u32 ccc_ports; /* Command Completion Coalsecing Ports */
  347. u32 em_loc; /* Enclosure Management Location */
  348. u32 em_ctl; /* Enclosure Management Control */
  349. u32 cap2; /* Host Capabilities Extended */
  350. u32 bohc; /* BIOS/OS Handoff Control and Status */
  351. };
  352. struct [[gnu::packed]] HBA {
  353. GenericHostControl control_regs;
  354. u8 reserved[52];
  355. u8 nvmhci[64];
  356. u8 vendor_specific[96];
  357. PortRegisters port_regs[32];
  358. };
  359. struct [[gnu::packed]] CommandHeader {
  360. u16 attributes;
  361. u16 prdtl; /* Physical Region Descriptor Table Length */
  362. u32 prdbc; /* Physical Region Descriptor Byte Count */
  363. u32 ctba; /* Command Table Descriptor Base Address */
  364. u32 ctbau; /* Command Table Descriptor Base Address Upper 32-bits */
  365. u32 reserved[4];
  366. };
  367. struct [[gnu::packed]] PhysicalRegionDescriptor {
  368. u32 base_low;
  369. u32 base_high;
  370. u32 reserved;
  371. u32 byte_count; /* Bit 31 - Interrupt completion, Bit 0 to 21 - Data Byte Count */
  372. };
  373. struct [[gnu::packed]] CommandTable {
  374. u8 command_fis[64];
  375. u8 atapi_command[32];
  376. u8 reserved[32];
  377. PhysicalRegionDescriptor descriptors[];
  378. };
  379. }