]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AhciMode.c
Update the function's descriptions (which is in AtaBus, AtaAtapiPassThru, Partition...
[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_OUT_OF_RESOURCES;
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_OUT_OF_RESOURCES;
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_COL);
1277
1278 AhciWaitMemSet (
1279 PciIo,
1280 Offset,
1281 EFI_AHCI_PORT_CMD_COL,
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 EFI_STATUS Status;
1393 UINT32 Delay;
1394 UINT32 Value;
1395
1396 AhciOrReg (PciIo, EFI_AHCI_GHC_OFFSET, EFI_AHCI_GHC_ENABLE);
1397
1398 AhciOrReg (PciIo, EFI_AHCI_GHC_OFFSET, EFI_AHCI_GHC_RESET);
1399
1400 Status = EFI_TIMEOUT;
1401
1402 Delay = (UINT32) (DivU64x32(Timeout, 1000) + 1);
1403
1404 do {
1405 Value = AhciReadReg(PciIo, EFI_AHCI_GHC_OFFSET);
1406
1407 if ((Value & EFI_AHCI_GHC_RESET) == 0) {
1408 break;
1409 }
1410
1411 //
1412 // Stall for 100 microseconds.
1413 //
1414 MicroSecondDelay(100);
1415
1416 Delay--;
1417 } while (Delay > 0);
1418
1419 if (Delay == 0) {
1420 return EFI_TIMEOUT;
1421 }
1422
1423 return EFI_SUCCESS;
1424 }
1425
1426 /**
1427 Send SMART Return Status command to check if the execution of SMART cmd is successful or not.
1428
1429 @param PciIo The PCI IO protocol instance.
1430 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1431 @param Port The number of port.
1432 @param PortMultiplier The timeout value of stop.
1433 @param AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.
1434
1435 @retval EFI_SUCCESS Successfully get the return status of S.M.A.R.T command execution.
1436 @retval Others Fail to get return status data.
1437
1438 **/
1439 EFI_STATUS
1440 EFIAPI
1441 AhciAtaSmartReturnStatusCheck (
1442 IN EFI_PCI_IO_PROTOCOL *PciIo,
1443 IN EFI_AHCI_REGISTERS *AhciRegisters,
1444 IN UINT8 Port,
1445 IN UINT8 PortMultiplier,
1446 IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock
1447 )
1448 {
1449 EFI_STATUS Status;
1450 EFI_ATA_COMMAND_BLOCK AtaCommandBlock;
1451 UINT8 LBAMid;
1452 UINT8 LBAHigh;
1453 UINTN FisBaseAddr;
1454 UINT32 Value;
1455
1456 ZeroMem (&AtaCommandBlock, sizeof (EFI_ATA_COMMAND_BLOCK));
1457
1458 AtaCommandBlock.AtaCommand = ATA_CMD_SMART;
1459 AtaCommandBlock.AtaFeatures = ATA_SMART_RETURN_STATUS;
1460 AtaCommandBlock.AtaCylinderLow = ATA_CONSTANT_4F;
1461 AtaCommandBlock.AtaCylinderHigh = ATA_CONSTANT_C2;
1462
1463 //
1464 // Send S.M.A.R.T Read Return Status command to device
1465 //
1466 Status = AhciNonDataTransfer (
1467 PciIo,
1468 AhciRegisters,
1469 (UINT8)Port,
1470 (UINT8)PortMultiplier,
1471 NULL,
1472 0,
1473 &AtaCommandBlock,
1474 AtaStatusBlock,
1475 ATA_ATAPI_TIMEOUT,
1476 NULL
1477 );
1478
1479 if (EFI_ERROR (Status)) {
1480 return EFI_DEVICE_ERROR;
1481 }
1482
1483 FisBaseAddr = (UINTN)AhciRegisters->AhciRFis + Port * sizeof (EFI_AHCI_RECEIVED_FIS);
1484
1485 Value = *(UINT32 *) (FisBaseAddr + EFI_AHCI_D2H_FIS_OFFSET);
1486
1487 if ((Value & EFI_AHCI_FIS_TYPE_MASK) == EFI_AHCI_FIS_REGISTER_D2H) {
1488 LBAMid = ((UINT8 *)(UINTN)(FisBaseAddr + EFI_AHCI_D2H_FIS_OFFSET))[5];
1489 LBAHigh = ((UINT8 *)(UINTN)(FisBaseAddr + EFI_AHCI_D2H_FIS_OFFSET))[6];
1490
1491 if ((LBAMid == 0x4f) && (LBAHigh == 0xc2)) {
1492 //
1493 // The threshold exceeded condition is not detected by the device
1494 //
1495 DEBUG ((EFI_D_INFO, "The S.M.A.R.T threshold exceeded condition is not detected\n"));
1496
1497 } else if ((LBAMid == 0xf4) && (LBAHigh == 0x2c)) {
1498 //
1499 // The threshold exceeded condition is detected by the device
1500 //
1501 DEBUG ((EFI_D_INFO, "The S.M.A.R.T threshold exceeded condition is detected\n"));
1502 }
1503 }
1504
1505 return EFI_SUCCESS;
1506 }
1507
1508 /**
1509 Enable SMART command of the disk if supported.
1510
1511 @param PciIo The PCI IO protocol instance.
1512 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1513 @param Port The number of port.
1514 @param PortMultiplier The timeout value of stop.
1515 @param IdentifyData A pointer to data buffer which is used to contain IDENTIFY data.
1516 @param AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.
1517
1518 **/
1519 VOID
1520 EFIAPI
1521 AhciAtaSmartSupport (
1522 IN EFI_PCI_IO_PROTOCOL *PciIo,
1523 IN EFI_AHCI_REGISTERS *AhciRegisters,
1524 IN UINT8 Port,
1525 IN UINT8 PortMultiplier,
1526 IN EFI_IDENTIFY_DATA *IdentifyData,
1527 IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock
1528 )
1529 {
1530 EFI_STATUS Status;
1531 EFI_ATA_COMMAND_BLOCK AtaCommandBlock;
1532
1533 //
1534 // Detect if the device supports S.M.A.R.T.
1535 //
1536 if ((IdentifyData->AtaData.command_set_supported_82 & 0x0001) != 0x0001) {
1537 //
1538 // S.M.A.R.T is not supported by the device
1539 //
1540 DEBUG ((EFI_D_INFO, "S.M.A.R.T feature is not supported at port [%d] PortMultiplier [%d]!\n",
1541 Port, PortMultiplier));
1542 } else {
1543 //
1544 // Check if the feature is enabled. If not, then enable S.M.A.R.T.
1545 //
1546 if ((IdentifyData->AtaData.command_set_feature_enb_85 & 0x0001) != 0x0001) {
1547 ZeroMem (&AtaCommandBlock, sizeof (EFI_ATA_COMMAND_BLOCK));
1548
1549 AtaCommandBlock.AtaCommand = ATA_CMD_SMART;
1550 AtaCommandBlock.AtaFeatures = ATA_SMART_ENABLE_OPERATION;
1551 AtaCommandBlock.AtaCylinderLow = ATA_CONSTANT_4F;
1552 AtaCommandBlock.AtaCylinderHigh = ATA_CONSTANT_C2;
1553
1554 //
1555 // Send S.M.A.R.T Enable command to device
1556 //
1557 Status = AhciNonDataTransfer (
1558 PciIo,
1559 AhciRegisters,
1560 (UINT8)Port,
1561 (UINT8)PortMultiplier,
1562 NULL,
1563 0,
1564 &AtaCommandBlock,
1565 AtaStatusBlock,
1566 ATA_ATAPI_TIMEOUT,
1567 NULL
1568 );
1569
1570
1571 if (!EFI_ERROR (Status)) {
1572 //
1573 // Send S.M.A.R.T AutoSave command to device
1574 //
1575 ZeroMem (&AtaCommandBlock, sizeof (EFI_ATA_COMMAND_BLOCK));
1576
1577 AtaCommandBlock.AtaCommand = ATA_CMD_SMART;
1578 AtaCommandBlock.AtaFeatures = 0xD2;
1579 AtaCommandBlock.AtaSectorCount = 0xF1;
1580 AtaCommandBlock.AtaCylinderLow = ATA_CONSTANT_4F;
1581 AtaCommandBlock.AtaCylinderHigh = ATA_CONSTANT_C2;
1582
1583 Status = AhciNonDataTransfer (
1584 PciIo,
1585 AhciRegisters,
1586 (UINT8)Port,
1587 (UINT8)PortMultiplier,
1588 NULL,
1589 0,
1590 &AtaCommandBlock,
1591 AtaStatusBlock,
1592 ATA_ATAPI_TIMEOUT,
1593 NULL
1594 );
1595
1596 if (!EFI_ERROR (Status)) {
1597 Status = AhciAtaSmartReturnStatusCheck (
1598 PciIo,
1599 AhciRegisters,
1600 (UINT8)Port,
1601 (UINT8)PortMultiplier,
1602 AtaStatusBlock
1603 );
1604 }
1605 }
1606 }
1607 DEBUG ((EFI_D_INFO, "Enabled S.M.A.R.T feature at port [%d] PortMultiplier [%d]!\n",
1608 Port, PortMultiplier));
1609 }
1610
1611 return ;
1612 }
1613
1614 /**
1615 Send Buffer cmd to specific device.
1616
1617 @param PciIo The PCI IO protocol instance.
1618 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1619 @param Port The number of port.
1620 @param PortMultiplier The timeout value of stop.
1621 @param Buffer The data buffer to store IDENTIFY PACKET data.
1622
1623 @retval EFI_DEVICE_ERROR The cmd abort with error occurs.
1624 @retval EFI_TIMEOUT The operation is time out.
1625 @retval EFI_UNSUPPORTED The device is not ready for executing.
1626 @retval EFI_SUCCESS The cmd executes successfully.
1627
1628 **/
1629 EFI_STATUS
1630 EFIAPI
1631 AhciIdentify (
1632 IN EFI_PCI_IO_PROTOCOL *PciIo,
1633 IN EFI_AHCI_REGISTERS *AhciRegisters,
1634 IN UINT8 Port,
1635 IN UINT8 PortMultiplier,
1636 IN OUT EFI_IDENTIFY_DATA *Buffer
1637 )
1638 {
1639 EFI_STATUS Status;
1640 EFI_ATA_COMMAND_BLOCK AtaCommandBlock;
1641 EFI_ATA_STATUS_BLOCK AtaStatusBlock;
1642
1643 if (PciIo == NULL || AhciRegisters == NULL || Buffer == NULL) {
1644 return EFI_INVALID_PARAMETER;
1645 }
1646
1647 ZeroMem (&AtaCommandBlock, sizeof (EFI_ATA_COMMAND_BLOCK));
1648 ZeroMem (&AtaStatusBlock, sizeof (EFI_ATA_STATUS_BLOCK));
1649
1650 AtaCommandBlock.AtaCommand = ATA_CMD_IDENTIFY_DRIVE;
1651 AtaCommandBlock.AtaSectorCount = 1;
1652
1653 Status = AhciPioTransfer (
1654 PciIo,
1655 AhciRegisters,
1656 Port,
1657 PortMultiplier,
1658 NULL,
1659 0,
1660 TRUE,
1661 &AtaCommandBlock,
1662 &AtaStatusBlock,
1663 Buffer,
1664 sizeof (EFI_IDENTIFY_DATA),
1665 ATA_ATAPI_TIMEOUT,
1666 NULL
1667 );
1668
1669 return Status;
1670 }
1671
1672 /**
1673 Send Buffer cmd to specific device.
1674
1675 @param PciIo The PCI IO protocol instance.
1676 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1677 @param Port The number of port.
1678 @param PortMultiplier The timeout value of stop.
1679 @param Buffer The data buffer to store IDENTIFY PACKET data.
1680
1681 @retval EFI_DEVICE_ERROR The cmd abort with error occurs.
1682 @retval EFI_TIMEOUT The operation is time out.
1683 @retval EFI_UNSUPPORTED The device is not ready for executing.
1684 @retval EFI_SUCCESS The cmd executes successfully.
1685
1686 **/
1687 EFI_STATUS
1688 EFIAPI
1689 AhciIdentifyPacket (
1690 IN EFI_PCI_IO_PROTOCOL *PciIo,
1691 IN EFI_AHCI_REGISTERS *AhciRegisters,
1692 IN UINT8 Port,
1693 IN UINT8 PortMultiplier,
1694 IN OUT EFI_IDENTIFY_DATA *Buffer
1695 )
1696 {
1697 EFI_STATUS Status;
1698 EFI_ATA_COMMAND_BLOCK AtaCommandBlock;
1699 EFI_ATA_STATUS_BLOCK AtaStatusBlock;
1700
1701 if (PciIo == NULL || AhciRegisters == NULL) {
1702 return EFI_INVALID_PARAMETER;
1703 }
1704
1705 ZeroMem (&AtaCommandBlock, sizeof (EFI_ATA_COMMAND_BLOCK));
1706 ZeroMem (&AtaStatusBlock, sizeof (EFI_ATA_STATUS_BLOCK));
1707
1708 AtaCommandBlock.AtaCommand = ATA_CMD_IDENTIFY_DEVICE;
1709 AtaCommandBlock.AtaSectorCount = 1;
1710
1711 Status = AhciPioTransfer (
1712 PciIo,
1713 AhciRegisters,
1714 Port,
1715 PortMultiplier,
1716 NULL,
1717 0,
1718 TRUE,
1719 &AtaCommandBlock,
1720 &AtaStatusBlock,
1721 Buffer,
1722 sizeof (EFI_IDENTIFY_DATA),
1723 ATA_ATAPI_TIMEOUT,
1724 NULL
1725 );
1726
1727 return Status;
1728 }
1729
1730 /**
1731 Send SET FEATURE cmd on specific device.
1732
1733 @param PciIo The PCI IO protocol instance.
1734 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1735 @param Port The number of port.
1736 @param PortMultiplier The timeout value of stop.
1737 @param Feature The data to send Feature register.
1738 @param FeatureSpecificData The specific data for SET FEATURE cmd.
1739
1740 @retval EFI_DEVICE_ERROR The cmd abort with error occurs.
1741 @retval EFI_TIMEOUT The operation is time out.
1742 @retval EFI_UNSUPPORTED The device is not ready for executing.
1743 @retval EFI_SUCCESS The cmd executes successfully.
1744
1745 **/
1746 EFI_STATUS
1747 EFIAPI
1748 AhciDeviceSetFeature (
1749 IN EFI_PCI_IO_PROTOCOL *PciIo,
1750 IN EFI_AHCI_REGISTERS *AhciRegisters,
1751 IN UINT8 Port,
1752 IN UINT8 PortMultiplier,
1753 IN UINT16 Feature,
1754 IN UINT32 FeatureSpecificData
1755 )
1756 {
1757 EFI_STATUS Status;
1758 EFI_ATA_COMMAND_BLOCK AtaCommandBlock;
1759 EFI_ATA_STATUS_BLOCK AtaStatusBlock;
1760
1761 ZeroMem (&AtaCommandBlock, sizeof (EFI_ATA_COMMAND_BLOCK));
1762 ZeroMem (&AtaStatusBlock, sizeof (EFI_ATA_STATUS_BLOCK));
1763
1764 AtaCommandBlock.AtaCommand = ATA_CMD_SET_FEATURES;
1765 AtaCommandBlock.AtaFeatures = (UINT8) Feature;
1766 AtaCommandBlock.AtaFeaturesExp = (UINT8) (Feature >> 8);
1767 AtaCommandBlock.AtaSectorCount = (UINT8) FeatureSpecificData;
1768 AtaCommandBlock.AtaSectorNumber = (UINT8) (FeatureSpecificData >> 8);
1769 AtaCommandBlock.AtaCylinderLow = (UINT8) (FeatureSpecificData >> 16);
1770 AtaCommandBlock.AtaCylinderHigh = (UINT8) (FeatureSpecificData >> 24);
1771
1772 Status = AhciNonDataTransfer (
1773 PciIo,
1774 AhciRegisters,
1775 (UINT8)Port,
1776 (UINT8)PortMultiplier,
1777 NULL,
1778 0,
1779 &AtaCommandBlock,
1780 &AtaStatusBlock,
1781 ATA_ATAPI_TIMEOUT,
1782 NULL
1783 );
1784
1785 return Status;
1786 }
1787
1788 /**
1789 This function is used to send out ATAPI commands conforms to the Packet Command
1790 with PIO Protocol.
1791
1792 @param PciIo The PCI IO protocol instance.
1793 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1794 @param Port The number of port.
1795 @param PortMultiplier The number of port multiplier.
1796 @param Packet A pointer to EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET structure.
1797
1798 @retval EFI_SUCCESS send out the ATAPI packet command successfully
1799 and device sends data successfully.
1800 @retval EFI_DEVICE_ERROR the device failed to send data.
1801
1802 **/
1803 EFI_STATUS
1804 EFIAPI
1805 AhciPacketCommandExecute (
1806 IN EFI_PCI_IO_PROTOCOL *PciIo,
1807 IN EFI_AHCI_REGISTERS *AhciRegisters,
1808 IN UINT8 Port,
1809 IN UINT8 PortMultiplier,
1810 IN EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet
1811 )
1812 {
1813 EFI_STATUS Status;
1814 VOID *Buffer;
1815 UINT32 Length;
1816 EFI_ATA_COMMAND_BLOCK AtaCommandBlock;
1817 EFI_ATA_STATUS_BLOCK AtaStatusBlock;
1818 BOOLEAN Read;
1819 UINT8 Retry;
1820
1821 if (Packet == NULL || Packet->Cdb == NULL) {
1822 return EFI_INVALID_PARAMETER;
1823 }
1824
1825 ZeroMem (&AtaCommandBlock, sizeof (EFI_ATA_COMMAND_BLOCK));
1826 ZeroMem (&AtaStatusBlock, sizeof (EFI_ATA_STATUS_BLOCK));
1827 AtaCommandBlock.AtaCommand = ATA_CMD_PACKET;
1828 //
1829 // No OVL; No DMA
1830 //
1831 AtaCommandBlock.AtaFeatures = 0x00;
1832 //
1833 // set the transfersize to ATAPI_MAX_BYTE_COUNT to let the device
1834 // determine how many data should be transferred.
1835 //
1836 AtaCommandBlock.AtaCylinderLow = (UINT8) (ATAPI_MAX_BYTE_COUNT & 0x00ff);
1837 AtaCommandBlock.AtaCylinderHigh = (UINT8) (ATAPI_MAX_BYTE_COUNT >> 8);
1838
1839 if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ) {
1840 Buffer = Packet->InDataBuffer;
1841 Length = Packet->InTransferLength;
1842 Read = TRUE;
1843 } else {
1844 Buffer = Packet->OutDataBuffer;
1845 Length = Packet->OutTransferLength;
1846 Read = FALSE;
1847 }
1848
1849 if (Length == 0) {
1850 Status = AhciNonDataTransfer (
1851 PciIo,
1852 AhciRegisters,
1853 Port,
1854 PortMultiplier,
1855 Packet->Cdb,
1856 Packet->CdbLength,
1857 &AtaCommandBlock,
1858 &AtaStatusBlock,
1859 Packet->Timeout,
1860 NULL
1861 );
1862 } else {
1863 //
1864 // READ_CAPACITY cmd may execute failure. Retry 5 times
1865 //
1866 if (((UINT8 *)Packet->Cdb)[0] == ATA_CMD_READ_CAPACITY) {
1867 Retry = 5;
1868 } else {
1869 Retry = 1;
1870 }
1871 do {
1872 Status = AhciPioTransfer (
1873 PciIo,
1874 AhciRegisters,
1875 Port,
1876 PortMultiplier,
1877 Packet->Cdb,
1878 Packet->CdbLength,
1879 Read,
1880 &AtaCommandBlock,
1881 &AtaStatusBlock,
1882 Buffer,
1883 Length,
1884 Packet->Timeout,
1885 NULL
1886 );
1887 if (!EFI_ERROR (Status)) {
1888 break;
1889 }
1890 Retry--;
1891 } while (Retry != 0);
1892 }
1893 return Status;
1894 }
1895
1896 /**
1897 Allocate transfer-related data struct which is used at AHCI mode.
1898
1899 @param PciIo The PCI IO protocol instance.
1900 @param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
1901
1902 **/
1903 EFI_STATUS
1904 EFIAPI
1905 AhciCreateTransferDescriptor (
1906 IN EFI_PCI_IO_PROTOCOL *PciIo,
1907 IN OUT EFI_AHCI_REGISTERS *AhciRegisters
1908 )
1909 {
1910 EFI_STATUS Status;
1911 UINTN Bytes;
1912 VOID *Buffer;
1913
1914 UINT32 Capability;
1915 UINT8 MaxPortNumber;
1916 UINT8 MaxCommandSlotNumber;
1917 BOOLEAN Support64Bit;
1918 UINT64 MaxReceiveFisSize;
1919 UINT64 MaxCommandListSize;
1920 UINT64 MaxCommandTableSize;
1921 EFI_PHYSICAL_ADDRESS AhciRFisPciAddr;
1922 EFI_PHYSICAL_ADDRESS AhciCmdListPciAddr;
1923 EFI_PHYSICAL_ADDRESS AhciCommandTablePciAddr;
1924
1925 Buffer = NULL;
1926 //
1927 // Collect AHCI controller information
1928 //
1929 Capability = AhciReadReg(PciIo, EFI_AHCI_CAPABILITY_OFFSET);
1930 MaxPortNumber = (UINT8) ((Capability & 0x1F) + 1);
1931 //
1932 // Get the number of command slots per port supported by this HBA.
1933 //
1934 MaxCommandSlotNumber = (UINT8) (((Capability & 0x1F00) >> 8) + 1);
1935 Support64Bit = (BOOLEAN) (((Capability & BIT31) != 0) ? TRUE : FALSE);
1936
1937 MaxReceiveFisSize = MaxPortNumber * sizeof (EFI_AHCI_RECEIVED_FIS);
1938 Status = PciIo->AllocateBuffer (
1939 PciIo,
1940 AllocateAnyPages,
1941 EfiBootServicesData,
1942 EFI_SIZE_TO_PAGES ((UINTN) MaxReceiveFisSize),
1943 &Buffer,
1944 0
1945 );
1946
1947 if (EFI_ERROR (Status)) {
1948 return EFI_OUT_OF_RESOURCES;
1949 }
1950
1951 ZeroMem (Buffer, (UINTN)MaxReceiveFisSize);
1952
1953 AhciRegisters->AhciRFis = Buffer;
1954 AhciRegisters->MaxReceiveFisSize = MaxReceiveFisSize;
1955 Bytes = (UINTN)MaxReceiveFisSize;
1956
1957 Status = PciIo->Map (
1958 PciIo,
1959 EfiPciIoOperationBusMasterCommonBuffer,
1960 Buffer,
1961 &Bytes,
1962 &AhciRFisPciAddr,
1963 &AhciRegisters->MapRFis
1964 );
1965
1966 if (EFI_ERROR (Status) || (Bytes != MaxReceiveFisSize)) {
1967 //
1968 // Map error or unable to map the whole RFis buffer into a contiguous region.
1969 //
1970 Status = EFI_OUT_OF_RESOURCES;
1971 goto Error6;
1972 }
1973
1974 if ((!Support64Bit) && (AhciRFisPciAddr > 0x100000000ULL)) {
1975 //
1976 // The AHCI HBA doesn't support 64bit addressing, so should not get a >4G pci bus master address.
1977 //
1978 Status = EFI_DEVICE_ERROR;
1979 goto Error5;
1980 }
1981 AhciRegisters->AhciRFisPciAddr = (EFI_AHCI_RECEIVED_FIS *)(UINTN)AhciRFisPciAddr;
1982
1983 //
1984 // Allocate memory for command list
1985 // Note that the implemenation is a single task model which only use a command list for all ports.
1986 //
1987 Buffer = NULL;
1988 MaxCommandListSize = MaxCommandSlotNumber * sizeof (EFI_AHCI_COMMAND_LIST);
1989 Status = PciIo->AllocateBuffer (
1990 PciIo,
1991 AllocateAnyPages,
1992 EfiBootServicesData,
1993 EFI_SIZE_TO_PAGES ((UINTN) MaxCommandListSize),
1994 &Buffer,
1995 0
1996 );
1997
1998 if (EFI_ERROR (Status)) {
1999 //
2000 // Free mapped resource.
2001 //
2002 Status = EFI_OUT_OF_RESOURCES;
2003 goto Error5;
2004 }
2005
2006 ZeroMem (Buffer, (UINTN)MaxCommandListSize);
2007
2008 AhciRegisters->AhciCmdList = Buffer;
2009 AhciRegisters->MaxCommandListSize = MaxCommandListSize;
2010 Bytes = (UINTN)MaxCommandListSize;
2011
2012 Status = PciIo->Map (
2013 PciIo,
2014 EfiPciIoOperationBusMasterCommonBuffer,
2015 Buffer,
2016 &Bytes,
2017 &AhciCmdListPciAddr,
2018 &AhciRegisters->MapCmdList
2019 );
2020
2021 if (EFI_ERROR (Status) || (Bytes != MaxCommandListSize)) {
2022 //
2023 // Map error or unable to map the whole cmd list buffer into a contiguous region.
2024 //
2025 Status = EFI_OUT_OF_RESOURCES;
2026 goto Error4;
2027 }
2028
2029 if ((!Support64Bit) && (AhciCmdListPciAddr > 0x100000000ULL)) {
2030 //
2031 // The AHCI HBA doesn't support 64bit addressing, so should not get a >4G pci bus master address.
2032 //
2033 Status = EFI_DEVICE_ERROR;
2034 goto Error3;
2035 }
2036 AhciRegisters->AhciCmdListPciAddr = (EFI_AHCI_COMMAND_LIST *)(UINTN)AhciCmdListPciAddr;
2037
2038 //
2039 // Allocate memory for command table
2040 // According to AHCI 1.3 spec, a PRD table can contain maximum 65535 entries.
2041 //
2042 Buffer = NULL;
2043 MaxCommandTableSize = sizeof (EFI_AHCI_COMMAND_TABLE);
2044
2045 Status = PciIo->AllocateBuffer (
2046 PciIo,
2047 AllocateAnyPages,
2048 EfiBootServicesData,
2049 EFI_SIZE_TO_PAGES ((UINTN) MaxCommandTableSize),
2050 &Buffer,
2051 0
2052 );
2053
2054 if (EFI_ERROR (Status)) {
2055 //
2056 // Free mapped resource.
2057 //
2058 Status = EFI_OUT_OF_RESOURCES;
2059 goto Error3;
2060 }
2061
2062 ZeroMem (Buffer, (UINTN)MaxCommandTableSize);
2063
2064 AhciRegisters->AhciCommandTable = Buffer;
2065 AhciRegisters->MaxCommandTableSize = MaxCommandTableSize;
2066 Bytes = (UINTN)MaxCommandTableSize;
2067
2068 Status = PciIo->Map (
2069 PciIo,
2070 EfiPciIoOperationBusMasterCommonBuffer,
2071 Buffer,
2072 &Bytes,
2073 &AhciCommandTablePciAddr,
2074 &AhciRegisters->MapCommandTable
2075 );
2076
2077 if (EFI_ERROR (Status) || (Bytes != MaxCommandTableSize)) {
2078 //
2079 // Map error or unable to map the whole cmd list buffer into a contiguous region.
2080 //
2081 Status = EFI_OUT_OF_RESOURCES;
2082 goto Error2;
2083 }
2084
2085 if ((!Support64Bit) && (AhciCommandTablePciAddr > 0x100000000ULL)) {
2086 //
2087 // The AHCI HBA doesn't support 64bit addressing, so should not get a >4G pci bus master address.
2088 //
2089 Status = EFI_DEVICE_ERROR;
2090 goto Error1;
2091 }
2092 AhciRegisters->AhciCommandTablePciAddr = (EFI_AHCI_COMMAND_TABLE *)(UINTN)AhciCommandTablePciAddr;
2093
2094 return EFI_SUCCESS;
2095 //
2096 // Map error or unable to map the whole CmdList buffer into a contiguous region.
2097 //
2098 Error1:
2099 PciIo->Unmap (
2100 PciIo,
2101 AhciRegisters->MapCommandTable
2102 );
2103 Error2:
2104 PciIo->FreeBuffer (
2105 PciIo,
2106 EFI_SIZE_TO_PAGES ((UINTN) MaxCommandTableSize),
2107 AhciRegisters->AhciCommandTable
2108 );
2109 Error3:
2110 PciIo->Unmap (
2111 PciIo,
2112 AhciRegisters->MapCmdList
2113 );
2114 Error4:
2115 PciIo->FreeBuffer (
2116 PciIo,
2117 EFI_SIZE_TO_PAGES ((UINTN) MaxCommandListSize),
2118 AhciRegisters->AhciCmdList
2119 );
2120 Error5:
2121 PciIo->Unmap (
2122 PciIo,
2123 AhciRegisters->MapRFis
2124 );
2125 Error6:
2126 PciIo->FreeBuffer (
2127 PciIo,
2128 EFI_SIZE_TO_PAGES ((UINTN) MaxReceiveFisSize),
2129 AhciRegisters->AhciRFis
2130 );
2131
2132 return Status;
2133 }
2134
2135 /**
2136 Initialize ATA host controller at AHCI mode.
2137
2138 The function is designed to initialize ATA host controller.
2139
2140 @param[in] Instance A pointer to the ATA_ATAPI_PASS_THRU_INSTANCE instance.
2141
2142 **/
2143 EFI_STATUS
2144 EFIAPI
2145 AhciModeInitialization (
2146 IN ATA_ATAPI_PASS_THRU_INSTANCE *Instance
2147 )
2148 {
2149 EFI_STATUS Status;
2150 EFI_PCI_IO_PROTOCOL *PciIo;
2151 EFI_IDE_CONTROLLER_INIT_PROTOCOL *IdeInit;
2152 UINT32 Capability;
2153 UINT8 MaxPortNumber;
2154 UINT32 PortImplementBitMap;
2155 UINT8 MaxCommandSlotNumber;
2156 BOOLEAN Support64Bit;
2157
2158 EFI_AHCI_REGISTERS *AhciRegisters;
2159
2160 UINT8 Port;
2161 DATA_64 Data64;
2162 UINT32 Offset;
2163 UINT32 Data;
2164 EFI_IDENTIFY_DATA Buffer;
2165 EFI_ATA_DEVICE_TYPE DeviceType;
2166 EFI_ATA_COLLECTIVE_MODE *SupportedModes;
2167 EFI_ATA_TRANSFER_MODE TransferMode;
2168
2169 if (Instance == NULL) {
2170 return EFI_INVALID_PARAMETER;
2171 }
2172
2173 PciIo = Instance->PciIo;
2174 IdeInit = Instance->IdeControllerInit;
2175
2176 Status = AhciReset (PciIo, ATA_ATAPI_TIMEOUT);
2177
2178 if (EFI_ERROR (Status)) {
2179 return EFI_DEVICE_ERROR;
2180 }
2181
2182 //
2183 // Enable AE before accessing any AHCI registers
2184 //
2185 AhciOrReg (PciIo, EFI_AHCI_GHC_OFFSET, EFI_AHCI_GHC_ENABLE);
2186
2187 //
2188 // Collect AHCI controller information
2189 //
2190 Capability = AhciReadReg(PciIo, EFI_AHCI_CAPABILITY_OFFSET);
2191
2192 //
2193 // Get the number of command slots per port supported by this HBA.
2194 //
2195 MaxCommandSlotNumber = (UINT8) (((Capability & 0x1F00) >> 8) + 1);
2196 Support64Bit = (BOOLEAN) (((Capability & BIT31) != 0) ? TRUE : FALSE);
2197
2198 //
2199 // Get the bit map of those ports exposed by this HBA.
2200 // It indicates which ports that the HBA supports are available for software to use.
2201 //
2202 PortImplementBitMap = AhciReadReg(PciIo, EFI_AHCI_PI_OFFSET);
2203 MaxPortNumber = (UINT8) ((Capability & 0x1F) + 1);
2204
2205 AhciRegisters = &Instance->AhciRegisters;
2206 Status = AhciCreateTransferDescriptor (PciIo, AhciRegisters);
2207
2208 if (EFI_ERROR (Status)) {
2209 return EFI_OUT_OF_RESOURCES;
2210 }
2211
2212 for (Port = 0; Port < MaxPortNumber; Port ++) {
2213 Data64.Uint64 = (UINTN) (AhciRegisters->AhciRFisPciAddr) + sizeof (EFI_AHCI_RECEIVED_FIS) * Port;
2214
2215 Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_FB;
2216 AhciWriteReg (PciIo, Offset, Data64.Uint32.Lower32);
2217 Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_FBU;
2218 AhciWriteReg (PciIo, Offset, Data64.Uint32.Upper32);
2219
2220 //
2221 // Single task envrionment, we only use one command table for all port
2222 //
2223 Data64.Uint64 = (UINTN) (AhciRegisters->AhciCmdListPciAddr);
2224
2225 Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CLB;
2226 AhciWriteReg (PciIo, Offset, Data64.Uint32.Lower32);
2227 Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CLBU;
2228 AhciWriteReg (PciIo, Offset, Data64.Uint32.Upper32);
2229
2230 if ((PortImplementBitMap & (BIT0 << Port)) != 0) {
2231 Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD;
2232
2233 if ((Capability & EFI_AHCI_PORT_CMD_ASP) != 0) {
2234 AhciOrReg (PciIo, Offset, EFI_AHCI_PORT_CMD_SUD);
2235 }
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 AhciAndReg (PciIo, Offset, (UINT32)~(EFI_AHCI_PORT_CMD_FRE|EFI_AHCI_PORT_CMD_COL|EFI_AHCI_PORT_CMD_ST));
2242 }
2243
2244 Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_SCTL;
2245 AhciAndReg (PciIo, Offset, (UINT32)~(EFI_AHCI_PORT_SCTL_IPM_MASK));
2246
2247 AhciAndReg (PciIo, Offset,(UINT32) ~(EFI_AHCI_PORT_SCTL_IPM_PSD));
2248 AhciOrReg (PciIo, Offset, EFI_AHCI_PORT_SCTL_IPM_PSD);
2249
2250 AhciAndReg (PciIo, Offset, (UINT32)~(EFI_AHCI_PORT_SCTL_IPM_SSD));
2251 AhciOrReg (PciIo, Offset, EFI_AHCI_PORT_SCTL_IPM_SSD);
2252
2253 Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_IE;
2254 AhciAndReg (PciIo, Offset, 0);
2255
2256 Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_SERR;
2257 AhciWriteReg (PciIo, Offset, AhciReadReg (PciIo, Offset));
2258 }
2259
2260 //
2261 // Stall for 100 milliseconds.
2262 //
2263 MicroSecondDelay(100000);
2264
2265 IdeInit->NotifyPhase (IdeInit, EfiIdeBeforeChannelEnumeration, Port);
2266
2267 for (Port = 0; Port < MaxPortNumber; Port ++) {
2268 if ((PortImplementBitMap & (BIT0 << Port)) != 0) {
2269
2270 Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_SSTS;
2271 Data = AhciReadReg (PciIo, Offset) & EFI_AHCI_PORT_SSTS_DET_MASK;
2272
2273 if (Data == 0) {
2274 continue;
2275 }
2276 //
2277 // Found device in the port
2278 //
2279 if (Data == EFI_AHCI_PORT_SSTS_DET_PCE) {
2280 Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_SIG;
2281
2282 Status = AhciWaitMemSet (
2283 PciIo,
2284 Offset,
2285 0x0000FFFF,
2286 0x00000101,
2287 ATA_ATAPI_TIMEOUT
2288 );
2289 if (EFI_ERROR (Status)) {
2290 continue;
2291 }
2292
2293 //
2294 // Now inform the IDE Controller Init Module.
2295 //
2296 IdeInit->NotifyPhase (IdeInit, EfiIdeBusBeforeDevicePresenceDetection, Port);
2297
2298 Data = AhciReadReg (PciIo, Offset);
2299
2300 if ((Data & EFI_AHCI_ATAPI_SIG_MASK) == EFI_AHCI_ATAPI_DEVICE_SIG) {
2301 Status = AhciIdentifyPacket (PciIo, AhciRegisters, Port, 0, &Buffer);
2302
2303 if (EFI_ERROR (Status)) {
2304 continue;
2305 }
2306
2307 DeviceType = EfiIdeCdrom;
2308 } else if ((Data & EFI_AHCI_ATAPI_SIG_MASK) == EFI_AHCI_ATA_DEVICE_SIG) {
2309 Status = AhciIdentify (PciIo, AhciRegisters, Port, 0, &Buffer);
2310
2311 if (EFI_ERROR (Status)) {
2312 continue;
2313 }
2314
2315 DeviceType = EfiIdeHarddisk;
2316 } else {
2317 continue;
2318 }
2319
2320 DEBUG ((EFI_D_INFO, "port [%d] port mulitplier [%d] has a [%a]\n",
2321 Port, 0, DeviceType == EfiIdeCdrom ? "cdrom" : "harddisk"));
2322
2323 //
2324 // If the device is a hard disk, then try to enable S.M.A.R.T feature
2325 //
2326 if (DeviceType == EfiIdeHarddisk) {
2327 AhciAtaSmartSupport (
2328 PciIo,
2329 AhciRegisters,
2330 Port,
2331 0,
2332 &Buffer,
2333 NULL
2334 );
2335 }
2336
2337 //
2338 // Submit identify data to IDE controller init driver
2339 //
2340 IdeInit->SubmitData (IdeInit, Port, 0, &Buffer);
2341
2342 //
2343 // Now start to config ide device parameter and transfer mode.
2344 //
2345 Status = IdeInit->CalculateMode (
2346 IdeInit,
2347 Port,
2348 0,
2349 &SupportedModes
2350 );
2351 if (EFI_ERROR (Status)) {
2352 DEBUG ((EFI_D_ERROR, "Calculate Mode Fail, Status = %r\n", Status));
2353 continue;
2354 }
2355
2356 //
2357 // Set best supported PIO mode on this IDE device
2358 //
2359 if (SupportedModes->PioMode.Mode <= EfiAtaPioMode2) {
2360 TransferMode.ModeCategory = EFI_ATA_MODE_DEFAULT_PIO;
2361 } else {
2362 TransferMode.ModeCategory = EFI_ATA_MODE_FLOW_PIO;
2363 }
2364
2365 TransferMode.ModeNumber = (UINT8) (SupportedModes->PioMode.Mode);
2366
2367 //
2368 // Set supported DMA mode on this IDE device. Note that UDMA & MDMA cann't
2369 // be set together. Only one DMA mode can be set to a device. If setting
2370 // DMA mode operation fails, we can continue moving on because we only use
2371 // PIO mode at boot time. DMA modes are used by certain kind of OS booting
2372 //
2373 if (SupportedModes->UdmaMode.Valid) {
2374 TransferMode.ModeCategory = EFI_ATA_MODE_UDMA;
2375 TransferMode.ModeNumber = (UINT8) (SupportedModes->UdmaMode.Mode);
2376 } else if (SupportedModes->MultiWordDmaMode.Valid) {
2377 TransferMode.ModeCategory = EFI_ATA_MODE_MDMA;
2378 TransferMode.ModeNumber = (UINT8) SupportedModes->MultiWordDmaMode.Mode;
2379 }
2380
2381 Status = AhciDeviceSetFeature (PciIo, AhciRegisters, Port, 0, 0x03, (UINT32)(*(UINT8 *)&TransferMode));
2382
2383 if (EFI_ERROR (Status)) {
2384 DEBUG ((EFI_D_ERROR, "Set transfer Mode Fail, Status = %r\n", Status));
2385 continue;
2386 }
2387 //
2388 // Found a ATA or ATAPI device, add it into the device list.
2389 //
2390 CreateNewDeviceInfo (Instance, Port, 0, DeviceType, &Buffer);
2391 }
2392 }
2393 }
2394 return EFI_SUCCESS;
2395 }
2396