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