#define MMCI0_BLOCKLEN 512\r
#define MMCI0_TIMEOUT 10000\r
\r
+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
EFI_STATUS\r
MmcIoBlocks (\r
IN EFI_BLOCK_IO_PROTOCOL *This,\r
EFI_MMC_HOST_PROTOCOL *MmcHost;\r
UINTN BytesRemainingToBeTransfered;\r
UINTN BlockCount;\r
+ UINTN ConsumeSize;\r
\r
BlockCount = 1;\r
MmcHostInstance = MMC_HOST_INSTANCE_FROM_BLOCK_IO_THIS (This);\r
return EFI_NO_MEDIA;\r
}\r
\r
+ if (MMC_HOST_HAS_ISMULTIBLOCK(MmcHost) && MmcHost->IsMultiBlock(MmcHost)) {\r
+ BlockCount = (BufferSize + This->Media->BlockSize - 1) / This->Media->BlockSize;\r
+ }\r
+\r
// All blocks must be within the device\r
if ((Lba + (BufferSize / This->Media->BlockSize)) > (This->Media->LastBlock + 1)) {\r
return EFI_INVALID_PARAMETER;\r
return EFI_NOT_READY;\r
}\r
\r
- //Set command argument based on the card access mode (Byte mode or Block mode)\r
- if (MmcHostInstance->CardInfo.OCRData.AccessMode & BIT1) {\r
- CmdArg = Lba;\r
- } else {\r
- CmdArg = Lba * This->Media->BlockSize;\r
- }\r
-\r
if (Transfer == MMC_IOBLOCKS_READ) {\r
- // Read a single block\r
- Cmd = MMC_CMD17;\r
- } else {\r
- // Write a single block\r
- Cmd = MMC_CMD24;\r
- }\r
- Status = MmcHost->SendCommand (MmcHost, Cmd, CmdArg);\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((EFI_D_ERROR, "MmcIoBlocks(MMC_CMD%d): Error %r\n", Cmd, Status));\r
- return Status;\r
- }\r
-\r
- if (Transfer == MMC_IOBLOCKS_READ) {\r
- // Read one block of Data\r
- Status = MmcHost->ReadBlockData (MmcHost, Lba, This->Media->BlockSize, Buffer);\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((EFI_D_BLKIO, "MmcIoBlocks(): Error Read Block Data and Status = %r\n", Status));\r
- MmcStopTransmission (MmcHost);\r
- return Status;\r
- }\r
- Status = MmcNotifyState (MmcHostInstance, MmcProgrammingState);\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((EFI_D_ERROR, "MmcIoBlocks() : Error MmcProgrammingState\n"));\r
- return Status;\r
+ if (BlockCount == 1) {\r
+ // Read a single block\r
+ Cmd = MMC_CMD17;\r
+ } else {\r
+ // Read multiple blocks\r
+ Cmd = MMC_CMD18;\r
}\r
} else {\r
- // Write one block of Data\r
- Status = MmcHost->WriteBlockData (MmcHost, Lba, This->Media->BlockSize, Buffer);\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((EFI_D_BLKIO, "MmcIoBlocks(): Error Write Block Data and Status = %r\n", Status));\r
- MmcStopTransmission (MmcHost);\r
- return Status;\r
+ if (BlockCount == 1) {\r
+ // Write a single block\r
+ Cmd = MMC_CMD24;\r
+ } else {\r
+ // Write multiple blocks\r
+ Cmd = MMC_CMD25;\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
- gBS->Stall (1);\r
+ ConsumeSize = BlockCount * This->Media->BlockSize;\r
+ if (BytesRemainingToBeTransfered < ConsumeSize) {\r
+ ConsumeSize = BytesRemainingToBeTransfered;\r
}\r
-\r
- Status = MmcNotifyState (MmcHostInstance, MmcTransferState);\r
+ Status = MmcTransferBlock (This, Cmd, Transfer, MediaId, Lba, ConsumeSize, Buffer);\r
if (EFI_ERROR (Status)) {\r
- DEBUG ((EFI_D_ERROR, "MmcIoBlocks() : Error MmcTransferState\n"));\r
- return Status;\r
+ DEBUG ((EFI_D_ERROR, "%a(): Failed to transfer block and Status:%r\n", __func__, Status));\r
}\r
\r
- BytesRemainingToBeTransfered -= This->Media->BlockSize;\r
- Lba += BlockCount;\r
- Buffer = (UINT8 *)Buffer + This->Media->BlockSize;\r
+ BytesRemainingToBeTransfered -= ConsumeSize;\r
+ if (BytesRemainingToBeTransfered > 0) {\r
+ Lba += BlockCount;\r
+ Buffer = (UINT8 *)Buffer + ConsumeSize;\r
+ }\r
}\r
\r
return EFI_SUCCESS;\r