]> git.proxmox.com Git - mirror_edk2.git/blobdiff - QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/CEATABlockIo.c
QuarkSocPkg: Add new package for Quark SoC X1000
[mirror_edk2.git] / QuarkSocPkg / QuarkSouthCluster / Sdio / Dxe / SDMediaDeviceDxe / CEATABlockIo.c
diff --git a/QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/CEATABlockIo.c b/QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/CEATABlockIo.c
new file mode 100644 (file)
index 0000000..a9addec
--- /dev/null
@@ -0,0 +1,396 @@
+/** @file\r
+\r
+Block I/O protocol for CE-ATA device\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
+  Implements EFI_BLOCK_IO_PROTOCOL.Reset() function.\r
+\r
+  @param  This                   The EFI_BLOCK_IO_PROTOCOL instance.\r
+  @param  ExtendedVerification   Indicates that the driver may perform a more exhaustive.\r
+                                 verification operation of the device during reset.\r
+                                 (This parameter is ingored in this driver.)\r
+\r
+  @retval EFI_SUCCESS                Success\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+CEATABlockReset (\r
+  IN  EFI_BLOCK_IO_PROTOCOL   *This,\r
+  IN  BOOLEAN                 ExtendedVerification\r
+  )\r
+{\r
+  EFI_STATUS                 Status;\r
+  CARD_DATA                  *CardData;\r
+  EFI_SD_HOST_IO_PROTOCOL    *SDHostIo;\r
+\r
+  CardData  = CARD_DATA_FROM_THIS(This);\r
+  SDHostIo = CardData->SDHostIo;\r
+\r
+  if (!ExtendedVerification) {\r
+    Status = SoftwareReset (CardData);\r
+  } else {\r
+    Status = SDHostIo->ResetSDHost (SDHostIo, Reset_DAT_CMD);\r
+    if (EFI_ERROR (Status)) {\r
+    DEBUG((EFI_D_ERROR, "CEATABlockReset: Fail to ResetSDHost\n" ));\r
+      return Status;\r
+    }\r
+    Status = MMCSDCardInit (CardData);\r
+  }\r
+\r
+\r
+  return Status;\r
+\r
+ }\r
+\r
+/**\r
+  Implements EFI_BLOCK_IO_PROTOCOL.ReadBlocks() function.\r
+\r
+  @param  This                   The EFI_BLOCK_IO_PROTOCOL instance.\r
+  @param  MediaId                The media id that the write request is for.\r
+  @param  LBA                    The starting logical block address to read from on the device.\r
+                                 The caller is responsible for writing to only legitimate locations.\r
+  @param  BufferSize             The size of the Buffer in bytes. This must be a multiple of the\r
+                                 intrinsic block size of 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
+\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
+EFI_STATUS\r
+EFIAPI\r
+CEATABlockReadBlocks (\r
+  IN  EFI_BLOCK_IO_PROTOCOL   *This,\r
+  IN  UINT32                  MediaId,\r
+  IN  EFI_LBA                 LBA,\r
+  IN  UINTN                   BufferSize,\r
+  OUT VOID                    *Buffer\r
+  )\r
+{\r
+  EFI_STATUS                  Status;\r
+  CARD_DATA                   *CardData;\r
+  UINT32                      TransferSize;\r
+  UINT8                       *pBuf;\r
+  UINT32                      Index;\r
+  UINT64                      Address;\r
+  UINT32                      Remainder;\r
+  UINT64                      CEATALBA;\r
+  UINT32                      BoundarySize;\r
+\r
+  Status       = EFI_SUCCESS;\r
+  CardData     = CARD_DATA_FROM_THIS(This);\r
+  pBuf         = Buffer;\r
+  Index        = 0;\r
+  Address      = MultU64x32(LBA, CardData->BlockIoMedia.BlockSize);\r
+  BoundarySize = CardData->SDHostIo->HostCapability.BoundarySize;\r
+\r
+  if (!Buffer) {\r
+    Status = EFI_INVALID_PARAMETER;\r
+    DEBUG((EFI_D_ERROR, "CEATABlockReadBlocks:Invalid parameter\n" ));\r
+    goto Exit;\r
+  }\r
+\r
+  if (MediaId != CardData->BlockIoMedia.MediaId) {\r
+    Status = EFI_MEDIA_CHANGED;\r
+  DEBUG((EFI_D_ERROR, "CEATABlockReadBlocks:Media changed\n" ));\r
+    goto Exit;\r
+  }\r
+\r
+  if ((BufferSize % CardData->BlockIoMedia.BlockSize) != 0) {\r
+    Status = EFI_BAD_BUFFER_SIZE;\r
+  DEBUG((EFI_D_ERROR, "CEATABlockReadBlocks:Bad buffer size\n" ));\r
+    goto Exit;\r
+  }\r
+\r
+  if (BufferSize == 0) {\r
+    Status = EFI_SUCCESS;\r
+    goto Exit;\r
+  }\r
+\r
+  if ((Address + BufferSize) > MultU64x32 (CardData->BlockIoMedia.LastBlock + 1, CardData->BlockIoMedia.BlockSize)) {\r
+    Status = EFI_INVALID_PARAMETER;\r
+    DEBUG((EFI_D_ERROR, "CEATABlockReadBlocks:Invalid parameter\n" ));\r
+    goto Exit;\r
+  }\r
+\r
+\r
+  do {\r
+    if (BufferSize < BoundarySize) {\r
+      TransferSize = (UINT32)BufferSize;\r
+    } else {\r
+      TransferSize = BoundarySize;\r
+    }\r
+\r
+    Address += Index * TransferSize;\r
+    CEATALBA = DivU64x32Remainder (Address, DATA_UNIT_SIZE, &Remainder);\r
+    ASSERT(Remainder == 0);\r
+\r
+    Status = ReadDMAExt (\r
+               CardData,\r
+               CEATALBA,\r
+               pBuf,\r
+               (UINT16)(TransferSize / DATA_UNIT_SIZE)\r
+               );\r
+    if (EFI_ERROR (Status)) {\r
+     DEBUG((EFI_D_ERROR, "Read Failed at 0x%x, Index %d, Size 0x%x\n", Address, Index, TransferSize));\r
+     This->Reset (This, TRUE);\r
+     goto Exit;\r
+    }\r
+    BufferSize -= TransferSize;\r
+    pBuf       += TransferSize;\r
+    Index ++;\r
+  } while (BufferSize != 0);\r
+\r
+\r
+Exit:\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Implements EFI_BLOCK_IO_PROTOCOL.WriteBlocks() function.\r
+\r
+  @param  This                   The EFI_BLOCK_IO_PROTOCOL instance.\r
+  @param  MediaId                The media id that the write request is for.\r
+  @param  LBA                    The starting logical block address to read from on the device.\r
+                                 The caller is responsible for writing to only legitimate locations.\r
+  @param  BufferSize             The size of the Buffer in bytes. This must be a multiple of the\r
+                                 intrinsic block size of 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
+\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
+EFI_STATUS\r
+EFIAPI\r
+CEATABlockWriteBlocks (\r
+  IN  EFI_BLOCK_IO_PROTOCOL   *This,\r
+  IN  UINT32                  MediaId,\r
+  IN  EFI_LBA                 LBA,\r
+  IN  UINTN                   BufferSize,\r
+  IN  VOID                    *Buffer\r
+  )\r
+{\r
+  EFI_STATUS                  Status;\r
+  CARD_DATA                   *CardData;\r
+  UINT32                      TransferSize;\r
+  UINT8                       *pBuf;\r
+  UINT32                      Index;\r
+  UINT64                      Address;\r
+  UINT32                      Remainder;\r
+  UINT64                      CEATALBA;\r
+  UINT32                      BoundarySize;\r
+\r
+\r
+  Status       = EFI_SUCCESS;\r
+  CardData     = CARD_DATA_FROM_THIS(This);\r
+  pBuf         = Buffer;\r
+  Index        = 0;\r
+  Address      = MultU64x32(LBA, CardData->BlockIoMedia.BlockSize);\r
+  BoundarySize = CardData->SDHostIo->HostCapability.BoundarySize;\r
+\r
+\r
+  if (!Buffer) {\r
+    Status = EFI_INVALID_PARAMETER;\r
+    goto Exit;\r
+  }\r
+\r
+  if (MediaId != CardData->BlockIoMedia.MediaId) {\r
+    Status = EFI_MEDIA_CHANGED;\r
+    goto Exit;\r
+  }\r
+\r
+  if ((BufferSize % CardData->BlockIoMedia.BlockSize) != 0) {\r
+    Status = EFI_BAD_BUFFER_SIZE;\r
+    goto Exit;\r
+  }\r
+\r
+  if (BufferSize == 0) {\r
+    Status = EFI_SUCCESS;\r
+    goto Exit;\r
+  }\r
+\r
+  if (CardData->BlockIoMedia.ReadOnly) {\r
+    Status = EFI_WRITE_PROTECTED;\r
+    goto Exit;\r
+  }\r
+\r
+  if ((Address + BufferSize) > MultU64x32 (CardData->BlockIoMedia.LastBlock + 1, CardData->BlockIoMedia.BlockSize)) {\r
+    Status = EFI_INVALID_PARAMETER;\r
+    goto Exit;\r
+  }\r
+\r
+  CardData->NeedFlush = TRUE;\r
+\r
+  do {\r
+    if (BufferSize < BoundarySize) {\r
+      TransferSize = (UINT32)BufferSize;\r
+    } else {\r
+      TransferSize = BoundarySize;\r
+    }\r
+\r
+    Address += Index * TransferSize;\r
+    CEATALBA = DivU64x32Remainder (Address, DATA_UNIT_SIZE, &Remainder);\r
+    ASSERT(Remainder == 0);\r
+\r
+    Status = WriteDMAExt (\r
+               CardData,\r
+               CEATALBA,\r
+               pBuf,\r
+               (UINT16)(TransferSize / DATA_UNIT_SIZE)\r
+               );\r
+    if (EFI_ERROR (Status)) {\r
+     DEBUG((EFI_D_ERROR, "Write Failed at 0x%x, Index %d, Size 0x%x\n", Address, Index, TransferSize));\r
+     This->Reset (This, TRUE);\r
+     goto Exit;\r
+    }\r
+    BufferSize -= TransferSize;\r
+    pBuf       += TransferSize;\r
+    Index ++;\r
+  } while (BufferSize != 0);\r
+\r
+\r
+Exit:\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Implements EFI_BLOCK_IO_PROTOCOL.FlushBlocks() function.\r
+    (In this driver, this function just returns EFI_SUCCESS.)\r
+\r
+  @param  This                   The EFI_BLOCK_IO_PROTOCOL instance.\r
+\r
+  @retval EFI_SUCCESS\r
+  @retval Others\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+CEATABlockFlushBlocks (\r
+  IN  EFI_BLOCK_IO_PROTOCOL   *This\r
+  )\r
+{\r
+\r
+  EFI_STATUS                  Status;\r
+  CARD_DATA                   *CardData;\r
+\r
+  CardData  = CARD_DATA_FROM_THIS(This);\r
+\r
+  if (CardData->NeedFlush) {\r
+    CardData->NeedFlush = FALSE;\r
+    Status = FlushCache (CardData);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  CEATA card BlockIo init function.\r
+\r
+  @param  CardData               Pointer to CARD_DATA.\r
+\r
+  @retval EFI_SUCCESS\r
+  @retval Others\r
+**/\r
+EFI_STATUS\r
+CEATABlockIoInit (\r
+  IN  CARD_DATA    *CardData\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    CEATA card BlockIo init function\r
+\r
+  Arguments:\r
+    CardData  -   Pointer to CARD_DATA\r
+\r
+  Returns:\r
+    EFI_SUCCESS - Success\r
+--*/\r
+{\r
+  EFI_STATUS   Status;\r
+  UINT64       MaxSize;\r
+  UINT32       Remainder;\r
+  //\r
+  //BlockIO protocol\r
+  //\r
+  CardData->BlockIo.Revision    = EFI_BLOCK_IO_PROTOCOL_REVISION;\r
+  CardData->BlockIo.Media       = &(CardData->BlockIoMedia);\r
+  CardData->BlockIo.Reset       = CEATABlockReset;\r
+  CardData->BlockIo.ReadBlocks  = CEATABlockReadBlocks ;\r
+  CardData->BlockIo.WriteBlocks = CEATABlockWriteBlocks;\r
+  CardData->BlockIo.FlushBlocks = CEATABlockFlushBlocks;\r
+\r
+  CardData->BlockIoMedia.MediaId          = 0;\r
+  CardData->BlockIoMedia.RemovableMedia   = FALSE;\r
+  CardData->BlockIoMedia.MediaPresent     = TRUE;\r
+  CardData->BlockIoMedia.LogicalPartition = FALSE;\r
+\r
+  if (CardData->CSDRegister.PERM_WRITE_PROTECT | CardData->CSDRegister.TMP_WRITE_PROTECT) {\r
+    CardData->BlockIoMedia.ReadOnly       = TRUE;\r
+  } else {\r
+    CardData->BlockIoMedia.ReadOnly       = FALSE;\r
+  }\r
+\r
+\r
+  CardData->BlockIoMedia.WriteCaching     = FALSE;\r
+  CardData->BlockIoMedia.IoAlign          = 1;\r
+\r
+  Status = IndentifyDevice (CardData);\r
+  if (EFI_ERROR (Status)) {\r
+   goto Exit;\r
+  }\r
+\r
+  //\r
+  //Some device does not support this feature\r
+  //\r
+\r
+  if (CardData->IndentifyDeviceData.MaxWritesPerAddress == 0) {\r
+    CardData->BlockIoMedia.ReadOnly       = TRUE;\r
+  }\r
+\r
+  CardData->BlockIoMedia.BlockSize        = (1 << CardData->IndentifyDeviceData.Sectorsize);\r
+  ASSERT(CardData->BlockIoMedia.BlockSize >= 12);\r
+\r
+\r
+  MaxSize = *(UINT64*)(CardData->IndentifyDeviceData.MaximumLBA);\r
+  MaxSize = MultU64x32 (MaxSize, 512);\r
+\r
+  Remainder = 0;\r
+  CardData->BlockNumber = DivU64x32Remainder (MaxSize, CardData->BlockIoMedia.BlockSize, &Remainder);\r
+  ASSERT(Remainder == 0);\r
+\r
+  CardData->BlockIoMedia.LastBlock        = (EFI_LBA)(CardData->BlockNumber - 1);\r
+\r
+\r
+Exit:\r
+  return Status;\r
+\r
+}\r
+\r
+\r
+\r