]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AhciMode.c
Add new adding ATA related status code in PI 1.3 to definition and ATA modules.
[mirror_edk2.git] / MdeModulePkg / Bus / Ata / AtaAtapiPassThru / AhciMode.c
index cfd2d807c31bd7e959817e65b756ceccf341ba4d..950b5da03882ccfec156d042b082653e04c6c79f 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 - 2013, 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
@@ -503,12 +503,12 @@ AhciBuildCommand (
   IN     UINT8                      AtapiCommandLength,\r
   IN     UINT8                      CommandSlotNumber,\r
   IN OUT VOID                       *DataPhysicalAddr,\r
-  IN     UINT64                     DataLength\r
+  IN     UINT32                     DataLength\r
   )\r
 {\r
   UINT64     BaseAddr;\r
-  UINT64     PrdtNumber;\r
-  UINT64     PrdtIndex;\r
+  UINT32     PrdtNumber;\r
+  UINT32     PrdtIndex;\r
   UINTN      RemainedData;\r
   UINTN      MemAddr;\r
   DATA_64    Data64;\r
@@ -548,7 +548,6 @@ AhciBuildCommand (
 \r
     CommandList->AhciCmdA = 1;\r
     CommandList->AhciCmdP = 1;\r
-    CommandList->AhciCmdC = (DataLength == 0) ? 1 : 0;\r
 \r
     AhciOrReg (PciIo, Offset, (EFI_AHCI_PORT_CMD_DLAE | EFI_AHCI_PORT_CMD_ATAPI));\r
   } else {\r
@@ -557,7 +556,7 @@ AhciBuildCommand (
 \r
   RemainedData = (UINTN) DataLength;\r
   MemAddr      = (UINTN) DataPhysicalAddr;\r
-  CommandList->AhciCmdPrdtl = (UINT32)PrdtNumber;\r
+  CommandList->AhciCmdPrdtl = PrdtNumber;\r
 \r
   for (PrdtIndex = 0; PrdtIndex < PrdtNumber; PrdtIndex++) {\r
     if (RemainedData < EFI_AHCI_MAX_DATA_PER_PRDT) {\r
@@ -759,17 +758,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
@@ -1484,9 +1487,18 @@ AhciAtaSmartReturnStatusCheck (
              );\r
 \r
   if (EFI_ERROR (Status)) {\r
+    REPORT_STATUS_CODE (\r
+      EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
+      (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_DISABLED)\r
+      );\r
     return EFI_DEVICE_ERROR;\r
   }\r
 \r
+  REPORT_STATUS_CODE (\r
+    EFI_PROGRESS_CODE,\r
+    (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_ENABLE)\r
+    );\r
+\r
   FisBaseAddr = (UINTN)AhciRegisters->AhciRFis + Port * sizeof (EFI_AHCI_RECEIVED_FIS);\r
 \r
   Value = *(UINT32 *) (FisBaseAddr + EFI_AHCI_D2H_FIS_OFFSET);\r
@@ -1500,12 +1512,19 @@ AhciAtaSmartReturnStatusCheck (
       // The threshold exceeded condition is not detected by the device\r
       //\r
       DEBUG ((EFI_D_INFO, "The S.M.A.R.T threshold exceeded condition is not detected\n"));\r
-\r
+      REPORT_STATUS_CODE (\r
+            EFI_PROGRESS_CODE,\r
+            (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_UNDERTHRESHOLD)\r
+            );\r
     } else if ((LBAMid == 0xf4) && (LBAHigh == 0x2c)) {\r
       //\r
       // The threshold exceeded condition is detected by the device\r
       //\r
       DEBUG ((EFI_D_INFO, "The S.M.A.R.T threshold exceeded condition is detected\n"));\r
+      REPORT_STATUS_CODE (\r
+           EFI_PROGRESS_CODE,\r
+           (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_OVERTHRESHOLD)\r
+           );\r
     }\r
   }\r
 \r
@@ -1546,11 +1565,21 @@ AhciAtaSmartSupport (
     //\r
     DEBUG ((EFI_D_INFO, "S.M.A.R.T feature is not supported at port [%d] PortMultiplier [%d]!\n",\r
             Port, PortMultiplier));\r
+    REPORT_STATUS_CODE (\r
+      EFI_ERROR_CODE | EFI_ERROR_MINOR,\r
+      (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_NOTSUPPORTED)\r
+      );\r
   } else {\r
     //\r
     // Check if the feature is enabled. If not, then enable S.M.A.R.T.\r
     //\r
     if ((IdentifyData->AtaData.command_set_feature_enb_85 & 0x0001) != 0x0001) {\r
+\r
+      REPORT_STATUS_CODE (\r
+        EFI_PROGRESS_CODE,\r
+        (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_DISABLE)\r
+        );\r
+\r
       ZeroMem (&AtaCommandBlock, sizeof (EFI_ATA_COMMAND_BLOCK));\r
 \r
       AtaCommandBlock.AtaCommand      = ATA_CMD_SMART;\r
@@ -1904,6 +1933,7 @@ AhciCreateTransferDescriptor (
   VOID                  *Buffer;\r
 \r
   UINT32                Capability;\r
+  UINT32                PortImplementBitMap;\r
   UINT8                 MaxPortNumber;\r
   UINT8                 MaxCommandSlotNumber;\r
   BOOLEAN               Support64Bit;\r
@@ -1919,12 +1949,20 @@ AhciCreateTransferDescriptor (
   // Collect AHCI controller information\r
   //\r
   Capability           = AhciReadReg(PciIo, EFI_AHCI_CAPABILITY_OFFSET);\r
-  MaxPortNumber        = (UINT8) ((Capability & 0x1F) + 1);\r
   //\r
   // Get the number of command slots per port supported by this HBA.\r
   //\r
   MaxCommandSlotNumber = (UINT8) (((Capability & 0x1F00) >> 8) + 1);\r
   Support64Bit         = (BOOLEAN) (((Capability & BIT31) != 0) ? TRUE : FALSE);\r
+  \r
+  PortImplementBitMap  = AhciReadReg(PciIo, EFI_AHCI_PI_OFFSET);\r
+  //\r
+  // Get the highest bit of implemented ports which decides how many bytes are allocated for recived FIS.\r
+  //\r
+  MaxPortNumber        = (UINT8)(UINTN)(HighBitSet32(PortImplementBitMap) + 1);\r
+  if (MaxPortNumber == 0) {\r
+    return EFI_DEVICE_ERROR;\r
+  }\r
 \r
   MaxReceiveFisSize    = MaxPortNumber * sizeof (EFI_AHCI_RECEIVED_FIS);\r
   Status = PciIo->AllocateBuffer (\r
@@ -2198,8 +2236,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 +2327,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 +2401,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