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