From: Jan Dąbroś <[email protected]> For multiple block write operation it is necessary to poll for device status to be ready for next transaction. For sending SD_DEVICE_STATUS command it is necessary to know device RCA. In order to make it possible, there is new field added to SD_DEVICE structure called "Rca".
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 | 61 +++++++++++++++++++++++++++++++++++ MdeModulePkg/Bus/Sd/SdDxe/SdDxe.c | 3 ++ MdeModulePkg/Bus/Sd/SdDxe/SdDxe.h | 1 + 3 files changed, 65 insertions(+) diff --git a/MdeModulePkg/Bus/Sd/SdDxe/SdBlockIo.c b/MdeModulePkg/Bus/Sd/SdDxe/SdBlockIo.c index 411f353..2ce65e8 100644 --- a/MdeModulePkg/Bus/Sd/SdDxe/SdBlockIo.c +++ b/MdeModulePkg/Bus/Sd/SdDxe/SdBlockIo.c @@ -336,6 +336,57 @@ SdSendStopTransmission ( } /** + Check if card is ready for next data transfer by reading its status. + + @param[in] Device A pointer to the SD_DEVICE instance. + + @retval EFI_SUCCESS Card is ready for next data transfer. + @retval EFI_DEVICE_ERROR Card status is erroneous. + @retval EFI_TIMEOUT Card is busy. + +**/ +STATIC +EFI_STATUS +SdIsReady ( + SD_DEVICE *Device, + UINT16 Rca, + UINTN Timeout + ) +{ + EFI_STATUS Status; + UINT32 DevStatus; + + do { + Status = SdSendStatus (Device, Rca, &DevStatus); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_INFO, "Cannot read SD status\n")); + return Status; + } + // Check device status + if ((DevStatus & (1 << 8)) && (DevStatus & (0xf << 9)) != (7 << 9)) { + break; + } else if (DevStatus & ~0x0206BF7F) { + DEBUG ((EFI_D_ERROR, "SD Status error\n")); + return EFI_DEVICE_ERROR; + } + + gBS->Stall (1000); + } while (Timeout--); + + if (Timeout <= 0) { + DEBUG ((EFI_D_ERROR, "SD Status timeout\n")); + return EFI_TIMEOUT; + } + + if (DevStatus & (1 << 7)) { + DEBUG ((EFI_D_ERROR, "SD switch error\n")); + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + +/** Read/write single block through sync or async I/O request. @param[in] Device A pointer to the SD_DEVICE instance. @@ -712,6 +763,16 @@ SdReadWrite ( } DEBUG ((EFI_D_INFO, "Sd%a(): Lba 0x%x BlkNo 0x%x Event %p with %r\n", IsRead ? "Read" : "Write", Lba, BlockNum, Token->Event, Status)); + if (FeaturePcdGet(PcdSdForcePioMode)) { + if (!IsRead) { + if (SdIsReady (Device, Device->Rca, 1000) == EFI_SUCCESS) { + Status = EFI_SUCCESS; + } + else + Status = EFI_DEVICE_ERROR; + } + } + Lba += BlockNum; Buffer = (UINT8*)Buffer + BufferSize; Remaining -= BlockNum; diff --git a/MdeModulePkg/Bus/Sd/SdDxe/SdDxe.c b/MdeModulePkg/Bus/Sd/SdDxe/SdDxe.c index f657fb9..fe0573d 100644 --- a/MdeModulePkg/Bus/Sd/SdDxe/SdDxe.c +++ b/MdeModulePkg/Bus/Sd/SdDxe/SdDxe.c @@ -83,6 +83,7 @@ SD_DEVICE mSdDeviceTemplate = { { // ModelName 0, }, + 0, NULL // Private }; @@ -224,6 +225,8 @@ DiscoverUserArea ( return Status; } + Device->Rca = Rca; + Status = SdSendStatus (Device, Rca, &DevStatus); if (EFI_ERROR (Status)) { return Status; diff --git a/MdeModulePkg/Bus/Sd/SdDxe/SdDxe.h b/MdeModulePkg/Bus/Sd/SdDxe/SdDxe.h index 0ba72b7..17008c0 100644 --- a/MdeModulePkg/Bus/Sd/SdDxe/SdDxe.h +++ b/MdeModulePkg/Bus/Sd/SdDxe/SdDxe.h @@ -114,6 +114,7 @@ struct _SD_DEVICE { // The delimiters of these fields are whitespace. // CHAR16 ModelName[SD_MODEL_NAME_MAX_LEN]; + CHAR16 Rca; SD_DRIVER_PRIVATE_DATA *Private; } ; -- 1.8.3.1 _______________________________________________ edk2-devel mailing list [email protected] https://lists.01.org/mailman/listinfo/edk2-devel

