Exemple #1
0
/*
************************************************************************************************************************
*                       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;
}