📄 sdiocontrollerbase.cpp
字号:
PUCHAR respBuff; // response buffer
DWORD dwWaitCount = 0;
//----- 1. Wait for the response information to get arrive at the controller -----
while(!(vm_pSDIReg->SDICSTA & RESPONSE_RECEIVED))
{
dwWaitCount++;
if( dwWaitCount > WAIT_TIME )
{
DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCD:GetCommandResponse() - timeout waiting for command response!\r\n")));
return SD_API_STATUS_RESPONSE_TIMEOUT;
}
if( !IsCardPresent() )
{
DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCD:GetCommandResponse() - Card ejected!\r\n")));
return SD_API_STATUS_DEVICE_REMOVED;
}
if(vm_pSDIReg->SDICSTA & COMMAND_TIMED_OUT)
{
vm_pSDIReg->SDICSTA = COMMAND_TIMED_OUT; // Clear the error
DEBUGMSG (SDCARD_ZONE_ERROR,(TEXT("GetCommandResponse returned SD_API_STATUS_RESPONSE_TIMEOUT (COMMAND_TIMED_OUT)\r\n")));
return SD_API_STATUS_RESPONSE_TIMEOUT;
}
if(vm_pSDIReg->SDIDSTA & CRC_CHECK_FAILED)
{
vm_pSDIReg->SDIDSTA = CRC_CHECK_FAILED; // Clear the error
DEBUGMSG (SDCARD_ZONE_ERROR,(TEXT("GetCommandResponse returned SD_API_STATUS_CRC_ERROR (CRC_CHECK_FAILED)\r\n")));
return SD_API_STATUS_CRC_ERROR;
}
if(vm_pSDIReg->SDIDSTA & DATA_TRANSMIT_CRC_ERROR)
{
vm_pSDIReg->SDIDSTA = DATA_TRANSMIT_CRC_ERROR; // Clear the error
DEBUGMSG (SDCARD_ZONE_ERROR,(TEXT("getSDICommandResponse returned SD_API_STATUS_CRC_ERROR (DATA_TRANSMIT_CRC_ERROR)\r\n")));
return SD_API_STATUS_CRC_ERROR;
}
if(vm_pSDIReg->SDIDSTA & DATA_RECEIVE_CRC_ERROR)
{
vm_pSDIReg->SDIDSTA = DATA_RECEIVE_CRC_ERROR; // Clear the error
DEBUGMSG (SDCARD_ZONE_ERROR,(TEXT("GetCommandResponse returned SD_API_STATUS_CRC_ERROR (DATA_RECEIVE_CRC_ERROR)\r\n")));
return SD_API_STATUS_CRC_ERROR;
}
if(vm_pSDIReg->SDIDSTA & DATA_TIME_OUT)
{
vm_pSDIReg->SDIDSTA = DATA_TIME_OUT; // Clear the error
DEBUGMSG (SDCARD_ZONE_ERROR,(TEXT("GetCommandResponse returned SD_API_STATUS_DATA_TIMEOUT (DATA_TIME_OUT)\r\n")));
return SD_API_STATUS_DATA_TIMEOUT;
}
}
vm_pSDIReg->SDICSTA = RESPONSE_RECEIVED; // Clear the status
//----- 2. Copy the response information to our "response buffer" -----
// NOTE: All START_BIT and TRANSMISSION_BIT bits ='0'. All END_BIT bits ='0'. All RESERVED bits ='1'
respBuff = pRequest->CommandResponse.ResponseBuffer;
switch(pRequest->CommandResponse.ResponseType)
{
case NoResponse:
break;
case ResponseR1:
case ResponseR1b:
//--- SHORT RESPONSE (48 bits total)---
// Format: { START_BIT(1) | TRANSMISSION_BIT(1) | COMMAND_INDEX(6) | CARD_STATUS(32) | CRC7(7) | END_BIT(1) }
// NOTE: START_BIT and TRANSMISSION_BIT = 0, END_BIT = 1
//
*(respBuff ) = (BYTE)(START_BIT | TRANSMISSION_BIT | pRequest->CommandCode);
*(respBuff + 1) = (BYTE)(vm_pSDIReg->SDIRSP0 );
*(respBuff + 2) = (BYTE)(vm_pSDIReg->SDIRSP0 >> 8 );
*(respBuff + 3) = (BYTE)(vm_pSDIReg->SDIRSP0 >> 16);
*(respBuff + 4) = (BYTE)(vm_pSDIReg->SDIRSP0 >> 24);
*(respBuff + 5) = (BYTE)(END_RESERVED | END_BIT);
break;
case ResponseR3:
case ResponseR4:
//--- SHORT RESPONSE (48 bits total)---
// Format: { START_BIT(1) | TRANSMISSION_BIT(1) | RESERVED(6) | CARD_STATUS(32) | RESERVED(7) | END_BIT(1) }
//
*(respBuff ) = (BYTE)(START_BIT | TRANSMISSION_BIT | START_RESERVED);
*(respBuff + 1) = (BYTE)(vm_pSDIReg->SDIRSP0 );
*(respBuff + 2) = (BYTE)(vm_pSDIReg->SDIRSP0 >> 8 );
*(respBuff + 3) = (BYTE)(vm_pSDIReg->SDIRSP0 >> 16);
*(respBuff + 4) = (BYTE)(vm_pSDIReg->SDIRSP0 >> 24);
*(respBuff + 5) = (BYTE)(END_RESERVED | END_BIT);
break;
case ResponseR5:
case ResponseR6:
//--- SHORT RESPONSE (48 bits total)---
// Format: { START_BIT(1) | TRANSMISSION_BIT(1) | COMMAND_INDEX(6) | RCA(16) | CARD_STATUS(16) | CRC7(7) | END_BIT(1) }
//
*(respBuff ) = (BYTE)(START_BIT | TRANSMISSION_BIT | pRequest->CommandCode);
*(respBuff + 1) = (BYTE)(vm_pSDIReg->SDIRSP0 );
*(respBuff + 2) = (BYTE)(vm_pSDIReg->SDIRSP0 >> 8 );
*(respBuff + 3) = (BYTE)(vm_pSDIReg->SDIRSP0 >> 16);
*(respBuff + 4) = (BYTE)(vm_pSDIReg->SDIRSP0 >> 24);
*(respBuff + 5) = (BYTE)(vm_pSDIReg->SDIRSP1 >> 24);
break;
case ResponseR2:
//--- LONG RESPONSE (136 bits total)---
// Format: { START_BIT(1) | TRANSMISSION_BIT(1) | RESERVED(6) | CARD_STATUS(127) | END_BIT(1) }
//
// NOTE: In this implementation, the caller doesn't require the upper 8 bits of reserved data.
// Consequently, these bits aren't included and the response info is copied directly into
// the beginning of the supplied buffer.
//
//*(respBuff ) = (BYTE)(START_BIT | TRANSMISSION_BIT | START_RESERVED);
//
*(respBuff + 0) = (BYTE)(vm_pSDIReg->SDIRSP3 );
*(respBuff + 1) = (BYTE)(vm_pSDIReg->SDIRSP3 >> 8 );
*(respBuff + 2) = (BYTE)(vm_pSDIReg->SDIRSP3 >> 16);
*(respBuff + 3) = (BYTE)(vm_pSDIReg->SDIRSP3 >> 24);
*(respBuff + 4) = (BYTE)(vm_pSDIReg->SDIRSP2 );
*(respBuff + 5) = (BYTE)(vm_pSDIReg->SDIRSP2 >> 8 );
*(respBuff + 6) = (BYTE)(vm_pSDIReg->SDIRSP2 >> 16);
*(respBuff + 7) = (BYTE)(vm_pSDIReg->SDIRSP2 >> 24);
*(respBuff + 8) = (BYTE)(vm_pSDIReg->SDIRSP1 );
*(respBuff + 9) = (BYTE)(vm_pSDIReg->SDIRSP1 >> 8 );
*(respBuff + 10)= (BYTE)(vm_pSDIReg->SDIRSP1 >> 16);
*(respBuff + 11)= (BYTE)(vm_pSDIReg->SDIRSP1 >> 24);
*(respBuff + 12)= (BYTE)(vm_pSDIReg->SDIRSP0 );
*(respBuff + 13)= (BYTE)(vm_pSDIReg->SDIRSP0 >> 8 );
*(respBuff + 14)= (BYTE)(vm_pSDIReg->SDIRSP0 >> 16);
*(respBuff + 15)= (BYTE)(vm_pSDIReg->SDIRSP0 >> 24);
break;
default:
DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCD:GetCmdResponse(): Unrecognized response type!\r\n")));
break;
}
DEBUGMSG (SDHC_RESPONSE_ZONE,(TEXT("GetCommandResponse returned SD_API_STATUS_SUCCESS\r\n")));
return SD_API_STATUS_SUCCESS;
}
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function: CSDIOControllerBase::SetupDmaXfer()
Description: Prepares the SDI device for a transfer
Returns: SD_API_STATUS code.
-------------------------------------------------------------------*/
BOOL CSDIOControllerBase::SetupDmaXfer(PSD_BUS_REQUEST pRequest)
{
//----- 1. Check the parameters -----
if(!pRequest)
{
DEBUGMSG(SDCARD_ZONE_ERROR, (TEXT("SDHCD:SetupDmaXfer() - Invalid parameters!\r\n")));
return FALSE;
}
//----- 2. Setup the SD/MMC controller according to the type of transfer -----
switch(pRequest->TransferClass)
{
case SD_READ:
//********* 3. READ request *********
m_dwLastTypeOfTransfer = SD_READ;
//----- 3a. Reset the FIFO -----
vm_pSDIReg->SDIDTIMER = MAX_DATABUSY_TIMEOUT;
vm_pSDIReg->SDIBSIZE = pRequest->BlockSize;
Stop_SDIO_DMA_Channel();
switch( m_dwDMAChannel )
{
case 0:
//----- 3b. Initialize the DMA channel for input mode -----
if (m_DATATransferSize == 4)
vm_pDMAreg->DISRC0 = (int)MMCFIFO_DWORD_PHYS;
else if (m_DATATransferSize == 2)
vm_pDMAreg->DISRC0 = (int)MMCFIFO_WORD_PHYS;
else
vm_pDMAreg->DISRC0 = (int)MMCFIFO_BYTE_PHYS;
vm_pDMAreg->DISRCC0 |= (SOURCE_PERIPHERAL_BUS | FIXED_SOURCE_ADDRESS); // Source is periperal bus, fixed addr
vm_pDMAreg->DIDST0 = (int)m_pDMABufferPhys.LowPart;
vm_pDMAreg->DIDSTC0 &= ~(DESTINATION_PERIPHERAL_BUS | FIXED_DESTINATION_ADDRESS); // Destination is system bus, increment addr
//----- 3c. Configure the DMA channel's transfer characteristics: handshake, sync PCLK, interrupt, -----
// single RX, single service,, MMC request, no auto-reload, word (32 bits), RX count
vm_pDMAreg->DCON0 = ( HANDSHAKE_MODE | GENERATE_INTERRUPT | MMC_DMA0 | DMA_TRIGGERED_BY_HARDWARE
| NO_DMA_AUTO_RELOAD );
if (m_DATATransferSize == 4)
if (m_bUseDMABurst)
vm_pDMAreg->DCON0 |= ( SELECT_BURST_TRANSFER | TRANSFER_WORD | ((pRequest->BlockSize >> 4) * pRequest->NumBlocks));
else
vm_pDMAreg->DCON0 |= ( TRANSFER_WORD | ((pRequest->BlockSize >> 2) * pRequest->NumBlocks));
else if (m_DATATransferSize == 2)
vm_pDMAreg->DCON0 |= ( TRANSFER_HALF_WORD | ((pRequest->BlockSize >> 1) * pRequest->NumBlocks));
else
vm_pDMAreg->DCON0 |= ( TRANSFER_BYTE | ((pRequest->BlockSize) * pRequest->NumBlocks));
break;
case 1:
//----- 3b. Initialize the DMA channel for input mode -----
if (m_DATATransferSize == 4)
vm_pDMAreg->DISRC1 = (int)MMCFIFO_DWORD_PHYS;
else if (m_DATATransferSize == 2)
vm_pDMAreg->DISRC1 = (int)MMCFIFO_WORD_PHYS;
else
vm_pDMAreg->DISRC1 = (int)MMCFIFO_BYTE_PHYS;
vm_pDMAreg->DISRCC1 |= (SOURCE_PERIPHERAL_BUS | FIXED_SOURCE_ADDRESS); // Source is periperal bus, fixed addr
vm_pDMAreg->DIDST1 = (int)m_pDMABufferPhys.LowPart;
vm_pDMAreg->DIDSTC1 &= ~(DESTINATION_PERIPHERAL_BUS | FIXED_DESTINATION_ADDRESS); // Destination is system bus, increment addr
//----- 3c. Configure the DMA channel's transfer characteristics: handshake, sync PCLK, interrupt, -----
// single RX, single service,, MMC request, no auto-reload, word (32 bits), RX count
vm_pDMAreg->DCON1 = ( HANDSHAKE_MODE | GENERATE_INTERRUPT | MMC_DMA0 | DMA_TRIGGERED_BY_HARDWARE
| NO_DMA_AUTO_RELOAD );
if (m_DATATransferSize == 4)
if (m_bUseDMABurst)
vm_pDMAreg->DCON1 |= ( SELECT_BURST_TRANSFER | TRANSFER_WORD | ((pRequest->BlockSize >> 4) * pRequest->NumBlocks));
else
vm_pDMAreg->DCON1 |= ( TRANSFER_WORD | ((pRequest->BlockSize >> 2) * pRequest->NumBlocks));
else if (m_DATATransferSize == 2)
vm_pDMAreg->DCON1 |= ( TRANSFER_HALF_WORD | ((pRequest->BlockSize >> 1) * pRequest->NumBlocks));
else
vm_pDMAreg->DCON1 |= ( TRANSFER_BYTE | ((pRequest->BlockSize) * pRequest->NumBlocks));
break;
case 2:
//----- 3b. Initialize the DMA channel for input mode -----
if (m_DATATransferSize == 4)
vm_pDMAreg->DISRC2 = (int)MMCFIFO_DWORD_PHYS;
else if (m_DATATransferSize == 2)
vm_pDMAreg->DISRC2 = (int)MMCFIFO_WORD_PHYS;
else
vm_pDMAreg->DISRC2 = (int)MMCFIFO_BYTE_PHYS;
vm_pDMAreg->DISRCC2 |= (SOURCE_PERIPHERAL_BUS | FIXED_SOURCE_ADDRESS); // Source is periperal bus, fixed addr
vm_pDMAreg->DIDST2 = (int)m_pDMABufferPhys.LowPart;
vm_pDMAreg->DIDSTC2 &= ~(DESTINATION_PERIPHERAL_BUS | FIXED_DESTINATION_ADDRESS); // Destination is system bus, increment addr
//----- 3c. Configure the DMA channel's transfer characteristics: handshake, sync PCLK, interrupt, -----
// single RX, single service,, MMC request, no auto-reload, word (32 bits), RX count
vm_pDMAreg->DCON2 = ( HANDSHAKE_MODE | GENERATE_INTERRUPT | MMC_DMA0 | DMA_TRIGGERED_BY_HARDWARE
| NO_DMA_AUTO_RELOAD );
if (m_DATATransferSize == 4)
if (m_bUseDMABurst)
vm_pDMAreg->DCON2 |= ( SELECT_BURST_TRANSFER | TRANSFER_WORD | ((pRequest->BlockSize >> 4) * pRequest->NumBlocks));
else
vm_pDMAreg->DCON2 |= ( TRANSFER_WORD | ((pRequest->BlockSize >> 2) * pRequest->NumBlocks));
else if (m_DATATransferSize == 2)
vm_pDMAreg->DCON2 |= ( TRANSFER_HALF_WORD | ((pRequest->BlockSize >> 1) * pRequest->NumBlocks));
else
vm_pDMAreg->DCON2 |= ( TRANSFER_BYTE | ((pRequest->BlockSize) * pRequest->NumBlocks));
break;
case 3:
//----- 3b. Initialize the DMA channel for input mode -----
if (m_DATATransferSize == 4)
vm_pDMAreg->DISRC3 = (int)MMCFIFO_DWORD_PHYS;
else if (m_DATATransferSize == 2)
vm_pDMAreg->DISRC3 = (int)MMCFIFO_WORD_PHYS;
else
vm_pDMAreg->DISRC3 = (int)MMCFIFO_BYTE_PHYS;
vm_pDMAreg->DISRCC3 |= (SOURCE_PERIPHERAL_BUS | FIXED_SOURCE_ADDRESS); // Source is periperal bus, fixed addr
vm_pDMAreg->DIDST3 = (int)m_pDMABufferPhys.LowPart;
vm_pDMAreg->DIDSTC3 &= ~(DESTINATION_PERIPHERAL_BUS | FIXED_DESTINATION_ADDRESS); // Destination is system bus, increment addr
//----- 3c. Configure the DMA channel's transfer characteristics: handshake, sync PCLK, interrupt, -----
// single RX, single service,, MMC request, no auto-reload, word (32 bits), RX count
vm_pDMAreg->DCON3 = ( HANDSHAKE_MODE | GENERATE_INTERRUPT | MMC_DMA0 | DMA_TRIGGERED_BY_HARDWARE
| NO_DMA_AUTO_RELOAD );
if (m_DATATransferSize == 4)
if (m_bUseDMABurst)
vm_pDMAreg->DCON3 |= ( SELECT_BURST_TRANSFER | TRANSFER_WORD | ((pRequest->BlockSize >> 4) * pRequest->NumBlocks));
else
vm_pDMAreg->DCON3 |= ( TRANSFER_WORD | ((pRequest->BlockSize >> 2) * pRequest->NumBlocks));
else if (m_DATATransferSize == 2)
vm_pDMAreg->DCON3 |= ( TRANSFER_HALF_WORD | ((pRequest->BlockSize >> 1) * pRequest->NumBlocks));
else
vm_pDMAreg->DCON3 |= ( TRANSFER_BYTE | ((pRequest->BlockSize) * pRequest->NumBlocks));
break;
default:
ASSERT(0); // invalid DMA Channel... we should never get here
}
//----- 3d. Setup the controller and DMA channel appropriately -----
vm_pSDIReg->SDIDCON = RECEIVE_AFTER_COMMAND | TRANSFER_BLOCK_MODE | Get_SDI_Bus_Width() | DMA_ENABLE | DATA_TRANS_START | DATA_RECEIVE_START | pRequest->NumBlocks;
if (m_DATATransferSize == 4)
if (m_bUseDMABurst)
vm_pSDIReg->SDIDCON |= (BURST4_ENABLE | DATA_SIZE_WORD);
else
vm_pSDIReg->SDIDCON |= DATA_SIZE_WORD;
else if(m_DATATransferSize == 2)
vm_pSDIReg->SDIDCON |= DATA_SIZE_HWORD;
else
vm_pSDIReg->SDIDCON |= DATA_SIZE_BYTE;
break;
case SD_WRITE:
//********* 4. WRITE request *********
m_dwLastTypeOfTransfer = SD_WRITE;
//----- 4a. Reset the FIFO -----
vm_pSDIReg->SDIDTIMER = MAX_DATABUSY_TIMEOUT;
vm_pSDIReg->SDIBSIZE = pRequest->BlockSize;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -