📄 sdhcslot.cpp
字号:
m_paDmaBuffer = BusAddr.LowPart;
}
else {
// If we fail, we will simply fall back to PIO mode
FreePhysBuffer(pvBuffer);
}
}
}
// Interrupts are not enabled on a newly inserted card.
EnableSDIOInterrupts(FALSE);
// Indicate device arrival
IndicateSlotStateChange(DeviceInserted);
}
BOOL
CSDHCSlotBase::HandleCommandComplete(
)
{
SETFNAME();
PSD_BUS_REQUEST pRequest;
BOOL fRet = FALSE;
int count = 0 ;
RETAILMSG(0,(TEXT("CSDHCSlotBase::HandleCommandComplete\n")));
// get the current request
pRequest = GetAndLockCurrentRequest();
DEBUGCHK(m_dwReadyInts == 0);
if (pRequest) {
RETAILMSG(0,(TEXT("CSDHCSlotBase::HandleCommandComplete pRequest\n")));
DEBUGCHK(pRequest->HCParam == 0);
SD_API_STATUS transferStatus = SD_API_STATUS_SUCCESS;
if (NoResponse != pRequest->CommandResponse.ResponseType) {
// Copy response over to request structure. Note that this is a
// bus driver buffer, so we do not need to SetProcPermissions
// or __try/__except.
UNALIGNED DWORD *pdwResponseBuffer =
(PDWORD) (pRequest->CommandResponse.ResponseBuffer + 1); // Skip CRC
WORD wCommand = ReadWord(SDHC_COMMAND);
if ((wCommand & CMD_RESPONSE_R1B_R5B) == CMD_RESPONSE_R1B_R5B) {
// wait for Transfer Complete status, which indicate the busy wait is over.
// we should not handle this TXN_COMPLETE interrupt in IST in this case
/*
RETAILMSG(0,(TEXT("HandleCommandComplete Status: 0x%X\n"),ReadWord(SDHC_NORMAL_INT_STATUS_ENABLE)));
RETAILMSG(0,(TEXT("HandleCommandComplete Signal: 0x%X\n"),ReadWord(SDHC_NORMAL_INT_SIGNAL_ENABLE)));
BOOL fSuccess = WaitForReg<WORD>(ReadWord, SDHC_NORMAL_INT_STATUS,
NORMAL_INT_STATUS_TRX_COMPLETE, NORMAL_INT_STATUS_TRX_COMPLETE, 5000);
RETAILMSG(0, (_T("%s Go waiting for NORMAL_INT_STATUS_TRX_COMPLETE\r\n"),
pszFname));
if (!fSuccess) {
RETAILMSG(0, (_T("%s Timeout waiting for NORMAL_INT_STATUS_TRX_COMPLETE\r\n"),
pszFname));
DEBUGMSG(SDCARD_ZONE_ERROR, (_T("%s Timeout waiting for NORMAL_INT_STATUS_TRX_COMPLETE\r\n"),
pszFname));
transferStatus = SD_API_STATUS_RESPONSE_TIMEOUT;
}*/
RETAILMSG(0,(TEXT("CSDHCSlotBase::HandleCommandComplete SoftwareReset\n")));
// Reset cmd and dat circuits
SoftwareReset(SOFT_RESET_CMD | SOFT_RESET_DAT);
}
pdwResponseBuffer[0] = ReadDword(SDHC_R0);
RETAILMSG(0,(TEXT("pdwResponseBuffer[0]= 0x%X\n"),pdwResponseBuffer[0]));
if (pRequest->CommandResponse.ResponseType == ResponseR2) {
pdwResponseBuffer[1] = ReadDword(SDHC_R2);
pdwResponseBuffer[2] = ReadDword(SDHC_R4);
pdwResponseBuffer[3] = ReadDword(SDHC_R6);
RETAILMSG(0,(TEXT("pdwResponseBuffer[1]= 0x%X\n"),pdwResponseBuffer[1]));
RETAILMSG(0,(TEXT("pdwResponseBuffer[2]= 0x%X\n"),pdwResponseBuffer[2]));
RETAILMSG(0,(TEXT("pdwResponseBuffer[3]= 0x%X\n"),pdwResponseBuffer[3]));
}
}
// check for command/response only
if (TRANSFER_IS_COMMAND_ONLY(pRequest)) {
IndicateBusRequestComplete(pRequest, transferStatus);
fRet = TRUE;
} else {
// handle data phase transfer
//pIOPreg->GPFDAT = (0x1<<7);
//WaitForReg<WORD>(ReadWord, SDHC_NORMAL_INT_STATUS, NORMAL_INT_STATUS_TRX_COMPLETE, NORMAL_INT_STATUS_TRX_COMPLETE);
/*
do{
}while ((ReadWord(SDHC_NORMAL_INT_STATUS)&NORMAL_INT_STATUS_TRX_COMPLETE) != NORMAL_INT_STATUS_TRX_COMPLETE); */
pRequest->HCParam = 0;
fRet = FALSE;
}
}
// else request must have been canceled due to an error
return fRet;
}
VOID
CSDHCSlotBase::HandleErrors(
)
{
SD_API_STATUS status = SD_API_STATUS_SUCCESS;
// get the current request
PSD_BUS_REQUEST pRequest = GetAndLockCurrentRequest();
WORD wErrorStatus = ReadWord(SDHC_ERROR_INT_STATUS);
RETAILMSG(1,
(TEXT("HandleErrors - ERROR INT STATUS=0x%02X\n"), wErrorStatus));
DEBUGMSG(SDCARD_ZONE_ERROR,
(TEXT("HandleErrors - ERROR INT STATUS=0x%02X\n"), wErrorStatus));
if (pRequest) {
DumpRequest(pRequest, SDCARD_ZONE_ERROR);
}
DEBUGCHK( (wErrorStatus & ERR_INT_STATUS_VENDOR) == 0 );
if (wErrorStatus) {
if ( wErrorStatus & ERR_INT_STATUS_CMD_TIMEOUT ) {
status = SD_API_STATUS_RESPONSE_TIMEOUT;
}
if ( wErrorStatus & ERR_INT_STATUS_CMD_CRC ) {
status = SD_API_STATUS_CRC_ERROR;
if ( wErrorStatus & ERR_INT_STATUS_CMD_TIMEOUT )
status = SD_API_STATUS_DEVICE_RESPONSE_ERROR;
}
if ( wErrorStatus & ERR_INT_STATUS_CMD_ENDBIT ) {
status = SD_API_STATUS_RESPONSE_TIMEOUT;
}
if ( wErrorStatus & ERR_INT_STATUS_CMD_INDEX ) {
status = SD_API_STATUS_DEVICE_RESPONSE_ERROR;
}
if ( wErrorStatus & ERR_INT_STATUS_DAT_TIMEOUT ) {
status = SD_API_STATUS_DATA_TIMEOUT;
}
if ( wErrorStatus & ERR_INT_STATUS_DAT_CRC ) {
status = SD_API_STATUS_CRC_ERROR;
}
if ( wErrorStatus & ERR_INT_STATUS_DAT_ENDBIT ) {
status = SD_API_STATUS_DEVICE_RESPONSE_ERROR;
}
if ( wErrorStatus & ERR_INT_STATUS_BUS_POWER ) {
status = SD_API_STATUS_DEVICE_RESPONSE_ERROR;
}
if ( wErrorStatus & ERR_INT_STATUS_AUTOCMD12 ) {
status = SD_API_STATUS_DEVICE_RESPONSE_ERROR;
}
// Perform basic error recovery
WORD wErrIntSignal = ReadWord(SDHC_ERROR_INT_SIGNAL_ENABLE);
WriteWord(SDHC_ERROR_INT_SIGNAL_ENABLE, 0);
if (IS_CMD_LINE_ERROR(wErrorStatus)) {
// Reset CMD line
DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("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("HandleErrors - Data line error (0x%x). Resetting DAT line.\r\n"),
wErrorStatus));
SoftwareReset(SOFT_RESET_DAT);
}
// clear all error status
WriteWord(SDHC_ERROR_INT_STATUS, wErrorStatus);
// re-enable error interrupt signals
WriteWord(SDHC_ERROR_INT_SIGNAL_ENABLE, wErrIntSignal);
RETAILMSG(0,(TEXT("Error Handler : 0x%X\n"),ReadWord(SDHC_NORMAL_INT_STATUS_ENABLE)));
// complete the request
if (pRequest) {
RETAILMSG(0,(TEXT("IndicateBusRequestComplete(pRequest, status)\n")));
IndicateBusRequestComplete(pRequest, status);
}
else
{
WORD wIntEnable = ReadWord(SDHC_NORMAL_INT_STATUS_ENABLE);
wIntEnable |= NORMAL_INT_ENABLE_CMD_COMPLETE | NORMAL_INT_ENABLE_TRX_COMPLETE;
WriteWord(SDHC_NORMAL_INT_STATUS_ENABLE,wIntEnable);
RETAILMSG(0,(TEXT("Error Handler : 0x%X\n"),ReadWord(SDHC_NORMAL_INT_STATUS_ENABLE)));
}
}
}
VOID
CSDHCSlotBase::HandleTransferDone(
)
{
PSD_BUS_REQUEST pRequest;
SD_API_STATUS status = SD_API_STATUS_SUCCESS;
// get the current request
pRequest = GetAndLockCurrentRequest();
RETAILMSG(0,(TEXT("CSDHCSlotBase::HandleTransferDone\n")));
if (pRequest) {
if (!TRANSFER_IS_COMMAND_ONLY(pRequest)) {
if (UseDmaForRequest(pRequest)) {
DWORD cbTransfer = TRANSFER_SIZE(pRequest);
DWORD cbRemainder = cbTransfer % CB_DMA_PAGE;
if (cbRemainder == 0) {
cbRemainder = CB_DMA_PAGE;
}
pRequest->HCParam += cbRemainder;
RETAILMSG(0,(TEXT("pRequest->HCParam=%d, cbTransfer=%d, PAGE_SIZE=%d\n"),pRequest->HCParam,cbTransfer,PAGE_SIZE));
//pIOPreg->GPFDAT &= ~(0x1<<7);
if (TRANSFER_IS_READ(pRequest)) {
BOOL fNoException;
DEBUGCHK(cbTransfer <= CB_DMA_BUFFER);
SD_SET_PROC_PERMISSIONS_FROM_REQUEST(pRequest) {
fNoException = SDPerformSafeCopy(pRequest->pBlockBuffer,
m_pbDmaBuffer, cbTransfer);
} SD_RESTORE_PROC_PERMISSIONS();
if (fNoException == FALSE) {
status = SD_API_STATUS_ACCESS_VIOLATION;
}
}
}
}
if (pRequest->HCParam != TRANSFER_SIZE(pRequest)) {
// This means that a Command Complete interrupt occurred before
// a Buffer Ready interrupt. Hardware should not allow this.
RETAILMSG(1,(TEXT("pRequest->HCParam != TRANSFER_SIZE(pRequest)\n")));
DEBUGCHK(FALSE);
status = SD_API_STATUS_DEVICE_RESPONSE_ERROR;
}
// complete the request
//if ((pRequest->Flags & SD_AUTO_ISSUE_CMD12) && *((DWORD *)(pRequest->hDevice)) != 0) {
if ((pRequest->Flags & SD_AUTO_ISSUE_CMD12)) {
RETAILMSG(0,(TEXT("SDSDSDCARD\n")));
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(!UseDmaForRequest(pRequest));
DEBUGCHK(pRequest->NumBlocks > 0);
DEBUGCHK(pRequest->HCParam < TRANSFER_SIZE(pRequest));
DEBUGCHK(TRANSFER_IS_READ(pRequest));
#ifdef DEBUG
++m_dwReadyInts;
#endif
DWORD dwOldPermissions = SetProcPermissions(pRequest->CurrentPermissions);
__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);
}
SetProcPermissions(dwOldPermissions);
}
__except(SDProcessException(GetExceptionInformation())) {
DEBUGMSG(SDCARD_ZONE_ERROR, (_T("Exception reading from client buffer!\r\n")));
SetProcPermissions(dwOldPermissions);
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(!UseDmaForRequest(pRequest));
DEBUGCHK(pRequest->NumBlocks > 0);
DEBUGCHK(pRequest->HCParam < TRANSFER_SIZE(pRequest));
#ifdef DEBUG
++m_dwReadyInts;
#endif
DWORD dwOldPermissions = SetProcPermissions(pRequest->CurrentPermissions);
__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;
}
SetProcPermissions(dwOldPermissions);
}
__except(SDProcessException(GetExceptionInformation())) {
DEBUGMSG(SDCARD_ZONE_ERROR, (_T("Exception reading from client buffer!\r\n")));
SetProcPermissions(dwOldPermissions);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -