fmd.cpp

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

CPP
2,345
字号
			NF_MECC_Lock();

			if (pSectorInfoBuff)
			{
				RdPageInfo((PBYTE)pSectorInfoBuff);		// Read page/sector information.
				pSectorInfoBuff ++;
			}
			else
			{
				BYTE TempInfo[8];
				RdPageInfo(TempInfo);				   	// Read page/sector information.
			}

			MECC  = NF_RDDATA_BYTE() << 0;
			MECC |= NF_RDDATA_BYTE() << 8;
			MECC |= NF_RDDATA_BYTE() << 16;
			MECC |= (NF_RDMECC0() &0xff000000);

			NF_WRMECCD0( ((MECC&0xff00)<<8)|(MECC&0xff) );
			NF_WRMECCD1( ((MECC&0xff000000)>>8)|((MECC&0xff0000)>>16) );

			if (NF_RDESTST & 0x3)
			{
				RETAILMSG(1,(TEXT("ECC error reg:%x rd:%x(NF_RDESTST:%x)\r\n"),NF_RDMECC0(),MECC, NF_RDESTST));

				NF_nFCE_H();	// Deselect the flash chip.
				SetKMode (bLastMode);
				return FALSE;
			}

			pSectorBuff += NAND_PAGE_SIZE;
		}

		NF_nFCE_H();
		++SectorAddr;
	}

	SetKMode (bLastMode);

	return(TRUE);
}

BOOL FMD_LB_WriteSector(SECTOR_ADDR startSectorAddr, LPBYTE pSectorBuff, PSectorInfo pSectorInfoBuff, DWORD dwNumSectors, int mode)
{
	DWORD   i;
	BOOL    bRet = TRUE;
	volatile DWORD	wrdata;
	DWORD MECCBuf[4];
	UINT16 nSectorLoop;
	int NewSpareAddr = 2048;
	int NewDataAddr = 0;
	int NewSectorAddr = startSectorAddr;
#if CHECK_SPAREECC
	DWORD SECCBuf;
#endif

#if (NAND_DEBUG)
	RETAILMSG(1, (TEXT("FMD::FMD_LB_WriteSector 0x%x \r\n"), startSectorAddr));
#endif

	//  Sanity check
	//  BUGBUGBUG: I need to come back to support dwNumSectors > 1
	if (!pSectorBuff && !pSectorInfoBuff) return(FALSE);

	if ( dwNumSectors > 1 )
	{
		RETAILMSG(1, (TEXT("######## FATAL ERROR => FMD::FMD_WriteSector->dwNumsectors is bigger than 1. \r\n")));
		return FALSE;
	}
	
	if (!pSectorBuff)
	{
		NAND_LB_WriteSectorInfo(startSectorAddr, pSectorInfoBuff, mode);
		return TRUE;
	}
	
    BOOL bLastMode = SetKMode(TRUE);	


	//  Enable Chip
	NF_nFCE_L();

	//  Issue command
	NF_CMD(CMD_WRITE);

	//  Setup address
	NF_ADDR((NewDataAddr)&0xff);
	NF_ADDR(((NewDataAddr)>>8)&0xff);
	NF_ADDR((NewSectorAddr) & 0xff);
	NF_ADDR((NewSectorAddr >> 8) & 0xff);
    if (NEED_EXT_ADDR) {
        NF_ADDR((NewSectorAddr >> 16) & 0xff);
    }

	for (nSectorLoop = 0; nSectorLoop < astNandSpec[dwPrimaryNandDevice].nSctsPerPg; nSectorLoop++)
	{
		//  Initialize ECC register
		NF_RSTECC();
		NF_MECC_UnLock();

		//  Special case to handle un-aligned buffer pointer.
		//
		if( ((DWORD) (pSectorBuff+nSectorLoop*SECTOR_SIZE)) & 0x3)
		{
			//  Write the data
			for(i=0; i<SECTOR_SIZE/sizeof(DWORD); i++)
			{
				wrdata = (pSectorBuff+nSectorLoop*SECTOR_SIZE)[i*4+0];
				wrdata |= (pSectorBuff+nSectorLoop*SECTOR_SIZE)[i*4+1]<<8;
				wrdata |= (pSectorBuff+nSectorLoop*SECTOR_SIZE)[i*4+2]<<16;
				wrdata |= (pSectorBuff+nSectorLoop*SECTOR_SIZE)[i*4+3]<<24;
				NF_WRDATA_WORD(wrdata);
			}
		}
		else
		{
			WrPage512(pSectorBuff+nSectorLoop*SECTOR_SIZE);
		}

		//  Read out the ECC value generated by HW
		NF_MECC_Lock();

		MECCBuf[nSectorLoop] = NF_RDMECC0();
	}

	NF_CMD(CMD_RDI);
	NF_ADDR((NewSpareAddr)&0xff);
	NF_ADDR((NewSpareAddr>>8)&0xff);

	// Write the SectorInfo data to the media
	// NOTE: This hardware is odd: only a byte can be written at a time and it must reside in the
	//       upper byte of a USHORT.
	if(pSectorInfoBuff)
	{
#if CHECK_SPAREECC
		NF_RSTECC();
		NF_SECC_UnLock();
#endif


		//  Write the first reserved field (DWORD)
		NF_WRDATA_BYTE(pSectorInfoBuff->bBadBlock);
		//NF_WRDATA_WORD(pSectorInfoBuff->dwReserved1);
		NF_WRDATA_BYTE(pSectorInfoBuff->dwReserved1&0xff);
		NF_WRDATA_BYTE((pSectorInfoBuff->dwReserved1>>8)&0xff);
		NF_WRDATA_BYTE((pSectorInfoBuff->dwReserved1>>16)&0xff);
		NF_WRDATA_BYTE((pSectorInfoBuff->dwReserved1>>24)&0xff);
		NF_WRDATA_BYTE(pSectorInfoBuff->bOEMReserved);
#if CHECK_SPAREECC
		NF_SECC_Lock();
		SECCBuf = NF_RDSECC();
#endif
		NF_WRDATA_BYTE(pSectorInfoBuff->wReserved2&0xff);
		NF_WRDATA_BYTE((pSectorInfoBuff->wReserved2>>8)&0xff);
	}
	else
	{
		// Make sure we advance the Flash's write pointer (even though we aren't writing the SectorInfo data)
		for(i=0; i<sizeof(SectorInfo)/sizeof(DWORD); i++)
		{
			NF_WRDATA_WORD(0xffffffff);
		}
	}

    //  Write the ECC value to the flash
	NF_WRDATA_WORD(MECCBuf[0]);
	NF_WRDATA_WORD(MECCBuf[1]);
	NF_WRDATA_WORD(MECCBuf[2]);
	NF_WRDATA_WORD(MECCBuf[3]);

#if CHECK_SPAREECC
	if(pSectorInfoBuff)
	{
		NF_WRDATA_WORD(SECCBuf);
	}
#endif

	//  Finish up the write operation
	NF_CMD(CMD_WRITE2);

	//  Wait for RB
	NF_DETECT_RB();	 // Wait tR(max 12us)

	if ( NF_RDSTAT & STATUS_ILLACC )
	{
		RETAILMSG(1, (TEXT("FMD_WriteSector() ######## Error Programming page (Illigar Access) %d!\n"), startSectorAddr));
		s6410NAND->NFSTAT =  STATUS_ILLACC;	// Write 1 to clear.
		bRet = FALSE;
	}
	else
	{
		//  Check the status
		NF_CMD(CMD_STATUS);

		if(NF_RDDATA_BYTE() & STATUS_ERROR)
		{
			RETAILMSG(1, (TEXT("FMD_WriteSector() ######## Error Programming page %d!\n"), startSectorAddr));
			bRet = FALSE;
		}
	}

	//  Disable the chip
	NF_nFCE_H();

	SetKMode(bLastMode);
	return bRet;
}

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

	BOOL bLastMode = SetKMode(TRUE);

	//  Chip enable
	NF_nFCE_L();
	NF_CLEAR_RB();

	//  Write the command
	//  First, let's point to the spare area
	NF_CMD(CMD_WRITE);

	//  Write the address
	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);
	}


#if CHECK_SPAREECC
	NF_RSTECC();
	NF_SECC_UnLock();
#endif
	//  Now let's write the SectorInfo data
	//
	//  Write the first reserved field (DWORD)
	NF_WRDATA_BYTE(pInfo->bBadBlock);
	NF_WRDATA_WORD(pInfo->dwReserved1);
	NF_WRDATA_BYTE(pInfo->bOEMReserved);
#if CHECK_SPAREECC
	NF_SECC_Lock();
#endif

	NF_WRDATA_BYTE(pInfo->wReserved2&0xff);
	NF_WRDATA_BYTE((pInfo->wReserved2>>8)&0xff);
	
	NF_WRDATA_WORD(0xffffffff);  // Mecc[0]
	NF_WRDATA_WORD(0xffffffff);  // Mecc[1]
	NF_WRDATA_WORD(0xffffffff);  // Mecc[2]
	NF_WRDATA_WORD(0xffffffff);  // Mecc[3]

#if CHECK_SPAREECC
	SECCBuf = NF_RDSECC();
	NF_WRDATA_WORD(SECCBuf);
#endif

	//  Issue the write complete command
	NF_CMD(CMD_WRITE2);

	//  Check ready bit
	NF_DETECT_RB();	 // Wait tR(max 12us)

	if ( NF_RDSTAT & STATUS_ILLACC )
	{
		RETAILMSG(1, (TEXT("NAND_LB_WriteSectorInfo() ######## Error Programming page (Illigar Access) %d!\n"), sectorAddr));
		s6410NAND->NFSTAT =  STATUS_ILLACC;	// Write 1 to clear.
		bRet = FALSE;
	}
	else
	{
		//  Check the status of program
		NF_CMD(CMD_STATUS);

		if( NF_RDDATA_BYTE() & STATUS_ERROR)
		{
			RETAILMSG(1, (TEXT("NAND_LB_WriteSectorInfo() ######## Error Programming page %d!\n"), sectorAddr));
			bRet = FALSE;
		}
	}

	NF_nFCE_H();

	SetKMode(bLastMode);
	return bRet;

}


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

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

#if (NAND_DEBUG)
	RETAILMSG(1,(TEXT("#### FMD_DRIVER:::FMD_sbwrite \r\n")));
#endif
	BOOL bLastMode = SetKMode(TRUE);

	NF_nFCE_L();						// Select the flash chip.

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

		if (!pSectorBuff)	// Only spare area
		{
			// If we are asked just to write the SectorInfo, we will do that separately
			NF_CMD(CMD_READ2);					 		// Send read command.

			NF_CMD(CMD_WRITE);							// Send write 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);  

			// Write the SectorInfo data to the media.
			// Spare area[7:0]
			WrPageInfo((PBYTE)pSectorInfoBuff);

			NF_CLEAR_RB();
			NF_CMD(CMD_WRITE2);				// Send write confirm command.
			NF_DETECT_RB();

			NF_CMD(CMD_STATUS);
			Status = NF_RDDATA_BYTE();					// Read command status.

			if (Status & STATUS_ERROR)
			{
				NF_nFCE_H();							// Deselect the flash chip.
				SetKMode (bLastMode);
				return(FALSE);
			}

			pSectorInfoBuff++;
		}
		else 		// Main area+Spare area.
		{
		NF_CMD(CMD_READ);					 		// Send read command.

		NF_CMD(CMD_WRITE);							// Send write 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);  

		//  Special case to handle un-aligned buffer pointer.
		NF_RSTECC();
		NF_MECC_UnLock();

		if( ((DWORD) pSectorBuff) & 0x3)
		{
			WrPage512Unalign (pSectorBuff);
		}
		else
		{
			WrPage512(pSectorBuff);					// Write page/sector data.
		}

		NF_MECC_Lock();

		// Write the SectorInfo data to the media.
		// Spare area[7:0]
		if(pSectorInfoBuff)
		{
			WrPageInfo((PBYTE)pSectorInfoBuff);
			pSectorInfoBuff++;
		}
		else	// Make sure we advance the Flash's write pointer (even though we aren't writing the SectorInfo data)
		{
			BYTE TempInfo[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
			WrPageInfo(TempInfo);
		}

		// Write the SectorInfo data to the media.
		// Spare area[11:8]
		// Get the ECC data from status register.
		MECC = NF_RDMECC0();
		// Now, Write the ECC data to Spare area[11:8]
		NF_WRDATA_BYTE((UCHAR)((MECC	  ) & 0xff));		// Spare area offset 8
		NF_WRDATA_BYTE((UCHAR)((MECC >>  8) & 0xff));	// Spare area offset 9
		NF_WRDATA_BYTE((UCHAR)((MECC >> 16) & 0xff));	// Spare area offset 10
		NF_WRDATA_BYTE((UCHAR)((MECC >> 24) & 0xff));	// Spare area offset 11

		NF_CLEAR_RB();
		NF_CMD(CMD_WRITE2);							// Send write confirm command.
		NF_DETECT_RB();

		do
		{
			NF_CMD(CMD_STATUS);
			Status = NF_RDDATA_BYTE();					// Read command status.
		}while(!(Status & STATUS_READY));

		if (Status & STATUS_ERROR)
		{
			NF_nFCE_H();							// Deselect the flash chip.
				SetKMode (bLastMode);
			return(FALSE);
		}
			pSectorBuff += NAND_PAGE_SIZE;
		}

		++SectorAddr;
	}

	NF_nFCE_H();										// Deselect the flash chip.

	SetKMode (bLastMode);
	
	return(TRUE);
}


BOOL FMD_LB_EraseBlock(BLOCK_ID blockID, int mode)
{
	BOOL    bRet = TRUE;
	DWORD   dwPageID = blockID << LB_NAND_LOG_2_PAGES_PER_BLOCK;
	BOOL bLastMode = SetKMode(TRUE);

#if (NAND_DEBUG)
	//RETAILMSG(1, (TEXT("FMD_LB_EraseBlock 0x%x \r\n"), blockID));
#endif

	//  Enable the chip
	NF_nFCE_L();						// Select the flash chip.

	NF_CLEAR_RB();

    //  Issue command
	NF_CMD(CMD_ERASE);

    //  Set up address
	NF_ADDR((dwPageID) & 0xff);
	NF_ADDR((dwPageID >> 8) & 0xff);

	if (NEED_EXT_ADDR) {
		NF_ADDR((dwPageID >> 16) & 0xff);
	}
	//  Complete erase operation
	NF_CMD(CMD_ERASE2);

	//  Wait for ready bit
	NF_DETECT_RB();	 // Wait tR(max 12us)

	if ( NF_RDSTAT & STATUS_ILLACC )
	{
		RETAILMSG(1, (TEXT("LB######## Error Erasing block (Illigar Access) %d!\n"), blockID));
		s6410NAND->NFSTAT =  STATUS_ILLACC;	// Write 1 to clear.
		bRet = FALSE;
	}
	else
	{
		//  Check the status
		NF_CMD(CMD_STATUS);

		if( NF_RDDATA_BYTE() & STATUS_ERROR)
		{
			RETAILMSG(1, (TEXT("LB######## Error Erasing block %d!\n"), blockID));
			bRet = FALSE;
		}
	}

	NF_nFCE_H();						// Select the flash chip.

	SetKMode(bLastMode);

	return bRet;
}

BOOL FMD_SB_EraseBlock(BLOCK_ID blockID, int mode)
{
	BOOL    bRet = TRUE;
	DWORD   dwPageID = blockID << SB_NAND_LOG_2_PAGES_PER_BLOCK;


	BOOL bLastMode = SetKMode(TRUE);

	//  Enable the chip
	NF_nFCE_L();						// Select the flash chip.

	//  Issue command
	NF_CMD(CMD_ERASE);

	//  Set up address
	NF_ADDR((dwPageID) & 0xff);
	NF_ADDR((dwPageID >> 8) & 0xff);

	if (NEED_EXT_ADDR) {
		NF_ADDR((dwPageID >> 16) & 0xff);
	}
	NF_CLEAR_RB();
	//  Complete erase operation
	NF_CMD(CMD_ERASE2);

	//  Wait for ready bit
	NF_DETECT_RB();	 // Wait tR(max 12us)

	if ( NF_RDSTAT & STATUS_ILLACC )
	{
		RETAILMSG(1, (TEXT("SB######## Error Erasing block (Illigar Access) %d!\n"), blockID));
		s6410NAND->NFSTAT =  STATUS_ILLACC;	// Write 1 to clear.
		bRet = FALSE;
	}
	else
	{
		//  Check the status
		NF_CMD(CMD_STATUS);

		if( NF_RDDATA_BYTE() & STATUS_ERROR)
		{
			RETAILMSG(1, (TEXT("SB######## Error Erasing block %d!\n"), blockID));
			bRet = FALSE;
		}
	}

	NF_nFCE_H();						// Select the flash chip.

	SetKMode(bLastMode);

	return bRet;
}

DWORD FMD_LB_GetBlockStatus(BLOCK_ID blockID, int mode)
{
	SECTOR_ADDR sectorAddr = blockID << LB_NAND_LOG_2_PAGES_PER_BLOCK;
	SectorInfo SI;
	DWORD dwResult = 0;

	BOOL bLastMode = SetKMode(TRUE);

#if 0
	if (LB_IsBlockBad(sectorAddr,0)) return BLOCK_STATUS_BAD;
#endif

	if(!FMD_LB_ReadSector(sectorAddr, NULL, &SI, 1, mode))
	{
		return BLOCK_STATUS_UNKNOWN;
	}

	if(!(SI.bOEMReserved & OEM_BLOCK_READONLY))
	{
		dwResult |= BLOCK_STATUS_READONLY;
	}

#if	MAGNETO
	if( sectorAddr < pBSPArgs->nfsblk )
	{
		dwResult |= BLOCK_STATUS_READONLY;
	}
#endif

	if (!(SI.bOEMReserved & OEM_BLOCK_RESERVED))
		dwResult |= BLOCK_STATUS_RESERVED;


	if(SI.bBadBlock != 0xFF)
	{
		dwResult |= BLOCK_STATUS_BAD;
	}

	SetKMode(bLastMode);

	return dwResult;
}

DWORD FMD_SB_GetBlockStatus(BLOCK_ID blockID, int mode)
{
	SECTOR_ADDR sectorAddr = blockID << SB_NAND_LOG_2_PAGES_PER_BLOCK;
	SectorInfo SI;
	DWORD dwResult = 0;

	BOOL bLastMode = SetKMode(TRUE);

⌨️ 快捷键说明

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