📄 sd_disk.c
字号:
}
if (error)
{
RETAILMSG(MSG_DISK, (_T("SD: SDI_ResetInterface - error:%d\r\n"), error));
if (errorcode)
*errorcode = error;
return FALSE;
}
return TRUE;
}
//------------------------------------------------------------------------------
//
// Deinit interface - deinit the current device
//
// Arguments:
// controller - handle for the instance.
// errorcode - record error.
//
// Functions:
// Realese DMA and close the interrupt event.
//
//------------------------------------------------------------------------------
BOOL
SDI_DeinitInterface(
SD_controller *controller,
unsigned long *errorcode
)
{
unsigned long error = 0;
if (!controller)
error = 1;
if (!error)
{
SDI_ResetInterface(controller, 0);
if (controller->Registers)
MmUnmapIoSpace((void*)controller->Registers, sizeof(SD_REG));
if (controller->InterruptEvent)
CloseHandle(controller->InterruptEvent);
if (controller->SysDetect)
MmUnmapIoSpace((void*)controller->SysDetect, sizeof(SD_REG));
}
if (!error)
{
SDI_ReleaseDMA();
if (DMAIntrEvent != NULL)
{
CloseHandle (DMAIntrEvent);
DMAIntrEvent = NULL;
}
}
if (error)
{
RETAILMSG(MSG_DISK, (_T("SD: SDI_DeinitInterface - error:%d\r\n"), error));
if (errorcode)
*errorcode = error;
return FALSE;
}
return TRUE;
}
//------------------------------------------------------------------------------
//
// Send Command
//
// Arguments:
// controller - handle for the instance.
// param - parameters of command.
// arg - arguments of command.
// response - return values if the command has response, or else ignored.
// errorcode - record error.
//
// Functions:
// Send command to card. Then wait the interrupt.
// If the command has response, it will feed back response. Else it will
// send a command end signal.
// See also define of CommandParameters.
//
//------------------------------------------------------------------------------
BOOL
SDI_SendCmd(
SD_controller*controller,
const Command_Parameter *param,
unsigned long arg,
apMCI_sResponse *response,
unsigned long *errorcode
)
{
unsigned long error = 0;
unsigned long CommandData = 0;
BOOL TimeOut = FALSE;
SD_REG *regs;
if (!controller || !param)
error = 1;
regs = controller->Registers;
if (!regs)
error = 2;
if (!error)
{
BOOL cmdok = FALSE;
regs->sd_CLEAR = MCI_STATUS_STATIC_MASK;
/*construct command*/
apBIT_SET(CommandData,MCI_CMD_INDEX, param->CmdIndex);
apBIT_SET(CommandData,MCI_CMD_RESPONSE, param->Responsetype);
apBIT_SET(CommandData,MCI_CMD_INTERRUPT, param->CmdTimer);
apBIT_SET(CommandData,MCI_CMD_PENDING, (param->Option & MCI_CMDOPT_PENDING)!=0);
/*enable bit*/
CommandData |= apBIT_MASK(MCI_CMD_ENABLE);
regs->sd_MASK0 = 0;
InterruptDone(SYSINTR_SD0);
regs->sd_MASK0 = param->InterruptMask;
regs->sd_ARGUMENT = arg ;
ResetEvent(controller->InterruptEvent);
regs->sd_COMMAND = CommandData;
while (!error && !cmdok)
{
if (WaitForSingleObject(controller->InterruptEvent, param->WaitTime) == WAIT_TIMEOUT)
{
error = 3;
InterruptDone(SYSINTR_SD0);
}
else
{
unsigned long LastStatus = regs->sd_STATUS¶m->InterruptMask;
if (((LastStatus&apMCI_CMDSTAT_SENT) && (param->Responsetype == apMCI_CMDRESP_NONE)) ||
((LastStatus&apMCI_CMDSTAT_RESPOK) && (param->Responsetype != apMCI_CMDRESP_NONE)))
{
cmdok = TRUE;
}
else if (LastStatus & apMCI_CMDSTAT_FAIL)
{
RETAILMSG(MSG_DISK, (_T("SD: SDI_SendCmd -Command:0x%x Status:0x%x\r\n"), CommandData, LastStatus));
error = 4;
}
regs->sd_CLEAR = LastStatus;
InterruptDone(SYSINTR_SD0);
}
}
regs->sd_MASK0 = 0;
regs->sd_CLEAR = MCI_STATUS_STATIC_MASK;
regs->sd_COMMAND = 0;
regs->sd_ARGUMENT = apBITS_ALL;
}
if (response && (param->Responsetype!=apMCI_CMDRESP_NONE))
{
if (param->Responsetype == apMCI_CMDRESP_SHORT)
response->ShortResponse = regs->sd_RESP0;
else if (param->Responsetype == apMCI_CMDRESP_LONG)
{
response->LongResponse[0] = regs->sd_RESP0;
response->LongResponse[1] = regs->sd_RESP1;
response->LongResponse[2] = regs->sd_RESP2;
response->LongResponse[3] = regs->sd_RESP3;
}
}
if (error)
{
RETAILMSG(MSG_DISK, (_T("SD: SDI_SendCmd - error:0x%x\r\n"), error));
if (errorcode)
*errorcode = error;
return FALSE;
}
return TRUE;
}
//------------------------------------------------------------------------------
//
// Decode long response
//
// Arguments:
// pLongResponse - Pointer to a long response structure.
// LowestBit - Lowest bit to decode.
// BitWidth - How many bits to decode.
//
// Functions:
// Intercept a segment in the long response.
//
//------------------------------------------------------------------------------
unsigned long
SDI_PrvLongResponseDecode(
apMCI_sResponse *pLongResponse,
unsigned long LowestBit,
unsigned long BitWidth
)
{
unsigned long Result;
unsigned long LowWordBits; // bits in the low word
// RETAILMSG(MSG_DISK, (_T("SD: SDI_PrvLongResponseDecode+\r\n")));
// The low bits are in the last words of the response, so bit B lies in word 4-(B/32)
LowWordBits=32 - (LowestBit & 31);
Result=apBIT_GET_FIELD(
pLongResponse->LongResponse[3-(LowestBit>>5)],
MIN(BitWidth,LowWordBits),
LowestBit & 31
);
// Go to the next word and take some low bits from there
if (BitWidth > LowWordBits)
{
Result|=apBIT_GET_FIELD(
pLongResponse->LongResponse[2-(LowestBit>>5)],
BitWidth - LowWordBits,
0
)<<LowWordBits;
}
// RETAILMSG(MSG_DISK, (_T("SD: SDI_PrvLongResponseDecode-\r\n")));
return Result;
}
//------------------------------------------------------------------------------
//
// Get card identification data
//
// Arguments:
// controller - handle for the instance.
// pDecodedResponse - pointer to decode respond.
// errorcode - record error.
//
//------------------------------------------------------------------------------
BOOL
SDI_GetCID(
SD_controller *controller,
apMCI_sDecodedCID *pDecodedResponse,
unsigned long *errorcode
)
{
apMCI_sResponse response, *pResponseData = &response;
unsigned long temp1, temp2, error = 0;
RETAILMSG(MSG_DISK, (_T("SD: SDI_GetCID+\r\n")));
if (!controller || !pDecodedResponse)
error = 1;
if (!error)
{
if (!SDI_SendCmd(controller, &CommandParameters[ALL_SEND_CID], 0x0, &response, &error))
{
if (!SDI_SendCmd(controller, &CommandParameters[ALL_SEND_CID], 0x0, &response, &error))
{
error = 2;
}
}
}
if (!error)
{
pDecodedResponse->MID=
SDI_PrvLongResponseDecode(pResponseData,bsMCI_CID_MID,bwMCI_CID_MID);
// get Application ID
pDecodedResponse->OID=
SDI_PrvLongResponseDecode(pResponseData,bsMCI_CID_OID,bwMCI_CID_OID);
temp1 = SDI_PrvLongResponseDecode(pResponseData,bsMCI_SD_CID_PNM_H,bwMCI_SD_CID_PNM_H);
temp2 = SDI_PrvLongResponseDecode(pResponseData,bsMCI_SD_CID_PNM_L,bwMCI_SD_CID_PNM_L);
pDecodedResponse->PNM[0] = (unsigned char)apBIT_GET_FIELD(temp1, 8, 0);
pDecodedResponse->PNM[1] = (unsigned char)apBIT_GET_FIELD(temp2, 8, 24);
pDecodedResponse->PNM[2] = (unsigned char)apBIT_GET_FIELD(temp2, 8, 16);
pDecodedResponse->PNM[3] = (unsigned char)apBIT_GET_FIELD(temp2, 8, 8);
pDecodedResponse->PNM[4] = (unsigned char)apBIT_GET_FIELD(temp2, 8, 0);
pDecodedResponse->PNM[5] = 0;
pDecodedResponse->PNM[6] = 0;
// get Product Revision
pDecodedResponse->PRV=
SDI_PrvLongResponseDecode(pResponseData,bsMCI_SD_CID_PRV,bwMCI_SD_CID_PRV);
// get Product Serial Number
pDecodedResponse->PSN=
SDI_PrvLongResponseDecode(pResponseData,bsMCI_SD_CID_PSN,bwMCI_SD_CID_PSN);
// get Manufacturing Date
pDecodedResponse->MDT=
SDI_PrvLongResponseDecode(pResponseData,bsMCI_SD_CID_MDT,bwMCI_SD_CID_MDT);
}
if (error)
{
RETAILMSG(MSG_DISK, (_T("SD: SDI_GetCID - error:%d\r\n"), error));
if (errorcode)
*errorcode = error;
return FALSE;
}
RETAILMSG(MSG_DISK, (_T("SD: SDI_GetCID-\r\n")));
return TRUE;
}
//------------------------------------------------------------------------------
//
// Get card specific data
//
// Arguments:
// controller - handle for the instance.
// pDecodedResponse - pointer to decode respond.
// errorcode - record error.
//
//------------------------------------------------------------------------------
BOOL SDI_GetCSD(
SD_controller *controller,
apMCI_sDecodedCSD *pDecodedResponse,
unsigned long RCA,
unsigned long *errorcode
)
{
unsigned long error = 0;
/* look up tables for calculating values in CSD register */
static const unsigned long TAACUnit[8] = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000}; /* calculates as 0.1ns */
static const unsigned long TranSpeedUnit[8] = {10, 100, 1000, 10000, 0, 0, 0, 0}; /* calculates as kHz */
static const unsigned long Value[16] = {0, 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80};
apMCI_sResponse response, *pResponseData = &response;
if (!controller || !pDecodedResponse)
error = 1;
if (!error)
{
if (!SDI_SendCmd(controller, &CommandParameters[SEND_CSD], RCA, &response, &error))
{
if (!SDI_SendCmd(controller, &CommandParameters[SEND_CSD], RCA, &response, &error))
{
error = 2;
}
}
}
if (!error)
{
pDecodedResponse->csd_structure = (unsigned char)SDI_PrvLongResponseDecode(pResponseData, bsMCI_CSD_STRUCTURE, bwMCI_CSD_STRUCTURE);
pDecodedResponse->crc = (unsigned char)SDI_PrvLongResponseDecode( pResponseData, bsMCI_CSD_CRC, bwMCI_CSD_CRC);
pDecodedResponse->file_format = (unsigned char)SDI_PrvLongResponseDecode( pResponseData, bsMCI_CSD_FILE_FORMAT, bwMCI_CSD_FILE_FORMAT);
pDecodedResponse->temporary_write_protection = SDI_PrvLongResponseDecode( pResponseData, bsMCI_CSD_TEMP_WP, bwMCI_CSD_TEMP_WP);
pDecodedResponse->permanent_write_protection = SDI_PrvLongResponseDecode( pResponseData, bsMCI_CSD_PERM_WP, bwMCI_CSD_PERM_WP);
pDecodedResponse->copy_flag = SDI_PrvLongResponseDecode( pResponseData, bsMCI_CSD_COPY, bwMCI_CSD_COPY);
pDecodedResponse->file_format_group = (unsigned char)SDI_PrvLongResponseDecode( pResponseData, bsMCI_CSD_FILE_FORMAT_GRP, bwMCI_CSD_FILE_FORMAT_GRP);
if (pDecodedResponse->csd_structure == 0)
{
pDecodedResponse->erase_sector_size = 1 + SDI_PrvLongResponseDecode( pResponseData, bsMCI_CSD_ERASE_SECT_SD, bwMCI_CSD_ERASE_SECT_SD);
}
else
{
pDecodedResponse->erase_sector_size = (1 + SDI_PrvLongResponseDecode( pResponseData, bsMCI_CSD_ERASE_GRP_SIZE11, bwMCI_CSD_ERASE_GRP_SIZE11))
* (1 + SDI_PrvLongResponseDecode( pResponseData, bsMCI_CSD_ERASE_GRP_MULT11, bwMCI_CSD_ERASE_GRP_MULT11));
}
if (pDecodedResponse->csd_structure == 0)
{
pDecodedResponse->write_protect_group_size = 1 + SDI_PrvLongResponseDecode( pResponseData, bsMCI_CSD_WP_GRP_SIZE, bwMCI_CSD_WP_GRP_SIZE);
}
else
{
pDecodedResponse->write_protect_group_size = 1 + SDI_PrvLongResponseDecode( pResponseData, bsMCI_CSD_WP_GRP_SIZE11, bwMCI_CSD_WP_GRP_SIZE11);
}
pDecodedResponse->partial_blocks_for_write_allowed = SDI_PrvLongResponseDecode( pResponseData, bsMCI_CSD_WTBLP, bwMCI_CSD_WTBLP);
pDecodedResponse->max_write_data_block_length = 1 << SDI_PrvLongResponseDecode( pResponseData, bsMCI_CSD_WTBL, bwMCI_CSD_WTBL);
pDecodedResponse->write_speed_factor = 1 << SDI_PrvLongResponseDecode( pResponseData, bsMCI_CSD_R2W, bwMCI_CSD_R2W);
pDecodedResponse->write_protect_group_enable = SDI_PrvLongResponseDecode( pResponseData, bsMCI_CSD_WP_GRP_ENABLE, bwMCI_CSD_WP_GRP_ENABLE);
pDecodedResponse->erase_single_block_enable = SDI_PrvLongResponseDecode( pResponseData, bsMCI_CSD_ERASE_SINGLE_BLOCK_ENABLE, bwMCI_CSD_ERASE_SINGLE_BLOCK_ENABLE);
pDecodedResponse->device_size_multiplier = 1 << (2 + SDI_PrvLongResponseDecode( pResponseData, bsMCI_CSD_CMULT, bwMCI_CSD_CMULT));
pDecodedResponse->max_write_current_max = (unsigned char)SDI_PrvLongResponseDecode( pResponseData, bsMCI_CSD_VDD_W_CURR_MAX, bwMCI_CSD_VDD_W_CURR_MAX);
pDecodedResponse->max_write_current_min = (unsigned char)SDI_PrvLongResponseDecode( pResponseData, bsMCI_CSD_VDD_W_CURR_MIN, bwMCI_CSD_VDD_W_CURR_MIN);
pDecodedResponse->max_read_current_max = (unsigned char)SDI_PrvLongResponseDecode( pResponseData, bsMCI_CSD_VDD_R_CURR_MAX, bwMCI_CSD_VDD_R_CURR_MAX);
pDecodedResponse->max_read_current_min = (unsigned char)SDI_PrvLongResponseDecode( pResponseData, bsMCI_CSD_VDD_R_CURR_MIN, bwMCI_CSD_VDD_R_CURR_MIN);
pDecodedResponse->device_size = SDI_PrvLongResponseDecode( pResponseData, bsMCI_CSD_CSIZE, bwMCI_CSD_CSIZE);
pDecodedResponse->dsr_implemented = SDI_PrvLongResponseDecode( pResponseData, bsMCI_CSD_DSR_IMP, bwMCI_CSD_DSR_IMP);
pDecodedResponse->read_block_misalignment = SDI_PrvLongResponseDecode( pResponseData, bsMCI_CSD_RDBLMIS, bwMCI_CSD_RDBLMIS);
pDecodedResponse->write_block_misalignment = SDI_PrvLongResponseDecode( pResponseData, bsMCI_CSD_WTBLMIS, bwMCI_CSD_WTBLMIS);
pDecodedResponse->partial_blocks_for_read_allowed = SDI_PrvLongResponseDecode( pResponseData, bsMCI_CSD_RDBLP, bwMCI_CSD_RDBLP);
pDecodedResponse->max_read_data_block_length = 1 << SDI_PrvLongResponseDecode( pResponseData, bsMCI_CSD_RDBL, bwMCI_CSD_RDBL);
pDecodedResponse->card_command_classes = SDI_PrvLongResponseDecode( pResponseData, bsMCI_CSD_CCC, bwMCI_CSD_CCC);
pDecodedResponse->max_data_transfer_rate_khz = TranSpeedUnit[SDI_PrvLongResponseDecode( pResponseData, bsMCI_CSD_MAXTRANLO, bwMCI_CSD_MAXTRANLO)]
* Value[SDI_PrvLongResponseDecode( pResponseData, bsMCI_CSD_MAXTRANHI, bwMCI_CSD_MAXTRANHI)];
pDecodedResponse->data_read_access_time_2_in_clk_cycles = 100 * SDI_PrvLongResponseDecode( pResponseData, bsMCI_CSD_NSAC, bwMCI_CSD_NSAC);
pDecodedResponse->data_read_access_time_1_tns = TAACUnit[SDI_PrvLongResponseDecode( pResponseData, bsMCI_CSD_TAACLO, bwMCI_CSD_TAACLO)]
* Value[SDI_PrvLongResponseDecode( pResponseData, bsMCI_CSD_TAACHI, bwMCI_CSD_TAACHI)];
pDecodedResponse->CardSize = (pDecodedResponse->device_size + 1)
* pDecodedResponse->device_size_multiplier
* pDecodedResponse->max_read_data_block_length;
}
if (error)
{
RETAILMSG(MSG_DISK, (_T("SD: SDI_GetCSD - error:%d\r\n"), error));
if (errorcode)
*errorcode = error;
return FALSE;
}
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -