AhciMode.c 86 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818
  1. /** @file
  2. The file for AHCI mode of ATA host controller.
  3. Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR>
  4. (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
  5. SPDX-License-Identifier: BSD-2-Clause-Patent
  6. **/
  7. #include "AtaAtapiPassThru.h"
  8. /**
  9. Read AHCI Operation register.
  10. @param PciIo The PCI IO protocol instance.
  11. @param Offset The operation register offset.
  12. @return The register content read.
  13. **/
  14. UINT32
  15. EFIAPI
  16. AhciReadReg (
  17. IN EFI_PCI_IO_PROTOCOL *PciIo,
  18. IN UINT32 Offset
  19. )
  20. {
  21. UINT32 Data;
  22. ASSERT (PciIo != NULL);
  23. Data = 0;
  24. PciIo->Mem.Read (
  25. PciIo,
  26. EfiPciIoWidthUint32,
  27. EFI_AHCI_BAR_INDEX,
  28. (UINT64) Offset,
  29. 1,
  30. &Data
  31. );
  32. return Data;
  33. }
  34. /**
  35. Write AHCI Operation register.
  36. @param PciIo The PCI IO protocol instance.
  37. @param Offset The operation register offset.
  38. @param Data The data used to write down.
  39. **/
  40. VOID
  41. EFIAPI
  42. AhciWriteReg (
  43. IN EFI_PCI_IO_PROTOCOL *PciIo,
  44. IN UINT32 Offset,
  45. IN UINT32 Data
  46. )
  47. {
  48. ASSERT (PciIo != NULL);
  49. PciIo->Mem.Write (
  50. PciIo,
  51. EfiPciIoWidthUint32,
  52. EFI_AHCI_BAR_INDEX,
  53. (UINT64) Offset,
  54. 1,
  55. &Data
  56. );
  57. return ;
  58. }
  59. /**
  60. Do AND operation with the value of AHCI Operation register.
  61. @param PciIo The PCI IO protocol instance.
  62. @param Offset The operation register offset.
  63. @param AndData The data used to do AND operation.
  64. **/
  65. VOID
  66. EFIAPI
  67. AhciAndReg (
  68. IN EFI_PCI_IO_PROTOCOL *PciIo,
  69. IN UINT32 Offset,
  70. IN UINT32 AndData
  71. )
  72. {
  73. UINT32 Data;
  74. ASSERT (PciIo != NULL);
  75. Data = AhciReadReg (PciIo, Offset);
  76. Data &= AndData;
  77. AhciWriteReg (PciIo, Offset, Data);
  78. }
  79. /**
  80. Do OR operation with the value of AHCI Operation register.
  81. @param PciIo The PCI IO protocol instance.
  82. @param Offset The operation register offset.
  83. @param OrData The data used to do OR operation.
  84. **/
  85. VOID
  86. EFIAPI
  87. AhciOrReg (
  88. IN EFI_PCI_IO_PROTOCOL *PciIo,
  89. IN UINT32 Offset,
  90. IN UINT32 OrData
  91. )
  92. {
  93. UINT32 Data;
  94. ASSERT (PciIo != NULL);
  95. Data = AhciReadReg (PciIo, Offset);
  96. Data |= OrData;
  97. AhciWriteReg (PciIo, Offset, Data);
  98. }
  99. /**
  100. Wait for the value of the specified MMIO register set to the test value.
  101. @param PciIo The PCI IO protocol instance.
  102. @param Offset The MMIO address to test.
  103. @param MaskValue The mask value of memory.
  104. @param TestValue The test value of memory.
  105. @param Timeout The time out value for wait memory set, uses 100ns as a unit.
  106. @retval EFI_TIMEOUT The MMIO setting is time out.
  107. @retval EFI_SUCCESS The MMIO is correct set.
  108. **/
  109. EFI_STATUS
  110. EFIAPI
  111. AhciWaitMmioSet (
  112. IN EFI_PCI_IO_PROTOCOL *PciIo,
  113. IN UINTN Offset,
  114. IN UINT32 MaskValue,
  115. IN UINT32 TestValue,
  116. IN UINT64 Timeout
  117. )
  118. {
  119. UINT32 Value;
  120. UINT64 Delay;
  121. BOOLEAN InfiniteWait;
  122. if (Timeout == 0) {
  123. InfiniteWait = TRUE;
  124. } else {
  125. InfiniteWait = FALSE;
  126. }
  127. Delay = DivU64x32 (Timeout, 1000) + 1;
  128. do {
  129. //
  130. // Access PCI MMIO space to see if the value is the tested one.
  131. //
  132. Value = AhciReadReg (PciIo, (UINT32) Offset) & MaskValue;
  133. if (Value == TestValue) {
  134. return EFI_SUCCESS;
  135. }
  136. //
  137. // Stall for 100 microseconds.
  138. //
  139. MicroSecondDelay (100);
  140. Delay--;
  141. } while (InfiniteWait || (Delay > 0));
  142. return EFI_TIMEOUT;
  143. }
  144. /**
  145. Wait for the value of the specified system memory set to the test value.
  146. @param Address The system memory address to test.
  147. @param MaskValue The mask value of memory.
  148. @param TestValue The test value of memory.
  149. @param Timeout The time out value for wait memory set, uses 100ns as a unit.
  150. @retval EFI_TIMEOUT The system memory setting is time out.
  151. @retval EFI_SUCCESS The system memory is correct set.
  152. **/
  153. EFI_STATUS
  154. EFIAPI
  155. AhciWaitMemSet (
  156. IN EFI_PHYSICAL_ADDRESS Address,
  157. IN UINT32 MaskValue,
  158. IN UINT32 TestValue,
  159. IN UINT64 Timeout
  160. )
  161. {
  162. UINT32 Value;
  163. UINT64 Delay;
  164. BOOLEAN InfiniteWait;
  165. if (Timeout == 0) {
  166. InfiniteWait = TRUE;
  167. } else {
  168. InfiniteWait = FALSE;
  169. }
  170. Delay = DivU64x32 (Timeout, 1000) + 1;
  171. do {
  172. //
  173. // Access sytem memory to see if the value is the tested one.
  174. //
  175. // The system memory pointed by Address will be updated by the
  176. // SATA Host Controller, "volatile" is introduced to prevent
  177. // compiler from optimizing the access to the memory address
  178. // to only read once.
  179. //
  180. Value = *(volatile UINT32 *) (UINTN) Address;
  181. Value &= MaskValue;
  182. if (Value == TestValue) {
  183. return EFI_SUCCESS;
  184. }
  185. //
  186. // Stall for 100 microseconds.
  187. //
  188. MicroSecondDelay (100);
  189. Delay--;
  190. } while (InfiniteWait || (Delay > 0));
  191. return EFI_TIMEOUT;
  192. }
  193. /**
  194. Check the memory status to the test value.
  195. @param[in] Address The memory address to test.
  196. @param[in] MaskValue The mask value of memory.
  197. @param[in] TestValue The test value of memory.
  198. @param[in, out] Task Optional. Pointer to the ATA_NONBLOCK_TASK used by
  199. non-blocking mode. If NULL, then just try once.
  200. @retval EFI_NOTREADY The memory is not set.
  201. @retval EFI_TIMEOUT The memory setting retry times out.
  202. @retval EFI_SUCCESS The memory is correct set.
  203. **/
  204. EFI_STATUS
  205. EFIAPI
  206. AhciCheckMemSet (
  207. IN UINTN Address,
  208. IN UINT32 MaskValue,
  209. IN UINT32 TestValue,
  210. IN OUT ATA_NONBLOCK_TASK *Task
  211. )
  212. {
  213. UINT32 Value;
  214. if (Task != NULL) {
  215. Task->RetryTimes--;
  216. }
  217. Value = *(volatile UINT32 *) Address;
  218. Value &= MaskValue;
  219. if (Value == TestValue) {
  220. return EFI_SUCCESS;
  221. }
  222. if ((Task != NULL) && !Task->InfiniteWait && (Task->RetryTimes == 0)) {
  223. return EFI_TIMEOUT;
  224. } else {
  225. return EFI_NOT_READY;
  226. }
  227. }
  228. /**
  229. Clear the port interrupt and error status. It will also clear
  230. HBA interrupt status.
  231. @param PciIo The PCI IO protocol instance.
  232. @param Port The number of port.
  233. **/
  234. VOID
  235. EFIAPI
  236. AhciClearPortStatus (
  237. IN EFI_PCI_IO_PROTOCOL *PciIo,
  238. IN UINT8 Port
  239. )
  240. {
  241. UINT32 Offset;
  242. //
  243. // Clear any error status
  244. //
  245. Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_SERR;
  246. AhciWriteReg (PciIo, Offset, AhciReadReg (PciIo, Offset));
  247. //
  248. // Clear any port interrupt status
  249. //
  250. Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_IS;
  251. AhciWriteReg (PciIo, Offset, AhciReadReg (PciIo, Offset));
  252. //
  253. // Clear any HBA interrupt status
  254. //
  255. AhciWriteReg (PciIo, EFI_AHCI_IS_OFFSET, AhciReadReg (PciIo, EFI_AHCI_IS_OFFSET));
  256. }
  257. /**
  258. This function is used to dump the Status Registers and if there is ERR bit set
  259. in the Status Register, the Error Register's value is also be dumped.
  260. @param PciIo The PCI IO protocol instance.
  261. @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
  262. @param Port The number of port.
  263. @param AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.
  264. **/
  265. VOID
  266. EFIAPI
  267. AhciDumpPortStatus (
  268. IN EFI_PCI_IO_PROTOCOL *PciIo,
  269. IN EFI_AHCI_REGISTERS *AhciRegisters,
  270. IN UINT8 Port,
  271. IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock
  272. )
  273. {
  274. UINTN Offset;
  275. UINT32 Data;
  276. UINTN FisBaseAddr;
  277. EFI_STATUS Status;
  278. ASSERT (PciIo != NULL);
  279. if (AtaStatusBlock != NULL) {
  280. ZeroMem (AtaStatusBlock, sizeof (EFI_ATA_STATUS_BLOCK));
  281. FisBaseAddr = (UINTN)AhciRegisters->AhciRFis + Port * sizeof (EFI_AHCI_RECEIVED_FIS);
  282. Offset = FisBaseAddr + EFI_AHCI_D2H_FIS_OFFSET;
  283. Status = AhciCheckMemSet (Offset, EFI_AHCI_FIS_TYPE_MASK, EFI_AHCI_FIS_REGISTER_D2H, NULL);
  284. if (!EFI_ERROR (Status)) {
  285. //
  286. // If D2H FIS is received, update StatusBlock with its content.
  287. //
  288. CopyMem (AtaStatusBlock, (UINT8 *)Offset, sizeof (EFI_ATA_STATUS_BLOCK));
  289. } else {
  290. //
  291. // If D2H FIS is not received, only update Status & Error field through PxTFD
  292. // as there is no other way to get the content of the Shadow Register Block.
  293. //
  294. Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_TFD;
  295. Data = AhciReadReg (PciIo, (UINT32)Offset);
  296. AtaStatusBlock->AtaStatus = (UINT8)Data;
  297. if ((AtaStatusBlock->AtaStatus & BIT0) != 0) {
  298. AtaStatusBlock->AtaError = (UINT8)(Data >> 8);
  299. }
  300. }
  301. }
  302. }
  303. /**
  304. Enable the FIS running for giving port.
  305. @param PciIo The PCI IO protocol instance.
  306. @param Port The number of port.
  307. @param Timeout The timeout value of enabling FIS, uses 100ns as a unit.
  308. @retval EFI_DEVICE_ERROR The FIS enable setting fails.
  309. @retval EFI_TIMEOUT The FIS enable setting is time out.
  310. @retval EFI_SUCCESS The FIS enable successfully.
  311. **/
  312. EFI_STATUS
  313. EFIAPI
  314. AhciEnableFisReceive (
  315. IN EFI_PCI_IO_PROTOCOL *PciIo,
  316. IN UINT8 Port,
  317. IN UINT64 Timeout
  318. )
  319. {
  320. UINT32 Offset;
  321. Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD;
  322. AhciOrReg (PciIo, Offset, EFI_AHCI_PORT_CMD_FRE);
  323. return EFI_SUCCESS;
  324. }
  325. /**
  326. Disable the FIS running for giving port.
  327. @param PciIo The PCI IO protocol instance.
  328. @param Port The number of port.
  329. @param Timeout The timeout value of disabling FIS, uses 100ns as a unit.
  330. @retval EFI_DEVICE_ERROR The FIS disable setting fails.
  331. @retval EFI_TIMEOUT The FIS disable setting is time out.
  332. @retval EFI_UNSUPPORTED The port is in running state.
  333. @retval EFI_SUCCESS The FIS disable successfully.
  334. **/
  335. EFI_STATUS
  336. EFIAPI
  337. AhciDisableFisReceive (
  338. IN EFI_PCI_IO_PROTOCOL *PciIo,
  339. IN UINT8 Port,
  340. IN UINT64 Timeout
  341. )
  342. {
  343. UINT32 Offset;
  344. UINT32 Data;
  345. Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD;
  346. Data = AhciReadReg (PciIo, Offset);
  347. //
  348. // Before disabling Fis receive, the DMA engine of the port should NOT be in running status.
  349. //
  350. if ((Data & (EFI_AHCI_PORT_CMD_ST | EFI_AHCI_PORT_CMD_CR)) != 0) {
  351. return EFI_UNSUPPORTED;
  352. }
  353. //
  354. // Check if the Fis receive DMA engine for the port is running.
  355. //
  356. if ((Data & EFI_AHCI_PORT_CMD_FR) != EFI_AHCI_PORT_CMD_FR) {
  357. return EFI_SUCCESS;
  358. }
  359. AhciAndReg (PciIo, Offset, (UINT32)~(EFI_AHCI_PORT_CMD_FRE));
  360. return AhciWaitMmioSet (
  361. PciIo,
  362. Offset,
  363. EFI_AHCI_PORT_CMD_FR,
  364. 0,
  365. Timeout
  366. );
  367. }
  368. /**
  369. Build the command list, command table and prepare the fis receiver.
  370. @param PciIo The PCI IO protocol instance.
  371. @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
  372. @param Port The number of port.
  373. @param PortMultiplier The timeout value of stop.
  374. @param CommandFis The control fis will be used for the transfer.
  375. @param CommandList The command list will be used for the transfer.
  376. @param AtapiCommand The atapi command will be used for the transfer.
  377. @param AtapiCommandLength The length of the atapi command.
  378. @param CommandSlotNumber The command slot will be used for the transfer.
  379. @param DataPhysicalAddr The pointer to the data buffer pci bus master address.
  380. @param DataLength The data count to be transferred.
  381. **/
  382. VOID
  383. EFIAPI
  384. AhciBuildCommand (
  385. IN EFI_PCI_IO_PROTOCOL *PciIo,
  386. IN EFI_AHCI_REGISTERS *AhciRegisters,
  387. IN UINT8 Port,
  388. IN UINT8 PortMultiplier,
  389. IN EFI_AHCI_COMMAND_FIS *CommandFis,
  390. IN EFI_AHCI_COMMAND_LIST *CommandList,
  391. IN EFI_AHCI_ATAPI_COMMAND *AtapiCommand OPTIONAL,
  392. IN UINT8 AtapiCommandLength,
  393. IN UINT8 CommandSlotNumber,
  394. IN OUT VOID *DataPhysicalAddr,
  395. IN UINT32 DataLength
  396. )
  397. {
  398. UINT64 BaseAddr;
  399. UINT32 PrdtNumber;
  400. UINT32 PrdtIndex;
  401. UINTN RemainedData;
  402. UINTN MemAddr;
  403. DATA_64 Data64;
  404. UINT32 Offset;
  405. //
  406. // Filling the PRDT
  407. //
  408. PrdtNumber = (UINT32)DivU64x32 (((UINT64)DataLength + EFI_AHCI_MAX_DATA_PER_PRDT - 1), EFI_AHCI_MAX_DATA_PER_PRDT);
  409. //
  410. // According to AHCI 1.3 spec, a PRDT entry can point to a maximum 4MB data block.
  411. // It also limits that the maximum amount of the PRDT entry in the command table
  412. // is 65535.
  413. //
  414. ASSERT (PrdtNumber <= 65535);
  415. Data64.Uint64 = (UINTN) (AhciRegisters->AhciRFis) + sizeof (EFI_AHCI_RECEIVED_FIS) * Port;
  416. BaseAddr = Data64.Uint64;
  417. ZeroMem ((VOID *)((UINTN) BaseAddr), sizeof (EFI_AHCI_RECEIVED_FIS));
  418. ZeroMem (AhciRegisters->AhciCommandTable, sizeof (EFI_AHCI_COMMAND_TABLE));
  419. CommandFis->AhciCFisPmNum = PortMultiplier;
  420. CopyMem (&AhciRegisters->AhciCommandTable->CommandFis, CommandFis, sizeof (EFI_AHCI_COMMAND_FIS));
  421. Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD;
  422. if (AtapiCommand != NULL) {
  423. CopyMem (
  424. &AhciRegisters->AhciCommandTable->AtapiCmd,
  425. AtapiCommand,
  426. AtapiCommandLength
  427. );
  428. CommandList->AhciCmdA = 1;
  429. CommandList->AhciCmdP = 1;
  430. AhciOrReg (PciIo, Offset, (EFI_AHCI_PORT_CMD_DLAE | EFI_AHCI_PORT_CMD_ATAPI));
  431. } else {
  432. AhciAndReg (PciIo, Offset, (UINT32)~(EFI_AHCI_PORT_CMD_DLAE | EFI_AHCI_PORT_CMD_ATAPI));
  433. }
  434. RemainedData = (UINTN) DataLength;
  435. MemAddr = (UINTN) DataPhysicalAddr;
  436. CommandList->AhciCmdPrdtl = PrdtNumber;
  437. for (PrdtIndex = 0; PrdtIndex < PrdtNumber; PrdtIndex++) {
  438. if (RemainedData < EFI_AHCI_MAX_DATA_PER_PRDT) {
  439. AhciRegisters->AhciCommandTable->PrdtTable[PrdtIndex].AhciPrdtDbc = (UINT32)RemainedData - 1;
  440. } else {
  441. AhciRegisters->AhciCommandTable->PrdtTable[PrdtIndex].AhciPrdtDbc = EFI_AHCI_MAX_DATA_PER_PRDT - 1;
  442. }
  443. Data64.Uint64 = (UINT64)MemAddr;
  444. AhciRegisters->AhciCommandTable->PrdtTable[PrdtIndex].AhciPrdtDba = Data64.Uint32.Lower32;
  445. AhciRegisters->AhciCommandTable->PrdtTable[PrdtIndex].AhciPrdtDbau = Data64.Uint32.Upper32;
  446. RemainedData -= EFI_AHCI_MAX_DATA_PER_PRDT;
  447. MemAddr += EFI_AHCI_MAX_DATA_PER_PRDT;
  448. }
  449. //
  450. // Set the last PRDT to Interrupt On Complete
  451. //
  452. if (PrdtNumber > 0) {
  453. AhciRegisters->AhciCommandTable->PrdtTable[PrdtNumber - 1].AhciPrdtIoc = 1;
  454. }
  455. CopyMem (
  456. (VOID *) ((UINTN) AhciRegisters->AhciCmdList + (UINTN) CommandSlotNumber * sizeof (EFI_AHCI_COMMAND_LIST)),
  457. CommandList,
  458. sizeof (EFI_AHCI_COMMAND_LIST)
  459. );
  460. Data64.Uint64 = (UINT64)(UINTN) AhciRegisters->AhciCommandTablePciAddr;
  461. AhciRegisters->AhciCmdList[CommandSlotNumber].AhciCmdCtba = Data64.Uint32.Lower32;
  462. AhciRegisters->AhciCmdList[CommandSlotNumber].AhciCmdCtbau = Data64.Uint32.Upper32;
  463. AhciRegisters->AhciCmdList[CommandSlotNumber].AhciCmdPmp = PortMultiplier;
  464. }
  465. /**
  466. Buid a command FIS.
  467. @param CmdFis A pointer to the EFI_AHCI_COMMAND_FIS data structure.
  468. @param AtaCommandBlock A pointer to the AhciBuildCommandFis data structure.
  469. **/
  470. VOID
  471. EFIAPI
  472. AhciBuildCommandFis (
  473. IN OUT EFI_AHCI_COMMAND_FIS *CmdFis,
  474. IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock
  475. )
  476. {
  477. ZeroMem (CmdFis, sizeof (EFI_AHCI_COMMAND_FIS));
  478. CmdFis->AhciCFisType = EFI_AHCI_FIS_REGISTER_H2D;
  479. //
  480. // Indicator it's a command
  481. //
  482. CmdFis->AhciCFisCmdInd = 0x1;
  483. CmdFis->AhciCFisCmd = AtaCommandBlock->AtaCommand;
  484. CmdFis->AhciCFisFeature = AtaCommandBlock->AtaFeatures;
  485. CmdFis->AhciCFisFeatureExp = AtaCommandBlock->AtaFeaturesExp;
  486. CmdFis->AhciCFisSecNum = AtaCommandBlock->AtaSectorNumber;
  487. CmdFis->AhciCFisSecNumExp = AtaCommandBlock->AtaSectorNumberExp;
  488. CmdFis->AhciCFisClyLow = AtaCommandBlock->AtaCylinderLow;
  489. CmdFis->AhciCFisClyLowExp = AtaCommandBlock->AtaCylinderLowExp;
  490. CmdFis->AhciCFisClyHigh = AtaCommandBlock->AtaCylinderHigh;
  491. CmdFis->AhciCFisClyHighExp = AtaCommandBlock->AtaCylinderHighExp;
  492. CmdFis->AhciCFisSecCount = AtaCommandBlock->AtaSectorCount;
  493. CmdFis->AhciCFisSecCountExp = AtaCommandBlock->AtaSectorCountExp;
  494. CmdFis->AhciCFisDevHead = (UINT8) (AtaCommandBlock->AtaDeviceHead | 0xE0);
  495. }
  496. /**
  497. Start a PIO data transfer on specific port.
  498. @param[in] PciIo The PCI IO protocol instance.
  499. @param[in] AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
  500. @param[in] Port The number of port.
  501. @param[in] PortMultiplier The timeout value of stop.
  502. @param[in] AtapiCommand The atapi command will be used for the
  503. transfer.
  504. @param[in] AtapiCommandLength The length of the atapi command.
  505. @param[in] Read The transfer direction.
  506. @param[in] AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.
  507. @param[in, out] AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.
  508. @param[in, out] MemoryAddr The pointer to the data buffer.
  509. @param[in] DataCount The data count to be transferred.
  510. @param[in] Timeout The timeout value of non data transfer, uses 100ns as a unit.
  511. @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK
  512. used by non-blocking mode.
  513. @retval EFI_DEVICE_ERROR The PIO data transfer abort with error occurs.
  514. @retval EFI_TIMEOUT The operation is time out.
  515. @retval EFI_UNSUPPORTED The device is not ready for transfer.
  516. @retval EFI_SUCCESS The PIO data transfer executes successfully.
  517. **/
  518. EFI_STATUS
  519. EFIAPI
  520. AhciPioTransfer (
  521. IN EFI_PCI_IO_PROTOCOL *PciIo,
  522. IN EFI_AHCI_REGISTERS *AhciRegisters,
  523. IN UINT8 Port,
  524. IN UINT8 PortMultiplier,
  525. IN EFI_AHCI_ATAPI_COMMAND *AtapiCommand OPTIONAL,
  526. IN UINT8 AtapiCommandLength,
  527. IN BOOLEAN Read,
  528. IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock,
  529. IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock,
  530. IN OUT VOID *MemoryAddr,
  531. IN UINT32 DataCount,
  532. IN UINT64 Timeout,
  533. IN ATA_NONBLOCK_TASK *Task
  534. )
  535. {
  536. EFI_STATUS Status;
  537. UINTN FisBaseAddr;
  538. UINTN Offset;
  539. EFI_PHYSICAL_ADDRESS PhyAddr;
  540. VOID *Map;
  541. UINTN MapLength;
  542. EFI_PCI_IO_PROTOCOL_OPERATION Flag;
  543. UINT64 Delay;
  544. EFI_AHCI_COMMAND_FIS CFis;
  545. EFI_AHCI_COMMAND_LIST CmdList;
  546. UINT32 PortTfd;
  547. UINT32 PrdCount;
  548. BOOLEAN InfiniteWait;
  549. BOOLEAN PioFisReceived;
  550. BOOLEAN D2hFisReceived;
  551. if (Timeout == 0) {
  552. InfiniteWait = TRUE;
  553. } else {
  554. InfiniteWait = FALSE;
  555. }
  556. if (Read) {
  557. Flag = EfiPciIoOperationBusMasterWrite;
  558. } else {
  559. Flag = EfiPciIoOperationBusMasterRead;
  560. }
  561. //
  562. // construct command list and command table with pci bus address
  563. //
  564. MapLength = DataCount;
  565. Status = PciIo->Map (
  566. PciIo,
  567. Flag,
  568. MemoryAddr,
  569. &MapLength,
  570. &PhyAddr,
  571. &Map
  572. );
  573. if (EFI_ERROR (Status) || (DataCount != MapLength)) {
  574. return EFI_BAD_BUFFER_SIZE;
  575. }
  576. //
  577. // Package read needed
  578. //
  579. AhciBuildCommandFis (&CFis, AtaCommandBlock);
  580. ZeroMem (&CmdList, sizeof (EFI_AHCI_COMMAND_LIST));
  581. CmdList.AhciCmdCfl = EFI_AHCI_FIS_REGISTER_H2D_LENGTH / 4;
  582. CmdList.AhciCmdW = Read ? 0 : 1;
  583. AhciBuildCommand (
  584. PciIo,
  585. AhciRegisters,
  586. Port,
  587. PortMultiplier,
  588. &CFis,
  589. &CmdList,
  590. AtapiCommand,
  591. AtapiCommandLength,
  592. 0,
  593. (VOID *)(UINTN)PhyAddr,
  594. DataCount
  595. );
  596. Status = AhciStartCommand (
  597. PciIo,
  598. Port,
  599. 0,
  600. Timeout
  601. );
  602. if (EFI_ERROR (Status)) {
  603. goto Exit;
  604. }
  605. //
  606. // Check the status and wait the driver sending data
  607. //
  608. FisBaseAddr = (UINTN)AhciRegisters->AhciRFis + Port * sizeof (EFI_AHCI_RECEIVED_FIS);
  609. if (Read && (AtapiCommand == 0)) {
  610. //
  611. // Wait device sends the PIO setup fis before data transfer
  612. //
  613. Status = EFI_TIMEOUT;
  614. Delay = DivU64x32 (Timeout, 1000) + 1;
  615. do {
  616. PioFisReceived = FALSE;
  617. D2hFisReceived = FALSE;
  618. Offset = FisBaseAddr + EFI_AHCI_PIO_FIS_OFFSET;
  619. Status = AhciCheckMemSet (Offset, EFI_AHCI_FIS_TYPE_MASK, EFI_AHCI_FIS_PIO_SETUP, NULL);
  620. if (!EFI_ERROR (Status)) {
  621. PioFisReceived = TRUE;
  622. }
  623. //
  624. // According to SATA 2.6 spec section 11.7, D2h FIS means an error encountered.
  625. // But Qemu and Marvel 9230 sata controller may just receive a D2h FIS from device
  626. // after the transaction is finished successfully.
  627. // To get better device compatibilities, we further check if the PxTFD's ERR bit is set.
  628. // By this way, we can know if there is a real error happened.
  629. //
  630. Offset = FisBaseAddr + EFI_AHCI_D2H_FIS_OFFSET;
  631. Status = AhciCheckMemSet (Offset, EFI_AHCI_FIS_TYPE_MASK, EFI_AHCI_FIS_REGISTER_D2H, NULL);
  632. if (!EFI_ERROR (Status)) {
  633. D2hFisReceived = TRUE;
  634. }
  635. if (PioFisReceived || D2hFisReceived) {
  636. Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_TFD;
  637. PortTfd = AhciReadReg (PciIo, (UINT32) Offset);
  638. //
  639. // PxTFD will be updated if there is a D2H or SetupFIS received.
  640. //
  641. if ((PortTfd & EFI_AHCI_PORT_TFD_ERR) != 0) {
  642. Status = EFI_DEVICE_ERROR;
  643. break;
  644. }
  645. PrdCount = *(volatile UINT32 *) (&(AhciRegisters->AhciCmdList[0].AhciCmdPrdbc));
  646. if (PrdCount == DataCount) {
  647. Status = EFI_SUCCESS;
  648. break;
  649. }
  650. }
  651. //
  652. // Stall for 100 microseconds.
  653. //
  654. MicroSecondDelay(100);
  655. Delay--;
  656. if (Delay == 0) {
  657. Status = EFI_TIMEOUT;
  658. }
  659. } while (InfiniteWait || (Delay > 0));
  660. } else {
  661. //
  662. // Wait for D2H Fis is received
  663. //
  664. Offset = FisBaseAddr + EFI_AHCI_D2H_FIS_OFFSET;
  665. Status = AhciWaitMemSet (
  666. Offset,
  667. EFI_AHCI_FIS_TYPE_MASK,
  668. EFI_AHCI_FIS_REGISTER_D2H,
  669. Timeout
  670. );
  671. if (EFI_ERROR (Status)) {
  672. goto Exit;
  673. }
  674. Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_TFD;
  675. PortTfd = AhciReadReg (PciIo, (UINT32) Offset);
  676. if ((PortTfd & EFI_AHCI_PORT_TFD_ERR) != 0) {
  677. Status = EFI_DEVICE_ERROR;
  678. }
  679. }
  680. Exit:
  681. AhciStopCommand (
  682. PciIo,
  683. Port,
  684. Timeout
  685. );
  686. AhciDisableFisReceive (
  687. PciIo,
  688. Port,
  689. Timeout
  690. );
  691. PciIo->Unmap (
  692. PciIo,
  693. Map
  694. );
  695. AhciDumpPortStatus (PciIo, AhciRegisters, Port, AtaStatusBlock);
  696. return Status;
  697. }
  698. /**
  699. Start a DMA data transfer on specific port
  700. @param[in] Instance The ATA_ATAPI_PASS_THRU_INSTANCE protocol instance.
  701. @param[in] AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
  702. @param[in] Port The number of port.
  703. @param[in] PortMultiplier The timeout value of stop.
  704. @param[in] AtapiCommand The atapi command will be used for the
  705. transfer.
  706. @param[in] AtapiCommandLength The length of the atapi command.
  707. @param[in] Read The transfer direction.
  708. @param[in] AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.
  709. @param[in, out] AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.
  710. @param[in, out] MemoryAddr The pointer to the data buffer.
  711. @param[in] DataCount The data count to be transferred.
  712. @param[in] Timeout The timeout value of non data transfer, uses 100ns as a unit.
  713. @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK
  714. used by non-blocking mode.
  715. @retval EFI_DEVICE_ERROR The DMA data transfer abort with error occurs.
  716. @retval EFI_TIMEOUT The operation is time out.
  717. @retval EFI_UNSUPPORTED The device is not ready for transfer.
  718. @retval EFI_SUCCESS The DMA data transfer executes successfully.
  719. **/
  720. EFI_STATUS
  721. EFIAPI
  722. AhciDmaTransfer (
  723. IN ATA_ATAPI_PASS_THRU_INSTANCE *Instance,
  724. IN EFI_AHCI_REGISTERS *AhciRegisters,
  725. IN UINT8 Port,
  726. IN UINT8 PortMultiplier,
  727. IN EFI_AHCI_ATAPI_COMMAND *AtapiCommand OPTIONAL,
  728. IN UINT8 AtapiCommandLength,
  729. IN BOOLEAN Read,
  730. IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock,
  731. IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock,
  732. IN OUT VOID *MemoryAddr,
  733. IN UINT32 DataCount,
  734. IN UINT64 Timeout,
  735. IN ATA_NONBLOCK_TASK *Task
  736. )
  737. {
  738. EFI_STATUS Status;
  739. UINTN Offset;
  740. EFI_PHYSICAL_ADDRESS PhyAddr;
  741. VOID *Map;
  742. UINTN MapLength;
  743. EFI_PCI_IO_PROTOCOL_OPERATION Flag;
  744. EFI_AHCI_COMMAND_FIS CFis;
  745. EFI_AHCI_COMMAND_LIST CmdList;
  746. UINTN FisBaseAddr;
  747. UINT32 PortTfd;
  748. EFI_PCI_IO_PROTOCOL *PciIo;
  749. EFI_TPL OldTpl;
  750. Map = NULL;
  751. PciIo = Instance->PciIo;
  752. if (PciIo == NULL) {
  753. return EFI_INVALID_PARAMETER;
  754. }
  755. //
  756. // Before starting the Blocking BlockIO operation, push to finish all non-blocking
  757. // BlockIO tasks.
  758. // Delay 100us to simulate the blocking time out checking.
  759. //
  760. OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
  761. while ((Task == NULL) && (!IsListEmpty (&Instance->NonBlockingTaskList))) {
  762. AsyncNonBlockingTransferRoutine (NULL, Instance);
  763. //
  764. // Stall for 100us.
  765. //
  766. MicroSecondDelay (100);
  767. }
  768. gBS->RestoreTPL (OldTpl);
  769. if ((Task == NULL) || ((Task != NULL) && (!Task->IsStart))) {
  770. //
  771. // Mark the Task to indicate that it has been started.
  772. //
  773. if (Task != NULL) {
  774. Task->IsStart = TRUE;
  775. }
  776. if (Read) {
  777. Flag = EfiPciIoOperationBusMasterWrite;
  778. } else {
  779. Flag = EfiPciIoOperationBusMasterRead;
  780. }
  781. //
  782. // Construct command list and command table with pci bus address.
  783. //
  784. MapLength = DataCount;
  785. Status = PciIo->Map (
  786. PciIo,
  787. Flag,
  788. MemoryAddr,
  789. &MapLength,
  790. &PhyAddr,
  791. &Map
  792. );
  793. if (EFI_ERROR (Status) || (DataCount != MapLength)) {
  794. return EFI_BAD_BUFFER_SIZE;
  795. }
  796. if (Task != NULL) {
  797. Task->Map = Map;
  798. }
  799. //
  800. // Package read needed
  801. //
  802. AhciBuildCommandFis (&CFis, AtaCommandBlock);
  803. ZeroMem (&CmdList, sizeof (EFI_AHCI_COMMAND_LIST));
  804. CmdList.AhciCmdCfl = EFI_AHCI_FIS_REGISTER_H2D_LENGTH / 4;
  805. CmdList.AhciCmdW = Read ? 0 : 1;
  806. AhciBuildCommand (
  807. PciIo,
  808. AhciRegisters,
  809. Port,
  810. PortMultiplier,
  811. &CFis,
  812. &CmdList,
  813. AtapiCommand,
  814. AtapiCommandLength,
  815. 0,
  816. (VOID *)(UINTN)PhyAddr,
  817. DataCount
  818. );
  819. Status = AhciStartCommand (
  820. PciIo,
  821. Port,
  822. 0,
  823. Timeout
  824. );
  825. if (EFI_ERROR (Status)) {
  826. goto Exit;
  827. }
  828. }
  829. //
  830. // Wait for command compelte
  831. //
  832. FisBaseAddr = (UINTN)AhciRegisters->AhciRFis + Port * sizeof (EFI_AHCI_RECEIVED_FIS);
  833. Offset = FisBaseAddr + EFI_AHCI_D2H_FIS_OFFSET;
  834. if (Task != NULL) {
  835. //
  836. // For Non-blocking
  837. //
  838. Status = AhciCheckMemSet (
  839. Offset,
  840. EFI_AHCI_FIS_TYPE_MASK,
  841. EFI_AHCI_FIS_REGISTER_D2H,
  842. Task
  843. );
  844. } else {
  845. Status = AhciWaitMemSet (
  846. Offset,
  847. EFI_AHCI_FIS_TYPE_MASK,
  848. EFI_AHCI_FIS_REGISTER_D2H,
  849. Timeout
  850. );
  851. }
  852. if (EFI_ERROR (Status)) {
  853. goto Exit;
  854. }
  855. Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_TFD;
  856. PortTfd = AhciReadReg (PciIo, (UINT32) Offset);
  857. if ((PortTfd & EFI_AHCI_PORT_TFD_ERR) != 0) {
  858. Status = EFI_DEVICE_ERROR;
  859. }
  860. Exit:
  861. //
  862. // For Blocking mode, the command should be stopped, the Fis should be disabled
  863. // and the PciIo should be unmapped.
  864. // For non-blocking mode, only when a error is happened (if the return status is
  865. // EFI_NOT_READY that means the command doesn't finished, try again.), first do the
  866. // context cleanup, then set the packet's Asb status.
  867. //
  868. if (Task == NULL ||
  869. ((Task != NULL) && (Status != EFI_NOT_READY))
  870. ) {
  871. AhciStopCommand (
  872. PciIo,
  873. Port,
  874. Timeout
  875. );
  876. AhciDisableFisReceive (
  877. PciIo,
  878. Port,
  879. Timeout
  880. );
  881. PciIo->Unmap (
  882. PciIo,
  883. (Task != NULL) ? Task->Map : Map
  884. );
  885. if (Task != NULL) {
  886. Task->Packet->Asb->AtaStatus = 0x01;
  887. }
  888. }
  889. AhciDumpPortStatus (PciIo, AhciRegisters, Port, AtaStatusBlock);
  890. return Status;
  891. }
  892. /**
  893. Start a non data transfer on specific port.
  894. @param[in] PciIo The PCI IO protocol instance.
  895. @param[in] AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
  896. @param[in] Port The number of port.
  897. @param[in] PortMultiplier The timeout value of stop.
  898. @param[in] AtapiCommand The atapi command will be used for the
  899. transfer.
  900. @param[in] AtapiCommandLength The length of the atapi command.
  901. @param[in] AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.
  902. @param[in, out] AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.
  903. @param[in] Timeout The timeout value of non data transfer, uses 100ns as a unit.
  904. @param[in] Task Optional. Pointer to the ATA_NONBLOCK_TASK
  905. used by non-blocking mode.
  906. @retval EFI_DEVICE_ERROR The non data transfer abort with error occurs.
  907. @retval EFI_TIMEOUT The operation is time out.
  908. @retval EFI_UNSUPPORTED The device is not ready for transfer.
  909. @retval EFI_SUCCESS The non data transfer executes successfully.
  910. **/
  911. EFI_STATUS
  912. EFIAPI
  913. AhciNonDataTransfer (
  914. IN EFI_PCI_IO_PROTOCOL *PciIo,
  915. IN EFI_AHCI_REGISTERS *AhciRegisters,
  916. IN UINT8 Port,
  917. IN UINT8 PortMultiplier,
  918. IN EFI_AHCI_ATAPI_COMMAND *AtapiCommand OPTIONAL,
  919. IN UINT8 AtapiCommandLength,
  920. IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock,
  921. IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock,
  922. IN UINT64 Timeout,
  923. IN ATA_NONBLOCK_TASK *Task
  924. )
  925. {
  926. EFI_STATUS Status;
  927. UINTN FisBaseAddr;
  928. UINTN Offset;
  929. UINT32 PortTfd;
  930. EFI_AHCI_COMMAND_FIS CFis;
  931. EFI_AHCI_COMMAND_LIST CmdList;
  932. //
  933. // Package read needed
  934. //
  935. AhciBuildCommandFis (&CFis, AtaCommandBlock);
  936. ZeroMem (&CmdList, sizeof (EFI_AHCI_COMMAND_LIST));
  937. CmdList.AhciCmdCfl = EFI_AHCI_FIS_REGISTER_H2D_LENGTH / 4;
  938. AhciBuildCommand (
  939. PciIo,
  940. AhciRegisters,
  941. Port,
  942. PortMultiplier,
  943. &CFis,
  944. &CmdList,
  945. AtapiCommand,
  946. AtapiCommandLength,
  947. 0,
  948. NULL,
  949. 0
  950. );
  951. Status = AhciStartCommand (
  952. PciIo,
  953. Port,
  954. 0,
  955. Timeout
  956. );
  957. if (EFI_ERROR (Status)) {
  958. goto Exit;
  959. }
  960. //
  961. // Wait device sends the Response Fis
  962. //
  963. FisBaseAddr = (UINTN)AhciRegisters->AhciRFis + Port * sizeof (EFI_AHCI_RECEIVED_FIS);
  964. Offset = FisBaseAddr + EFI_AHCI_D2H_FIS_OFFSET;
  965. Status = AhciWaitMemSet (
  966. Offset,
  967. EFI_AHCI_FIS_TYPE_MASK,
  968. EFI_AHCI_FIS_REGISTER_D2H,
  969. Timeout
  970. );
  971. if (EFI_ERROR (Status)) {
  972. goto Exit;
  973. }
  974. Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_TFD;
  975. PortTfd = AhciReadReg (PciIo, (UINT32) Offset);
  976. if ((PortTfd & EFI_AHCI_PORT_TFD_ERR) != 0) {
  977. Status = EFI_DEVICE_ERROR;
  978. }
  979. Exit:
  980. AhciStopCommand (
  981. PciIo,
  982. Port,
  983. Timeout
  984. );
  985. AhciDisableFisReceive (
  986. PciIo,
  987. Port,
  988. Timeout
  989. );
  990. AhciDumpPortStatus (PciIo, AhciRegisters, Port, AtaStatusBlock);
  991. return Status;
  992. }
  993. /**
  994. Stop command running for giving port
  995. @param PciIo The PCI IO protocol instance.
  996. @param Port The number of port.
  997. @param Timeout The timeout value of stop, uses 100ns as a unit.
  998. @retval EFI_DEVICE_ERROR The command stop unsuccessfully.
  999. @retval EFI_TIMEOUT The operation is time out.
  1000. @retval EFI_SUCCESS The command stop successfully.
  1001. **/
  1002. EFI_STATUS
  1003. EFIAPI
  1004. AhciStopCommand (
  1005. IN EFI_PCI_IO_PROTOCOL *PciIo,
  1006. IN UINT8 Port,
  1007. IN UINT64 Timeout
  1008. )
  1009. {
  1010. UINT32 Offset;
  1011. UINT32 Data;
  1012. Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD;
  1013. Data = AhciReadReg (PciIo, Offset);
  1014. if ((Data & (EFI_AHCI_PORT_CMD_ST | EFI_AHCI_PORT_CMD_CR)) == 0) {
  1015. return EFI_SUCCESS;
  1016. }
  1017. if ((Data & EFI_AHCI_PORT_CMD_ST) != 0) {
  1018. AhciAndReg (PciIo, Offset, (UINT32)~(EFI_AHCI_PORT_CMD_ST));
  1019. }
  1020. return AhciWaitMmioSet (
  1021. PciIo,
  1022. Offset,
  1023. EFI_AHCI_PORT_CMD_CR,
  1024. 0,
  1025. Timeout
  1026. );
  1027. }
  1028. /**
  1029. Start command for give slot on specific port.
  1030. @param PciIo The PCI IO protocol instance.
  1031. @param Port The number of port.
  1032. @param CommandSlot The number of Command Slot.
  1033. @param Timeout The timeout value of start, uses 100ns as a unit.
  1034. @retval EFI_DEVICE_ERROR The command start unsuccessfully.
  1035. @retval EFI_TIMEOUT The operation is time out.
  1036. @retval EFI_SUCCESS The command start successfully.
  1037. **/
  1038. EFI_STATUS
  1039. EFIAPI
  1040. AhciStartCommand (
  1041. IN EFI_PCI_IO_PROTOCOL *PciIo,
  1042. IN UINT8 Port,
  1043. IN UINT8 CommandSlot,
  1044. IN UINT64 Timeout
  1045. )
  1046. {
  1047. UINT32 CmdSlotBit;
  1048. EFI_STATUS Status;
  1049. UINT32 PortStatus;
  1050. UINT32 StartCmd;
  1051. UINT32 PortTfd;
  1052. UINT32 Offset;
  1053. UINT32 Capability;
  1054. //
  1055. // Collect AHCI controller information
  1056. //
  1057. Capability = AhciReadReg(PciIo, EFI_AHCI_CAPABILITY_OFFSET);
  1058. CmdSlotBit = (UINT32) (1 << CommandSlot);
  1059. AhciClearPortStatus (
  1060. PciIo,
  1061. Port
  1062. );
  1063. Status = AhciEnableFisReceive (
  1064. PciIo,
  1065. Port,
  1066. Timeout
  1067. );
  1068. if (EFI_ERROR (Status)) {
  1069. return Status;
  1070. }
  1071. Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD;
  1072. PortStatus = AhciReadReg (PciIo, Offset);
  1073. StartCmd = 0;
  1074. if ((PortStatus & EFI_AHCI_PORT_CMD_ALPE) != 0) {
  1075. StartCmd = AhciReadReg (PciIo, Offset);
  1076. StartCmd &= ~EFI_AHCI_PORT_CMD_ICC_MASK;
  1077. StartCmd |= EFI_AHCI_PORT_CMD_ACTIVE;
  1078. }
  1079. Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_TFD;
  1080. PortTfd = AhciReadReg (PciIo, Offset);
  1081. if ((PortTfd & (EFI_AHCI_PORT_TFD_BSY | EFI_AHCI_PORT_TFD_DRQ)) != 0) {
  1082. if ((Capability & BIT24) != 0) {
  1083. Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD;
  1084. AhciOrReg (PciIo, Offset, EFI_AHCI_PORT_CMD_CLO);
  1085. AhciWaitMmioSet (
  1086. PciIo,
  1087. Offset,
  1088. EFI_AHCI_PORT_CMD_CLO,
  1089. 0,
  1090. Timeout
  1091. );
  1092. }
  1093. }
  1094. Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD;
  1095. AhciOrReg (PciIo, Offset, EFI_AHCI_PORT_CMD_ST | StartCmd);
  1096. //
  1097. // Setting the command
  1098. //
  1099. Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CI;
  1100. AhciAndReg (PciIo, Offset, 0);
  1101. AhciOrReg (PciIo, Offset, CmdSlotBit);
  1102. return EFI_SUCCESS;
  1103. }
  1104. /**
  1105. Do AHCI HBA reset.
  1106. @param PciIo The PCI IO protocol instance.
  1107. @param Timeout The timeout value of reset, uses 100ns as a unit.
  1108. @retval EFI_DEVICE_ERROR AHCI controller is failed to complete hardware reset.
  1109. @retval EFI_TIMEOUT The reset operation is time out.
  1110. @retval EFI_SUCCESS AHCI controller is reset successfully.
  1111. **/
  1112. EFI_STATUS
  1113. EFIAPI
  1114. AhciReset (
  1115. IN EFI_PCI_IO_PROTOCOL *PciIo,
  1116. IN UINT64 Timeout
  1117. )
  1118. {
  1119. UINT64 Delay;
  1120. UINT32 Value;
  1121. //
  1122. // Make sure that GHC.AE bit is set before accessing any AHCI registers.
  1123. //
  1124. Value = AhciReadReg(PciIo, EFI_AHCI_GHC_OFFSET);
  1125. if ((Value & EFI_AHCI_GHC_ENABLE) == 0) {
  1126. AhciOrReg (PciIo, EFI_AHCI_GHC_OFFSET, EFI_AHCI_GHC_ENABLE);
  1127. }
  1128. AhciOrReg (PciIo, EFI_AHCI_GHC_OFFSET, EFI_AHCI_GHC_RESET);
  1129. Delay = DivU64x32(Timeout, 1000) + 1;
  1130. do {
  1131. Value = AhciReadReg(PciIo, EFI_AHCI_GHC_OFFSET);
  1132. if ((Value & EFI_AHCI_GHC_RESET) == 0) {
  1133. break;
  1134. }
  1135. //
  1136. // Stall for 100 microseconds.
  1137. //
  1138. MicroSecondDelay(100);
  1139. Delay--;
  1140. } while (Delay > 0);
  1141. if (Delay == 0) {
  1142. return EFI_TIMEOUT;
  1143. }
  1144. return EFI_SUCCESS;
  1145. }
  1146. /**
  1147. Send SMART Return Status command to check if the execution of SMART cmd is successful or not.
  1148. @param PciIo The PCI IO protocol instance.
  1149. @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
  1150. @param Port The number of port.
  1151. @param PortMultiplier The port multiplier port number.
  1152. @param AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.
  1153. @retval EFI_SUCCESS Successfully get the return status of S.M.A.R.T command execution.
  1154. @retval Others Fail to get return status data.
  1155. **/
  1156. EFI_STATUS
  1157. EFIAPI
  1158. AhciAtaSmartReturnStatusCheck (
  1159. IN EFI_PCI_IO_PROTOCOL *PciIo,
  1160. IN EFI_AHCI_REGISTERS *AhciRegisters,
  1161. IN UINT8 Port,
  1162. IN UINT8 PortMultiplier,
  1163. IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock
  1164. )
  1165. {
  1166. EFI_STATUS Status;
  1167. EFI_ATA_COMMAND_BLOCK AtaCommandBlock;
  1168. UINT8 LBAMid;
  1169. UINT8 LBAHigh;
  1170. UINTN FisBaseAddr;
  1171. UINT32 Value;
  1172. ZeroMem (&AtaCommandBlock, sizeof (EFI_ATA_COMMAND_BLOCK));
  1173. AtaCommandBlock.AtaCommand = ATA_CMD_SMART;
  1174. AtaCommandBlock.AtaFeatures = ATA_SMART_RETURN_STATUS;
  1175. AtaCommandBlock.AtaCylinderLow = ATA_CONSTANT_4F;
  1176. AtaCommandBlock.AtaCylinderHigh = ATA_CONSTANT_C2;
  1177. //
  1178. // Send S.M.A.R.T Read Return Status command to device
  1179. //
  1180. Status = AhciNonDataTransfer (
  1181. PciIo,
  1182. AhciRegisters,
  1183. (UINT8)Port,
  1184. (UINT8)PortMultiplier,
  1185. NULL,
  1186. 0,
  1187. &AtaCommandBlock,
  1188. AtaStatusBlock,
  1189. ATA_ATAPI_TIMEOUT,
  1190. NULL
  1191. );
  1192. if (EFI_ERROR (Status)) {
  1193. REPORT_STATUS_CODE (
  1194. EFI_ERROR_CODE | EFI_ERROR_MINOR,
  1195. (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_DISABLED)
  1196. );
  1197. return EFI_DEVICE_ERROR;
  1198. }
  1199. REPORT_STATUS_CODE (
  1200. EFI_PROGRESS_CODE,
  1201. (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_ENABLE)
  1202. );
  1203. FisBaseAddr = (UINTN)AhciRegisters->AhciRFis + Port * sizeof (EFI_AHCI_RECEIVED_FIS);
  1204. Value = *(UINT32 *) (FisBaseAddr + EFI_AHCI_D2H_FIS_OFFSET);
  1205. if ((Value & EFI_AHCI_FIS_TYPE_MASK) == EFI_AHCI_FIS_REGISTER_D2H) {
  1206. LBAMid = ((UINT8 *)(UINTN)(FisBaseAddr + EFI_AHCI_D2H_FIS_OFFSET))[5];
  1207. LBAHigh = ((UINT8 *)(UINTN)(FisBaseAddr + EFI_AHCI_D2H_FIS_OFFSET))[6];
  1208. if ((LBAMid == 0x4f) && (LBAHigh == 0xc2)) {
  1209. //
  1210. // The threshold exceeded condition is not detected by the device
  1211. //
  1212. DEBUG ((EFI_D_INFO, "The S.M.A.R.T threshold exceeded condition is not detected\n"));
  1213. REPORT_STATUS_CODE (
  1214. EFI_PROGRESS_CODE,
  1215. (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_UNDERTHRESHOLD)
  1216. );
  1217. } else if ((LBAMid == 0xf4) && (LBAHigh == 0x2c)) {
  1218. //
  1219. // The threshold exceeded condition is detected by the device
  1220. //
  1221. DEBUG ((EFI_D_INFO, "The S.M.A.R.T threshold exceeded condition is detected\n"));
  1222. REPORT_STATUS_CODE (
  1223. EFI_PROGRESS_CODE,
  1224. (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_OVERTHRESHOLD)
  1225. );
  1226. }
  1227. }
  1228. return EFI_SUCCESS;
  1229. }
  1230. /**
  1231. Enable SMART command of the disk if supported.
  1232. @param PciIo The PCI IO protocol instance.
  1233. @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
  1234. @param Port The number of port.
  1235. @param PortMultiplier The port multiplier port number.
  1236. @param IdentifyData A pointer to data buffer which is used to contain IDENTIFY data.
  1237. @param AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.
  1238. **/
  1239. VOID
  1240. EFIAPI
  1241. AhciAtaSmartSupport (
  1242. IN EFI_PCI_IO_PROTOCOL *PciIo,
  1243. IN EFI_AHCI_REGISTERS *AhciRegisters,
  1244. IN UINT8 Port,
  1245. IN UINT8 PortMultiplier,
  1246. IN EFI_IDENTIFY_DATA *IdentifyData,
  1247. IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock
  1248. )
  1249. {
  1250. EFI_STATUS Status;
  1251. EFI_ATA_COMMAND_BLOCK AtaCommandBlock;
  1252. //
  1253. // Detect if the device supports S.M.A.R.T.
  1254. //
  1255. if ((IdentifyData->AtaData.command_set_supported_82 & 0x0001) != 0x0001) {
  1256. //
  1257. // S.M.A.R.T is not supported by the device
  1258. //
  1259. DEBUG ((EFI_D_INFO, "S.M.A.R.T feature is not supported at port [%d] PortMultiplier [%d]!\n",
  1260. Port, PortMultiplier));
  1261. REPORT_STATUS_CODE (
  1262. EFI_ERROR_CODE | EFI_ERROR_MINOR,
  1263. (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_NOTSUPPORTED)
  1264. );
  1265. } else {
  1266. //
  1267. // Check if the feature is enabled. If not, then enable S.M.A.R.T.
  1268. //
  1269. if ((IdentifyData->AtaData.command_set_feature_enb_85 & 0x0001) != 0x0001) {
  1270. REPORT_STATUS_CODE (
  1271. EFI_PROGRESS_CODE,
  1272. (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_DISABLE)
  1273. );
  1274. ZeroMem (&AtaCommandBlock, sizeof (EFI_ATA_COMMAND_BLOCK));
  1275. AtaCommandBlock.AtaCommand = ATA_CMD_SMART;
  1276. AtaCommandBlock.AtaFeatures = ATA_SMART_ENABLE_OPERATION;
  1277. AtaCommandBlock.AtaCylinderLow = ATA_CONSTANT_4F;
  1278. AtaCommandBlock.AtaCylinderHigh = ATA_CONSTANT_C2;
  1279. //
  1280. // Send S.M.A.R.T Enable command to device
  1281. //
  1282. Status = AhciNonDataTransfer (
  1283. PciIo,
  1284. AhciRegisters,
  1285. (UINT8)Port,
  1286. (UINT8)PortMultiplier,
  1287. NULL,
  1288. 0,
  1289. &AtaCommandBlock,
  1290. AtaStatusBlock,
  1291. ATA_ATAPI_TIMEOUT,
  1292. NULL
  1293. );
  1294. if (!EFI_ERROR (Status)) {
  1295. //
  1296. // Send S.M.A.R.T AutoSave command to device
  1297. //
  1298. ZeroMem (&AtaCommandBlock, sizeof (EFI_ATA_COMMAND_BLOCK));
  1299. AtaCommandBlock.AtaCommand = ATA_CMD_SMART;
  1300. AtaCommandBlock.AtaFeatures = 0xD2;
  1301. AtaCommandBlock.AtaSectorCount = 0xF1;
  1302. AtaCommandBlock.AtaCylinderLow = ATA_CONSTANT_4F;
  1303. AtaCommandBlock.AtaCylinderHigh = ATA_CONSTANT_C2;
  1304. Status = AhciNonDataTransfer (
  1305. PciIo,
  1306. AhciRegisters,
  1307. (UINT8)Port,
  1308. (UINT8)PortMultiplier,
  1309. NULL,
  1310. 0,
  1311. &AtaCommandBlock,
  1312. AtaStatusBlock,
  1313. ATA_ATAPI_TIMEOUT,
  1314. NULL
  1315. );
  1316. if (!EFI_ERROR (Status)) {
  1317. Status = AhciAtaSmartReturnStatusCheck (
  1318. PciIo,
  1319. AhciRegisters,
  1320. (UINT8)Port,
  1321. (UINT8)PortMultiplier,
  1322. AtaStatusBlock
  1323. );
  1324. }
  1325. }
  1326. }
  1327. DEBUG ((EFI_D_INFO, "Enabled S.M.A.R.T feature at port [%d] PortMultiplier [%d]!\n",
  1328. Port, PortMultiplier));
  1329. }
  1330. return ;
  1331. }
  1332. /**
  1333. Send Buffer cmd to specific device.
  1334. @param PciIo The PCI IO protocol instance.
  1335. @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
  1336. @param Port The number of port.
  1337. @param PortMultiplier The port multiplier port number.
  1338. @param Buffer The data buffer to store IDENTIFY PACKET data.
  1339. @retval EFI_DEVICE_ERROR The cmd abort with error occurs.
  1340. @retval EFI_TIMEOUT The operation is time out.
  1341. @retval EFI_UNSUPPORTED The device is not ready for executing.
  1342. @retval EFI_SUCCESS The cmd executes successfully.
  1343. **/
  1344. EFI_STATUS
  1345. EFIAPI
  1346. AhciIdentify (
  1347. IN EFI_PCI_IO_PROTOCOL *PciIo,
  1348. IN EFI_AHCI_REGISTERS *AhciRegisters,
  1349. IN UINT8 Port,
  1350. IN UINT8 PortMultiplier,
  1351. IN OUT EFI_IDENTIFY_DATA *Buffer
  1352. )
  1353. {
  1354. EFI_STATUS Status;
  1355. EFI_ATA_COMMAND_BLOCK AtaCommandBlock;
  1356. EFI_ATA_STATUS_BLOCK AtaStatusBlock;
  1357. if (PciIo == NULL || AhciRegisters == NULL || Buffer == NULL) {
  1358. return EFI_INVALID_PARAMETER;
  1359. }
  1360. ZeroMem (&AtaCommandBlock, sizeof (EFI_ATA_COMMAND_BLOCK));
  1361. ZeroMem (&AtaStatusBlock, sizeof (EFI_ATA_STATUS_BLOCK));
  1362. AtaCommandBlock.AtaCommand = ATA_CMD_IDENTIFY_DRIVE;
  1363. AtaCommandBlock.AtaSectorCount = 1;
  1364. Status = AhciPioTransfer (
  1365. PciIo,
  1366. AhciRegisters,
  1367. Port,
  1368. PortMultiplier,
  1369. NULL,
  1370. 0,
  1371. TRUE,
  1372. &AtaCommandBlock,
  1373. &AtaStatusBlock,
  1374. Buffer,
  1375. sizeof (EFI_IDENTIFY_DATA),
  1376. ATA_ATAPI_TIMEOUT,
  1377. NULL
  1378. );
  1379. return Status;
  1380. }
  1381. /**
  1382. Send Buffer cmd to specific device.
  1383. @param PciIo The PCI IO protocol instance.
  1384. @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
  1385. @param Port The number of port.
  1386. @param PortMultiplier The port multiplier port number.
  1387. @param Buffer The data buffer to store IDENTIFY PACKET data.
  1388. @retval EFI_DEVICE_ERROR The cmd abort with error occurs.
  1389. @retval EFI_TIMEOUT The operation is time out.
  1390. @retval EFI_UNSUPPORTED The device is not ready for executing.
  1391. @retval EFI_SUCCESS The cmd executes successfully.
  1392. **/
  1393. EFI_STATUS
  1394. EFIAPI
  1395. AhciIdentifyPacket (
  1396. IN EFI_PCI_IO_PROTOCOL *PciIo,
  1397. IN EFI_AHCI_REGISTERS *AhciRegisters,
  1398. IN UINT8 Port,
  1399. IN UINT8 PortMultiplier,
  1400. IN OUT EFI_IDENTIFY_DATA *Buffer
  1401. )
  1402. {
  1403. EFI_STATUS Status;
  1404. EFI_ATA_COMMAND_BLOCK AtaCommandBlock;
  1405. EFI_ATA_STATUS_BLOCK AtaStatusBlock;
  1406. if (PciIo == NULL || AhciRegisters == NULL) {
  1407. return EFI_INVALID_PARAMETER;
  1408. }
  1409. ZeroMem (&AtaCommandBlock, sizeof (EFI_ATA_COMMAND_BLOCK));
  1410. ZeroMem (&AtaStatusBlock, sizeof (EFI_ATA_STATUS_BLOCK));
  1411. AtaCommandBlock.AtaCommand = ATA_CMD_IDENTIFY_DEVICE;
  1412. AtaCommandBlock.AtaSectorCount = 1;
  1413. Status = AhciPioTransfer (
  1414. PciIo,
  1415. AhciRegisters,
  1416. Port,
  1417. PortMultiplier,
  1418. NULL,
  1419. 0,
  1420. TRUE,
  1421. &AtaCommandBlock,
  1422. &AtaStatusBlock,
  1423. Buffer,
  1424. sizeof (EFI_IDENTIFY_DATA),
  1425. ATA_ATAPI_TIMEOUT,
  1426. NULL
  1427. );
  1428. return Status;
  1429. }
  1430. /**
  1431. Send SET FEATURE cmd on specific device.
  1432. @param PciIo The PCI IO protocol instance.
  1433. @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
  1434. @param Port The number of port.
  1435. @param PortMultiplier The port multiplier port number.
  1436. @param Feature The data to send Feature register.
  1437. @param FeatureSpecificData The specific data for SET FEATURE cmd.
  1438. @param Timeout The timeout value of SET FEATURE cmd, uses 100ns as a unit.
  1439. @retval EFI_DEVICE_ERROR The cmd abort with error occurs.
  1440. @retval EFI_TIMEOUT The operation is time out.
  1441. @retval EFI_UNSUPPORTED The device is not ready for executing.
  1442. @retval EFI_SUCCESS The cmd executes successfully.
  1443. **/
  1444. EFI_STATUS
  1445. EFIAPI
  1446. AhciDeviceSetFeature (
  1447. IN EFI_PCI_IO_PROTOCOL *PciIo,
  1448. IN EFI_AHCI_REGISTERS *AhciRegisters,
  1449. IN UINT8 Port,
  1450. IN UINT8 PortMultiplier,
  1451. IN UINT16 Feature,
  1452. IN UINT32 FeatureSpecificData,
  1453. IN UINT64 Timeout
  1454. )
  1455. {
  1456. EFI_STATUS Status;
  1457. EFI_ATA_COMMAND_BLOCK AtaCommandBlock;
  1458. EFI_ATA_STATUS_BLOCK AtaStatusBlock;
  1459. ZeroMem (&AtaCommandBlock, sizeof (EFI_ATA_COMMAND_BLOCK));
  1460. ZeroMem (&AtaStatusBlock, sizeof (EFI_ATA_STATUS_BLOCK));
  1461. AtaCommandBlock.AtaCommand = ATA_CMD_SET_FEATURES;
  1462. AtaCommandBlock.AtaFeatures = (UINT8) Feature;
  1463. AtaCommandBlock.AtaFeaturesExp = (UINT8) (Feature >> 8);
  1464. AtaCommandBlock.AtaSectorCount = (UINT8) FeatureSpecificData;
  1465. AtaCommandBlock.AtaSectorNumber = (UINT8) (FeatureSpecificData >> 8);
  1466. AtaCommandBlock.AtaCylinderLow = (UINT8) (FeatureSpecificData >> 16);
  1467. AtaCommandBlock.AtaCylinderHigh = (UINT8) (FeatureSpecificData >> 24);
  1468. Status = AhciNonDataTransfer (
  1469. PciIo,
  1470. AhciRegisters,
  1471. (UINT8)Port,
  1472. (UINT8)PortMultiplier,
  1473. NULL,
  1474. 0,
  1475. &AtaCommandBlock,
  1476. &AtaStatusBlock,
  1477. Timeout,
  1478. NULL
  1479. );
  1480. return Status;
  1481. }
  1482. /**
  1483. This function is used to send out ATAPI commands conforms to the Packet Command
  1484. with PIO Protocol.
  1485. @param PciIo The PCI IO protocol instance.
  1486. @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
  1487. @param Port The number of port.
  1488. @param PortMultiplier The number of port multiplier.
  1489. @param Packet A pointer to EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET structure.
  1490. @retval EFI_SUCCESS send out the ATAPI packet command successfully
  1491. and device sends data successfully.
  1492. @retval EFI_DEVICE_ERROR the device failed to send data.
  1493. **/
  1494. EFI_STATUS
  1495. EFIAPI
  1496. AhciPacketCommandExecute (
  1497. IN EFI_PCI_IO_PROTOCOL *PciIo,
  1498. IN EFI_AHCI_REGISTERS *AhciRegisters,
  1499. IN UINT8 Port,
  1500. IN UINT8 PortMultiplier,
  1501. IN EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet
  1502. )
  1503. {
  1504. EFI_STATUS Status;
  1505. VOID *Buffer;
  1506. UINT32 Length;
  1507. EFI_ATA_COMMAND_BLOCK AtaCommandBlock;
  1508. EFI_ATA_STATUS_BLOCK AtaStatusBlock;
  1509. BOOLEAN Read;
  1510. if (Packet == NULL || Packet->Cdb == NULL) {
  1511. return EFI_INVALID_PARAMETER;
  1512. }
  1513. ZeroMem (&AtaCommandBlock, sizeof (EFI_ATA_COMMAND_BLOCK));
  1514. ZeroMem (&AtaStatusBlock, sizeof (EFI_ATA_STATUS_BLOCK));
  1515. AtaCommandBlock.AtaCommand = ATA_CMD_PACKET;
  1516. //
  1517. // No OVL; No DMA
  1518. //
  1519. AtaCommandBlock.AtaFeatures = 0x00;
  1520. //
  1521. // set the transfersize to ATAPI_MAX_BYTE_COUNT to let the device
  1522. // determine how many data should be transferred.
  1523. //
  1524. AtaCommandBlock.AtaCylinderLow = (UINT8) (ATAPI_MAX_BYTE_COUNT & 0x00ff);
  1525. AtaCommandBlock.AtaCylinderHigh = (UINT8) (ATAPI_MAX_BYTE_COUNT >> 8);
  1526. if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ) {
  1527. Buffer = Packet->InDataBuffer;
  1528. Length = Packet->InTransferLength;
  1529. Read = TRUE;
  1530. } else {
  1531. Buffer = Packet->OutDataBuffer;
  1532. Length = Packet->OutTransferLength;
  1533. Read = FALSE;
  1534. }
  1535. if (Length == 0) {
  1536. Status = AhciNonDataTransfer (
  1537. PciIo,
  1538. AhciRegisters,
  1539. Port,
  1540. PortMultiplier,
  1541. Packet->Cdb,
  1542. Packet->CdbLength,
  1543. &AtaCommandBlock,
  1544. &AtaStatusBlock,
  1545. Packet->Timeout,
  1546. NULL
  1547. );
  1548. } else {
  1549. Status = AhciPioTransfer (
  1550. PciIo,
  1551. AhciRegisters,
  1552. Port,
  1553. PortMultiplier,
  1554. Packet->Cdb,
  1555. Packet->CdbLength,
  1556. Read,
  1557. &AtaCommandBlock,
  1558. &AtaStatusBlock,
  1559. Buffer,
  1560. Length,
  1561. Packet->Timeout,
  1562. NULL
  1563. );
  1564. }
  1565. return Status;
  1566. }
  1567. /**
  1568. Allocate transfer-related data struct which is used at AHCI mode.
  1569. @param PciIo The PCI IO protocol instance.
  1570. @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
  1571. **/
  1572. EFI_STATUS
  1573. EFIAPI
  1574. AhciCreateTransferDescriptor (
  1575. IN EFI_PCI_IO_PROTOCOL *PciIo,
  1576. IN OUT EFI_AHCI_REGISTERS *AhciRegisters
  1577. )
  1578. {
  1579. EFI_STATUS Status;
  1580. UINTN Bytes;
  1581. VOID *Buffer;
  1582. UINT32 Capability;
  1583. UINT32 PortImplementBitMap;
  1584. UINT8 MaxPortNumber;
  1585. UINT8 MaxCommandSlotNumber;
  1586. BOOLEAN Support64Bit;
  1587. UINT64 MaxReceiveFisSize;
  1588. UINT64 MaxCommandListSize;
  1589. UINT64 MaxCommandTableSize;
  1590. EFI_PHYSICAL_ADDRESS AhciRFisPciAddr;
  1591. EFI_PHYSICAL_ADDRESS AhciCmdListPciAddr;
  1592. EFI_PHYSICAL_ADDRESS AhciCommandTablePciAddr;
  1593. Buffer = NULL;
  1594. //
  1595. // Collect AHCI controller information
  1596. //
  1597. Capability = AhciReadReg(PciIo, EFI_AHCI_CAPABILITY_OFFSET);
  1598. //
  1599. // Get the number of command slots per port supported by this HBA.
  1600. //
  1601. MaxCommandSlotNumber = (UINT8) (((Capability & 0x1F00) >> 8) + 1);
  1602. Support64Bit = (BOOLEAN) (((Capability & BIT31) != 0) ? TRUE : FALSE);
  1603. PortImplementBitMap = AhciReadReg(PciIo, EFI_AHCI_PI_OFFSET);
  1604. //
  1605. // Get the highest bit of implemented ports which decides how many bytes are allocated for recived FIS.
  1606. //
  1607. MaxPortNumber = (UINT8)(UINTN)(HighBitSet32(PortImplementBitMap) + 1);
  1608. if (MaxPortNumber == 0) {
  1609. return EFI_DEVICE_ERROR;
  1610. }
  1611. MaxReceiveFisSize = MaxPortNumber * sizeof (EFI_AHCI_RECEIVED_FIS);
  1612. Status = PciIo->AllocateBuffer (
  1613. PciIo,
  1614. AllocateAnyPages,
  1615. EfiBootServicesData,
  1616. EFI_SIZE_TO_PAGES ((UINTN) MaxReceiveFisSize),
  1617. &Buffer,
  1618. 0
  1619. );
  1620. if (EFI_ERROR (Status)) {
  1621. return EFI_OUT_OF_RESOURCES;
  1622. }
  1623. ZeroMem (Buffer, (UINTN)MaxReceiveFisSize);
  1624. AhciRegisters->AhciRFis = Buffer;
  1625. AhciRegisters->MaxReceiveFisSize = MaxReceiveFisSize;
  1626. Bytes = (UINTN)MaxReceiveFisSize;
  1627. Status = PciIo->Map (
  1628. PciIo,
  1629. EfiPciIoOperationBusMasterCommonBuffer,
  1630. Buffer,
  1631. &Bytes,
  1632. &AhciRFisPciAddr,
  1633. &AhciRegisters->MapRFis
  1634. );
  1635. if (EFI_ERROR (Status) || (Bytes != MaxReceiveFisSize)) {
  1636. //
  1637. // Map error or unable to map the whole RFis buffer into a contiguous region.
  1638. //
  1639. Status = EFI_OUT_OF_RESOURCES;
  1640. goto Error6;
  1641. }
  1642. if ((!Support64Bit) && (AhciRFisPciAddr > 0x100000000ULL)) {
  1643. //
  1644. // The AHCI HBA doesn't support 64bit addressing, so should not get a >4G pci bus master address.
  1645. //
  1646. Status = EFI_DEVICE_ERROR;
  1647. goto Error5;
  1648. }
  1649. AhciRegisters->AhciRFisPciAddr = (EFI_AHCI_RECEIVED_FIS *)(UINTN)AhciRFisPciAddr;
  1650. //
  1651. // Allocate memory for command list
  1652. // Note that the implemenation is a single task model which only use a command list for all ports.
  1653. //
  1654. Buffer = NULL;
  1655. MaxCommandListSize = MaxCommandSlotNumber * sizeof (EFI_AHCI_COMMAND_LIST);
  1656. Status = PciIo->AllocateBuffer (
  1657. PciIo,
  1658. AllocateAnyPages,
  1659. EfiBootServicesData,
  1660. EFI_SIZE_TO_PAGES ((UINTN) MaxCommandListSize),
  1661. &Buffer,
  1662. 0
  1663. );
  1664. if (EFI_ERROR (Status)) {
  1665. //
  1666. // Free mapped resource.
  1667. //
  1668. Status = EFI_OUT_OF_RESOURCES;
  1669. goto Error5;
  1670. }
  1671. ZeroMem (Buffer, (UINTN)MaxCommandListSize);
  1672. AhciRegisters->AhciCmdList = Buffer;
  1673. AhciRegisters->MaxCommandListSize = MaxCommandListSize;
  1674. Bytes = (UINTN)MaxCommandListSize;
  1675. Status = PciIo->Map (
  1676. PciIo,
  1677. EfiPciIoOperationBusMasterCommonBuffer,
  1678. Buffer,
  1679. &Bytes,
  1680. &AhciCmdListPciAddr,
  1681. &AhciRegisters->MapCmdList
  1682. );
  1683. if (EFI_ERROR (Status) || (Bytes != MaxCommandListSize)) {
  1684. //
  1685. // Map error or unable to map the whole cmd list buffer into a contiguous region.
  1686. //
  1687. Status = EFI_OUT_OF_RESOURCES;
  1688. goto Error4;
  1689. }
  1690. if ((!Support64Bit) && (AhciCmdListPciAddr > 0x100000000ULL)) {
  1691. //
  1692. // The AHCI HBA doesn't support 64bit addressing, so should not get a >4G pci bus master address.
  1693. //
  1694. Status = EFI_DEVICE_ERROR;
  1695. goto Error3;
  1696. }
  1697. AhciRegisters->AhciCmdListPciAddr = (EFI_AHCI_COMMAND_LIST *)(UINTN)AhciCmdListPciAddr;
  1698. //
  1699. // Allocate memory for command table
  1700. // According to AHCI 1.3 spec, a PRD table can contain maximum 65535 entries.
  1701. //
  1702. Buffer = NULL;
  1703. MaxCommandTableSize = sizeof (EFI_AHCI_COMMAND_TABLE);
  1704. Status = PciIo->AllocateBuffer (
  1705. PciIo,
  1706. AllocateAnyPages,
  1707. EfiBootServicesData,
  1708. EFI_SIZE_TO_PAGES ((UINTN) MaxCommandTableSize),
  1709. &Buffer,
  1710. 0
  1711. );
  1712. if (EFI_ERROR (Status)) {
  1713. //
  1714. // Free mapped resource.
  1715. //
  1716. Status = EFI_OUT_OF_RESOURCES;
  1717. goto Error3;
  1718. }
  1719. ZeroMem (Buffer, (UINTN)MaxCommandTableSize);
  1720. AhciRegisters->AhciCommandTable = Buffer;
  1721. AhciRegisters->MaxCommandTableSize = MaxCommandTableSize;
  1722. Bytes = (UINTN)MaxCommandTableSize;
  1723. Status = PciIo->Map (
  1724. PciIo,
  1725. EfiPciIoOperationBusMasterCommonBuffer,
  1726. Buffer,
  1727. &Bytes,
  1728. &AhciCommandTablePciAddr,
  1729. &AhciRegisters->MapCommandTable
  1730. );
  1731. if (EFI_ERROR (Status) || (Bytes != MaxCommandTableSize)) {
  1732. //
  1733. // Map error or unable to map the whole cmd list buffer into a contiguous region.
  1734. //
  1735. Status = EFI_OUT_OF_RESOURCES;
  1736. goto Error2;
  1737. }
  1738. if ((!Support64Bit) && (AhciCommandTablePciAddr > 0x100000000ULL)) {
  1739. //
  1740. // The AHCI HBA doesn't support 64bit addressing, so should not get a >4G pci bus master address.
  1741. //
  1742. Status = EFI_DEVICE_ERROR;
  1743. goto Error1;
  1744. }
  1745. AhciRegisters->AhciCommandTablePciAddr = (EFI_AHCI_COMMAND_TABLE *)(UINTN)AhciCommandTablePciAddr;
  1746. return EFI_SUCCESS;
  1747. //
  1748. // Map error or unable to map the whole CmdList buffer into a contiguous region.
  1749. //
  1750. Error1:
  1751. PciIo->Unmap (
  1752. PciIo,
  1753. AhciRegisters->MapCommandTable
  1754. );
  1755. Error2:
  1756. PciIo->FreeBuffer (
  1757. PciIo,
  1758. EFI_SIZE_TO_PAGES ((UINTN) MaxCommandTableSize),
  1759. AhciRegisters->AhciCommandTable
  1760. );
  1761. Error3:
  1762. PciIo->Unmap (
  1763. PciIo,
  1764. AhciRegisters->MapCmdList
  1765. );
  1766. Error4:
  1767. PciIo->FreeBuffer (
  1768. PciIo,
  1769. EFI_SIZE_TO_PAGES ((UINTN) MaxCommandListSize),
  1770. AhciRegisters->AhciCmdList
  1771. );
  1772. Error5:
  1773. PciIo->Unmap (
  1774. PciIo,
  1775. AhciRegisters->MapRFis
  1776. );
  1777. Error6:
  1778. PciIo->FreeBuffer (
  1779. PciIo,
  1780. EFI_SIZE_TO_PAGES ((UINTN) MaxReceiveFisSize),
  1781. AhciRegisters->AhciRFis
  1782. );
  1783. return Status;
  1784. }
  1785. /**
  1786. Read logs from SATA device.
  1787. @param PciIo The PCI IO protocol instance.
  1788. @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
  1789. @param Port The number of port.
  1790. @param PortMultiplier The multiplier of port.
  1791. @param Buffer The data buffer to store SATA logs.
  1792. @param LogNumber The address of the log.
  1793. @param PageNumber The page number of the log.
  1794. @retval EFI_INVALID_PARAMETER PciIo, AhciRegisters or Buffer is NULL.
  1795. @retval others Return status of AhciPioTransfer().
  1796. **/
  1797. EFI_STATUS
  1798. AhciReadLogExt (
  1799. IN EFI_PCI_IO_PROTOCOL *PciIo,
  1800. IN EFI_AHCI_REGISTERS *AhciRegisters,
  1801. IN UINT8 Port,
  1802. IN UINT8 PortMultiplier,
  1803. IN OUT UINT8 *Buffer,
  1804. IN UINT8 LogNumber,
  1805. IN UINT8 PageNumber
  1806. )
  1807. {
  1808. EFI_ATA_COMMAND_BLOCK AtaCommandBlock;
  1809. EFI_ATA_STATUS_BLOCK AtaStatusBlock;
  1810. if (PciIo == NULL || AhciRegisters == NULL || Buffer == NULL) {
  1811. return EFI_INVALID_PARAMETER;
  1812. }
  1813. ///
  1814. /// Read log from device
  1815. ///
  1816. ZeroMem (&AtaCommandBlock, sizeof (EFI_ATA_COMMAND_BLOCK));
  1817. ZeroMem (&AtaStatusBlock, sizeof (EFI_ATA_STATUS_BLOCK));
  1818. ZeroMem (Buffer, 512);
  1819. AtaCommandBlock.AtaCommand = ATA_CMD_READ_LOG_EXT;
  1820. AtaCommandBlock.AtaSectorCount = 1;
  1821. AtaCommandBlock.AtaSectorNumber = LogNumber;
  1822. AtaCommandBlock.AtaCylinderLow = PageNumber;
  1823. return AhciPioTransfer (
  1824. PciIo,
  1825. AhciRegisters,
  1826. Port,
  1827. PortMultiplier,
  1828. NULL,
  1829. 0,
  1830. TRUE,
  1831. &AtaCommandBlock,
  1832. &AtaStatusBlock,
  1833. Buffer,
  1834. 512,
  1835. ATA_ATAPI_TIMEOUT,
  1836. NULL
  1837. );
  1838. }
  1839. /**
  1840. Enable DEVSLP of the disk if supported.
  1841. @param PciIo The PCI IO protocol instance.
  1842. @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
  1843. @param Port The number of port.
  1844. @param PortMultiplier The multiplier of port.
  1845. @param IdentifyData A pointer to data buffer which is used to contain IDENTIFY data.
  1846. @retval EFI_SUCCESS The DEVSLP is enabled per policy successfully.
  1847. @retval EFI_UNSUPPORTED The DEVSLP isn't supported by the controller/device and policy requires to enable it.
  1848. **/
  1849. EFI_STATUS
  1850. AhciEnableDevSlp (
  1851. IN EFI_PCI_IO_PROTOCOL *PciIo,
  1852. IN EFI_AHCI_REGISTERS *AhciRegisters,
  1853. IN UINT8 Port,
  1854. IN UINT8 PortMultiplier,
  1855. IN EFI_IDENTIFY_DATA *IdentifyData
  1856. )
  1857. {
  1858. EFI_STATUS Status;
  1859. UINT32 Offset;
  1860. UINT32 Capability2;
  1861. UINT8 LogData[512];
  1862. DEVSLP_TIMING_VARIABLES DevSlpTiming;
  1863. UINT32 PortCmd;
  1864. UINT32 PortDevSlp;
  1865. if (mAtaAtapiPolicy->DeviceSleepEnable != 1) {
  1866. return EFI_SUCCESS;
  1867. }
  1868. //
  1869. // Do not enable DevSlp if DevSlp is not supported.
  1870. //
  1871. Capability2 = AhciReadReg (PciIo, AHCI_CAPABILITY2_OFFSET);
  1872. DEBUG ((DEBUG_INFO, "AHCI CAPABILITY2 = %08x\n", Capability2));
  1873. if ((Capability2 & AHCI_CAP2_SDS) == 0) {
  1874. return EFI_UNSUPPORTED;
  1875. }
  1876. //
  1877. // Do not enable DevSlp if DevSlp is not present
  1878. // Do not enable DevSlp if Hot Plug or Mechanical Presence Switch is supported
  1879. //
  1880. Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH;
  1881. PortCmd = AhciReadReg (PciIo, Offset + EFI_AHCI_PORT_CMD);
  1882. PortDevSlp = AhciReadReg (PciIo, Offset + AHCI_PORT_DEVSLP);
  1883. DEBUG ((DEBUG_INFO, "Port CMD/DEVSLP = %08x / %08x\n", PortCmd, PortDevSlp));
  1884. if (((PortDevSlp & AHCI_PORT_DEVSLP_DSP) == 0) ||
  1885. ((PortCmd & (EFI_AHCI_PORT_CMD_HPCP | EFI_AHCI_PORT_CMD_MPSP)) != 0)
  1886. ) {
  1887. return EFI_UNSUPPORTED;
  1888. }
  1889. //
  1890. // Do not enable DevSlp if the device doesn't support DevSlp
  1891. //
  1892. DEBUG ((DEBUG_INFO, "IDENTIFY DEVICE: [77] = %04x, [78] = %04x, [79] = %04x\n",
  1893. IdentifyData->AtaData.reserved_77,
  1894. IdentifyData->AtaData.serial_ata_features_supported, IdentifyData->AtaData.serial_ata_features_enabled));
  1895. if ((IdentifyData->AtaData.serial_ata_features_supported & BIT8) == 0) {
  1896. DEBUG ((DEBUG_INFO, "DevSlp feature is not supported for device at port [%d] PortMultiplier [%d]!\n",
  1897. Port, PortMultiplier));
  1898. return EFI_UNSUPPORTED;
  1899. }
  1900. //
  1901. // Enable DevSlp when it is not enabled.
  1902. //
  1903. if ((IdentifyData->AtaData.serial_ata_features_enabled & BIT8) != 0) {
  1904. Status = AhciDeviceSetFeature (
  1905. PciIo, AhciRegisters, Port, 0, ATA_SUB_CMD_ENABLE_SATA_FEATURE, 0x09, ATA_ATAPI_TIMEOUT
  1906. );
  1907. DEBUG ((DEBUG_INFO, "DevSlp set feature for device at port [%d] PortMultiplier [%d] - %r\n",
  1908. Port, PortMultiplier, Status));
  1909. if (EFI_ERROR (Status)) {
  1910. return Status;
  1911. }
  1912. }
  1913. Status = AhciReadLogExt(PciIo, AhciRegisters, Port, PortMultiplier, LogData, 0x30, 0x08);
  1914. //
  1915. // Clear PxCMD.ST and PxDEVSLP.ADSE before updating PxDEVSLP.DITO and PxDEVSLP.MDAT.
  1916. //
  1917. AhciWriteReg (PciIo, Offset + EFI_AHCI_PORT_CMD, PortCmd & ~EFI_AHCI_PORT_CMD_ST);
  1918. PortDevSlp &= ~AHCI_PORT_DEVSLP_ADSE;
  1919. AhciWriteReg (PciIo, Offset + AHCI_PORT_DEVSLP, PortDevSlp);
  1920. //
  1921. // Set PxDEVSLP.DETO and PxDEVSLP.MDAT to 0.
  1922. //
  1923. PortDevSlp &= ~AHCI_PORT_DEVSLP_DETO_MASK;
  1924. PortDevSlp &= ~AHCI_PORT_DEVSLP_MDAT_MASK;
  1925. AhciWriteReg (PciIo, Offset + AHCI_PORT_DEVSLP, PortDevSlp);
  1926. DEBUG ((DEBUG_INFO, "Read Log Ext at port [%d] PortMultiplier [%d] - %r\n", Port, PortMultiplier, Status));
  1927. if (EFI_ERROR (Status)) {
  1928. //
  1929. // Assume DEVSLP TIMING VARIABLES is not supported if the Identify Device Data log (30h, 8) fails
  1930. //
  1931. ZeroMem (&DevSlpTiming, sizeof (DevSlpTiming));
  1932. } else {
  1933. CopyMem (&DevSlpTiming, &LogData[48], sizeof (DevSlpTiming));
  1934. DEBUG ((DEBUG_INFO, "DevSlpTiming: Supported(%d), Deto(%d), Madt(%d)\n",
  1935. DevSlpTiming.Supported, DevSlpTiming.Deto, DevSlpTiming.Madt));
  1936. }
  1937. //
  1938. // Use 20ms as default DETO when DEVSLP TIMING VARIABLES is not supported or the DETO is 0.
  1939. //
  1940. if ((DevSlpTiming.Supported == 0) || (DevSlpTiming.Deto == 0)) {
  1941. DevSlpTiming.Deto = 20;
  1942. }
  1943. //
  1944. // Use 10ms as default MADT when DEVSLP TIMING VARIABLES is not supported or the MADT is 0.
  1945. //
  1946. if ((DevSlpTiming.Supported == 0) || (DevSlpTiming.Madt == 0)) {
  1947. DevSlpTiming.Madt = 10;
  1948. }
  1949. PortDevSlp |= DevSlpTiming.Deto << 2;
  1950. PortDevSlp |= DevSlpTiming.Madt << 10;
  1951. AhciOrReg (PciIo, Offset + AHCI_PORT_DEVSLP, PortDevSlp);
  1952. if (mAtaAtapiPolicy->AggressiveDeviceSleepEnable == 1) {
  1953. if ((Capability2 & AHCI_CAP2_SADM) != 0) {
  1954. PortDevSlp &= ~AHCI_PORT_DEVSLP_DITO_MASK;
  1955. PortDevSlp |= (625 << 15);
  1956. AhciWriteReg (PciIo, Offset + AHCI_PORT_DEVSLP, PortDevSlp);
  1957. PortDevSlp |= AHCI_PORT_DEVSLP_ADSE;
  1958. AhciWriteReg (PciIo, Offset + AHCI_PORT_DEVSLP, PortDevSlp);
  1959. }
  1960. }
  1961. AhciWriteReg (PciIo, Offset + EFI_AHCI_PORT_CMD, PortCmd);
  1962. DEBUG ((DEBUG_INFO, "Enabled DevSlp feature at port [%d] PortMultiplier [%d], Port CMD/DEVSLP = %08x / %08x\n",
  1963. Port, PortMultiplier, PortCmd, PortDevSlp));
  1964. return EFI_SUCCESS;
  1965. }
  1966. /**
  1967. Spin-up disk if IDD was incomplete or PUIS feature is enabled
  1968. @param PciIo The PCI IO protocol instance.
  1969. @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
  1970. @param Port The number of port.
  1971. @param PortMultiplier The multiplier of port.
  1972. @param IdentifyData A pointer to data buffer which is used to contain IDENTIFY data.
  1973. **/
  1974. EFI_STATUS
  1975. AhciSpinUpDisk (
  1976. IN EFI_PCI_IO_PROTOCOL *PciIo,
  1977. IN EFI_AHCI_REGISTERS *AhciRegisters,
  1978. IN UINT8 Port,
  1979. IN UINT8 PortMultiplier,
  1980. IN OUT EFI_IDENTIFY_DATA *IdentifyData
  1981. )
  1982. {
  1983. EFI_STATUS Status;
  1984. EFI_ATA_COMMAND_BLOCK AtaCommandBlock;
  1985. EFI_ATA_STATUS_BLOCK AtaStatusBlock;
  1986. UINT8 Buffer[512];
  1987. if (IdentifyData->AtaData.specific_config == ATA_SPINUP_CFG_REQUIRED_IDD_INCOMPLETE) {
  1988. //
  1989. // Use SET_FEATURE subcommand to spin up the device.
  1990. //
  1991. Status = AhciDeviceSetFeature (
  1992. PciIo, AhciRegisters, Port, PortMultiplier,
  1993. ATA_SUB_CMD_PUIS_SET_DEVICE_SPINUP, 0x00, ATA_SPINUP_TIMEOUT
  1994. );
  1995. DEBUG ((DEBUG_INFO, "CMD_PUIS_SET_DEVICE_SPINUP for device at port [%d] PortMultiplier [%d] - %r!\n",
  1996. Port, PortMultiplier, Status));
  1997. if (EFI_ERROR (Status)) {
  1998. return Status;
  1999. }
  2000. } else {
  2001. ASSERT (IdentifyData->AtaData.specific_config == ATA_SPINUP_CFG_NOT_REQUIRED_IDD_INCOMPLETE);
  2002. //
  2003. // Use READ_SECTORS to spin up the device if SpinUp SET FEATURE subcommand is not supported
  2004. //
  2005. ZeroMem (&AtaCommandBlock, sizeof (EFI_ATA_COMMAND_BLOCK));
  2006. ZeroMem (&AtaStatusBlock, sizeof (EFI_ATA_STATUS_BLOCK));
  2007. //
  2008. // Perform READ SECTORS PIO Data-In command to Read LBA 0
  2009. //
  2010. AtaCommandBlock.AtaCommand = ATA_CMD_READ_SECTORS;
  2011. AtaCommandBlock.AtaSectorCount = 0x1;
  2012. Status = AhciPioTransfer (
  2013. PciIo,
  2014. AhciRegisters,
  2015. Port,
  2016. PortMultiplier,
  2017. NULL,
  2018. 0,
  2019. TRUE,
  2020. &AtaCommandBlock,
  2021. &AtaStatusBlock,
  2022. &Buffer,
  2023. sizeof (Buffer),
  2024. ATA_SPINUP_TIMEOUT,
  2025. NULL
  2026. );
  2027. DEBUG ((DEBUG_INFO, "Read LBA 0 for device at port [%d] PortMultiplier [%d] - %r!\n",
  2028. Port, PortMultiplier, Status));
  2029. if (EFI_ERROR (Status)) {
  2030. return Status;
  2031. }
  2032. }
  2033. //
  2034. // Read the complete IDENTIFY DEVICE data.
  2035. //
  2036. ZeroMem (IdentifyData, sizeof (*IdentifyData));
  2037. Status = AhciIdentify (PciIo, AhciRegisters, Port, PortMultiplier, IdentifyData);
  2038. if (EFI_ERROR (Status)) {
  2039. DEBUG ((DEBUG_ERROR, "Read IDD failed for device at port [%d] PortMultiplier [%d] - %r!\n",
  2040. Port, PortMultiplier, Status));
  2041. return Status;
  2042. }
  2043. DEBUG ((DEBUG_INFO, "IDENTIFY DEVICE: [0] = %016x, [2] = %016x, [83] = %016x, [86] = %016x\n",
  2044. IdentifyData->AtaData.config, IdentifyData->AtaData.specific_config,
  2045. IdentifyData->AtaData.command_set_supported_83, IdentifyData->AtaData.command_set_feature_enb_86));
  2046. //
  2047. // Check if IDD is incomplete
  2048. //
  2049. if ((IdentifyData->AtaData.config & BIT2) != 0) {
  2050. return EFI_DEVICE_ERROR;
  2051. }
  2052. return EFI_SUCCESS;
  2053. }
  2054. /**
  2055. Enable/disable/skip PUIS of the disk according to policy.
  2056. @param PciIo The PCI IO protocol instance.
  2057. @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
  2058. @param Port The number of port.
  2059. @param PortMultiplier The multiplier of port.
  2060. **/
  2061. EFI_STATUS
  2062. AhciPuisEnable (
  2063. IN EFI_PCI_IO_PROTOCOL *PciIo,
  2064. IN EFI_AHCI_REGISTERS *AhciRegisters,
  2065. IN UINT8 Port,
  2066. IN UINT8 PortMultiplier
  2067. )
  2068. {
  2069. EFI_STATUS Status;
  2070. Status = EFI_SUCCESS;
  2071. if (mAtaAtapiPolicy->PuisEnable == 0) {
  2072. Status = AhciDeviceSetFeature (PciIo, AhciRegisters, Port, PortMultiplier, ATA_SUB_CMD_DISABLE_PUIS, 0x00, ATA_ATAPI_TIMEOUT);
  2073. } else if (mAtaAtapiPolicy->PuisEnable == 1) {
  2074. Status = AhciDeviceSetFeature (PciIo, AhciRegisters, Port, PortMultiplier, ATA_SUB_CMD_ENABLE_PUIS, 0x00, ATA_ATAPI_TIMEOUT);
  2075. }
  2076. DEBUG ((DEBUG_INFO, "%a PUIS feature at port [%d] PortMultiplier [%d] - %r!\n",
  2077. (mAtaAtapiPolicy->PuisEnable == 0) ? "Disable" : (
  2078. (mAtaAtapiPolicy->PuisEnable == 1) ? "Enable" : "Skip"
  2079. ), Port, PortMultiplier, Status));
  2080. return Status;
  2081. }
  2082. /**
  2083. Initialize ATA host controller at AHCI mode.
  2084. The function is designed to initialize ATA host controller.
  2085. @param[in] Instance A pointer to the ATA_ATAPI_PASS_THRU_INSTANCE instance.
  2086. **/
  2087. EFI_STATUS
  2088. EFIAPI
  2089. AhciModeInitialization (
  2090. IN ATA_ATAPI_PASS_THRU_INSTANCE *Instance
  2091. )
  2092. {
  2093. EFI_STATUS Status;
  2094. EFI_PCI_IO_PROTOCOL *PciIo;
  2095. EFI_IDE_CONTROLLER_INIT_PROTOCOL *IdeInit;
  2096. UINT32 Capability;
  2097. UINT8 MaxPortNumber;
  2098. UINT32 PortImplementBitMap;
  2099. EFI_AHCI_REGISTERS *AhciRegisters;
  2100. UINT8 Port;
  2101. DATA_64 Data64;
  2102. UINT32 Offset;
  2103. UINT32 Data;
  2104. EFI_IDENTIFY_DATA Buffer;
  2105. EFI_ATA_DEVICE_TYPE DeviceType;
  2106. EFI_ATA_COLLECTIVE_MODE *SupportedModes;
  2107. EFI_ATA_TRANSFER_MODE TransferMode;
  2108. UINT32 PhyDetectDelay;
  2109. UINT32 Value;
  2110. if (Instance == NULL) {
  2111. return EFI_INVALID_PARAMETER;
  2112. }
  2113. PciIo = Instance->PciIo;
  2114. IdeInit = Instance->IdeControllerInit;
  2115. Status = AhciReset (PciIo, EFI_AHCI_BUS_RESET_TIMEOUT);
  2116. if (EFI_ERROR (Status)) {
  2117. return EFI_DEVICE_ERROR;
  2118. }
  2119. //
  2120. // Collect AHCI controller information
  2121. //
  2122. Capability = AhciReadReg (PciIo, EFI_AHCI_CAPABILITY_OFFSET);
  2123. //
  2124. // Make sure that GHC.AE bit is set before accessing any AHCI registers.
  2125. //
  2126. Value = AhciReadReg(PciIo, EFI_AHCI_GHC_OFFSET);
  2127. if ((Value & EFI_AHCI_GHC_ENABLE) == 0) {
  2128. AhciOrReg (PciIo, EFI_AHCI_GHC_OFFSET, EFI_AHCI_GHC_ENABLE);
  2129. }
  2130. //
  2131. // Enable 64-bit DMA support in the PCI layer if this controller
  2132. // supports it.
  2133. //
  2134. if ((Capability & EFI_AHCI_CAP_S64A) != 0) {
  2135. Status = PciIo->Attributes (
  2136. PciIo,
  2137. EfiPciIoAttributeOperationEnable,
  2138. EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE,
  2139. NULL
  2140. );
  2141. if (EFI_ERROR (Status)) {
  2142. DEBUG ((EFI_D_WARN,
  2143. "AhciModeInitialization: failed to enable 64-bit DMA on 64-bit capable controller (%r)\n",
  2144. Status));
  2145. }
  2146. }
  2147. //
  2148. // Get the number of command slots per port supported by this HBA.
  2149. //
  2150. MaxPortNumber = (UINT8) ((Capability & 0x1F) + 1);
  2151. //
  2152. // Get the bit map of those ports exposed by this HBA.
  2153. // It indicates which ports that the HBA supports are available for software to use.
  2154. //
  2155. PortImplementBitMap = AhciReadReg(PciIo, EFI_AHCI_PI_OFFSET);
  2156. AhciRegisters = &Instance->AhciRegisters;
  2157. Status = AhciCreateTransferDescriptor (PciIo, AhciRegisters);
  2158. if (EFI_ERROR (Status)) {
  2159. return EFI_OUT_OF_RESOURCES;
  2160. }
  2161. for (Port = 0; Port < EFI_AHCI_MAX_PORTS; Port ++) {
  2162. if ((PortImplementBitMap & (((UINT32)BIT0) << Port)) != 0) {
  2163. //
  2164. // According to AHCI spec, MaxPortNumber should be equal or greater than the number of implemented ports.
  2165. //
  2166. if ((MaxPortNumber--) == 0) {
  2167. //
  2168. // Should never be here.
  2169. //
  2170. ASSERT (FALSE);
  2171. return EFI_SUCCESS;
  2172. }
  2173. IdeInit->NotifyPhase (IdeInit, EfiIdeBeforeChannelEnumeration, Port);
  2174. //
  2175. // Initialize FIS Base Address Register and Command List Base Address Register for use.
  2176. //
  2177. Data64.Uint64 = (UINTN) (AhciRegisters->AhciRFisPciAddr) + sizeof (EFI_AHCI_RECEIVED_FIS) * Port;
  2178. Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_FB;
  2179. AhciWriteReg (PciIo, Offset, Data64.Uint32.Lower32);
  2180. Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_FBU;
  2181. AhciWriteReg (PciIo, Offset, Data64.Uint32.Upper32);
  2182. Data64.Uint64 = (UINTN) (AhciRegisters->AhciCmdListPciAddr);
  2183. Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CLB;
  2184. AhciWriteReg (PciIo, Offset, Data64.Uint32.Lower32);
  2185. Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CLBU;
  2186. AhciWriteReg (PciIo, Offset, Data64.Uint32.Upper32);
  2187. Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD;
  2188. Data = AhciReadReg (PciIo, Offset);
  2189. if ((Data & EFI_AHCI_PORT_CMD_CPD) != 0) {
  2190. AhciOrReg (PciIo, Offset, EFI_AHCI_PORT_CMD_POD);
  2191. }
  2192. if ((Capability & EFI_AHCI_CAP_SSS) != 0) {
  2193. AhciOrReg (PciIo, Offset, EFI_AHCI_PORT_CMD_SUD);
  2194. }
  2195. //
  2196. // Disable aggressive power management.
  2197. //
  2198. Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_SCTL;
  2199. AhciOrReg (PciIo, Offset, EFI_AHCI_PORT_SCTL_IPM_INIT);
  2200. //
  2201. // Disable the reporting of the corresponding interrupt to system software.
  2202. //
  2203. Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_IE;
  2204. AhciAndReg (PciIo, Offset, 0);
  2205. //
  2206. // Now inform the IDE Controller Init Module.
  2207. //
  2208. IdeInit->NotifyPhase (IdeInit, EfiIdeBusBeforeDevicePresenceDetection, Port);
  2209. //
  2210. // Enable FIS Receive DMA engine for the first D2H FIS.
  2211. //
  2212. Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD;
  2213. AhciOrReg (PciIo, Offset, EFI_AHCI_PORT_CMD_FRE);
  2214. //
  2215. // Wait for the Phy to detect the presence of a device.
  2216. //
  2217. PhyDetectDelay = EFI_AHCI_BUS_PHY_DETECT_TIMEOUT;
  2218. Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_SSTS;
  2219. do {
  2220. Data = AhciReadReg (PciIo, Offset) & EFI_AHCI_PORT_SSTS_DET_MASK;
  2221. if ((Data == EFI_AHCI_PORT_SSTS_DET_PCE) || (Data == EFI_AHCI_PORT_SSTS_DET)) {
  2222. break;
  2223. }
  2224. MicroSecondDelay (1000);
  2225. PhyDetectDelay--;
  2226. } while (PhyDetectDelay > 0);
  2227. if (PhyDetectDelay == 0) {
  2228. //
  2229. // No device detected at this port.
  2230. // Clear PxCMD.SUD for those ports at which there are no device present.
  2231. //
  2232. Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD;
  2233. AhciAndReg (PciIo, Offset, (UINT32) ~(EFI_AHCI_PORT_CMD_SUD));
  2234. continue;
  2235. }
  2236. //
  2237. // According to SATA1.0a spec section 5.2, we need to wait for PxTFD.BSY and PxTFD.DRQ
  2238. // and PxTFD.ERR to be zero. The maximum wait time is 16s which is defined at ATA spec.
  2239. //
  2240. PhyDetectDelay = 16 * 1000;
  2241. do {
  2242. Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_SERR;
  2243. if (AhciReadReg(PciIo, Offset) != 0) {
  2244. AhciWriteReg (PciIo, Offset, AhciReadReg(PciIo, Offset));
  2245. }
  2246. Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_TFD;
  2247. Data = AhciReadReg (PciIo, Offset) & EFI_AHCI_PORT_TFD_MASK;
  2248. if (Data == 0) {
  2249. break;
  2250. }
  2251. MicroSecondDelay (1000);
  2252. PhyDetectDelay--;
  2253. } while (PhyDetectDelay > 0);
  2254. if (PhyDetectDelay == 0) {
  2255. DEBUG ((EFI_D_ERROR, "Port %d Device presence detected but phy not ready (TFD=0x%X)\n", Port, Data));
  2256. continue;
  2257. }
  2258. //
  2259. // When the first D2H register FIS is received, the content of PxSIG register is updated.
  2260. //
  2261. Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_SIG;
  2262. Status = AhciWaitMmioSet (
  2263. PciIo,
  2264. Offset,
  2265. 0x0000FFFF,
  2266. 0x00000101,
  2267. EFI_TIMER_PERIOD_SECONDS(16)
  2268. );
  2269. if (EFI_ERROR (Status)) {
  2270. continue;
  2271. }
  2272. Data = AhciReadReg (PciIo, Offset);
  2273. if ((Data & EFI_AHCI_ATAPI_SIG_MASK) == EFI_AHCI_ATAPI_DEVICE_SIG) {
  2274. Status = AhciIdentifyPacket (PciIo, AhciRegisters, Port, 0, &Buffer);
  2275. if (EFI_ERROR (Status)) {
  2276. continue;
  2277. }
  2278. DeviceType = EfiIdeCdrom;
  2279. } else if ((Data & EFI_AHCI_ATAPI_SIG_MASK) == EFI_AHCI_ATA_DEVICE_SIG) {
  2280. Status = AhciIdentify (PciIo, AhciRegisters, Port, 0, &Buffer);
  2281. if (EFI_ERROR (Status)) {
  2282. REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_PERIPHERAL_FIXED_MEDIA | EFI_P_EC_NOT_DETECTED));
  2283. continue;
  2284. }
  2285. DEBUG ((
  2286. DEBUG_INFO, "IDENTIFY DEVICE: [0] = %016x, [2] = %016x, [83] = %016x, [86] = %016x\n",
  2287. Buffer.AtaData.config, Buffer.AtaData.specific_config,
  2288. Buffer.AtaData.command_set_supported_83, Buffer.AtaData.command_set_feature_enb_86
  2289. ));
  2290. if ((Buffer.AtaData.config & BIT2) != 0) {
  2291. //
  2292. // SpinUp disk if device reported incomplete IDENTIFY DEVICE.
  2293. //
  2294. Status = AhciSpinUpDisk (
  2295. PciIo,
  2296. AhciRegisters,
  2297. Port,
  2298. 0,
  2299. &Buffer
  2300. );
  2301. if (EFI_ERROR (Status)) {
  2302. DEBUG ((DEBUG_ERROR, "Spin up standby device failed - %r\n", Status));
  2303. continue;
  2304. }
  2305. }
  2306. DeviceType = EfiIdeHarddisk;
  2307. } else {
  2308. continue;
  2309. }
  2310. DEBUG ((EFI_D_INFO, "port [%d] port mulitplier [%d] has a [%a]\n",
  2311. Port, 0, DeviceType == EfiIdeCdrom ? "cdrom" : "harddisk"));
  2312. //
  2313. // If the device is a hard disk, then try to enable S.M.A.R.T feature
  2314. //
  2315. if ((DeviceType == EfiIdeHarddisk) && PcdGetBool (PcdAtaSmartEnable)) {
  2316. AhciAtaSmartSupport (
  2317. PciIo,
  2318. AhciRegisters,
  2319. Port,
  2320. 0,
  2321. &Buffer,
  2322. NULL
  2323. );
  2324. }
  2325. //
  2326. // Submit identify data to IDE controller init driver
  2327. //
  2328. IdeInit->SubmitData (IdeInit, Port, 0, &Buffer);
  2329. //
  2330. // Now start to config ide device parameter and transfer mode.
  2331. //
  2332. Status = IdeInit->CalculateMode (
  2333. IdeInit,
  2334. Port,
  2335. 0,
  2336. &SupportedModes
  2337. );
  2338. if (EFI_ERROR (Status)) {
  2339. DEBUG ((EFI_D_ERROR, "Calculate Mode Fail, Status = %r\n", Status));
  2340. continue;
  2341. }
  2342. //
  2343. // Set best supported PIO mode on this IDE device
  2344. //
  2345. if (SupportedModes->PioMode.Mode <= EfiAtaPioMode2) {
  2346. TransferMode.ModeCategory = EFI_ATA_MODE_DEFAULT_PIO;
  2347. } else {
  2348. TransferMode.ModeCategory = EFI_ATA_MODE_FLOW_PIO;
  2349. }
  2350. TransferMode.ModeNumber = (UINT8) (SupportedModes->PioMode.Mode);
  2351. //
  2352. // Set supported DMA mode on this IDE device. Note that UDMA & MDMA cann't
  2353. // be set together. Only one DMA mode can be set to a device. If setting
  2354. // DMA mode operation fails, we can continue moving on because we only use
  2355. // PIO mode at boot time. DMA modes are used by certain kind of OS booting
  2356. //
  2357. if (SupportedModes->UdmaMode.Valid) {
  2358. TransferMode.ModeCategory = EFI_ATA_MODE_UDMA;
  2359. TransferMode.ModeNumber = (UINT8) (SupportedModes->UdmaMode.Mode);
  2360. } else if (SupportedModes->MultiWordDmaMode.Valid) {
  2361. TransferMode.ModeCategory = EFI_ATA_MODE_MDMA;
  2362. TransferMode.ModeNumber = (UINT8) SupportedModes->MultiWordDmaMode.Mode;
  2363. }
  2364. Status = AhciDeviceSetFeature (PciIo, AhciRegisters, Port, 0, 0x03, (UINT32)(*(UINT8 *)&TransferMode), ATA_ATAPI_TIMEOUT);
  2365. if (EFI_ERROR (Status)) {
  2366. DEBUG ((EFI_D_ERROR, "Set transfer Mode Fail, Status = %r\n", Status));
  2367. continue;
  2368. }
  2369. //
  2370. // Found a ATA or ATAPI device, add it into the device list.
  2371. //
  2372. CreateNewDeviceInfo (Instance, Port, 0xFFFF, DeviceType, &Buffer);
  2373. if (DeviceType == EfiIdeHarddisk) {
  2374. REPORT_STATUS_CODE (EFI_PROGRESS_CODE, (EFI_PERIPHERAL_FIXED_MEDIA | EFI_P_PC_ENABLE));
  2375. AhciEnableDevSlp (
  2376. PciIo,
  2377. AhciRegisters,
  2378. Port,
  2379. 0,
  2380. &Buffer
  2381. );
  2382. }
  2383. //
  2384. // Enable/disable PUIS according to policy setting if PUIS is capable (Word[83].BIT5 is set).
  2385. //
  2386. if ((Buffer.AtaData.command_set_supported_83 & BIT5) != 0) {
  2387. Status = AhciPuisEnable (
  2388. PciIo,
  2389. AhciRegisters,
  2390. Port,
  2391. 0
  2392. );
  2393. if (EFI_ERROR (Status)) {
  2394. DEBUG ((DEBUG_ERROR, "PUIS enable/disable failed, Status = %r\n", Status));
  2395. continue;
  2396. }
  2397. }
  2398. }
  2399. }
  2400. return EFI_SUCCESS;
  2401. }