/*! * * \par Description: * This function copy valuable data from log block or dat block to free block, change free to data ,change * data and log to free. * * \param [in] LogNum,serial number within log block space * \return sucess or failed. * \note this function was called when log block is not suit for swap or move. **/ __s32 _free2data_simple_merge(__u32 nlogical) { __u8 InData; __u16 SuperPage; __u16 SrcPage,DstPage; __u32 SrcBlk,DstBlk; struct __SuperPhyBlkType_t DataBlk; struct __SuperPhyBlkType_t FreeBlk; struct __LogBlkType_t LogBlk; struct __PhysicOpPara_t SrcParam,DstParam; /*init block info*/ BMM_GetDataBlk(nlogical,&DataBlk); BMM_GetLogBlk(nlogical,&LogBlk); if (NAND_OP_TRUE != BMM_GetFreeBlk(LOWEST_EC_TYPE, &FreeBlk)) return NAND_OP_FALSE; /*copy data from data block or log block to free block*/ if((SUPPORT_LOG_BLOCK_MANAGE)&&(LogBlk.LogBlkType == LSB_TYPE)) { //DBUG_INF("[DBUG] nand lsb type simple merge block %x\n", nlogical); for (SuperPage = 0; SuperPage < PAGE_CNT_OF_LOGIC_BLK; SuperPage++) { /*set source address and destination address*/ DstPage = SuperPage; DstBlk = FreeBlk.PhyBlkNum; SrcPage = PMM_GetCurMapPage(SuperPage); InData = (SrcPage == 0xffff)?1 : 0; if(InData) { SrcBlk = DataBlk.PhyBlkNum; } else { if(SrcPage&(0x1<<15)) SrcBlk = LogBlk.PhyBlk1.PhyBlkNum; else SrcBlk = LogBlk.PhyBlk.PhyBlkNum; } SrcPage = InData?SuperPage:(SrcPage&0x7fff); LML_CalculatePhyOpPar(&SrcParam, CUR_MAP_ZONE,SrcBlk, SrcPage); LML_CalculatePhyOpPar(&DstParam, CUR_MAP_ZONE,DstBlk, DstPage); if (DstPage == 0) { __u8 SeqPlus; //SeqPlus = InData?1:0; SeqPlus = InData?2:1; if(NAND_OP_FALSE == _copy_page0(SrcBlk, SrcPage, DstBlk,SeqPlus)) { LOGICCTL_ERR("simple_merge : copy page 0 err\n"); return NAND_OP_FALSE; } } else { if(NAND_OP_TRUE != PHY_PageCopyback(&SrcParam,&DstParam)) { LOGICCTL_ERR("simple merge : copy back err\n"); return NAND_OP_FALSE; } } if(NAND_OP_TRUE != PHY_SynchBank(DstParam.BankNum, SYNC_BANK_MODE)) { struct __SuperPhyBlkType_t SubBlk; if(NAND_OP_TRUE != LML_BadBlkManage(&FreeBlk,CUR_MAP_ZONE,DstPage, &SubBlk)) { LOGICCTL_ERR("simgple merge : bad block manage err after copy back\n"); return NAND_OP_FALSE; } FreeBlk = SubBlk; SuperPage -= 1; } } /*move free block to data block*/ BMM_SetDataBlk(nlogical, &FreeBlk); /*move erased data block to free block*/ if ( NAND_OP_TRUE != LML_VirtualBlkErase(CUR_MAP_ZONE, DataBlk.PhyBlkNum)){ if (NAND_OP_TRUE != LML_BadBlkManage(&DataBlk,CUR_MAP_ZONE,0,NULL)){ LOGICCTL_ERR("swap merge : bad block manage err erase data block\n"); return NAND_OP_FALSE; } } /*move erased data block to free block*/ if (DataBlk.BlkEraseCnt < 0xffff) DataBlk.BlkEraseCnt ++; BMM_SetFreeBlk(&DataBlk); //DBUG_INF("[DBUG] logic %x simple merge: erase data block: %x\n", LogBlk.LogicBlkNum, DataBlk.PhyBlkNum); /*move erased log block to free block*/ if ( NAND_OP_TRUE != LML_VirtualBlkErase(CUR_MAP_ZONE, LogBlk.PhyBlk.PhyBlkNum)){ if (NAND_OP_TRUE != LML_BadBlkManage(&LogBlk.PhyBlk,CUR_MAP_ZONE,0,NULL)){ LOGICCTL_ERR("simple merge : bad block manage err after erase log block\n"); return NAND_OP_FALSE; } } if (LogBlk.PhyBlk.BlkEraseCnt < 0xffff) LogBlk.PhyBlk.BlkEraseCnt ++; BMM_SetFreeBlk(&LogBlk.PhyBlk); //DBUG_INF("[DBUG] logic %x simple merge: erase log block 0: %x\n", LogBlk.LogicBlkNum, LogBlk.PhyBlk.PhyBlkNum); /*move erased log block to free block*/ if ( NAND_OP_TRUE != LML_VirtualBlkErase(CUR_MAP_ZONE, LogBlk.PhyBlk1.PhyBlkNum)){ if (NAND_OP_TRUE != LML_BadBlkManage(&LogBlk.PhyBlk1,CUR_MAP_ZONE,0,NULL)){ LOGICCTL_ERR("simple merge : bad block manage err after erase log block\n"); return NAND_OP_FALSE; } } if (LogBlk.PhyBlk1.BlkEraseCnt < 0xffff) LogBlk.PhyBlk1.BlkEraseCnt ++; BMM_SetFreeBlk(&LogBlk.PhyBlk1); //DBUG_INF("[DBUG] logic %x simple merge: erase log block 1: %x\n", LogBlk.LogicBlkNum, LogBlk.PhyBlk1.PhyBlkNum); MEMSET(&LogBlk, 0xff, sizeof(struct __LogBlkType_t)); LogBlk.LogBlkType = 0; LogBlk.WriteBlkIndex = 0; LogBlk.ReadBlkIndex = 0; BMM_SetLogBlk(nlogical, &LogBlk); /*clear page map table*/ PMM_ClearCurMapTbl(); } else { for (SuperPage = 0; SuperPage < PAGE_CNT_OF_LOGIC_BLK; SuperPage++) { /*set source address and destination address*/ DstPage = SuperPage; DstBlk = FreeBlk.PhyBlkNum; SrcPage = PMM_GetCurMapPage(SuperPage); InData = (SrcPage == 0xffff)?1 : 0; SrcBlk = InData?DataBlk.PhyBlkNum : LogBlk.PhyBlk.PhyBlkNum; SrcPage = InData?SuperPage:SrcPage; LML_CalculatePhyOpPar(&SrcParam, CUR_MAP_ZONE,SrcBlk, SrcPage); LML_CalculatePhyOpPar(&DstParam, CUR_MAP_ZONE,DstBlk, DstPage); if (DstPage == 0) { __u8 SeqPlus; //SeqPlus = InData?1:0; SeqPlus = InData?2:1; if(NAND_OP_FALSE == _copy_page0(SrcBlk, SrcPage, DstBlk,SeqPlus)) { LOGICCTL_ERR("simple_merge : copy page 0 err\n"); return NAND_OP_FALSE; } } else { if(NAND_OP_TRUE != PHY_PageCopyback(&SrcParam,&DstParam)) { LOGICCTL_ERR("simple merge : copy back err\n"); return NAND_OP_FALSE; } } if(NAND_OP_TRUE != PHY_SynchBank(DstParam.BankNum, SYNC_BANK_MODE)) { struct __SuperPhyBlkType_t SubBlk; if(NAND_OP_TRUE != LML_BadBlkManage(&FreeBlk,CUR_MAP_ZONE,DstPage, &SubBlk)) { LOGICCTL_ERR("simgple merge : bad block manage err after copy back\n"); return NAND_OP_FALSE; } FreeBlk = SubBlk; SuperPage -= 1; } } /*move free block to data block*/ BMM_SetDataBlk(nlogical, &FreeBlk); /*move erased data block to free block*/ if ( NAND_OP_TRUE != LML_VirtualBlkErase(CUR_MAP_ZONE, DataBlk.PhyBlkNum)){ if (NAND_OP_TRUE != LML_BadBlkManage(&DataBlk,CUR_MAP_ZONE,0,NULL)){ LOGICCTL_ERR("swap merge : bad block manage err erase data block\n"); return NAND_OP_FALSE; } } /*move erased data block to free block*/ if (DataBlk.BlkEraseCnt < 0xffff) DataBlk.BlkEraseCnt ++; BMM_SetFreeBlk(&DataBlk); /*move erased log block to free block*/ if ( NAND_OP_TRUE != LML_VirtualBlkErase(CUR_MAP_ZONE, LogBlk.PhyBlk.PhyBlkNum)){ if (NAND_OP_TRUE != LML_BadBlkManage(&LogBlk.PhyBlk,CUR_MAP_ZONE,0,NULL)){ LOGICCTL_ERR("move merge : bad block manage err after erase log block\n"); return NAND_OP_FALSE; } } if (LogBlk.PhyBlk.BlkEraseCnt < 0xffff) LogBlk.PhyBlk.BlkEraseCnt ++; BMM_SetFreeBlk(&LogBlk.PhyBlk); MEMSET(&LogBlk, 0xff, sizeof(struct __LogBlkType_t)); LogBlk.LogBlkType = 0; LogBlk.WriteBlkIndex = 0; LogBlk.ReadBlkIndex = 0; BMM_SetLogBlk(nlogical, &LogBlk); /*clear page map table*/ PMM_ClearCurMapTbl(); } return NAND_OP_TRUE; }