📄 sdiocontrollerbase.cpp
字号:
pBlockCaps->ReadBlockSize, pBlockCaps->ReadBlocks));
DEBUGMSG(SDCARD_ZONE_INFO, (TEXT("SDHCD:SDHCDSlotOptionHandler() - Write Block Length: %d , Write Blocks: %d\n"),
pBlockCaps->WriteBlockSize, pBlockCaps->WriteBlocks));
pBlockCaps = (PSD_HOST_BLOCK_CAPABILITY)pData;
//----- Validate block transfer properties -----
if (pBlockCaps->ReadBlockSize < MINIMUM_BLOCK_TRANSFER_SIZE )
{
pBlockCaps->ReadBlockSize = MINIMUM_BLOCK_TRANSFER_SIZE;
}
if (pBlockCaps->WriteBlockSize < MINIMUM_BLOCK_TRANSFER_SIZE )
{
pBlockCaps->WriteBlockSize = MINIMUM_BLOCK_TRANSFER_SIZE;
}
if (pBlockCaps->ReadBlockSize > MAXIMUM_BLOCK_TRANSFER_SIZE )
{
pBlockCaps->ReadBlockSize = MAXIMUM_BLOCK_TRANSFER_SIZE;
}
if (pBlockCaps->WriteBlockSize > MAXIMUM_BLOCK_TRANSFER_SIZE )
{
pBlockCaps->WriteBlockSize = MAXIMUM_BLOCK_TRANSFER_SIZE;
}
break;
case SDHCDGetSlotInfo:
DEBUGMSG (SDCARD_ZONE_INFO,(TEXT("SDHCDSlotOptionHandler option=SDHCDGetSlotInfo")));
if( OptionSize != sizeof(SDCARD_HC_SLOT_INFO) || pData == NULL )
{
status = SD_API_STATUS_INVALID_PARAMETER;
}
else
{
PSDCARD_HC_SLOT_INFO pSlotInfo = (PSDCARD_HC_SLOT_INFO)pData;
// set the slot capabilities
SDHCDSetSlotCapabilities(pSlotInfo, SD_SLOT_SD_4BIT_CAPABLE |
SD_SLOT_SD_1BIT_CAPABLE |
SD_SLOT_SDIO_CAPABLE |
SD_SLOT_SDIO_INT_DETECT_4BIT_MULTI_BLOCK);
SDHCDSetVoltageWindowMask(pSlotInfo, (SD_VDD_WINDOW_3_2_TO_3_3 | SD_VDD_WINDOW_3_3_TO_3_4));
// Set optimal voltage
SDHCDSetDesiredSlotVoltage(pSlotInfo, SD_VDD_WINDOW_3_2_TO_3_3);
SDHCDSetMaxClockRate(pSlotInfo, MAX_SDI_BUS_TRANSFER_SPEED);
// Set power up delay. We handle this in SetVoltage().
SDHCDSetPowerUpDelay(pSlotInfo, 300);
}
break;
default:
DEBUGMSG (SDCARD_ZONE_WARN,(TEXT("SDHCDSlotOptionHandler option=SD_API_STATUS_INVALID_PARAMETER")));
status = SD_API_STATUS_INVALID_PARAMETER;
}
DEBUGMSG (SDCARD_ZONE_FUNC,(TEXT("SDHCDSlotOptionHandler ends")));
return status;
}
///////////////////////////////////////////////////////////////////////////////
// CSDIOControllerBase::BusRequestHandler - bus request handler
// Input: Slot - slot the request is going on
// pRequest - the request
//
// Output:
// Return: SD_API_STATUS Code
// Notes: The request passed in is marked as uncancelable, this function
// has the option of making the outstanding request cancelable
//
///////////////////////////////////////////////////////////////////////////////
SD_API_STATUS CSDIOControllerBase::BusRequestHandler(DWORD dwSlot, PSD_BUS_REQUEST pRequest)
{
DEBUGMSG (SDCARD_ZONE_FUNC,(TEXT("BusRequestHandler starts (CMD:%d)"), pRequest->CommandCode));
SD_API_STATUS status;
// Reset FIFO and status registers
vm_pSDIReg->SDICON |= RESET_FIFO;
vm_pSDIReg->SDIDSTA = 0xffff;
vm_pSDIReg->SDIDCON = 0;
vm_pSDIReg->SDICSTA = 0xffff;
vm_pSDIReg->SDICCON = 0;
Start_SDI_Clock();
//----- 1. Determine the type of command (data vs. no data) and send the command -----
m_dwNumBytesToTransfer = pRequest->BlockSize * pRequest->NumBlocks;
//----- 2 Can we schedule a DMA operation using the caller's buffer as-is? -----
//
// There are two situations that we need to account for:
//
// 1) A non-DWORD aligned buffer
// 2) A buffer whose "transfer size" isn't a multiple of sizeof(DWORD)
//
// For the first case, an data-alignment exception will occur if the buffer is
// addressed at the non-DWORD aligned address. For the second case, the SDI
// controller will pad zeros into the remaining bytes of the last unfilled DWORD.
// Practically, this means that the SD Card will get a corrupted data string.
//
// To handle these two situations, we can simply use our polling I/O routines to
// fulfill the I/O request.
//
if( ( m_dwDMAChannel == 0xffffffff ) || (!IS_BUFFER_DWORD_ALIGNED(pRequest->pBlockBuffer)) || (!IS_BUFFER_SIZE_A_DWORD_MULTPLE(pRequest->BlockSize)) || m_dwNumBytesToTransfer > MAXIMUM_DMA_TRANSFER_SIZE )
{
m_bUseDMAForTransfer = FALSE;
SetupPollingXfer(pRequest); // Use polling I/O routines for data transfer
}else{
m_bUseDMAForTransfer = TRUE;
SetupDmaXfer(pRequest); // Use DMA for data transfer
}
if(pRequest->TransferClass == SD_COMMAND)
{
// Command only
status = SendCommand(pRequest->CommandCode, pRequest->CommandArgument, pRequest->CommandResponse.ResponseType, FALSE);
if(!SD_API_SUCCESS(status))
{
DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCD:SDHCDBusRequestHandler() - Error sending command:0x%02x\r\n"), pRequest->CommandCode));
goto BUS_REQUEST_COMPLETE;
}
//----- 2. Is this the first command sent to the card? If so, delay the 74 (or 80) clock cycles per the SD spec -----
if(m_bSendInitClocks)
{
m_bSendInitClocks = FALSE;
Wait_80_SDI_Clock_Cycles();
}
}
else
{
// Command with data transfer
status = SendCommand(pRequest->CommandCode, pRequest->CommandArgument, pRequest->CommandResponse.ResponseType, TRUE);
if(!SD_API_SUCCESS(status))
{
DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCD:SDHCDBusRequestHandler() - Error sending command:0x%02x\r\n"), pRequest->CommandCode));
goto BUS_REQUEST_COMPLETE;
}
}
//----- 3. Signal an IST that processes response information and cache our state -----
// NOTE: It is critical that this API NOT complete the bus request directly (which
// is why another thread is used). The bus driver expects bus requests to complete
// asynchronously and a stack overflow WILL eventually occur if this rule isn't honored.
SetEvent(m_hResponseReceivedEvent);
m_CurrentState = CommandSent;
status = SD_API_STATUS_PENDING;
BUS_REQUEST_COMPLETE:
DEBUGMSG (SDCARD_ZONE_FUNC,(TEXT("SDHCD:BusRequestHandler ends")));
return status;
}
//-------------------------------------- Interrupt Service Threads---------------------------------------
///////////////////////////////////////////////////////////////////////////////
// CSDIOControllerBase::TransferIstThread - IST thread for DMA channel dedicated to SDIO
// Input: pController - the controller instance
// Output:
// Return: Thread exit code
// Notes:
///////////////////////////////////////////////////////////////////////////////
DWORD CSDIOControllerBase::TransferIstThread()
{
PSD_BUS_REQUEST pRequest = NULL; // the request to complete
SD_API_STATUS status;
if( m_DMAIstThreadPriority != 0xffffffff && !CeSetThreadPriority( GetCurrentThread(), m_DMAIstThreadPriority ) )
{
DEBUGMSG(SDCARD_ZONE_WARN,(TEXT("SDHCDriver:TransferIstThread(): warning, failed to set CEThreadPriority \n")));
}
for(;;)
{
//----- 1. Wait for the command response -----
status = SD_API_STATUS_PENDING;
if(WaitForSingleObject(m_hResponseReceivedEvent, INFINITE) == WAIT_FAILED)
{
DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCDriver:TransferIstThread(): Wait Failed!\n")));
return FALSE;
}
if(m_bDriverShutdown)
{
DEBUGMSG(SDCARD_ZONE_WARN, (TEXT("SDHCD:TransferIstThread(): Thread Exiting\n")));
return FALSE;
}
//----- 2. Get and lock the current bus request -----
if(pRequest == NULL)
{
if((pRequest = SDHCDGetAndLockCurrentRequest(m_pHCContext, 0)) == NULL)
{
DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCD:SDHControllerIstThread() - Unable to get/lock current request!\r\n")));
status = SD_API_STATUS_INVALID_DEVICE_REQUEST;
goto TRANSFER_DONE;
}
}
//----- 3. SPECIAL CASE: The SD_CMD_STOP_TRANSMISSION that is sent after a SD_CMD_WRITE_MULTIPLE_BLOCK command -----
// requires a BUSY_CHECK
if( ( m_fHandleBusyCheckOnCommand38 && pRequest->CommandCode == SD_CMD_ERASE ) ||
( ( pRequest->CommandCode == SD_CMD_STOP_TRANSMISSION ) && ( m_dwLastTypeOfTransfer == SD_WRITE ) ) )
{
DWORD dwWaitCount = 0;
//----- 4. Wait until the I/O transfer is complete -----
while(!(vm_pSDIReg->SDIDSTA & BUSY_CHECKS_FINISH))
{
dwWaitCount++;
if( dwWaitCount > WAIT_TIME )
{
DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCD:SDHControllerIstThread() - timeout waiting for BUSY_CHECKS to finish!\r\n")));
status = SD_API_STATUS_DATA_TIMEOUT;
goto TRANSFER_DONE;
}
if( !IsCardPresent() )
{
DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCD:SDHControllerIstThread() - Card ejected!\r\n")));
status = SD_API_STATUS_DEVICE_REMOVED;
goto TRANSFER_DONE;
}
if((vm_pSDIReg->SDIDSTA & FIFO_FAIL_ERROR))
{
vm_pSDIReg->SDIDSTA = BUSY_CHECKS_FINISH | FIFO_FAIL_ERROR;
DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCD:SDHControllerIstThread() - FIFO Error waiting for BUSY_CHECKS to finish!\r\n")));
status = SD_API_STATUS_DATA_ERROR;
goto TRANSFER_DONE;
}
if((vm_pSDIReg->SDIDSTA & DATA_TRANSMIT_CRC_ERROR))
{
vm_pSDIReg->SDIDSTA = BUSY_CHECKS_FINISH | DATA_TRANSMIT_CRC_ERROR;
DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCD:SDHControllerIstThread() - Transmit CRC Error waiting for BUSY_CHECKS to finish!\r\n")));
status = SD_API_STATUS_DATA_ERROR;
goto TRANSFER_DONE;
}
if((vm_pSDIReg->SDIDSTA & DATA_RECEIVE_CRC_ERROR))
{
vm_pSDIReg->SDIDSTA = BUSY_CHECKS_FINISH | DATA_RECEIVE_CRC_ERROR;
DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCD:SDHControllerIstThread() - Receive CRC Error waiting for BUSY_CHECKS to finish!\r\n")));
status = SD_API_STATUS_DATA_ERROR;
goto TRANSFER_DONE;
}
if((vm_pSDIReg->SDIDSTA & DATA_TIME_OUT))
{
vm_pSDIReg->SDIDSTA = BUSY_CHECKS_FINISH | DATA_TIME_OUT;
DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCD:SDHControllerIstThread() - Data timeout waiting for BUSY_CHECKS to finish!\r\n")));
status = SD_API_STATUS_DATA_TIMEOUT;
goto TRANSFER_DONE;
}
}
vm_pSDIReg->SDIDSTA = BUSY_CHECKS_FINISH;
}
//----- 5. Get the response information -----
if(pRequest->CommandResponse.ResponseType == NoResponse)
{
goto TRANSFER_DONE;
}else{
status = GetCommandResponse(pRequest);
if(!SD_API_SUCCESS(status))
{
DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCD:SDHCDBusRequestHandler() - Error getting response for command:0x%02x\r\n"), pRequest->CommandCode));
goto TRANSFER_DONE;
}
}
//----- 6. If this is a data transfer, start the I/O operation; otherwise, finish the request -----
if(pRequest->TransferClass == SD_COMMAND)
{
goto TRANSFER_DONE;
}
//----- 7. If this is a DMA transfer, we enable interrupts and wait for the DMA interrupt. Otherwise, -----
// we use our polling routines to complete the I/O.
if(m_bUseDMAForTransfer == FALSE)
{
//----- 8. Polling I/O, use our special routines to handle this request
switch(pRequest->TransferClass)
{
case SD_READ:
if(!PollingReceive(pRequest, m_dwNumBytesToTransfer))
{
DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCD:BusRequestHandler() - PollingReceive() failed\r\n")));
goto TRANSFER_DONE;
}
break;
case SD_WRITE:
if(!PollingTransmit(pRequest, m_dwNumBytesToTransfer))
{
DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCD:BusRequestHandler() - PollingReceive() failed\r\n")));
goto TRANSFER_DONE;
}
break;
}
status = SD_API_STATUS_SUCCESS;
}else
{
//----- 9. For WRITE requests, be sure to copy the write data from the caller's buffer into DMA memory-----
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -