/** @file\r
The file for AHCI mode of ATA host controller.\r
\r
- Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>\r
+ Copyright (c) 2010 - 2012, Intel Corporation. All rights reserved.<BR>\r
This program and the accompanying materials\r
are licensed and made available under the terms and conditions of the BSD License\r
which accompanies this distribution. The full text of the license may be found at\r
Status = EFI_TIMEOUT;\r
Delay = (UINT32) (DivU64x32 (Timeout, 1000) + 1);\r
do {\r
- Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_TFD;\r
- PortTfd = AhciReadReg (PciIo, (UINT32) Offset);\r
-\r
- if ((PortTfd & EFI_AHCI_PORT_TFD_ERR) != 0) {\r
- Status = EFI_DEVICE_ERROR;\r
- break;\r
- }\r
Offset = FisBaseAddr + EFI_AHCI_PIO_FIS_OFFSET;\r
\r
Status = AhciCheckMemSet (Offset, EFI_AHCI_FIS_TYPE_MASK, EFI_AHCI_FIS_PIO_SETUP, 0);\r
if (!EFI_ERROR (Status)) {\r
+ Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_TFD;\r
+ PortTfd = AhciReadReg (PciIo, (UINT32) Offset);\r
+ //\r
+ // PxTFD will be updated if there is a D2H or SetupFIS received. \r
+ // For PIO IN transfer, D2H means a device error. Therefore we only need to check the TFD after receiving a SetupFIS.\r
+ //\r
+ if ((PortTfd & EFI_AHCI_PORT_TFD_ERR) != 0) {\r
+ Status = EFI_DEVICE_ERROR;\r
+ break;\r
+ }\r
+\r
PrdCount = *(volatile UINT32 *) (&(AhciRegisters->AhciCmdList[0].AhciCmdPrdbc));\r
if (PrdCount == DataCount) {\r
break;\r
return EFI_OUT_OF_RESOURCES;\r
}\r
\r
- for (Port = 0; Port < MaxPortNumber; Port ++) {\r
+ for (Port = 0; Port < EFI_AHCI_MAX_PORTS; Port ++) {\r
if ((PortImplementBitMap & (BIT0 << Port)) != 0) {\r
+ //\r
+ // According to AHCI spec, MaxPortNumber should be equal or greater than the number of implemented ports.\r
+ //\r
+ if ((MaxPortNumber--) == 0) {\r
+ //\r
+ // Should never be here.\r
+ //\r
+ ASSERT (FALSE);\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
IdeInit->NotifyPhase (IdeInit, EfiIdeBeforeChannelEnumeration, Port);\r
\r
//\r
if (PhyDetectDelay == 0) {\r
//\r
// No device detected at this port.\r
+ // Clear PxCMD.SUD for those ports at which there are no device present.\r
//\r
+ Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD;\r
+ AhciAndReg (PciIo, Offset, (UINT32) ~(EFI_AHCI_PORT_CMD_SUD));\r
continue;\r
}\r
\r
//\r
// If the device is a hard disk, then try to enable S.M.A.R.T feature\r
//\r
- if (DeviceType == EfiIdeHarddisk) {\r
+ if ((DeviceType == EfiIdeHarddisk) && PcdGetBool (PcdAtaSmartEnable)) {\r
AhciAtaSmartSupport (\r
PciIo,\r
AhciRegisters,\r