]> git.proxmox.com Git - mirror_edk2.git/blobdiff - QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/CEATA.c
QuarkSocPkg: Add new package for Quark SoC X1000
[mirror_edk2.git] / QuarkSocPkg / QuarkSouthCluster / Sdio / Dxe / SDMediaDeviceDxe / CEATA.c
diff --git a/QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/CEATA.c b/QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/CEATA.c
new file mode 100644 (file)
index 0000000..0261295
--- /dev/null
@@ -0,0 +1,656 @@
+/** @file\r
+\r
+CEATA specific functions implementation\r
+\r
+Copyright (c) 2013-2015 Intel Corporation.\r
+\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
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "SDMediaDevice.h"\r
+\r
+/**\r
+  Send RW_MULTIPLE_REGISTER command\r
+\r
+  @param  CardData             Pointer to CARD_DATA.\r
+  @param  Address              Register address.\r
+  @param  ByteCount            Buffer size.\r
+  @param  Write                TRUE means write, FALSE means read.\r
+  @param  Buffer               Buffer pointer.\r
+\r
+  @retval EFI_SUCCESS                Success\r
+  @retval EFI_DEVICE_ERROR           Hardware Error\r
+  @retval EFI_INVALID_PARAMETER      Parameter is error\r
+  @retval EFI_NO_MEDIA               No media\r
+  @retval EFI_MEDIA_CHANGED          Media Change\r
+  @retval EFI_BAD_BUFFER_SIZE        Buffer size is bad\r
+\r
+**/\r
+EFI_STATUS\r
+ReadWriteMultipleRegister (\r
+  IN  CARD_DATA   *CardData,\r
+  IN  UINT16      Address,\r
+  IN  UINT8       ByteCount,\r
+  IN  BOOLEAN     Write,\r
+  IN  UINT8       *Buffer\r
+  )\r
+{\r
+  EFI_STATUS                 Status;\r
+  UINT32                     Argument;\r
+\r
+  Status   = EFI_SUCCESS;\r
+\r
+  if ((Address % 4 != 0) || (ByteCount % 4 != 0)) {\r
+    Status = EFI_INVALID_PARAMETER;\r
+    goto Exit;\r
+  }\r
+\r
+  Argument = (Address << 16) | ByteCount;\r
+  if (Write) {\r
+    Argument |= BIT31;\r
+  }\r
+\r
+\r
+  if (Write) {\r
+    CopyMem (CardData->AlignedBuffer, Buffer, ByteCount);\r
+\r
+    Status = SendCommand (\r
+               CardData,\r
+               RW_MULTIPLE_REGISTER,\r
+               Argument,\r
+               OutData,\r
+               CardData->AlignedBuffer,\r
+               ByteCount,\r
+               ResponseR1b,\r
+               TIMEOUT_DATA,\r
+               (UINT32*)&(CardData->CardStatus)\r
+               );\r
+  } else {\r
+    Status = SendCommand (\r
+               CardData,\r
+               RW_MULTIPLE_REGISTER,\r
+               Argument,\r
+               InData,\r
+               CardData->AlignedBuffer,\r
+               ByteCount,\r
+               ResponseR1,\r
+               TIMEOUT_DATA,\r
+               (UINT32*)&(CardData->CardStatus)\r
+               );\r
+    if (!EFI_ERROR (Status)) {\r
+      CopyMem (Buffer, CardData->AlignedBuffer, ByteCount);\r
+    }\r
+\r
+  }\r
+Exit:\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Send ReadWriteMultipleBlock command with RW_MULTIPLE_REGISTER command\r
+\r
+  @param  CardData             Pointer to CARD_DATA.\r
+  @param  DataUnitCount        Buffer size in 512 bytes unit.\r
+  @param  Write                TRUE means write, FALSE means read.\r
+  @param  Buffer               Buffer pointer.\r
+\r
+  @retval EFI_SUCCESS                Success\r
+  @retval EFI_DEVICE_ERROR           Hardware Error\r
+  @retval EFI_INVALID_PARAMETER      Parameter is error\r
+  @retval EFI_NO_MEDIA               No media\r
+  @retval EFI_MEDIA_CHANGED          Media Change\r
+  @retval EFI_BAD_BUFFER_SIZE        Buffer size is bad\r
+\r
+**/\r
+EFI_STATUS\r
+ReadWriteMultipleBlock (\r
+  IN  CARD_DATA   *CardData,\r
+  IN  UINT16      DataUnitCount,\r
+  IN  BOOLEAN     Write,\r
+  IN  UINT8       *Buffer\r
+  )\r
+{\r
+  EFI_STATUS                 Status;\r
+  EFI_SD_HOST_IO_PROTOCOL    *SDHostIo;\r
+  UINT32                     TransferLength;\r
+\r
+  Status   = EFI_SUCCESS;\r
+  SDHostIo = CardData->SDHostIo;\r
+\r
+  TransferLength = DataUnitCount * DATA_UNIT_SIZE;\r
+  if (TransferLength > SDHostIo->HostCapability.BoundarySize) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (Write) {\r
+    CopyMem (CardData->AlignedBuffer, Buffer, TransferLength);\r
+\r
+    Status = SendCommand (\r
+               CardData,\r
+               RW_MULTIPLE_BLOCK,\r
+               (DataUnitCount | BIT31),\r
+               OutData,\r
+               CardData->AlignedBuffer,\r
+               TransferLength,\r
+               ResponseR1b,\r
+               TIMEOUT_DATA,\r
+               (UINT32*)&(CardData->CardStatus)\r
+               );\r
+   } else {\r
+      Status = SendCommand (\r
+                 CardData,\r
+                 RW_MULTIPLE_BLOCK,\r
+                 DataUnitCount,\r
+                 InData,\r
+                 CardData->AlignedBuffer,\r
+                 TransferLength,\r
+                 ResponseR1,\r
+                 TIMEOUT_DATA,\r
+                 (UINT32*)&(CardData->CardStatus)\r
+                 );\r
+      if (!EFI_ERROR (Status)) {\r
+        CopyMem (Buffer, CardData->AlignedBuffer, TransferLength);\r
+      }\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Send software reset\r
+\r
+  @param  CardData             Pointer to CARD_DATA.\r
+\r
+  @retval EFI_SUCCESS                Success\r
+  @retval EFI_DEVICE_ERROR           Hardware Error\r
+  @retval EFI_INVALID_PARAMETER      Parameter is error\r
+  @retval EFI_NO_MEDIA               No media\r
+  @retval EFI_MEDIA_CHANGED          Media Change\r
+  @retval EFI_BAD_BUFFER_SIZE        Buffer size is bad\r
+\r
+**/\r
+EFI_STATUS\r
+SoftwareReset (\r
+  IN  CARD_DATA    *CardData\r
+  )\r
+{\r
+  EFI_STATUS    Status;\r
+  UINT8         Data;\r
+  UINT32        TimeOut;\r
+\r
+  Data = BIT2;\r
+\r
+  Status = FastIO (CardData, Reg_Control, &Data, TRUE);\r
+  if (EFI_ERROR (Status)) {\r
+    goto Exit;\r
+  }\r
+\r
+  TimeOut = 5 * 1000;\r
+\r
+  do {\r
+    gBS->Stall (1 * 1000);\r
+    Status = FastIO (CardData, Reg_Control, &Data, FALSE);\r
+    if (EFI_ERROR (Status)) {\r
+      goto Exit;\r
+    }\r
+    if ((Data & BIT2) == BIT2) {\r
+      break;\r
+    }\r
+\r
+    TimeOut--;\r
+  } while (TimeOut > 0);\r
+\r
+  if (TimeOut == 0) {\r
+   Status = EFI_TIMEOUT;\r
+   goto Exit;\r
+  }\r
+\r
+  Data &= ~BIT2;\r
+  Status = FastIO (CardData, Reg_Control, &Data, TRUE);\r
+\r
+  TimeOut = 5 * 1000;\r
+\r
+  do {\r
+    gBS->Stall (1 * 1000);\r
+    Status = FastIO (CardData, Reg_Control, &Data, FALSE);\r
+    if (EFI_ERROR (Status)) {\r
+      goto Exit;\r
+    }\r
+    if ((Data & BIT2) != BIT2) {\r
+      break;\r
+    }\r
+\r
+    TimeOut--;\r
+  } while (TimeOut > 0);\r
+\r
+\r
+  if (TimeOut == 0) {\r
+   Status = EFI_TIMEOUT;\r
+   goto Exit;\r
+  }\r
+\r
+\r
+Exit:\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  SendATACommand specificed in Taskfile\r
+\r
+  @param  CardData             Pointer to CARD_DATA.\r
+  @param  TaskFile             Pointer to TASK_FILE.\r
+  @param  Write                TRUE means write, FALSE means read.\r
+  @param  Buffer               If NULL, means no data transfer, neither read nor write.\r
+  @param  SectorCount          Buffer size in 512 bytes unit.\r
+\r
+  @retval EFI_SUCCESS                Success\r
+  @retval EFI_DEVICE_ERROR           Hardware Error\r
+  @retval EFI_INVALID_PARAMETER      Parameter is error\r
+  @retval EFI_NO_MEDIA               No media\r
+  @retval EFI_MEDIA_CHANGED          Media Change\r
+  @retval EFI_BAD_BUFFER_SIZE        Buffer size is bad\r
+\r
+**/\r
+EFI_STATUS\r
+SendATACommand (\r
+  IN  CARD_DATA   *CardData,\r
+  IN  TASK_FILE   *TaskFile,\r
+  IN  BOOLEAN     Write,\r
+  IN  UINT8       *Buffer,\r
+  IN  UINT16      SectorCount\r
+  )\r
+{\r
+  EFI_STATUS                 Status;\r
+  EFI_SD_HOST_IO_PROTOCOL    *SDHostIo;\r
+  UINT8                      Data;\r
+  UINT32                     TimeOut;\r
+\r
+  SDHostIo = CardData->SDHostIo;\r
+\r
+  //\r
+  //Write register\r
+  //\r
+  Status = ReadWriteMultipleRegister (\r
+             CardData,\r
+             0,\r
+             sizeof (TASK_FILE),\r
+             TRUE,\r
+             (UINT8*)TaskFile\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG((EFI_D_ERROR, "ReadWriteMultipleRegister 0x%x\n", Status));\r
+    goto Exit;\r
+  }\r
+\r
+  TimeOut = 5000;\r
+  do {\r
+    gBS->Stall (1 * 1000);\r
+    Data = 0;\r
+    Status = FastIO (\r
+               CardData,\r
+               Reg_Command_Status,\r
+               &Data,\r
+               FALSE\r
+               );\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+    if (((Data & BIT7) == 0) && ((Data & BIT6) == BIT6)) {\r
+      break;\r
+    }\r
+\r
+    TimeOut --;\r
+  } while (TimeOut > 0);\r
+\r
+  if (TimeOut == 0) {\r
+    DEBUG((EFI_D_ERROR, "ReadWriteMultipleRegister FastIO EFI_TIMEOUT 0x%x\n", Data));\r
+    Status = EFI_TIMEOUT;\r
+    goto Exit;\r
+  }\r
+\r
+\r
+  if (Buffer != NULL) {\r
+    Status = ReadWriteMultipleBlock (\r
+               CardData,\r
+               SectorCount,\r
+               Write,\r
+               (UINT8*)Buffer\r
+               );\r
+    if (EFI_ERROR (Status)) {\r
+      DEBUG((EFI_D_ERROR, "ReadWriteMultipleBlock EFI_TIMEOUT 0x%x\n", Status));\r
+      goto Exit;\r
+    }\r
+\r
+    TimeOut = 5 * 1000;\r
+    do {\r
+      gBS->Stall (1 * 1000);\r
+\r
+      Data = 0;\r
+      Status = FastIO (\r
+                 CardData,\r
+                 Reg_Command_Status,\r
+                 &Data,\r
+                 FALSE\r
+                 );\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+\r
+      if (((Data & BIT7) == 0) && ((Data & BIT3) == 0)) {\r
+        break;\r
+      }\r
+\r
+      TimeOut --;\r
+    } while (TimeOut > 0);\r
+    if (TimeOut == 0) {\r
+      DEBUG((EFI_D_ERROR, "ReadWriteMultipleBlock FastIO EFI_TIMEOUT 0x%x\n", Data));\r
+      Status = EFI_TIMEOUT;\r
+      goto Exit;\r
+    }\r
+\r
+\r
+    if (((Data & BIT6) == BIT6) && (Data & BIT0) == 0) {\r
+      Status = EFI_SUCCESS;\r
+    } else {\r
+      Status = EFI_DEVICE_ERROR;\r
+    }\r
+  }\r
+\r
+Exit:\r
+  if (EFI_ERROR (Status)) {\r
+    SoftwareReset (CardData);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  IDENTIFY_DEVICE command\r
+\r
+  @param  CardData             Pointer to CARD_DATA.\r
+\r
+  @retval EFI_SUCCESS                Success\r
+  @retval EFI_DEVICE_ERROR           Hardware Error\r
+  @retval EFI_INVALID_PARAMETER      Parameter is error\r
+  @retval EFI_NO_MEDIA               No media\r
+  @retval EFI_MEDIA_CHANGED          Media Change\r
+  @retval EFI_BAD_BUFFER_SIZE        Buffer size is bad\r
+\r
+**/\r
+EFI_STATUS\r
+IndentifyDevice (\r
+  IN  CARD_DATA    *CardData\r
+  )\r
+{\r
+  EFI_STATUS                 Status;\r
+\r
+  ZeroMem (&CardData->TaskFile, sizeof (TASK_FILE));\r
+\r
+  //\r
+  //The host only supports nIEN = 0\r
+  //\r
+  CardData->TaskFile.Command_Status = IDENTIFY_DEVICE;\r
+\r
+\r
+  Status = SendATACommand (\r
+             CardData,\r
+             &CardData->TaskFile,\r
+             FALSE,\r
+             (UINT8*)&(CardData->IndentifyDeviceData),\r
+             1\r
+             );\r
+\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  FLUSH_CACHE_EXT command\r
+\r
+  @param  CardData             Pointer to CARD_DATA.\r
+\r
+  @retval EFI_SUCCESS                Success\r
+  @retval EFI_DEVICE_ERROR           Hardware Error\r
+  @retval EFI_INVALID_PARAMETER      Parameter is error\r
+  @retval EFI_NO_MEDIA               No media\r
+  @retval EFI_MEDIA_CHANGED          Media Change\r
+  @retval EFI_BAD_BUFFER_SIZE        Buffer size is bad\r
+\r
+**/\r
+EFI_STATUS\r
+FlushCache (\r
+  IN  CARD_DATA    *CardData\r
+  )\r
+{\r
+\r
+  //\r
+  //Hitachi CE-ATA will always make the busy high after\r
+  //receving this command\r
+  //\r
+/*\r
+  EFI_STATUS  Status;\r
+  ZeroMem (&CardData->TaskFile, sizeof (TASK_FILE));\r
+  //\r
+  //The host only supports nIEN = 0\r
+  //\r
+  CardData->TaskFile.Command_Status = FLUSH_CACHE_EXT;\r
+\r
+  Status = SendATACommand (\r
+             CardData,\r
+             &CardData->TaskFile,\r
+             FALSE,\r
+             NULL,\r
+             0\r
+             );\r
+*/\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  STANDBY_IMMEDIATE command\r
+\r
+  @param  CardData             Pointer to CARD_DATA.\r
+\r
+  @retval EFI_SUCCESS                Success\r
+  @retval EFI_DEVICE_ERROR           Hardware Error\r
+  @retval EFI_INVALID_PARAMETER      Parameter is error\r
+  @retval EFI_NO_MEDIA               No media\r
+  @retval EFI_MEDIA_CHANGED          Media Change\r
+  @retval EFI_BAD_BUFFER_SIZE        Buffer size is bad\r
+\r
+**/\r
+EFI_STATUS\r
+StandByImmediate (\r
+  IN  CARD_DATA    *CardData\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  ZeroMem (&CardData->TaskFile, sizeof (TASK_FILE));\r
+  //\r
+  //The host only supports nIEN = 0\r
+  //\r
+  CardData->TaskFile.Command_Status = STANDBY_IMMEDIATE;\r
+\r
+\r
+  Status = SendATACommand (\r
+             CardData,\r
+             &CardData->TaskFile,\r
+             FALSE,\r
+             NULL,\r
+             0\r
+             );\r
+  return Status;\r
+}\r
+\r
+/**\r
+  READ_DMA_EXT command\r
+\r
+  @param  CardData             Pointer to CARD_DATA.\r
+  @param  LBA                  The starting logical block address to read from on the device.\r
+  @param  Buffer               A pointer to the destination buffer for the data. The caller\r
+                               is responsible for either having implicit or explicit ownership\r
+                               of the buffer.\r
+  @param  SectorCount          Size in 512 bytes unit.\r
+\r
+  @retval EFI_SUCCESS                Success\r
+  @retval EFI_DEVICE_ERROR           Hardware Error\r
+  @retval EFI_INVALID_PARAMETER      Parameter is error\r
+  @retval EFI_NO_MEDIA               No media\r
+  @retval EFI_MEDIA_CHANGED          Media Change\r
+  @retval EFI_BAD_BUFFER_SIZE        Buffer size is bad\r
+\r
+**/\r
+EFI_STATUS\r
+ReadDMAExt (\r
+  IN  CARD_DATA   *CardData,\r
+  IN  EFI_LBA     LBA,\r
+  IN  UINT8       *Buffer,\r
+  IN  UINT16      SectorCount\r
+  )\r
+{\r
+\r
+  EFI_STATUS  Status;\r
+\r
+  ZeroMem (&CardData->TaskFile, sizeof (TASK_FILE));\r
+  //\r
+  //The host only supports nIEN = 0\r
+  //\r
+  CardData->TaskFile.Command_Status = READ_DMA_EXT;\r
+\r
+  CardData->TaskFile.SectorCount     = (UINT8)SectorCount;\r
+  CardData->TaskFile.SectorCount_Exp = (UINT8)(SectorCount >> 8);\r
+\r
+  CardData->TaskFile.LBALow          = (UINT8)LBA;\r
+  CardData->TaskFile.LBAMid          = (UINT8)RShiftU64(LBA, 8);\r
+  CardData->TaskFile.LBAHigh         = (UINT8)RShiftU64(LBA, 16);\r
+\r
+  CardData->TaskFile.LBALow_Exp      = (UINT8)RShiftU64(LBA, 24);\r
+  CardData->TaskFile.LBAMid_Exp      = (UINT8)RShiftU64(LBA, 32);\r
+  CardData->TaskFile.LBAHigh_Exp     = (UINT8)RShiftU64(LBA, 40);\r
+\r
+  Status = SendATACommand (\r
+             CardData,\r
+             &CardData->TaskFile,\r
+             FALSE,\r
+             Buffer,\r
+             SectorCount\r
+             );\r
+  return Status;\r
+\r
+}\r
+\r
+/**\r
+  WRITE_DMA_EXT command\r
+\r
+  @param  CardData             Pointer to CARD_DATA.\r
+  @param  LBA                  The starting logical block address to read from on the device.\r
+  @param  Buffer               A pointer to the destination buffer for the data. The caller\r
+                               is responsible for either having implicit or explicit ownership\r
+                               of the buffer.\r
+  @param  SectorCount          Size in 512 bytes unit.\r
+\r
+  @retval EFI_SUCCESS                Success\r
+  @retval EFI_DEVICE_ERROR           Hardware Error\r
+  @retval EFI_INVALID_PARAMETER      Parameter is error\r
+  @retval EFI_NO_MEDIA               No media\r
+  @retval EFI_MEDIA_CHANGED          Media Change\r
+  @retval EFI_BAD_BUFFER_SIZE        Buffer size is bad\r
+\r
+**/\r
+EFI_STATUS\r
+WriteDMAExt (\r
+  IN  CARD_DATA   *CardData,\r
+  IN  EFI_LBA     LBA,\r
+  IN  UINT8       *Buffer,\r
+  IN  UINT16      SectorCount\r
+  )\r
+{\r
+\r
+  EFI_STATUS  Status;\r
+\r
+  ZeroMem (&CardData->TaskFile, sizeof (TASK_FILE));\r
+  //\r
+  //The host only supports nIEN = 0\r
+  //\r
+  CardData->TaskFile.Command_Status = WRITE_DMA_EXT;\r
+\r
+  CardData->TaskFile.SectorCount     = (UINT8)SectorCount;\r
+  CardData->TaskFile.SectorCount_Exp = (UINT8)(SectorCount >> 8);\r
+\r
+  CardData->TaskFile.LBALow          = (UINT8)LBA;\r
+  CardData->TaskFile.LBAMid          = (UINT8)RShiftU64(LBA, 8);\r
+  CardData->TaskFile.LBAHigh         = (UINT8)RShiftU64(LBA, 16);\r
+\r
+  CardData->TaskFile.LBALow_Exp      = (UINT8)RShiftU64(LBA, 24);\r
+  CardData->TaskFile.LBAMid_Exp      = (UINT8)RShiftU64(LBA, 32);\r
+  CardData->TaskFile.LBAHigh_Exp     = (UINT8)RShiftU64(LBA, 40);\r
+\r
+  Status = SendATACommand (\r
+             CardData,\r
+             &CardData->TaskFile,\r
+             TRUE,\r
+             Buffer,\r
+             SectorCount\r
+             );\r
+  return Status;\r
+\r
+}\r
+\r
+\r
+/**\r
+  Judge whether it is CE-ATA device or not.\r
+\r
+  @param  CardData             Pointer to CARD_DATA.\r
+\r
+  @retval TRUE\r
+  @retval FALSE\r
+\r
+**/\r
+BOOLEAN\r
+IsCEATADevice (\r
+  IN  CARD_DATA    *CardData\r
+  )\r
+{\r
+  EFI_STATUS                 Status;\r
+\r
+  Status = ReadWriteMultipleRegister (\r
+             CardData,\r
+             0,\r
+             sizeof (TASK_FILE),\r
+             FALSE,\r
+             (UINT8*)&CardData->TaskFile\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    //\r
+    //To bring back the normal MMC card to work\r
+    //\r
+    CardData->SDHostIo->ResetSDHost (CardData->SDHostIo, Reset_DAT_CMD);\r
+    return FALSE;\r
+  }\r
+\r
+  if (CardData->TaskFile.LBAMid == CE_ATA_SIG_CE &&\r
+      CardData->TaskFile.LBAHigh == CE_ATA_SIG_AA\r
+    ) {\r
+    //\r
+    //Disable Auto CMD for CE-ATA\r
+    //\r
+    CardData->SDHostIo->EnableAutoStopCmd (CardData->SDHostIo, FALSE);\r
+\r
+    return TRUE;\r
+  }\r
+\r
+  return FALSE;\r
+}\r
+\r
+\r
+\r