]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Bus/Ata/AhciPei/AhciMode.c
MdeModulePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / MdeModulePkg / Bus / Ata / AhciPei / AhciMode.c
1 /** @file
2 The AhciPei driver is used to manage ATA hard disk device working under AHCI
3 mode at PEI phase.
4
5 Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
6
7 SPDX-License-Identifier: BSD-2-Clause-Patent
8
9 **/
10
11 #include "AhciPei.h"
12
13 #define ATA_CMD_TRUST_NON_DATA 0x5B
14 #define ATA_CMD_TRUST_RECEIVE 0x5C
15 #define ATA_CMD_TRUST_SEND 0x5E
16
17 //
18 // Look up table (IsWrite) for EFI_ATA_PASS_THRU_CMD_PROTOCOL
19 //
20 EFI_ATA_PASS_THRU_CMD_PROTOCOL mAtaPassThruCmdProtocols[2] = {
21 EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_IN,
22 EFI_ATA_PASS_THRU_PROTOCOL_PIO_DATA_OUT
23 };
24
25 //
26 // Look up table (Lba48Bit, IsIsWrite) for ATA_CMD
27 //
28 UINT8 mAtaCommands[2][2] = {
29 {
30 ATA_CMD_READ_SECTORS, // 28-bit LBA; PIO read
31 ATA_CMD_WRITE_SECTORS // 28-bit LBA; PIO write
32 },
33 {
34 ATA_CMD_READ_SECTORS_EXT, // 48-bit LBA; PIO read
35 ATA_CMD_WRITE_SECTORS_EXT // 48-bit LBA; PIO write
36 }
37 };
38
39 //
40 // Look up table (IsTrustSend) for ATA_CMD
41 //
42 UINT8 mAtaTrustCommands[2] = {
43 ATA_CMD_TRUST_RECEIVE, // PIO read
44 ATA_CMD_TRUST_SEND // PIO write
45 };
46
47 //
48 // Look up table (Lba48Bit) for maximum transfer block number
49 //
50 #define MAX_28BIT_TRANSFER_BLOCK_NUM 0x100
51 #define MAX_48BIT_TRANSFER_BLOCK_NUM 0xFFFF
52
53 UINT32 mMaxTransferBlockNumber[2] = {
54 MAX_28BIT_TRANSFER_BLOCK_NUM,
55 MAX_48BIT_TRANSFER_BLOCK_NUM
56 };
57
58 //
59 // The maximum total sectors count in 28 bit addressing mode
60 //
61 #define MAX_28BIT_ADDRESSING_CAPACITY 0xfffffff
62
63
64 /**
65 Read AHCI Operation register.
66
67 @param[in] AhciBar AHCI bar address.
68 @param[in] Offset The operation register offset.
69
70 @return The register content read.
71
72 **/
73 UINT32
74 AhciReadReg (
75 IN UINTN AhciBar,
76 IN UINT32 Offset
77 )
78 {
79 UINT32 Data;
80
81 Data = 0;
82 Data = MmioRead32 (AhciBar + Offset);
83
84 return Data;
85 }
86
87 /**
88 Write AHCI Operation register.
89
90 @param[in] AhciBar AHCI bar address.
91 @param[in] Offset The operation register offset.
92 @param[in] Data The Data used to write down.
93
94 **/
95 VOID
96 AhciWriteReg (
97 IN UINTN AhciBar,
98 IN UINT32 Offset,
99 IN UINT32 Data
100 )
101 {
102 MmioWrite32 (AhciBar + Offset, Data);
103 }
104
105 /**
106 Do AND operation with the value of AHCI Operation register.
107
108 @param[in] AhciBar AHCI bar address.
109 @param[in] Offset The operation register offset.
110 @param[in] AndData The data used to do AND operation.
111
112 **/
113 VOID
114 AhciAndReg (
115 IN UINTN AhciBar,
116 IN UINT32 Offset,
117 IN UINT32 AndData
118 )
119 {
120 UINT32 Data;
121
122 Data = AhciReadReg (AhciBar, Offset);
123 Data &= AndData;
124
125 AhciWriteReg (AhciBar, Offset, Data);
126 }
127
128 /**
129 Do OR operation with the Value of AHCI Operation register.
130
131 @param[in] AhciBar AHCI bar address.
132 @param[in] Offset The operation register offset.
133 @param[in] OrData The Data used to do OR operation.
134
135 **/
136 VOID
137 AhciOrReg (
138 IN UINTN AhciBar,
139 IN UINT32 Offset,
140 IN UINT32 OrData
141 )
142 {
143 UINT32 Data;
144
145 Data = AhciReadReg (AhciBar, Offset);
146 Data |= OrData;
147
148 AhciWriteReg (AhciBar, Offset, Data);
149 }
150
151 /**
152 Wait for memory set to the test Value.
153
154 @param[in] AhciBar AHCI bar address.
155 @param[in] Offset The memory offset to test.
156 @param[in] MaskValue The mask Value of memory.
157 @param[in] TestValue The test Value of memory.
158 @param[in] Timeout The timeout, in 100ns units, for wait memory set.
159
160 @retval EFI_DEVICE_ERROR The memory is not set.
161 @retval EFI_TIMEOUT The memory setting is time out.
162 @retval EFI_SUCCESS The memory is correct set.
163
164 **/
165 EFI_STATUS
166 EFIAPI
167 AhciWaitMmioSet (
168 IN UINTN AhciBar,
169 IN UINT32 Offset,
170 IN UINT32 MaskValue,
171 IN UINT32 TestValue,
172 IN UINT64 Timeout
173 )
174 {
175 UINT32 Value;
176 UINT32 Delay;
177
178 Delay = (UINT32) (DivU64x32(Timeout, 1000) + 1);
179
180 do {
181 Value = AhciReadReg (AhciBar, Offset) & MaskValue;
182
183 if (Value == TestValue) {
184 return EFI_SUCCESS;
185 }
186
187 //
188 // Stall for 100 microseconds.
189 //
190 MicroSecondDelay (100);
191
192 Delay--;
193
194 } while (Delay > 0);
195
196 return EFI_TIMEOUT;
197 }
198
199 /**
200 Check the memory status to the test value.
201
202 @param[in] Address The memory address to test.
203 @param[in] MaskValue The mask value of memory.
204 @param[in] TestValue The test value of memory.
205
206 @retval EFI_NOT_READY The memory is not set.
207 @retval EFI_SUCCESS The memory is correct set.
208
209 **/
210 EFI_STATUS
211 AhciCheckMemSet (
212 IN UINTN Address,
213 IN UINT32 MaskValue,
214 IN UINT32 TestValue
215 )
216 {
217 UINT32 Value;
218
219 Value = *(volatile UINT32 *) Address;
220 Value &= MaskValue;
221
222 if (Value == TestValue) {
223 return EFI_SUCCESS;
224 } else {
225 return EFI_NOT_READY;
226 }
227 }
228
229 /**
230 Wait for the value of the specified system memory set to the test value.
231
232 @param[in] Address The system memory address to test.
233 @param[in] MaskValue The mask value of memory.
234 @param[in] TestValue The test value of memory.
235 @param[in] Timeout The timeout, in 100ns units, for wait memory set.
236
237 @retval EFI_TIMEOUT The system memory setting is time out.
238 @retval EFI_SUCCESS The system memory is correct set.
239
240 **/
241 EFI_STATUS
242 AhciWaitMemSet (
243 IN EFI_PHYSICAL_ADDRESS Address,
244 IN UINT32 MaskValue,
245 IN UINT32 TestValue,
246 IN UINT64 Timeout
247 )
248 {
249 UINT32 Value;
250 UINT64 Delay;
251 BOOLEAN InfiniteWait;
252
253 if (Timeout == 0) {
254 InfiniteWait = TRUE;
255 } else {
256 InfiniteWait = FALSE;
257 }
258
259 Delay = DivU64x32 (Timeout, 1000) + 1;
260
261 do {
262 //
263 // Access sytem memory to see if the value is the tested one.
264 //
265 // The system memory pointed by Address will be updated by the
266 // SATA Host Controller, "volatile" is introduced to prevent
267 // compiler from optimizing the access to the memory address
268 // to only read once.
269 //
270 Value = *(volatile UINT32 *) (UINTN) Address;
271 Value &= MaskValue;
272
273 if (Value == TestValue) {
274 return EFI_SUCCESS;
275 }
276
277 //
278 // Stall for 100 microseconds.
279 //
280 MicroSecondDelay (100);
281
282 Delay--;
283
284 } while (InfiniteWait || (Delay > 0));
285
286 return EFI_TIMEOUT;
287 }
288
289 /**
290
291 Clear the port interrupt and error status. It will also clear HBA interrupt
292 status.
293
294 @param[in] AhciBar AHCI bar address.
295 @param[in] Port The number of port.
296
297 **/
298 VOID
299 AhciClearPortStatus (
300 IN UINTN AhciBar,
301 IN UINT8 Port
302 )
303 {
304 UINT32 Offset;
305
306 //
307 // Clear any error status
308 //
309 Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_SERR;
310 AhciWriteReg (AhciBar, Offset, AhciReadReg (AhciBar, Offset));
311
312 //
313 // Clear any port interrupt status
314 //
315 Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_IS;
316 AhciWriteReg (AhciBar, Offset, AhciReadReg (AhciBar, Offset));
317
318 //
319 // Clear any HBA interrupt status
320 //
321 AhciWriteReg (AhciBar, AHCI_IS_OFFSET, AhciReadReg (AhciBar, AHCI_IS_OFFSET));
322 }
323
324 /**
325 Enable the FIS running for giving port.
326
327 @param[in] AhciBar AHCI bar address.
328 @param[in] Port The number of port.
329 @param[in] Timeout The timeout, in 100ns units, to enabling FIS.
330
331 @retval EFI_DEVICE_ERROR The FIS enable setting fails.
332 @retval EFI_TIMEOUT The FIS enable setting is time out.
333 @retval EFI_SUCCESS The FIS enable successfully.
334
335 **/
336 EFI_STATUS
337 AhciEnableFisReceive (
338 IN UINTN AhciBar,
339 IN UINT8 Port,
340 IN UINT64 Timeout
341 )
342 {
343 UINT32 Offset;
344
345 Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_CMD;
346 AhciOrReg (AhciBar, Offset, AHCI_PORT_CMD_FRE);
347
348 return EFI_SUCCESS;
349 }
350
351 /**
352 Disable the FIS running for giving port.
353
354 @param[in] AhciBar AHCI bar address.
355 @param[in] Port The number of port.
356 @param[in] Timeout The timeout value of disabling FIS, uses 100ns as a unit.
357
358 @retval EFI_DEVICE_ERROR The FIS disable setting fails.
359 @retval EFI_TIMEOUT The FIS disable setting is time out.
360 @retval EFI_UNSUPPORTED The port is in running state.
361 @retval EFI_SUCCESS The FIS disable successfully.
362
363 **/
364 EFI_STATUS
365 AhciDisableFisReceive (
366 IN UINTN AhciBar,
367 IN UINT8 Port,
368 IN UINT64 Timeout
369 )
370 {
371 UINT32 Offset;
372 UINT32 Data;
373
374 Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_CMD;
375 Data = AhciReadReg (AhciBar, Offset);
376
377 //
378 // Before disabling Fis receive, the DMA engine of the port should NOT be in
379 // running status.
380 //
381 if ((Data & (AHCI_PORT_CMD_ST | AHCI_PORT_CMD_CR)) != 0) {
382 return EFI_UNSUPPORTED;
383 }
384
385 //
386 // Check if the Fis receive DMA engine for the port is running.
387 //
388 if ((Data & AHCI_PORT_CMD_FR) != AHCI_PORT_CMD_FR) {
389 return EFI_SUCCESS;
390 }
391
392 AhciAndReg (AhciBar, Offset, (UINT32)~(AHCI_PORT_CMD_FRE));
393
394 return AhciWaitMmioSet (
395 AhciBar,
396 Offset,
397 AHCI_PORT_CMD_FR,
398 0,
399 Timeout
400 );
401 }
402
403 /**
404 Build the command list, command table and prepare the fis receiver.
405
406 @param[in] Private The pointer to the PEI_AHCI_CONTROLLER_PRIVATE_DATA.
407 @param[in] Port The number of port.
408 @param[in] PortMultiplier The number of port multiplier.
409 @param[in] FisIndex The offset index of the FIS base address.
410 @param[in] CommandFis The control fis will be used for the transfer.
411 @param[in] CommandList The command list will be used for the transfer.
412 @param[in] CommandSlotNumber The command slot will be used for the transfer.
413 @param[in,out] DataPhysicalAddr The pointer to the data buffer pci bus master
414 address.
415 @param[in] DataLength The data count to be transferred.
416
417 **/
418 VOID
419 AhciBuildCommand (
420 IN PEI_AHCI_CONTROLLER_PRIVATE_DATA *Private,
421 IN UINT8 Port,
422 IN UINT8 PortMultiplier,
423 IN UINT8 FisIndex,
424 IN EFI_AHCI_COMMAND_FIS *CommandFis,
425 IN EFI_AHCI_COMMAND_LIST *CommandList,
426 IN UINT8 CommandSlotNumber,
427 IN OUT VOID *DataPhysicalAddr,
428 IN UINT32 DataLength
429 )
430 {
431 EFI_AHCI_REGISTERS *AhciRegisters;
432 UINTN AhciBar;
433 UINT64 BaseAddr;
434 UINT32 PrdtNumber;
435 UINT32 PrdtIndex;
436 UINTN RemainedData;
437 UINTN MemAddr;
438 DATA_64 Data64;
439 UINT32 Offset;
440
441 AhciRegisters = &Private->AhciRegisters;
442 AhciBar = Private->MmioBase;
443
444 //
445 // Filling the PRDT
446 //
447 PrdtNumber = (UINT32)DivU64x32 (
448 (UINT64)DataLength + AHCI_MAX_DATA_PER_PRDT - 1,
449 AHCI_MAX_DATA_PER_PRDT
450 );
451
452 //
453 // According to AHCI 1.3 spec, a PRDT entry can point to a maximum 4MB data block.
454 // It also limits that the maximum amount of the PRDT entry in the command table
455 // is 65535.
456 // Current driver implementation supports up to a maximum of AHCI_MAX_PRDT_NUMBER
457 // PRDT entries.
458 //
459 ASSERT (PrdtNumber <= AHCI_MAX_PRDT_NUMBER);
460 if (PrdtNumber > AHCI_MAX_PRDT_NUMBER) {
461 return;
462 }
463
464 Data64.Uint64 = (UINTN) (AhciRegisters->AhciRFis) + sizeof (EFI_AHCI_RECEIVED_FIS) * FisIndex;
465
466 BaseAddr = Data64.Uint64;
467
468 ZeroMem ((VOID *)((UINTN) BaseAddr), sizeof (EFI_AHCI_RECEIVED_FIS));
469
470 ZeroMem (AhciRegisters->AhciCmdTable, sizeof (EFI_AHCI_COMMAND_TABLE));
471
472 CommandFis->AhciCFisPmNum = PortMultiplier;
473
474 CopyMem (&AhciRegisters->AhciCmdTable->CommandFis, CommandFis, sizeof (EFI_AHCI_COMMAND_FIS));
475
476 Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_CMD;
477 AhciAndReg (AhciBar, Offset, (UINT32)~(AHCI_PORT_CMD_DLAE | AHCI_PORT_CMD_ATAPI));
478
479 RemainedData = (UINTN) DataLength;
480 MemAddr = (UINTN) DataPhysicalAddr;
481 CommandList->AhciCmdPrdtl = PrdtNumber;
482
483 for (PrdtIndex = 0; PrdtIndex < PrdtNumber; PrdtIndex++) {
484 if (RemainedData < AHCI_MAX_DATA_PER_PRDT) {
485 AhciRegisters->AhciCmdTable->PrdtTable[PrdtIndex].AhciPrdtDbc = (UINT32)RemainedData - 1;
486 } else {
487 AhciRegisters->AhciCmdTable->PrdtTable[PrdtIndex].AhciPrdtDbc = AHCI_MAX_DATA_PER_PRDT - 1;
488 }
489
490 Data64.Uint64 = (UINT64)MemAddr;
491 AhciRegisters->AhciCmdTable->PrdtTable[PrdtIndex].AhciPrdtDba = Data64.Uint32.Lower32;
492 AhciRegisters->AhciCmdTable->PrdtTable[PrdtIndex].AhciPrdtDbau = Data64.Uint32.Upper32;
493 RemainedData -= AHCI_MAX_DATA_PER_PRDT;
494 MemAddr += AHCI_MAX_DATA_PER_PRDT;
495 }
496
497 //
498 // Set the last PRDT to Interrupt On Complete
499 //
500 if (PrdtNumber > 0) {
501 AhciRegisters->AhciCmdTable->PrdtTable[PrdtNumber - 1].AhciPrdtIoc = 1;
502 }
503
504 CopyMem (
505 (VOID *) ((UINTN) AhciRegisters->AhciCmdList + (UINTN) CommandSlotNumber * sizeof (EFI_AHCI_COMMAND_LIST)),
506 CommandList,
507 sizeof (EFI_AHCI_COMMAND_LIST)
508 );
509
510 Data64.Uint64 = (UINT64)(UINTN) AhciRegisters->AhciCmdTable;
511 AhciRegisters->AhciCmdList[CommandSlotNumber].AhciCmdCtba = Data64.Uint32.Lower32;
512 AhciRegisters->AhciCmdList[CommandSlotNumber].AhciCmdCtbau = Data64.Uint32.Upper32;
513 AhciRegisters->AhciCmdList[CommandSlotNumber].AhciCmdPmp = PortMultiplier;
514 }
515
516 /**
517 Buid a command FIS.
518
519 @param[in,out] CmdFis A pointer to the EFI_AHCI_COMMAND_FIS data
520 structure.
521 @param[in] AtaCommandBlock A pointer to the EFI_ATA_COMMAND_BLOCK data
522 structure.
523
524 **/
525 VOID
526 AhciBuildCommandFis (
527 IN OUT EFI_AHCI_COMMAND_FIS *CmdFis,
528 IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock
529 )
530 {
531 ZeroMem (CmdFis, sizeof (EFI_AHCI_COMMAND_FIS));
532
533 CmdFis->AhciCFisType = AHCI_FIS_REGISTER_H2D;
534 //
535 // Indicator it's a command
536 //
537 CmdFis->AhciCFisCmdInd = 0x1;
538 CmdFis->AhciCFisCmd = AtaCommandBlock->AtaCommand;
539
540 CmdFis->AhciCFisFeature = AtaCommandBlock->AtaFeatures;
541 CmdFis->AhciCFisFeatureExp = AtaCommandBlock->AtaFeaturesExp;
542
543 CmdFis->AhciCFisSecNum = AtaCommandBlock->AtaSectorNumber;
544 CmdFis->AhciCFisSecNumExp = AtaCommandBlock->AtaSectorNumberExp;
545
546 CmdFis->AhciCFisClyLow = AtaCommandBlock->AtaCylinderLow;
547 CmdFis->AhciCFisClyLowExp = AtaCommandBlock->AtaCylinderLowExp;
548
549 CmdFis->AhciCFisClyHigh = AtaCommandBlock->AtaCylinderHigh;
550 CmdFis->AhciCFisClyHighExp = AtaCommandBlock->AtaCylinderHighExp;
551
552 CmdFis->AhciCFisSecCount = AtaCommandBlock->AtaSectorCount;
553 CmdFis->AhciCFisSecCountExp = AtaCommandBlock->AtaSectorCountExp;
554
555 CmdFis->AhciCFisDevHead = (UINT8) (AtaCommandBlock->AtaDeviceHead | 0xE0);
556 }
557
558 /**
559 Stop command running for giving port
560
561 @param[in] AhciBar AHCI bar address.
562 @param[in] Port The number of port.
563 @param[in] Timeout The timeout value, in 100ns units, to stop.
564
565 @retval EFI_DEVICE_ERROR The command stop unsuccessfully.
566 @retval EFI_TIMEOUT The operation is time out.
567 @retval EFI_SUCCESS The command stop successfully.
568
569 **/
570 EFI_STATUS
571 AhciStopCommand (
572 IN UINTN AhciBar,
573 IN UINT8 Port,
574 IN UINT64 Timeout
575 )
576 {
577 UINT32 Offset;
578 UINT32 Data;
579
580 Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_CMD;
581 Data = AhciReadReg (AhciBar, Offset);
582
583 if ((Data & (AHCI_PORT_CMD_ST | AHCI_PORT_CMD_CR)) == 0) {
584 return EFI_SUCCESS;
585 }
586
587 if ((Data & AHCI_PORT_CMD_ST) != 0) {
588 AhciAndReg (AhciBar, Offset, (UINT32)~(AHCI_PORT_CMD_ST));
589 }
590
591 return AhciWaitMmioSet (
592 AhciBar,
593 Offset,
594 AHCI_PORT_CMD_CR,
595 0,
596 Timeout
597 );
598 }
599
600 /**
601 Start command for give slot on specific port.
602
603 @param[in] AhciBar AHCI bar address.
604 @param[in] Port The number of port.
605 @param[in] CommandSlot The number of Command Slot.
606 @param[in] Timeout The timeout value, in 100ns units, to start.
607
608 @retval EFI_DEVICE_ERROR The command start unsuccessfully.
609 @retval EFI_TIMEOUT The operation is time out.
610 @retval EFI_SUCCESS The command start successfully.
611
612 **/
613 EFI_STATUS
614 AhciStartCommand (
615 IN UINTN AhciBar,
616 IN UINT8 Port,
617 IN UINT8 CommandSlot,
618 IN UINT64 Timeout
619 )
620 {
621 UINT32 CmdSlotBit;
622 EFI_STATUS Status;
623 UINT32 PortStatus;
624 UINT32 StartCmd;
625 UINT32 PortTfd;
626 UINT32 Offset;
627 UINT32 Capability;
628
629 //
630 // Collect AHCI controller information
631 //
632 Capability = AhciReadReg (AhciBar, AHCI_CAPABILITY_OFFSET);
633
634 CmdSlotBit = (UINT32) (1 << CommandSlot);
635
636 AhciClearPortStatus (
637 AhciBar,
638 Port
639 );
640
641 Status = AhciEnableFisReceive (
642 AhciBar,
643 Port,
644 Timeout
645 );
646 if (EFI_ERROR (Status)) {
647 return Status;
648 }
649
650 Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_CMD;
651 PortStatus = AhciReadReg (AhciBar, Offset);
652
653 StartCmd = 0;
654 if ((PortStatus & AHCI_PORT_CMD_ALPE) != 0) {
655 StartCmd = AhciReadReg (AhciBar, Offset);
656 StartCmd &= ~AHCI_PORT_CMD_ICC_MASK;
657 StartCmd |= AHCI_PORT_CMD_ACTIVE;
658 }
659
660 Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_TFD;
661 PortTfd = AhciReadReg (AhciBar, Offset);
662
663 if ((PortTfd & (AHCI_PORT_TFD_BSY | AHCI_PORT_TFD_DRQ)) != 0) {
664 if ((Capability & BIT24) != 0) {
665 Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_CMD;
666 AhciOrReg (AhciBar, Offset, AHCI_PORT_CMD_CLO);
667
668 AhciWaitMmioSet (
669 AhciBar,
670 Offset,
671 AHCI_PORT_CMD_CLO,
672 0,
673 Timeout
674 );
675 }
676 }
677
678 Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_CMD;
679 AhciOrReg (AhciBar, Offset, AHCI_PORT_CMD_ST | StartCmd);
680
681 //
682 // Setting the command
683 //
684 Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_CI;
685 AhciAndReg (AhciBar, Offset, 0);
686 AhciOrReg (AhciBar, Offset, CmdSlotBit);
687
688 return EFI_SUCCESS;
689 }
690
691 /**
692 Start a PIO Data transfer on specific port.
693
694 @param[in] Private The pointer to the PEI_AHCI_CONTROLLER_PRIVATE_DATA.
695 @param[in] Port The number of port.
696 @param[in] PortMultiplier The number of port multiplier.
697 @param[in] FisIndex The offset index of the FIS base address.
698 @param[in] Read The transfer direction.
699 @param[in] AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.
700 @param[in,out] AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.
701 @param[in,out] MemoryAddr The pointer to the data buffer.
702 @param[in] DataCount The data count to be transferred.
703 @param[in] Timeout The timeout value of PIO data transfer, uses
704 100ns as a unit.
705
706 @retval EFI_DEVICE_ERROR The PIO data transfer abort with error occurs.
707 @retval EFI_TIMEOUT The operation is time out.
708 @retval EFI_UNSUPPORTED The device is not ready for transfer.
709 @retval EFI_OUT_OF_RESOURCES The operation fails due to lack of resources.
710 @retval EFI_SUCCESS The PIO data transfer executes successfully.
711
712 **/
713 EFI_STATUS
714 AhciPioTransfer (
715 IN PEI_AHCI_CONTROLLER_PRIVATE_DATA *Private,
716 IN UINT8 Port,
717 IN UINT8 PortMultiplier,
718 IN UINT8 FisIndex,
719 IN BOOLEAN Read,
720 IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock,
721 IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock,
722 IN OUT VOID *MemoryAddr,
723 IN UINT32 DataCount,
724 IN UINT64 Timeout
725 )
726 {
727 EFI_STATUS Status;
728 EDKII_IOMMU_OPERATION MapOp;
729 UINTN MapLength;
730 EFI_PHYSICAL_ADDRESS PhyAddr;
731 VOID *MapData;
732 EFI_AHCI_REGISTERS *AhciRegisters;
733 UINTN AhciBar;
734 BOOLEAN InfiniteWait;
735 UINT32 Offset;
736 UINT32 OldRfisLo;
737 UINT32 OldRfisHi;
738 UINT32 OldCmdListLo;
739 UINT32 OldCmdListHi;
740 DATA_64 Data64;
741 UINT32 FisBaseAddr;
742 UINT32 Delay;
743 EFI_AHCI_COMMAND_FIS CFis;
744 EFI_AHCI_COMMAND_LIST CmdList;
745 UINT32 PortTfd;
746 UINT32 PrdCount;
747 BOOLEAN PioFisReceived;
748 BOOLEAN D2hFisReceived;
749
750 //
751 // Current driver implementation supports up to a maximum of AHCI_MAX_PRDT_NUMBER
752 // PRDT entries.
753 //
754 if (DataCount / (UINT32)AHCI_MAX_PRDT_NUMBER > AHCI_MAX_DATA_PER_PRDT) {
755 DEBUG ((
756 DEBUG_ERROR,
757 "%a: Driver only support a maximum of 0x%x PRDT entries, "
758 "current number of data byte 0x%x is too large, maximum allowed is 0x%x.\n",
759 __FUNCTION__, AHCI_MAX_PRDT_NUMBER, DataCount,
760 AHCI_MAX_PRDT_NUMBER * AHCI_MAX_DATA_PER_PRDT
761 ));
762 return EFI_UNSUPPORTED;
763 }
764
765 MapOp = Read ? EdkiiIoMmuOperationBusMasterWrite :
766 EdkiiIoMmuOperationBusMasterRead;
767 MapLength = DataCount;
768 Status = IoMmuMap (
769 MapOp,
770 MemoryAddr,
771 &MapLength,
772 &PhyAddr,
773 &MapData
774 );
775 if (EFI_ERROR (Status) || (MapLength != DataCount)) {
776 DEBUG ((DEBUG_ERROR, "%a: Fail to map data buffer.\n", __FUNCTION__));
777 return EFI_OUT_OF_RESOURCES;
778 }
779
780 AhciRegisters = &Private->AhciRegisters;
781 AhciBar = Private->MmioBase;
782 InfiniteWait = (Timeout == 0) ? TRUE : FALSE;
783
784 //
785 // Fill FIS base address register
786 //
787 Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_FB;
788 OldRfisLo = AhciReadReg (AhciBar, Offset);
789 Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_FBU;
790 OldRfisHi = AhciReadReg (AhciBar, Offset);
791 Data64.Uint64 = (UINTN) (AhciRegisters->AhciRFis) + sizeof (EFI_AHCI_RECEIVED_FIS) * FisIndex;
792 Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_FB;
793 AhciWriteReg (AhciBar, Offset, Data64.Uint32.Lower32);
794 Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_FBU;
795 AhciWriteReg (AhciBar, Offset, Data64.Uint32.Upper32);
796
797 //
798 // Single task envrionment, we only use one command table for all port
799 //
800 Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_CLB;
801 OldCmdListLo = AhciReadReg (AhciBar, Offset);
802 Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_CLBU;
803 OldCmdListHi = AhciReadReg (AhciBar, Offset);
804 Data64.Uint64 = (UINTN) (AhciRegisters->AhciCmdList);
805 Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_CLB;
806 AhciWriteReg (AhciBar, Offset, Data64.Uint32.Lower32);
807 Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_CLBU;
808 AhciWriteReg (AhciBar, Offset, Data64.Uint32.Upper32);
809
810 //
811 // Package read needed
812 //
813 AhciBuildCommandFis (&CFis, AtaCommandBlock);
814
815 ZeroMem (&CmdList, sizeof (EFI_AHCI_COMMAND_LIST));
816
817 CmdList.AhciCmdCfl = AHCI_FIS_REGISTER_H2D_LENGTH / 4;
818 CmdList.AhciCmdW = Read ? 0 : 1;
819
820 AhciBuildCommand (
821 Private,
822 Port,
823 PortMultiplier,
824 FisIndex,
825 &CFis,
826 &CmdList,
827 0,
828 (VOID *)(UINTN)PhyAddr,
829 DataCount
830 );
831
832 Status = AhciStartCommand (
833 AhciBar,
834 Port,
835 0,
836 Timeout
837 );
838 if (EFI_ERROR (Status)) {
839 goto Exit;
840 }
841
842 //
843 // Checking the status and wait the driver sending Data
844 //
845 FisBaseAddr = (UINT32)(UINTN)AhciRegisters->AhciRFis + sizeof (EFI_AHCI_RECEIVED_FIS) * FisIndex;
846 if (Read) {
847 //
848 // Wait device sends the PIO setup fis before data transfer
849 //
850 Status = EFI_TIMEOUT;
851 Delay = (UINT32) DivU64x32 (Timeout, 1000) + 1;
852 do {
853 PioFisReceived = FALSE;
854 D2hFisReceived = FALSE;
855 Offset = FisBaseAddr + AHCI_PIO_FIS_OFFSET;
856 Status = AhciCheckMemSet (Offset, AHCI_FIS_TYPE_MASK, AHCI_FIS_PIO_SETUP);
857 if (!EFI_ERROR (Status)) {
858 DEBUG ((DEBUG_INFO, "%a: PioFisReceived.\n", __FUNCTION__));
859 PioFisReceived = TRUE;
860 }
861 //
862 // According to SATA 2.6 spec section 11.7, D2h FIS means an error encountered.
863 // But Qemu and Marvel 9230 sata controller may just receive a D2h FIS from
864 // device after the transaction is finished successfully.
865 // To get better device compatibilities, we further check if the PxTFD's
866 // ERR bit is set. By this way, we can know if there is a real error happened.
867 //
868 Offset = FisBaseAddr + AHCI_D2H_FIS_OFFSET;
869 Status = AhciCheckMemSet (Offset, AHCI_FIS_TYPE_MASK, AHCI_FIS_REGISTER_D2H);
870 if (!EFI_ERROR (Status)) {
871 DEBUG ((DEBUG_INFO, "%a: D2hFisReceived.\n", __FUNCTION__));
872 D2hFisReceived = TRUE;
873 }
874
875 if (PioFisReceived || D2hFisReceived) {
876 Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_TFD;
877 PortTfd = AhciReadReg (AhciBar, (UINT32) Offset);
878 //
879 // PxTFD will be updated if there is a D2H or SetupFIS received.
880 //
881 if ((PortTfd & AHCI_PORT_TFD_ERR) != 0) {
882 Status = EFI_DEVICE_ERROR;
883 break;
884 }
885
886 PrdCount = *(volatile UINT32 *) (&(AhciRegisters->AhciCmdList[0].AhciCmdPrdbc));
887 if (PrdCount == DataCount) {
888 Status = EFI_SUCCESS;
889 break;
890 }
891 }
892
893 //
894 // Stall for 100 microseconds.
895 //
896 MicroSecondDelay(100);
897
898 Delay--;
899 if (Delay == 0) {
900 Status = EFI_TIMEOUT;
901 }
902 } while (InfiniteWait || (Delay > 0));
903 } else {
904 //
905 // Wait for D2H Fis is received
906 //
907 Offset = FisBaseAddr + AHCI_D2H_FIS_OFFSET;
908 Status = AhciWaitMemSet (
909 Offset,
910 AHCI_FIS_TYPE_MASK,
911 AHCI_FIS_REGISTER_D2H,
912 Timeout
913 );
914 if (EFI_ERROR (Status)) {
915 DEBUG ((DEBUG_ERROR, "%a: AhciWaitMemSet (%r)\n", __FUNCTION__, Status));
916 goto Exit;
917 }
918
919 Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_TFD;
920 PortTfd = AhciReadReg (AhciBar, (UINT32) Offset);
921 if ((PortTfd & AHCI_PORT_TFD_ERR) != 0) {
922 Status = EFI_DEVICE_ERROR;
923 }
924 }
925
926 Exit:
927 AhciStopCommand (
928 AhciBar,
929 Port,
930 Timeout
931 );
932
933 AhciDisableFisReceive (
934 AhciBar,
935 Port,
936 Timeout
937 );
938
939 if (MapData != NULL) {
940 IoMmuUnmap (MapData);
941 }
942
943 Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_FB;
944 AhciWriteReg (AhciBar, Offset, OldRfisLo);
945 Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_FBU;
946 AhciWriteReg (AhciBar, Offset, OldRfisHi);
947
948 Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_CLB;
949 AhciWriteReg (AhciBar, Offset, OldCmdListLo);
950 Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_CLBU;
951 AhciWriteReg (AhciBar, Offset, OldCmdListHi);
952
953 return Status;
954 }
955
956 /**
957 Start a non data transfer on specific port.
958
959 @param[in] Private The pointer to the PEI_AHCI_CONTROLLER_PRIVATE_DATA.
960 @param[in] Port The number of port.
961 @param[in] PortMultiplier The number of port multiplier.
962 @param[in] FisIndex The offset index of the FIS base address.
963 @param[in] AtaCommandBlock The EFI_ATA_COMMAND_BLOCK data.
964 @param[in,out] AtaStatusBlock The EFI_ATA_STATUS_BLOCK data.
965 @param[in] Timeout The timeout value of non data transfer, uses
966 100ns as a unit.
967
968 @retval EFI_DEVICE_ERROR The non data transfer abort with error occurs.
969 @retval EFI_TIMEOUT The operation is time out.
970 @retval EFI_UNSUPPORTED The device is not ready for transfer.
971 @retval EFI_SUCCESS The non data transfer executes successfully.
972
973 **/
974 EFI_STATUS
975 AhciNonDataTransfer (
976 IN PEI_AHCI_CONTROLLER_PRIVATE_DATA *Private,
977 IN UINT8 Port,
978 IN UINT8 PortMultiplier,
979 IN UINT8 FisIndex,
980 IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock,
981 IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock,
982 IN UINT64 Timeout
983 )
984 {
985 EFI_STATUS Status;
986 UINTN AhciBar;
987 EFI_AHCI_REGISTERS *AhciRegisters;
988 UINTN FisBaseAddr;
989 UINTN Offset;
990 UINT32 PortTfd;
991 EFI_AHCI_COMMAND_FIS CFis;
992 EFI_AHCI_COMMAND_LIST CmdList;
993
994 AhciBar = Private->MmioBase;
995 AhciRegisters = &Private->AhciRegisters;
996
997 //
998 // Package read needed
999 //
1000 AhciBuildCommandFis (&CFis, AtaCommandBlock);
1001
1002 ZeroMem (&CmdList, sizeof (EFI_AHCI_COMMAND_LIST));
1003
1004 CmdList.AhciCmdCfl = AHCI_FIS_REGISTER_H2D_LENGTH / 4;
1005
1006 AhciBuildCommand (
1007 Private,
1008 Port,
1009 PortMultiplier,
1010 FisIndex,
1011 &CFis,
1012 &CmdList,
1013 0,
1014 NULL,
1015 0
1016 );
1017
1018 Status = AhciStartCommand (
1019 AhciBar,
1020 Port,
1021 0,
1022 Timeout
1023 );
1024 if (EFI_ERROR (Status)) {
1025 goto Exit;
1026 }
1027
1028 //
1029 // Wait device sends the Response Fis
1030 //
1031 FisBaseAddr = (UINTN)AhciRegisters->AhciRFis + sizeof (EFI_AHCI_RECEIVED_FIS) * FisIndex;
1032 Offset = FisBaseAddr + AHCI_D2H_FIS_OFFSET;
1033 Status = AhciWaitMemSet (
1034 Offset,
1035 AHCI_FIS_TYPE_MASK,
1036 AHCI_FIS_REGISTER_D2H,
1037 Timeout
1038 );
1039
1040 if (EFI_ERROR (Status)) {
1041 goto Exit;
1042 }
1043
1044 Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_TFD;
1045 PortTfd = AhciReadReg (AhciBar, (UINT32) Offset);
1046 if ((PortTfd & AHCI_PORT_TFD_ERR) != 0) {
1047 Status = EFI_DEVICE_ERROR;
1048 }
1049
1050 Exit:
1051 AhciStopCommand (
1052 AhciBar,
1053 Port,
1054 Timeout
1055 );
1056
1057 AhciDisableFisReceive (
1058 AhciBar,
1059 Port,
1060 Timeout
1061 );
1062
1063 return Status;
1064 }
1065
1066 /**
1067 Do AHCI HBA reset.
1068
1069 @param[in] AhciBar AHCI bar address.
1070 @param[in] Timeout The timeout, in 100ns units, to reset.
1071
1072 @retval EFI_DEVICE_ERROR AHCI controller is failed to complete hardware reset.
1073 @retval EFI_TIMEOUT The reset operation is time out.
1074 @retval EFI_SUCCESS AHCI controller is reset successfully.
1075
1076 **/
1077 EFI_STATUS
1078 AhciReset (
1079 IN UINTN AhciBar,
1080 IN UINT64 Timeout
1081 )
1082 {
1083 UINT32 Delay;
1084 UINT32 Value;
1085 UINT32 Capability;
1086
1087 //
1088 // Collect AHCI controller information
1089 //
1090 Capability = AhciReadReg (AhciBar, AHCI_CAPABILITY_OFFSET);
1091
1092 //
1093 // Enable AE before accessing any AHCI registers if Supports AHCI Mode Only is not set
1094 //
1095 if ((Capability & AHCI_CAP_SAM) == 0) {
1096 AhciOrReg (AhciBar, AHCI_GHC_OFFSET, AHCI_GHC_ENABLE);
1097 }
1098
1099 AhciOrReg (AhciBar, AHCI_GHC_OFFSET, AHCI_GHC_RESET);
1100
1101 Delay = (UINT32) (DivU64x32(Timeout, 1000) + 1);
1102
1103 do {
1104 Value = AhciReadReg(AhciBar, AHCI_GHC_OFFSET);
1105 if ((Value & AHCI_GHC_RESET) == 0) {
1106 return EFI_SUCCESS;
1107 }
1108
1109 //
1110 // Stall for 100 microseconds.
1111 //
1112 MicroSecondDelay(100);
1113
1114 Delay--;
1115 } while (Delay > 0);
1116
1117 return EFI_TIMEOUT;
1118 }
1119
1120 /**
1121 Send Identify Drive command to a specific device.
1122
1123 @param[in] Private The pointer to the PEI_AHCI_CONTROLLER_PRIVATE_DATA.
1124 @param[in] Port The number of port.
1125 @param[in] PortMultiplier The port multiplier port number.
1126 @param[in] FisIndex The offset index of the FIS base address.
1127 @param[in] Buffer The data buffer to store IDENTIFY PACKET data.
1128
1129 @retval EFI_SUCCESS The cmd executes successfully.
1130 @retval EFI_INVALID_PARAMETER Buffer is NULL.
1131 @retval EFI_DEVICE_ERROR The cmd abort with error occurs.
1132 @retval EFI_TIMEOUT The operation is time out.
1133 @retval EFI_UNSUPPORTED The device is not ready for executing.
1134
1135 **/
1136 EFI_STATUS
1137 AhciIdentify (
1138 IN PEI_AHCI_CONTROLLER_PRIVATE_DATA *Private,
1139 IN UINT8 Port,
1140 IN UINT8 PortMultiplier,
1141 IN UINT8 FisIndex,
1142 IN ATA_IDENTIFY_DATA *Buffer
1143 )
1144 {
1145 EFI_STATUS Status;
1146 EFI_ATA_COMMAND_BLOCK Acb;
1147 EFI_ATA_STATUS_BLOCK Asb;
1148
1149 if (Buffer == NULL) {
1150 return EFI_INVALID_PARAMETER;
1151 }
1152
1153 ZeroMem (&Acb, sizeof (EFI_ATA_COMMAND_BLOCK));
1154 ZeroMem (&Asb, sizeof (EFI_ATA_STATUS_BLOCK));
1155
1156 Acb.AtaCommand = ATA_CMD_IDENTIFY_DRIVE;
1157 Acb.AtaSectorCount = 1;
1158
1159 Status = AhciPioTransfer (
1160 Private,
1161 Port,
1162 PortMultiplier,
1163 FisIndex,
1164 TRUE,
1165 &Acb,
1166 &Asb,
1167 Buffer,
1168 sizeof (ATA_IDENTIFY_DATA),
1169 ATA_TIMEOUT
1170 );
1171
1172 return Status;
1173 }
1174
1175
1176 /**
1177 Collect the number of bits set within a port bitmap.
1178
1179 @param[in] PortBitMap A 32-bit wide bit map of ATA AHCI ports.
1180
1181 @retval The number of bits set in the bitmap.
1182
1183 **/
1184 UINT8
1185 AhciGetNumberOfPortsFromMap (
1186 IN UINT32 PortBitMap
1187 )
1188 {
1189 UINT8 NumberOfPorts;
1190
1191 NumberOfPorts = 0;
1192
1193 while (PortBitMap != 0) {
1194 if ((PortBitMap & ((UINT32)BIT0)) != 0) {
1195 NumberOfPorts++;
1196 }
1197 PortBitMap = PortBitMap >> 1;
1198 }
1199
1200 return NumberOfPorts;
1201 }
1202
1203 /**
1204 Get the specified port number from a port bitmap.
1205
1206 @param[in] PortBitMap A 32-bit wide bit map of ATA AHCI ports.
1207 @param[in] PortIndex The specified port index.
1208 @param[out] Port The port number of the port specified by PortIndex.
1209
1210 @retval EFI_SUCCESS The specified port is found and its port number is
1211 in Port.
1212 @retval EFI_NOT_FOUND Cannot find the specified port within the port bitmap.
1213
1214 **/
1215 EFI_STATUS
1216 AhciGetPortFromMap (
1217 IN UINT32 PortBitMap,
1218 IN UINT8 PortIndex,
1219 OUT UINT8 *Port
1220 )
1221 {
1222 if (PortIndex == 0) {
1223 return EFI_NOT_FOUND;
1224 }
1225
1226 *Port = 0;
1227
1228 while (PortBitMap != 0) {
1229 if ((PortBitMap & ((UINT32)BIT0)) != 0) {
1230 PortIndex--;
1231
1232 //
1233 // Found the port specified by PortIndex.
1234 //
1235 if (PortIndex == 0) {
1236 return EFI_SUCCESS;
1237 }
1238 }
1239 PortBitMap = PortBitMap >> 1;
1240 *Port = *Port + 1;
1241 }
1242
1243 return EFI_NOT_FOUND;
1244 }
1245
1246 /**
1247 Allocate transfer-related data struct which is used at AHCI mode.
1248
1249 @param[in,out] Private A pointer to the PEI_AHCI_CONTROLLER_PRIVATE_DATA instance.
1250
1251 @retval EFI_SUCCESS Data structures are allocated successfully.
1252 @retval Others Data structures are not allocated successfully.
1253
1254 **/
1255 EFI_STATUS
1256 AhciCreateTransferDescriptor (
1257 IN OUT PEI_AHCI_CONTROLLER_PRIVATE_DATA *Private
1258 )
1259 {
1260 EFI_STATUS Status;
1261 UINTN AhciBar;
1262 EFI_AHCI_REGISTERS *AhciRegisters;
1263 EFI_PHYSICAL_ADDRESS DeviceAddress;
1264 VOID *Base;
1265 VOID *Mapping;
1266 UINT32 Capability;
1267 UINT32 PortImplementBitMap;
1268 UINT8 MaxPortNumber;
1269 UINT8 MaxCommandSlotNumber;
1270 UINTN MaxRFisSize;
1271 UINTN MaxCmdListSize;
1272 UINTN MaxCmdTableSize;
1273
1274 AhciBar = Private->MmioBase;
1275 AhciRegisters = &Private->AhciRegisters;
1276
1277 //
1278 // Collect AHCI controller information
1279 //
1280 Capability = AhciReadReg (AhciBar, AHCI_CAPABILITY_OFFSET);
1281
1282 //
1283 // Get the number of command slots per port supported by this HBA.
1284 //
1285 MaxCommandSlotNumber = (UINT8) (((Capability & 0x1F00) >> 8) + 1);
1286 ASSERT (MaxCommandSlotNumber > 0);
1287 if (MaxCommandSlotNumber == 0) {
1288 return EFI_DEVICE_ERROR;
1289 }
1290
1291 //
1292 // Get the highest bit of implemented ports which decides how many bytes are
1293 // allocated for recived FIS.
1294 //
1295 PortImplementBitMap = AhciReadReg (AhciBar, AHCI_PI_OFFSET);
1296 MaxPortNumber = (UINT8)(UINTN)(HighBitSet32(PortImplementBitMap) + 1);
1297 if (MaxPortNumber == 0) {
1298 return EFI_DEVICE_ERROR;
1299 }
1300 //
1301 // Get the number of ports that actually needed to be initialized.
1302 //
1303 MaxPortNumber = MIN (MaxPortNumber, AhciGetNumberOfPortsFromMap (Private->PortBitMap));
1304
1305 //
1306 // Allocate memory for received FIS.
1307 //
1308 MaxRFisSize = MaxPortNumber * sizeof (EFI_AHCI_RECEIVED_FIS);
1309 Status = IoMmuAllocateBuffer (
1310 EFI_SIZE_TO_PAGES (MaxRFisSize),
1311 &Base,
1312 &DeviceAddress,
1313 &Mapping
1314 );
1315 if (EFI_ERROR (Status)) {
1316 return EFI_OUT_OF_RESOURCES;
1317 }
1318 ASSERT (DeviceAddress == ((EFI_PHYSICAL_ADDRESS) (UINTN) Base));
1319 AhciRegisters->AhciRFis = Base;
1320 AhciRegisters->AhciRFisMap = Mapping;
1321 AhciRegisters->MaxRFisSize = MaxRFisSize;
1322 ZeroMem (AhciRegisters->AhciRFis, EFI_PAGE_SIZE * EFI_SIZE_TO_PAGES (MaxRFisSize));
1323
1324 //
1325 // Allocate memory for command list.
1326 // Note that the implemenation is a single task model which only use a command
1327 // list for each port.
1328 //
1329 MaxCmdListSize = 1 * sizeof (EFI_AHCI_COMMAND_LIST);
1330 Status = IoMmuAllocateBuffer (
1331 EFI_SIZE_TO_PAGES (MaxCmdListSize),
1332 &Base,
1333 &DeviceAddress,
1334 &Mapping
1335 );
1336 if (EFI_ERROR (Status)) {
1337 Status = EFI_OUT_OF_RESOURCES;
1338 goto ErrorExit;
1339 }
1340 ASSERT (DeviceAddress == ((EFI_PHYSICAL_ADDRESS) (UINTN) Base));
1341 AhciRegisters->AhciCmdList = Base;
1342 AhciRegisters->AhciCmdListMap = Mapping;
1343 AhciRegisters->MaxCmdListSize = MaxCmdListSize;
1344 ZeroMem (AhciRegisters->AhciCmdList, EFI_PAGE_SIZE * EFI_SIZE_TO_PAGES (MaxCmdListSize));
1345
1346 //
1347 // Allocate memory for command table
1348 // According to AHCI 1.3 spec, a PRD table can contain maximum 65535 entries.
1349 //
1350 MaxCmdTableSize = sizeof (EFI_AHCI_COMMAND_TABLE);
1351 Status = IoMmuAllocateBuffer (
1352 EFI_SIZE_TO_PAGES (MaxCmdTableSize),
1353 &Base,
1354 &DeviceAddress,
1355 &Mapping
1356 );
1357 if (EFI_ERROR (Status)) {
1358 Status = EFI_OUT_OF_RESOURCES;
1359 goto ErrorExit;
1360 }
1361 ASSERT (DeviceAddress == ((EFI_PHYSICAL_ADDRESS) (UINTN) Base));
1362 AhciRegisters->AhciCmdTable = Base;
1363 AhciRegisters->AhciCmdTableMap = Mapping;
1364 AhciRegisters->MaxCmdTableSize = MaxCmdTableSize;
1365 ZeroMem (AhciRegisters->AhciCmdTable, EFI_PAGE_SIZE * EFI_SIZE_TO_PAGES (MaxCmdTableSize));
1366
1367 return EFI_SUCCESS;
1368
1369 ErrorExit:
1370 if (AhciRegisters->AhciRFisMap != NULL) {
1371 IoMmuFreeBuffer (
1372 EFI_SIZE_TO_PAGES (AhciRegisters->MaxRFisSize),
1373 AhciRegisters->AhciRFis,
1374 AhciRegisters->AhciRFisMap
1375 );
1376 AhciRegisters->AhciRFis = NULL;
1377 }
1378
1379 if (AhciRegisters->AhciCmdListMap != NULL) {
1380 IoMmuFreeBuffer (
1381 EFI_SIZE_TO_PAGES (AhciRegisters->MaxCmdListSize),
1382 AhciRegisters->AhciCmdList,
1383 AhciRegisters->AhciCmdListMap
1384 );
1385 AhciRegisters->AhciCmdList = NULL;
1386 }
1387
1388 return Status;
1389 }
1390
1391 /**
1392 Gets ATA device Capacity according to ATA 6.
1393
1394 This function returns the capacity of the ATA device if it follows
1395 ATA 6 to support 48 bit addressing.
1396
1397 @param[in] IdentifyData A pointer to ATA_IDENTIFY_DATA structure.
1398
1399 @return The capacity of the ATA device or 0 if the device does not support
1400 48-bit addressing defined in ATA 6.
1401
1402 **/
1403 EFI_LBA
1404 GetAtapi6Capacity (
1405 IN ATA_IDENTIFY_DATA *IdentifyData
1406 )
1407 {
1408 EFI_LBA Capacity;
1409 EFI_LBA TmpLba;
1410 UINTN Index;
1411
1412 if ((IdentifyData->command_set_supported_83 & BIT10) == 0) {
1413 //
1414 // The device doesn't support 48 bit addressing
1415 //
1416 return 0;
1417 }
1418
1419 //
1420 // 48 bit address feature set is supported, get maximum capacity
1421 //
1422 Capacity = 0;
1423 for (Index = 0; Index < 4; Index++) {
1424 //
1425 // Lower byte goes first: word[100] is the lowest word, word[103] is highest
1426 //
1427 TmpLba = IdentifyData->maximum_lba_for_48bit_addressing[Index];
1428 Capacity |= LShiftU64 (TmpLba, 16 * Index);
1429 }
1430
1431 return Capacity;
1432 }
1433
1434 /**
1435 Identifies ATA device via the Identify data.
1436
1437 This function identifies the ATA device and initializes the media information.
1438
1439 @attention This is boundary function that may receive untrusted input.
1440 @attention The input is from peripheral hardware device.
1441
1442 The Identify Drive command response data from an ATA device is the peripheral
1443 hardware input, so this routine will do basic validation for the Identify Drive
1444 command response data.
1445
1446 @param[in,out] DeviceData A pointer to PEI_AHCI_ATA_DEVICE_DATA structure.
1447
1448 @retval EFI_SUCCESS The device is successfully identified and media
1449 information is correctly initialized.
1450 @retval EFI_UNSUPPORTED The device is not a valid ATA device (hard disk).
1451
1452 **/
1453 EFI_STATUS
1454 IdentifyAtaDevice (
1455 IN OUT PEI_AHCI_ATA_DEVICE_DATA *DeviceData
1456 )
1457 {
1458 ATA_IDENTIFY_DATA *IdentifyData;
1459 EFI_PEI_BLOCK_IO2_MEDIA *Media;
1460 EFI_LBA Capacity;
1461 UINT32 MaxSectorCount;
1462 UINT16 PhyLogicSectorSupport;
1463
1464 IdentifyData = DeviceData->IdentifyData;
1465 Media = &DeviceData->Media;
1466
1467 if ((IdentifyData->config & BIT15) != 0) {
1468 DEBUG ((
1469 DEBUG_ERROR, "%a: Not a hard disk device on Port 0x%x PortMultiplierPort 0x%x\n",
1470 __FUNCTION__, DeviceData->Port, DeviceData->PortMultiplier
1471 ));
1472 return EFI_UNSUPPORTED;
1473 }
1474
1475 DEBUG ((
1476 DEBUG_INFO, "%a: Identify Device: Port 0x%x PortMultiplierPort 0x%x\n",
1477 __FUNCTION__, DeviceData->Port, DeviceData->PortMultiplier
1478 ));
1479
1480 //
1481 // Skip checking whether the WORD 88 (supported UltraDMA by drive), since the
1482 // driver only support PIO data transfer for now.
1483 //
1484
1485 //
1486 // Get the capacity information of the device.
1487 //
1488 Capacity = GetAtapi6Capacity (IdentifyData);
1489 if (Capacity > MAX_28BIT_ADDRESSING_CAPACITY) {
1490 //
1491 // Capacity exceeds 120GB. 48-bit addressing is really needed
1492 //
1493 DeviceData->Lba48Bit = TRUE;
1494 } else {
1495 //
1496 // This is a hard disk <= 120GB capacity, treat it as normal hard disk
1497 //
1498 Capacity = ((UINT32)IdentifyData->user_addressable_sectors_hi << 16) |
1499 IdentifyData->user_addressable_sectors_lo;
1500 DeviceData->Lba48Bit = FALSE;
1501 }
1502
1503 if (Capacity == 0) {
1504 DEBUG ((DEBUG_ERROR, "%a: Invalid Capacity (0) for ATA device.\n", __FUNCTION__));
1505 return EFI_UNSUPPORTED;
1506 }
1507 Media->LastBlock = (EFI_PEI_LBA) (Capacity - 1);
1508
1509 Media->BlockSize = 0x200;
1510 //
1511 // Check whether Long Physical Sector Feature is supported
1512 //
1513 PhyLogicSectorSupport = IdentifyData->phy_logic_sector_support;
1514 DEBUG ((
1515 DEBUG_INFO, "%a: PhyLogicSectorSupport = 0x%x\n",
1516 __FUNCTION__, PhyLogicSectorSupport
1517 ));
1518 if ((PhyLogicSectorSupport & (BIT14 | BIT15)) == BIT14) {
1519 //
1520 // Check logical block size
1521 //
1522 if ((PhyLogicSectorSupport & BIT12) != 0) {
1523 Media->BlockSize = (UINT32) (((IdentifyData->logic_sector_size_hi << 16) |
1524 IdentifyData->logic_sector_size_lo) * sizeof (UINT16));
1525 }
1526 }
1527
1528 //
1529 // Check BlockSize validity
1530 //
1531 MaxSectorCount = mMaxTransferBlockNumber[DeviceData->Lba48Bit];
1532 if ((Media->BlockSize == 0) || (Media->BlockSize > MAX_UINT32 / MaxSectorCount)) {
1533 DEBUG ((DEBUG_ERROR, "%a: Invalid BlockSize (0x%x).\n", __FUNCTION__, Media->BlockSize));
1534 return EFI_UNSUPPORTED;
1535 }
1536
1537 DEBUG ((
1538 DEBUG_INFO, "%a: BlockSize = 0x%x, LastBlock = 0x%lx\n",
1539 __FUNCTION__, Media->BlockSize, Media->LastBlock
1540 ));
1541
1542 if ((IdentifyData->trusted_computing_support & BIT0) != 0) {
1543 DEBUG ((DEBUG_INFO, "%a: Found Trust Computing feature support.\n", __FUNCTION__));
1544 DeviceData->TrustComputing = TRUE;
1545 }
1546
1547 Media->InterfaceType = MSG_SATA_DP;
1548 Media->RemovableMedia = FALSE;
1549 Media->MediaPresent = TRUE;
1550 Media->ReadOnly = FALSE;
1551
1552 return EFI_SUCCESS;
1553 }
1554
1555 /**
1556 Allocate device information data structure to contain device information.
1557 And insert the data structure to the tail of device list for tracing.
1558
1559 @param[in,out] Private A pointer to the PEI_AHCI_CONTROLLER_PRIVATE_DATA
1560 instance.
1561 @param[in] DeviceIndex The device index.
1562 @param[in] Port The port number of the ATA device to send
1563 the command.
1564 @param[in] PortMultiplierPort The port multiplier port number of the ATA
1565 device to send the command.
1566 If there is no port multiplier, then specify
1567 0xFFFF.
1568 @param[in] FisIndex The index of the FIS of the ATA device to
1569 send the command.
1570 @param[in] IdentifyData The data buffer to store the output of the
1571 IDENTIFY command.
1572
1573 @retval EFI_SUCCESS Successfully insert the ATA device to the
1574 tail of device list.
1575 @retval EFI_OUT_OF_RESOURCES Not enough resource.
1576
1577 **/
1578 EFI_STATUS
1579 CreateNewDevice (
1580 IN OUT PEI_AHCI_CONTROLLER_PRIVATE_DATA *Private,
1581 IN UINTN DeviceIndex,
1582 IN UINT16 Port,
1583 IN UINT16 PortMultiplier,
1584 IN UINT8 FisIndex,
1585 IN ATA_IDENTIFY_DATA *IdentifyData
1586 )
1587 {
1588 PEI_AHCI_ATA_DEVICE_DATA *DeviceData;
1589 EFI_STATUS Status;
1590
1591 DeviceData = AllocateZeroPool (sizeof (PEI_AHCI_ATA_DEVICE_DATA));
1592 if (DeviceData == NULL) {
1593 return EFI_OUT_OF_RESOURCES;
1594 }
1595
1596 if (IdentifyData != NULL) {
1597 DeviceData->IdentifyData = AllocateCopyPool (sizeof (ATA_IDENTIFY_DATA), IdentifyData);
1598 if (DeviceData->IdentifyData == NULL) {
1599 return EFI_OUT_OF_RESOURCES;
1600 }
1601 }
1602
1603 DeviceData->Signature = AHCI_PEI_ATA_DEVICE_DATA_SIGNATURE;
1604 DeviceData->Port = Port;
1605 DeviceData->PortMultiplier = PortMultiplier;
1606 DeviceData->FisIndex = FisIndex;
1607 DeviceData->DeviceIndex = DeviceIndex;
1608 DeviceData->Private = Private;
1609
1610 Status = IdentifyAtaDevice (DeviceData);
1611 if (EFI_ERROR (Status)) {
1612 return Status;
1613 }
1614
1615 if (DeviceData->TrustComputing) {
1616 Private->TrustComputingDevices++;
1617 DeviceData->TrustComputingDeviceIndex = Private->TrustComputingDevices;
1618 }
1619 Private->ActiveDevices++;
1620 InsertTailList (&Private->DeviceList, &DeviceData->Link);
1621
1622 return EFI_SUCCESS;
1623 }
1624
1625 /**
1626 Initialize ATA host controller at AHCI mode.
1627
1628 The function is designed to initialize ATA host controller.
1629
1630 @param[in,out] Private A pointer to the PEI_AHCI_CONTROLLER_PRIVATE_DATA instance.
1631
1632 @retval EFI_SUCCESS The ATA AHCI controller is initialized successfully.
1633 @retval EFI_OUT_OF_RESOURCES Not enough resource to complete while initializing
1634 the controller.
1635 @retval Others A device error occurred while initializing the
1636 controller.
1637
1638 **/
1639 EFI_STATUS
1640 AhciModeInitialization (
1641 IN OUT PEI_AHCI_CONTROLLER_PRIVATE_DATA *Private
1642 )
1643 {
1644 EFI_STATUS Status;
1645 UINTN AhciBar;
1646 UINT32 Capability;
1647 UINT32 Value;
1648 UINT8 MaxPortNumber;
1649 UINT32 PortImplementBitMap;
1650 UINT32 PortInitializeBitMap;
1651 EFI_AHCI_REGISTERS *AhciRegisters;
1652 UINT8 PortIndex;
1653 UINT8 Port;
1654 DATA_64 Data64;
1655 UINT32 Data;
1656 UINT32 Offset;
1657 UINT32 PhyDetectDelay;
1658 UINTN DeviceIndex;
1659 ATA_IDENTIFY_DATA IdentifyData;
1660
1661 AhciBar = Private->MmioBase;
1662
1663 Status = AhciReset (AhciBar, AHCI_PEI_RESET_TIMEOUT);
1664 if (EFI_ERROR (Status)) {
1665 DEBUG ((DEBUG_ERROR, "%a: AHCI HBA reset failed with %r.\n", __FUNCTION__, Status));
1666 return EFI_DEVICE_ERROR;
1667 }
1668
1669 //
1670 // Collect AHCI controller information
1671 //
1672 Capability = AhciReadReg (AhciBar, AHCI_CAPABILITY_OFFSET);
1673
1674 //
1675 // Make sure that GHC.AE bit is set before accessing any AHCI registers.
1676 //
1677 Value = AhciReadReg (AhciBar, AHCI_GHC_OFFSET);
1678 if ((Value & AHCI_GHC_ENABLE) == 0) {
1679 AhciOrReg (AhciBar, AHCI_GHC_OFFSET, AHCI_GHC_ENABLE);
1680 }
1681
1682 Status = AhciCreateTransferDescriptor (Private);
1683 if (EFI_ERROR (Status)) {
1684 DEBUG ((
1685 DEBUG_ERROR,
1686 "%a: Transfer-related data allocation failed with %r.\n",
1687 __FUNCTION__, Status
1688 ));
1689 return EFI_OUT_OF_RESOURCES;
1690 }
1691
1692 //
1693 // Get the number of command slots per port supported by this HBA.
1694 //
1695 MaxPortNumber = (UINT8) ((Capability & 0x1F) + 1);
1696
1697 //
1698 // Get the bit map of those ports exposed by this HBA.
1699 // It indicates which ports that the HBA supports are available for software
1700 // to use.
1701 //
1702 PortImplementBitMap = AhciReadReg (AhciBar, AHCI_PI_OFFSET);
1703
1704 //
1705 // Get the number of ports that actually needed to be initialized.
1706 //
1707 MaxPortNumber = MIN (MaxPortNumber, (UINT8)(UINTN)(HighBitSet32(PortImplementBitMap) + 1));
1708 MaxPortNumber = MIN (MaxPortNumber, AhciGetNumberOfPortsFromMap (Private->PortBitMap));
1709
1710 PortInitializeBitMap = Private->PortBitMap;
1711 AhciRegisters = &Private->AhciRegisters;
1712 DeviceIndex = 0;
1713 //
1714 // Enumerate ATA ports
1715 //
1716 for (PortIndex = 1; PortIndex <= MaxPortNumber; PortIndex ++) {
1717 Status = AhciGetPortFromMap (PortInitializeBitMap, PortIndex, &Port);
1718 if ((PortImplementBitMap & (BIT0 << Port)) != 0) {
1719 //
1720 // Initialize FIS Base Address Register and Command List Base Address
1721 // Register for use.
1722 //
1723 Data64.Uint64 = (UINTN) (AhciRegisters->AhciRFis) +
1724 sizeof (EFI_AHCI_RECEIVED_FIS) * (PortIndex - 1);
1725 Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_FB;
1726 AhciWriteReg (AhciBar, Offset, Data64.Uint32.Lower32);
1727 Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_FBU;
1728 AhciWriteReg (AhciBar, Offset, Data64.Uint32.Upper32);
1729
1730 Data64.Uint64 = (UINTN) (AhciRegisters->AhciCmdList);
1731 Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_CLB;
1732 AhciWriteReg (AhciBar, Offset, Data64.Uint32.Lower32);
1733 Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_CLBU;
1734 AhciWriteReg (AhciBar, Offset, Data64.Uint32.Upper32);
1735
1736 Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_CMD;
1737 Data = AhciReadReg (AhciBar, Offset);
1738 if ((Data & AHCI_PORT_CMD_CPD) != 0) {
1739 AhciOrReg (AhciBar, Offset, AHCI_PORT_CMD_POD);
1740 }
1741
1742 if ((Capability & AHCI_CAP_SSS) != 0) {
1743 AhciOrReg (AhciBar, Offset, AHCI_PORT_CMD_SUD);
1744 }
1745
1746 //
1747 // Disable aggressive power management.
1748 //
1749 Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_SCTL;
1750 AhciOrReg (AhciBar, Offset, AHCI_PORT_SCTL_IPM_INIT);
1751 //
1752 // Disable the reporting of the corresponding interrupt to system software.
1753 //
1754 Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_IE;
1755 AhciAndReg (AhciBar, Offset, 0);
1756
1757 //
1758 // Enable FIS Receive DMA engine for the first D2H FIS.
1759 //
1760 Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_CMD;
1761 AhciOrReg (AhciBar, Offset, AHCI_PORT_CMD_FRE);
1762
1763 //
1764 // Wait no longer than 15 ms to wait the Phy to detect the presence of a device.
1765 //
1766 PhyDetectDelay = AHCI_BUS_PHY_DETECT_TIMEOUT;
1767 Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_SSTS;
1768 do {
1769 Data = AhciReadReg (AhciBar, Offset) & AHCI_PORT_SSTS_DET_MASK;
1770 if ((Data == AHCI_PORT_SSTS_DET_PCE) || (Data == AHCI_PORT_SSTS_DET)) {
1771 break;
1772 }
1773
1774 MicroSecondDelay (1000);
1775 PhyDetectDelay--;
1776 } while (PhyDetectDelay > 0);
1777
1778 if (PhyDetectDelay == 0) {
1779 //
1780 // No device detected at this port.
1781 // Clear PxCMD.SUD for those ports at which there are no device present.
1782 //
1783 Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_CMD;
1784 AhciAndReg (AhciBar, Offset, (UINT32) ~(AHCI_PORT_CMD_SUD));
1785 DEBUG ((DEBUG_ERROR, "%a: No device detected at Port %d.\n", __FUNCTION__, Port));
1786 continue;
1787 }
1788
1789 //
1790 // According to SATA1.0a spec section 5.2, we need to wait for PxTFD.BSY and PxTFD.DRQ
1791 // and PxTFD.ERR to be zero. The maximum wait time is 16s which is defined at ATA spec.
1792 //
1793 PhyDetectDelay = 16 * 1000;
1794 do {
1795 Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_SERR;
1796 if (AhciReadReg(AhciBar, Offset) != 0) {
1797 AhciWriteReg (AhciBar, Offset, AhciReadReg (AhciBar, Offset));
1798 }
1799 Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_TFD;
1800
1801 Data = AhciReadReg (AhciBar, Offset) & AHCI_PORT_TFD_MASK;
1802 if (Data == 0) {
1803 break;
1804 }
1805
1806 MicroSecondDelay (1000);
1807 PhyDetectDelay--;
1808 } while (PhyDetectDelay > 0);
1809
1810 if (PhyDetectDelay == 0) {
1811 DEBUG ((
1812 DEBUG_ERROR,
1813 "%a: Port %d device presence detected but phy not ready (TFD=0x%x).\n",
1814 __FUNCTION__, Port, Data
1815 ));
1816 continue;
1817 }
1818
1819 //
1820 // When the first D2H register FIS is received, the content of PxSIG register is updated.
1821 //
1822 Offset = AHCI_PORT_START + Port * AHCI_PORT_REG_WIDTH + AHCI_PORT_SIG;
1823 Status = AhciWaitMmioSet (
1824 AhciBar,
1825 Offset,
1826 0x0000FFFF,
1827 0x00000101,
1828 160000000
1829 );
1830 if (EFI_ERROR (Status)) {
1831 DEBUG ((
1832 DEBUG_ERROR,
1833 "%a: Error occured when waiting for the first D2H register FIS - %r\n",
1834 __FUNCTION__, Status
1835 ));
1836 continue;
1837 }
1838
1839 Data = AhciReadReg (AhciBar, Offset);
1840 if ((Data & AHCI_ATAPI_SIG_MASK) == AHCI_ATA_DEVICE_SIG) {
1841 Status = AhciIdentify (Private, Port, 0, PortIndex - 1, &IdentifyData);
1842 if (EFI_ERROR (Status)) {
1843 DEBUG ((DEBUG_ERROR, "%a: AhciIdentify() failed with %r\n", __FUNCTION__, Status));
1844 continue;
1845 }
1846 DEBUG ((DEBUG_INFO, "%a: ATA hard disk found on Port %d.\n", __FUNCTION__, Port));
1847 } else {
1848 continue;
1849 }
1850
1851 //
1852 // Found an ATA hard disk device, add it into the device list.
1853 //
1854 DeviceIndex++;
1855 CreateNewDevice (
1856 Private,
1857 DeviceIndex,
1858 Port,
1859 0xFFFF,
1860 PortIndex - 1,
1861 &IdentifyData
1862 );
1863 }
1864 }
1865
1866 return EFI_SUCCESS;
1867 }
1868
1869 /**
1870 Trust transfer data from/to ATA device.
1871
1872 This function performs one ATA pass through transaction to do a trust transfer
1873 from/to ATA device. It chooses the appropriate ATA command and protocol to invoke
1874 PassThru interface of ATA pass through.
1875
1876 @param[in] DeviceData Pointer to PEI_AHCI_ATA_DEVICE_DATA structure.
1877 @param[in,out] Buffer The pointer to the current transaction buffer.
1878 @param[in] SecurityProtocolId
1879 The value of the "Security Protocol" parameter
1880 of the security protocol command to be sent.
1881 @param[in] SecurityProtocolSpecificData
1882 The value of the "Security Protocol Specific"
1883 parameter of the security protocol command to
1884 be sent.
1885 @param[in] TransferLength The block number or sector count of the transfer.
1886 @param[in] IsTrustSend Indicates whether it is a trust send operation
1887 or not.
1888 @param[in] Timeout The timeout, in 100ns units, to use for the execution
1889 of the security protocol command. A Timeout value
1890 of 0 means that this function will wait indefinitely
1891 for the security protocol command to execute. If
1892 Timeout is greater than zero, then this function
1893 will return EFI_TIMEOUT if the time required to
1894 execute the receive data command is greater than
1895 Timeout.
1896 @param[out] TransferLengthOut
1897 A pointer to a buffer to store the size in bytes
1898 of the data written to the buffer. Ignore it when
1899 IsTrustSend is TRUE.
1900
1901 @retval EFI_SUCCESS The data transfer is complete successfully.
1902 @return others Some error occurs when transferring data.
1903
1904 **/
1905 EFI_STATUS
1906 TrustTransferAtaDevice (
1907 IN PEI_AHCI_ATA_DEVICE_DATA *DeviceData,
1908 IN OUT VOID *Buffer,
1909 IN UINT8 SecurityProtocolId,
1910 IN UINT16 SecurityProtocolSpecificData,
1911 IN UINTN TransferLength,
1912 IN BOOLEAN IsTrustSend,
1913 IN UINT64 Timeout,
1914 OUT UINTN *TransferLengthOut
1915 )
1916 {
1917 PEI_AHCI_CONTROLLER_PRIVATE_DATA *Private;
1918 EDKII_PEI_ATA_PASS_THRU_PPI *AtaPassThru;
1919 EFI_ATA_COMMAND_BLOCK Acb;
1920 EFI_ATA_PASS_THRU_COMMAND_PACKET Packet;
1921 EFI_STATUS Status;
1922 VOID *NewBuffer;
1923
1924 Private = DeviceData->Private;
1925 AtaPassThru = &Private->AtaPassThruPpi;
1926
1927 //
1928 // Ensure IsTrustSend are valid boolean values
1929 //
1930 ASSERT ((UINTN) IsTrustSend < 2);
1931 if ((UINTN) IsTrustSend >= 2) {
1932 return EFI_INVALID_PARAMETER;
1933 }
1934
1935 //
1936 // Prepare for ATA command block.
1937 //
1938 ZeroMem (&Acb, sizeof (EFI_ATA_COMMAND_BLOCK));
1939 if (TransferLength == 0) {
1940 Acb.AtaCommand = ATA_CMD_TRUST_NON_DATA;
1941 } else {
1942 Acb.AtaCommand = mAtaTrustCommands[IsTrustSend];
1943 }
1944 Acb.AtaFeatures = SecurityProtocolId;
1945 Acb.AtaSectorCount = (UINT8) (TransferLength / 512);
1946 Acb.AtaSectorNumber = (UINT8) ((TransferLength / 512) >> 8);
1947 //
1948 // NOTE: ATA Spec has no explicitly definition for Security Protocol Specific layout.
1949 // Here use big endian for Cylinder register.
1950 //
1951 Acb.AtaCylinderHigh = (UINT8) SecurityProtocolSpecificData;
1952 Acb.AtaCylinderLow = (UINT8) (SecurityProtocolSpecificData >> 8);
1953 Acb.AtaDeviceHead = (UINT8) (BIT7 | BIT6 | BIT5 |
1954 (DeviceData->PortMultiplier == 0xFFFF ?
1955 0 : (DeviceData->PortMultiplier << 4)));
1956
1957 //
1958 // Prepare for ATA pass through packet.
1959 //
1960 ZeroMem (&Packet, sizeof (EFI_ATA_PASS_THRU_COMMAND_PACKET));
1961 if (TransferLength == 0) {
1962 Packet.InTransferLength = 0;
1963 Packet.OutTransferLength = 0;
1964 Packet.Protocol = EFI_ATA_PASS_THRU_PROTOCOL_ATA_NON_DATA;
1965 } else if (IsTrustSend) {
1966 //
1967 // Check the alignment of the incoming buffer prior to invoking underlying
1968 // ATA PassThru PPI.
1969 //
1970 if ((AtaPassThru->Mode->IoAlign > 1) &&
1971 !IS_ALIGNED (Buffer, AtaPassThru->Mode->IoAlign)) {
1972 NewBuffer = AllocateAlignedPages (
1973 EFI_SIZE_TO_PAGES (TransferLength),
1974 AtaPassThru->Mode->IoAlign
1975 );
1976 if (NewBuffer == NULL) {
1977 return EFI_OUT_OF_RESOURCES;
1978 }
1979
1980 CopyMem (NewBuffer, Buffer, TransferLength);
1981 Buffer = NewBuffer;
1982 }
1983 Packet.OutDataBuffer = Buffer;
1984 Packet.OutTransferLength = (UINT32) TransferLength;
1985 Packet.Protocol = mAtaPassThruCmdProtocols[IsTrustSend];
1986 } else {
1987 Packet.InDataBuffer = Buffer;
1988 Packet.InTransferLength = (UINT32) TransferLength;
1989 Packet.Protocol = mAtaPassThruCmdProtocols[IsTrustSend];
1990 }
1991 Packet.Asb = NULL;
1992 Packet.Acb = &Acb;
1993 Packet.Timeout = Timeout;
1994 Packet.Length = EFI_ATA_PASS_THRU_LENGTH_BYTES;
1995
1996 Status = AtaPassThru->PassThru (
1997 AtaPassThru,
1998 DeviceData->Port,
1999 DeviceData->PortMultiplier,
2000 &Packet
2001 );
2002 if (TransferLengthOut != NULL) {
2003 if (!IsTrustSend) {
2004 *TransferLengthOut = Packet.InTransferLength;
2005 }
2006 }
2007 return Status;
2008 }