⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fmd.cpp

📁 S3C2443 WINCE6.0 BSP
💻 CPP
📖 第 1 页 / 共 4 页
字号:
    //  OK, instead of reading it from the chip, we use the hardcoded
    //  numbers here.

	pFlashInfo->dwNumBlocks			= wNUM_BLOCKS;
	pFlashInfo->wSectorsPerBlock	= NAND_PAGE_CNT;
	pFlashInfo->wDataBytesPerSector = NAND_PAGE_SIZE;
	pFlashInfo->dwBytesPerBlock     = (pFlashInfo->wSectorsPerBlock * pFlashInfo->wDataBytesPerSector);

	RETAILMSG(1, (TEXT("NUMBLOCKS : %d(0x%x), SECTORSPERBLOCK = %d(0x%x), BYTESPERSECTOR = %d(0x%x) \r\n"), pFlashInfo->dwNumBlocks, pFlashInfo->dwNumBlocks, pFlashInfo->wSectorsPerBlock, pFlashInfo->wSectorsPerBlock, pFlashInfo->wDataBytesPerSector, pFlashInfo->wDataBytesPerSector));

	//SetKMode(bLastMode);
    return TRUE;



}

#define VALIDADDR	0x05	// S3C2443NAND

static BOOL IsBlockBad(BLOCK_ID blockID)
{
	BOOL bRet = FALSE;
	int i;

	if ( blockID < wPRIMARY_NAND_BLOCKS )
	{
		if ( astNandSpec[dwPrimaryNandDevice].nSctsPerPg == 4 )
		{
			for ( i = 0; i < LB_BLOCK_LOOP; i++ )
			{
				bRet = LB_IsBlockBad(blockID*(LB_BLOCK_LOOP) + i, USE_NFCE);
				if ( bRet == TRUE ) break;
			}
		}
		else
		{
			for ( i = 0; i < SB_BLOCK_LOOP; i++ )
			{
				bRet = SB_IsBlockBad(blockID*(SB_BLOCK_LOOP) + i, USE_NFCE);
				if ( bRet == TRUE ) break;
			}
		}
	}
	else
	{
		if ( astNandSpec[dwSecondaryNandDevice].nSctsPerPg == 4 )
		{
			for ( i = 0; i < LB_BLOCK_LOOP; i++ )
			{
				bRet = LB_IsBlockBad((blockID-wPRIMARY_NAND_BLOCKS)*(LB_BLOCK_LOOP) + i, USE_GPIO);
				if ( bRet == TRUE ) break;
			}
		}
		else
		{
			for ( i = 0; i < SB_BLOCK_LOOP; i++ )
			{
				bRet = SB_IsBlockBad((blockID-wPRIMARY_NAND_BLOCKS)*(SB_BLOCK_LOOP) + i, USE_GPIO);
				if ( bRet == TRUE ) break;
			}
		}
	}

	return bRet;
}


/*
	@func   DWORD | FMD_GetBlockStatus | Returns the status of the specified block.
	@rdesc  Block status (see fmd.h).
	@comm	
	@xref   
*/
DWORD FMD_GetBlockStatus(BLOCK_ID blockID)
{
    DWORD dwResult = 0;
	int i;


	if ( blockID < wPRIMARY_NAND_BLOCKS )
	{
		if ( astNandSpec[dwPrimaryNandDevice].nSctsPerPg == 4 )
		{
			for ( i = 0; i < LB_BLOCK_LOOP; i++ )
			{
				dwResult |= FMD_LB_GetBlockStatus(blockID*(LB_BLOCK_LOOP) + i, USE_NFCE);
			}
		}
		else
		{
			for ( i = 0; i < SB_BLOCK_LOOP; i++ )
			{
				dwResult |= FMD_SB_GetBlockStatus(blockID*(SB_BLOCK_LOOP) + i, USE_NFCE);
			}
		}
	}
	else
	{
		if ( astNandSpec[dwSecondaryNandDevice].nSctsPerPg == 4 )
		{
			for ( i = 0; i < LB_BLOCK_LOOP; i++ )
			{
				dwResult |= FMD_LB_GetBlockStatus((blockID-wPRIMARY_NAND_BLOCKS)*(LB_BLOCK_LOOP) + i, USE_GPIO);
			}
		}
		else
		{
			for ( i = 0; i < SB_BLOCK_LOOP; i++ )
			{
				dwResult |= FMD_SB_GetBlockStatus((blockID-wPRIMARY_NAND_BLOCKS)*(SB_BLOCK_LOOP) + i, USE_GPIO);
			}
		}
	}

    return dwResult;
}


/*
	@func   BOOL | MarkBlockBad | Marks the specified block as bad.
	@rdesc  TRUE = Success, FALSE = Failure.
	@comm	
	@xref   
*/
static BOOL MarkBlockBad(BLOCK_ID blockID)
{
    BOOL    bRet = TRUE;
	int i;

	if ( blockID < wPRIMARY_NAND_BLOCKS )
	{
		if ( astNandSpec[dwPrimaryNandDevice].nSctsPerPg == 4 )
		{
			for ( i = 0; i < LB_BLOCK_LOOP; i++ )
			{
				bRet = LB_MarkBlockBad(blockID*(LB_BLOCK_LOOP) + i, USE_NFCE);
				if ( bRet == FALSE ) break;
			}
		}
		else
		{
			for ( i = 0; i < SB_BLOCK_LOOP; i++ )
			{
				bRet = SB_MarkBlockBad(blockID*(SB_BLOCK_LOOP) + i, USE_NFCE);
				if ( bRet == FALSE ) break;
			}
		}
	}
	else	// if ( PRIMARY_NAND == SMALL_BLOCK_NAND )
	{
		if ( astNandSpec[dwSecondaryNandDevice].nSctsPerPg == 4 )
		{
			for ( i = 0; i < LB_BLOCK_LOOP; i++ )
			{
				bRet = LB_MarkBlockBad((blockID-wPRIMARY_NAND_BLOCKS)*(LB_BLOCK_LOOP) + i, USE_GPIO);
				if ( bRet == FALSE ) break;
			}
		}
		else
		{
			for ( i = 0; i < SB_BLOCK_LOOP; i++ )
			{
				bRet = SB_MarkBlockBad((blockID-wPRIMARY_NAND_BLOCKS)*(SB_BLOCK_LOOP) + i, USE_GPIO);
				if ( bRet == FALSE ) break;
			}
		}
	}

    return bRet;
}

/*
	@func   BOOL | FMD_SetBlockStatus | Marks the block with the specified block status.
	@rdesc  TRUE = Success, FALSE = Failure.
	@comm	
	@xref   
*/
BOOL FMD_SetBlockStatus(BLOCK_ID blockID, DWORD dwStatus)
{
    BOOL    bRet = TRUE;
	int i;

	if ( blockID < wPRIMARY_NAND_BLOCKS )
	{
		if ( astNandSpec[dwPrimaryNandDevice].nSctsPerPg == 4 )
		{
			for ( i = 0; i < LB_BLOCK_LOOP; i++ )
			{
				bRet = FMD_LB_SetBlockStatus(blockID*(LB_BLOCK_LOOP) + i, dwStatus, USE_NFCE);
				if ( bRet == FALSE ) break;
			}
		}
		else
		{
			for ( i = 0; i < SB_BLOCK_LOOP; i++ )
			{
				bRet = FMD_SB_SetBlockStatus(blockID*(SB_BLOCK_LOOP) + i, dwStatus, USE_NFCE);
				if ( bRet == FALSE ) break;
			}
		}
	}
	else	// if ( PRIMARY_NAND == SMALL_BLOCK_NAND )
	{
		if ( astNandSpec[dwSecondaryNandDevice].nSctsPerPg == 4 )
		{
			for ( i = 0; i < LB_BLOCK_LOOP; i++ )
			{
				bRet = FMD_LB_SetBlockStatus((blockID-wPRIMARY_NAND_BLOCKS)*(LB_BLOCK_LOOP) + i, dwStatus, USE_GPIO);
				if ( bRet == FALSE ) break;
			}
		}
		else
		{
			for ( i = 0; i < SB_BLOCK_LOOP; i++ )
			{
				bRet = FMD_SB_SetBlockStatus((blockID-wPRIMARY_NAND_BLOCKS)*(SB_BLOCK_LOOP) + i, dwStatus, USE_GPIO);
				if ( bRet == FALSE ) break;
			}
		}
	}

    return bRet;
}

BOOL FMD_LB_ReadSector(SECTOR_ADDR startSectorAddr, LPBYTE pSectorBuff, PSectorInfo pSectorInfoBuff, DWORD dwNumSectors,int mode)
{
	ULONG SectorAddr = (ULONG)startSectorAddr;
//	ULONG MECC;
	DWORD       i;
	BYTE        eccBuf[8];	
	volatile DWORD		rddata;	
	int NewSpareAddr = 2048 + 16*(startSectorAddr%4);
	int NewDataAddr = 512*(startSectorAddr%4);
	int NewSectorAddr = startSectorAddr/4;

	//RETAILMSG(1,(TEXT("#### FMD_DRIVER:::FMD_LB_READSECTOR %x %x\r\n"),startSectorAddr,NewDataAddr));

	if (!pSectorBuff && !pSectorInfoBuff)
		return(FALSE);

	if ( dwNumSectors > 1 )
	{
		RETAILMSG(1, (TEXT("######## FATAL ERROR => FMD::FMD_ReadSector->dwNumsectors is bigger than 1. \r\n")));
		return FALSE;
	}

//	BOOL bLastMode = SetKMode(TRUE);

	if (!pSectorBuff)
	{
		NAND_LB_ReadSectorInfo(startSectorAddr, pSectorInfoBuff, mode);

		return TRUE;
	}


	NF_RSTECC();
	NF_MECC_UnLock();
	NF_nFCE_L();
	
	NF_CLEAR_RB();

	NF_CMD(CMD_READ);							// Send read command.

	NF_ADDR((NewDataAddr)&0xff);
	NF_ADDR(((NewDataAddr)>>8)&0xff);
	NF_ADDR((NewSectorAddr) & 0xff);
	NF_ADDR((NewSectorAddr >> 8) & 0xff);

#if 1 // hsjang 060613	
	if (NEED_EXT_ADDR)
		NF_ADDR((NewSectorAddr >> 16) & 0xff);  
#endif

	NF_CMD(CMD_READ3);	// 2nd command
	NF_DETECT_RB();								// Wait for command to complete.

	if( ((DWORD) pSectorBuff) & 0x3) 
	{
		for(i=0; i<NAND_PAGE_SIZE/sizeof(DWORD); i++) {
			rddata = (DWORD) NF_RDDATA_WORD();
			pSectorBuff[i*4+0] = (BYTE)(rddata & 0xff);
			pSectorBuff[i*4+1] = (BYTE)(rddata>>8 & 0xff);
			pSectorBuff[i*4+2] = (BYTE)(rddata>>16 & 0xff);
			pSectorBuff[i*4+3] = (BYTE)(rddata>>24 & 0xff);
		}
	}
	else 
	{
		#if 1
		RdPage512(pSectorBuff);					// Read page/sector data.
		#else
		for(volatile int i=0; i<512; i++)
		{
		for(volatile int j=0; j<5; j++);
			*pSectorBuff++ = (BYTE)s2443NAND->NFDATA;
		}
		#endif
	}
	NF_MECC_Lock();


	NF_CMD(CMD_RDO);
	//  Set up address
	NF_ADDR((NewSpareAddr)&0xff);
	NF_ADDR(((NewSpareAddr)>>8)&0xff);

	NF_CMD(CMD_RDO2);

#if 0
	if (pSectorInfoBuff)
	{
		RdPageInfo((PBYTE)pSectorInfoBuff);		// Read page/sector information.
		pSectorInfoBuff ++;
	}
#else
	if (pSectorInfoBuff)
	{

//		RdPageInfo((PBYTE)pSectorInfoBuff);		// Read page/sector information.
		rddata= NF_RDDATA_WORD();
	        pSectorInfoBuff->dwReserved1  = rddata;
		//RETAILMSG(1, (TEXT("111Spare DATA you want it 0x%x\r\n"),rddata));				
		rddata= NF_RDDATA_WORD();
		//RETAILMSG(1, (TEXT("Spare DATA you want it 0x%x\r\n"),rddata));	        
       	 pSectorInfoBuff->bOEMReserved = (BYTE) (rddata & 0xff);;

	        //  Read the bad block mark
       	 pSectorInfoBuff->bBadBlock = (BYTE) ((rddata>>8) & 0xff);

	        //  Second reserved field (WORD)
	        pSectorInfoBuff->wReserved2 = (WORD) ((rddata>>16) & 0xffff);
	       // pSectorInfoBuff->wReserved2 |= ((BYTE) NF_DATA_R());
	}
#endif
	else
	{
		#if 0 // hsjang 060613
		BYTE TempInfo[8];
		RdPageInfo(TempInfo);				   	// Read page/sector information.
		#endif
		 for(i=0; i<sizeof(SectorInfo)/sizeof(DWORD); i++) 
			rddata = (DWORD) NF_RDDATA_WORD();		// read and trash the data
	}

	for(i=0; i<2; i++) {
		rddata = (DWORD) NF_RDDATA_WORD();
		//RETAILMSG(1, (TEXT("333Spare DATA you want it 0x%x\r\n"),rddata));	        		
//		RETAILMSG(1, (TEXT("rddata 0x%x \r\n"), rddata));
	eccBuf[i*4+0] = (BYTE)(rddata & 0xff);
	eccBuf[i*4+1] = (BYTE)(rddata>>8 & 0xff);
	eccBuf[i*4+2] = (BYTE)(rddata>>16 & 0xff);
	eccBuf[i*4+3] = (BYTE)(rddata>>24 & 0xff);
	}

//	Mecc0 = READ_REGISTER_ULONG(pNFMECC0);

    //  Compare with the ECC generated from the HW
	NF_WRMECCD0( (DWORD)((DWORD)(eccBuf[3]<<24) | (DWORD)(eccBuf[2]<<16) |(DWORD)(eccBuf[1]<<8) | (DWORD)(eccBuf[0]&0xff)));
	//NF_WRMECCD1( (DWORD)((DWORD)(eccBuf[3]<<8) | (DWORD)(eccBuf[2]&0xff)));

	if (NF_RDESTST & 0x3)
	{
		RETAILMSG(1,(TEXT("ECC error reg:%x rd:%x(NF_RDESTST:%x)\r\n"),NF_RDMECC0(),rddata, NF_RDESTST));
 			
		NF_nFCE_H();							// Deselect the flash chip.
//		SetKMode (bLastMode);
		return FALSE;	
	}			

	NF_nFCE_H();

	//RETAILMSG(1, (TEXT(".")));
//	SetKMode (bLastMode);

	return(TRUE);
}	




void NAND_LB_ReadSectorInfo(SECTOR_ADDR sectorAddr, PSectorInfo pInfo, int mode)
{
	volatile DWORD rddata;
	int NewSpareAddr = 2048 + 16*(sectorAddr%4);
	int NewSectorAddr = sectorAddr/4;

//	 BOOL bLastMode = SetKMode(TRUE);

#if 1
	NF_nFCE_L();

	NF_CLEAR_RB();
	NF_CMD(CMD_READ);							// Send read confirm command.

	NF_ADDR((NewSpareAddr)&0xff);
	NF_ADDR((NewSpareAddr>>8)&0xff);
	NF_ADDR((NewSectorAddr)&0xff);
	NF_ADDR((NewSectorAddr>>8) & 0xff);

#if 1	// hsjang 060613
	if (NEED_EXT_ADDR)
		NF_ADDR((NewSectorAddr >> 16) & 0xff);  
#endif
	NF_CMD(CMD_READ3);

	NF_DETECT_RB();
			
	pInfo->dwReserved1  = NF_RDDATA_WORD();

	rddata = NF_RDDATA_WORD();

    //  OEM byte
	pInfo->bOEMReserved = (BYTE) (rddata & 0xff);

    //  Read the bad block mark
	pInfo->bBadBlock = (BYTE) ((rddata>>8) & 0xff);

    //  Second reserved field (WORD)
	pInfo->wReserved2 = (WORD) ((rddata>>16) & 0xffff);
	NF_nFCE_H();
#endif 

	
	//SetKMode(bLastMode);
}		


BOOL FMD_SB_ReadSector(SECTOR_ADDR startSectorAddr, LPBYTE pSectorBuff, PSectorInfo pSectorInfoBuff, DWORD dwNumSectors,int mode)
{
	ULONG SectorAddr = (ULONG)startSectorAddr;
	ULONG MECC;

	if (!pSectorBuff && !pSectorInfoBuff)
		return(FALSE);

//	BOOL bLastMode = SetKMode(TRUE);

	//RETAILMSG(1,(TEXT("#### FMD_DRIVER:::FMD_sbreadT \r\n")));			

	while (dwNumSectors--)
	{
		ULONG blockPage = (((SectorAddr / NAND_PAGE_CNT) * NAND_PAGE_CNT) | (SectorAddr % NAND_PAGE_CNT));

		NF_RSTECC();
		NF_MECC_UnLock();
		NF_nFCE_L();
		
		if (!pSectorBuff)
		{
			NF_CLEAR_RB();
			NF_CMD(CMD_READ2);							// Send read confirm command.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -