]> git.proxmox.com Git - mirror_edk2.git/blobdiff - QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/MMCSDBlockIo.c
QuarkSocPkg: Add new package for Quark SoC X1000
[mirror_edk2.git] / QuarkSocPkg / QuarkSouthCluster / Sdio / Dxe / SDMediaDeviceDxe / MMCSDBlockIo.c
diff --git a/QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/MMCSDBlockIo.c b/QuarkSocPkg/QuarkSouthCluster/Sdio/Dxe/SDMediaDeviceDxe/MMCSDBlockIo.c
new file mode 100644 (file)
index 0000000..584c541
--- /dev/null
@@ -0,0 +1,544 @@
+/** @file\r
+\r
+Block I/O protocol for MMC/SD 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
+MMCSDBlockReset (\r
+  IN  EFI_BLOCK_IO_PROTOCOL   *This,\r
+  IN  BOOLEAN                 ExtendedVerification\r
+  )\r
+{\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
+  return SDHostIo->ResetSDHost (SDHostIo, Reset_DAT_CMD);\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
+MMCSDBlockReadBlocks (\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
+  UINT32                      Address;\r
+  CARD_DATA                   *CardData;\r
+  EFI_SD_HOST_IO_PROTOCOL     *SDHostIo;\r
+  UINT32                      RemainingLength;\r
+  UINT32                      TransferLength;\r
+  UINT8                       *BufferPointer;\r
+  BOOLEAN                     SectorAddressing;\r
+  UINTN                       TotalBlock;\r
+\r
+  DEBUG((EFI_D_INFO, "Read(LBA=%08lx, Buffer=%08x, Size=%08x)\n", LBA, Buffer, BufferSize));\r
+  Status   = EFI_SUCCESS;\r
+  CardData  = CARD_DATA_FROM_THIS(This);\r
+  SDHostIo = CardData->SDHostIo;\r
+  if (MediaId != CardData->BlockIoMedia.MediaId) {\r
+    return EFI_MEDIA_CHANGED;\r
+  }\r
+\r
+  if (ModU64x32 (BufferSize,CardData->BlockIoMedia.BlockSize) != 0) {\r
+    return EFI_BAD_BUFFER_SIZE;\r
+  }\r
+  if ((CardData->CardType == SDMemoryCard2High) || (CardData->CardType == MMCCardHighCap)) {\r
+    SectorAddressing = TRUE;\r
+  } else {\r
+    SectorAddressing = FALSE;\r
+  }\r
+  if (SectorAddressing) {\r
+    //\r
+    //Block Address\r
+    //\r
+    Address = (UINT32)DivU64x32 (MultU64x32 (LBA, CardData->BlockIoMedia.BlockSize), 512);\r
+  } else {\r
+    //\r
+    //Byte Address\r
+    //\r
+    Address  = (UINT32)MultU64x32 (LBA, CardData->BlockIoMedia.BlockSize);\r
+  }\r
+  TotalBlock = (UINTN) DivU64x32 (BufferSize, CardData->BlockIoMedia.BlockSize);\r
+  if (LBA + TotalBlock > CardData->BlockIoMedia.LastBlock + 1) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+\r
+  if (!Buffer) {\r
+    Status = EFI_INVALID_PARAMETER;\r
+    DEBUG ((EFI_D_ERROR, "MMCSDBlockReadBlocks:Invalid parameter \r\n"));\r
+    goto Done;\r
+  }\r
+\r
+  if ((BufferSize % CardData->BlockIoMedia.BlockSize) != 0) {\r
+    Status = EFI_BAD_BUFFER_SIZE;\r
+    DEBUG ((EFI_D_ERROR, "MMCSDBlockReadBlocks: Bad buffer size \r\n"));\r
+    goto Done;\r
+  }\r
+\r
+  if (BufferSize == 0) {\r
+    Status = EFI_SUCCESS;\r
+    goto Done;\r
+  }\r
+\r
+\r
+\r
+\r
+    BufferPointer   = Buffer;\r
+    RemainingLength = (UINT32)BufferSize;\r
+\r
+    while (RemainingLength > 0) {\r
+    if ((BufferSize > CardData->BlockIoMedia.BlockSize)) {\r
+      if (RemainingLength > SDHostIo->HostCapability.BoundarySize) {\r
+        TransferLength = SDHostIo->HostCapability.BoundarySize;\r
+      } else {\r
+        TransferLength = RemainingLength;\r
+      }\r
+\r
+      if (CardData->CardType == MMCCard || CardData->CardType == MMCCardHighCap) {\r
+        if (!(CardData->ExtCSDRegister.CARD_TYPE & (BIT2 | BIT3))) {\r
+      Status = SendCommand (\r
+                     CardData,\r
+                     SET_BLOCKLEN,\r
+                     CardData->BlockIoMedia.BlockSize,\r
+                     NoData,\r
+                     NULL,\r
+                     0,\r
+                     ResponseR1,\r
+                     TIMEOUT_COMMAND,\r
+                     (UINT32*)&(CardData->CardStatus)\r
+                     );\r
+          if (EFI_ERROR (Status)) {\r
+            break;\r
+          }\r
+        }\r
+        Status = SendCommand (\r
+                   CardData,\r
+                   SET_BLOCK_COUNT,\r
+                   TransferLength / CardData->BlockIoMedia.BlockSize,\r
+                   NoData,\r
+                   NULL,\r
+                   0,\r
+                   ResponseR1,\r
+                   TIMEOUT_COMMAND,\r
+                   (UINT32*)&(CardData->CardStatus)\r
+                   );\r
+        if (EFI_ERROR (Status)) {\r
+          break;\r
+        }\r
+      }\r
+      Status = SendCommand (\r
+                 CardData,\r
+                 READ_MULTIPLE_BLOCK,\r
+                 Address,\r
+                 InData,\r
+                 CardData->AlignedBuffer,\r
+                 TransferLength,\r
+                 ResponseR1,\r
+                 TIMEOUT_DATA,\r
+                 (UINT32*)&(CardData->CardStatus)\r
+                 );\r
+\r
+      if (EFI_ERROR (Status)) {\r
+        DEBUG ((EFI_D_ERROR, "MMCSDBlockReadBlocks: READ_MULTIPLE_BLOCK -> Fail\n"));\r
+        break;\r
+      }\r
+    } else {\r
+      if (RemainingLength > CardData->BlockIoMedia.BlockSize) {\r
+        TransferLength = CardData->BlockIoMedia.BlockSize;\r
+      } else {\r
+        TransferLength = RemainingLength;\r
+      }\r
+\r
+      Status = SendCommand (\r
+                 CardData,\r
+                 READ_SINGLE_BLOCK,\r
+                 Address,\r
+                 InData,\r
+                 CardData->AlignedBuffer,\r
+                 (UINT32)TransferLength,\r
+                 ResponseR1,\r
+                 TIMEOUT_DATA,\r
+                 (UINT32*)&(CardData->CardStatus)\r
+                 );\r
+      if (EFI_ERROR (Status)) {\r
+        DEBUG ((EFI_D_ERROR, "MMCSDBlockReadBlocks: READ_SINGLE_BLOCK -> Fail\n"));\r
+        break;\r
+      }\r
+    }\r
+      CopyMem (BufferPointer, CardData->AlignedBuffer, TransferLength);\r
+\r
+    if (SectorAddressing) {\r
+        //\r
+        //Block Address\r
+        //\r
+        Address += TransferLength / 512;\r
+      } else {\r
+        //\r
+        //Byte Address\r
+        //\r
+        Address += TransferLength;\r
+      }\r
+      BufferPointer   += TransferLength;\r
+      RemainingLength -= TransferLength;\r
+   }\r
+\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    if ((CardData->CardType == SDMemoryCard) ||\r
+        (CardData->CardType == SDMemoryCard2)||\r
+        (CardData->CardType == SDMemoryCard2High)) {\r
+         SendCommand (\r
+           CardData,\r
+           STOP_TRANSMISSION,\r
+           0,\r
+           NoData,\r
+           NULL,\r
+           0,\r
+           ResponseR1b,\r
+           TIMEOUT_COMMAND,\r
+           (UINT32*)&(CardData->CardStatus)\r
+           );\r
+    } else {\r
+       SendCommand (\r
+         CardData,\r
+         STOP_TRANSMISSION,\r
+         0,\r
+         NoData,\r
+         NULL,\r
+         0,\r
+         ResponseR1,\r
+         TIMEOUT_COMMAND,\r
+         (UINT32*)&(CardData->CardStatus)\r
+         );\r
+    }\r
+\r
+  }\r
+\r
+\r
+Done:\r
+  DEBUG((EFI_D_INFO, "MMCSDBlockReadBlocks: Status = %r\n", Status));\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
+MMCSDBlockWriteBlocks (\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
+  UINT32                      Address;\r
+  CARD_DATA                   *CardData;\r
+  EFI_SD_HOST_IO_PROTOCOL     *SDHostIo;\r
+  UINT32                      RemainingLength;\r
+  UINT32                      TransferLength;\r
+  UINT8                       *BufferPointer;\r
+  BOOLEAN                     SectorAddressing;\r
+\r
+  DEBUG((EFI_D_INFO, "Write(LBA=%08lx, Buffer=%08x, Size=%08x)\n", LBA, Buffer, BufferSize));\r
+  Status   = EFI_SUCCESS;\r
+  CardData  = CARD_DATA_FROM_THIS(This);\r
+  SDHostIo = CardData->SDHostIo;\r
+  if ((CardData->CardType == SDMemoryCard2High) || (CardData->CardType == MMCCardHighCap)) {\r
+    SectorAddressing = TRUE;\r
+  } else {\r
+    SectorAddressing = FALSE;\r
+  }\r
+  if (SectorAddressing) {\r
+    //\r
+    //Block Address\r
+    //\r
+    Address = (UINT32)DivU64x32 (MultU64x32 (LBA, CardData->BlockIoMedia.BlockSize), 512);\r
+  } else {\r
+    //\r
+    //Byte Address\r
+    //\r
+    Address = (UINT32)MultU64x32 (LBA, CardData->BlockIoMedia.BlockSize);\r
+  }\r
+\r
+  if (!Buffer) {\r
+    Status = EFI_INVALID_PARAMETER;\r
+    DEBUG ((EFI_D_ERROR, "MMCSDBlockWriteBlocks: Invalid parameter \r\n"));\r
+    goto Done;\r
+  }\r
+\r
+  if ((BufferSize % CardData->BlockIoMedia.BlockSize) != 0) {\r
+    Status = EFI_BAD_BUFFER_SIZE;\r
+    DEBUG ((EFI_D_ERROR, "MMCSDBlockWriteBlocks: Bad buffer size \r\n"));\r
+    goto Done;\r
+  }\r
+\r
+  if (BufferSize == 0) {\r
+    Status = EFI_SUCCESS;\r
+    goto Done;\r
+  }\r
+\r
+  if (This->Media->ReadOnly == TRUE) {\r
+    Status = EFI_WRITE_PROTECTED;\r
+    DEBUG ((EFI_D_ERROR, "MMCSDBlockWriteBlocks: Write protected \r\n"));\r
+    goto Done;\r
+  }\r
+\r
+\r
+\r
+    BufferPointer   = Buffer;\r
+    RemainingLength = (UINT32)BufferSize;\r
+\r
+    while (RemainingLength > 0) {\r
+    if ((BufferSize > CardData->BlockIoMedia.BlockSize) ) {\r
+      if (RemainingLength > SDHostIo->HostCapability.BoundarySize) {\r
+        TransferLength = SDHostIo->HostCapability.BoundarySize;\r
+      } else {\r
+        TransferLength = RemainingLength;\r
+      }\r
+\r
+      if (CardData->CardType == MMCCard || CardData->CardType == MMCCardHighCap) {\r
+\r
+        if (!(CardData->ExtCSDRegister.CARD_TYPE & (BIT2 | BIT3)))  {\r
+            Status = SendCommand (\r
+                       CardData,\r
+                       SET_BLOCKLEN,\r
+                       CardData->BlockIoMedia.BlockSize,\r
+                       NoData,\r
+                       NULL,\r
+                       0,\r
+                       ResponseR1,\r
+                       TIMEOUT_COMMAND,\r
+                       (UINT32*)&(CardData->CardStatus)\r
+                       );\r
+            if (EFI_ERROR (Status)) {\r
+              break;\r
+            }\r
+        }\r
+        Status = SendCommand (\r
+                      CardData,\r
+                   SET_BLOCK_COUNT,\r
+                   TransferLength / CardData->BlockIoMedia.BlockSize,\r
+                      NoData,\r
+                      NULL,\r
+                      0,\r
+                      ResponseR1,\r
+                      TIMEOUT_COMMAND,\r
+                      (UINT32*)&(CardData->CardStatus)\r
+                      );\r
+        if (EFI_ERROR (Status)) {\r
+          break;\r
+        }\r
+      }\r
+\r
+      CopyMem (CardData->AlignedBuffer, BufferPointer, TransferLength);\r
+\r
+      Status = SendCommand (\r
+                 CardData,\r
+                 WRITE_MULTIPLE_BLOCK,\r
+                 Address,\r
+                 OutData,\r
+                 CardData->AlignedBuffer,\r
+                 (UINT32)TransferLength,\r
+                 ResponseR1,\r
+                 TIMEOUT_DATA,\r
+                 (UINT32*)&(CardData->CardStatus)\r
+                 );\r
+      if (EFI_ERROR (Status)) {\r
+        DEBUG ((EFI_D_ERROR, "MMCSDBlockWriteBlocks: WRITE_MULTIPLE_BLOCK -> Fail\n"));\r
+        break;\r
+      }\r
+    } else {\r
+      if (RemainingLength > CardData->BlockIoMedia.BlockSize) {\r
+        TransferLength = CardData->BlockIoMedia.BlockSize;\r
+      } else {\r
+        TransferLength = RemainingLength;\r
+      }\r
+\r
+      CopyMem (CardData->AlignedBuffer, BufferPointer, TransferLength);\r
+\r
+      Status = SendCommand (\r
+                 CardData,\r
+                 WRITE_BLOCK,\r
+                 Address,\r
+                 OutData,\r
+                 CardData->AlignedBuffer,\r
+                 (UINT32)TransferLength,\r
+                 ResponseR1,\r
+                 TIMEOUT_DATA,\r
+                 (UINT32*)&(CardData->CardStatus)\r
+                 );\r
+    }\r
+    if (SectorAddressing) {\r
+        //\r
+        //Block Address\r
+        //\r
+        Address += TransferLength / 512;\r
+      } else {\r
+        //\r
+        //Byte Address\r
+        //\r
+        Address += TransferLength;\r
+      }\r
+      BufferPointer   += TransferLength;\r
+      RemainingLength -= TransferLength;\r
+\r
+  }\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    SendCommand (\r
+      CardData,\r
+      STOP_TRANSMISSION,\r
+      0,\r
+      NoData,\r
+      NULL,\r
+      0,\r
+      ResponseR1b,\r
+      TIMEOUT_COMMAND,\r
+      (UINT32*)&(CardData->CardStatus)\r
+      );\r
+\r
+  }\r
+\r
+\r
+Done:\r
+  return EFI_SUCCESS;\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
+MMCSDBlockFlushBlocks (\r
+  IN  EFI_BLOCK_IO_PROTOCOL   *This\r
+  )\r
+{\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  MMC/SD 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
+MMCSDBlockIoInit (\r
+  IN  CARD_DATA    *CardData\r
+  )\r
+{\r
+  //\r
+  //BlockIO protocol\r
+  //\r
+  CardData->BlockIo.Revision    = EFI_BLOCK_IO_PROTOCOL_REVISION;\r
+  CardData->BlockIo.Media       = &(CardData->BlockIoMedia);\r
+  CardData->BlockIo.Reset       = MMCSDBlockReset;\r
+  CardData->BlockIo.ReadBlocks  = MMCSDBlockReadBlocks ;\r
+  CardData->BlockIo.WriteBlocks = MMCSDBlockWriteBlocks;\r
+  CardData->BlockIo.FlushBlocks = MMCSDBlockFlushBlocks;\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.BlockSize        = CardData->BlockLen;\r
+  CardData->BlockIoMedia.IoAlign          = 1;\r
+  CardData->BlockIoMedia.LastBlock        = (EFI_LBA)(CardData->BlockNumber - 1);\r
+\r
+\r
+  return EFI_SUCCESS;\r
+\r
+}\r
+\r
+\r
+\r