+STATIC\r
+EFI_STATUS\r
+MmcTransferBlock (\r
+ IN EFI_BLOCK_IO_PROTOCOL *This,\r
+ IN UINTN Cmd,\r
+ IN UINTN Transfer,\r
+ IN UINT32 MediaId,\r
+ IN EFI_LBA Lba,\r
+ IN UINTN BufferSize,\r
+ OUT VOID *Buffer\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN CmdArg;\r
+ INTN Timeout;\r
+ UINT32 Response[4];\r
+ MMC_HOST_INSTANCE *MmcHostInstance;\r
+ EFI_MMC_HOST_PROTOCOL *MmcHost;\r
+\r
+ MmcHostInstance = MMC_HOST_INSTANCE_FROM_BLOCK_IO_THIS (This);\r
+ MmcHost = MmcHostInstance->MmcHost;\r
+\r
+ //Set command argument based on the card access mode (Byte mode or Block mode)\r
+ if ((MmcHostInstance->CardInfo.OCRData.AccessMode & MMC_OCR_ACCESS_MASK) ==\r
+ MMC_OCR_ACCESS_SECTOR) {\r
+ CmdArg = Lba;\r
+ } else {\r
+ CmdArg = Lba * This->Media->BlockSize;\r
+ }\r
+\r
+ Status = MmcHost->SendCommand (MmcHost, Cmd, CmdArg);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_ERROR, "%a(MMC_CMD%d): Error %r\n", __func__, Cmd, Status));\r
+ return Status;\r
+ }\r
+\r
+ if (Transfer == MMC_IOBLOCKS_READ) {\r
+ // Read Data\r
+ Status = MmcHost->ReadBlockData (MmcHost, Lba, BufferSize, Buffer);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_BLKIO, "%a(): Error Read Block Data and Status = %r\n", __func__, Status));\r
+ MmcStopTransmission (MmcHost);\r
+ return Status;\r
+ }\r
+ Status = MmcNotifyState (MmcHostInstance, MmcProgrammingState);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_ERROR, "%a() : Error MmcProgrammingState\n", __func__));\r
+ return Status;\r
+ }\r
+ } else {\r
+ // Write Data\r
+ Status = MmcHost->WriteBlockData (MmcHost, Lba, BufferSize, Buffer);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_BLKIO, "%a(): Error Write Block Data and Status = %r\n", __func__, Status));\r
+ MmcStopTransmission (MmcHost);\r
+ return Status;\r
+ }\r
+ }\r
+\r
+ // Command 13 - Read status and wait for programming to complete (return to tran)\r
+ Timeout = MMCI0_TIMEOUT;\r
+ CmdArg = MmcHostInstance->CardInfo.RCA << 16;\r
+ Response[0] = 0;\r
+ while(!(Response[0] & MMC_R0_READY_FOR_DATA)\r
+ && (MMC_R0_CURRENTSTATE (Response) != MMC_R0_STATE_TRAN)\r
+ && Timeout--) {\r
+ Status = MmcHost->SendCommand (MmcHost, MMC_CMD13, CmdArg);\r
+ if (!EFI_ERROR (Status)) {\r
+ MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_R1, Response);\r
+ if (Response[0] & MMC_R0_READY_FOR_DATA) {\r
+ break; // Prevents delay once finished\r
+ }\r
+ }\r
+ }\r
+\r
+ if (BufferSize > This->Media->BlockSize) {\r
+ Status = MmcHost->SendCommand (MmcHost, MMC_CMD12, 0);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_BLKIO, "%a(): Error and Status:%r\n", __func__, Status));\r
+ }\r
+ }\r
+\r
+ Status = MmcNotifyState (MmcHostInstance, MmcTransferState);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_ERROR, "MmcIoBlocks() : Error MmcTransferState\n"));\r
+ return Status;\r
+ }\r
+ return Status;\r
+}\r
+\r