mirror of https://github.com/acidanthera/audk.git
MdeModulePkg/SdMmcPciHcDxe: Fix PIO transfer mode
Current driver does not support PIO transfer mode for commands other then tuning. This change adds the code to transfer PIO data. Cc: Hao A Wu <hao.a.wu@intel.com> Cc: Marcin Wojtas <mw@semihalf.com> Cc: Zhichao Gao <zhichao.gao@intel.com> Cc: Liming Gao <liming.gao@intel.com> Signed-off-by: Mateusz Albecki <mateusz.albecki@intel.com> Tested-by: Hao A Wu <hao.a.wu@intel.com> Reviewed-by: Hao A Wu <hao.a.wu@intel.com>
This commit is contained in:
parent
63fd7f3898
commit
9bfaa3da1e
|
@ -158,6 +158,9 @@ typedef struct {
|
|||
UINT64 Timeout;
|
||||
UINT32 Retries;
|
||||
|
||||
BOOLEAN PioModeTransferCompleted;
|
||||
UINT32 PioBlockIndex;
|
||||
|
||||
SD_MMC_HC_ADMA_32_DESC_LINE *Adma32Desc;
|
||||
SD_MMC_HC_ADMA_64_V3_DESC_LINE *Adma64V3Desc;
|
||||
SD_MMC_HC_ADMA_64_V4_DESC_LINE *Adma64V4Desc;
|
||||
|
|
|
@ -1715,6 +1715,8 @@ SdMmcPrintTrb (
|
|||
DEBUG ((DebugLevel, "CommandComplete: %d\n", Trb->CommandComplete));
|
||||
DEBUG ((DebugLevel, "Timeout: %ld\n", Trb->Timeout));
|
||||
DEBUG ((DebugLevel, "Retries: %d\n", Trb->Retries));
|
||||
DEBUG ((DebugLevel, "PioModeTransferCompleted: %d\n", Trb->PioModeTransferCompleted));
|
||||
DEBUG ((DebugLevel, "PioBlockIndex: %d\n", Trb->PioBlockIndex));
|
||||
DEBUG ((DebugLevel, "Adma32Desc: %p\n", Trb->Adma32Desc));
|
||||
DEBUG ((DebugLevel, "Adma64V3Desc: %p\n", Trb->Adma64V3Desc));
|
||||
DEBUG ((DebugLevel, "Adma64V4Desc: %p\n", Trb->Adma64V4Desc));
|
||||
|
@ -1819,6 +1821,8 @@ SdMmcCreateTrb (
|
|||
Trb->CommandComplete = FALSE;
|
||||
Trb->Timeout = Packet->Timeout;
|
||||
Trb->Retries = SD_MMC_TRB_RETRIES;
|
||||
Trb->PioModeTransferCompleted = FALSE;
|
||||
Trb->PioBlockIndex = 0;
|
||||
Trb->Private = Private;
|
||||
|
||||
if ((Packet->InTransferLength != 0) && (Packet->InDataBuffer != NULL)) {
|
||||
|
@ -2481,6 +2485,104 @@ SdMmcCheckCommandComplete (
|
|||
return EFI_NOT_READY;
|
||||
}
|
||||
|
||||
/**
|
||||
Transfers data from card using PIO method.
|
||||
|
||||
@param[in] Private A pointer to the SD_MMC_HC_PRIVATE_DATA instance.
|
||||
@param[in] Trb The pointer to the SD_MMC_HC_TRB instance.
|
||||
@param[in] IntStatus Snapshot of the normal interrupt status register.
|
||||
|
||||
@retval EFI_SUCCESS PIO transfer completed successfully.
|
||||
@retval EFI_NOT_READY PIO transfer completion still pending.
|
||||
@retval Others PIO transfer failed to complete.
|
||||
**/
|
||||
EFI_STATUS
|
||||
SdMmcTransferDataWithPio (
|
||||
IN SD_MMC_HC_PRIVATE_DATA *Private,
|
||||
IN SD_MMC_HC_TRB *Trb,
|
||||
IN UINT16 IntStatus
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINT16 Data16;
|
||||
UINT32 BlockCount;
|
||||
EFI_PCI_IO_PROTOCOL_WIDTH Width;
|
||||
UINTN Count;
|
||||
|
||||
BlockCount = (Trb->DataLen / Trb->BlockSize);
|
||||
if (Trb->DataLen % Trb->BlockSize != 0) {
|
||||
BlockCount += 1;
|
||||
}
|
||||
|
||||
if (Trb->PioBlockIndex >= BlockCount) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
switch (Trb->BlockSize % sizeof (UINT32)) {
|
||||
case 0:
|
||||
Width = EfiPciIoWidthFifoUint32;
|
||||
Count = Trb->BlockSize / sizeof (UINT32);
|
||||
break;
|
||||
case 2:
|
||||
Width = EfiPciIoWidthFifoUint16;
|
||||
Count = Trb->BlockSize / sizeof (UINT16);
|
||||
break;
|
||||
case 1:
|
||||
case 3:
|
||||
default:
|
||||
Width = EfiPciIoWidthFifoUint8;
|
||||
Count = Trb->BlockSize;
|
||||
break;
|
||||
}
|
||||
|
||||
if (Trb->Read) {
|
||||
if ((IntStatus & BIT5) == 0) {
|
||||
return EFI_NOT_READY;
|
||||
}
|
||||
Data16 = BIT5;
|
||||
SdMmcHcRwMmio (Private->PciIo, Trb->Slot, SD_MMC_HC_NOR_INT_STS, FALSE, sizeof (Data16), &Data16);
|
||||
|
||||
Status = Private->PciIo->Mem.Read (
|
||||
Private->PciIo,
|
||||
Width,
|
||||
Trb->Slot,
|
||||
SD_MMC_HC_BUF_DAT_PORT,
|
||||
Count,
|
||||
(VOID*)((UINT8*)Trb->Data + (Trb->BlockSize * Trb->PioBlockIndex))
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
Trb->PioBlockIndex++;
|
||||
} else {
|
||||
if ((IntStatus & BIT4) == 0) {
|
||||
return EFI_NOT_READY;
|
||||
}
|
||||
Data16 = BIT4;
|
||||
SdMmcHcRwMmio (Private->PciIo, Trb->Slot, SD_MMC_HC_NOR_INT_STS, FALSE, sizeof (Data16), &Data16);
|
||||
|
||||
Status = Private->PciIo->Mem.Write (
|
||||
Private->PciIo,
|
||||
Width,
|
||||
Trb->Slot,
|
||||
SD_MMC_HC_BUF_DAT_PORT,
|
||||
Count,
|
||||
(VOID*)((UINT8*)Trb->Data + (Trb->BlockSize * Trb->PioBlockIndex))
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
Trb->PioBlockIndex++;
|
||||
}
|
||||
|
||||
if (Trb->PioBlockIndex >= BlockCount) {
|
||||
Trb->PioModeTransferCompleted = TRUE;
|
||||
return EFI_SUCCESS;
|
||||
} else {
|
||||
return EFI_NOT_READY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Update the SDMA address on the SDMA buffer boundary interrupt.
|
||||
|
||||
|
@ -2565,6 +2667,13 @@ SdMmcCheckDataTransfer (
|
|||
return Status;
|
||||
}
|
||||
|
||||
if (Trb->Mode == SdMmcPioMode && !Trb->PioModeTransferCompleted) {
|
||||
Status = SdMmcTransferDataWithPio (Private, Trb, IntStatus);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
if ((Trb->Mode == SdMmcSdmaMode) && ((IntStatus & BIT3) != 0)) {
|
||||
Data16 = BIT3;
|
||||
Status = SdMmcHcRwMmio (
|
||||
|
@ -2607,7 +2716,6 @@ SdMmcCheckTrbResult (
|
|||
EFI_STATUS Status;
|
||||
EFI_SD_MMC_PASS_THRU_COMMAND_PACKET *Packet;
|
||||
UINT16 IntStatus;
|
||||
UINT32 PioLength;
|
||||
|
||||
Packet = Trb->Packet;
|
||||
//
|
||||
|
@ -2643,26 +2751,8 @@ SdMmcCheckTrbResult (
|
|||
(Packet->SdMmcCmdBlk->CommandIndex == EMMC_SEND_TUNING_BLOCK)) ||
|
||||
((Private->Slot[Trb->Slot].CardType == SdCardType) &&
|
||||
(Packet->SdMmcCmdBlk->CommandIndex == SD_SEND_TUNING_BLOCK))) {
|
||||
//
|
||||
// When performing tuning procedure (Execute Tuning is set to 1) through PIO mode,
|
||||
// wait Buffer Read Ready bit of Normal Interrupt Status Register to be 1.
|
||||
// Refer to SD Host Controller Simplified Specification 3.0 figure 2-29 for details.
|
||||
//
|
||||
if ((IntStatus & BIT5) == BIT5) {
|
||||
//
|
||||
// Clear Buffer Read Ready interrupt at first.
|
||||
//
|
||||
IntStatus = BIT5;
|
||||
SdMmcHcRwMmio (Private->PciIo, Trb->Slot, SD_MMC_HC_NOR_INT_STS, FALSE, sizeof (IntStatus), &IntStatus);
|
||||
//
|
||||
// Read data out from Buffer Port register
|
||||
//
|
||||
for (PioLength = 0; PioLength < Trb->DataLen; PioLength += 4) {
|
||||
SdMmcHcRwMmio (Private->PciIo, Trb->Slot, SD_MMC_HC_BUF_DAT_PORT, TRUE, 4, (UINT8*)Trb->Data + PioLength);
|
||||
}
|
||||
Status = EFI_SUCCESS;
|
||||
goto Done;
|
||||
}
|
||||
Status = SdMmcTransferDataWithPio (Private, Trb, IntStatus);
|
||||
goto Done;
|
||||
}
|
||||
|
||||
if (!Trb->CommandComplete) {
|
||||
|
|
Loading…
Reference in New Issue