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