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