]> 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 6e419e0d982e0b9bbefc6bb47b7ee747790b3c6d..6548ef71dee1d7797bde8bcd06744e92f77d9918 100644 (file)
@@ -1715,6 +1715,8 @@ SdMmcPrintTrb (
   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
@@ -1819,6 +1821,8 @@ SdMmcCreateTrb (
   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
@@ -2481,6 +2485,104 @@ SdMmcCheckCommandComplete (
   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
@@ -2565,6 +2667,13 @@ SdMmcCheckDataTransfer (
     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
@@ -2607,7 +2716,6 @@ SdMmcCheckTrbResult (
   EFI_STATUS                          Status;\r
   EFI_SD_MMC_PASS_THRU_COMMAND_PACKET *Packet;\r
   UINT16                              IntStatus;\r
-  UINT32                              PioLength;\r
 \r
   Packet  = Trb->Packet;\r
   //\r
@@ -2643,26 +2751,8 @@ SdMmcCheckTrbResult (
        (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
+    Status = SdMmcTransferDataWithPio (Private, Trb, IntStatus);\r
+    goto Done;\r
   }\r
 \r
   if (!Trb->CommandComplete) {\r