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