📄 sd_disk.c
字号:
controller->Registers->sd_POWER = MCI_POWER_OFF; //InterruptDisable(SYSINTR_SD0); //msleep(10); {volatile int a; for(a=0; a<10000; a++); } } 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) iounmap((void*)controller->Registers); /* if (controller->InterruptEvent) CloseHandle(controller->InterruptEvent); */ if (controller->SysDetect) iounmap((void*)controller->SysDetect); } /* 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; DECLARE_COMPLETION(comp); 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); //controller->cmddone_data = NULL; controller->cmddone_data = ∁ regs->sd_MASK0 = 0; //InterruptDone(SYSINTR_SD0); regs->sd_MASK0 = param->InterruptMask; regs->sd_ARGUMENT = arg ; //ResetEvent(controller->InterruptEvent); regs->sd_COMMAND = CommandData; wait_for_completion(&comp); { if (((controller->laststatus&apMCI_CMDSTAT_SENT) && (param->Responsetype == apMCI_CMDRESP_NONE)) || ((controller->laststatus&apMCI_CMDSTAT_RESPOK) && (param->Responsetype != apMCI_CMDRESP_NONE))) { cmdok = TRUE; } else if (controller->laststatus & apMCI_CMDSTAT_FAIL) { error = 4; } } controller->cmddone_data = NULL; 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) { 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; if (!controller || !pDecodedResponse) error = 1; if (!error) { int i=0; while(!SDI_SendCmd(controller, &CommandParameters[ALL_SEND_CID], 0x0, &response, &error)) { i++; if(i%10==0){ error = 2; break; } msleep(100); /*{ volatile int a, b; for(a=0; a<100; a++); for(b=0; b<10000; b++); }*/ } if(i>1) printk("%d times getcid ok\n", i); } 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 SD_DISK_DEBUG { int i; printk("MID: %x\n", pDecodedResponse->MID); printk("OID: %x\n", pDecodedResponse->OID); printk("MID: "); for (i=0; i<7; i++) { printk("%x ", pDecodedResponse->PNM[i]); } printk("\n"); printk("PRV: %x\n", pDecodedResponse->PRV); printk("PSN: %x\n", pDecodedResponse->PSN); printk("MDT: %x\n", pDecodedResponse->MDT); }#endif if (error) { if (errorcode) *errorcode = error; return FALSE; } 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) { if (errorcode) *errorcode = error; return FALSE; }#if SD_DISK_DEBUG { printk("device_size: %x\n", pDecodedResponse->device_size); printk("device_size_multiplier: %x\n", pDecodedResponse->device_size_multiplier); printk("max_read_data_block_length: %x\n", pDecodedResponse->max_read_data_block_length); printk("CardSize: %x\n", pDecodedResponse->CardSize); } { printk("csd_struct: %x\n", pDecodedResponse->csd_structure); printk("data_read_access_time_1_tns: %x\n", pDecodedResponse->data_read_access_time_1_tns); printk("data_read_access_time_2_in_clk_cycles: %x\n", pDecodedResponse->data_read_access_time_2_in_clk_cycles); printk("max_data_transfer_rate_khz: %x\n", pDecodedResponse->max_data_transfer_rate_khz); printk("card_command_classes: %x\n", pDecodedResponse->card_command_classes); printk("max_read_data_block_length: %x\n", pDecodedResponse->max_read_data_block_length); printk("partial_blocks_for_read_allowed: %x\n", pDecodedResponse->partial_blocks_for_read_allowed); printk("write_block_misalignment: %x\n", pDecodedResponse->write_block_misalignment); printk("read_block_misalignment: %x\n", pDecodedResponse->read_block_misalignment); printk("dsr_implemented: %x\n", pDecodedResponse->dsr_implemented); printk("device_size: %x\n", pDecodedResponse->device_size); printk("max_read_current_min: %x\n", pDecodedResponse->max_read_current_min); printk("max_read_current_max: %x\n", pDecodedResponse->max_read_current_max); printk("max_write_current_min: %x\n", pDecodedResponse->max_write_current_min); printk("max_write_current_max: %x\n", pDecodedResponse->max_write_current_max); printk("device_size_multiplier: %x\n", pDecodedResponse->device_size_multiplier); printk("erase_single_block_enable: %x\n", pDecodedResponse->erase_single_block_enable); //todo:: }#endif return TRUE;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -