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