Description
Source
Call Graph
Start Line: 375
unsigned char SDSPI_SendCommand(SdSpi *pSdSpi, SdSpiCmd *pSdSpiCmd)
{
AT91S_SPI *pSpiHw = pSdSpi->pSpiHw;
unsigned char CmdToken[6];
unsigned char *pData;
unsigned int blockSize;
unsigned int i;
unsigned char error;
unsigned char dataHeader;
unsigned int dataRetry1 = 100;
unsigned int dataRetry2 = 100;
unsigned char crc[2];
unsigned char crcPrev = 0;
unsigned char crcPrev2 = 0;
SANITY_CHECK(pSdSpi);
SANITY_CHECK(pSpiHw);
SANITY_CHECK(pCommand);
CmdToken[0] = pCommand->cmd & 0x3F;
pData = pCommand->pData;
blockSize = pCommand->blockSize;
SDSPI_MakeCmd((unsigned char *)&CmdToken, pCommand->arg);
// Command is now being executed
pSdSpi->pCommand = pCommand;
pCommand->status = SDSPI_STATUS_PENDING;
// Send the command
if((pCommand->conTrans == SPI_NEW_TRANSFER) || (blockSize == 0)) {
for(i = 0; i < 6; i++) {
error = SDSPI_Write(pSdSpi, &CmdToken[i], 1);
if (error) {
TRACE_DEBUG("Error: %d\n\r", error);
return error;
}
}
// Specific for Cmd12()
if ((pCommand->cmd & 0x3F) == 12) {
if( 1 == SDSPI_Wait(pSdSpi, 2) ) {
TRACE_DEBUG("Pb Send command 12\n\r");
}
}
if (pCommand->pResp) {
error = SDSPI_GetCmdResp(pSdSpi, pCommand);
if (error) {
TRACE_DEBUG("Error: %d\n\r", error);
return error;
}
}
}
if( (blockSize > 0) && (pCommand->nbBlock == 0) ) {
pCommand->nbBlock = 1;
}
// For data block operations
while (pCommand->nbBlock > 0) {
// If data block size is invalid, return error
if (blockSize == 0) {
TRACE_DEBUG("Block Size = 0\n\r");
return 1;
}
// DATA transfer from card to host
if (pCommand->isRead) {
do {
SDSPI_Read(pSdSpi, &dataHeader, 1);
dataRetry1 --;
if (dataHeader == SDSPI_START_BLOCK_1) {
break;
}
else if((dataHeader & 0xf0) == 0x00) {
pCommand->status = SDSPI_STATUS_ERROR;
TRACE_DEBUG("Data Error 0x%X!\n\r", dataHeader);
return 1;
}
} while(dataRetry1 > 0);
if (dataRetry1 == 0) {
TRACE_DEBUG("Timeout dataretry1\n\r");
return 1;
}
SDSPI_Read(pSdSpi, pData, blockSize);
// Specific for Cmd9()
if ((pCommand->cmd & 0x3f) != 0x9) {
SDSPI_Read(pSdSpi, crc, 2);
#ifdef SDSPI_CRC_ON
// Check data CRC
TRACE_DEBUG("Check Data CRC\n\r");
crcPrev = 0;
crcPrev2 = 0;
if (crc[0] != ((crc_itu_t(crcPrev, pData, blockSize) & 0xff00) >> 8 )
|| crc[1] != (crc_itu_t(crcPrev2, pData, blockSize) & 0xff)) {
TRACE_ERROR("CRC error 0x%X 0x%X 0x%X\n\r", \
crc[0], crc[1], crc_itu_t(pData, blockSize));
return 1;
}
#endif
}
}
// DATA transfer from host to card
else {
SDSPI_NCS(pSdSpi);
if ((pCommand->conTrans == SPI_CONTINUE_TRANSFER) || ((pCommand->cmd & 0x3f) == 25)) {
dataHeader = SDSPI_START_BLOCK_2;
}
else {
dataHeader = SDSPI_START_BLOCK_1;
}
crcPrev = 0;
crc[0] = (crc_itu_t(crcPrev, pData, blockSize) & 0xff00) >> 8;
crcPrev2 = 0;
crc[1] = (crc_itu_t(crcPrev2, pData, blockSize) & 0xff);
SDSPI_Write(pSdSpi, &dataHeader, 1);
SDSPI_Write(pSdSpi, pData, blockSize);
SDSPI_Write(pSdSpi, crc, 2);
// If status bits in data response is not "data accepted", return error
if ((SDSPI_GetDataResp(pSdSpi, pCommand) & 0xe) != 0x4) {
TRACE_ERROR("Write resp error!\n\r");
return 1;
}
do {
if (SDSPI_WaitDataBusy(pSdSpi) == 0) {
break;
}
dataRetry2--;
} while(dataRetry2 > 0);
}
pData += blockSize;
pCommand->nbBlock--;
}
if (pCommand->status == SDSPI_STATUS_PENDING) {
pCommand->status = 0;
}
//TRACE_DEBUG("end SDSPI_SendCommand\n\r");
return 0;
}