/*-----------------------------------*/ static int MountDevice(void * DriveData, int DeviceNumber, int DeviceType, DWORD Flags) { if(gMSDC_Handle->mIsInitialized) return SECTOR_SIZE; gMSP.is_failed = KAL_FALSE; start: if(!gMSDC_Handle->mIsPresent) { MSDC_PDNControl(KAL_TRUE); return FS_MSDC_MOUNT_ERROR; } MSDC_PDNControl(KAL_FALSE); MSP_POWER_ON(); if(MSP_Initialize() != MSP_NOERROR) { goto err_exit; } MSDC_PDNControl(KAL_TRUE); return SECTOR_SIZE; err_exit: MSP_POWER_OFF(); /* if(retry++ <= 1) { gMSP.is_failed = KAL_TRUE; goto start; } */ gMSP.is_failed = KAL_TRUE; MSDC_PDNControl(KAL_TRUE); return FS_MSDC_MOUNT_ERROR; }
static int HighLevelFormat(void * DriveData) { MSDC_PDNControl(KAL_FALSE); MS_API_CheckLogicalAdrsValid(); MSDC_PDNControl(KAL_TRUE); return FS_NO_ERROR; }
/*-----------------------------------*/ static int MountDevice(void * DriveData, int DeviceNumber, int DeviceType, DWORD Flags) { kal_uint8 retry = 0; //dbg_print("MountDevice_MS \r\n"); if(gMSDC_Handle->mIsInitialized) return SECTOR_SIZE; START: if(!gMSDC_Handle->mIsPresent) { //dbg_print("not present \r\n"); MSDC_PDNControl(KAL_TRUE); return FS_MSDC_MOUNT_ERROR; } MSDC_PDNControl(KAL_FALSE); if(MS_Initialize() != NO_ERROR) { goto ERR_EXIT; } #if defined(MS_FORMAT) if(MS_MountDevice(DeviceType) != FS_NO_ERROR) goto ERR_EXIT; #endif // get total sector number { int i = 0; FS_PartitionRecord *ptr; kal_uint8 c = gMS.Capacity; while((c >>= 1) != 2) i++; ptr = (FS_PartitionRecord*)MS_MBR[i]; gMS.TotalSectors = ptr->Sectors; } MSDC_PDNControl(KAL_TRUE); return SECTOR_SIZE; ERR_EXIT: if(retry++ < MAX_TRY) { //dbg_print("Mount MS failed! retry: %d \r\n",retry); goto START; } MSDC_PDNControl(KAL_TRUE); return FS_MSDC_MOUNT_ERROR; }
static int HighLevelFormat(void * DriveData) { MSP_STATUS status; if(!gMSDC_Handle->mIsInitialized) return FS_MSDC_FORMAT_ERROR; MSDC_PDNControl(KAL_FALSE); status = MSP_CMD_Format(MSP_FULL,NULL); MSDC_PDNControl(KAL_TRUE); if(status) return FS_MSDC_FORMAT_ERROR; return FS_NO_ERROR; }
/*-----------------------------------*/ static int ReadSectors(void * DriveData, DWORD Sector, UINT Sectors, void * Buffer) { MSP_STATUS status; kal_uint8 retry = 0; kal_uint16 read; gMSDC_Handle->timeout_count = 0; start: if(!gMSDC_Handle->mIsInitialized) { //dbg_print("Read but not Initialized \r\n"); MSDC_PDNControl(KAL_TRUE); return FS_MSDC_READ_SECTOR_ERROR; } MSDC_PDNControl(KAL_FALSE); status = MSP_CMD_ReadWriteData(Sector,Sectors,(kal_uint32*)Buffer,&read,MSP_READ); if(status != MSP_NOERROR) goto err_exit; MSDC_PDNControl(KAL_TRUE); return FS_NO_ERROR; err_exit: if(retry++ <= MAX_TRY && kal_query_systemInit()== KAL_FALSE) { gMSP.is_failed = KAL_TRUE; if(status == MSP_ERR_TIMEOUT || status == MSDC_GPT_TIMEOUT_ERR) gMSDC_Handle->timeout_count++; if(gMSDC_Handle->timeout_count == 3 && gMSDC_Handle->mIsPresent == KAL_TRUE) { kal_print("[MSDC]:re-mount(read fail)"); gMSDC_Handle->mIsInitialized = KAL_FALSE; retry = 0; if(MSP_Initialize() != MSP_NOERROR) return FS_MSDC_READ_SECTOR_ERROR; } //dbg_print("read sector failed! retry: %d \r\n",retry); goto start; } MSDC_PDNControl(KAL_TRUE); return FS_MSDC_READ_SECTOR_ERROR ; }
/* only allow two case: case 1: Sectors == 1 case 2: Sectors == gMS.PagesPerBlk */ static int WriteSectors(void * DriveData, DWORD Sector, UINT Sectors, void * Buffer) { MS_STATUS status; kal_uint8 PagesPerBlk,page,pages,extra[4],owflag,len; kal_uint32 lba,pba,i,spareblk; kal_uint8 *p = NULL,*ptr; kal_uint16 *LPTable,*FreeTable; kal_uint8 retry = 0; gMSDC_Handle->timeout_count = 0; START: if(!gMSDC_Handle->mIsInitialized) { //dbg_print("Write but not Initialized \r\n"); MSDC_PDNControl(KAL_TRUE); return FS_MSDC_WRITE_SECTOR_ERROR; } gMS.is_write = KAL_TRUE; LPTable = gMS.pLPTbl; FreeTable = gMS.pFreeTbl; PagesPerBlk = gMS.PagesPerBlk; ptr = (kal_uint8*)Buffer; p = (kal_uint8 * )MS_buffer; // get physical block address from sector lba = Sector/PagesPerBlk; len = page = Sector%PagesPerBlk; MSDC_PDNControl(KAL_FALSE); while(1) { if(PagesPerBlk - page < Sectors) len = PagesPerBlk - page; else len = Sectors; ASSERT(len >= 1 && len <= 32); status = MS_API_LogToPhy(LPTable,lba,&pba); if(status != MS_NOERROR) goto ERR_EXIT; // set update status to 0 MS_API_ReadExtraData(pba, 0, (kal_uint32 *)extra); owflag = extra[0]; extra[0] &= ~MS_OVFLG_UDST; MS_API_WriteOWF(pba, 0, extra[0]); // read the entire block status = MS_API_ReadBlock(pba,(kal_uint32*)p, (kal_uint32 *)extra, 0, PagesPerBlk, &pages); if(status != MS_NOERROR) { goto ERR_EXIT; } if(gMS.uc_pages != 0) { MS_API_LogToPhy(LPTable,lba,&pba); MS_API_ReadExtraData(pba, 0, (kal_uint32 *)extra); owflag = extra[0]; extra[0] &= ~MS_OVFLG_UDST; status = MS_API_WriteExtraData(pba, 0, (kal_uint32 *)extra); } // update the page in the memory kal_mem_cpy((kal_uint8*)(p+page*MS_PAGE_SIZE), (kal_uint8*)ptr, MS_PAGE_SIZE*len); // find a unused block from FreeTable, erase it and write updated info into it i = 0; while((FreeTable[i++] == 0xFFFF) && (i < MS_FREETABLE_SIZE)); spareblk = FreeTable[i-1]; status = MS_API_EraseBlock(spareblk); if(status != MS_NOERROR) goto ERR_EXIT; extra[0] = (owflag|MS_OVFLG_UDST); status = MS_API_WriteBlock(spareblk, (kal_uint32*)p, (kal_uint32*)extra, 0, PagesPerBlk, &pages); if(status != MS_NOERROR) goto ERR_EXIT; // update the LPTable and FreeTable LPTable[MS_GetLPIndex(lba)] = spareblk; FreeTable[i-1] = pba; // erase original block status = MS_API_EraseBlock(pba); if(status != MS_NOERROR) goto ERR_EXIT; if(gMS.uc_pages || gMS.de_pages) { kal_uint32 pages; if(gMS.uc_pages) pages = gMS.uc_pages; else pages = gMS.de_pages; for(i=0;i<32;i++) { if(pages & (1<<i)) { MS_API_ReadExtraData(spareblk, i, (kal_uint32 *)extra); extra[0] &= ~MS_OVFLG_PGST; MS_API_WriteExtraData(spareblk, i, (kal_uint32 *)extra); } } } MS_API_ReadExtraData(spareblk, 0x18, (kal_uint32 *)extra); Sectors -= len; if(Sectors == 0) break; ptr += MS_PAGE_SIZE*len; page = 0; lba++; } // end of while MSDC_PDNControl(KAL_TRUE); return FS_NO_ERROR; ERR_EXIT: //dbg_print("W: fail %d\r\n",retry); if(retry++ <= MAX_TRY && kal_query_systemInit()== KAL_FALSE) { if(status == MS_ERR_TIMEOUT || status == MSDC_GPT_TIMEOUT_ERR) gMSDC_Handle->timeout_count++; if(gMSDC_Handle->timeout_count == 3 && gMSDC_Handle->mIsPresent == KAL_TRUE) { kal_print("[MSDC]:re-mount(write fail)"); gMSDC_Handle->mIsInitialized = KAL_FALSE; retry = 0; if(MS_Initialize() != NO_ERROR) return FS_MSDC_READ_SECTOR_ERROR; } //dbg_print("W: fail retry:%d adrs:%d sectors: %d \r\n",retry,Sector, Sectors); goto START; } MSDC_PDNControl(KAL_TRUE); return FS_MSDC_WRITE_SECTOR_ERROR; }
/*-----------------------------------*/ static int ReadSectors(void * DriveData, DWORD Sector, UINT Sectors, void * Buffer) { MS_STATUS status; kal_uint8 PagesPerBlk,page,readpage,len,*ptr, extra[4]; kal_uint32 lba,pba; kal_uint8 retry = 0; gMSDC_Handle->timeout_count = 0; START: if(!gMSDC_Handle->mIsInitialized) { //dbg_print("Read but not Initialized \r\n"); MSDC_PDNControl(KAL_TRUE); return FS_MSDC_READ_SECTOR_ERROR; } gMS.is_write = KAL_FALSE; PagesPerBlk = gMS.PagesPerBlk; lba = Sector/PagesPerBlk; page = Sector%PagesPerBlk; ptr = (kal_uint8*) Buffer; MSDC_PDNControl(KAL_FALSE); while(1) { if(PagesPerBlk - page < Sectors) len = PagesPerBlk - page; else len = Sectors; ASSERT(len >= 1 && len <= 32); status = MS_API_LogToPhy(gMS.pLPTbl,lba,&pba); if(status != MS_NOERROR) goto ERR_EXIT;//return FS_MSDC_READ_SECTOR_ERROR; if(len == 1) status = MS_API_ReadSinglePage(pba,page,(kal_uint32*)ptr,NULL); else status = MS_API_ReadBlock(pba, (kal_uint32*)ptr, NULL, page, len, &readpage); if(status != MS_NOERROR) goto ERR_EXIT;//return FS_MSDC_READ_SECTOR_ERROR; //============ change the update status ====================// MS_API_ReadExtraData(pba, 0, (kal_uint32*)extra); if(MS_UPDATE_STATUS(extra[OVERWRITE_FLAG]) == 0) { kal_uint32 i; kal_uint16 *FreeTable, *LPTable, spareblk; kal_uint8 readpage; // find a unused block from FreeTable, erase it and write updated info into it LPTable = gMS.pLPTbl; FreeTable = gMS.pFreeTbl; i = 0; while((FreeTable[i++] == 0xFFFF) && (i < MS_FREETABLE_SIZE)); spareblk = FreeTable[i-1]; MS_API_ReadBlock(pba,(kal_uint32*)MS_buffer, (kal_uint32 *)extra, 0, PagesPerBlk, &readpage); extra[0] |= MS_OVFLG_UDST; MS_API_WriteExtraData(spareblk, 0, (kal_uint32 *)extra); MS_API_WriteBlock(spareblk,(kal_uint32*)MS_buffer, (kal_uint32 *)extra, 0, PagesPerBlk, &readpage); MS_API_EraseBlock(pba); // update the LPTable and FreeTable LPTable[MS_GetLPIndex(lba)] = spareblk; FreeTable[i-1] = pba; } //================================// Sectors -= len; if(Sectors == 0) break; page = 0; ptr += MS_PAGE_SIZE*len; lba++; } MSDC_PDNControl(KAL_TRUE); return FS_NO_ERROR; ERR_EXIT: if(retry++ <= MAX_TRY && kal_query_systemInit()== KAL_FALSE) { if(status == MS_ERR_TIMEOUT || status == MSDC_GPT_TIMEOUT_ERR) gMSDC_Handle->timeout_count++; if(gMSDC_Handle->timeout_count == 3 && gMSDC_Handle->mIsPresent == KAL_TRUE) { kal_print("[MSDC]:re-mount(read fail)"); gMSDC_Handle->mIsInitialized = KAL_FALSE; retry = 0; if(MS_Initialize() != NO_ERROR) return FS_MSDC_READ_SECTOR_ERROR; } //dbg_print("R: fail retry:%d adrs:%d sectors: %d \r\n",retry,Sector, Sectors); goto START; } MSDC_PDNControl(KAL_TRUE); return FS_MSDC_READ_SECTOR_ERROR; }
/*-----------------------------------*/ static int MountDevice(void * DriveData, int DeviceNumber, int DeviceType, DWORD Flags) { kal_uint8 retry = 0; #if defined(__SIM_PLUS__) sd_select_enum sel; if((MSDC_HANDLE *)DriveData == &MSDC_Blk[0]) sel = SD_EXT; else { sel = SD_SIM; } MSDC_Switch_Card(sel); #endif #ifdef DRV_LSD /*notifiedFMT may be modified by FMT and MMI tasks, but it is no need to protect this, FMT can't preempt MMI*/ if(1 == notifiedFMT)/*in this state. we dont allow any access on memory card, we will return fail on any mount trial*/ { return FS_MSDC_MOUNT_ERROR; } #endif if(gMSDC_Handle->mIsInitialized) return SECTOR_SIZE; gMSDC_Handle->is_init_timeout = KAL_FALSE; start: if(!gMSDC_Handle->mIsPresent) { //dbg_print("not present \r\n"); #if defined(_NAND_FLASH_BOOTING_) // add the following code for solving plug in or out the SD card during // NFB loading process. The card detection interruptwill disapperared // while interrupt controller is masked. IRQMask(IRQ_MSDC_CODE); if(*(volatile kal_uint16*)MSDC_PS & MSDC_PS_PIN0) { if(gMSDC_Handle->ins_level == MSDC_IOCTRL_PULL_UP) gMSDC_Handle->mIsPresent = KAL_FALSE; else gMSDC_Handle->mIsPresent = KAL_TRUE; } else { if(gMSDC_Handle->ins_level == MSDC_IOCTRL_PULL_UP) gMSDC_Handle->mIsPresent = KAL_TRUE; else gMSDC_Handle->mIsPresent = KAL_FALSE; } IRQUnmask(IRQ_MSDC_CODE); #endif // _NAND_FLASH_BOOTING_ if(!gMSDC_Handle->mIsPresent) { MSDC_PDNControl(KAL_TRUE); return FS_MSDC_MOUNT_ERROR; } } MSDC_PDNControl(KAL_FALSE); if(SD_Initialize() != NO_ERROR) { goto err_exit; } //if(SD_MountDevice(DeviceType) != FS_NO_ERROR) //return FS_MSDC_MOUNT_ERROR; //dbg_print("Mount success! \r\n"); #ifdef MSDC_SDMMC_NAND /*for SDMMC NAND, some manufacturs sale NAND with all sectors zero, we should format it first*/ if(ReadSectors( DriveData, 0, 1, MSDC_Sector) != NO_ERROR) goto err_exit; if(0x55aa != (MSDC_Sector[128] & 0xffff0000)) { /*it doesn't have correct MBR*/ SD_SelfFormat(); } else { if(ReadSectors( DriveData, 1, 1, MSDC_Sector) != NO_ERROR) goto err_exit; if(0x55aa != (MSDC_Sector[128] & 0xffff0000)) { /*it doesn't have correct PBR*/ SD_SelfFormat(); } } #endif MSDC_PDNControl(KAL_TRUE); #ifdef DRV_LSD if(KAL_TRUE == kal_query_systemInit()) { /*we don't let access memory card before FMT get plug in message*/ /*there is no task can access when system init*/ notifiedFMT = 1; return FS_MSDC_MOUNT_ERROR; } #endif return SECTOR_SIZE; err_exit: if(retry++ <= SD_MAX_RETRY && gMSDC_Handle->is_init_timeout == KAL_FALSE) { //dbg_print("SD MountDevice failed! retry: %d \r\n",retry); goto start; } #if defined(__MSDC_NOT_SUPPORT_HOT_PLUG__) gMSDC_Handle->mIsPresent = KAL_FALSE; #endif #if defined(__SIM_PLUS__) if(INT_USBBoot() == KAL_TRUE && current_card == SD_SIM) { gMSDC_Handle->mIsPresent = KAL_FALSE; } #endif MSDC_PDNControl(KAL_TRUE); return FS_MSDC_MOUNT_ERROR; }
/*-----------------------------------*/ static int WriteSectors(void * DriveData, DWORD Sector, UINT Sectors, void * Buffer) { SDC_CMD_STATUS status; kal_uint8 retry = 0; kal_uint32 adrs; #if defined(__SIM_PLUS__) sd_select_enum sel; if((MSDC_HANDLE *)DriveData == &MSDC_Blk[0]) sel = SD_EXT; else sel = SD_SIM; MSDC_Switch_Card(sel); #endif #if defined(SD_MMC_HIGH_DENSITY_SUPPORT) if(gSD->flags & SD_FLAG_HCS_SUPPORT) adrs = Sector; else #endif adrs = Sector * SECTOR_SIZE; gMSDC_Handle->timeout_count = 0; start: if(!gMSDC_Handle->mIsInitialized) { //dbg_print("Write but not Initialized \r\n"); MSDC_PDNControl(KAL_TRUE); return FS_MSDC_WRITE_SECTOR_ERROR; } retry++; MSDC_PDNControl(KAL_FALSE); #ifndef LSD_SINGLE_WRITE if(Sectors > 1) { if(gMSDC_Handle->mMSDC_type == SD_CARD) SD_SetPreEraseBlk(Sectors); status = SD_WriteMultiBlock((kal_uint32)adrs,(kal_uint32*)Buffer,(kal_uint32)Sectors); } else status = SD_WriteSingleBlock((kal_uint32)adrs,(kal_uint32*)Buffer); #else while(Sectors) { status = SD_WriteSingleBlock((kal_uint32)adrs,(kal_uint32*)Buffer); if(status != NO_ERROR ) break; (kal_uint8 *)Buffer += SECTOR_SIZE; Sector ++; #if defined(SD_MMC_HIGH_DENSITY_SUPPORT) if(gSD->flags & SD_FLAG_HCS_SUPPORT) adrs = Sector; else #endif adrs = Sector * SECTOR_SIZE; Sectors--; } #endif if(status != NO_ERROR) { sd_w++; if(kal_query_systemInit()== KAL_TRUE) { MSDC_PDNControl(KAL_TRUE); return FS_MSDC_WRITE_SECTOR_ERROR; } //dbg_print("write retry:%d,status:%d,total %d\r\n",retry,status,sd_w); if(status == ERR_CMD_TIMEOUT || status == MSDC_GPT_TIMEOUT_ERR) gMSDC_Handle->timeout_count++; if(gMSDC_Handle->timeout_count++ == 3 && gMSDC_Handle->mIsPresent == KAL_TRUE) { kal_print("[MSDC]:SD re-mount (write fail)"); gMSDC_Handle->mIsInitialized = KAL_FALSE; retry = 0; if(SD_Initialize() != NO_ERROR) { MSDC_PDNControl(KAL_TRUE); return FS_MSDC_WRITE_SECTOR_ERROR; } } if(retry >= SD_MAX_RETRY) { MSDC_PDNControl(KAL_TRUE); return FS_MSDC_WRITE_SECTOR_ERROR; } else { // kal_prompt_trace(MOD_AUD,"CRC write Error retry %d",retry); goto start; } } MSDC_PDNControl(KAL_TRUE); return FS_NO_ERROR; }