📄 sdhceventhandlers.cpp
字号:
DWORD Argument,
SD_TRANSFER_CLASS TransferClass,
SD_RESPONSE_TYPE ResponseType,
PSD_COMMAND_RESPONSE pResponse,
DWORD NumberOfBlocks,
ULONG BlockSize,
PUCHAR pBlockBuffer)
{
SD_API_STATUS status; // intermediate status
PSDCARD_DEVICE_CONTEXT pDevice; // the device context
CSDBusDriver *pBusDriver; // the bus driver
ULONG retryCount; // retry count
ULONG i; // loop variable
DWORD clientFlags; // client flags backup
// send the APP Command primer (CMD 55)
status = SendSDCommand(hDevice,
SD_CMD_APP_CMD,
((DWORD)(((PSDCARD_DEVICE_CONTEXT)hDevice)->RelativeAddress)) << 16,
ResponseR1,
pResponse);
if (!SD_API_SUCCESS(status)){
return status;
}
// CMD55 did not timeout so send the command
if (CLIENT_HANDLES_RETRY(SDDCGetClientDeviceFromHandle(hDevice))) {
status = SDSynchronousBusRequest__X(hDevice,
Command,
Argument,
TransferClass,
ResponseType,
pResponse,
NumberOfBlocks,
BlockSize,
pBlockBuffer,
0);
}
else {
// handle app cmd retry here if client does not handle it,
// tell bus driver do not handle retry
pDevice = SDDCGetClientDeviceFromHandle(hDevice);
// save original ClientFlags
clientFlags = pDevice->ClientFlags;
pDevice->ClientFlags |= SD_CLIENT_HANDLES_RETRY;
pDevice = SDDCGetClientDeviceFromHandle(hDevice);
status = SDSynchronousBusRequest__X(hDevice,
Command,
Argument,
TransferClass,
ResponseType,
pResponse,
NumberOfBlocks,
BlockSize,
pBlockBuffer,
0);
if (!SD_API_SUCCESS(status)) {
pBusDriver = SDDCGetBusDriver((PSDCARD_DEVICE_CONTEXT)hDevice);
retryCount = pBusDriver->GetRetryCount();
for (i = 0; i < retryCount; i++) {
// check for retry
if ( !( (SD_API_STATUS_RESPONSE_TIMEOUT == status) ||
(SD_API_STATUS_DATA_TIMEOUT == status) ||
(SD_API_STATUS_CRC_ERROR == status) ) ) {
break;
}
// send the APP Command primer (CMD55)
status = SendSDCommand(hDevice,
SD_CMD_APP_CMD,
((DWORD)(((PSDCARD_DEVICE_CONTEXT)hDevice)->RelativeAddress)) << 16,
ResponseR1,
pResponse);
if (!SD_API_SUCCESS(status)){
break;
}
// send the command again
status = SDSynchronousBusRequest__X(hDevice,
Command,
Argument,
TransferClass,
ResponseType,
pResponse,
NumberOfBlocks,
BlockSize,
pBlockBuffer,
0);
}
}
// restore client flags
pDevice->ClientFlags = clientFlags;
}
return status;
}
///////////////////////////////////////////////////////////////////////////////
// UpdateCachedRegisterFromResponse - update the device shadow registers from the
// information in the response buffer
// Input: pDevice - the device who's shadowed register should be updated
// Register - the information to update
// pResponse - the response containing the register data
// Output:
// Return
// Notes:
//
///////////////////////////////////////////////////////////////////////////////
VOID UpdateCachedRegisterFromResponse(PSDCARD_DEVICE_CONTEXT pDevice,
SD_INFO_TYPE Register,
PSD_COMMAND_RESPONSE pResponse)
{
switch (Register) {
case SD_INFO_REGISTER_CID:
memcpy(pDevice->CachedRegisters.CID, pResponse->ResponseBuffer, SD_CID_REGISTER_SIZE);
break;
case SD_INFO_REGISTER_RCA:
// RCA is in bytes 3,4
pDevice->RelativeAddress = (SD_CARD_RCA)pResponse->ResponseBuffer[3];
pDevice->RelativeAddress |= ((SD_CARD_RCA)pResponse->ResponseBuffer[4]) << 8;
break;
case SD_INFO_REGISTER_OCR:
pDevice->CachedRegisters.OCR[3] = pResponse->ResponseBuffer[4];
pDevice->CachedRegisters.OCR[2] = pResponse->ResponseBuffer[3];
pDevice->CachedRegisters.OCR[1] = pResponse->ResponseBuffer[2];
pDevice->CachedRegisters.OCR[0] = pResponse->ResponseBuffer[1];
break;
case SD_INFO_REGISTER_CSD:
memcpy(pDevice->CachedRegisters.CSD, pResponse->ResponseBuffer, SD_CSD_REGISTER_SIZE);
#if USE_MMCPLUS
if ( g_bIsMMC == TRUE )
{
/*
for ( int i= 0 ; i<SD_CSD_REGISTER_SIZE ; i++)
{
RETAILMSG(0,(TEXT("CSD[%d] = %x\r\n"),i,pResponse->ResponseBuffer[i] ));
}*/
if ( pResponse->ResponseBuffer[15] & 0x10 )
{
RETAILMSG(0,(TEXT("This card is HSMMC\r\n")));
g_bIsHSMMC = TRUE;
}
else
RETAILMSG(0,(TEXT("This card is not HSMMC\r\n")));
}
#endif
break;
case SD_INFO_REGISTER_IO_OCR:
pDevice->CachedRegisters.IO_OCR[2] = pResponse->ResponseBuffer[3];
pDevice->CachedRegisters.IO_OCR[1] = pResponse->ResponseBuffer[2];
pDevice->CachedRegisters.IO_OCR[0] = pResponse->ResponseBuffer[1];
break;
default:
DEBUGCHK(FALSE);
}
}
///////////////////////////////////////////////////////////////////////////////
// DelayForPowerUp - Delay for powerup
// Input: pSlot - slot to delay on
//
// Output:
// Notes:
//
///////////////////////////////////////////////////////////////////////////////
VOID DelayForPowerUp(PSDBUS_HC_SLOT_CONTEXT pSlot)
{
// delay for power up
if (pSlot->PowerUpDelay != 0) {
Sleep(pSlot->PowerUpDelay);
} else {
// powerup delay should be set
DEBUG_CHECK(FALSE, (TEXT("SDBusDriver: Slot Delay is 0!!!\n")));
Sleep(500);
}
}
///////////////////////////////////////////////////////////////////////////////
// SetCardPower - Set the card power
// Input: DeviceType - the device type
// OperatingVoltageMask - operating voltage mask
// pSlot - the slot
// SetHCPower - flag to indicate whether the power should be set in the HC
// (combo cards do not need to reset power if the I/O portion
// was already powered).
//
// Output:
// Return: SD_API_STATUS code
// Notes:
// This function sets the card power and polls the card until it is
// not busy
///////////////////////////////////////////////////////////////////////////////
SD_API_STATUS SetCardPower(SDCARD_DEVICE_TYPE DeviceType,
DWORD OperatingVoltageMask,
PSDBUS_HC_SLOT_CONTEXT pSlot,
BOOL SetHCPower,
CReg *pregDevice)
{
SD_API_STATUS status = SD_API_STATUS_SUCCESS; // intermediate status
SD_COMMAND_RESPONSE response; // response
UCHAR command; // command
SD_RESPONSE_TYPE responseType; // response type
ULONG powerUpRetries; // power up retries
BOOL appcmd = FALSE; // command is an app cmd
ULONG powerUpInterval; // powerup interval
ULONG totalPowerUpTime; // total powerup time
ULONG powerUpIntervalByDevice; // powerup interval by device
switch (DeviceType) {
case Device_MMC:
command = SD_CMD_MMC_SEND_OPCOND;
responseType = ResponseR3;
powerUpIntervalByDevice = DEFAULT_POWER_UP_MMC_POLL_INTERVAL;
break;
case Device_SD_IO:
command = SD_CMD_IO_OP_COND;
responseType = ResponseR4;
powerUpIntervalByDevice = DEFAULT_POWER_UP_SDIO_POLL_INTERVAL;
break;
case Device_SD_Memory:
command = SD_ACMD_SD_SEND_OP_COND;
responseType = ResponseR3;
appcmd = TRUE;
powerUpIntervalByDevice = DEFAULT_POWER_UP_SD_POLL_INTERVAL;
break;
default:
DEBUGCHK(FALSE);
return SD_API_STATUS_INVALID_PARAMETER;
}
// check to see if we need to apply power
if (SetHCPower) {
DEBUGMSG(SDBUS_ZONE_DEVICE, (TEXT("SDBusDriver: Setting slot %d power to 0x%08X \n"),
pSlot->SlotIndex, OperatingVoltageMask));
// set slot power
status = SDSetSlotPower(pSlot,
OperatingVoltageMask);
if (!SD_API_SUCCESS(status)) {
DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDBusDriver: Host failed to set slot power 0x%08X on slot:%d \n"),
status, pSlot->SlotIndex));
return status;
}
DelayForPowerUp(pSlot);
}
if (Device_SD_IO != DeviceType) {
// put the card into idle again
status = SendSDCommand(pSlot->hDevice,
SD_CMD_GO_IDLE_STATE,
0x00000000,
NoResponse,
NULL);
if (!SD_API_SUCCESS(status)){
DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDBusDriver: Go Idle Failed during powerup: Status: 0x%08X on slot:%d \n"),status,
pSlot->SlotIndex));
return status;
}
}
totalPowerUpTime = pregDevice->ValueDW(POWER_UP_POLL_TIME_KEY,
DEFAULT_POWER_UP_TOTAL_WAIT_TIME);
powerUpInterval = pregDevice->ValueDW(POWER_UP_POLL_TIME_INTERVAL_KEY,
powerUpIntervalByDevice);
powerUpRetries = totalPowerUpTime/powerUpInterval;
DEBUGMSG(SDBUS_ZONE_DEVICE, (TEXT("SDBusDriver: Power Set, checking card in slot %d, MaxRetries: %d, Time: %d MS, Interval: %d MS \n"),
pSlot->SlotIndex, powerUpRetries, totalPowerUpTime , powerUpInterval));
while (powerUpRetries != 0) {
if (appcmd) {
// send it as an APP cmd
status = SendSDAppCommand(pSlot->hDevice,
command,
OperatingVoltageMask,
responseType,
&response);
} else {
// send the command to get the ready bit
status = SendSDCommand(pSlot->hDevice,
command,
OperatingVoltageMask,
responseType,
&response);
}
if (!SD_API_SUCCESS(status)){
break;
}
if (Device_SD_IO == DeviceType) {
// check to see if the I/O is ready
if (SD_IS_IO_READY(&response)) {
// we're done
break;
}
} else {
// check to see if the MMC or Memory card is ready
if (SD_IS_MEM_READY(&response)) {
// card is ready
break;
}
}
DEBUGMSG(SDBUS_ZONE_DEVICE, (TEXT("SDBusDriver: Card in slot %d not ready, countdown: %d \n"),
pSlot->SlotIndex, powerUpRetries));
powerUpRetries--;
// sleep the powerup interval
Sleep(powerUpInterval);
}
if (0 == powerUpRetries) {
DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDBusDriver: Device failed to powerup after voltage setting \n")));
status = SD_API_STATUS_DEVICE_NOT_RESPONDING;
}
if (SD_API_SUCCESS(status)) {
DEBUGMSG(SDBUS_ZONE_DEVICE, (TEXT("SDBusDriver: Card in slot %d ready \n"),
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -