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