fmd.cpp

来自「SAMSUNG S3C6410 CPU BSP for winmobile6」· C++ 代码 · 共 2,345 行 · 第 1/4 页

CPP
2,345
字号
	        pInterface->pSetBlockStatus = FMD_SetBlockStatus;
	        pInterface->pReadSector = FMD_ReadSector;
	        pInterface->pWriteSector = FMD_WriteSector;
	        pInterface->pEraseBlock = FMD_EraseBlock;
	        pInterface->pPowerUp = FMD_PowerUp;
	        pInterface->pPowerDown = FMD_PowerDown;
	        pInterface->pGetPhysSectorAddr = NULL;            
	
	        break;
	    }
		#if 0
		case IOCTL_FMD_LOCK_BLOCKS:
			// LOCK is not supported.!!!!
			BlockLockInfo * pLockInfo;
			pLockInfo = (BlockLockInfo *)pInBuf;
			RETAILMSG(1, (TEXT("IOCTL_FMD_LOCK_BLOCKS!!!!(0x%x,0x%x) \r\n"), pLockInfo->StartBlock, pLockInfo->NumBlocks));

			if ( astNandSpec[dwPrimaryNandDevice].nSctsPerPg == 4 )		// Large Block
			{
				if ( READ_REGISTER_BYTE(pNFSBLK) >> 6 < (ULONG)(pLockInfo->StartBlock + pLockInfo->NumBlocks) )
					WRITE_REGISTER_USHORT(pNFSBLK, (pLockInfo->StartBlock + pLockInfo->NumBlocks)<<6);
			}
			else	// Small Block
			{
				if ( READ_REGISTER_BYTE(pNFSBLK) >> 5 < (ULONG)(pLockInfo->StartBlock + pLockInfo->NumBlocks)*8 )
				{
//					RETAILMSG(1, (TEXT("Write value (0x%x) \r\n"), ((ULONG)(pLockInfo->StartBlock + pLockInfo->NumBlocks)*8)<<5));
					WRITE_REGISTER_ULONG(pNFSBLK, ((ULONG)(pLockInfo->StartBlock + pLockInfo->NumBlocks)*8)<<5);
//					RETAILMSG(1, (TEXT("Read value  (0x%x) \r\n"), READ_REGISTER_ULONG(pNFSBLK)));
				}
			}
			pBSPArgs->nfsblk = pLockInfo->StartBlock + pLockInfo->NumBlocks;
			
			break;
		case IOCTL_FMD_UNLOCK_BLOCKS:
			RETAILMSG(1, (TEXT("IOCTL_FMD_UNLOCK_BLOCKS!!!!(0x%x,0x%x) \r\n"), pLockInfo->StartBlock, pLockInfo->NumBlocks));
			RETAILMSG(1, (TEXT("S3C6410 Does not support IOCTL_FMD_UNLOCK_BLOCKS !!!! \r\n")));
	        return(FALSE);
			#endif	
	    default:
	        RETAILMSG(1, (TEXT("FMD_OEMIoControl: unrecognized IOCTL (0x%x).\r\n"), dwIoControlCode));
	        return(FALSE);
								
    }

    return TRUE; 
}

#endif // NOSYSCALL
#endif // MAGNETO

//#define VALIDADDR	0x05	// S3C6410NAND

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;
	DWORD       i;
	volatile DWORD		rddata;
	UINT32 nRetEcc = 0;
	DWORD MECCBuf[4];
	UINT16 nSectorLoop;
	int NewSpareAddr = 2048;
	int NewDataAddr = 0;
	int NewSectorAddr = startSectorAddr;
#if CHECK_SPAREECC
	DWORD SECCBuf;
#endif

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

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

		return TRUE;
	}
	
	BOOL bLastMode = SetKMode(TRUE);	

	NF_nFCE_L();

	NF_CLEAR_RB();

	NF_CMD(CMD_READ);							// Send read 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);	// 2nd command
	NF_DETECT_RB();								// Wait for command to complete.


	if (pSectorInfoBuff)
	{
#if CHECK_SPAREECC
		NF_RSTECC();
		NF_SECC_UnLock();
#endif

		pSectorInfoBuff->bBadBlock = NF_RDDATA_BYTE();
		pSectorInfoBuff->dwReserved1 = NF_RDDATA_WORD();
		pSectorInfoBuff->bOEMReserved = NF_RDDATA_BYTE();

#if CHECK_SPAREECC
		NF_SECC_Lock();
#endif

		pSectorInfoBuff->wReserved2 = NF_RDDATA_BYTE();
		pSectorInfoBuff->wReserved2 |= (NF_RDDATA_BYTE()<<8);
	}
	else
	{
		 for(i=0; i<sizeof(SectorInfo)/sizeof(DWORD); i++)
		 {
			rddata = (DWORD) NF_RDDATA_WORD();		// read and trash the data
		 }
	}
	
	for (nSectorLoop = 0; nSectorLoop < astNandSpec[dwPrimaryNandDevice].nSctsPerPg; nSectorLoop++)
	{
		MECCBuf[nSectorLoop] = NF_RDDATA_WORD();
	}
	
#if CHECK_SPAREECC
	if (pSectorInfoBuff)
	{
		SECCBuf = NF_RDDATA_WORD();
		NF_WRSECCD((SECCBuf&0xff)|((SECCBuf<<8)&0xff0000));


		nRetEcc = NF_ECC_ERR0;

		if (!ECC_CorrectData(startSectorAddr, (LPBYTE)pSectorInfoBuff, nRetEcc, ECC_CORRECT_SPARE))
		{
			return FALSE;
		}
	}
#endif		

	for (nSectorLoop = 0; nSectorLoop < astNandSpec[dwPrimaryNandDevice].nSctsPerPg; nSectorLoop++)
	{
		NewDataAddr = nSectorLoop * SECTOR_SIZE;

		NF_CMD(CMD_RDO);							// Send read command.
		NF_ADDR((NewDataAddr)&0xff);
		NF_ADDR((NewDataAddr>>8)&0xff);
		NF_CMD(CMD_RDO2);	// 2nd command

		NF_RSTECC();
		NF_MECC_UnLock();

		if( ((DWORD) (pSectorBuff+nSectorLoop*SECTOR_SIZE)) & 0x3)
		{
			for(i=0; i<SECTOR_SIZE/sizeof(DWORD); i++)
			{
				rddata = (DWORD) NF_RDDATA_WORD();
				(pSectorBuff+nSectorLoop*SECTOR_SIZE)[i*4+0] = (BYTE)(rddata & 0xff);
				(pSectorBuff+nSectorLoop*SECTOR_SIZE)[i*4+1] = (BYTE)(rddata>>8 & 0xff);
				(pSectorBuff+nSectorLoop*SECTOR_SIZE)[i*4+2] = (BYTE)(rddata>>16 & 0xff);
				(pSectorBuff+nSectorLoop*SECTOR_SIZE)[i*4+3] = (BYTE)(rddata>>24 & 0xff);
			}
		}
		else
		{
			RdPage512(pSectorBuff+nSectorLoop*SECTOR_SIZE);					// Read page/sector data.
		}

		NF_MECC_Lock();

		NF_WRMECCD0( ((MECCBuf[nSectorLoop]&0xff00)<<8)|(MECCBuf[nSectorLoop]&0xff) );
		NF_WRMECCD1( ((MECCBuf[nSectorLoop]&0xff000000)>>8)|((MECCBuf[nSectorLoop]&0xff0000)>>16) );

		nRetEcc = NF_ECC_ERR0;

		if (!ECC_CorrectData(startSectorAddr, pSectorBuff+nSectorLoop*SECTOR_SIZE, nRetEcc, ECC_CORRECT_MAIN))
		{
			return FALSE;
		}
	}

	NF_nFCE_H();

	SetKMode (bLastMode);

	return(TRUE);
}

#if 0
BOOL RAW_LB_ReadSector(UINT32 startSectorAddr, LPBYTE pSectorBuff, LPBYTE pSectorInfoBuff)
{
	ULONG SectorAddr = (ULONG)startSectorAddr;
	DWORD       i;
	volatile DWORD		rddata;
	UINT32 nRetEcc = 0;
//	DWORD MECCBuf[4];
	UINT16 nSectorLoop;
	int NewDataAddr = 0;

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

	BOOL bLastMode = SetKMode(TRUE);	

	NF_nFCE_L();

	NF_CLEAR_RB();

	NF_CMD(CMD_READ);							// Send read command.

	NF_ADDR((NewDataAddr)&0xff);
	NF_ADDR(((NewDataAddr)>>8)&0xff);
	NF_ADDR((SectorAddr) & 0xff);
	NF_ADDR((SectorAddr >> 8) & 0xff);
	if (NEED_EXT_ADDR)
		NF_ADDR((SectorAddr >> 16) & 0xff);  

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

	for (nSectorLoop = 0; nSectorLoop < 4; nSectorLoop++)
	{
		if( ((DWORD) (pSectorBuff+nSectorLoop*SECTOR_SIZE)) & 0x3)
		{
			for(i=0; i<SECTOR_SIZE/sizeof(DWORD); i++)
			{
				rddata = (DWORD) NF_RDDATA_WORD();
				(pSectorBuff+nSectorLoop*SECTOR_SIZE)[i*4+0] = (BYTE)(rddata & 0xff);
				(pSectorBuff+nSectorLoop*SECTOR_SIZE)[i*4+1] = (BYTE)(rddata>>8 & 0xff);
				(pSectorBuff+nSectorLoop*SECTOR_SIZE)[i*4+2] = (BYTE)(rddata>>16 & 0xff);
				(pSectorBuff+nSectorLoop*SECTOR_SIZE)[i*4+3] = (BYTE)(rddata>>24 & 0xff);
			}
		}
		else
		{
			RdPage512(pSectorBuff+nSectorLoop*SECTOR_SIZE);					// Read page/sector data.
		}
	}

	 for(i=0; i<64; i++)
	 {
		*pSectorInfoBuff = NF_RDDATA_BYTE();		// read and trash the data
		pSectorInfoBuff+=1;
	 }

	NF_nFCE_H();

	SetKMode (bLastMode);

	return(TRUE);
}
#endif

void NAND_LB_ReadSectorInfo(SECTOR_ADDR sectorAddr, PSectorInfo pInfo, int mode)
{
	BOOL bRet = TRUE;
	int NewSpareAddr = 2048;
	int NewSectorAddr = sectorAddr;
#if CHECK_SPAREECC
	DWORD SECCBuf;
	UINT32 nRetEcc = 0;
#endif

	 BOOL bLastMode = SetKMode(TRUE);

	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 (NEED_EXT_ADDR)
		NF_ADDR((NewSectorAddr >> 16) & 0xff);  
	NF_CMD(CMD_READ3);

	NF_DETECT_RB();

#if CHECK_SPAREECC
	NF_RSTECC();
	NF_SECC_UnLock();
#endif

	pInfo->bBadBlock = NF_RDDATA_BYTE();
	pInfo->dwReserved1  = NF_RDDATA_WORD();
	pInfo->bOEMReserved = NF_RDDATA_BYTE();

#if CHECK_SPAREECC
	NF_SECC_Lock();
#endif

	pInfo->wReserved2 = NF_RDDATA_BYTE();
	pInfo->wReserved2 |= (NF_RDDATA_BYTE()<<8);
	
#if CHECK_SPAREECC
	SECCBuf = NF_RDSECC();
	NF_WRSECCD((SECCBuf&0xff)|((SECCBuf<<8)&0xff0000));

	nRetEcc = NF_ECC_ERR0;

	bRet = ECC_CorrectData(sectorAddr, (LPBYTE)pInfo, nRetEcc, ECC_CORRECT_SPARE);
#endif	

	NF_nFCE_H();
	
	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);

#if (NAND_DEBUG)
	RETAILMSG(1,(TEXT("#### FMD_DRIVER:::FMD_sbreadT \r\n")));
#endif

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

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

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

			NF_ADDR(0);									// Ignored.
			NF_ADDR(blockPage		 & 0xff);			// Page address.
			NF_ADDR((blockPage >>  8) & 0xff);
			if (NEED_EXT_ADDR)
				NF_ADDR((blockPage >> 16) & 0xff);  

			NF_DETECT_RB();

			RdPageInfo((PBYTE)pSectorInfoBuff);	// Read page/sector information.

			pSectorInfoBuff++;
		}
		else
		{
			NF_CLEAR_RB();

			NF_CMD(CMD_READ);							// Send read command.

			NF_ADDR(0);									// Column = 0.
			NF_ADDR(blockPage		 & 0xff);			// Page address.
			NF_ADDR((blockPage >>  8) & 0xff);
			if (NEED_EXT_ADDR)
				NF_ADDR((blockPage >> 16) & 0xff);  

			NF_DETECT_RB();								// Wait for command to complete.

			if( ((DWORD) pSectorBuff) & 0x3)
			{
				RdPage512Unalign (pSectorBuff);
			}
			else
			{
				RdPage512(pSectorBuff);					// Read page/sector data.
			}

⌨️ 快捷键说明

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