]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AhciMode.c
MdeModulePkg/AtaAtapiPassThru: valid ports transverse algo of AHCI controller is...
[mirror_edk2.git] / MdeModulePkg / Bus / Ata / AtaAtapiPassThru / AhciMode.c
index 5a6a3d7d0f862d5f7bbdb4a87e8b5ef67afcacfb..1c45312712bb96382f162ce3e871904d7542e3c3 100644 (file)
@@ -1,7 +1,7 @@
 /** @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
@@ -759,17 +759,21 @@ AhciPioTransfer (
     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
@@ -2198,8 +2202,19 @@ AhciModeInitialization (
     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
@@ -2278,7 +2293,10 @@ AhciModeInitialization (
       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
@@ -2349,7 +2367,7 @@ AhciModeInitialization (
       //\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