]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c
MdeModulePkg/SdMmcPciHcDxe: Fix PIO transfer mode
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / SdMmcPciHcDxe / SdMmcPciHci.c
index d6294eb4c88a15d126f30eeeeda4711661618ca4..6548ef71dee1d7797bde8bcd06744e92f77d9918 100644 (file)
@@ -1712,8 +1712,11 @@ SdMmcPrintTrb (
   DEBUG ((DebugLevel, "AdmaLengthMode: %d\n", Trb->AdmaLengthMode));\r
   DEBUG ((DebugLevel, "Event: %p\n", Trb->Event));\r
   DEBUG ((DebugLevel, "Started: %d\n", Trb->Started));\r
+  DEBUG ((DebugLevel, "CommandComplete: %d\n", Trb->CommandComplete));\r
   DEBUG ((DebugLevel, "Timeout: %ld\n", Trb->Timeout));\r
   DEBUG ((DebugLevel, "Retries: %d\n", Trb->Retries));\r
+  DEBUG ((DebugLevel, "PioModeTransferCompleted: %d\n", Trb->PioModeTransferCompleted));\r
+  DEBUG ((DebugLevel, "PioBlockIndex: %d\n", Trb->PioBlockIndex));\r
   DEBUG ((DebugLevel, "Adma32Desc: %p\n", Trb->Adma32Desc));\r
   DEBUG ((DebugLevel, "Adma64V3Desc: %p\n", Trb->Adma64V3Desc));\r
   DEBUG ((DebugLevel, "Adma64V4Desc: %p\n", Trb->Adma64V4Desc));\r
@@ -1723,6 +1726,62 @@ SdMmcPrintTrb (
   SdMmcPrintPacket (DebugLevel, Trb->Packet);\r
 }\r
 \r
+/**\r
+  Sets up host memory to allow DMA transfer.\r
+\r
+  @param[in] Private  A pointer to the SD_MMC_HC_PRIVATE_DATA instance.\r
+  @param[in] Slot     The slot number of the SD card to send the command to.\r
+  @param[in] Packet   A pointer to the SD command data structure.\r
+\r
+  @retval EFI_SUCCESS  Memory has been mapped for DMA transfer.\r
+  @retval Others       Memory has not been mapped.\r
+**/\r
+EFI_STATUS\r
+SdMmcSetupMemoryForDmaTransfer (\r
+  IN SD_MMC_HC_PRIVATE_DATA  *Private,\r
+  IN UINT8                   Slot,\r
+  IN SD_MMC_HC_TRB           *Trb\r
+  )\r
+{\r
+  EFI_PCI_IO_PROTOCOL_OPERATION Flag;\r
+  EFI_PCI_IO_PROTOCOL           *PciIo;\r
+  UINTN                         MapLength;\r
+  EFI_STATUS                    Status;\r
+\r
+  if (Trb->Read) {\r
+    Flag = EfiPciIoOperationBusMasterWrite;\r
+  } else {\r
+    Flag = EfiPciIoOperationBusMasterRead;\r
+  }\r
+\r
+  PciIo = Private->PciIo;\r
+  if (Trb->Data != NULL && Trb->DataLen != 0) {\r
+    MapLength = Trb->DataLen;\r
+    Status = PciIo->Map (\r
+                      PciIo,\r
+                      Flag,\r
+                      Trb->Data,\r
+                      &MapLength,\r
+                      &Trb->DataPhy,\r
+                      &Trb->DataMap\r
+                      );\r
+    if (EFI_ERROR (Status) || (Trb->DataLen != MapLength)) {\r
+      return EFI_BAD_BUFFER_SIZE;\r
+    }\r
+  }\r
+\r
+  if (Trb->Mode == SdMmcAdma32bMode ||\r
+      Trb->Mode == SdMmcAdma64bV3Mode ||\r
+      Trb->Mode == SdMmcAdma64bV4Mode) {\r
+    Status = BuildAdmaDescTable (Trb, Private->ControllerVersion[Slot]);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
 /**\r
   Create a new TRB for the SD/MMC cmd request.\r
 \r
@@ -1747,9 +1806,6 @@ SdMmcCreateTrb (
   SD_MMC_HC_TRB                 *Trb;\r
   EFI_STATUS                    Status;\r
   EFI_TPL                       OldTpl;\r
-  EFI_PCI_IO_PROTOCOL_OPERATION Flag;\r
-  EFI_PCI_IO_PROTOCOL           *PciIo;\r
-  UINTN                         MapLength;\r
 \r
   Trb = AllocateZeroPool (sizeof (SD_MMC_HC_TRB));\r
   if (Trb == NULL) {\r
@@ -1762,8 +1818,11 @@ SdMmcCreateTrb (
   Trb->Packet    = Packet;\r
   Trb->Event     = Event;\r
   Trb->Started   = FALSE;\r
+  Trb->CommandComplete = FALSE;\r
   Trb->Timeout   = Packet->Timeout;\r
   Trb->Retries   = SD_MMC_TRB_RETRIES;\r
+  Trb->PioModeTransferCompleted = FALSE;\r
+  Trb->PioBlockIndex = 0;\r
   Trb->Private   = Private;\r
 \r
   if ((Packet->InTransferLength != 0) && (Packet->InDataBuffer != NULL)) {\r
@@ -1791,29 +1850,6 @@ SdMmcCreateTrb (
        (Packet->SdMmcCmdBlk->CommandIndex == SD_SEND_TUNING_BLOCK))) {\r
     Trb->Mode = SdMmcPioMode;\r
   } else {\r
-    if (Trb->Read) {\r
-      Flag = EfiPciIoOperationBusMasterWrite;\r
-    } else {\r
-      Flag = EfiPciIoOperationBusMasterRead;\r
-    }\r
-\r
-    PciIo = Private->PciIo;\r
-    if (Trb->DataLen != 0) {\r
-      MapLength = Trb->DataLen;\r
-      Status = PciIo->Map (\r
-                        PciIo,\r
-                        Flag,\r
-                        Trb->Data,\r
-                        &MapLength,\r
-                        &Trb->DataPhy,\r
-                        &Trb->DataMap\r
-                        );\r
-      if (EFI_ERROR (Status) || (Trb->DataLen != MapLength)) {\r
-        Status = EFI_BAD_BUFFER_SIZE;\r
-        goto Error;\r
-      }\r
-    }\r
-\r
     if (Trb->DataLen == 0) {\r
       Trb->Mode = SdMmcNoData;\r
     } else if (Private->Capability[Slot].Adma2 != 0) {\r
@@ -1831,12 +1867,16 @@ SdMmcCreateTrb (
       if (Private->ControllerVersion[Slot] >= SD_MMC_HC_CTRL_VER_410) {\r
         Trb->AdmaLengthMode = SdMmcAdmaLen26b;\r
       }\r
-      Status = BuildAdmaDescTable (Trb, Private->ControllerVersion[Slot]);\r
+      Status = SdMmcSetupMemoryForDmaTransfer (Private, Slot, Trb);\r
       if (EFI_ERROR (Status)) {\r
         goto Error;\r
       }\r
     } else if (Private->Capability[Slot].Sdma != 0) {\r
       Trb->Mode = SdMmcSdmaMode;\r
+      Status = SdMmcSetupMemoryForDmaTransfer (Private, Slot, Trb);\r
+      if (EFI_ERROR (Status)) {\r
+        goto Error;\r
+      }\r
     } else {\r
       Trb->Mode = SdMmcPioMode;\r
     }\r
@@ -2352,6 +2392,310 @@ SdMmcCheckAndRecoverErrors (
   return ErrorStatus;\r
 }\r
 \r
+/**\r
+  Reads the response data into the TRB buffer.\r
+  This function assumes that caller made sure that\r
+  command has completed.\r
+\r
+  @param[in] Private  A pointer to the SD_MMC_HC_PRIVATE_DATA instance.\r
+  @param[in] Trb      The pointer to the SD_MMC_HC_TRB instance.\r
+\r
+  @retval EFI_SUCCESS  Response read successfully.\r
+  @retval Others       Failed to get response.\r
+**/\r
+EFI_STATUS\r
+SdMmcGetResponse (\r
+  IN SD_MMC_HC_PRIVATE_DATA  *Private,\r
+  IN SD_MMC_HC_TRB           *Trb\r
+  )\r
+{\r
+  EFI_SD_MMC_PASS_THRU_COMMAND_PACKET  *Packet;\r
+  UINT8                                Index;\r
+  UINT32                               Response[4];\r
+  EFI_STATUS                           Status;\r
+\r
+  Packet = Trb->Packet;\r
+\r
+  if (Packet->SdMmcCmdBlk->CommandType == SdMmcCommandTypeBc) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  for (Index = 0; Index < 4; Index++) {\r
+    Status = SdMmcHcRwMmio (\r
+               Private->PciIo,\r
+               Trb->Slot,\r
+               SD_MMC_HC_RESPONSE + Index * 4,\r
+               TRUE,\r
+               sizeof (UINT32),\r
+               &Response[Index]\r
+               );\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+    }\r
+  CopyMem (Packet->SdMmcStatusBlk, Response, sizeof (Response));\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Checks if the command completed. If the command\r
+  completed it gets the response and records the\r
+  command completion in the TRB.\r
+\r
+  @param[in] Private    A pointer to the SD_MMC_HC_PRIVATE_DATA instance.\r
+  @param[in] Trb        The pointer to the SD_MMC_HC_TRB instance.\r
+  @param[in] IntStatus  Snapshot of the normal interrupt status register.\r
+\r
+  @retval EFI_SUCCESS   Command completed successfully.\r
+  @retval EFI_NOT_READY Command completion still pending.\r
+  @retval Others        Command failed to complete.\r
+**/\r
+EFI_STATUS\r
+SdMmcCheckCommandComplete (\r
+  IN SD_MMC_HC_PRIVATE_DATA  *Private,\r
+  IN SD_MMC_HC_TRB           *Trb,\r
+  IN UINT16                  IntStatus\r
+  )\r
+{\r
+  UINT16      Data16;\r
+  EFI_STATUS  Status;\r
+\r
+  if ((IntStatus & BIT0) != 0) {\r
+    Data16 = BIT0;\r
+    Status = SdMmcHcRwMmio (\r
+               Private->PciIo,\r
+               Trb->Slot,\r
+               SD_MMC_HC_NOR_INT_STS,\r
+               FALSE,\r
+               sizeof (Data16),\r
+               &Data16\r
+               );\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+    Status = SdMmcGetResponse (Private, Trb);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+    Trb->CommandComplete = TRUE;\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  return EFI_NOT_READY;\r
+}\r
+\r
+/**\r
+  Transfers data from card using PIO method.\r
+\r
+  @param[in] Private    A pointer to the SD_MMC_HC_PRIVATE_DATA instance.\r
+  @param[in] Trb        The pointer to the SD_MMC_HC_TRB instance.\r
+  @param[in] IntStatus  Snapshot of the normal interrupt status register.\r
+\r
+  @retval EFI_SUCCESS   PIO transfer completed successfully.\r
+  @retval EFI_NOT_READY PIO transfer completion still pending.\r
+  @retval Others        PIO transfer failed to complete.\r
+**/\r
+EFI_STATUS\r
+SdMmcTransferDataWithPio (\r
+  IN SD_MMC_HC_PRIVATE_DATA  *Private,\r
+  IN SD_MMC_HC_TRB           *Trb,\r
+  IN UINT16                  IntStatus\r
+  )\r
+{\r
+  EFI_STATUS                  Status;\r
+  UINT16                      Data16;\r
+  UINT32                      BlockCount;\r
+  EFI_PCI_IO_PROTOCOL_WIDTH  Width;\r
+  UINTN                       Count;\r
+\r
+  BlockCount = (Trb->DataLen / Trb->BlockSize);\r
+  if (Trb->DataLen % Trb->BlockSize != 0) {\r
+    BlockCount += 1;\r
+  }\r
+\r
+  if (Trb->PioBlockIndex >= BlockCount) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  switch (Trb->BlockSize % sizeof (UINT32)) {\r
+    case 0:\r
+      Width = EfiPciIoWidthFifoUint32;\r
+      Count = Trb->BlockSize / sizeof (UINT32);\r
+      break;\r
+    case 2:\r
+      Width = EfiPciIoWidthFifoUint16;\r
+      Count = Trb->BlockSize / sizeof (UINT16);\r
+      break;\r
+    case 1:\r
+    case 3:\r
+    default:\r
+      Width = EfiPciIoWidthFifoUint8;\r
+      Count = Trb->BlockSize;\r
+      break;\r
+    }\r
+\r
+  if (Trb->Read) {\r
+    if ((IntStatus & BIT5) == 0) {\r
+      return EFI_NOT_READY;\r
+    }\r
+    Data16 = BIT5;\r
+    SdMmcHcRwMmio (Private->PciIo, Trb->Slot, SD_MMC_HC_NOR_INT_STS, FALSE, sizeof (Data16), &Data16);\r
+\r
+    Status = Private->PciIo->Mem.Read (\r
+               Private->PciIo,\r
+               Width,\r
+               Trb->Slot,\r
+               SD_MMC_HC_BUF_DAT_PORT,\r
+               Count,\r
+               (VOID*)((UINT8*)Trb->Data + (Trb->BlockSize * Trb->PioBlockIndex))\r
+               );\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+    Trb->PioBlockIndex++;\r
+  } else {\r
+    if ((IntStatus & BIT4) == 0) {\r
+      return EFI_NOT_READY;\r
+    }\r
+    Data16 = BIT4;\r
+    SdMmcHcRwMmio (Private->PciIo, Trb->Slot, SD_MMC_HC_NOR_INT_STS, FALSE, sizeof (Data16), &Data16);\r
+\r
+    Status = Private->PciIo->Mem.Write (\r
+               Private->PciIo,\r
+               Width,\r
+               Trb->Slot,\r
+               SD_MMC_HC_BUF_DAT_PORT,\r
+               Count,\r
+               (VOID*)((UINT8*)Trb->Data + (Trb->BlockSize * Trb->PioBlockIndex))\r
+               );\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+    Trb->PioBlockIndex++;\r
+  }\r
+\r
+  if (Trb->PioBlockIndex >= BlockCount) {\r
+    Trb->PioModeTransferCompleted = TRUE;\r
+    return EFI_SUCCESS;\r
+  } else {\r
+    return EFI_NOT_READY;\r
+  }\r
+}\r
+\r
+/**\r
+  Update the SDMA address on the SDMA buffer boundary interrupt.\r
+\r
+  @param[in] Private    A pointer to the SD_MMC_HC_PRIVATE_DATA instance.\r
+  @param[in] Trb        The pointer to the SD_MMC_HC_TRB instance.\r
+\r
+  @retval EFI_SUCCESS  Updated SDMA buffer address.\r
+  @retval Others       Failed to update SDMA buffer address.\r
+**/\r
+EFI_STATUS\r
+SdMmcUpdateSdmaAddress (\r
+  IN SD_MMC_HC_PRIVATE_DATA  *Private,\r
+  IN SD_MMC_HC_TRB           *Trb\r
+  )\r
+{\r
+  UINT64      SdmaAddr;\r
+  EFI_STATUS  Status;\r
+\r
+  SdmaAddr = SD_MMC_SDMA_ROUND_UP ((UINTN)Trb->DataPhy, SD_MMC_SDMA_BOUNDARY);\r
+\r
+  if (Private->ControllerVersion[Trb->Slot] >= SD_MMC_HC_CTRL_VER_400) {\r
+    Status = SdMmcHcRwMmio (\r
+               Private->PciIo,\r
+               Trb->Slot,\r
+               SD_MMC_HC_ADMA_SYS_ADDR,\r
+               FALSE,\r
+               sizeof (UINT64),\r
+               &SdmaAddr\r
+               );\r
+  } else {\r
+    Status = SdMmcHcRwMmio (\r
+               Private->PciIo,\r
+               Trb->Slot,\r
+               SD_MMC_HC_SDMA_ADDR,\r
+               FALSE,\r
+               sizeof (UINT32),\r
+               &SdmaAddr\r
+               );\r
+  }\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Trb->DataPhy = (UINT64)(UINTN)SdmaAddr;\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Checks if the data transfer completed and performs any actions\r
+  neccessary to continue the data transfer such as SDMA system\r
+  address fixup or PIO data transfer.\r
+\r
+  @param[in] Private    A pointer to the SD_MMC_HC_PRIVATE_DATA instance.\r
+  @param[in] Trb        The pointer to the SD_MMC_HC_TRB instance.\r
+  @param[in] IntStatus  Snapshot of the normal interrupt status register.\r
+\r
+  @retval EFI_SUCCESS   Data transfer completed successfully.\r
+  @retval EFI_NOT_READY Data transfer completion still pending.\r
+  @retval Others        Data transfer failed to complete.\r
+**/\r
+EFI_STATUS\r
+SdMmcCheckDataTransfer (\r
+  IN SD_MMC_HC_PRIVATE_DATA  *Private,\r
+  IN SD_MMC_HC_TRB           *Trb,\r
+  IN UINT16                  IntStatus\r
+  )\r
+{\r
+  UINT16      Data16;\r
+  EFI_STATUS  Status;\r
+\r
+  if ((IntStatus & BIT1) != 0) {\r
+    Data16 = BIT1;\r
+    Status = SdMmcHcRwMmio (\r
+               Private->PciIo,\r
+               Trb->Slot,\r
+               SD_MMC_HC_NOR_INT_STS,\r
+               FALSE,\r
+               sizeof (Data16),\r
+               &Data16\r
+               );\r
+    return Status;\r
+  }\r
+\r
+  if (Trb->Mode == SdMmcPioMode && !Trb->PioModeTransferCompleted) {\r
+    Status = SdMmcTransferDataWithPio (Private, Trb, IntStatus);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+  }\r
+\r
+  if ((Trb->Mode == SdMmcSdmaMode) && ((IntStatus & BIT3) != 0)) {\r
+    Data16 = BIT3;\r
+    Status = SdMmcHcRwMmio (\r
+               Private->PciIo,\r
+               Trb->Slot,\r
+               SD_MMC_HC_NOR_INT_STS,\r
+               FALSE,\r
+               sizeof (Data16),\r
+               &Data16\r
+               );\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+    Status = SdMmcUpdateSdmaAddress (Private, Trb);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+  }\r
+\r
+  return EFI_NOT_READY;\r
+}\r
+\r
 /**\r
   Check the TRB execution result.\r
 \r
@@ -2372,10 +2716,6 @@ SdMmcCheckTrbResult (
   EFI_STATUS                          Status;\r
   EFI_SD_MMC_PASS_THRU_COMMAND_PACKET *Packet;\r
   UINT16                              IntStatus;\r
-  UINT32                              Response[4];\r
-  UINT64                              SdmaAddr;\r
-  UINT8                               Index;\r
-  UINT32                              PioLength;\r
 \r
   Packet  = Trb->Packet;\r
   //\r
@@ -2403,122 +2743,34 @@ SdMmcCheckTrbResult (
   }\r
 \r
   //\r
-  // Check Transfer Complete bit is set or not.\r
+  // Tuning commands are the only ones that do not generate command\r
+  // complete interrupt. Process them here before entering the code\r
+  // that waits for command completion.\r
   //\r
-  if ((IntStatus & BIT1) == BIT1) {\r
+  if (((Private->Slot[Trb->Slot].CardType == EmmcCardType) &&\r
+       (Packet->SdMmcCmdBlk->CommandIndex == EMMC_SEND_TUNING_BLOCK)) ||\r
+      ((Private->Slot[Trb->Slot].CardType == SdCardType) &&\r
+       (Packet->SdMmcCmdBlk->CommandIndex == SD_SEND_TUNING_BLOCK))) {\r
+    Status = SdMmcTransferDataWithPio (Private, Trb, IntStatus);\r
     goto Done;\r
   }\r
 \r
-  //\r
-  // Check if DMA interrupt is signalled for the SDMA transfer.\r
-  //\r
-  if ((Trb->Mode == SdMmcSdmaMode) && ((IntStatus & BIT3) == BIT3)) {\r
-    //\r
-    // Clear DMA interrupt bit.\r
-    //\r
-    IntStatus = BIT3;\r
-    Status    = SdMmcHcRwMmio (\r
-                  Private->PciIo,\r
-                  Trb->Slot,\r
-                  SD_MMC_HC_NOR_INT_STS,\r
-                  FALSE,\r
-                  sizeof (IntStatus),\r
-                  &IntStatus\r
-                  );\r
+  if (!Trb->CommandComplete) {\r
+    Status = SdMmcCheckCommandComplete (Private, Trb, IntStatus);\r
     if (EFI_ERROR (Status)) {\r
       goto Done;\r
     }\r
-    //\r
-    // Update SDMA Address register.\r
-    //\r
-    SdmaAddr = SD_MMC_SDMA_ROUND_UP ((UINTN)Trb->DataPhy, SD_MMC_SDMA_BOUNDARY);\r
-\r
-    if (Private->ControllerVersion[Trb->Slot] >= SD_MMC_HC_CTRL_VER_400) {\r
-      Status = SdMmcHcRwMmio (\r
-                 Private->PciIo,\r
-                 Trb->Slot,\r
-                 SD_MMC_HC_ADMA_SYS_ADDR,\r
-                 FALSE,\r
-                 sizeof (UINT64),\r
-                 &SdmaAddr\r
-                 );\r
-    } else {\r
-      Status = SdMmcHcRwMmio (\r
-                 Private->PciIo,\r
-                 Trb->Slot,\r
-                 SD_MMC_HC_SDMA_ADDR,\r
-                 FALSE,\r
-                 sizeof (UINT32),\r
-                 &SdmaAddr\r
-                 );\r
-    }\r
-\r
-    if (EFI_ERROR (Status)) {\r
-      goto Done;\r
-    }\r
-    Trb->DataPhy = (UINT64)(UINTN)SdmaAddr;\r
   }\r
 \r
-  if ((Packet->SdMmcCmdBlk->CommandType != SdMmcCommandTypeAdtc) &&\r
-      (Packet->SdMmcCmdBlk->ResponseType != SdMmcResponseTypeR1b) &&\r
-      (Packet->SdMmcCmdBlk->ResponseType != SdMmcResponseTypeR5b)) {\r
-    if ((IntStatus & BIT0) == BIT0) {\r
-      Status = EFI_SUCCESS;\r
-      goto Done;\r
-    }\r
-  }\r
-\r
-  if (((Private->Slot[Trb->Slot].CardType == EmmcCardType) &&\r
-       (Packet->SdMmcCmdBlk->CommandIndex == EMMC_SEND_TUNING_BLOCK)) ||\r
-      ((Private->Slot[Trb->Slot].CardType == SdCardType) &&\r
-       (Packet->SdMmcCmdBlk->CommandIndex == SD_SEND_TUNING_BLOCK))) {\r
-    //\r
-    // When performing tuning procedure (Execute Tuning is set to 1) through PIO mode,\r
-    // wait Buffer Read Ready bit of Normal Interrupt Status Register to be 1.\r
-    // Refer to SD Host Controller Simplified Specification 3.0 figure 2-29 for details.\r
-    //\r
-    if ((IntStatus & BIT5) == BIT5) {\r
-      //\r
-      // Clear Buffer Read Ready interrupt at first.\r
-      //\r
-      IntStatus = BIT5;\r
-      SdMmcHcRwMmio (Private->PciIo, Trb->Slot, SD_MMC_HC_NOR_INT_STS, FALSE, sizeof (IntStatus), &IntStatus);\r
-      //\r
-      // Read data out from Buffer Port register\r
-      //\r
-      for (PioLength = 0; PioLength < Trb->DataLen; PioLength += 4) {\r
-        SdMmcHcRwMmio (Private->PciIo, Trb->Slot, SD_MMC_HC_BUF_DAT_PORT, TRUE, 4, (UINT8*)Trb->Data + PioLength);\r
-      }\r
-      Status = EFI_SUCCESS;\r
-      goto Done;\r
-    }\r
+  if (Packet->SdMmcCmdBlk->CommandType == SdMmcCommandTypeAdtc ||\r
+      Packet->SdMmcCmdBlk->ResponseType == SdMmcResponseTypeR1b ||\r
+      Packet->SdMmcCmdBlk->ResponseType == SdMmcResponseTypeR5b) {\r
+    Status = SdMmcCheckDataTransfer (Private, Trb, IntStatus);\r
+  } else {\r
+    Status = EFI_SUCCESS;\r
   }\r
 \r
-  Status = EFI_NOT_READY;\r
 Done:\r
-  //\r
-  // Get response data when the cmd is executed successfully.\r
-  //\r
-  if (!EFI_ERROR (Status)) {\r
-    if (Packet->SdMmcCmdBlk->CommandType != SdMmcCommandTypeBc) {\r
-      for (Index = 0; Index < 4; Index++) {\r
-        Status = SdMmcHcRwMmio (\r
-                   Private->PciIo,\r
-                   Trb->Slot,\r
-                   SD_MMC_HC_RESPONSE + Index * 4,\r
-                   TRUE,\r
-                   sizeof (UINT32),\r
-                   &Response[Index]\r
-                   );\r
-        if (EFI_ERROR (Status)) {\r
-          SdMmcHcLedOnOff (Private->PciIo, Trb->Slot, FALSE);\r
-          return Status;\r
-        }\r
-      }\r
-      CopyMem (Packet->SdMmcStatusBlk, Response, sizeof (Response));\r
-    }\r
-  }\r
-\r
   if (Status != EFI_NOT_READY) {\r
     SdMmcHcLedOnOff (Private->PciIo, Trb->Slot, FALSE);\r
     if (EFI_ERROR (Status)) {\r