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, "Adma32Desc: %p\n", Trb->Adma32Desc));\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->Private = Private;\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
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
goto Done;\r
}\r
\r
+ //\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 (((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
+ }\r
+\r
+ if (!Trb->CommandComplete) {\r
+ Status = SdMmcCheckCommandComplete (Private, Trb, IntStatus);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ } else {\r
+ //\r
+ // If the command doesn't require data transfer skip the transfer\r
+ // complete checking.\r
+ //\r
+ if ((Packet->SdMmcCmdBlk->CommandType != SdMmcCommandTypeAdtc) &&\r
+ (Packet->SdMmcCmdBlk->ResponseType != SdMmcResponseTypeR1b) &&\r
+ (Packet->SdMmcCmdBlk->ResponseType != SdMmcResponseTypeR5b)) {\r
+ goto Done;\r
+ }\r
+ }\r
+ }\r
+\r
//\r
// Check Transfer Complete bit is set or not.\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
- }\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