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