예제 #1
0
/*
************************************************************************************************************************
*                   SET LOG BLOCK PARAMETER IN THE LOG BLOCK TABLE
*
*Description: Set the parameter for log block in the log block table.
*
*Arguments  : nLogicBlk     the logical block number which the log block is belonged to;
*             pLogBlk       the pointer to log block parameter which need be set to log block table.
*
*Return     : set log block result;
*               = 0     set log block successful;
*               < 0     set log block failed.
************************************************************************************************************************
*/
__s32 BMM_SetLogBlk(__u32 nLogicBlk, struct __LogBlkType_t *pLogBlk)
{
    __s32   tmpLogPst;

    tmpLogPst = _GetLogBlkPst(nLogicBlk);
    if(tmpLogPst < 0)
    {
        tmpLogPst = _GetLogBlkPst(0xffff);
        if(tmpLogPst < 0)
        {
            MAPPING_ERR("[MAPPING_ERR] Set log block table item failed!\n");

            return -1;
        }
    }

    //set the log block item in the log block table
    LOG_BLK_TBL[tmpLogPst] = *pLogBlk;

    return 0;
}
예제 #2
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;
}
예제 #3
0
/*
************************************************************************************************************************
*                       GET LOG PAGE FOR WRITE
*
*Description: Get a log page for write.
*
*Arguments  : nBlk      the logical block number of the log block;
*             nPage     the number of the logical page, which page need log page;
*             pLogPage  the pointer to the log page number, for return value;
*             pLogPst   the pointer to the position of the log block in the log block table.
*
*Return     : get log page result.
*               = 0     get log page for write successful;
*               =-1     get log page for write failed.
************************************************************************************************************************
*/
static __s32 _GetLogPageForWrite(__u32 nBlk, __u32 nPage, __u16 *pLogPage, __u32 *pLogPst)
{
    __s32   result, tmpLogPst;
    __u16   tmpPage, tempBank;
    struct __PhysicOpPara_t tmpPhyPage;
    struct __NandUserData_t tmpSpare[2];

    tmpLogPst = _GetLogBlkPst(nBlk);
    if(tmpLogPst < 0)
    {
        //get log block position failed, there is no such log block, need create a new one
        result = _CreateNewLogBlk(nBlk, (__u32 *)&tmpLogPst);
        if(result < 0)
        {
            MAPPING_ERR("[MAPPING_ERR] Create new log block failed!\n");
            return -1;
        }
    }

    //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 -1;
    }

    //need get log page by write mode,
    tmpPage = LOG_BLK_TBL[tmpLogPst].LastUsedPage;

	if(SUPPORT_ALIGN_NAND_BNK)
    {
        if(tmpPage == 0xffff)
        {
            //the log block is empty, need get log page in the first page line
            tmpPage = nPage % INTERLEAVE_BANK_CNT;
        }
        else
        {
            //need bank align, the log page and the data page should be in the same bank
            if((nPage % INTERLEAVE_BANK_CNT) > (tmpPage % INTERLEAVE_BANK_CNT))
            {
                //get the log page in the same page line with last used page
                tmpPage = tmpPage + ((nPage % INTERLEAVE_BANK_CNT) - (tmpPage % INTERLEAVE_BANK_CNT));
            }
            else
            {
                //need get the log page in the next page line of the last used page
                tmpPage = tmpPage + (nPage % INTERLEAVE_BANK_CNT) + (INTERLEAVE_BANK_CNT - (tmpPage % INTERLEAVE_BANK_CNT));
            }
        }
    }
    else
    {

        //use the page which is the next of the last used page
        tmpPage = tmpPage + 1;
    }

	if((SUPPORT_LOG_BLOCK_MANAGE)&&(LOG_BLK_TBL[tmpLogPst].LogBlkType == LSB_TYPE))
	{
		DBUG_MSG("[DBUG_MSG] _GetLogPageForWrite, select bak log block\n");

		if(SUPPORT_ALIGN_NAND_BNK)
		{
			tempBank = tmpPage%INTERLEAVE_BANK_CNT;
			tmpPage =PMM_CalNextLogPage(tmpPage);
			while(tmpPage%INTERLEAVE_BANK_CNT != tempBank)
			{
				tmpPage++;
				tmpPage =PMM_CalNextLogPage(tmpPage);
				if(tmpPage>=PAGE_CNT_OF_SUPER_BLK)
					break;
			}
		}
		else
		{
			tmpPage =PMM_CalNextLogPage(tmpPage);
		}

		if((tmpPage >= PAGE_CNT_OF_SUPER_BLK)&&(LOG_BLK_TBL[tmpLogPst].WriteBlkIndex == 0))
		{
			LOG_BLK_TBL[tmpLogPst].WriteBlkIndex = 1;
			tmpPage = tmpPage - PAGE_CNT_OF_SUPER_BLK;
		}
		if(LOG_BLK_TBL[tmpLogPst].WriteBlkIndex == 1)
			DBUG_MSG("[DBUG_MSG] _GetLogPageForWrite, log block index: %x, log block num: %x, page: %x \n", LOG_BLK_TBL[tmpLogPst].WriteBlkIndex, LOG_BLK_TBL[tmpLogPst].PhyBlk1.PhyBlkNum, tmpPage);
		else
			DBUG_MSG("[DBUG_MSG] _GetLogPageForWrite, log block index: %x, log block num: %x, page: %x \n", LOG_BLK_TBL[tmpLogPst].WriteBlkIndex, LOG_BLK_TBL[tmpLogPst].PhyBlk.PhyBlkNum, tmpPage);
	}

__CHECK_WRITE_LOGICAL_INFO_OF_LOG_BLOCK:
    //check if need write the logical information in the first page of the log block
    if((LOG_BLK_TBL[tmpLogPst].LastUsedPage == 0xffff) && (tmpPage != 0))
    {
        //get logical information from the data block
        LML_CalculatePhyOpPar(&tmpPhyPage, CUR_MAP_ZONE, DATA_BLK_TBL[nBlk].PhyBlkNum, 0);
        tmpPhyPage.SectBitmap = 0x03;
        tmpPhyPage.MDataPtr = LML_TEMP_BUF;
        tmpPhyPage.SDataPtr = (void *)tmpSpare;
        LML_VirtualPageRead(&tmpPhyPage);

		//if((SUPPORT_LOG_BLOCK_MANAGE)&&(LOG_BLK_TBL[tmpLogPst].LogBlkType == LSB_TYPE))
		//{
		//	PRINT("_GetLogPageForWrite log %x page 0, data age: %x, log age: %x\n", LOG_BLK_TBL[tmpLogPst].WriteBlkIndex, tmpSpare[0].PageStatus, tmpSpare[0].PageStatus+1);
		//}

        tmpSpare[0].BadBlkFlag = 0xff;
        tmpSpare[1].BadBlkFlag = 0xff;
        tmpSpare[0].LogicInfo = ((CUR_MAP_ZONE % ZONE_CNT_OF_DIE)<<10) | nBlk;
        tmpSpare[1].LogicInfo = ((CUR_MAP_ZONE % ZONE_CNT_OF_DIE)<<10) | nBlk;
        tmpSpare[0].LogicPageNum = 0xffff;
        tmpSpare[1].LogicPageNum = 0xffff;
        tmpSpare[0].PageStatus =  tmpSpare[0].PageStatus + 1;
        tmpSpare[1].PageStatus = tmpSpare[0].PageStatus;
		if((SUPPORT_LOG_BLOCK_MANAGE)&&(LOG_BLK_TBL[tmpLogPst].LogBlkType == LSB_TYPE))
		{
			tmpSpare[0].LogType = LSB_TYPE|(LOG_BLK_TBL[tmpLogPst].WriteBlkIndex<<4);
			tmpSpare[1].LogType = LSB_TYPE|(LOG_BLK_TBL[tmpLogPst].WriteBlkIndex<<4);
		}
		else
		{
			tmpSpare[0].LogType = 0xff;
			tmpSpare[1].LogType = 0xff;
		}

       //write the logical information to the spare area of the data block
       	if((SUPPORT_LOG_BLOCK_MANAGE)&&(LOG_BLK_TBL[tmpLogPst].LogBlkType == LSB_TYPE))
       	{
       		DBUG_MSG("[DBUG] _GetLogPageForWrite, write the logical information to log page 0, writeblkindex: %x\n", LOG_BLK_TBL[tmpLogPst].WriteBlkIndex);
       		LML_CalculatePhyOpPar(&tmpPhyPage, CUR_MAP_ZONE, LOG_BLK_TBL[tmpLogPst].PhyBlk.PhyBlkNum, 0);
       	}
		else
        	LML_CalculatePhyOpPar(&tmpPhyPage, CUR_MAP_ZONE, LOG_BLK_TBL[tmpLogPst].PhyBlk.PhyBlkNum, 0);

		tmpPhyPage.SectBitmap = FULL_BITMAP_OF_SUPER_PAGE;
        result = LML_VirtualPageWrite(&tmpPhyPage);
        if(result < 0)
        {
            LOGICCTL_ERR("[MAPPING_ERR] Physical write module failed when write logical information, Err:0x%x!\n", result);
            return -1;
        }

        result = PHY_SynchBank(tmpPhyPage.BankNum, SYNC_CHIP_MODE);
        if(result < 0)
        {
            //the last write operation on current bank is failed, the block is bad, need proccess it
            LOGICCTL_DBG("[LOGICCTL_DBG] Find a bad block when write logical page! bank:0x%x, block:0x%x, page:0x%x\n",
                    tmpPhyPage.BankNum, tmpPhyPage.BlkNum, tmpPhyPage.PageNum);

            //process the bad block
            result = LML_BadBlkManage(&LOG_BLK_TBL[tmpLogPst].PhyBlk, CUR_MAP_ZONE, 0, &LOG_BLK_TBL[tmpLogPst].PhyBlk);
            if(result < 0)
            {
                LOGICCTL_ERR("[MAPPING_ERR] Bad block process failed when get log page for write, Err:0x%x!\n", result);
                return -1;
            }

           goto __CHECK_WRITE_LOGICAL_INFO_OF_LOG_BLOCK;
        }
    }

    //set the log page number for return
    *pLogPage = tmpPage;
    *pLogPst = tmpLogPst;

    return 0;
}
예제 #4
0
/*
************************************************************************************************************************
*                       GET PARAMETER OF LOG BLOCK
*
*Description: Get parameter of log block.
*
*Arguments  : nLogicBlk     the logical block number which the log block is belonged to;
*             pLogBlk       the pointer to the log block item for return;
*
*Return     : get log block result;
*               = 0     get log block successful;
*               =-1     get log block failed.
*
*Note       : Scan the log block table which is accessing in the buffer currently,
*             to look for the log block, if the log block is exsit, return 0,
*             else, return -1
************************************************************************************************************************
*/
__s32 BMM_GetLogBlk(__u32 nLogicBlk, struct __LogBlkType_t *pLogBlk)
{
    __s32   tmpLogPst, result;
	struct __SuperPhyBlkType_t tmpFreeBlk1;
	__u32   LogBlkType;

    tmpLogPst = _GetLogBlkPst(nLogicBlk);

    if(tmpLogPst < 0)
    {
        //if the logic block number is invalid, report error
        if(nLogicBlk > DATA_BLK_CNT_OF_ZONE)
        {
            MAPPING_ERR("[MAPPING_ERR] Logical block number(0x%x) is invalid when get log block!\n", nLogicBlk);
        }

        if(pLogBlk != NULL)
        {
            pLogBlk->LogicBlkNum = 0xffff;
            pLogBlk->LastUsedPage = 0xffff;
			pLogBlk->LogBlkType = 0;
			pLogBlk->ReadBlkIndex = 0;
			pLogBlk->WriteBlkIndex = 0;
            pLogBlk->PhyBlk.PhyBlkNum = 0xffff;
            pLogBlk->PhyBlk.BlkEraseCnt = 0xffff;
			pLogBlk->PhyBlk1.PhyBlkNum = 0xffff;
            pLogBlk->PhyBlk1.BlkEraseCnt = 0xffff;
			pLogBlk->PhyBlk2.PhyBlkNum = 0xffff;
            pLogBlk->PhyBlk2.BlkEraseCnt = 0xffff;
        }

        return -1;
    }
    else
    {
        if(pLogBlk != NULL)
        {

			if(SUPPORT_LOG_BLOCK_MANAGE)
			{
				LogBlkType = BMM_CalLogBlkType(nLogicBlk);
				if(LOG_BLK_TBL[tmpLogPst].LogBlkType == 0xffff)
				{
					PRINT("[DBUG] find a log table item with valid log block type!\n");
					LOG_BLK_TBL[tmpLogPst].LogBlkType = 0;
					LOG_BLK_TBL[tmpLogPst].WriteBlkIndex = 0;
					LOG_BLK_TBL[tmpLogPst].ReadBlkIndex = 0;
				}

	        	//check log type for debug
				if(LOG_BLK_TBL[tmpLogPst].LogBlkType != LogBlkType)
				{
					PRINT("[DBUG] LogBlkTye mismatch: 0x%x, 0x%x\n",LOG_BLK_TBL[tmpLogPst].LogBlkType, LogBlkType);
					if((LOG_BLK_TBL[tmpLogPst].LogBlkType == NORMAL_TYPE)&&(LogBlkType == LSB_TYPE))
					{
						//get a free block to create a new log block
					    result = BMM_GetFreeBlk(LOWEST_EC_TYPE, &tmpFreeBlk1);
					    if(result < 0)
					    {
					        MAPPING_ERR("[MAPPING_ERR] Get free block failed when create new log block!\n");
					        return -1;
					    }

					    //make a new log item in the log block table
						LOG_BLK_TBL[tmpLogPst].LogBlkType = LogBlkType;
						LOG_BLK_TBL[tmpLogPst].WriteBlkIndex = 0;
						LOG_BLK_TBL[tmpLogPst].ReadBlkIndex = 0;
						LOG_BLK_TBL[tmpLogPst].PhyBlk1.PhyBlkNum = tmpFreeBlk1.PhyBlkNum;
						LOG_BLK_TBL[tmpLogPst].PhyBlk1.BlkEraseCnt = tmpFreeBlk1.BlkEraseCnt;

						*pLogBlk = LOG_BLK_TBL[tmpLogPst];

					}

				}
				else
				{
                	*pLogBlk = LOG_BLK_TBL[tmpLogPst];
				}
			}
			else
			{
            	*pLogBlk = LOG_BLK_TBL[tmpLogPst];
			}
        }
    }

    return 0;
}