/* ************************************************************************************************************************ * GET LOG PAGE PARAMETER * *Description: Get a page from log block for read or write. * *Arguments : nBlk the logical block number of the log block; * nPage the number of the logical page, which page need log page; * nMode the type of get log page, 'r' or 'w', others is invalid. * *Return : the number of the log page; * != 0xffff get log page successful, return page number; * = 0xffff get log page failed. * *Note : Scan the log block table to try to get the log block. * when the get type is 'r', if the log block is exsit and the logical * page contain a log page, return the number of the log page, else, * return 0xffff; * when the get type is 'w', if the log block is not exsit, need create * log block, then, if get log page failed, need merge the log block, and * try to get log page again, this mode should return a value page number * except there is no enough valid blocks. ************************************************************************************************************************ */ __u32 PMM_GetLogPage(__u32 nBlk, __u32 nPage, __u8 nMode) { __s32 result, tmpLogPst; __u16 tmpPage, PhyPageNum; if(nMode == 'r') { tmpLogPst = _GetLogBlkPst(nBlk); if(tmpLogPst < 0) { //get log page by read mode, there is no log block, return invalid value return INVALID_PAGE_NUM; } //need swap the page mapping table to ram which is accessing currently result = PMM_SwitchMapTbl(tmpLogPst); if(result < 0) { MAPPING_ERR("[MAPPING_ERR] Switch page mapping table failed when get log page! Err:0x%x\n", result); return INVALID_PAGE_NUM; } _CalLogAccessCnt(tmpLogPst); //get active read log block index if((SUPPORT_LOG_BLOCK_MANAGE)&&(LOG_BLK_TBL[tmpLogPst].LogBlkType == LSB_TYPE)) { PhyPageNum = PAGE_MAP_TBL[nPage].PhyPageNum; if((PhyPageNum&(0x1<<15))&&(PhyPageNum!= 0xffff)) { LOG_BLK_TBL[tmpLogPst].ReadBlkIndex = 1; PhyPageNum &= 0x7fff; } else LOG_BLK_TBL[tmpLogPst].ReadBlkIndex = 0; return (PhyPageNum|LOG_BLK_TBL[tmpLogPst].ReadBlkIndex<<16); } else { LOG_BLK_TBL[tmpLogPst].ReadBlkIndex = 0; return PAGE_MAP_TBL[nPage].PhyPageNum; } } result = _GetLogPageForWrite(nBlk, nPage, &tmpPage, (__u32 *)&tmpLogPst); if(result < 0) { //get log page for write failed MAPPING_ERR("[MAPPING_ERR] Get log page for write failed!\n"); return INVALID_PAGE_NUM; } //check if the log page is valid if(!(tmpPage < PAGE_CNT_OF_SUPER_BLK)) { //the log page is not invalid, need to merge the log block, and get again result = LML_MergeLogBlk(SPECIAL_MERGE_MODE, nBlk); if(result < 0) { //merge log block failed, report error MAPPING_ERR("[MAPPING_ERR] Merge log block failed when get log page! Err:0x%x\n", result); return INVALID_PAGE_NUM; } //try to get log page for write again result = _GetLogPageForWrite(nBlk, nPage, &tmpPage, (__u32 *)&tmpLogPst); if(result < 0) { //get log page for write failed MAPPING_ERR("[MAPPING_ERR] Get log page for write failed!\n"); return INVALID_PAGE_NUM; } } //check if the log page is valid if(!(tmpPage < PAGE_CNT_OF_SUPER_BLK)) { //get log page for write failed MAPPING_ERR("[MAPPING_ERR] Get log page for write failed!\n"); return INVALID_PAGE_NUM; } else { LOG_BLK_TBL[tmpLogPst].LastUsedPage = tmpPage; } //update the page mapping table item if((SUPPORT_LOG_BLOCK_MANAGE)&&(LOG_BLK_TBL[tmpLogPst].LogBlkType == LSB_TYPE)) { DBUG_MSG("[DBUG_MSG] PMM_GetLogPage 2, select bak log block\n"); PAGE_MAP_TBL[nPage].PhyPageNum = tmpPage|((LOG_BLK_TBL[tmpLogPst].WriteBlkIndex&0x1)<<15); } else PAGE_MAP_TBL[nPage].PhyPageNum = tmpPage; //set the flag that mark need update the page mapping table PAGE_MAP_CACHE->DirtyFlag = 1; _CalLogAccessCnt(tmpLogPst); if((SUPPORT_LOG_BLOCK_MANAGE)&&(LOG_BLK_TBL[tmpLogPst].LogBlkType == LSB_TYPE)) return (tmpPage|LOG_BLK_TBL[tmpLogPst].WriteBlkIndex<<16); else return tmpPage; }