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