AhciMode.c 61 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008
  1. /** @file
  2. The AhciPei driver is used to manage ATA hard disk device working under AHCI
  3. mode at PEI phase.
  4. Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
  5. SPDX-License-Identifier: BSD-2-Clause-Patent
  6. **/
  7. #include "AhciPei.h"
  8. #define ATA_CMD_TRUST_NON_DATA 0x5B
  9. #define ATA_CMD_TRUST_RECEIVE 0x5C
  10. #define ATA_CMD_TRUST_SEND 0x5E
  11. //
  12. // Look up table (IsWrite) for EFI_ATA_PASS_THRU_CMD_PROTOCOL
  13. //
  14. EFI_ATA_PASS_THRU_CMD_PROTOCOL mAtaPassThruCmdProtocols[2] = {
  15. EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_IN,
  16. EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_OUT
  17. };
  18. //
  19. // Look up table (Lba48Bit, IsIsWrite) for ATA_CMD
  20. //
  21. UINT8 mAtaCommands[2][2] = {
  22. {
  23. ATA_CMD_READ_SECTORS, // 28-bit LBA; PIO read
  24. ATA_CMD_WRITE_SECTORS // 28-bit LBA; PIO write
  25. },
  26. {
  27. ATA_CMD_READ_SECTORS_EXT, // 48-bit LBA; PIO read
  28. ATA_CMD_WRITE_SECTORS_EXT // 48-bit LBA; PIO write
  29. }
  30. };
  31. //
  32. // Look up table (IsTrustSend) for ATA_CMD
  33. //
  34. UINT8 mAtaTrustCommands[2] = {
  35. ATA_CMD_TRUST_RECEIVE, // PIO read
  36. ATA_CMD_TRUST_SEND // PIO write
  37. };
  38. //
  39. // Look up table (Lba48Bit) for maximum transfer block number
  40. //
  41. #define MAX_28BIT_TRANSFER_BLOCK_NUM 0x100
  42. #define MAX_48BIT_TRANSFER_BLOCK_NUM 0xFFFF
  43. UINT32 mMaxTransferBlockNumber[2] = {
  44. MAX_28BIT_TRANSFER_BLOCK_NUM,
  45. MAX_48BIT_TRANSFER_BLOCK_NUM
  46. };
  47. //
  48. // The maximum total sectors count in 28 bit addressing mode
  49. //
  50. #define MAX_28BIT_ADDRESSING_CAPACITY 0xfffffff
  51. /**
  52. Read AHCI Operation register.
  53. @param[in] AhciBar AHCI bar address.
  54. @param[in] Offset The operation register offset.
  55. @return The register content read.
  56. **/
  57. UINT32
  58. AhciReadReg (
  59. IN UINTN AhciBar,
  60. IN UINT32 Offset
  61. )
  62. {
  63. UINT32 Data;
  64. Data = 0;
  65. Data = MmioRead32 (AhciBar + Offset);
  66. return Data;
  67. }
  68. /**
  69. Write AHCI Operation register.
  70. @param[in] AhciBar AHCI bar address.
  71. @param[in] Offset The operation register offset.
  72. @param[in] Data The Data used to write down.
  73. **/
  74. VOID
  75. AhciWriteReg (
  76. IN UINTN AhciBar,
  77. IN UINT32 Offset,
  78. IN UINT32 Data
  79. )
  80. {
  81. MmioWrite32 (AhciBar + Offset, Data);
  82. }
  83. /**
  84. Do AND operation with the value of AHCI Operation register.
  85. @param[in] AhciBar AHCI bar address.
  86. @param[in] Offset The operation register offset.
  87. @param[in] AndData The data used to do AND operation.
  88. **/
  89. VOID
  90. AhciAndReg (
  91. IN UINTN AhciBar,
  92. IN UINT32 Offset,
  93. IN UINT32 AndData
  94. )
  95. {
  96. UINT32 Data;
  97. Data = AhciReadReg (AhciBar, Offset);
  98. Data &= AndData;
  99. AhciWriteReg (AhciBar, Offset, Data);
  100. }
  101. /**
  102. Do OR operation with the Value of AHCI Operation register.
  103. @param[in] AhciBar AHCI bar address.
  104. @param[in] Offset The operation register offset.
  105. @param[in] OrData The Data used to do OR operation.
  106. **/
  107. VOID
  108. AhciOrReg (
  109. IN UINTN AhciBar,
  110. IN UINT32 Offset,
  111. IN UINT32 OrData
  112. )
  113. {
  114. UINT32 Data;
  115. Data = AhciReadReg (AhciBar, Offset);
  116. Data |= OrData;
  117. AhciWriteReg (AhciBar, Offset, Data);
  118. }
  119. /**
  120. Wait for memory set to the test Value.
  121. @param[in] AhciBar AHCI bar address.
  122. @param[in] Offset The memory offset to test.
  123. @param[in] MaskValue The mask Value of memory.
  124. @param[in] TestValue The test Value of memory.
  125. @param[in] Timeout The timeout, in 100ns units, for wait memory set.
  126. @retval EFI_DEVICE_ERROR The memory is not set.
  127. @retval EFI_TIMEOUT The memory setting is time out.
  128. @retval EFI_SUCCESS The memory is correct set.
  129. **/
  130. EFI_STATUS
  131. EFIAPI
  132. AhciWaitMmioSet (
  133. IN UINTN AhciBar,
  134. IN UINT32 Offset,
  135. IN UINT32 MaskValue,
  136. IN UINT32 TestValue,
  137. IN UINT64 Timeout
  138. )
  139. {
  140. UINT32 Value;
  141. UINT32 Delay;
  142. Delay = (UINT32) (DivU64x32(Timeout, 1000) + 1);
  143. do {
  144. Value = AhciReadReg (AhciBar, Offset) & MaskValue;
  145. if (Value == TestValue) {
  146. return EFI_SUCCESS;
  147. }
  148. //
  149. // Stall for 100 microseconds.
  150. //
  151. MicroSecondDelay (100);
  152. Delay--;
  153. } while (Delay > 0);
  154. return EFI_TIMEOUT;
  155. }
  156. /**
  157. Check the memory status to the test value.
  158. @param[in] Address The memory address to test.
  159. @param[in] MaskValue The mask value of memory.
  160. @param[in] TestValue The test value of memory.
  161. @retval EFI_NOT_READY The memory is not set.
  162. @retval EFI_SUCCESS The memory is correct set.
  163. **/
  164. EFI_STATUS
  165. AhciCheckMemSet (
  166. IN UINTN Address,
  167. IN UINT32 MaskValue,
  168. IN UINT32 TestValue
  169. )
  170. {
  171. UINT32 Value;
  172. Value = *(volatile UINT32 *) Address;
  173. Value &= MaskValue;
  174. if (Value == TestValue) {
  175. return EFI_SUCCESS;
  176. } else {
  177. return EFI_NOT_READY;
  178. }
  179. }
  180. /**
  181. Wait for the value of the specified system memory set to the test value.
  182. @param[in] Address The system memory address to test.
  183. @param[in] MaskValue The mask value of memory.
  184. @param[in] TestValue The test value of memory.
  185. @param[in] Timeout The timeout, in 100ns units, for wait memory set.
  186. @retval EFI_TIMEOUT The system memory setting is time out.
  187. @retval EFI_SUCCESS The system memory is correct set.
  188. **/
  189. EFI_STATUS
  190. AhciWaitMemSet (
  191. IN EFI_PHYSICAL_ADDRESS Address,
  192. IN UINT32 MaskValue,
  193. IN UINT32 TestValue,
  194. IN UINT64 Timeout
  195. )
  196. {
  197. UINT32 Value;
  198. UINT64 Delay;
  199. BOOLEAN InfiniteWait;
  200. if (Timeout == 0) {
  201. InfiniteWait = TRUE;
  202. } else {
  203. InfiniteWait = FALSE;
  204. }
  205. Delay = DivU64x32 (Timeout, 1000) + 1;
  206. do {
  207. //
  208. // Access sytem memory to see if the value is the tested one.
  209. //
  210. // The system memory pointed by Address will be updated by the
  211. // SATA Host Controller, "volatile" is introduced to prevent
  212. // compiler from optimizing the access to the memory address
  213. // to only read once.
  214. //
  215. Value = *(volatile UINT32 *) (UINTN) Address;
  216. Value &= MaskValue;
  217. if (Value == TestValue) {
  218. return EFI_SUCCESS;
  219. }
  220. //
  221. // Stall for 100 microseconds.
  222. //
  223. MicroSecondDelay (100);
  224. Delay--;
  225. } while (InfiniteWait || (Delay > 0));
  226. return EFI_TIMEOUT;
  227. }
  228. /**
  229. Clear the port interrupt and error status. It will also clear HBA interrupt
  230. status.
  231. @param[in] AhciBar AHCI bar address.
  232. @param[in] Port The number of port.
  233. **/
  234. VOID
  235. AhciClearPortStatus (
  236. IN UINTN AhciBar,
  237. IN UINT8 Port
  238. )
  239. {
  240. UINT32 Offset;
  241. //
  242. // Clear any error status
  243. //
  244. Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_SERR;
  245. AhciWriteReg (AhciBar, Offset, AhciReadReg (AhciBar, Offset));
  246. //
  247. // Clear any port interrupt status
  248. //
  249. Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_IS;
  250. AhciWriteReg (AhciBar, Offset, AhciReadReg (AhciBar, Offset));
  251. //
  252. // Clear any HBA interrupt status
  253. //
  254. AhciWriteReg (AhciBar, AHCI_IS_OFFSET, AhciReadReg (AhciBar, AHCI_IS_OFFSET));
  255. }
  256. /**
  257. Enable the FIS running for giving port.
  258. @param[in] AhciBar AHCI bar address.
  259. @param[in] Port The number of port.
  260. @param[in] Timeout The timeout, in 100ns units, to enabling FIS.
  261. @retval EFI_DEVICE_ERROR The FIS enable setting fails.
  262. @retval EFI_TIMEOUT The FIS enable setting is time out.
  263. @retval EFI_SUCCESS The FIS enable successfully.
  264. **/
  265. EFI_STATUS
  266. AhciEnableFisReceive (
  267. IN UINTN AhciBar,
  268. IN UINT8 Port,
  269. IN UINT64 Timeout
  270. )
  271. {
  272. UINT32 Offset;
  273. Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_CMD;
  274. AhciOrReg (AhciBar, Offset, AHCI_PORT_CMD_FRE);
  275. return EFI_SUCCESS;
  276. }
  277. /**
  278. Disable the FIS running for giving port.
  279. @param[in] AhciBar AHCI bar address.
  280. @param[in] Port The number of port.
  281. @param[in] Timeout The timeout value of disabling FIS, uses 100ns as a unit.
  282. @retval EFI_DEVICE_ERROR The FIS disable setting fails.
  283. @retval EFI_TIMEOUT The FIS disable setting is time out.
  284. @retval EFI_UNSUPPORTED The port is in running state.
  285. @retval EFI_SUCCESS The FIS disable successfully.
  286. **/
  287. EFI_STATUS
  288. AhciDisableFisReceive (
  289. IN UINTN AhciBar,
  290. IN UINT8 Port,
  291. IN UINT64 Timeout
  292. )
  293. {
  294. UINT32 Offset;
  295. UINT32 Data;
  296. Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_CMD;
  297. Data = AhciReadReg (AhciBar, Offset);
  298. //
  299. // Before disabling Fis receive, the DMA engine of the port should NOT be in
  300. // running status.
  301. //
  302. if ((Data & (AHCI_PORT_CMD_ST | AHCI_PORT_CMD_CR)) != 0) {
  303. return EFI_UNSUPPORTED;
  304. }
  305. //
  306. // Check if the Fis receive DMA engine for the port is running.
  307. //
  308. if ((Data & AHCI_PORT_CMD_FR) != AHCI_PORT_CMD_FR) {
  309. return EFI_SUCCESS;
  310. }
  311. AhciAndReg (AhciBar, Offset, (UINT32)~(AHCI_PORT_CMD_FRE));
  312. return AhciWaitMmioSet (
  313. AhciBar,
  314. Offset,
  315. AHCI_PORT_CMD_FR,
  316. 0,
  317. Timeout
  318. );
  319. }
  320. /**
  321. Build the command list, command table and prepare the fis receiver.
  322. @param[in] Private The pointer to the PEI_AHCI_CONTROLLER_PRIVATE_DATA.
  323. @param[in] Port The number of port.
  324. @param[in] PortMultiplier The number of port multiplier.
  325. @param[in] FisIndex The offset index of the FIS base address.
  326. @param[in] CommandFis The control fis will be used for the transfer.
  327. @param[in] CommandList The command list will be used for the transfer.
  328. @param[in] CommandSlotNumber The command slot will be used for the transfer.
  329. @param[in,out] DataPhysicalAddr The pointer to the data buffer pci bus master
  330. address.
  331. @param[in] DataLength The data count to be transferred.
  332. **/
  333. VOID
  334. AhciBuildCommand (
  335. IN PEI_AHCI_CONTROLLER_PRIVATE_DATA *Private,
  336. IN UINT8 Port,
  337. IN UINT8 PortMultiplier,
  338. IN UINT8 FisIndex,
  339. IN EFI_AHCI_COMMAND_FIS *CommandFis,
  340. IN EFI_AHCI_COMMAND_LIST *CommandList,
  341. IN UINT8 CommandSlotNumber,
  342. IN OUT VOID *DataPhysicalAddr,
  343. IN UINT32 DataLength
  344. )
  345. {
  346. EFI_AHCI_REGISTERS *AhciRegisters;
  347. UINTN AhciBar;
  348. UINT64 BaseAddr;
  349. UINT32 PrdtNumber;
  350. UINT32 PrdtIndex;
  351. UINTN RemainedData;
  352. UINTN MemAddr;
  353. DATA_64 Data64;
  354. UINT32 Offset;
  355. AhciRegisters = &Private->AhciRegisters;
  356. AhciBar = Private->MmioBase;
  357. //
  358. // Filling the PRDT
  359. //
  360. PrdtNumber = (UINT32)DivU64x32 (
  361. (UINT64)DataLength + AHCI_MAX_DATA_PER_PRDT - 1,
  362. AHCI_MAX_DATA_PER_PRDT
  363. );
  364. //
  365. // According to AHCI 1.3 spec, a PRDT entry can point to a maximum 4MB data block.
  366. // It also limits that the maximum amount of the PRDT entry in the command table
  367. // is 65535.
  368. // Current driver implementation supports up to a maximum of AHCI_MAX_PRDT_NUMBER
  369. // PRDT entries.
  370. //
  371. ASSERT (PrdtNumber <= AHCI_MAX_PRDT_NUMBER);
  372. if (PrdtNumber > AHCI_MAX_PRDT_NUMBER) {
  373. return;
  374. }
  375. Data64.Uint64 = (UINTN) (AhciRegisters->AhciRFis) + sizeof (EFI_AHCI_RECEIVED_FIS) * FisIndex;
  376. BaseAddr = Data64.Uint64;
  377. ZeroMem ((VOID *)((UINTN) BaseAddr), sizeof (EFI_AHCI_RECEIVED_FIS));
  378. ZeroMem (AhciRegisters->AhciCmdTable, sizeof (EFI_AHCI_COMMAND_TABLE));
  379. CommandFis->AhciCFisPmNum = PortMultiplier;
  380. CopyMem (&AhciRegisters->AhciCmdTable->CommandFis, CommandFis, sizeof (EFI_AHCI_COMMAND_FIS));
  381. Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_CMD;
  382. AhciAndReg (AhciBar, Offset, (UINT32)~(AHCI_PORT_CMD_DLAE | AHCI_PORT_CMD_ATAPI));
  383. RemainedData = (UINTN) DataLength;
  384. MemAddr = (UINTN) DataPhysicalAddr;
  385. CommandList->AhciCmdPrdtl = PrdtNumber;
  386. for (PrdtIndex = 0; PrdtIndex < PrdtNumber; PrdtIndex++) {
  387. if (RemainedData < AHCI_MAX_DATA_PER_PRDT) {
  388. AhciRegisters->AhciCmdTable->PrdtTable[PrdtIndex].AhciPrdtDbc = (UINT32)RemainedData - 1;
  389. } else {
  390. AhciRegisters->AhciCmdTable->PrdtTable[PrdtIndex].AhciPrdtDbc = AHCI_MAX_DATA_PER_PRDT - 1;
  391. }
  392. Data64.Uint64 = (UINT64)MemAddr;
  393. AhciRegisters->AhciCmdTable->PrdtTable[PrdtIndex].AhciPrdtDba = Data64.Uint32.Lower32;
  394. AhciRegisters->AhciCmdTable->PrdtTable[PrdtIndex].AhciPrdtDbau = Data64.Uint32.Upper32;
  395. RemainedData -= AHCI_MAX_DATA_PER_PRDT;
  396. MemAddr += AHCI_MAX_DATA_PER_PRDT;
  397. }
  398. //
  399. // Set the last PRDT to Interrupt On Complete
  400. //
  401. if (PrdtNumber > 0) {
  402. AhciRegisters->AhciCmdTable->PrdtTable[PrdtNumber - 1].AhciPrdtIoc = 1;
  403. }
  404. CopyMem (
  405. (VOID *) ((UINTN) AhciRegisters->AhciCmdList + (UINTN) CommandSlotNumber * sizeof (EFI_AHCI_COMMAND_LIST)),
  406. CommandList,
  407. sizeof (EFI_AHCI_COMMAND_LIST)
  408. );
  409. Data64.Uint64 = (UINT64)(UINTN) AhciRegisters->AhciCmdTable;
  410. AhciRegisters->AhciCmdList[CommandSlotNumber].AhciCmdCtba = Data64.Uint32.Lower32;
  411. AhciRegisters->AhciCmdList[CommandSlotNumber].AhciCmdCtbau = Data64.Uint32.Upper32;
  412. AhciRegisters->AhciCmdList[CommandSlotNumber].AhciCmdPmp = PortMultiplier;
  413. }
  414. /**
  415. Buid a command FIS.
  416. @param[in,out] CmdFis A pointer to the EFI_AHCI_COMMAND_FIS data
  417. structure.
  418. @param[in] AtaCommandBlock A pointer to the EFI_ATA_COMMAND_BLOCK data
  419. structure.
  420. **/
  421. VOID
  422. AhciBuildCommandFis (
  423. IN OUT EFI_AHCI_COMMAND_FIS *CmdFis,
  424. IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock
  425. )
  426. {
  427. ZeroMem (CmdFis, sizeof (EFI_AHCI_COMMAND_FIS));
  428. CmdFis->AhciCFisType = AHCI_FIS_REGISTER_H2D;
  429. //
  430. // Indicator it's a command
  431. //
  432. CmdFis->AhciCFisCmdInd = 0x1;
  433. CmdFis->AhciCFisCmd = AtaCommandBlock->AtaCommand;
  434. CmdFis->AhciCFisFeature = AtaCommandBlock->AtaFeatures;
  435. CmdFis->AhciCFisFeatureExp = AtaCommandBlock->AtaFeaturesExp;
  436. CmdFis->AhciCFisSecNum = AtaCommandBlock->AtaSectorNumber;
  437. CmdFis->AhciCFisSecNumExp = AtaCommandBlock->AtaSectorNumberExp;
  438. CmdFis->AhciCFisClyLow = AtaCommandBlock->AtaCylinderLow;
  439. CmdFis->AhciCFisClyLowExp = AtaCommandBlock->AtaCylinderLowExp;
  440. CmdFis->AhciCFisClyHigh = AtaCommandBlock->AtaCylinderHigh;
  441. CmdFis->AhciCFisClyHighExp = AtaCommandBlock->AtaCylinderHighExp;
  442. CmdFis->AhciCFisSecCount = AtaCommandBlock->AtaSectorCount;
  443. CmdFis->AhciCFisSecCountExp = AtaCommandBlock->AtaSectorCountExp;
  444. CmdFis->AhciCFisDevHead = (UINT8) (AtaCommandBlock->AtaDeviceHead | 0xE0);
  445. }
  446. /**
  447. Stop command running for giving port
  448. @param[in] AhciBar AHCI bar address.
  449. @param[in] Port The number of port.
  450. @param[in] Timeout The timeout value, in 100ns units, to stop.
  451. @retval EFI_DEVICE_ERROR The command stop unsuccessfully.
  452. @retval EFI_TIMEOUT The operation is time out.
  453. @retval EFI_SUCCESS The command stop successfully.
  454. **/
  455. EFI_STATUS
  456. AhciStopCommand (
  457. IN UINTN AhciBar,
  458. IN UINT8 Port,
  459. IN UINT64 Timeout
  460. )
  461. {
  462. UINT32 Offset;
  463. UINT32 Data;
  464. Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_CMD;
  465. Data = AhciReadReg (AhciBar, Offset);
  466. if ((Data & (AHCI_PORT_CMD_ST | AHCI_PORT_CMD_CR)) == 0) {
  467. return EFI_SUCCESS;
  468. }
  469. if ((Data & AHCI_PORT_CMD_ST) != 0) {
  470. AhciAndReg (AhciBar, Offset, (UINT32)~(AHCI_PORT_CMD_ST));
  471. }
  472. return AhciWaitMmioSet (
  473. AhciBar,
  474. Offset,
  475. AHCI_PORT_CMD_CR,
  476. 0,
  477. Timeout
  478. );
  479. }
  480. /**
  481. Start command for give slot on specific port.
  482. @param[in] AhciBar AHCI bar address.
  483. @param[in] Port The number of port.
  484. @param[in] CommandSlot The number of Command Slot.
  485. @param[in] Timeout The timeout value, in 100ns units, to start.
  486. @retval EFI_DEVICE_ERROR The command start unsuccessfully.
  487. @retval EFI_TIMEOUT The operation is time out.
  488. @retval EFI_SUCCESS The command start successfully.
  489. **/
  490. EFI_STATUS
  491. AhciStartCommand (
  492. IN UINTN AhciBar,
  493. IN UINT8 Port,
  494. IN UINT8 CommandSlot,
  495. IN UINT64 Timeout
  496. )
  497. {
  498. UINT32 CmdSlotBit;
  499. EFI_STATUS Status;
  500. UINT32 PortStatus;
  501. UINT32 StartCmd;
  502. UINT32 PortTfd;
  503. UINT32 Offset;
  504. UINT32 Capability;
  505. //
  506. // Collect AHCI controller information
  507. //
  508. Capability = AhciReadReg (AhciBar, AHCI_CAPABILITY_OFFSET);
  509. CmdSlotBit = (UINT32) (1 << CommandSlot);
  510. AhciClearPortStatus (
  511. AhciBar,
  512. Port
  513. );
  514. Status = AhciEnableFisReceive (
  515. AhciBar,
  516. Port,
  517. Timeout
  518. );
  519. if (EFI_ERROR (Status)) {
  520. return Status;
  521. }
  522. Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_CMD;
  523. PortStatus = AhciReadReg (AhciBar, Offset);
  524. StartCmd = 0;
  525. if ((PortStatus & AHCI_PORT_CMD_ALPE) != 0) {
  526. StartCmd = AhciReadReg (AhciBar, Offset);
  527. StartCmd &= ~AHCI_PORT_CMD_ICC_MASK;
  528. StartCmd |= AHCI_PORT_CMD_ACTIVE;
  529. }
  530. Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_TFD;
  531. PortTfd = AhciReadReg (AhciBar, Offset);
  532. if ((PortTfd & (AHCI_PORT_TFD_BSY | AHCI_PORT_TFD_DRQ)) != 0) {
  533. if ((Capability & BIT24) != 0) {
  534. Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_CMD;
  535. AhciOrReg (AhciBar, Offset, AHCI_PORT_CMD_CLO);
  536. AhciWaitMmioSet (
  537. AhciBar,
  538. Offset,
  539. AHCI_PORT_CMD_CLO,
  540. 0,
  541. Timeout
  542. );
  543. }
  544. }
  545. Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_CMD;
  546. AhciOrReg (AhciBar, Offset, AHCI_PORT_CMD_ST | StartCmd);
  547. //
  548. // Setting the command
  549. //
  550. Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_CI;
  551. AhciAndReg (AhciBar, Offset, 0);
  552. AhciOrReg (AhciBar, Offset, CmdSlotBit);
  553. return EFI_SUCCESS;
  554. }
  555. /**
  556. Start a PIO Data transfer on specific port.
  557. @param[in] Private The pointer to the PEI_AHCI_CONTROLLER_PRIVATE_DATA.
  558. @param[in] Port The number of port.
  559. @param[in] PortMultiplier The number of port multiplier.
  560. @param[in] FisIndex The offset index of the FIS base address.
  561. @param[in] Read The transfer direction.
  562. @param[in] AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.
  563. @param[in,out] AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.
  564. @param[in,out] MemoryAddr The pointer to the data buffer.
  565. @param[in] DataCount The data count to be transferred.
  566. @param[in] Timeout The timeout value of PIO data transfer, uses
  567. 100ns as a unit.
  568. @retval EFI_DEVICE_ERROR The PIO data transfer abort with error occurs.
  569. @retval EFI_TIMEOUT The operation is time out.
  570. @retval EFI_UNSUPPORTED The device is not ready for transfer.
  571. @retval EFI_OUT_OF_RESOURCES The operation fails due to lack of resources.
  572. @retval EFI_SUCCESS The PIO data transfer executes successfully.
  573. **/
  574. EFI_STATUS
  575. AhciPioTransfer (
  576. IN PEI_AHCI_CONTROLLER_PRIVATE_DATA *Private,
  577. IN UINT8 Port,
  578. IN UINT8 PortMultiplier,
  579. IN UINT8 FisIndex,
  580. IN BOOLEAN Read,
  581. IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock,
  582. IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock,
  583. IN OUT VOID *MemoryAddr,
  584. IN UINT32 DataCount,
  585. IN UINT64 Timeout
  586. )
  587. {
  588. EFI_STATUS Status;
  589. EDKII_IOMMU_OPERATION MapOp;
  590. UINTN MapLength;
  591. EFI_PHYSICAL_ADDRESS PhyAddr;
  592. VOID *MapData;
  593. EFI_AHCI_REGISTERS *AhciRegisters;
  594. UINTN AhciBar;
  595. BOOLEAN InfiniteWait;
  596. UINT32 Offset;
  597. UINT32 OldRfisLo;
  598. UINT32 OldRfisHi;
  599. UINT32 OldCmdListLo;
  600. UINT32 OldCmdListHi;
  601. DATA_64 Data64;
  602. UINT32 FisBaseAddr;
  603. UINT32 Delay;
  604. EFI_AHCI_COMMAND_FIS CFis;
  605. EFI_AHCI_COMMAND_LIST CmdList;
  606. UINT32 PortTfd;
  607. UINT32 PrdCount;
  608. BOOLEAN PioFisReceived;
  609. BOOLEAN D2hFisReceived;
  610. //
  611. // Current driver implementation supports up to a maximum of AHCI_MAX_PRDT_NUMBER
  612. // PRDT entries.
  613. //
  614. if (DataCount / (UINT32)AHCI_MAX_PRDT_NUMBER > AHCI_MAX_DATA_PER_PRDT) {
  615. DEBUG ((
  616. DEBUG_ERROR,
  617. "%a: Driver only support a maximum of 0x%x PRDT entries, "
  618. "current number of data byte 0x%x is too large, maximum allowed is 0x%x.\n",
  619. __FUNCTION__, AHCI_MAX_PRDT_NUMBER, DataCount,
  620. AHCI_MAX_PRDT_NUMBER * AHCI_MAX_DATA_PER_PRDT
  621. ));
  622. return EFI_UNSUPPORTED;
  623. }
  624. MapOp = Read ? EdkiiIoMmuOperationBusMasterWrite :
  625. EdkiiIoMmuOperationBusMasterRead;
  626. MapLength = DataCount;
  627. Status = IoMmuMap (
  628. MapOp,
  629. MemoryAddr,
  630. &MapLength,
  631. &PhyAddr,
  632. &MapData
  633. );
  634. if (EFI_ERROR (Status) || (MapLength != DataCount)) {
  635. DEBUG ((DEBUG_ERROR, "%a: Fail to map data buffer.\n", __FUNCTION__));
  636. return EFI_OUT_OF_RESOURCES;
  637. }
  638. AhciRegisters = &Private->AhciRegisters;
  639. AhciBar = Private->MmioBase;
  640. InfiniteWait = (Timeout == 0) ? TRUE : FALSE;
  641. //
  642. // Fill FIS base address register
  643. //
  644. Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_FB;
  645. OldRfisLo = AhciReadReg (AhciBar, Offset);
  646. Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_FBU;
  647. OldRfisHi = AhciReadReg (AhciBar, Offset);
  648. Data64.Uint64 = (UINTN) (AhciRegisters->AhciRFis) + sizeof (EFI_AHCI_RECEIVED_FIS) * FisIndex;
  649. Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_FB;
  650. AhciWriteReg (AhciBar, Offset, Data64.Uint32.Lower32);
  651. Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_FBU;
  652. AhciWriteReg (AhciBar, Offset, Data64.Uint32.Upper32);
  653. //
  654. // Single task envrionment, we only use one command table for all port
  655. //
  656. Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_CLB;
  657. OldCmdListLo = AhciReadReg (AhciBar, Offset);
  658. Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_CLBU;
  659. OldCmdListHi = AhciReadReg (AhciBar, Offset);
  660. Data64.Uint64 = (UINTN) (AhciRegisters->AhciCmdList);
  661. Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_CLB;
  662. AhciWriteReg (AhciBar, Offset, Data64.Uint32.Lower32);
  663. Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_CLBU;
  664. AhciWriteReg (AhciBar, Offset, Data64.Uint32.Upper32);
  665. //
  666. // Package read needed
  667. //
  668. AhciBuildCommandFis (&CFis, AtaCommandBlock);
  669. ZeroMem (&CmdList, sizeof (EFI_AHCI_COMMAND_LIST));
  670. CmdList.AhciCmdCfl = AHCI_FIS_REGISTER_H2D_LENGTH / 4;
  671. CmdList.AhciCmdW = Read ? 0 : 1;
  672. AhciBuildCommand (
  673. Private,
  674. Port,
  675. PortMultiplier,
  676. FisIndex,
  677. &CFis,
  678. &CmdList,
  679. 0,
  680. (VOID *)(UINTN)PhyAddr,
  681. DataCount
  682. );
  683. Status = AhciStartCommand (
  684. AhciBar,
  685. Port,
  686. 0,
  687. Timeout
  688. );
  689. if (EFI_ERROR (Status)) {
  690. goto Exit;
  691. }
  692. //
  693. // Checking the status and wait the driver sending Data
  694. //
  695. FisBaseAddr = (UINT32)(UINTN)AhciRegisters->AhciRFis + sizeof (EFI_AHCI_RECEIVED_FIS) * FisIndex;
  696. if (Read) {
  697. //
  698. // Wait device sends the PIO setup fis before data transfer
  699. //
  700. Status = EFI_TIMEOUT;
  701. Delay = (UINT32) DivU64x32 (Timeout, 1000) + 1;
  702. do {
  703. PioFisReceived = FALSE;
  704. D2hFisReceived = FALSE;
  705. Offset = FisBaseAddr + AHCI_PIO_FIS_OFFSET;
  706. Status = AhciCheckMemSet (Offset, AHCI_FIS_TYPE_MASK, AHCI_FIS_PIO_SETUP);
  707. if (!EFI_ERROR (Status)) {
  708. DEBUG ((DEBUG_INFO, "%a: PioFisReceived.\n", __FUNCTION__));
  709. PioFisReceived = TRUE;
  710. }
  711. //
  712. // According to SATA 2.6 spec section 11.7, D2h FIS means an error encountered.
  713. // But Qemu and Marvel 9230 sata controller may just receive a D2h FIS from
  714. // device after the transaction is finished successfully.
  715. // To get better device compatibilities, we further check if the PxTFD's
  716. // ERR bit is set. By this way, we can know if there is a real error happened.
  717. //
  718. Offset = FisBaseAddr + AHCI_D2H_FIS_OFFSET;
  719. Status = AhciCheckMemSet (Offset, AHCI_FIS_TYPE_MASK, AHCI_FIS_REGISTER_D2H);
  720. if (!EFI_ERROR (Status)) {
  721. DEBUG ((DEBUG_INFO, "%a: D2hFisReceived.\n", __FUNCTION__));
  722. D2hFisReceived = TRUE;
  723. }
  724. if (PioFisReceived || D2hFisReceived) {
  725. Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_TFD;
  726. PortTfd = AhciReadReg (AhciBar, (UINT32) Offset);
  727. //
  728. // PxTFD will be updated if there is a D2H or SetupFIS received.
  729. //
  730. if ((PortTfd & AHCI_PORT_TFD_ERR) != 0) {
  731. Status = EFI_DEVICE_ERROR;
  732. break;
  733. }
  734. PrdCount = *(volatile UINT32 *) (&(AhciRegisters->AhciCmdList[0].AhciCmdPrdbc));
  735. if (PrdCount == DataCount) {
  736. Status = EFI_SUCCESS;
  737. break;
  738. }
  739. }
  740. //
  741. // Stall for 100 microseconds.
  742. //
  743. MicroSecondDelay(100);
  744. Delay--;
  745. if (Delay == 0) {
  746. Status = EFI_TIMEOUT;
  747. }
  748. } while (InfiniteWait || (Delay > 0));
  749. } else {
  750. //
  751. // Wait for D2H Fis is received
  752. //
  753. Offset = FisBaseAddr + AHCI_D2H_FIS_OFFSET;
  754. Status = AhciWaitMemSet (
  755. Offset,
  756. AHCI_FIS_TYPE_MASK,
  757. AHCI_FIS_REGISTER_D2H,
  758. Timeout
  759. );
  760. if (EFI_ERROR (Status)) {
  761. DEBUG ((DEBUG_ERROR, "%a: AhciWaitMemSet (%r)\n", __FUNCTION__, Status));
  762. goto Exit;
  763. }
  764. Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_TFD;
  765. PortTfd = AhciReadReg (AhciBar, (UINT32) Offset);
  766. if ((PortTfd & AHCI_PORT_TFD_ERR) != 0) {
  767. Status = EFI_DEVICE_ERROR;
  768. }
  769. }
  770. Exit:
  771. AhciStopCommand (
  772. AhciBar,
  773. Port,
  774. Timeout
  775. );
  776. AhciDisableFisReceive (
  777. AhciBar,
  778. Port,
  779. Timeout
  780. );
  781. if (MapData != NULL) {
  782. IoMmuUnmap (MapData);
  783. }
  784. Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_FB;
  785. AhciWriteReg (AhciBar, Offset, OldRfisLo);
  786. Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_FBU;
  787. AhciWriteReg (AhciBar, Offset, OldRfisHi);
  788. Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_CLB;
  789. AhciWriteReg (AhciBar, Offset, OldCmdListLo);
  790. Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_CLBU;
  791. AhciWriteReg (AhciBar, Offset, OldCmdListHi);
  792. return Status;
  793. }
  794. /**
  795. Start a non data transfer on specific port.
  796. @param[in] Private The pointer to the PEI_AHCI_CONTROLLER_PRIVATE_DATA.
  797. @param[in] Port The number of port.
  798. @param[in] PortMultiplier The number of port multiplier.
  799. @param[in] FisIndex The offset index of the FIS base address.
  800. @param[in] AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.
  801. @param[in,out] AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.
  802. @param[in] Timeout The timeout value of non data transfer, uses
  803. 100ns as a unit.
  804. @retval EFI_DEVICE_ERROR The non data transfer abort with error occurs.
  805. @retval EFI_TIMEOUT The operation is time out.
  806. @retval EFI_UNSUPPORTED The device is not ready for transfer.
  807. @retval EFI_SUCCESS The non data transfer executes successfully.
  808. **/
  809. EFI_STATUS
  810. AhciNonDataTransfer (
  811. IN PEI_AHCI_CONTROLLER_PRIVATE_DATA *Private,
  812. IN UINT8 Port,
  813. IN UINT8 PortMultiplier,
  814. IN UINT8 FisIndex,
  815. IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock,
  816. IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock,
  817. IN UINT64 Timeout
  818. )
  819. {
  820. EFI_STATUS Status;
  821. UINTN AhciBar;
  822. EFI_AHCI_REGISTERS *AhciRegisters;
  823. UINTN FisBaseAddr;
  824. UINTN Offset;
  825. UINT32 PortTfd;
  826. EFI_AHCI_COMMAND_FIS CFis;
  827. EFI_AHCI_COMMAND_LIST CmdList;
  828. AhciBar = Private->MmioBase;
  829. AhciRegisters = &Private->AhciRegisters;
  830. //
  831. // Package read needed
  832. //
  833. AhciBuildCommandFis (&CFis, AtaCommandBlock);
  834. ZeroMem (&CmdList, sizeof (EFI_AHCI_COMMAND_LIST));
  835. CmdList.AhciCmdCfl = AHCI_FIS_REGISTER_H2D_LENGTH / 4;
  836. AhciBuildCommand (
  837. Private,
  838. Port,
  839. PortMultiplier,
  840. FisIndex,
  841. &CFis,
  842. &CmdList,
  843. 0,
  844. NULL,
  845. 0
  846. );
  847. Status = AhciStartCommand (
  848. AhciBar,
  849. Port,
  850. 0,
  851. Timeout
  852. );
  853. if (EFI_ERROR (Status)) {
  854. goto Exit;
  855. }
  856. //
  857. // Wait device sends the Response Fis
  858. //
  859. FisBaseAddr = (UINTN)AhciRegisters->AhciRFis + sizeof (EFI_AHCI_RECEIVED_FIS) * FisIndex;
  860. Offset = FisBaseAddr + AHCI_D2H_FIS_OFFSET;
  861. Status = AhciWaitMemSet (
  862. Offset,
  863. AHCI_FIS_TYPE_MASK,
  864. AHCI_FIS_REGISTER_D2H,
  865. Timeout
  866. );
  867. if (EFI_ERROR (Status)) {
  868. goto Exit;
  869. }
  870. Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_TFD;
  871. PortTfd = AhciReadReg (AhciBar, (UINT32) Offset);
  872. if ((PortTfd & AHCI_PORT_TFD_ERR) != 0) {
  873. Status = EFI_DEVICE_ERROR;
  874. }
  875. Exit:
  876. AhciStopCommand (
  877. AhciBar,
  878. Port,
  879. Timeout
  880. );
  881. AhciDisableFisReceive (
  882. AhciBar,
  883. Port,
  884. Timeout
  885. );
  886. return Status;
  887. }
  888. /**
  889. Do AHCI HBA reset.
  890. @param[in] AhciBar AHCI bar address.
  891. @param[in] Timeout The timeout, in 100ns units, to reset.
  892. @retval EFI_DEVICE_ERROR AHCI controller is failed to complete hardware reset.
  893. @retval EFI_TIMEOUT The reset operation is time out.
  894. @retval EFI_SUCCESS AHCI controller is reset successfully.
  895. **/
  896. EFI_STATUS
  897. AhciReset (
  898. IN UINTN AhciBar,
  899. IN UINT64 Timeout
  900. )
  901. {
  902. UINT32 Delay;
  903. UINT32 Value;
  904. UINT32 Capability;
  905. //
  906. // Collect AHCI controller information
  907. //
  908. Capability = AhciReadReg (AhciBar, AHCI_CAPABILITY_OFFSET);
  909. //
  910. // Enable AE before accessing any AHCI registers if Supports AHCI Mode Only is not set
  911. //
  912. if ((Capability & AHCI_CAP_SAM) == 0) {
  913. AhciOrReg (AhciBar, AHCI_GHC_OFFSET, AHCI_GHC_ENABLE);
  914. }
  915. AhciOrReg (AhciBar, AHCI_GHC_OFFSET, AHCI_GHC_RESET);
  916. Delay = (UINT32) (DivU64x32(Timeout, 1000) + 1);
  917. do {
  918. Value = AhciReadReg(AhciBar, AHCI_GHC_OFFSET);
  919. if ((Value & AHCI_GHC_RESET) == 0) {
  920. return EFI_SUCCESS;
  921. }
  922. //
  923. // Stall for 100 microseconds.
  924. //
  925. MicroSecondDelay(100);
  926. Delay--;
  927. } while (Delay > 0);
  928. return EFI_TIMEOUT;
  929. }
  930. /**
  931. Send Identify Drive command to a specific device.
  932. @param[in] Private The pointer to the PEI_AHCI_CONTROLLER_PRIVATE_DATA.
  933. @param[in] Port The number of port.
  934. @param[in] PortMultiplier The port multiplier port number.
  935. @param[in] FisIndex The offset index of the FIS base address.
  936. @param[in] Buffer The data buffer to store IDENTIFY PACKET data.
  937. @retval EFI_SUCCESS The cmd executes successfully.
  938. @retval EFI_INVALID_PARAMETER Buffer is NULL.
  939. @retval EFI_DEVICE_ERROR The cmd abort with error occurs.
  940. @retval EFI_TIMEOUT The operation is time out.
  941. @retval EFI_UNSUPPORTED The device is not ready for executing.
  942. **/
  943. EFI_STATUS
  944. AhciIdentify (
  945. IN PEI_AHCI_CONTROLLER_PRIVATE_DATA *Private,
  946. IN UINT8 Port,
  947. IN UINT8 PortMultiplier,
  948. IN UINT8 FisIndex,
  949. IN ATA_IDENTIFY_DATA *Buffer
  950. )
  951. {
  952. EFI_STATUS Status;
  953. EFI_ATA_COMMAND_BLOCK Acb;
  954. EFI_ATA_STATUS_BLOCK Asb;
  955. if (Buffer == NULL) {
  956. return EFI_INVALID_PARAMETER;
  957. }
  958. ZeroMem (&Acb, sizeof (EFI_ATA_COMMAND_BLOCK));
  959. ZeroMem (&Asb, sizeof (EFI_ATA_STATUS_BLOCK));
  960. Acb.AtaCommand = ATA_CMD_IDENTIFY_DRIVE;
  961. Acb.AtaSectorCount = 1;
  962. Status = AhciPioTransfer (
  963. Private,
  964. Port,
  965. PortMultiplier,
  966. FisIndex,
  967. TRUE,
  968. &Acb,
  969. &Asb,
  970. Buffer,
  971. sizeof (ATA_IDENTIFY_DATA),
  972. ATA_TIMEOUT
  973. );
  974. return Status;
  975. }
  976. /**
  977. Collect the number of bits set within a port bitmap.
  978. @param[in] PortBitMap A 32-bit wide bit map of ATA AHCI ports.
  979. @retval The number of bits set in the bitmap.
  980. **/
  981. UINT8
  982. AhciGetNumberOfPortsFromMap (
  983. IN UINT32 PortBitMap
  984. )
  985. {
  986. UINT8 NumberOfPorts;
  987. NumberOfPorts = 0;
  988. while (PortBitMap != 0) {
  989. if ((PortBitMap & ((UINT32)BIT0)) != 0) {
  990. NumberOfPorts++;
  991. }
  992. PortBitMap = PortBitMap >> 1;
  993. }
  994. return NumberOfPorts;
  995. }
  996. /**
  997. Get the specified port number from a port bitmap.
  998. @param[in] PortBitMap A 32-bit wide bit map of ATA AHCI ports.
  999. @param[in] PortIndex The specified port index.
  1000. @param[out] Port The port number of the port specified by PortIndex.
  1001. @retval EFI_SUCCESS The specified port is found and its port number is
  1002. in Port.
  1003. @retval EFI_NOT_FOUND Cannot find the specified port within the port bitmap.
  1004. **/
  1005. EFI_STATUS
  1006. AhciGetPortFromMap (
  1007. IN UINT32 PortBitMap,
  1008. IN UINT8 PortIndex,
  1009. OUT UINT8 *Port
  1010. )
  1011. {
  1012. if (PortIndex == 0) {
  1013. return EFI_NOT_FOUND;
  1014. }
  1015. *Port = 0;
  1016. while (PortBitMap != 0) {
  1017. if ((PortBitMap & ((UINT32)BIT0)) != 0) {
  1018. PortIndex--;
  1019. //
  1020. // Found the port specified by PortIndex.
  1021. //
  1022. if (PortIndex == 0) {
  1023. return EFI_SUCCESS;
  1024. }
  1025. }
  1026. PortBitMap = PortBitMap >> 1;
  1027. *Port = *Port + 1;
  1028. }
  1029. return EFI_NOT_FOUND;
  1030. }
  1031. /**
  1032. Allocate transfer-related data struct which is used at AHCI mode.
  1033. @param[in,out] Private A pointer to the PEI_AHCI_CONTROLLER_PRIVATE_DATA instance.
  1034. @retval EFI_SUCCESS Data structures are allocated successfully.
  1035. @retval Others Data structures are not allocated successfully.
  1036. **/
  1037. EFI_STATUS
  1038. AhciCreateTransferDescriptor (
  1039. IN OUT PEI_AHCI_CONTROLLER_PRIVATE_DATA *Private
  1040. )
  1041. {
  1042. EFI_STATUS Status;
  1043. UINTN AhciBar;
  1044. EFI_AHCI_REGISTERS *AhciRegisters;
  1045. EFI_PHYSICAL_ADDRESS DeviceAddress;
  1046. VOID *Base;
  1047. VOID *Mapping;
  1048. UINT32 Capability;
  1049. UINT32 PortImplementBitMap;
  1050. UINT8 MaxPortNumber;
  1051. UINT8 MaxCommandSlotNumber;
  1052. UINTN MaxRFisSize;
  1053. UINTN MaxCmdListSize;
  1054. UINTN MaxCmdTableSize;
  1055. AhciBar = Private->MmioBase;
  1056. AhciRegisters = &Private->AhciRegisters;
  1057. //
  1058. // Collect AHCI controller information
  1059. //
  1060. Capability = AhciReadReg (AhciBar, AHCI_CAPABILITY_OFFSET);
  1061. //
  1062. // Get the number of command slots per port supported by this HBA.
  1063. //
  1064. MaxCommandSlotNumber = (UINT8) (((Capability & 0x1F00) >> 8) + 1);
  1065. ASSERT (MaxCommandSlotNumber > 0);
  1066. if (MaxCommandSlotNumber == 0) {
  1067. return EFI_DEVICE_ERROR;
  1068. }
  1069. //
  1070. // Get the highest bit of implemented ports which decides how many bytes are
  1071. // allocated for recived FIS.
  1072. //
  1073. PortImplementBitMap = AhciReadReg (AhciBar, AHCI_PI_OFFSET);
  1074. MaxPortNumber = (UINT8)(UINTN)(HighBitSet32(PortImplementBitMap) + 1);
  1075. if (MaxPortNumber == 0) {
  1076. return EFI_DEVICE_ERROR;
  1077. }
  1078. //
  1079. // Get the number of ports that actually needed to be initialized.
  1080. //
  1081. MaxPortNumber = MIN (MaxPortNumber, AhciGetNumberOfPortsFromMap (Private->PortBitMap));
  1082. //
  1083. // Allocate memory for received FIS.
  1084. //
  1085. MaxRFisSize = MaxPortNumber * sizeof (EFI_AHCI_RECEIVED_FIS);
  1086. Status = IoMmuAllocateBuffer (
  1087. EFI_SIZE_TO_PAGES (MaxRFisSize),
  1088. &Base,
  1089. &DeviceAddress,
  1090. &Mapping
  1091. );
  1092. if (EFI_ERROR (Status)) {
  1093. return EFI_OUT_OF_RESOURCES;
  1094. }
  1095. ASSERT (DeviceAddress == ((EFI_PHYSICAL_ADDRESS) (UINTN) Base));
  1096. AhciRegisters->AhciRFis = Base;
  1097. AhciRegisters->AhciRFisMap = Mapping;
  1098. AhciRegisters->MaxRFisSize = MaxRFisSize;
  1099. ZeroMem (AhciRegisters->AhciRFis, EFI_PAGE_SIZE * EFI_SIZE_TO_PAGES (MaxRFisSize));
  1100. //
  1101. // Allocate memory for command list.
  1102. // Note that the implemenation is a single task model which only use a command
  1103. // list for each port.
  1104. //
  1105. MaxCmdListSize = 1 * sizeof (EFI_AHCI_COMMAND_LIST);
  1106. Status = IoMmuAllocateBuffer (
  1107. EFI_SIZE_TO_PAGES (MaxCmdListSize),
  1108. &Base,
  1109. &DeviceAddress,
  1110. &Mapping
  1111. );
  1112. if (EFI_ERROR (Status)) {
  1113. Status = EFI_OUT_OF_RESOURCES;
  1114. goto ErrorExit;
  1115. }
  1116. ASSERT (DeviceAddress == ((EFI_PHYSICAL_ADDRESS) (UINTN) Base));
  1117. AhciRegisters->AhciCmdList = Base;
  1118. AhciRegisters->AhciCmdListMap = Mapping;
  1119. AhciRegisters->MaxCmdListSize = MaxCmdListSize;
  1120. ZeroMem (AhciRegisters->AhciCmdList, EFI_PAGE_SIZE * EFI_SIZE_TO_PAGES (MaxCmdListSize));
  1121. //
  1122. // Allocate memory for command table
  1123. // According to AHCI 1.3 spec, a PRD table can contain maximum 65535 entries.
  1124. //
  1125. MaxCmdTableSize = sizeof (EFI_AHCI_COMMAND_TABLE);
  1126. Status = IoMmuAllocateBuffer (
  1127. EFI_SIZE_TO_PAGES (MaxCmdTableSize),
  1128. &Base,
  1129. &DeviceAddress,
  1130. &Mapping
  1131. );
  1132. if (EFI_ERROR (Status)) {
  1133. Status = EFI_OUT_OF_RESOURCES;
  1134. goto ErrorExit;
  1135. }
  1136. ASSERT (DeviceAddress == ((EFI_PHYSICAL_ADDRESS) (UINTN) Base));
  1137. AhciRegisters->AhciCmdTable = Base;
  1138. AhciRegisters->AhciCmdTableMap = Mapping;
  1139. AhciRegisters->MaxCmdTableSize = MaxCmdTableSize;
  1140. ZeroMem (AhciRegisters->AhciCmdTable, EFI_PAGE_SIZE * EFI_SIZE_TO_PAGES (MaxCmdTableSize));
  1141. return EFI_SUCCESS;
  1142. ErrorExit:
  1143. if (AhciRegisters->AhciRFisMap != NULL) {
  1144. IoMmuFreeBuffer (
  1145. EFI_SIZE_TO_PAGES (AhciRegisters->MaxRFisSize),
  1146. AhciRegisters->AhciRFis,
  1147. AhciRegisters->AhciRFisMap
  1148. );
  1149. AhciRegisters->AhciRFis = NULL;
  1150. }
  1151. if (AhciRegisters->AhciCmdListMap != NULL) {
  1152. IoMmuFreeBuffer (
  1153. EFI_SIZE_TO_PAGES (AhciRegisters->MaxCmdListSize),
  1154. AhciRegisters->AhciCmdList,
  1155. AhciRegisters->AhciCmdListMap
  1156. );
  1157. AhciRegisters->AhciCmdList = NULL;
  1158. }
  1159. return Status;
  1160. }
  1161. /**
  1162. Gets ATA device Capacity according to ATA 6.
  1163. This function returns the capacity of the ATA device if it follows
  1164. ATA 6 to support 48 bit addressing.
  1165. @param[in] IdentifyData A pointer to ATA_IDENTIFY_DATA structure.
  1166. @return The capacity of the ATA device or 0 if the device does not support
  1167. 48-bit addressing defined in ATA 6.
  1168. **/
  1169. EFI_LBA
  1170. GetAtapi6Capacity (
  1171. IN ATA_IDENTIFY_DATA *IdentifyData
  1172. )
  1173. {
  1174. EFI_LBA Capacity;
  1175. EFI_LBA TmpLba;
  1176. UINTN Index;
  1177. if ((IdentifyData->command_set_supported_83 & BIT10) == 0) {
  1178. //
  1179. // The device doesn't support 48 bit addressing
  1180. //
  1181. return 0;
  1182. }
  1183. //
  1184. // 48 bit address feature set is supported, get maximum capacity
  1185. //
  1186. Capacity = 0;
  1187. for (Index = 0; Index < 4; Index++) {
  1188. //
  1189. // Lower byte goes first: word[100] is the lowest word, word[103] is highest
  1190. //
  1191. TmpLba = IdentifyData->maximum_lba_for_48bit_addressing[Index];
  1192. Capacity |= LShiftU64 (TmpLba, 16 * Index);
  1193. }
  1194. return Capacity;
  1195. }
  1196. /**
  1197. Identifies ATA device via the Identify data.
  1198. This function identifies the ATA device and initializes the media information.
  1199. @attention This is boundary function that may receive untrusted input.
  1200. @attention The input is from peripheral hardware device.
  1201. The Identify Drive command response data from an ATA device is the peripheral
  1202. hardware input, so this routine will do basic validation for the Identify Drive
  1203. command response data.
  1204. @param[in,out] DeviceData A pointer to PEI_AHCI_ATA_DEVICE_DATA structure.
  1205. @retval EFI_SUCCESS The device is successfully identified and media
  1206. information is correctly initialized.
  1207. @retval EFI_UNSUPPORTED The device is not a valid ATA device (hard disk).
  1208. **/
  1209. EFI_STATUS
  1210. IdentifyAtaDevice (
  1211. IN OUT PEI_AHCI_ATA_DEVICE_DATA *DeviceData
  1212. )
  1213. {
  1214. ATA_IDENTIFY_DATA *IdentifyData;
  1215. EFI_PEI_BLOCK_IO2_MEDIA *Media;
  1216. EFI_LBA Capacity;
  1217. UINT32 MaxSectorCount;
  1218. UINT16 PhyLogicSectorSupport;
  1219. IdentifyData = DeviceData->IdentifyData;
  1220. Media = &DeviceData->Media;
  1221. if ((IdentifyData->config & BIT15) != 0) {
  1222. DEBUG ((
  1223. DEBUG_ERROR, "%a: Not a hard disk device on Port 0x%x PortMultiplierPort 0x%x\n",
  1224. __FUNCTION__, DeviceData->Port, DeviceData->PortMultiplier
  1225. ));
  1226. return EFI_UNSUPPORTED;
  1227. }
  1228. DEBUG ((
  1229. DEBUG_INFO, "%a: Identify Device: Port 0x%x PortMultiplierPort 0x%x\n",
  1230. __FUNCTION__, DeviceData->Port, DeviceData->PortMultiplier
  1231. ));
  1232. //
  1233. // Skip checking whether the WORD 88 (supported UltraDMA by drive), since the
  1234. // driver only support PIO data transfer for now.
  1235. //
  1236. //
  1237. // Get the capacity information of the device.
  1238. //
  1239. Capacity = GetAtapi6Capacity (IdentifyData);
  1240. if (Capacity > MAX_28BIT_ADDRESSING_CAPACITY) {
  1241. //
  1242. // Capacity exceeds 120GB. 48-bit addressing is really needed
  1243. //
  1244. DeviceData->Lba48Bit = TRUE;
  1245. } else {
  1246. //
  1247. // This is a hard disk <= 120GB capacity, treat it as normal hard disk
  1248. //
  1249. Capacity = ((UINT32)IdentifyData->user_addressable_sectors_hi << 16) |
  1250. IdentifyData->user_addressable_sectors_lo;
  1251. DeviceData->Lba48Bit = FALSE;
  1252. }
  1253. if (Capacity == 0) {
  1254. DEBUG ((DEBUG_ERROR, "%a: Invalid Capacity (0) for ATA device.\n", __FUNCTION__));
  1255. return EFI_UNSUPPORTED;
  1256. }
  1257. Media->LastBlock = (EFI_PEI_LBA) (Capacity - 1);
  1258. Media->BlockSize = 0x200;
  1259. //
  1260. // Check whether Long Physical Sector Feature is supported
  1261. //
  1262. PhyLogicSectorSupport = IdentifyData->phy_logic_sector_support;
  1263. DEBUG ((
  1264. DEBUG_INFO, "%a: PhyLogicSectorSupport = 0x%x\n",
  1265. __FUNCTION__, PhyLogicSectorSupport
  1266. ));
  1267. if ((PhyLogicSectorSupport & (BIT14 | BIT15)) == BIT14) {
  1268. //
  1269. // Check logical block size
  1270. //
  1271. if ((PhyLogicSectorSupport & BIT12) != 0) {
  1272. Media->BlockSize = (UINT32) (((IdentifyData->logic_sector_size_hi << 16) |
  1273. IdentifyData->logic_sector_size_lo) * sizeof (UINT16));
  1274. }
  1275. }
  1276. //
  1277. // Check BlockSize validity
  1278. //
  1279. MaxSectorCount = mMaxTransferBlockNumber[DeviceData->Lba48Bit];
  1280. if ((Media->BlockSize == 0) || (Media->BlockSize > MAX_UINT32 / MaxSectorCount)) {
  1281. DEBUG ((DEBUG_ERROR, "%a: Invalid BlockSize (0x%x).\n", __FUNCTION__, Media->BlockSize));
  1282. return EFI_UNSUPPORTED;
  1283. }
  1284. DEBUG ((
  1285. DEBUG_INFO, "%a: BlockSize = 0x%x, LastBlock = 0x%lx\n",
  1286. __FUNCTION__, Media->BlockSize, Media->LastBlock
  1287. ));
  1288. if ((IdentifyData->trusted_computing_support & BIT0) != 0) {
  1289. DEBUG ((DEBUG_INFO, "%a: Found Trust Computing feature support.\n", __FUNCTION__));
  1290. DeviceData->TrustComputing = TRUE;
  1291. }
  1292. Media->InterfaceType = MSG_SATA_DP;
  1293. Media->RemovableMedia = FALSE;
  1294. Media->MediaPresent = TRUE;
  1295. Media->ReadOnly = FALSE;
  1296. return EFI_SUCCESS;
  1297. }
  1298. /**
  1299. Allocate device information data structure to contain device information.
  1300. And insert the data structure to the tail of device list for tracing.
  1301. @param[in,out] Private A pointer to the PEI_AHCI_CONTROLLER_PRIVATE_DATA
  1302. instance.
  1303. @param[in] DeviceIndex The device index.
  1304. @param[in] Port The port number of the ATA device to send
  1305. the command.
  1306. @param[in] PortMultiplierPort The port multiplier port number of the ATA
  1307. device to send the command.
  1308. If there is no port multiplier, then specify
  1309. 0xFFFF.
  1310. @param[in] FisIndex The index of the FIS of the ATA device to
  1311. send the command.
  1312. @param[in] IdentifyData The data buffer to store the output of the
  1313. IDENTIFY command.
  1314. @retval EFI_SUCCESS Successfully insert the ATA device to the
  1315. tail of device list.
  1316. @retval EFI_OUT_OF_RESOURCES Not enough resource.
  1317. **/
  1318. EFI_STATUS
  1319. CreateNewDevice (
  1320. IN OUT PEI_AHCI_CONTROLLER_PRIVATE_DATA *Private,
  1321. IN UINTN DeviceIndex,
  1322. IN UINT16 Port,
  1323. IN UINT16 PortMultiplier,
  1324. IN UINT8 FisIndex,
  1325. IN ATA_IDENTIFY_DATA *IdentifyData
  1326. )
  1327. {
  1328. PEI_AHCI_ATA_DEVICE_DATA *DeviceData;
  1329. EFI_STATUS Status;
  1330. DeviceData = AllocateZeroPool (sizeof (PEI_AHCI_ATA_DEVICE_DATA));
  1331. if (DeviceData == NULL) {
  1332. return EFI_OUT_OF_RESOURCES;
  1333. }
  1334. if (IdentifyData != NULL) {
  1335. DeviceData->IdentifyData = AllocateCopyPool (sizeof (ATA_IDENTIFY_DATA), IdentifyData);
  1336. if (DeviceData->IdentifyData == NULL) {
  1337. return EFI_OUT_OF_RESOURCES;
  1338. }
  1339. }
  1340. DeviceData->Signature = AHCI_PEI_ATA_DEVICE_DATA_SIGNATURE;
  1341. DeviceData->Port = Port;
  1342. DeviceData->PortMultiplier = PortMultiplier;
  1343. DeviceData->FisIndex = FisIndex;
  1344. DeviceData->DeviceIndex = DeviceIndex;
  1345. DeviceData->Private = Private;
  1346. Status = IdentifyAtaDevice (DeviceData);
  1347. if (EFI_ERROR (Status)) {
  1348. return Status;
  1349. }
  1350. if (DeviceData->TrustComputing) {
  1351. Private->TrustComputingDevices++;
  1352. DeviceData->TrustComputingDeviceIndex = Private->TrustComputingDevices;
  1353. }
  1354. Private->ActiveDevices++;
  1355. InsertTailList (&Private->DeviceList, &DeviceData->Link);
  1356. return EFI_SUCCESS;
  1357. }
  1358. /**
  1359. Initialize ATA host controller at AHCI mode.
  1360. The function is designed to initialize ATA host controller.
  1361. @param[in,out] Private A pointer to the PEI_AHCI_CONTROLLER_PRIVATE_DATA instance.
  1362. @retval EFI_SUCCESS The ATA AHCI controller is initialized successfully.
  1363. @retval EFI_OUT_OF_RESOURCES Not enough resource to complete while initializing
  1364. the controller.
  1365. @retval Others A device error occurred while initializing the
  1366. controller.
  1367. **/
  1368. EFI_STATUS
  1369. AhciModeInitialization (
  1370. IN OUT PEI_AHCI_CONTROLLER_PRIVATE_DATA *Private
  1371. )
  1372. {
  1373. EFI_STATUS Status;
  1374. UINTN AhciBar;
  1375. UINT32 Capability;
  1376. UINT32 Value;
  1377. UINT8 MaxPortNumber;
  1378. UINT32 PortImplementBitMap;
  1379. UINT32 PortInitializeBitMap;
  1380. EFI_AHCI_REGISTERS *AhciRegisters;
  1381. UINT8 PortIndex;
  1382. UINT8 Port;
  1383. DATA_64 Data64;
  1384. UINT32 Data;
  1385. UINT32 Offset;
  1386. UINT32 PhyDetectDelay;
  1387. UINTN DeviceIndex;
  1388. ATA_IDENTIFY_DATA IdentifyData;
  1389. AhciBar = Private->MmioBase;
  1390. Status = AhciReset (AhciBar, AHCI_PEI_RESET_TIMEOUT);
  1391. if (EFI_ERROR (Status)) {
  1392. DEBUG ((DEBUG_ERROR, "%a: AHCI HBA reset failed with %r.\n", __FUNCTION__, Status));
  1393. return EFI_DEVICE_ERROR;
  1394. }
  1395. //
  1396. // Collect AHCI controller information
  1397. //
  1398. Capability = AhciReadReg (AhciBar, AHCI_CAPABILITY_OFFSET);
  1399. //
  1400. // Make sure that GHC.AE bit is set before accessing any AHCI registers.
  1401. //
  1402. Value = AhciReadReg (AhciBar, AHCI_GHC_OFFSET);
  1403. if ((Value & AHCI_GHC_ENABLE) == 0) {
  1404. AhciOrReg (AhciBar, AHCI_GHC_OFFSET, AHCI_GHC_ENABLE);
  1405. }
  1406. Status = AhciCreateTransferDescriptor (Private);
  1407. if (EFI_ERROR (Status)) {
  1408. DEBUG ((
  1409. DEBUG_ERROR,
  1410. "%a: Transfer-related data allocation failed with %r.\n",
  1411. __FUNCTION__, Status
  1412. ));
  1413. return EFI_OUT_OF_RESOURCES;
  1414. }
  1415. //
  1416. // Get the number of command slots per port supported by this HBA.
  1417. //
  1418. MaxPortNumber = (UINT8) ((Capability & 0x1F) + 1);
  1419. //
  1420. // Get the bit map of those ports exposed by this HBA.
  1421. // It indicates which ports that the HBA supports are available for software
  1422. // to use.
  1423. //
  1424. PortImplementBitMap = AhciReadReg (AhciBar, AHCI_PI_OFFSET);
  1425. //
  1426. // Get the number of ports that actually needed to be initialized.
  1427. //
  1428. MaxPortNumber = MIN (MaxPortNumber, (UINT8)(UINTN)(HighBitSet32(PortImplementBitMap) + 1));
  1429. MaxPortNumber = MIN (MaxPortNumber, AhciGetNumberOfPortsFromMap (Private->PortBitMap));
  1430. PortInitializeBitMap = Private->PortBitMap;
  1431. AhciRegisters = &Private->AhciRegisters;
  1432. DeviceIndex = 0;
  1433. //
  1434. // Enumerate ATA ports
  1435. //
  1436. for (PortIndex = 1; PortIndex <= MaxPortNumber; PortIndex ++) {
  1437. Status = AhciGetPortFromMap (PortInitializeBitMap, PortIndex, &Port);
  1438. if ((PortImplementBitMap & (BIT0 << Port)) != 0) {
  1439. //
  1440. // Initialize FIS Base Address Register and Command List Base Address
  1441. // Register for use.
  1442. //
  1443. Data64.Uint64 = (UINTN) (AhciRegisters->AhciRFis) +
  1444. sizeof (EFI_AHCI_RECEIVED_FIS) * (PortIndex - 1);
  1445. Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_FB;
  1446. AhciWriteReg (AhciBar, Offset, Data64.Uint32.Lower32);
  1447. Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_FBU;
  1448. AhciWriteReg (AhciBar, Offset, Data64.Uint32.Upper32);
  1449. Data64.Uint64 = (UINTN) (AhciRegisters->AhciCmdList);
  1450. Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_CLB;
  1451. AhciWriteReg (AhciBar, Offset, Data64.Uint32.Lower32);
  1452. Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_CLBU;
  1453. AhciWriteReg (AhciBar, Offset, Data64.Uint32.Upper32);
  1454. Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_CMD;
  1455. Data = AhciReadReg (AhciBar, Offset);
  1456. if ((Data & AHCI_PORT_CMD_CPD) != 0) {
  1457. AhciOrReg (AhciBar, Offset, AHCI_PORT_CMD_POD);
  1458. }
  1459. if ((Capability & AHCI_CAP_SSS) != 0) {
  1460. AhciOrReg (AhciBar, Offset, AHCI_PORT_CMD_SUD);
  1461. }
  1462. //
  1463. // Disable aggressive power management.
  1464. //
  1465. Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_SCTL;
  1466. AhciOrReg (AhciBar, Offset, AHCI_PORT_SCTL_IPM_INIT);
  1467. //
  1468. // Disable the reporting of the corresponding interrupt to system software.
  1469. //
  1470. Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_IE;
  1471. AhciAndReg (AhciBar, Offset, 0);
  1472. //
  1473. // Enable FIS Receive DMA engine for the first D2H FIS.
  1474. //
  1475. Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_CMD;
  1476. AhciOrReg (AhciBar, Offset, AHCI_PORT_CMD_FRE);
  1477. //
  1478. // Wait no longer than 15 ms to wait the Phy to detect the presence of a device.
  1479. //
  1480. PhyDetectDelay = AHCI_BUS_PHY_DETECT_TIMEOUT;
  1481. Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_SSTS;
  1482. do {
  1483. Data = AhciReadReg (AhciBar, Offset) & AHCI_PORT_SSTS_DET_MASK;
  1484. if ((Data == AHCI_PORT_SSTS_DET_PCE) || (Data == AHCI_PORT_SSTS_DET)) {
  1485. break;
  1486. }
  1487. MicroSecondDelay (1000);
  1488. PhyDetectDelay--;
  1489. } while (PhyDetectDelay > 0);
  1490. if (PhyDetectDelay == 0) {
  1491. //
  1492. // No device detected at this port.
  1493. // Clear PxCMD.SUD for those ports at which there are no device present.
  1494. //
  1495. Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_CMD;
  1496. AhciAndReg (AhciBar, Offset, (UINT32) ~(AHCI_PORT_CMD_SUD));
  1497. DEBUG ((DEBUG_ERROR, "%a: No device detected at Port %d.\n", __FUNCTION__, Port));
  1498. continue;
  1499. }
  1500. //
  1501. // According to SATA1.0a spec section 5.2, we need to wait for PxTFD.BSY and PxTFD.DRQ
  1502. // and PxTFD.ERR to be zero. The maximum wait time is 16s which is defined at ATA spec.
  1503. //
  1504. PhyDetectDelay = 16 * 1000;
  1505. do {
  1506. Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_SERR;
  1507. if (AhciReadReg(AhciBar, Offset) != 0) {
  1508. AhciWriteReg (AhciBar, Offset, AhciReadReg (AhciBar, Offset));
  1509. }
  1510. Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_TFD;
  1511. Data = AhciReadReg (AhciBar, Offset) & AHCI_PORT_TFD_MASK;
  1512. if (Data == 0) {
  1513. break;
  1514. }
  1515. MicroSecondDelay (1000);
  1516. PhyDetectDelay--;
  1517. } while (PhyDetectDelay > 0);
  1518. if (PhyDetectDelay == 0) {
  1519. DEBUG ((
  1520. DEBUG_ERROR,
  1521. "%a: Port %d device presence detected but phy not ready (TFD=0x%x).\n",
  1522. __FUNCTION__, Port, Data
  1523. ));
  1524. continue;
  1525. }
  1526. //
  1527. // When the first D2H register FIS is received, the content of PxSIG register is updated.
  1528. //
  1529. Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_SIG;
  1530. Status = AhciWaitMmioSet (
  1531. AhciBar,
  1532. Offset,
  1533. 0x0000FFFF,
  1534. 0x00000101,
  1535. 160000000
  1536. );
  1537. if (EFI_ERROR (Status)) {
  1538. DEBUG ((
  1539. DEBUG_ERROR,
  1540. "%a: Error occured when waiting for the first D2H register FIS - %r\n",
  1541. __FUNCTION__, Status
  1542. ));
  1543. continue;
  1544. }
  1545. Data = AhciReadReg (AhciBar, Offset);
  1546. if ((Data & AHCI_ATAPI_SIG_MASK) == AHCI_ATA_DEVICE_SIG) {
  1547. Status = AhciIdentify (Private, Port, 0, PortIndex - 1, &IdentifyData);
  1548. if (EFI_ERROR (Status)) {
  1549. DEBUG ((DEBUG_ERROR, "%a: AhciIdentify() failed with %r\n", __FUNCTION__, Status));
  1550. continue;
  1551. }
  1552. DEBUG ((DEBUG_INFO, "%a: ATA hard disk found on Port %d.\n", __FUNCTION__, Port));
  1553. } else {
  1554. continue;
  1555. }
  1556. //
  1557. // Found an ATA hard disk device, add it into the device list.
  1558. //
  1559. DeviceIndex++;
  1560. CreateNewDevice (
  1561. Private,
  1562. DeviceIndex,
  1563. Port,
  1564. 0xFFFF,
  1565. PortIndex - 1,
  1566. &IdentifyData
  1567. );
  1568. }
  1569. }
  1570. return EFI_SUCCESS;
  1571. }
  1572. /**
  1573. Trust transfer data from/to ATA device.
  1574. This function performs one ATA pass through transaction to do a trust transfer
  1575. from/to ATA device. It chooses the appropriate ATA command and protocol to invoke
  1576. PassThru interface of ATA pass through.
  1577. @param[in] DeviceData Pointer to PEI_AHCI_ATA_DEVICE_DATA structure.
  1578. @param[in,out] Buffer The pointer to the current transaction buffer.
  1579. @param[in] SecurityProtocolId
  1580. The value of the "Security Protocol" parameter
  1581. of the security protocol command to be sent.
  1582. @param[in] SecurityProtocolSpecificData
  1583. The value of the "Security Protocol Specific"
  1584. parameter of the security protocol command to
  1585. be sent.
  1586. @param[in] TransferLength The block number or sector count of the transfer.
  1587. @param[in] IsTrustSend Indicates whether it is a trust send operation
  1588. or not.
  1589. @param[in] Timeout The timeout, in 100ns units, to use for the execution
  1590. of the security protocol command. A Timeout value
  1591. of 0 means that this function will wait indefinitely
  1592. for the security protocol command to execute. If
  1593. Timeout is greater than zero, then this function
  1594. will return EFI_TIMEOUT if the time required to
  1595. execute the receive data command is greater than
  1596. Timeout.
  1597. @param[out] TransferLengthOut
  1598. A pointer to a buffer to store the size in bytes
  1599. of the data written to the buffer. Ignore it when
  1600. IsTrustSend is TRUE.
  1601. @retval EFI_SUCCESS The data transfer is complete successfully.
  1602. @return others Some error occurs when transferring data.
  1603. **/
  1604. EFI_STATUS
  1605. TrustTransferAtaDevice (
  1606. IN PEI_AHCI_ATA_DEVICE_DATA *DeviceData,
  1607. IN OUT VOID *Buffer,
  1608. IN UINT8 SecurityProtocolId,
  1609. IN UINT16 SecurityProtocolSpecificData,
  1610. IN UINTN TransferLength,
  1611. IN BOOLEAN IsTrustSend,
  1612. IN UINT64 Timeout,
  1613. OUT UINTN *TransferLengthOut
  1614. )
  1615. {
  1616. PEI_AHCI_CONTROLLER_PRIVATE_DATA *Private;
  1617. EDKII_PEI_ATA_PASS_THRU_PPI *AtaPassThru;
  1618. EFI_ATA_COMMAND_BLOCK Acb;
  1619. EFI_ATA_PASS_THRU_COMMAND_PACKET Packet;
  1620. EFI_STATUS Status;
  1621. VOID *NewBuffer;
  1622. Private = DeviceData->Private;
  1623. AtaPassThru = &Private->AtaPassThruPpi;
  1624. //
  1625. // Ensure IsTrustSend are valid boolean values
  1626. //
  1627. ASSERT ((UINTN) IsTrustSend < 2);
  1628. if ((UINTN) IsTrustSend >= 2) {
  1629. return EFI_INVALID_PARAMETER;
  1630. }
  1631. //
  1632. // Prepare for ATA command block.
  1633. //
  1634. ZeroMem (&Acb, sizeof (EFI_ATA_COMMAND_BLOCK));
  1635. if (TransferLength == 0) {
  1636. Acb.AtaCommand = ATA_CMD_TRUST_NON_DATA;
  1637. } else {
  1638. Acb.AtaCommand = mAtaTrustCommands[IsTrustSend];
  1639. }
  1640. Acb.AtaFeatures = SecurityProtocolId;
  1641. Acb.AtaSectorCount = (UINT8) (TransferLength / 512);
  1642. Acb.AtaSectorNumber = (UINT8) ((TransferLength / 512) >> 8);
  1643. //
  1644. // NOTE: ATA Spec has no explicitly definition for Security Protocol Specific layout.
  1645. // Here use big endian for Cylinder register.
  1646. //
  1647. Acb.AtaCylinderHigh = (UINT8) SecurityProtocolSpecificData;
  1648. Acb.AtaCylinderLow = (UINT8) (SecurityProtocolSpecificData >> 8);
  1649. Acb.AtaDeviceHead = (UINT8) (BIT7 | BIT6 | BIT5 |
  1650. (DeviceData->PortMultiplier == 0xFFFF ?
  1651. 0 : (DeviceData->PortMultiplier << 4)));
  1652. //
  1653. // Prepare for ATA pass through packet.
  1654. //
  1655. ZeroMem (&Packet, sizeof (EFI_ATA_PASS_THRU_COMMAND_PACKET));
  1656. if (TransferLength == 0) {
  1657. Packet.InTransferLength = 0;
  1658. Packet.OutTransferLength = 0;
  1659. Packet.Protocol = EFI_ATA_PASS_THRU_PROTOCOL_ATA_NON_DATA;
  1660. } else if (IsTrustSend) {
  1661. //
  1662. // Check the alignment of the incoming buffer prior to invoking underlying
  1663. // ATA PassThru PPI.
  1664. //
  1665. if ((AtaPassThru->Mode->IoAlign > 1) &&
  1666. !IS_ALIGNED (Buffer, AtaPassThru->Mode->IoAlign)) {
  1667. NewBuffer = AllocateAlignedPages (
  1668. EFI_SIZE_TO_PAGES (TransferLength),
  1669. AtaPassThru->Mode->IoAlign
  1670. );
  1671. if (NewBuffer == NULL) {
  1672. return EFI_OUT_OF_RESOURCES;
  1673. }
  1674. CopyMem (NewBuffer, Buffer, TransferLength);
  1675. Buffer = NewBuffer;
  1676. }
  1677. Packet.OutDataBuffer = Buffer;
  1678. Packet.OutTransferLength = (UINT32) TransferLength;
  1679. Packet.Protocol = mAtaPassThruCmdProtocols[IsTrustSend];
  1680. } else {
  1681. Packet.InDataBuffer = Buffer;
  1682. Packet.InTransferLength = (UINT32) TransferLength;
  1683. Packet.Protocol = mAtaPassThruCmdProtocols[IsTrustSend];
  1684. }
  1685. Packet.Asb = NULL;
  1686. Packet.Acb = &Acb;
  1687. Packet.Timeout = Timeout;
  1688. Packet.Length = EFI_ATA_PASS_THRU_LENGTH_BYTES;
  1689. Status = AtaPassThru->PassThru (
  1690. AtaPassThru,
  1691. DeviceData->Port,
  1692. DeviceData->PortMultiplier,
  1693. &Packet
  1694. );
  1695. if (TransferLengthOut != NULL) {
  1696. if (!IsTrustSend) {
  1697. *TransferLengthOut = Packet.InTransferLength;
  1698. }
  1699. }
  1700. return Status;
  1701. }