]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AhciMode.c
fix 32bit build warning
[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, 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 memory set to the test value.
137
138 @param PciIo The PCI IO protocol instance.
139 @param Offset The memory 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.
143
144 @retval EFI_DEVICE_ERROR The memory is not set.
145 @retval EFI_TIMEOUT The memory setting is time out.
146 @retval EFI_SUCCESS The memory is correct set.
147
148 **/
149 EFI_STATUS
150 EFIAPI
151 AhciWaitMemSet (
152 IN EFI_PCI_IO_PROTOCOL *PciIo,
153 IN UINT32 Offset,
154 IN UINT32 MaskValue,
155 IN UINT32 TestValue,
156 IN UINT64 Timeout
157 )
158 {
159 UINT32 Value;
160 UINT32 Delay;
161
162 Delay = (UINT32) (DivU64x32(Timeout, 1000) + 1);
163
164 do {
165 Value = AhciReadReg (PciIo, Offset) & MaskValue;
166
167 if (Value == TestValue) {
168 return EFI_SUCCESS;
169 }
170
171 //
172 // Stall for 100 microseconds.
173 //
174 MicroSecondDelay (100);
175
176 Delay--;
177
178 } while (Delay > 0);
179
180 if (Delay == 0) {
181 return EFI_TIMEOUT;
182 }
183
184 return EFI_DEVICE_ERROR;
185 }
186
187 /**
188 Check if the device is still on port. It also checks if the AHCI controller
189 supports the address and data count will be transfered.
190
191 @param PciIo The PCI IO protocol instance.
192 @param Port The number of port.
193
194 @retval EFI_SUCCESS The device is attached to port and the transfer data is
195 supported by AHCI controller.
196 @retval EFI_UNSUPPORTED The transfer address and count is not supported by AHCI
197 controller.
198 @retval EFI_NOT_READY The physical communication between AHCI controller and device
199 is not ready.
200
201 **/
202 EFI_STATUS
203 EFIAPI
204 AhciCheckDeviceStatus (
205 IN EFI_PCI_IO_PROTOCOL *PciIo,
206 IN UINT8 Port
207 )
208 {
209 UINT32 Data;
210 UINT32 Offset;
211
212 Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_SSTS;
213
214 Data = AhciReadReg (PciIo, Offset) & EFI_AHCI_PORT_SSTS_DET_MASK;
215
216 if (Data == EFI_AHCI_PORT_SSTS_DET_PCE) {
217 return EFI_SUCCESS;
218 }
219
220 return EFI_NOT_READY;
221 }
222
223 /**
224
225 Clear the port interrupt and error status. It will also clear
226 HBA interrupt status.
227
228 @param PciIo The PCI IO protocol instance.
229 @param Port The number of port.
230
231 **/
232 VOID
233 EFIAPI
234 AhciClearPortStatus (
235 IN EFI_PCI_IO_PROTOCOL *PciIo,
236 IN UINT8 Port
237 )
238 {
239 UINT32 Offset;
240
241 //
242 // Clear any error status
243 //
244 Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_SERR;
245 AhciWriteReg (PciIo, Offset, AhciReadReg (PciIo, Offset));
246
247 //
248 // Clear any port interrupt status
249 //
250 Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_IS;
251 AhciWriteReg (PciIo, Offset, AhciReadReg (PciIo, Offset));
252
253 //
254 // Clear any HBA interrupt status
255 //
256 AhciWriteReg (PciIo, EFI_AHCI_IS_OFFSET, AhciReadReg (PciIo, EFI_AHCI_IS_OFFSET));
257 }
258
259 /**
260 Enable the FIS running for giving port.
261
262 @param PciIo The PCI IO protocol instance.
263 @param Port The number of port.
264 @param Timeout The timeout value of enabling FIS.
265
266 @retval EFI_DEVICE_ERROR The FIS enable setting fails.
267 @retval EFI_TIMEOUT The FIS enable setting is time out.
268 @retval EFI_SUCCESS The FIS enable successfully.
269
270 **/
271 EFI_STATUS
272 EFIAPI
273 AhciEnableFisReceive (
274 IN EFI_PCI_IO_PROTOCOL *PciIo,
275 IN UINT8 Port,
276 IN UINT64 Timeout
277 )
278 {
279 UINT32 Offset;
280
281 Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD;
282 AhciOrReg (PciIo, Offset, EFI_AHCI_PORT_CMD_FRE);
283
284 return AhciWaitMemSet (
285 PciIo,
286 Offset,
287 EFI_AHCI_PORT_CMD_FR,
288 EFI_AHCI_PORT_CMD_FR,
289 Timeout
290 );
291 }
292
293 /**
294 Disable the FIS running for giving port.
295
296 @param PciIo The PCI IO protocol instance.
297 @param Port The number of port.
298 @param Timeout The timeout value of disabling FIS.
299
300 @retval EFI_DEVICE_ERROR The FIS disable setting fails.
301 @retval EFI_TIMEOUT The FIS disable setting is time out.
302 @retval EFI_UNSUPPORTED The port is in running state.
303 @retval EFI_SUCCESS The FIS disable successfully.
304
305 **/
306 EFI_STATUS
307 EFIAPI
308 AhciDisableFisReceive (
309 IN EFI_PCI_IO_PROTOCOL *PciIo,
310 IN UINT8 Port,
311 IN UINT64 Timeout
312 )
313 {
314 UINT32 Offset;
315 UINT32 Data;
316
317 Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD;
318 Data = AhciReadReg (PciIo, Offset);
319
320 //
321 // Before disabling Fis receive, the DMA engine of the port should NOT be in running status.
322 //
323 if ((Data & (EFI_AHCI_PORT_CMD_ST | EFI_AHCI_PORT_CMD_CR)) != 0) {
324 return EFI_UNSUPPORTED;
325 }
326
327 //
328 // Check if the Fis receive DMA engine for the port is running.
329 //
330 if ((Data & EFI_AHCI_PORT_CMD_FR) != EFI_AHCI_PORT_CMD_FR) {
331 return EFI_SUCCESS;
332 }
333
334 AhciAndReg (PciIo, Offset, (UINT32)~(EFI_AHCI_PORT_CMD_FRE));
335
336 return AhciWaitMemSet (
337 PciIo,
338 Offset,
339 EFI_AHCI_PORT_CMD_FR,
340 0,
341 Timeout
342 );
343 }
344
345
346
347 /**
348 Build the command list, command table and prepare the fis receiver.
349
350 @param PciIo The PCI IO protocol instance.
351 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
352 @param Port The number of port.
353 @param PortMultiplier The timeout value of stop.
354 @param CommandFis The control fis will be used for the transfer.
355 @param CommandList The command list will be used for the transfer.
356 @param AtapiCommand The atapi command will be used for the transfer.
357 @param AtapiCommandLength The length of the atapi command.
358 @param CommandSlotNumber The command slot will be used for the transfer.
359 @param DataPhysicalAddr The pointer to the data buffer pci bus master address.
360 @param DataLength The data count to be transferred.
361
362 **/
363 VOID
364 EFIAPI
365 AhciBuildCommand (
366 IN EFI_PCI_IO_PROTOCOL *PciIo,
367 IN EFI_AHCI_REGISTERS *AhciRegisters,
368 IN UINT8 Port,
369 IN UINT8 PortMultiplier,
370 IN EFI_AHCI_COMMAND_FIS *CommandFis,
371 IN EFI_AHCI_COMMAND_LIST *CommandList,
372 IN EFI_AHCI_ATAPI_COMMAND *AtapiCommand OPTIONAL,
373 IN UINT8 AtapiCommandLength,
374 IN UINT8 CommandSlotNumber,
375 IN OUT VOID *DataPhysicalAddr,
376 IN UINT64 DataLength
377 )
378 {
379 UINT64 BaseAddr;
380 UINT64 PrdtNumber;
381 UINT64 PrdtIndex;
382 UINTN RemainedData;
383 UINTN MemAddr;
384 DATA_64 Data64;
385 UINT32 Offset;
386
387 //
388 // Filling the PRDT
389 //
390 PrdtNumber = (DataLength + EFI_AHCI_MAX_DATA_PER_PRDT - 1) / EFI_AHCI_MAX_DATA_PER_PRDT;
391
392 //
393 // According to AHCI 1.3 spec, a PRDT entry can point to a maximum 4MB data block.
394 // It also limits that the maximum amount of the PRDT entry in the command table
395 // is 65535.
396 //
397 ASSERT (PrdtNumber <= 65535);
398
399 Data64.Uint64 = (UINTN) (AhciRegisters->AhciRFis) + sizeof (EFI_AHCI_RECEIVED_FIS) * Port;
400
401 BaseAddr = Data64.Uint64;
402
403 ZeroMem ((VOID *)((UINTN) BaseAddr), sizeof (EFI_AHCI_RECEIVED_FIS));
404
405 ZeroMem (AhciRegisters->AhciCommandTable, sizeof (EFI_AHCI_COMMAND_TABLE));
406
407 CommandFis->AhciCFisPmNum = PortMultiplier;
408
409 CopyMem (&AhciRegisters->AhciCommandTable->CommandFis, CommandFis, sizeof (EFI_AHCI_COMMAND_FIS));
410
411 Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD;
412 if (AtapiCommand != NULL) {
413 CopyMem (
414 &AhciRegisters->AhciCommandTable->AtapiCmd,
415 AtapiCommand,
416 AtapiCommandLength
417 );
418
419 CommandList->AhciCmdA = 1;
420 CommandList->AhciCmdP = 1;
421 CommandList->AhciCmdC = (DataLength == 0) ? 1 : 0;
422
423 AhciOrReg (PciIo, Offset, (EFI_AHCI_PORT_CMD_DLAE | EFI_AHCI_PORT_CMD_ATAPI));
424 } else {
425 AhciAndReg (PciIo, Offset, (UINT32)~(EFI_AHCI_PORT_CMD_DLAE | EFI_AHCI_PORT_CMD_ATAPI));
426 }
427
428 RemainedData = (UINTN) DataLength;
429 MemAddr = (UINTN) DataPhysicalAddr;
430 CommandList->AhciCmdPrdtl = (UINT32)PrdtNumber;
431
432 for (PrdtIndex = 0; PrdtIndex < PrdtNumber; PrdtIndex++) {
433 if (RemainedData < EFI_AHCI_MAX_DATA_PER_PRDT) {
434 AhciRegisters->AhciCommandTable->PrdtTable[PrdtIndex].AhciPrdtDbc = (UINT32)RemainedData - 1;
435 } else {
436 AhciRegisters->AhciCommandTable->PrdtTable[PrdtIndex].AhciPrdtDbc = EFI_AHCI_MAX_DATA_PER_PRDT - 1;
437 }
438
439 Data64.Uint64 = (UINT64)MemAddr;
440 AhciRegisters->AhciCommandTable->PrdtTable[PrdtIndex].AhciPrdtDba = Data64.Uint32.Lower32;
441 AhciRegisters->AhciCommandTable->PrdtTable[PrdtIndex].AhciPrdtDbau = Data64.Uint32.Upper32;
442 RemainedData -= EFI_AHCI_MAX_DATA_PER_PRDT;
443 MemAddr += EFI_AHCI_MAX_DATA_PER_PRDT;
444 }
445
446 //
447 // Set the last PRDT to Interrupt On Complete
448 //
449 if (PrdtNumber > 0) {
450 AhciRegisters->AhciCommandTable->PrdtTable[PrdtNumber - 1].AhciPrdtIoc = 1;
451 }
452
453 CopyMem (
454 (VOID *) ((UINTN) AhciRegisters->AhciCmdList + (UINTN) CommandSlotNumber * sizeof (EFI_AHCI_COMMAND_LIST)),
455 CommandList,
456 sizeof (EFI_AHCI_COMMAND_LIST)
457 );
458
459 Data64.Uint64 = (UINT64)(UINTN) AhciRegisters->AhciCommandTablePciAddr;
460 AhciRegisters->AhciCmdList[CommandSlotNumber].AhciCmdCtba = Data64.Uint32.Lower32;
461 AhciRegisters->AhciCmdList[CommandSlotNumber].AhciCmdCtbau = Data64.Uint32.Upper32;
462 AhciRegisters->AhciCmdList[CommandSlotNumber].AhciCmdPmp = PortMultiplier;
463
464 }
465
466 /**
467 Buid a command FIS.
468
469 @param CmdFis A pointer to the EFI_AHCI_COMMAND_FIS data structure.
470 @param AtaCommandBlock A pointer to the AhciBuildCommandFis data structure.
471
472 **/
473 VOID
474 EFIAPI
475 AhciBuildCommandFis (
476 IN OUT EFI_AHCI_COMMAND_FIS *CmdFis,
477 IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock
478 )
479 {
480 ZeroMem (CmdFis, sizeof (EFI_AHCI_COMMAND_FIS));
481
482 CmdFis->AhciCFisType = EFI_AHCI_FIS_REGISTER_H2D;
483 //
484 // Indicator it's a command
485 //
486 CmdFis->AhciCFisCmdInd = 0x1;
487 CmdFis->AhciCFisCmd = AtaCommandBlock->AtaCommand;
488
489 CmdFis->AhciCFisFeature = AtaCommandBlock->AtaFeatures;
490 CmdFis->AhciCFisFeatureExp = AtaCommandBlock->AtaFeaturesExp;
491
492 CmdFis->AhciCFisSecNum = AtaCommandBlock->AtaSectorNumber;
493 CmdFis->AhciCFisSecNumExp = AtaCommandBlock->AtaSectorNumberExp;
494
495 CmdFis->AhciCFisClyLow = AtaCommandBlock->AtaCylinderLow;
496 CmdFis->AhciCFisClyLowExp = AtaCommandBlock->AtaCylinderLowExp;
497
498 CmdFis->AhciCFisClyHigh = AtaCommandBlock->AtaCylinderHigh;
499 CmdFis->AhciCFisClyHighExp = AtaCommandBlock->AtaCylinderHighExp;
500
501 CmdFis->AhciCFisSecCount = AtaCommandBlock->AtaSectorCount;
502 CmdFis->AhciCFisSecCountExp = AtaCommandBlock->AtaSectorCountExp;
503
504 CmdFis->AhciCFisDevHead = (UINT8) (AtaCommandBlock->AtaDeviceHead | 0xE0);
505 }
506
507 /**
508 Start a PIO data transfer on specific port.
509
510 @param PciIo The PCI IO protocol instance.
511 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
512 @param Port The number of port.
513 @param PortMultiplier The timeout value of stop.
514 @param AtapiCommand The atapi command will be used for the transfer.
515 @param AtapiCommandLength The length of the atapi command.
516 @param Read The transfer direction.
517 @param AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.
518 @param AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.
519 @param MemoryAddr The pointer to the data buffer.
520 @param DataCount The data count to be transferred.
521 @param Timeout The timeout value of non data transfer.
522
523 @retval EFI_DEVICE_ERROR The PIO data transfer abort with error occurs.
524 @retval EFI_TIMEOUT The operation is time out.
525 @retval EFI_UNSUPPORTED The device is not ready for transfer.
526 @retval EFI_SUCCESS The PIO data transfer executes successfully.
527
528 **/
529 EFI_STATUS
530 EFIAPI
531 AhciPioTransfer (
532 IN EFI_PCI_IO_PROTOCOL *PciIo,
533 IN EFI_AHCI_REGISTERS *AhciRegisters,
534 IN UINT8 Port,
535 IN UINT8 PortMultiplier,
536 IN EFI_AHCI_ATAPI_COMMAND *AtapiCommand OPTIONAL,
537 IN UINT8 AtapiCommandLength,
538 IN BOOLEAN Read,
539 IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock,
540 IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock,
541 IN OUT VOID *MemoryAddr,
542 IN UINT32 DataCount,
543 IN UINT64 Timeout
544 )
545 {
546 EFI_STATUS Status;
547 UINTN FisBaseAddr;
548 UINT32 Offset;
549 UINT32 Value;
550 EFI_PHYSICAL_ADDRESS PhyAddr;
551 VOID *Map;
552 UINTN MapLength;
553 EFI_PCI_IO_PROTOCOL_OPERATION Flag;
554 UINT32 Delay;
555 EFI_AHCI_COMMAND_FIS CFis;
556 EFI_AHCI_COMMAND_LIST CmdList;
557
558 if (Read) {
559 Flag = EfiPciIoOperationBusMasterWrite;
560 } else {
561 Flag = EfiPciIoOperationBusMasterRead;
562 }
563
564 //
565 // construct command list and command table with pci bus address
566 //
567 MapLength = DataCount;
568 Status = PciIo->Map (
569 PciIo,
570 Flag,
571 MemoryAddr,
572 &MapLength,
573 &PhyAddr,
574 &Map
575 );
576
577 if (EFI_ERROR (Status) || (DataCount != MapLength)) {
578 return EFI_OUT_OF_RESOURCES;
579 }
580
581 //
582 // Package read needed
583 //
584 AhciBuildCommandFis (&CFis, AtaCommandBlock);
585
586 ZeroMem (&CmdList, sizeof (EFI_AHCI_COMMAND_LIST));
587
588 CmdList.AhciCmdCfl = EFI_AHCI_FIS_REGISTER_H2D_LENGTH / 4;
589 CmdList.AhciCmdW = Read ? 0 : 1;
590
591 AhciBuildCommand (
592 PciIo,
593 AhciRegisters,
594 Port,
595 PortMultiplier,
596 &CFis,
597 &CmdList,
598 AtapiCommand,
599 AtapiCommandLength,
600 0,
601 (VOID *)(UINTN)PhyAddr,
602 DataCount
603 );
604
605 Status = AhciStartCommand (
606 PciIo,
607 Port,
608 0,
609 Timeout
610 );
611 if (EFI_ERROR (Status)) {
612 goto Exit;
613 }
614
615 //
616 // Checking the status and wait the driver sending data
617 //
618 FisBaseAddr = (UINTN)AhciRegisters->AhciRFis + Port * sizeof (EFI_AHCI_RECEIVED_FIS);
619 //
620 // Wait device sends the PIO setup fis before data transfer
621 //
622 Delay = (UINT32) (DivU64x32(Timeout, 1000) + 1);
623 do {
624 Value = *(UINT32 *) (FisBaseAddr + EFI_AHCI_PIO_FIS_OFFSET);
625
626 if ((Value & EFI_AHCI_FIS_TYPE_MASK) == EFI_AHCI_FIS_PIO_SETUP) {
627 break;
628 }
629
630 //
631 // Stall for 100 microseconds.
632 //
633 MicroSecondDelay(100);
634
635 Delay--;
636 } while (Delay > 0);
637
638 if (Delay == 0) {
639 Status = EFI_TIMEOUT;
640 goto Exit;
641 }
642
643 //
644 // Wait for command compelte
645 //
646 Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CI;
647 Status = AhciWaitMemSet (
648 PciIo,
649 Offset,
650 0xFFFFFFFF,
651 0,
652 Timeout
653 );
654
655 if (EFI_ERROR (Status)) {
656 goto Exit;
657 }
658
659 Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_IS;
660 Status = AhciWaitMemSet (
661 PciIo,
662 Offset,
663 EFI_AHCI_PORT_IS_PSS,
664 EFI_AHCI_PORT_IS_PSS,
665 Timeout
666 );
667 if (EFI_ERROR (Status)) {
668 goto Exit;
669 }
670
671 Exit:
672 AhciStopCommand (
673 PciIo,
674 Port,
675 Timeout
676 );
677
678 AhciDisableFisReceive (
679 PciIo,
680 Port,
681 Timeout
682 );
683
684 PciIo->Unmap (
685 PciIo,
686 Map
687 );
688
689 return Status;
690 }
691
692 /**
693 Start a DMA data transfer on specific port
694
695 @param PciIo The PCI IO protocol instance.
696 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
697 @param Port The number of port.
698 @param PortMultiplier The timeout value of stop.
699 @param AtapiCommand The atapi command will be used for the transfer.
700 @param AtapiCommandLength The length of the atapi command.
701 @param Read The transfer direction.
702 @param AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.
703 @param AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.
704 @param MemoryAddr The pointer to the data buffer.
705 @param DataCount The data count to be transferred.
706 @param Timeout The timeout value of non data transfer.
707
708 @retval EFI_DEVICE_ERROR The DMA data transfer abort with error occurs.
709 @retval EFI_TIMEOUT The operation is time out.
710 @retval EFI_UNSUPPORTED The device is not ready for transfer.
711 @retval EFI_SUCCESS The DMA data transfer executes successfully.
712
713 **/
714 EFI_STATUS
715 EFIAPI
716 AhciDmaTransfer (
717 IN EFI_PCI_IO_PROTOCOL *PciIo,
718 IN EFI_AHCI_REGISTERS *AhciRegisters,
719 IN UINT8 Port,
720 IN UINT8 PortMultiplier,
721 IN EFI_AHCI_ATAPI_COMMAND *AtapiCommand OPTIONAL,
722 IN UINT8 AtapiCommandLength,
723 IN BOOLEAN Read,
724 IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock,
725 IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock,
726 IN OUT VOID *MemoryAddr,
727 IN UINTN DataCount,
728 IN UINT64 Timeout
729 )
730 {
731 EFI_STATUS Status;
732 UINT32 Offset;
733 EFI_PHYSICAL_ADDRESS PhyAddr;
734 VOID *Map;
735 UINTN MapLength;
736 EFI_PCI_IO_PROTOCOL_OPERATION Flag;
737 EFI_AHCI_COMMAND_FIS CFis;
738 EFI_AHCI_COMMAND_LIST CmdList;
739
740 if (Read) {
741 Flag = EfiPciIoOperationBusMasterWrite;
742 } else {
743 Flag = EfiPciIoOperationBusMasterRead;
744 }
745
746 //
747 // construct command list and command table with pci bus address
748 //
749 MapLength = DataCount;
750 Status = PciIo->Map (
751 PciIo,
752 Flag,
753 MemoryAddr,
754 &MapLength,
755 &PhyAddr,
756 &Map
757 );
758
759 if (EFI_ERROR (Status) || (DataCount != MapLength)) {
760 return EFI_OUT_OF_RESOURCES;
761 }
762
763 //
764 // Package read needed
765 //
766 AhciBuildCommandFis (&CFis, AtaCommandBlock);
767
768 ZeroMem (&CmdList, sizeof (EFI_AHCI_COMMAND_LIST));
769
770 CmdList.AhciCmdCfl = EFI_AHCI_FIS_REGISTER_H2D_LENGTH / 4;
771 CmdList.AhciCmdW = Read ? 0 : 1;
772
773 AhciBuildCommand (
774 PciIo,
775 AhciRegisters,
776 Port,
777 PortMultiplier,
778 &CFis,
779 &CmdList,
780 AtapiCommand,
781 AtapiCommandLength,
782 0,
783 (VOID *)(UINTN)PhyAddr,
784 DataCount
785 );
786
787 Status = AhciStartCommand (
788 PciIo,
789 Port,
790 0,
791 Timeout
792 );
793 if (EFI_ERROR (Status)) {
794 goto Exit;
795 }
796
797 //
798 // Wait device PRD processed
799 //
800 Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_IS;
801 Status = AhciWaitMemSet (
802 PciIo,
803 Offset,
804 EFI_AHCI_PORT_IS_DPS,
805 EFI_AHCI_PORT_IS_DPS,
806 Timeout
807 );
808
809 if (EFI_ERROR (Status)) {
810 goto Exit;
811 }
812
813 //
814 // Wait for command compelte
815 //
816 Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CI;
817 Status = AhciWaitMemSet (
818 PciIo,
819 Offset,
820 0xFFFFFFFF,
821 0,
822 Timeout
823 );
824 if (EFI_ERROR (Status)) {
825 goto Exit;
826 }
827
828 Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_IS;
829 Status = AhciWaitMemSet (
830 PciIo,
831 Offset,
832 EFI_AHCI_PORT_IS_DHRS,
833 EFI_AHCI_PORT_IS_DHRS,
834 Timeout
835 );
836 if (EFI_ERROR (Status)) {
837 goto Exit;
838 }
839
840 Exit:
841 AhciStopCommand (
842 PciIo,
843 Port,
844 Timeout
845 );
846
847 AhciDisableFisReceive (
848 PciIo,
849 Port,
850 Timeout
851 );
852
853 PciIo->Unmap (
854 PciIo,
855 Map
856 );
857
858 return Status;
859 }
860
861 /**
862 Start a non data transfer on specific port.
863
864 @param PciIo The PCI IO protocol instance.
865 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
866 @param Port The number of port.
867 @param PortMultiplier The timeout value of stop.
868 @param AtapiCommand The atapi command will be used for the transfer.
869 @param AtapiCommandLength The length of the atapi command.
870 @param AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.
871 @param AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.
872 @param Timeout The timeout value of non data transfer.
873
874 @retval EFI_DEVICE_ERROR The non data transfer abort with error occurs.
875 @retval EFI_TIMEOUT The operation is time out.
876 @retval EFI_UNSUPPORTED The device is not ready for transfer.
877 @retval EFI_SUCCESS The non data transfer executes successfully.
878
879 **/
880 EFI_STATUS
881 EFIAPI
882 AhciNonDataTransfer (
883 IN EFI_PCI_IO_PROTOCOL *PciIo,
884 IN EFI_AHCI_REGISTERS *AhciRegisters,
885 IN UINT8 Port,
886 IN UINT8 PortMultiplier,
887 IN EFI_AHCI_ATAPI_COMMAND *AtapiCommand OPTIONAL,
888 IN UINT8 AtapiCommandLength,
889 IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock,
890 IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock,
891 IN UINT64 Timeout
892 )
893 {
894 EFI_STATUS Status;
895 UINTN FisBaseAddr;
896 UINT32 Offset;
897 UINT32 Value;
898 UINT32 Delay;
899
900 EFI_AHCI_COMMAND_FIS CFis;
901 EFI_AHCI_COMMAND_LIST CmdList;
902
903 //
904 // Package read needed
905 //
906 AhciBuildCommandFis (&CFis, AtaCommandBlock);
907
908 ZeroMem (&CmdList, sizeof (EFI_AHCI_COMMAND_LIST));
909
910 CmdList.AhciCmdCfl = EFI_AHCI_FIS_REGISTER_H2D_LENGTH / 4;
911
912 AhciBuildCommand (
913 PciIo,
914 AhciRegisters,
915 Port,
916 PortMultiplier,
917 &CFis,
918 &CmdList,
919 AtapiCommand,
920 AtapiCommandLength,
921 0,
922 NULL,
923 0
924 );
925
926 Status = AhciStartCommand (
927 PciIo,
928 Port,
929 0,
930 Timeout
931 );
932 if (EFI_ERROR (Status)) {
933 goto Exit;
934 }
935
936 //
937 // Wait device sends the Response Fis
938 //
939 FisBaseAddr = (UINTN)AhciRegisters->AhciRFis + Port * sizeof (EFI_AHCI_RECEIVED_FIS);
940 //
941 // Wait device sends the PIO setup fis before data transfer
942 //
943 Delay = (UINT32) (DivU64x32(Timeout, 1000) + 1);
944 do {
945 Value = *(UINT32 *) (FisBaseAddr + EFI_AHCI_D2H_FIS_OFFSET);
946
947 if ((Value & EFI_AHCI_FIS_TYPE_MASK) == EFI_AHCI_FIS_REGISTER_D2H) {
948 break;
949 }
950
951 //
952 // Stall for 100 microseconds.
953 //
954 MicroSecondDelay(100);
955
956 Delay --;
957 } while (Delay > 0);
958
959 if (Delay == 0) {
960 Status = EFI_TIMEOUT;
961 goto Exit;
962 }
963
964 Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CI;
965
966 Status = AhciWaitMemSet (
967 PciIo,
968 Offset,
969 0xFFFFFFFF,
970 0,
971 Timeout
972 );
973
974 Exit:
975 AhciStopCommand (
976 PciIo,
977 Port,
978 Timeout
979 );
980
981 AhciDisableFisReceive (
982 PciIo,
983 Port,
984 Timeout
985 );
986
987 return Status;
988 }
989
990 /**
991 Stop command running for giving port
992
993 @param PciIo The PCI IO protocol instance.
994 @param Port The number of port.
995 @param Timeout The timeout value of stop.
996
997 @retval EFI_DEVICE_ERROR The command stop unsuccessfully.
998 @retval EFI_TIMEOUT The operation is time out.
999 @retval EFI_SUCCESS The command stop successfully.
1000
1001 **/
1002 EFI_STATUS
1003 EFIAPI
1004 AhciStopCommand (
1005 IN EFI_PCI_IO_PROTOCOL *PciIo,
1006 IN UINT8 Port,
1007 IN UINT64 Timeout
1008 )
1009 {
1010 UINT32 Offset;
1011 UINT32 Data;
1012
1013 Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD;
1014 Data = AhciReadReg (PciIo, Offset);
1015
1016 if ((Data & (EFI_AHCI_PORT_CMD_ST | EFI_AHCI_PORT_CMD_CR)) == 0) {
1017 return EFI_SUCCESS;
1018 }
1019
1020 if ((Data & EFI_AHCI_PORT_CMD_ST) != 0) {
1021 AhciAndReg (PciIo, Offset, (UINT32)~(EFI_AHCI_PORT_CMD_ST));
1022 }
1023
1024 return AhciWaitMemSet (
1025 PciIo,
1026 Offset,
1027 EFI_AHCI_PORT_CMD_CR,
1028 0,
1029 Timeout
1030 );
1031 }
1032
1033 /**
1034 Start command for give slot on specific port.
1035
1036 @param PciIo The PCI IO protocol instance.
1037 @param Port The number of port.
1038 @param CommandSlot The number of CommandSlot.
1039 @param Timeout The timeout value of start.
1040
1041 @retval EFI_DEVICE_ERROR The command start unsuccessfully.
1042 @retval EFI_TIMEOUT The operation is time out.
1043 @retval EFI_SUCCESS The command start successfully.
1044
1045 **/
1046 EFI_STATUS
1047 EFIAPI
1048 AhciStartCommand (
1049 IN EFI_PCI_IO_PROTOCOL *PciIo,
1050 IN UINT8 Port,
1051 IN UINT8 CommandSlot,
1052 IN UINT64 Timeout
1053 )
1054 {
1055 UINT32 CmdSlotBit;
1056 EFI_STATUS Status;
1057 UINT32 PortStatus;
1058 UINT32 StartCmd;
1059 UINT32 PortTfd;
1060 UINT32 Offset;
1061 UINT32 Capability;
1062
1063 //
1064 // Collect AHCI controller information
1065 //
1066 Capability = AhciReadReg(PciIo, EFI_AHCI_CAPABILITY_OFFSET);
1067
1068 CmdSlotBit = (UINT32) (1 << CommandSlot);
1069
1070 AhciClearPortStatus (
1071 PciIo,
1072 Port
1073 );
1074
1075 Status = AhciEnableFisReceive (
1076 PciIo,
1077 Port,
1078 Timeout
1079 );
1080
1081 if (EFI_ERROR (Status)) {
1082 return Status;
1083 }
1084
1085 //
1086 // Setting the command
1087 //
1088 Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_SACT;
1089 AhciAndReg (PciIo, Offset, 0);
1090 AhciOrReg (PciIo, Offset, CmdSlotBit);
1091
1092 Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CI;
1093 AhciAndReg (PciIo, Offset, 0);
1094 AhciOrReg (PciIo, Offset, CmdSlotBit);
1095
1096 Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD;
1097 PortStatus = AhciReadReg (PciIo, Offset);
1098
1099 StartCmd = 0;
1100 if ((PortStatus & EFI_AHCI_PORT_CMD_ALPE) != 0) {
1101 StartCmd = AhciReadReg (PciIo, Offset);
1102 StartCmd &= ~EFI_AHCI_PORT_CMD_ICC_MASK;
1103 StartCmd |= EFI_AHCI_PORT_CMD_ACTIVE;
1104 }
1105
1106 Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_TFD;
1107 PortTfd = AhciReadReg (PciIo, Offset);
1108
1109 if ((PortTfd & (EFI_AHCI_PORT_TFD_BSY | EFI_AHCI_PORT_TFD_DRQ)) != 0) {
1110 if ((Capability & BIT24) != 0) {
1111 Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD;
1112 AhciOrReg (PciIo, Offset, EFI_AHCI_PORT_CMD_COL);
1113
1114 AhciWaitMemSet (
1115 PciIo,
1116 Offset,
1117 EFI_AHCI_PORT_CMD_COL,
1118 0,
1119 Timeout
1120 );
1121 }
1122 }
1123
1124 Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD;
1125 AhciOrReg (PciIo, Offset, EFI_AHCI_PORT_CMD_ST | StartCmd);
1126
1127 return EFI_SUCCESS;
1128 }
1129
1130 /**
1131 Do AHCI port reset.
1132
1133 @param PciIo The PCI IO protocol instance.
1134 @param Port The number of port.
1135 @param Timeout The timeout value of reset.
1136
1137 @retval EFI_DEVICE_ERROR The port reset unsuccessfully
1138 @retval EFI_TIMEOUT The reset operation is time out.
1139 @retval EFI_SUCCESS The port reset successfully.
1140
1141 **/
1142 EFI_STATUS
1143 EFIAPI
1144 AhciPortReset (
1145 IN EFI_PCI_IO_PROTOCOL *PciIo,
1146 IN UINT8 Port,
1147 IN UINT64 Timeout
1148 )
1149 {
1150 EFI_STATUS Status;
1151 UINT32 Offset;
1152
1153 AhciClearPortStatus (PciIo, Port);
1154
1155 AhciStopCommand (PciIo, Port, Timeout);
1156
1157 AhciDisableFisReceive (PciIo, Port, Timeout);
1158
1159 AhciEnableFisReceive (PciIo, Port, Timeout);
1160
1161 Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_SCTL;
1162
1163 AhciOrReg (PciIo, Offset, EFI_AHCI_PORT_SCTL_DET_INIT);
1164
1165 //
1166 // wait 5 milliseceond before de-assert DET
1167 //
1168 MicroSecondDelay (5000);
1169
1170 AhciAndReg (PciIo, Offset, (UINT32)EFI_AHCI_PORT_SCTL_MASK);
1171
1172 //
1173 // wait 5 milliseceond before de-assert DET
1174 //
1175 MicroSecondDelay (5000);
1176
1177 //
1178 // Wait for communication to be re-established
1179 //
1180 Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_SSTS;
1181 Status = AhciWaitMemSet (
1182 PciIo,
1183 Offset,
1184 EFI_AHCI_PORT_SSTS_DET_MASK,
1185 EFI_AHCI_PORT_SSTS_DET_PCE,
1186 Timeout
1187 );
1188
1189 if (EFI_ERROR (Status)) {
1190 return Status;
1191 }
1192
1193 Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_SERR;
1194 AhciOrReg (PciIo, Offset, EFI_AHCI_PORT_ERR_CLEAR);
1195
1196 return EFI_SUCCESS;
1197 }
1198
1199 /**
1200 Do AHCI HBA reset.
1201
1202 @param PciIo The PCI IO protocol instance.
1203 @param Timeout The timeout value of reset.
1204
1205
1206 @retval EFI_DEVICE_ERROR AHCI controller is failed to complete hardware reset.
1207 @retval EFI_TIMEOUT The reset operation is time out.
1208 @retval EFI_SUCCESS AHCI controller is reset successfully.
1209
1210 **/
1211 EFI_STATUS
1212 EFIAPI
1213 AhciReset (
1214 IN EFI_PCI_IO_PROTOCOL *PciIo,
1215 IN UINT64 Timeout
1216 )
1217 {
1218 EFI_STATUS Status;
1219 UINT32 Delay;
1220 UINT32 Value;
1221
1222 AhciOrReg (PciIo, EFI_AHCI_GHC_OFFSET, EFI_AHCI_GHC_ENABLE);
1223
1224 AhciOrReg (PciIo, EFI_AHCI_GHC_OFFSET, EFI_AHCI_GHC_RESET);
1225
1226 Status = EFI_TIMEOUT;
1227
1228 Delay = (UINT32) (DivU64x32(Timeout, 1000) + 1);
1229
1230 do {
1231 Value = AhciReadReg(PciIo, EFI_AHCI_GHC_OFFSET);
1232
1233 if ((Value & EFI_AHCI_GHC_RESET) == 0) {
1234 break;
1235 }
1236
1237 //
1238 // Stall for 100 microseconds.
1239 //
1240 MicroSecondDelay(100);
1241
1242 Delay--;
1243 } while (Delay > 0);
1244
1245 if (Delay == 0) {
1246 return EFI_TIMEOUT;
1247 }
1248
1249 return EFI_SUCCESS;
1250 }
1251
1252 /**
1253 Send Buffer cmd to specific device.
1254
1255 @param PciIo The PCI IO protocol instance.
1256 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1257 @param Port The number of port.
1258 @param PortMultiplier The timeout value of stop.
1259 @param Buffer The data buffer to store IDENTIFY PACKET data.
1260
1261 @retval EFI_DEVICE_ERROR The cmd abort with error occurs.
1262 @retval EFI_TIMEOUT The operation is time out.
1263 @retval EFI_UNSUPPORTED The device is not ready for executing.
1264 @retval EFI_SUCCESS The cmd executes successfully.
1265
1266 **/
1267 EFI_STATUS
1268 EFIAPI
1269 AhciIdentify (
1270 IN EFI_PCI_IO_PROTOCOL *PciIo,
1271 IN EFI_AHCI_REGISTERS *AhciRegisters,
1272 IN UINT8 Port,
1273 IN UINT8 PortMultiplier,
1274 IN OUT EFI_IDENTIFY_DATA *Buffer
1275 )
1276 {
1277 EFI_STATUS Status;
1278 EFI_ATA_COMMAND_BLOCK AtaCommandBlock;
1279 EFI_ATA_STATUS_BLOCK AtaStatusBlock;
1280
1281 if (PciIo == NULL || AhciRegisters == NULL || Buffer == NULL) {
1282 return EFI_INVALID_PARAMETER;
1283 }
1284
1285 ZeroMem (&AtaCommandBlock, sizeof (EFI_ATA_COMMAND_BLOCK));
1286 ZeroMem (&AtaStatusBlock, sizeof (EFI_ATA_STATUS_BLOCK));
1287
1288 AtaCommandBlock.AtaCommand = ATA_CMD_IDENTIFY_DRIVE;
1289 AtaCommandBlock.AtaSectorCount = 1;
1290
1291 Status = AhciPioTransfer (
1292 PciIo,
1293 AhciRegisters,
1294 Port,
1295 PortMultiplier,
1296 NULL,
1297 0,
1298 TRUE,
1299 &AtaCommandBlock,
1300 &AtaStatusBlock,
1301 Buffer,
1302 sizeof (EFI_IDENTIFY_DATA),
1303 ATA_ATAPI_TIMEOUT
1304 );
1305
1306 return Status;
1307 }
1308
1309 /**
1310 Send Buffer cmd to specific device.
1311
1312 @param PciIo The PCI IO protocol instance.
1313 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1314 @param Port The number of port.
1315 @param PortMultiplier The timeout value of stop.
1316 @param Buffer The data buffer to store IDENTIFY PACKET data.
1317
1318 @retval EFI_DEVICE_ERROR The cmd abort with error occurs.
1319 @retval EFI_TIMEOUT The operation is time out.
1320 @retval EFI_UNSUPPORTED The device is not ready for executing.
1321 @retval EFI_SUCCESS The cmd executes successfully.
1322
1323 **/
1324 EFI_STATUS
1325 EFIAPI
1326 AhciIdentifyPacket (
1327 IN EFI_PCI_IO_PROTOCOL *PciIo,
1328 IN EFI_AHCI_REGISTERS *AhciRegisters,
1329 IN UINT8 Port,
1330 IN UINT8 PortMultiplier,
1331 IN OUT EFI_IDENTIFY_DATA *Buffer
1332 )
1333 {
1334 EFI_STATUS Status;
1335 EFI_ATA_COMMAND_BLOCK AtaCommandBlock;
1336 EFI_ATA_STATUS_BLOCK AtaStatusBlock;
1337
1338 if (PciIo == NULL || AhciRegisters == NULL) {
1339 return EFI_INVALID_PARAMETER;
1340 }
1341
1342 ZeroMem (&AtaCommandBlock, sizeof (EFI_ATA_COMMAND_BLOCK));
1343 ZeroMem (&AtaStatusBlock, sizeof (EFI_ATA_STATUS_BLOCK));
1344
1345 AtaCommandBlock.AtaCommand = ATA_CMD_IDENTIFY_DEVICE;
1346 AtaCommandBlock.AtaSectorCount = 1;
1347
1348 Status = AhciPioTransfer (
1349 PciIo,
1350 AhciRegisters,
1351 Port,
1352 PortMultiplier,
1353 NULL,
1354 0,
1355 TRUE,
1356 &AtaCommandBlock,
1357 &AtaStatusBlock,
1358 Buffer,
1359 sizeof (EFI_IDENTIFY_DATA),
1360 ATA_ATAPI_TIMEOUT
1361 );
1362
1363 return Status;
1364 }
1365
1366 /**
1367 Send SET FEATURE cmd on specific device.
1368
1369 @param PciIo The PCI IO protocol instance.
1370 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1371 @param Port The number of port.
1372 @param PortMultiplier The timeout value of stop.
1373 @param Feature The data to send Feature register.
1374 @param FeatureSpecificData The specific data for SET FEATURE cmd.
1375
1376 @retval EFI_DEVICE_ERROR The cmd abort with error occurs.
1377 @retval EFI_TIMEOUT The operation is time out.
1378 @retval EFI_UNSUPPORTED The device is not ready for executing.
1379 @retval EFI_SUCCESS The cmd executes successfully.
1380
1381 **/
1382 EFI_STATUS
1383 EFIAPI
1384 AhciDeviceSetFeature (
1385 IN EFI_PCI_IO_PROTOCOL *PciIo,
1386 IN EFI_AHCI_REGISTERS *AhciRegisters,
1387 IN UINT8 Port,
1388 IN UINT8 PortMultiplier,
1389 IN UINT16 Feature,
1390 IN UINT32 FeatureSpecificData
1391 )
1392 {
1393 EFI_STATUS Status;
1394 EFI_ATA_COMMAND_BLOCK AtaCommandBlock;
1395 EFI_ATA_STATUS_BLOCK AtaStatusBlock;
1396
1397 ZeroMem (&AtaCommandBlock, sizeof (EFI_ATA_COMMAND_BLOCK));
1398 ZeroMem (&AtaStatusBlock, sizeof (EFI_ATA_STATUS_BLOCK));
1399
1400 AtaCommandBlock.AtaCommand = ATA_CMD_SET_FEATURES;
1401 AtaCommandBlock.AtaFeatures = (UINT8) Feature;
1402 AtaCommandBlock.AtaFeaturesExp = (UINT8) (Feature >> 8);
1403 AtaCommandBlock.AtaSectorCount = (UINT8) FeatureSpecificData;
1404 AtaCommandBlock.AtaSectorNumber = (UINT8) (FeatureSpecificData >> 8);
1405 AtaCommandBlock.AtaCylinderLow = (UINT8) (FeatureSpecificData >> 16);
1406 AtaCommandBlock.AtaCylinderHigh = (UINT8) (FeatureSpecificData >> 24);
1407
1408 Status = AhciNonDataTransfer (
1409 PciIo,
1410 AhciRegisters,
1411 (UINT8)Port,
1412 (UINT8)PortMultiplier,
1413 NULL,
1414 0,
1415 &AtaCommandBlock,
1416 &AtaStatusBlock,
1417 ATA_ATAPI_TIMEOUT
1418 );
1419
1420 return Status;
1421 }
1422
1423 /**
1424 This function is used to send out ATAPI commands conforms to the Packet Command
1425 with PIO Protocol.
1426
1427 @param PciIo The PCI IO protocol instance.
1428 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1429 @param Port The number of port.
1430 @param PortMultiplier The number of port multiplier.
1431 @param Packet A pointer to EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET structure.
1432
1433 @retval EFI_SUCCESS send out the ATAPI packet command successfully
1434 and device sends data successfully.
1435 @retval EFI_DEVICE_ERROR the device failed to send data.
1436
1437 **/
1438 EFI_STATUS
1439 EFIAPI
1440 AhciPacketCommandExecute (
1441 IN EFI_PCI_IO_PROTOCOL *PciIo,
1442 IN EFI_AHCI_REGISTERS *AhciRegisters,
1443 IN UINT8 Port,
1444 IN UINT8 PortMultiplier,
1445 IN EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet
1446 )
1447 {
1448 EFI_STATUS Status;
1449 VOID *Buffer;
1450 UINT32 Length;
1451 EFI_ATA_COMMAND_BLOCK AtaCommandBlock;
1452 EFI_ATA_STATUS_BLOCK AtaStatusBlock;
1453 BOOLEAN Read;
1454 UINT8 Retry;
1455
1456 if (Packet == NULL || Packet->Cdb == NULL) {
1457 return EFI_INVALID_PARAMETER;
1458 }
1459
1460 ZeroMem (&AtaCommandBlock, sizeof (EFI_ATA_COMMAND_BLOCK));
1461 ZeroMem (&AtaStatusBlock, sizeof (EFI_ATA_STATUS_BLOCK));
1462 AtaCommandBlock.AtaCommand = ATA_CMD_PACKET;
1463 //
1464 // No OVL; No DMA
1465 //
1466 AtaCommandBlock.AtaFeatures = 0x00;
1467 //
1468 // set the transfersize to ATAPI_MAX_BYTE_COUNT to let the device
1469 // determine how many data should be transferred.
1470 //
1471 AtaCommandBlock.AtaCylinderLow = (UINT8) (ATAPI_MAX_BYTE_COUNT & 0x00ff);
1472 AtaCommandBlock.AtaCylinderHigh = (UINT8) (ATAPI_MAX_BYTE_COUNT >> 8);
1473
1474 if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ) {
1475 Buffer = Packet->InDataBuffer;
1476 Length = Packet->InTransferLength;
1477 Read = TRUE;
1478 } else {
1479 Buffer = Packet->OutDataBuffer;
1480 Length = Packet->OutTransferLength;
1481 Read = FALSE;
1482 }
1483
1484 if (Length == 0) {
1485 Status = AhciNonDataTransfer (
1486 PciIo,
1487 AhciRegisters,
1488 Port,
1489 PortMultiplier,
1490 Packet->Cdb,
1491 Packet->CdbLength,
1492 &AtaCommandBlock,
1493 &AtaStatusBlock,
1494 Packet->Timeout
1495 );
1496 } else {
1497 //
1498 // READ_CAPACITY cmd may execute failure. Retry 5 times
1499 //
1500 if (((UINT8 *)Packet->Cdb)[0] == ATA_CMD_READ_CAPACITY) {
1501 Retry = 5;
1502 } else {
1503 Retry = 1;
1504 }
1505 do {
1506 Status = AhciPioTransfer (
1507 PciIo,
1508 AhciRegisters,
1509 Port,
1510 PortMultiplier,
1511 Packet->Cdb,
1512 Packet->CdbLength,
1513 Read,
1514 &AtaCommandBlock,
1515 &AtaStatusBlock,
1516 Buffer,
1517 Length,
1518 Packet->Timeout
1519 );
1520 if (!EFI_ERROR (Status)) {
1521 break;
1522 }
1523 Retry--;
1524 } while (Retry != 0);
1525 }
1526 return Status;
1527 }
1528
1529 /**
1530 Allocate transfer-related data struct which is used at AHCI mode.
1531
1532 @param PciIo The PCI IO protocol instance.
1533 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1534
1535 **/
1536 EFI_STATUS
1537 EFIAPI
1538 AhciCreateTransferDescriptor (
1539 IN EFI_PCI_IO_PROTOCOL *PciIo,
1540 IN OUT EFI_AHCI_REGISTERS *AhciRegisters
1541 )
1542 {
1543 EFI_STATUS Status;
1544 UINTN Bytes;
1545 VOID *Buffer;
1546
1547 UINT32 Capability;
1548 UINT8 MaxPortNumber;
1549 UINT8 MaxCommandSlotNumber;
1550 BOOLEAN Support64Bit;
1551 UINT64 MaxReceiveFisSize;
1552 UINT64 MaxCommandListSize;
1553 UINT64 MaxCommandTableSize;
1554
1555 Buffer = NULL;
1556 //
1557 // Collect AHCI controller information
1558 //
1559 Capability = AhciReadReg(PciIo, EFI_AHCI_CAPABILITY_OFFSET);
1560 MaxPortNumber = (UINT8) ((Capability & 0x1F) + 1);
1561 //
1562 // Get the number of command slots per port supported by this HBA.
1563 //
1564 MaxCommandSlotNumber = (UINT8) (((Capability & 0x1F00) >> 8) + 1);
1565 Support64Bit = (BOOLEAN) (((Capability & BIT31) != 0) ? TRUE : FALSE);
1566
1567 MaxReceiveFisSize = MaxPortNumber * sizeof (EFI_AHCI_RECEIVED_FIS);
1568 Status = PciIo->AllocateBuffer (
1569 PciIo,
1570 AllocateAnyPages,
1571 EfiBootServicesData,
1572 (UINTN)EFI_SIZE_TO_PAGES (MaxReceiveFisSize),
1573 &Buffer,
1574 0
1575 );
1576
1577 if (EFI_ERROR (Status)) {
1578 return EFI_OUT_OF_RESOURCES;
1579 }
1580
1581 ZeroMem (Buffer, (UINTN)MaxReceiveFisSize);
1582
1583 AhciRegisters->AhciRFis = Buffer;
1584 AhciRegisters->MaxReceiveFisSize = MaxReceiveFisSize;
1585 Bytes = (UINTN)MaxReceiveFisSize;
1586
1587 Status = PciIo->Map (
1588 PciIo,
1589 EfiPciIoOperationBusMasterCommonBuffer,
1590 Buffer,
1591 &Bytes,
1592 (EFI_PHYSICAL_ADDRESS *) &AhciRegisters->AhciRFisPciAddr,
1593 &AhciRegisters->MapRFis
1594 );
1595
1596 if (EFI_ERROR (Status) || (Bytes != MaxReceiveFisSize)) {
1597 //
1598 // Map error or unable to map the whole RFis buffer into a contiguous region.
1599 //
1600 Status = EFI_OUT_OF_RESOURCES;
1601 goto Error6;
1602 }
1603
1604 if ((!Support64Bit) && ((EFI_PHYSICAL_ADDRESS)(UINTN)AhciRegisters->AhciRFisPciAddr > 0x100000000ULL)) {
1605 //
1606 // The AHCI HBA doesn't support 64bit addressing, so should not get a >4G pci bus master address.
1607 //
1608 Status = EFI_DEVICE_ERROR;
1609 goto Error5;
1610 }
1611
1612 //
1613 // Allocate memory for command list
1614 // Note that the implemenation is a single task model which only use a command list for all ports.
1615 //
1616 Buffer = NULL;
1617 MaxCommandListSize = MaxCommandSlotNumber * sizeof (EFI_AHCI_COMMAND_LIST);
1618 Status = PciIo->AllocateBuffer (
1619 PciIo,
1620 AllocateAnyPages,
1621 EfiBootServicesData,
1622 (UINTN)EFI_SIZE_TO_PAGES (MaxCommandListSize),
1623 &Buffer,
1624 0
1625 );
1626
1627 if (EFI_ERROR (Status)) {
1628 //
1629 // Free mapped resource.
1630 //
1631 Status = EFI_OUT_OF_RESOURCES;
1632 goto Error5;
1633 }
1634
1635 ZeroMem (Buffer, (UINTN)MaxCommandListSize);
1636
1637 AhciRegisters->AhciCmdList = Buffer;
1638 AhciRegisters->MaxCommandListSize = MaxCommandListSize;
1639 Bytes = (UINTN)MaxCommandListSize;
1640
1641 Status = PciIo->Map (
1642 PciIo,
1643 EfiPciIoOperationBusMasterCommonBuffer,
1644 Buffer,
1645 &Bytes,
1646 (EFI_PHYSICAL_ADDRESS *)&AhciRegisters->AhciCmdListPciAddr,
1647 &AhciRegisters->MapCmdList
1648 );
1649
1650 if (EFI_ERROR (Status) || (Bytes != MaxCommandListSize)) {
1651 //
1652 // Map error or unable to map the whole cmd list buffer into a contiguous region.
1653 //
1654 Status = EFI_OUT_OF_RESOURCES;
1655 goto Error4;
1656 }
1657
1658 if ((!Support64Bit) && ((EFI_PHYSICAL_ADDRESS)(UINTN)AhciRegisters->AhciCmdListPciAddr > 0x100000000ULL)) {
1659 //
1660 // The AHCI HBA doesn't support 64bit addressing, so should not get a >4G pci bus master address.
1661 //
1662 Status = EFI_DEVICE_ERROR;
1663 goto Error3;
1664 }
1665
1666 //
1667 // Allocate memory for command table
1668 // According to AHCI 1.3 spec, a PRD table can contain maximum 65535 entries.
1669 //
1670 Buffer = NULL;
1671 MaxCommandTableSize = sizeof (EFI_AHCI_COMMAND_TABLE);
1672
1673 Status = PciIo->AllocateBuffer (
1674 PciIo,
1675 AllocateAnyPages,
1676 EfiBootServicesData,
1677 (UINTN)EFI_SIZE_TO_PAGES (MaxCommandTableSize),
1678 &Buffer,
1679 0
1680 );
1681
1682 if (EFI_ERROR (Status)) {
1683 //
1684 // Free mapped resource.
1685 //
1686 Status = EFI_OUT_OF_RESOURCES;
1687 goto Error3;
1688 }
1689
1690 ZeroMem (Buffer, (UINTN)MaxCommandTableSize);
1691
1692 AhciRegisters->AhciCommandTable = Buffer;
1693 AhciRegisters->MaxCommandTableSize = MaxCommandTableSize;
1694 Bytes = (UINTN)MaxCommandTableSize;
1695
1696 Status = PciIo->Map (
1697 PciIo,
1698 EfiPciIoOperationBusMasterCommonBuffer,
1699 Buffer,
1700 &Bytes,
1701 (EFI_PHYSICAL_ADDRESS *)&AhciRegisters->AhciCommandTablePciAddr,
1702 &AhciRegisters->MapCommandTable
1703 );
1704
1705 if (EFI_ERROR (Status) || (Bytes != MaxCommandTableSize)) {
1706 //
1707 // Map error or unable to map the whole cmd list buffer into a contiguous region.
1708 //
1709 Status = EFI_OUT_OF_RESOURCES;
1710 goto Error2;
1711 }
1712
1713 if ((!Support64Bit) && ((EFI_PHYSICAL_ADDRESS)(UINTN)AhciRegisters->AhciCommandTablePciAddr > 0x100000000ULL)) {
1714 //
1715 // The AHCI HBA doesn't support 64bit addressing, so should not get a >4G pci bus master address.
1716 //
1717 Status = EFI_DEVICE_ERROR;
1718 goto Error1;
1719 }
1720
1721 return EFI_SUCCESS;
1722 //
1723 // Map error or unable to map the whole CmdList buffer into a contiguous region.
1724 //
1725 Error1:
1726 PciIo->Unmap (
1727 PciIo,
1728 AhciRegisters->MapCommandTable
1729 );
1730 Error2:
1731 PciIo->FreeBuffer (
1732 PciIo,
1733 (UINTN)EFI_SIZE_TO_PAGES (MaxCommandTableSize),
1734 AhciRegisters->AhciCommandTable
1735 );
1736 Error3:
1737 PciIo->Unmap (
1738 PciIo,
1739 AhciRegisters->MapCmdList
1740 );
1741 Error4:
1742 PciIo->FreeBuffer (
1743 PciIo,
1744 (UINTN)EFI_SIZE_TO_PAGES (MaxCommandListSize),
1745 AhciRegisters->AhciCmdList
1746 );
1747 Error5:
1748 PciIo->Unmap (
1749 PciIo,
1750 AhciRegisters->MapRFis
1751 );
1752 Error6:
1753 PciIo->FreeBuffer (
1754 PciIo,
1755 (UINTN)EFI_SIZE_TO_PAGES (MaxReceiveFisSize),
1756 AhciRegisters->AhciRFis
1757 );
1758
1759 return Status;
1760 }
1761
1762 /**
1763 Initialize ATA host controller at AHCI mode.
1764
1765 The function is designed to initialize ATA host controller.
1766
1767 @param[in] Instance A pointer to the ATA_ATAPI_PASS_THRU_INSTANCE instance.
1768
1769 **/
1770 EFI_STATUS
1771 EFIAPI
1772 AhciModeInitialization (
1773 IN ATA_ATAPI_PASS_THRU_INSTANCE *Instance
1774 )
1775 {
1776 EFI_STATUS Status;
1777 EFI_PCI_IO_PROTOCOL *PciIo;
1778 EFI_IDE_CONTROLLER_INIT_PROTOCOL *IdeInit;
1779 UINT32 Capability;
1780 UINT8 MaxPortNumber;
1781 UINT32 PortImplementBitMap;
1782 UINT8 MaxCommandSlotNumber;
1783 BOOLEAN Support64Bit;
1784
1785 EFI_AHCI_REGISTERS *AhciRegisters;
1786
1787 UINT8 Port;
1788 DATA_64 Data64;
1789 UINT32 Offset;
1790 UINT32 Data;
1791 EFI_IDENTIFY_DATA Buffer;
1792 EFI_ATA_DEVICE_TYPE DeviceType;
1793 EFI_ATA_COLLECTIVE_MODE *SupportedModes;
1794 EFI_ATA_TRANSFER_MODE TransferMode;
1795
1796 if (Instance == NULL) {
1797 return EFI_INVALID_PARAMETER;
1798 }
1799
1800 PciIo = Instance->PciIo;
1801 IdeInit = Instance->IdeControllerInit;
1802
1803 Status = AhciReset (PciIo, ATA_ATAPI_TIMEOUT);
1804
1805 if (EFI_ERROR (Status)) {
1806 return EFI_DEVICE_ERROR;
1807 }
1808
1809 //
1810 // Enable AE before accessing any AHCI registers
1811 //
1812 AhciOrReg (PciIo, EFI_AHCI_GHC_OFFSET, EFI_AHCI_GHC_ENABLE);
1813
1814 //
1815 // Collect AHCI controller information
1816 //
1817 Capability = AhciReadReg(PciIo, EFI_AHCI_CAPABILITY_OFFSET);
1818
1819 //
1820 // Get the number of command slots per port supported by this HBA.
1821 //
1822 MaxCommandSlotNumber = (UINT8) (((Capability & 0x1F00) >> 8) + 1);
1823 Support64Bit = (BOOLEAN) (((Capability & BIT31) != 0) ? TRUE : FALSE);
1824
1825 //
1826 // Get the bit map of those ports exposed by this HBA.
1827 // It indicates which ports that the HBA supports are available for software to use.
1828 //
1829 PortImplementBitMap = AhciReadReg(PciIo, EFI_AHCI_PI_OFFSET);
1830 MaxPortNumber = (UINT8) ((Capability & 0x1F) + 1);
1831
1832 AhciRegisters = &Instance->AhciRegisters;
1833 Status = AhciCreateTransferDescriptor (PciIo, AhciRegisters);
1834
1835 if (EFI_ERROR (Status)) {
1836 return EFI_OUT_OF_RESOURCES;
1837 }
1838
1839 for (Port = 0; Port < MaxPortNumber; Port ++) {
1840 Data64.Uint64 = (UINTN) (AhciRegisters->AhciRFisPciAddr) + sizeof (EFI_AHCI_RECEIVED_FIS) * Port;
1841
1842 Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_FB;
1843 AhciWriteReg (PciIo, Offset, Data64.Uint32.Lower32);
1844 Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_FBU;
1845 AhciWriteReg (PciIo, Offset, Data64.Uint32.Upper32);
1846
1847 //
1848 // Single task envrionment, we only use one command table for all port
1849 //
1850 Data64.Uint64 = (UINTN) (AhciRegisters->AhciCmdListPciAddr);
1851
1852 Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CLB;
1853 AhciWriteReg (PciIo, Offset, Data64.Uint32.Lower32);
1854 Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CLBU;
1855 AhciWriteReg (PciIo, Offset, Data64.Uint32.Upper32);
1856
1857 if ((PortImplementBitMap & (BIT0 << Port)) != 0) {
1858 Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD;
1859
1860 if ((Capability & EFI_AHCI_PORT_CMD_ASP) != 0) {
1861 AhciOrReg (PciIo, Offset, EFI_AHCI_PORT_CMD_SUD);
1862 }
1863 Data = AhciReadReg (PciIo, Offset);
1864 if ((Data & EFI_AHCI_PORT_CMD_CPD) != 0) {
1865 AhciOrReg (PciIo, Offset, EFI_AHCI_PORT_CMD_POD);
1866 }
1867
1868 AhciAndReg (PciIo, Offset, (UINT32)~(EFI_AHCI_PORT_CMD_FRE|EFI_AHCI_PORT_CMD_COL|EFI_AHCI_PORT_CMD_ST));
1869 }
1870
1871 Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_SCTL;
1872 AhciAndReg (PciIo, Offset, (UINT32)~(EFI_AHCI_PORT_SCTL_IPM_MASK));
1873
1874 AhciAndReg (PciIo, Offset,(UINT32) ~(EFI_AHCI_PORT_SCTL_IPM_PSD));
1875 AhciOrReg (PciIo, Offset, EFI_AHCI_PORT_SCTL_IPM_PSD);
1876
1877 AhciAndReg (PciIo, Offset, (UINT32)~(EFI_AHCI_PORT_SCTL_IPM_SSD));
1878 AhciOrReg (PciIo, Offset, EFI_AHCI_PORT_SCTL_IPM_SSD);
1879
1880 Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_IE;
1881 AhciAndReg (PciIo, Offset, 0);
1882
1883 Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_SERR;
1884 AhciWriteReg (PciIo, Offset, AhciReadReg (PciIo, Offset));
1885 }
1886
1887 //
1888 // Stall for 100 milliseconds.
1889 //
1890 MicroSecondDelay(100000);
1891
1892 IdeInit->NotifyPhase (IdeInit, EfiIdeBeforeChannelEnumeration, Port);
1893
1894 for (Port = 0; Port < MaxPortNumber; Port ++) {
1895 if ((PortImplementBitMap & (BIT0 << Port)) != 0) {
1896
1897 Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_SSTS;
1898 Data = AhciReadReg (PciIo, Offset) & EFI_AHCI_PORT_SSTS_DET_MASK;
1899
1900 if (Data == 0) {
1901 continue;
1902 }
1903 //
1904 // Found device in the port
1905 //
1906 if (Data == EFI_AHCI_PORT_SSTS_DET_PCE) {
1907 Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_SIG;
1908
1909 Status = AhciWaitMemSet (
1910 PciIo,
1911 Offset,
1912 0x0000FFFF,
1913 0x00000101,
1914 ATA_ATAPI_TIMEOUT
1915 );
1916 if (EFI_ERROR (Status)) {
1917 continue;
1918 }
1919
1920 //
1921 // Now inform the IDE Controller Init Module.
1922 //
1923 IdeInit->NotifyPhase (IdeInit, EfiIdeBusBeforeDevicePresenceDetection, Port);
1924
1925 Data = AhciReadReg (PciIo, Offset);
1926
1927 if ((Data & EFI_AHCI_ATAPI_SIG_MASK) == EFI_AHCI_ATAPI_DEVICE_SIG) {
1928 Status = AhciIdentifyPacket (PciIo, AhciRegisters, Port, 0, &Buffer);
1929
1930 if (EFI_ERROR (Status)) {
1931 continue;
1932 }
1933
1934 DeviceType = EfiIdeCdrom;
1935 } else if ((Data & EFI_AHCI_ATAPI_SIG_MASK) == EFI_AHCI_ATA_DEVICE_SIG) {
1936 Status = AhciIdentify (PciIo, AhciRegisters, Port, 0, &Buffer);
1937
1938 if (EFI_ERROR (Status)) {
1939 continue;
1940 }
1941
1942 DeviceType = EfiIdeHarddisk;
1943 } else {
1944 continue;
1945 }
1946
1947 DEBUG ((EFI_D_INFO, "port [%d] port mulitplier [%d] has a [%a]\n",
1948 Port, 0, DeviceType == EfiIdeCdrom ? "cdrom" : "harddisk"));
1949
1950 //
1951 // Submit identify data to IDE controller init driver
1952 //
1953 IdeInit->SubmitData (IdeInit, Port, 0, &Buffer);
1954
1955 //
1956 // Now start to config ide device parameter and transfer mode.
1957 //
1958 Status = IdeInit->CalculateMode (
1959 IdeInit,
1960 Port,
1961 0,
1962 &SupportedModes
1963 );
1964 if (EFI_ERROR (Status)) {
1965 DEBUG ((EFI_D_ERROR, "Calculate Mode Fail, Status = %r\n", Status));
1966 continue;
1967 }
1968
1969 //
1970 // Set best supported PIO mode on this IDE device
1971 //
1972 if (SupportedModes->PioMode.Mode <= EfiAtaPioMode2) {
1973 TransferMode.ModeCategory = EFI_ATA_MODE_DEFAULT_PIO;
1974 } else {
1975 TransferMode.ModeCategory = EFI_ATA_MODE_FLOW_PIO;
1976 }
1977
1978 TransferMode.ModeNumber = (UINT8) (SupportedModes->PioMode.Mode);
1979
1980 //
1981 // Set supported DMA mode on this IDE device. Note that UDMA & MDMA cann't
1982 // be set together. Only one DMA mode can be set to a device. If setting
1983 // DMA mode operation fails, we can continue moving on because we only use
1984 // PIO mode at boot time. DMA modes are used by certain kind of OS booting
1985 //
1986 if (SupportedModes->UdmaMode.Valid) {
1987 TransferMode.ModeCategory = EFI_ATA_MODE_UDMA;
1988 TransferMode.ModeNumber = (UINT8) (SupportedModes->UdmaMode.Mode);
1989 } else if (SupportedModes->MultiWordDmaMode.Valid) {
1990 TransferMode.ModeCategory = EFI_ATA_MODE_MDMA;
1991 TransferMode.ModeNumber = (UINT8) SupportedModes->MultiWordDmaMode.Mode;
1992 }
1993
1994 Status = AhciDeviceSetFeature (PciIo, AhciRegisters, Port, 0, 0x03, (UINT32)(*(UINT8 *)&TransferMode));
1995
1996 if (EFI_ERROR (Status)) {
1997 DEBUG ((EFI_D_ERROR, "Set transfer Mode Fail, Status = %r\n", Status));
1998 continue;
1999 }
2000 //
2001 // Found a ATA or ATAPI device, add it into the device list.
2002 //
2003 CreateNewDeviceInfo (Instance, Port, 0, DeviceType, &Buffer);
2004 }
2005 }
2006 }
2007 return EFI_SUCCESS;
2008 }
2009