From: Jan Dąbroś <[email protected]> SD_STOP_TRANSMISSION command is necessary for multi block operations (read and write). This patch adds such functionality for devices not supporting DMA data transfer.
Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Jan Dabros <[email protected]> Signed-off-by: Marcin Wojtas <[email protected]> --- MdeModulePkg/Bus/Sd/SdDxe/SdBlockIo.c | 51 +++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/MdeModulePkg/Bus/Sd/SdDxe/SdBlockIo.c b/MdeModulePkg/Bus/Sd/SdDxe/SdBlockIo.c index d8b9459..2032f1d 100644 --- a/MdeModulePkg/Bus/Sd/SdDxe/SdBlockIo.c +++ b/MdeModulePkg/Bus/Sd/SdDxe/SdBlockIo.c @@ -296,6 +296,46 @@ SdGetCid ( } /** + Send command SD_STOP_TRANSMISSION to stop multiple block transfer. + + @param[in] Device A pointer to the SD_DEVICE instance. + + @retval EFI_SUCCESS The request is executed successfully. + @retval Others The request could not be executed successfully. + +**/ +EFI_STATUS +SdSendStopTransmission ( + IN SD_DEVICE *Device + ) +{ + EFI_STATUS Status; + EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru; + EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk; + EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk; + EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet; + + PassThru = Device->Private->PassThru; + + ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk)); + ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk)); + ZeroMem (&Packet, sizeof (Packet)); + + Packet.SdMmcCmdBlk = &SdMmcCmdBlk; + Packet.SdMmcStatusBlk = &SdMmcStatusBlk; + Packet.Timeout = SD_GENERIC_TIMEOUT; + + SdMmcCmdBlk.CommandIndex = SD_STOP_TRANSMISSION; + SdMmcCmdBlk.CommandType = SdMmcCommandTypeAc; + SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1b; + SdMmcCmdBlk.CommandArgument = 0; + + Status = PassThru->PassThru (PassThru, Device->Slot, &Packet, NULL); + + return Status; +} + +/** Read/write single block through sync or async I/O request. @param[in] Device A pointer to the SD_DEVICE instance. @@ -456,6 +496,7 @@ SdRwMultiBlocks ( SD_REQUEST *RwMultiBlkReq; EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru; EFI_TPL OldTpl; + EFI_STATUS DmaSupported; RwMultiBlkReq = NULL; @@ -523,6 +564,16 @@ SdRwMultiBlocks ( } Status = PassThru->PassThru (PassThru, Device->Slot, &RwMultiBlkReq->Packet, RwMultiBlkReq->Event); + if (EFI_ERROR(Status)) { + goto Error; + } + + DmaSupported = PassThru->IsDmaEnabled(PassThru, Device->Slot); + + // Send STOP_TRANSMISSION command for multi block transfers + if (DmaSupported == EFI_UNSUPPORTED) { + Status = SdSendStopTransmission (Device); + } Error: if ((Token != NULL) && (Token->Event != NULL)) { -- 1.8.3.1 _______________________________________________ edk2-devel mailing list [email protected] https://lists.01.org/mailman/listinfo/edk2-devel

