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