}\r
}\r
\r
+ Private->Slot[Slot].CurrentFreq = ClockFreq;\r
+\r
return Status;\r
}\r
\r
PciIo,\r
Trb->AdmaMap\r
);\r
+ Trb->AdmaMap = NULL;\r
+\r
PciIo->FreeBuffer (\r
PciIo,\r
EFI_SIZE_TO_PAGES (TableSize),\r
return EFI_SUCCESS;\r
}\r
\r
+/**\r
+ Prints the contents of the command packet to the debug port.\r
+\r
+ @param[in] DebugLevel Debug level at which the packet should be printed.\r
+ @param[in] Packet Pointer to packet to print.\r
+**/\r
+VOID\r
+SdMmcPrintPacket (\r
+ IN UINT32 DebugLevel,\r
+ IN EFI_SD_MMC_PASS_THRU_COMMAND_PACKET *Packet\r
+ )\r
+{\r
+ if (Packet == NULL) {\r
+ return;\r
+ }\r
+\r
+ DEBUG ((DebugLevel, "Printing EFI_SD_MMC_PASS_THRU_COMMAND_PACKET\n"));\r
+ if (Packet->SdMmcCmdBlk != NULL) {\r
+ DEBUG ((DebugLevel, "Command index: %d, argument: %X\n", Packet->SdMmcCmdBlk->CommandIndex, Packet->SdMmcCmdBlk->CommandArgument));\r
+ DEBUG ((DebugLevel, "Command type: %d, response type: %d\n", Packet->SdMmcCmdBlk->CommandType, Packet->SdMmcCmdBlk->ResponseType));\r
+ }\r
+ if (Packet->SdMmcStatusBlk != NULL) {\r
+ DEBUG ((DebugLevel, "Response 0: %X, 1: %X, 2: %X, 3: %X\n",\r
+ Packet->SdMmcStatusBlk->Resp0,\r
+ Packet->SdMmcStatusBlk->Resp1,\r
+ Packet->SdMmcStatusBlk->Resp2,\r
+ Packet->SdMmcStatusBlk->Resp3\r
+ ));\r
+ }\r
+ DEBUG ((DebugLevel, "Timeout: %ld\n", Packet->Timeout));\r
+ DEBUG ((DebugLevel, "InDataBuffer: %p\n", Packet->InDataBuffer));\r
+ DEBUG ((DebugLevel, "OutDataBuffer: %p\n", Packet->OutDataBuffer));\r
+ DEBUG ((DebugLevel, "InTransferLength: %d\n", Packet->InTransferLength));\r
+ DEBUG ((DebugLevel, "OutTransferLength: %d\n", Packet->OutTransferLength));\r
+ DEBUG ((DebugLevel, "TransactionStatus: %r\n", Packet->TransactionStatus));\r
+}\r
+\r
+/**\r
+ Prints the contents of the TRB to the debug port.\r
+\r
+ @param[in] DebugLevel Debug level at which the TRB should be printed.\r
+ @param[in] Trb Pointer to the TRB structure.\r
+**/\r
+VOID\r
+SdMmcPrintTrb (\r
+ IN UINT32 DebugLevel,\r
+ IN SD_MMC_HC_TRB *Trb\r
+ )\r
+{\r
+ if (Trb == NULL) {\r
+ return;\r
+ }\r
+\r
+ DEBUG ((DebugLevel, "Printing SD_MMC_HC_TRB\n"));\r
+ DEBUG ((DebugLevel, "Slot: %d\n", Trb->Slot));\r
+ DEBUG ((DebugLevel, "BlockSize: %d\n", Trb->BlockSize));\r
+ DEBUG ((DebugLevel, "Data: %p\n", Trb->Data));\r
+ DEBUG ((DebugLevel, "DataLen: %d\n", Trb->DataLen));\r
+ DEBUG ((DebugLevel, "Read: %d\n", Trb->Read));\r
+ DEBUG ((DebugLevel, "DataPhy: %lX\n", Trb->DataPhy));\r
+ DEBUG ((DebugLevel, "DataMap: %p\n", Trb->DataMap));\r
+ DEBUG ((DebugLevel, "Mode: %d\n", Trb->Mode));\r
+ DEBUG ((DebugLevel, "AdmaLengthMode: %d\n", Trb->AdmaLengthMode));\r
+ DEBUG ((DebugLevel, "Event: %p\n", Trb->Event));\r
+ DEBUG ((DebugLevel, "Started: %d\n", Trb->Started));\r
+ DEBUG ((DebugLevel, "CommandComplete: %d\n", Trb->CommandComplete));\r
+ DEBUG ((DebugLevel, "Timeout: %ld\n", Trb->Timeout));\r
+ DEBUG ((DebugLevel, "Retries: %d\n", Trb->Retries));\r
+ DEBUG ((DebugLevel, "PioModeTransferCompleted: %d\n", Trb->PioModeTransferCompleted));\r
+ DEBUG ((DebugLevel, "PioBlockIndex: %d\n", Trb->PioBlockIndex));\r
+ DEBUG ((DebugLevel, "Adma32Desc: %p\n", Trb->Adma32Desc));\r
+ DEBUG ((DebugLevel, "Adma64V3Desc: %p\n", Trb->Adma64V3Desc));\r
+ DEBUG ((DebugLevel, "Adma64V4Desc: %p\n", Trb->Adma64V4Desc));\r
+ DEBUG ((DebugLevel, "AdmaMap: %p\n", Trb->AdmaMap));\r
+ DEBUG ((DebugLevel, "AdmaPages: %X\n", Trb->AdmaPages));\r
+\r
+ SdMmcPrintPacket (DebugLevel, Trb->Packet);\r
+}\r
+\r
+/**\r
+ Sets up host memory to allow DMA transfer.\r
+\r
+ @param[in] Private A pointer to the SD_MMC_HC_PRIVATE_DATA instance.\r
+ @param[in] Slot The slot number of the SD card to send the command to.\r
+ @param[in] Packet A pointer to the SD command data structure.\r
+\r
+ @retval EFI_SUCCESS Memory has been mapped for DMA transfer.\r
+ @retval Others Memory has not been mapped.\r
+**/\r
+EFI_STATUS\r
+SdMmcSetupMemoryForDmaTransfer (\r
+ IN SD_MMC_HC_PRIVATE_DATA *Private,\r
+ IN UINT8 Slot,\r
+ IN SD_MMC_HC_TRB *Trb\r
+ )\r
+{\r
+ EFI_PCI_IO_PROTOCOL_OPERATION Flag;\r
+ EFI_PCI_IO_PROTOCOL *PciIo;\r
+ UINTN MapLength;\r
+ EFI_STATUS Status;\r
+\r
+ if (Trb->Read) {\r
+ Flag = EfiPciIoOperationBusMasterWrite;\r
+ } else {\r
+ Flag = EfiPciIoOperationBusMasterRead;\r
+ }\r
+\r
+ PciIo = Private->PciIo;\r
+ if (Trb->Data != NULL && Trb->DataLen != 0) {\r
+ MapLength = Trb->DataLen;\r
+ Status = PciIo->Map (\r
+ PciIo,\r
+ Flag,\r
+ Trb->Data,\r
+ &MapLength,\r
+ &Trb->DataPhy,\r
+ &Trb->DataMap\r
+ );\r
+ if (EFI_ERROR (Status) || (Trb->DataLen != MapLength)) {\r
+ return EFI_BAD_BUFFER_SIZE;\r
+ }\r
+ }\r
+\r
+ if (Trb->Mode == SdMmcAdma32bMode ||\r
+ Trb->Mode == SdMmcAdma64bV3Mode ||\r
+ Trb->Mode == SdMmcAdma64bV4Mode) {\r
+ Status = BuildAdmaDescTable (Trb, Private->ControllerVersion[Slot]);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
/**\r
Create a new TRB for the SD/MMC cmd request.\r
\r
SD_MMC_HC_TRB *Trb;\r
EFI_STATUS Status;\r
EFI_TPL OldTpl;\r
- EFI_PCI_IO_PROTOCOL_OPERATION Flag;\r
- EFI_PCI_IO_PROTOCOL *PciIo;\r
- UINTN MapLength;\r
\r
Trb = AllocateZeroPool (sizeof (SD_MMC_HC_TRB));\r
if (Trb == NULL) {\r
Trb->Packet = Packet;\r
Trb->Event = Event;\r
Trb->Started = FALSE;\r
+ Trb->CommandComplete = FALSE;\r
Trb->Timeout = Packet->Timeout;\r
+ Trb->Retries = SD_MMC_TRB_RETRIES;\r
+ Trb->PioModeTransferCompleted = FALSE;\r
+ Trb->PioBlockIndex = 0;\r
Trb->Private = Private;\r
\r
if ((Packet->InTransferLength != 0) && (Packet->InDataBuffer != NULL)) {\r
(Packet->SdMmcCmdBlk->CommandIndex == SD_SEND_TUNING_BLOCK))) {\r
Trb->Mode = SdMmcPioMode;\r
} else {\r
- if (Trb->Read) {\r
- Flag = EfiPciIoOperationBusMasterWrite;\r
- } else {\r
- Flag = EfiPciIoOperationBusMasterRead;\r
- }\r
-\r
- PciIo = Private->PciIo;\r
- if (Trb->DataLen != 0) {\r
- MapLength = Trb->DataLen;\r
- Status = PciIo->Map (\r
- PciIo,\r
- Flag,\r
- Trb->Data,\r
- &MapLength,\r
- &Trb->DataPhy,\r
- &Trb->DataMap\r
- );\r
- if (EFI_ERROR (Status) || (Trb->DataLen != MapLength)) {\r
- Status = EFI_BAD_BUFFER_SIZE;\r
- goto Error;\r
- }\r
- }\r
-\r
if (Trb->DataLen == 0) {\r
Trb->Mode = SdMmcNoData;\r
} else if (Private->Capability[Slot].Adma2 != 0) {\r
if (Private->ControllerVersion[Slot] >= SD_MMC_HC_CTRL_VER_410) {\r
Trb->AdmaLengthMode = SdMmcAdmaLen26b;\r
}\r
- Status = BuildAdmaDescTable (Trb, Private->ControllerVersion[Slot]);\r
+ Status = SdMmcSetupMemoryForDmaTransfer (Private, Slot, Trb);\r
if (EFI_ERROR (Status)) {\r
- PciIo->Unmap (PciIo, Trb->DataMap);\r
goto Error;\r
}\r
} else if (Private->Capability[Slot].Sdma != 0) {\r
Trb->Mode = SdMmcSdmaMode;\r
+ Status = SdMmcSetupMemoryForDmaTransfer (Private, Slot, Trb);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Error;\r
+ }\r
} else {\r
Trb->Mode = SdMmcPioMode;\r
}\r
SD specification section 3.10.\r
\r
@param[in] Private Pointer to driver private data.\r
- @param[in] Trb Pointer to currently executing TRB.\r
+ @param[in] Slot Index of the slot for device.\r
@param[in] IntStatus Normal interrupt status mask.\r
\r
@retval EFI_CRC_ERROR CRC error happened during CMD execution.\r
return Status;\r
}\r
\r
+ DEBUG ((DEBUG_ERROR, "Error reported by SDHCI\n"));\r
+ DEBUG ((DEBUG_ERROR, "Interrupt status = %X\n", IntStatus));\r
+ DEBUG ((DEBUG_ERROR, "Error interrupt status = %X\n", ErrIntStatus));\r
+\r
//\r
// If the data timeout error is reported\r
// but data transfer is signaled as completed we\r
return ErrorStatus;\r
}\r
\r
+/**\r
+ Reads the response data into the TRB buffer.\r
+ This function assumes that caller made sure that\r
+ command has completed.\r
+\r
+ @param[in] Private A pointer to the SD_MMC_HC_PRIVATE_DATA instance.\r
+ @param[in] Trb The pointer to the SD_MMC_HC_TRB instance.\r
+\r
+ @retval EFI_SUCCESS Response read successfully.\r
+ @retval Others Failed to get response.\r
+**/\r
+EFI_STATUS\r
+SdMmcGetResponse (\r
+ IN SD_MMC_HC_PRIVATE_DATA *Private,\r
+ IN SD_MMC_HC_TRB *Trb\r
+ )\r
+{\r
+ EFI_SD_MMC_PASS_THRU_COMMAND_PACKET *Packet;\r
+ UINT8 Index;\r
+ UINT32 Response[4];\r
+ EFI_STATUS Status;\r
+\r
+ Packet = Trb->Packet;\r
+\r
+ if (Packet->SdMmcCmdBlk->CommandType == SdMmcCommandTypeBc) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ for (Index = 0; Index < 4; Index++) {\r
+ Status = SdMmcHcRwMmio (\r
+ Private->PciIo,\r
+ Trb->Slot,\r
+ SD_MMC_HC_RESPONSE + Index * 4,\r
+ TRUE,\r
+ sizeof (UINT32),\r
+ &Response[Index]\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ }\r
+ CopyMem (Packet->SdMmcStatusBlk, Response, sizeof (Response));\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Checks if the command completed. If the command\r
+ completed it gets the response and records the\r
+ command completion in the TRB.\r
+\r
+ @param[in] Private A pointer to the SD_MMC_HC_PRIVATE_DATA instance.\r
+ @param[in] Trb The pointer to the SD_MMC_HC_TRB instance.\r
+ @param[in] IntStatus Snapshot of the normal interrupt status register.\r
+\r
+ @retval EFI_SUCCESS Command completed successfully.\r
+ @retval EFI_NOT_READY Command completion still pending.\r
+ @retval Others Command failed to complete.\r
+**/\r
+EFI_STATUS\r
+SdMmcCheckCommandComplete (\r
+ IN SD_MMC_HC_PRIVATE_DATA *Private,\r
+ IN SD_MMC_HC_TRB *Trb,\r
+ IN UINT16 IntStatus\r
+ )\r
+{\r
+ UINT16 Data16;\r
+ EFI_STATUS Status;\r
+\r
+ if ((IntStatus & BIT0) != 0) {\r
+ Data16 = BIT0;\r
+ Status = SdMmcHcRwMmio (\r
+ Private->PciIo,\r
+ Trb->Slot,\r
+ SD_MMC_HC_NOR_INT_STS,\r
+ FALSE,\r
+ sizeof (Data16),\r
+ &Data16\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ Status = SdMmcGetResponse (Private, Trb);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ Trb->CommandComplete = TRUE;\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ return EFI_NOT_READY;\r
+}\r
+\r
+/**\r
+ Transfers data from card using PIO method.\r
+\r
+ @param[in] Private A pointer to the SD_MMC_HC_PRIVATE_DATA instance.\r
+ @param[in] Trb The pointer to the SD_MMC_HC_TRB instance.\r
+ @param[in] IntStatus Snapshot of the normal interrupt status register.\r
+\r
+ @retval EFI_SUCCESS PIO transfer completed successfully.\r
+ @retval EFI_NOT_READY PIO transfer completion still pending.\r
+ @retval Others PIO transfer failed to complete.\r
+**/\r
+EFI_STATUS\r
+SdMmcTransferDataWithPio (\r
+ IN SD_MMC_HC_PRIVATE_DATA *Private,\r
+ IN SD_MMC_HC_TRB *Trb,\r
+ IN UINT16 IntStatus\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINT16 Data16;\r
+ UINT32 BlockCount;\r
+ EFI_PCI_IO_PROTOCOL_WIDTH Width;\r
+ UINTN Count;\r
+\r
+ BlockCount = (Trb->DataLen / Trb->BlockSize);\r
+ if (Trb->DataLen % Trb->BlockSize != 0) {\r
+ BlockCount += 1;\r
+ }\r
+\r
+ if (Trb->PioBlockIndex >= BlockCount) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ switch (Trb->BlockSize % sizeof (UINT32)) {\r
+ case 0:\r
+ Width = EfiPciIoWidthFifoUint32;\r
+ Count = Trb->BlockSize / sizeof (UINT32);\r
+ break;\r
+ case 2:\r
+ Width = EfiPciIoWidthFifoUint16;\r
+ Count = Trb->BlockSize / sizeof (UINT16);\r
+ break;\r
+ case 1:\r
+ case 3:\r
+ default:\r
+ Width = EfiPciIoWidthFifoUint8;\r
+ Count = Trb->BlockSize;\r
+ break;\r
+ }\r
+\r
+ if (Trb->Read) {\r
+ if ((IntStatus & BIT5) == 0) {\r
+ return EFI_NOT_READY;\r
+ }\r
+ Data16 = BIT5;\r
+ SdMmcHcRwMmio (Private->PciIo, Trb->Slot, SD_MMC_HC_NOR_INT_STS, FALSE, sizeof (Data16), &Data16);\r
+\r
+ Status = Private->PciIo->Mem.Read (\r
+ Private->PciIo,\r
+ Width,\r
+ Trb->Slot,\r
+ SD_MMC_HC_BUF_DAT_PORT,\r
+ Count,\r
+ (VOID*)((UINT8*)Trb->Data + (Trb->BlockSize * Trb->PioBlockIndex))\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ Trb->PioBlockIndex++;\r
+ } else {\r
+ if ((IntStatus & BIT4) == 0) {\r
+ return EFI_NOT_READY;\r
+ }\r
+ Data16 = BIT4;\r
+ SdMmcHcRwMmio (Private->PciIo, Trb->Slot, SD_MMC_HC_NOR_INT_STS, FALSE, sizeof (Data16), &Data16);\r
+\r
+ Status = Private->PciIo->Mem.Write (\r
+ Private->PciIo,\r
+ Width,\r
+ Trb->Slot,\r
+ SD_MMC_HC_BUF_DAT_PORT,\r
+ Count,\r
+ (VOID*)((UINT8*)Trb->Data + (Trb->BlockSize * Trb->PioBlockIndex))\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ Trb->PioBlockIndex++;\r
+ }\r
+\r
+ if (Trb->PioBlockIndex >= BlockCount) {\r
+ Trb->PioModeTransferCompleted = TRUE;\r
+ return EFI_SUCCESS;\r
+ } else {\r
+ return EFI_NOT_READY;\r
+ }\r
+}\r
+\r
+/**\r
+ Update the SDMA address on the SDMA buffer boundary interrupt.\r
+\r
+ @param[in] Private A pointer to the SD_MMC_HC_PRIVATE_DATA instance.\r
+ @param[in] Trb The pointer to the SD_MMC_HC_TRB instance.\r
+\r
+ @retval EFI_SUCCESS Updated SDMA buffer address.\r
+ @retval Others Failed to update SDMA buffer address.\r
+**/\r
+EFI_STATUS\r
+SdMmcUpdateSdmaAddress (\r
+ IN SD_MMC_HC_PRIVATE_DATA *Private,\r
+ IN SD_MMC_HC_TRB *Trb\r
+ )\r
+{\r
+ UINT64 SdmaAddr;\r
+ EFI_STATUS Status;\r
+\r
+ SdmaAddr = SD_MMC_SDMA_ROUND_UP ((UINTN)Trb->DataPhy, SD_MMC_SDMA_BOUNDARY);\r
+\r
+ if (Private->ControllerVersion[Trb->Slot] >= SD_MMC_HC_CTRL_VER_400) {\r
+ Status = SdMmcHcRwMmio (\r
+ Private->PciIo,\r
+ Trb->Slot,\r
+ SD_MMC_HC_ADMA_SYS_ADDR,\r
+ FALSE,\r
+ sizeof (UINT64),\r
+ &SdmaAddr\r
+ );\r
+ } else {\r
+ Status = SdMmcHcRwMmio (\r
+ Private->PciIo,\r
+ Trb->Slot,\r
+ SD_MMC_HC_SDMA_ADDR,\r
+ FALSE,\r
+ sizeof (UINT32),\r
+ &SdmaAddr\r
+ );\r
+ }\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Trb->DataPhy = (UINT64)(UINTN)SdmaAddr;\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Checks if the data transfer completed and performs any actions\r
+ neccessary to continue the data transfer such as SDMA system\r
+ address fixup or PIO data transfer.\r
+\r
+ @param[in] Private A pointer to the SD_MMC_HC_PRIVATE_DATA instance.\r
+ @param[in] Trb The pointer to the SD_MMC_HC_TRB instance.\r
+ @param[in] IntStatus Snapshot of the normal interrupt status register.\r
+\r
+ @retval EFI_SUCCESS Data transfer completed successfully.\r
+ @retval EFI_NOT_READY Data transfer completion still pending.\r
+ @retval Others Data transfer failed to complete.\r
+**/\r
+EFI_STATUS\r
+SdMmcCheckDataTransfer (\r
+ IN SD_MMC_HC_PRIVATE_DATA *Private,\r
+ IN SD_MMC_HC_TRB *Trb,\r
+ IN UINT16 IntStatus\r
+ )\r
+{\r
+ UINT16 Data16;\r
+ EFI_STATUS Status;\r
+\r
+ if ((IntStatus & BIT1) != 0) {\r
+ Data16 = BIT1;\r
+ Status = SdMmcHcRwMmio (\r
+ Private->PciIo,\r
+ Trb->Slot,\r
+ SD_MMC_HC_NOR_INT_STS,\r
+ FALSE,\r
+ sizeof (Data16),\r
+ &Data16\r
+ );\r
+ return Status;\r
+ }\r
+\r
+ if (Trb->Mode == SdMmcPioMode && !Trb->PioModeTransferCompleted) {\r
+ Status = SdMmcTransferDataWithPio (Private, Trb, IntStatus);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ }\r
+\r
+ if ((Trb->Mode == SdMmcSdmaMode) && ((IntStatus & BIT3) != 0)) {\r
+ Data16 = BIT3;\r
+ Status = SdMmcHcRwMmio (\r
+ Private->PciIo,\r
+ Trb->Slot,\r
+ SD_MMC_HC_NOR_INT_STS,\r
+ FALSE,\r
+ sizeof (Data16),\r
+ &Data16\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ Status = SdMmcUpdateSdmaAddress (Private, Trb);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ }\r
+\r
+ return EFI_NOT_READY;\r
+}\r
+\r
/**\r
Check the TRB execution result.\r
\r
EFI_STATUS Status;\r
EFI_SD_MMC_PASS_THRU_COMMAND_PACKET *Packet;\r
UINT16 IntStatus;\r
- UINT32 Response[4];\r
- UINT64 SdmaAddr;\r
- UINT8 Index;\r
- UINT32 PioLength;\r
\r
Packet = Trb->Packet;\r
//\r
}\r
\r
//\r
- // Check Transfer Complete bit is set or not.\r
+ // Tuning commands are the only ones that do not generate command\r
+ // complete interrupt. Process them here before entering the code\r
+ // that waits for command completion.\r
//\r
- if ((IntStatus & BIT1) == BIT1) {\r
+ if (((Private->Slot[Trb->Slot].CardType == EmmcCardType) &&\r
+ (Packet->SdMmcCmdBlk->CommandIndex == EMMC_SEND_TUNING_BLOCK)) ||\r
+ ((Private->Slot[Trb->Slot].CardType == SdCardType) &&\r
+ (Packet->SdMmcCmdBlk->CommandIndex == SD_SEND_TUNING_BLOCK))) {\r
+ Status = SdMmcTransferDataWithPio (Private, Trb, IntStatus);\r
goto Done;\r
}\r
\r
- //\r
- // Check if DMA interrupt is signalled for the SDMA transfer.\r
- //\r
- if ((Trb->Mode == SdMmcSdmaMode) && ((IntStatus & BIT3) == BIT3)) {\r
- //\r
- // Clear DMA interrupt bit.\r
- //\r
- IntStatus = BIT3;\r
- Status = SdMmcHcRwMmio (\r
- Private->PciIo,\r
- Trb->Slot,\r
- SD_MMC_HC_NOR_INT_STS,\r
- FALSE,\r
- sizeof (IntStatus),\r
- &IntStatus\r
- );\r
- if (EFI_ERROR (Status)) {\r
- goto Done;\r
- }\r
- //\r
- // Update SDMA Address register.\r
- //\r
- SdmaAddr = SD_MMC_SDMA_ROUND_UP ((UINTN)Trb->DataPhy, SD_MMC_SDMA_BOUNDARY);\r
-\r
- if (Private->ControllerVersion[Trb->Slot] >= SD_MMC_HC_CTRL_VER_400) {\r
- Status = SdMmcHcRwMmio (\r
- Private->PciIo,\r
- Trb->Slot,\r
- SD_MMC_HC_ADMA_SYS_ADDR,\r
- FALSE,\r
- sizeof (UINT64),\r
- &SdmaAddr\r
- );\r
- } else {\r
- Status = SdMmcHcRwMmio (\r
- Private->PciIo,\r
- Trb->Slot,\r
- SD_MMC_HC_SDMA_ADDR,\r
- FALSE,\r
- sizeof (UINT32),\r
- &SdmaAddr\r
- );\r
- }\r
-\r
+ if (!Trb->CommandComplete) {\r
+ Status = SdMmcCheckCommandComplete (Private, Trb, IntStatus);\r
if (EFI_ERROR (Status)) {\r
goto Done;\r
}\r
- Trb->DataPhy = (UINT64)(UINTN)SdmaAddr;\r
- }\r
-\r
- if ((Packet->SdMmcCmdBlk->CommandType != SdMmcCommandTypeAdtc) &&\r
- (Packet->SdMmcCmdBlk->ResponseType != SdMmcResponseTypeR1b) &&\r
- (Packet->SdMmcCmdBlk->ResponseType != SdMmcResponseTypeR5b)) {\r
- if ((IntStatus & BIT0) == BIT0) {\r
- Status = EFI_SUCCESS;\r
- goto Done;\r
- }\r
}\r
\r
- if (((Private->Slot[Trb->Slot].CardType == EmmcCardType) &&\r
- (Packet->SdMmcCmdBlk->CommandIndex == EMMC_SEND_TUNING_BLOCK)) ||\r
- ((Private->Slot[Trb->Slot].CardType == SdCardType) &&\r
- (Packet->SdMmcCmdBlk->CommandIndex == SD_SEND_TUNING_BLOCK))) {\r
- //\r
- // When performing tuning procedure (Execute Tuning is set to 1) through PIO mode,\r
- // wait Buffer Read Ready bit of Normal Interrupt Status Register to be 1.\r
- // Refer to SD Host Controller Simplified Specification 3.0 figure 2-29 for details.\r
- //\r
- if ((IntStatus & BIT5) == BIT5) {\r
- //\r
- // Clear Buffer Read Ready interrupt at first.\r
- //\r
- IntStatus = BIT5;\r
- SdMmcHcRwMmio (Private->PciIo, Trb->Slot, SD_MMC_HC_NOR_INT_STS, FALSE, sizeof (IntStatus), &IntStatus);\r
- //\r
- // Read data out from Buffer Port register\r
- //\r
- for (PioLength = 0; PioLength < Trb->DataLen; PioLength += 4) {\r
- SdMmcHcRwMmio (Private->PciIo, Trb->Slot, SD_MMC_HC_BUF_DAT_PORT, TRUE, 4, (UINT8*)Trb->Data + PioLength);\r
- }\r
- Status = EFI_SUCCESS;\r
- goto Done;\r
- }\r
+ if (Packet->SdMmcCmdBlk->CommandType == SdMmcCommandTypeAdtc ||\r
+ Packet->SdMmcCmdBlk->ResponseType == SdMmcResponseTypeR1b ||\r
+ Packet->SdMmcCmdBlk->ResponseType == SdMmcResponseTypeR5b) {\r
+ Status = SdMmcCheckDataTransfer (Private, Trb, IntStatus);\r
+ } else {\r
+ Status = EFI_SUCCESS;\r
}\r
\r
- Status = EFI_NOT_READY;\r
Done:\r
- //\r
- // Get response data when the cmd is executed successfully.\r
- //\r
- if (!EFI_ERROR (Status)) {\r
- if (Packet->SdMmcCmdBlk->CommandType != SdMmcCommandTypeBc) {\r
- for (Index = 0; Index < 4; Index++) {\r
- Status = SdMmcHcRwMmio (\r
- Private->PciIo,\r
- Trb->Slot,\r
- SD_MMC_HC_RESPONSE + Index * 4,\r
- TRUE,\r
- sizeof (UINT32),\r
- &Response[Index]\r
- );\r
- if (EFI_ERROR (Status)) {\r
- SdMmcHcLedOnOff (Private->PciIo, Trb->Slot, FALSE);\r
- return Status;\r
- }\r
- }\r
- CopyMem (Packet->SdMmcStatusBlk, Response, sizeof (Response));\r
- }\r
- }\r
-\r
if (Status != EFI_NOT_READY) {\r
SdMmcHcLedOnOff (Private->PciIo, Trb->Slot, FALSE);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_ERROR, "TRB failed with %r\n", Status));\r
+ SdMmcPrintTrb (DEBUG_ERROR, Trb);\r
+ } else {\r
+ DEBUG ((DEBUG_VERBOSE, "TRB success\n"));\r
+ SdMmcPrintTrb (DEBUG_VERBOSE, Trb);\r
+ }\r
}\r
\r
return Status;\r