📄 sdhcslot.cpp
字号:
DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("[HSMMC1] HandleErrors - ADMA Error without DMA Enabled (0x%x). Resetting CMD line.\r\n"),
wErrorStatus));
}
}
// Perform basic error recovery
WORD wErrIntSignal = ReadWord(SDHC_ERROR_INT_SIGNAL_ENABLE);
WriteWord(SDHC_ERROR_INT_SIGNAL_ENABLE, 0);
// Make sure that the value of "Error Interrupt Status Enable" is zero
WORD wErrIntStatusEn = ReadWord(SDHC_ERROR_INT_STATUS_ENABLE);
WriteWord(SDHC_ERROR_INT_STATUS_ENABLE,0);
if (IS_CMD_LINE_ERROR(wErrorStatus)) {
// Reset CMD line
DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("[HSMMC1] HandleErrors - Command line error (0x%x). Resetting CMD line.\r\n"),
wErrorStatus));
SoftwareReset(SOFT_RESET_CMD);
}
if (IS_DAT_LINE_ERROR(wErrorStatus)) {
// Reset DAT line
DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("[HSMMC1] HandleErrors - Data line error (0x%x). Resetting DAT line.\r\n"),
wErrorStatus));
DWORD RetryResetCount = 5000;
SoftwareReset(SOFT_RESET_DAT);
do {
WriteWord(SDHC_ERROR_INT_STATUS,wErrorStatus);
if ((ReadWord(SDHC_NORMAL_INT_STATUS) & NORMAL_INT_STATUS_ERROR_INT)) {
RetryResetCount--;
} else {
break;
}
if(RetryResetCount == 0) {
DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("[HSMMC1] HandleErrors - DAT line error Recovery Timeout...\r\n")));
}
} while(RetryResetCount != 0);
}
// clear all error status
WriteWord(SDHC_ERROR_INT_STATUS, wErrorStatus);
// re-enable error interrupt signals
WriteWord(SDHC_ERROR_INT_STATUS_ENABLE, wErrIntStatusEn);
WriteWord(SDHC_ERROR_INT_SIGNAL_ENABLE, wErrIntSignal);
// complete the request
if (pRequest) {
IndicateBusRequestComplete(pRequest, status);
} else {
// If there is not a current request, the initialize of normal interrupt status enable is needed.
WriteWord(SDHC_NORMAL_INT_STATUS_ENABLE,
(ReadWord(SDHC_NORMAL_INT_STATUS_ENABLE)) | NORMAL_INT_ENABLE_CMD_COMPLETE | NORMAL_INT_ENABLE_TRX_COMPLETE);
}
}
}
VOID
CSDHCSlotBase::HandleTransferDone(
)
{
PSD_BUS_REQUEST pRequest;
SD_API_STATUS status = SD_API_STATUS_SUCCESS;
// get the current request
pRequest = GetAndLockCurrentRequest();
if (pRequest) {
if (!TRANSFER_IS_COMMAND_ONLY(pRequest)) {
if (m_SlotDma && !m_SlotDma->IsDMACompleted()) {
m_SlotDma->DMANotifyEvent(*pRequest, TRANSFER_COMPLETED);
}
}
if (pRequest->HCParam != TRANSFER_SIZE(pRequest)) {
// This means that a Command Complete interrupt occurred before
// a Buffer Ready interrupt. Hardware should not allow this.
DEBUGCHK(FALSE);
status = SD_API_STATUS_DEVICE_RESPONSE_ERROR;
}
// complete the request
if (pRequest->Flags & SD_AUTO_ISSUE_CMD12) {
m_fAutoCMD12Success = TRUE;
}
IndicateBusRequestComplete(pRequest, status);
}
// else request must have been canceled due to an error
}
VOID
CSDHCSlotBase::HandleReadReady(
)
{
DEBUGMSG(SDHC_RECEIVE_ZONE, (TEXT("HandleReadReady - HandleReadReady!\n")));
// get the current request
PSD_BUS_REQUEST pRequest = GetAndLockCurrentRequest();
if (pRequest) {
DEBUGCHK(pRequest->NumBlocks > 0);
DEBUGCHK(pRequest->HCParam < TRANSFER_SIZE(pRequest));
DEBUGCHK(TRANSFER_IS_READ(pRequest));
#ifdef DEBUG
++m_dwReadyInts;
#endif
__try {
PDWORD pdwUserBuffer = (PDWORD) &pRequest->pBlockBuffer[pRequest->HCParam];
PDWORD pdwBuffer = pdwUserBuffer;
DWORD rgdwIntermediateBuffer[SDHC_MAX_BLOCK_LENGTH / sizeof(DWORD)];
BOOL fUsingIntermediateBuffer = FALSE;
DWORD cDwords = pRequest->BlockSize / 4;
DWORD dwRemainder = pRequest->BlockSize % 4;
PREFAST_DEBUGCHK(sizeof(rgdwIntermediateBuffer) >= pRequest->BlockSize);
if (((DWORD) pdwUserBuffer) % 4 != 0) {
// Buffer is not DWORD aligned so we must use an
// intermediate buffer.
pdwBuffer = rgdwIntermediateBuffer;
fUsingIntermediateBuffer = TRUE;
}
DWORD dwDwordsRemaining = cDwords;
pRequest->HCParam += dwDwordsRemaining * 4;
// Read the data from the device
while ( dwDwordsRemaining-- ) {
*(pdwBuffer++) = ReadDword(SDHC_BUFFER_DATA_PORT_0);
}
if ( dwRemainder != 0 ) {
DWORD dwLastWord = ReadDword(SDHC_BUFFER_DATA_PORT_0);
memcpy(pdwBuffer, &dwLastWord, dwRemainder);
pRequest->HCParam += dwRemainder;
}
if (fUsingIntermediateBuffer) {
memcpy(pdwUserBuffer, rgdwIntermediateBuffer, pRequest->BlockSize);
}
}
__except(SDProcessException(GetExceptionInformation())) {
DEBUGMSG(SDCARD_ZONE_ERROR, (_T("Exception reading from client buffer!\r\n")));
IndicateBusRequestComplete(pRequest, SD_API_STATUS_ACCESS_VIOLATION);
}
DEBUGCHK(pRequest->HCParam == (m_dwReadyInts * pRequest->BlockSize));
}
// else request must have been canceled due to an error
}
VOID
CSDHCSlotBase::HandleWriteReady(
)
{
DEBUGMSG(SDHC_TRANSMIT_ZONE, (TEXT("HandleWriteReady - HandleWriteReady! \n")));
// get the current request
PSD_BUS_REQUEST pRequest = GetAndLockCurrentRequest();
if (pRequest) {
DEBUGCHK(TRANSFER_IS_WRITE(pRequest));
DEBUGCHK(pRequest->NumBlocks > 0);
DEBUGCHK(pRequest->HCParam < TRANSFER_SIZE(pRequest));
#ifdef DEBUG
++m_dwReadyInts;
#endif
__try {
PDWORD pdwUserBuffer = (PDWORD) &pRequest->pBlockBuffer[pRequest->HCParam];
PDWORD pdwBuffer = pdwUserBuffer;
DWORD rgdwIntermediateBuffer[SDHC_MAX_BLOCK_LENGTH / sizeof(DWORD)];
BOOL fUsingIntermediateBuffer = FALSE;
DWORD cDwords = pRequest->BlockSize / 4;
DWORD dwRemainder = pRequest->BlockSize % 4;
PREFAST_DEBUGCHK(sizeof(rgdwIntermediateBuffer) >= pRequest->BlockSize);
if (((DWORD) pdwUserBuffer) % 4 != 0) {
// Buffer is not DWORD aligned so we must use an
// intermediate buffer.
pdwBuffer = rgdwIntermediateBuffer;
memcpy(rgdwIntermediateBuffer, pdwUserBuffer, pRequest->BlockSize);
}
DWORD dwDwordsRemaining = cDwords;
pRequest->HCParam += dwDwordsRemaining * 4;
// Write data to buffer data port
while ( dwDwordsRemaining-- ) {
WriteDword(SDHC_BUFFER_DATA_PORT_0, *(pdwBuffer++));
}
if ( dwRemainder != 0 ) {
DWORD dwLastWord = 0;
memcpy(&dwLastWord, pdwBuffer, dwRemainder);
WriteDword(SDHC_BUFFER_DATA_PORT_0, dwLastWord);
pRequest->HCParam += dwRemainder;
}
}
__except(SDProcessException(GetExceptionInformation())) {
DEBUGMSG(SDCARD_ZONE_ERROR, (_T("Exception reading from client buffer!\r\n")));
IndicateBusRequestComplete(pRequest, SD_API_STATUS_ACCESS_VIOLATION);
}
DEBUGCHK(pRequest->HCParam == (m_dwReadyInts * pRequest->BlockSize));
}
// else request must have been canceled due to an error
}
PVOID
CSDHCSlotBase::AllocPhysBuffer(
size_t cb,
PDWORD pdwPhysAddr
)
{
PVOID pvUncached;
PVOID pvRet = NULL;
DWORD dwPhysAddr;
pvUncached = AllocPhysMem(cb, PAGE_READWRITE, 0, 0, &dwPhysAddr);
if (pvUncached) {
*pdwPhysAddr = dwPhysAddr;
pvRet = pvUncached;
}
return pvRet;
}
VOID
CSDHCSlotBase::FreePhysBuffer(
PVOID pv
)
{
BOOL fSuccess;
DEBUGCHK(pv);
fSuccess = FreePhysMem(pv);
DEBUGCHK(fSuccess);
}
VOID
CSDHCSlotBase::SetHardwarePowerState(
CEDEVICE_POWER_STATE cpsNew
)
{
DEBUGCHK(VALID_DX(cpsNew));
DEBUGCHK(!DX_D1_OR_D2(cpsNew));
DEBUGCHK(m_cpsCurrent != cpsNew);
CEDEVICE_POWER_STATE cpsCurrent = m_cpsCurrent;
m_cpsCurrent = cpsNew;
BYTE bWakeupControl = m_bWakeupControl;
if (cpsCurrent == D0) {
SDClockOff();
if (cpsNew == D3) {
if ( m_fSDIOInterruptsEnabled &&
(bWakeupControl & WAKEUP_INTERRUPT) ) {
DEBUGCHK(m_fCardPresent);
m_fSleepsWithPower = TRUE;
m_fPowerUpDisabledInts = FALSE;
}
else {
// Wake on status changes only
WriteByte(SDHC_POWER_CONTROL, 0);
bWakeupControl &= ~WAKEUP_INTERRUPT;
}
// enable wakeup sources
m_wIntSignals = ReadWord(SDHC_NORMAL_INT_SIGNAL_ENABLE);
WriteWord(SDHC_NORMAL_INT_SIGNAL_ENABLE, 0);
WriteWord(SDHC_NORMAL_INT_STATUS, ReadWord(SDHC_NORMAL_INT_STATUS));
WriteByte(SDHC_WAKEUP_CONTROL, bWakeupControl);
}
else {
DEBUGCHK(cpsNew == D4);
WriteByte(SDHC_CLOCK_CONTROL, 0);
WriteByte(SDHC_POWER_CONTROL, 0);
}
}
else if (cpsCurrent == D3) {
// Coming out of wakeup state
if (cpsNew == D0) {
WriteByte(SDHC_WAKEUP_CONTROL, 0);
if (!m_fSleepsWithPower) {
// Power was turned off to the socket. Re-enumerate card.
if (m_fCardPresent) {
HandleRemoval(TRUE);
}
m_fCheckSlot = TRUE;
SetInterruptEvent();
}
else {
if (m_fCardPresent) {
// Do not do this if the card was removed or
// if power was not kept.
if (m_fPowerUpDisabledInts) {
EnableSDIOInterrupts(TRUE);
}
}
}
WriteWord(SDHC_NORMAL_INT_SIGNAL_ENABLE, m_wIntSignals);
}
else {
DEBUGCHK(cpsNew == D4);
WriteByte(SDHC_CLOCK_CONTROL, 0);
WriteByte(SDHC_WAKEUP_CONTROL, 0);
WriteByte(SDHC_POWER_CONTROL, 0);
WriteWord(SDHC_NORMAL_INT_SIGNAL_ENABLE, m_wIntSignals);
}
m_fSleepsWithPower = FALSE;
}
else {
DEBUGCHK(cpsCurrent == D4);
// Coming out of unpowered state - signal card removal
// so any card present will be re-enumerated.
//
// We do the same thing when we go to D3 as D0 because
// the slot has lost power so it could have been removed
// or changed. In other words, D3 is a meaningless state
// after D4.
m_cpsCurrent = D0; // Force to D0
// Do not call HandleRemoval here because it could cause
// a context switch in a PowerUp callback.
m_fFakeCardRemoval = TRUE;
m_fCheckSlot = TRUE;
SetInterruptEvent();
}
}
VOID
CSDHCSlotBase::DoEnableSDIOInterrupts(
BOOL fEnable
)
{
// To control the SDIO card interrupt on S3C6410, control
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -