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

📄 fmd.cpp

📁 Samsung公司S3C6400芯片的BSP源码包
💻 CPP
📖 第 1 页 / 共 3 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this sample source code is subject to the terms of the Microsoft
// license agreement under which you licensed this sample source code. If
// you did not accept the terms of the license agreement, you are not
// authorized to use this sample source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the LICENSE.RTF on your install media or the root of your tools installation.
// THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
#include <fmd.h>
#include <bsp.h>
//#include <ethdbg.h>
#include "Cfnand.h"
//#include <kitl.h>

//#define SYNC_OP
#define CHECK_SPAREECC	(1)
#define NAND_DEBUG		(0)

#define NAND_BASE		(0xB0200000)	// PA:0x70200000
#define SYSCON_BASE		(0xB2A0F000)	// PA:0x7E00F000

#ifdef	SYNC_OP
CRITICAL_SECTION	g_csNandFlash;
#endif

static volatile S3C6400_NAND_REG *g_pNFConReg = NULL;
static volatile S3C6400_SYSCON_REG *g_pSysConReg = NULL;

extern "C"
{
	void RdPage512(unsigned char *bufPt);
	void RdPage512Unalign(unsigned char *bufPt);
	void WrPage512(unsigned char *bufPt);
	void WrPage512Unalign(unsigned char *bufPt);
	void WrPageInfo(PBYTE pBuff);
	void RdPageInfo(PBYTE pBuff);
}

NANDDeviceInfo GetNandInfo(void) { return stDeviceInfo; }

/*
    @func   DWORD | ReadFlashID | Reads the flash manufacturer and device codes.
    @rdesc  Manufacturer and device codes.
    @comm
    @xref
*/
static DWORD ReadFlashID(void)
{
	BYTE Mfg, Dev;
	int i;

	NF_nFCE_L();				// Deselect the flash chip.
	NF_CMD(CMD_READID);		// Send flash ID read command.

	NF_ADDR(0);

	for (i=0; i<10; i++)
	{
		Mfg	= NF_RDDATA_BYTE();
		if (Mfg == 0xEC || Mfg == 0x98) break;
	}

	Dev	= NF_RDDATA_BYTE();

	NF_nFCE_H();

	return ((DWORD)(Mfg<<8)+Dev);
}

/*
    @func   PVOID | FMD_Init | Initializes the Smart Media NAND flash controller.
    @rdesc  Pointer to S3C2410 NAND controller registers.
    @comm
    @xref
*/
PVOID FMD_Init(LPCTSTR lpActiveReg, PPCI_REG_INFO pRegIn, PPCI_REG_INFO pRegOut)
{
	volatile DWORD nNandID;
	UINT8 nMID, nDID;
	UINT32 nCnt;
	BOOL bNandExt = FALSE;

	RETAILMSG(1, (TEXT("[FMD] ++FMD_Init()\r\n")));

	if (pRegIn && pRegIn->MemBase.Num && pRegIn->MemBase.Reg[0])
	{
		g_pNFConReg = (S3C6400_NAND_REG *)(pRegIn->MemBase.Reg[0]);
	}
	else
	{
		g_pNFConReg = (S3C6400_NAND_REG *)NAND_BASE;
	}

	g_pSysConReg = (S3C6400_SYSCON_REG *)SYSCON_BASE;

#ifdef	SYNC_OP
	InitializeCriticalSection(&g_csNandFlash);

	EnterCriticalSection(&g_csNandFlash);
#endif

	// Configure BUS Width and Chip Select for NAND Flash
	g_pSysConReg->MEM_SYS_CFG &= ~(1<<12);	// NAND Flash BUS Width -> 8 bit
	g_pSysConReg->MEM_SYS_CFG &= ~(0x1<<1);	// Xm0CS2 -> NFCON CS0

	// Set up initial flash controller configuration.
	g_pNFConReg->NFCONF = (TACLS<<12) | (TWRPH0<<8) | (TWRPH1<<4);
	g_pNFConReg->NFCONT = (0<<17)|(0<<16)|(0<<10)|(0<<9)|(0<<8)|(1<<7)|(1<<6)|(1<<5)|(1<<4)|(0x3<<1)|(1<<0);
	g_pNFConReg->NFSTAT = (1<<4);

	nNandID = ReadFlashID();

#ifdef	SYNC_OP
	LeaveCriticalSection(&g_csNandFlash);
#endif

	nMID = (UINT8)(nNandID >> 8);
	nDID = (UINT8)(nNandID & 0xff);

	RETAILMSG(1, (TEXT("[FMD:INF] FMD_Init() : Read ID = 0x%08x\n\r"), nNandID));

	for (nCnt = 0; astNandSpec[nCnt].nMID != 0; nCnt++)
	{
		if (nDID == astNandSpec[nCnt].nDID)
		{
			bNandExt = TRUE;
			break;
		}
	}

	if (!bNandExt)
	{
		RETAILMSG(1, (TEXT("[FMD:ERR] FMD_Init() : Unknown ID = 0x%08x\n\r"), nNandID));
		return NULL;
	}

	NUM_OF_BLOCKS = astNandSpec[nCnt].nNumOfBlks;
	PAGES_PER_BLOCK = astNandSpec[nCnt].nPgsPerBlk;
	SECTORS_PER_PAGE = astNandSpec[nCnt].nSctsPerPg;

	RETAILMSG(1, (TEXT("[FMD] FMD_Init() : NUM_OF_BLOCKS = %d\n\r"), NUM_OF_BLOCKS));
	RETAILMSG(1, (TEXT("[FMD] FMD_Init() : PAGES_PER_BLOCK = %d\n\r"), PAGES_PER_BLOCK));
	RETAILMSG(1, (TEXT("[FMD] FMD_Init() : SECTORS_PER_PAGE = %d\n\r"), SECTORS_PER_PAGE));

	RETAILMSG(1, (TEXT("[FMD] --FMD_Init()\r\n")));

	return((PVOID)g_pNFConReg);
}


/*
    @func   BOOL | FMD_ReadSector | Reads the specified sector(s) from NAND flash.
    @rdesc  TRUE = Success, FALSE = Failure.
    @comm
    @xref
*/
BOOL FMD_ReadSector(SECTOR_ADDR startSectorAddr, LPBYTE pSectorBuff, PSectorInfo pSectorInfoBuff, DWORD dwNumSectors)
{
	BOOL bRet;

	//RETAILMSG(1, (TEXT("[R:0x%08x] \r\n"), startSectorAddr));
#if (NAND_DEBUG)
	RETAILMSG(1, (TEXT("[FMD] ++FMD_ReadSector(0x%08x) \r\n"), startSectorAddr));
#endif

#ifdef	SYNC_OP
	EnterCriticalSection(&g_csNandFlash);
#endif

	if ( IS_LB )
	{
		bRet = FMD_LB_ReadSector(startSectorAddr, pSectorBuff, pSectorInfoBuff, dwNumSectors, USE_NFCE);
	}
	else
	{
		bRet = FMD_SB_ReadSector(startSectorAddr, pSectorBuff, pSectorInfoBuff, dwNumSectors, USE_NFCE);
	}

#ifdef	SYNC_OP
	LeaveCriticalSection(&g_csNandFlash);
#endif

#if (NAND_DEBUG)
	RETAILMSG(1, (TEXT("[FMD] --FMD_ReadSector()\r\n")));
#endif

	return bRet;
}


/*
    @func   BOOL | FMD_EraseBlock | Erases the specified flash block.
    @rdesc  TRUE = Success, FALSE = Failure.
    @comm
    @xref
*/
BOOL FMD_EraseBlock(BLOCK_ID blockID)
{
	BOOL    bRet = TRUE;

#if (NAND_DEBUG)
	RETAILMSG(1, (TEXT("[FMD] ++FMD_EraseBlock(0x%08x) \r\n"), blockID));
#endif

#ifdef	SYNC_OP
	EnterCriticalSection(&g_csNandFlash);
#endif

	if ( IS_LB )
	{
		bRet = FMD_LB_EraseBlock(blockID, USE_NFCE);
	}
	else
	{
		bRet = FMD_SB_EraseBlock(blockID, USE_NFCE);
	}

#ifdef	SYNC_OP
	LeaveCriticalSection(&g_csNandFlash);
#endif

#if (NAND_DEBUG)
	RETAILMSG(1, (TEXT("[FMD] --FMD_EraseBlock()\r\n")));
#endif

	return bRet;
}


/*
    @func   BOOL | FMD_WriteSector | Writes the specified data to the specified NAND flash sector/page.
    @rdesc  TRUE = Success, FALSE = Failure.
    @comm
    @xref
*/
BOOL FMD_WriteSector(SECTOR_ADDR startSectorAddr, LPBYTE pSectorBuff, PSectorInfo pSectorInfoBuff, DWORD dwNumSectors)
{
	BOOL    bRet = TRUE;

#if (NAND_DEBUG)
	RETAILMSG(1, (TEXT("[FMD] ++FMD_WriteSector(0x%08x) \r\n"), startSectorAddr));
#endif

#ifdef	SYNC_OP
	EnterCriticalSection(&g_csNandFlash);
#endif

	if ( IS_LB )
	{
		bRet = FMD_LB_WriteSector(startSectorAddr, pSectorBuff, pSectorInfoBuff, dwNumSectors, USE_NFCE);
	}
	else
	{
		bRet = FMD_SB_WriteSector(startSectorAddr, pSectorBuff, pSectorInfoBuff, dwNumSectors, USE_NFCE);
	}

#ifdef	SYNC_OP
	LeaveCriticalSection(&g_csNandFlash);
#endif

#if (NAND_DEBUG)
	RETAILMSG(1, (TEXT("[FMD] --FMD_WriteSector()\r\n")));
#endif

	return bRet;
}


VOID FMD_PowerUp(VOID)
{
#if (NAND_DEBUG)
	RETAILMSG(1, (TEXT("[FMD] FMD_PowerUp() \r\n")));
#endif

	// Set up initial flash controller configuration.
	g_pNFConReg->NFCONF = (TACLS<<12) | (TWRPH0<<8) | (TWRPH1<<4);
	g_pNFConReg->NFCONT = (0<<17)|(0<<16)|(0<<10)|(0<<9)|(0<<8)|(1<<7)|(1<<6)|(1<<5)|(1<<4)|(0x3<<1)|(1<<0);
	g_pNFConReg->NFSTAT = (1<<4);
}


VOID FMD_PowerDown(VOID)
{
#if (NAND_DEBUG)
	RETAILMSG(1, (TEXT("[FMD] FMD_PowerDown() \r\n")));
#endif

}


BOOL FMD_OEMIoControl(DWORD dwIoControlCode, PBYTE pInBuf, DWORD nInBufSize, PBYTE pOutBuf, DWORD nOutBufSize, PDWORD pBytesReturned)
{
	switch(dwIoControlCode)
	{
		case IOCTL_FMD_GET_INTERFACE:
		{
			RETAILMSG(1, (TEXT("[FMD] FMD_OEMIoControl() : IOCTL_FMD_GET_INTERFACE\r\n")));

			if (!pOutBuf || nOutBufSize < sizeof(FMDInterface))
			{
				DEBUGMSG(1, (TEXT("FMD_OEMIoControl: IOCTL_FMD_GET_INTERFACE bad parameter(s).\r\n")));
				return(FALSE);
			}

			PFMDInterface pInterface = (PFMDInterface)pOutBuf;

			pInterface->cbSize = sizeof(FMDInterface);
			pInterface->pInit = FMD_Init;
			pInterface->pDeInit = FMD_Deinit;
			pInterface->pGetInfo = FMD_GetInfo;
			pInterface->pGetInfoEx = NULL;		//FMD_GetInfoEx;
			pInterface->pGetBlockStatus = FMD_GetBlockStatus;
			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;
		}

	case IOCTL_FMD_LOCK_BLOCKS:
		RETAILMSG(1, (TEXT("[FMD:ERR] FMD_OEMIoControl() : IOCTL_FMD_LOCK_BLOCKS Not Supported\r\n")));
		return FALSE;

	case IOCTL_FMD_UNLOCK_BLOCKS:
		RETAILMSG(1, (TEXT("[FMD:ERR] FMD_OEMIoControl() : IOCTL_FMD_UNLOCK_BLOCKS Not Supported\r\n")));
		return FALSE;

	case IOCTL_FMD_READ_RESERVED:
		RETAILMSG(1, (TEXT("[FMD:ERR] FMD_OEMIoControl() : IOCTL_FMD_READ_RESERVED\r\n")));
		return FALSE;

	case IOCTL_FMD_WRITE_RESERVED:
		RETAILMSG(1, (TEXT("[FMD:ERR] FMD_OEMIoControl() : IOCTL_FMD_WRITE_RESERVED\r\n")));
		return FALSE;

	case IOCTL_FMD_GET_RESERVED_TABLE:
		RETAILMSG(1, (TEXT("[FMD:ERR] FMD_OEMIoControl() : IOCTL_FMD_GET_RESERVED_TABLE\r\n")));
		return FALSE;

	case IOCTL_FMD_SET_REGION_TABLE:
		RETAILMSG(1, (TEXT("[FMD:ERR] FMD_OEMIoControl() : IOCTL_FMD_SET_REGION_TABLE\r\n")));
		return FALSE;

	case IOCTL_FMD_SET_SECTORSIZE:
		RETAILMSG(1, (TEXT("[FMD:ERR] FMD_OEMIoControl() : IOCTL_FMD_SET_SECTORSIZE\r\n")));
		return FALSE;

	case IOCTL_FMD_RAW_WRITE_BLOCKS:
		RETAILMSG(1, (TEXT("[FMD:ERR] FMD_OEMIoControl() : IOCTL_FMD_RAW_WRITE_BLOCKS\r\n")));
		return FALSE;

	case IOCTL_FMD_GET_RAW_BLOCK_SIZE:
		RETAILMSG(1, (TEXT("[FMD:ERR] FMD_OEMIoControl() : IOCTL_FMD_GET_RAW_BLOCK_SIZE\r\n")));
		return FALSE;

	case IOCTL_FMD_GET_INFO:
		RETAILMSG(1, (TEXT("[FMD:ERR] FMD_OEMIoControl() : IOCTL_FMD_GET_INFO\r\n")));
		return FALSE;

	case  IOCTL_FMD_SET_XIPMODE	:
		RETAILMSG(1, (TEXT("[FMD:ERR] FMD_OEMIoControl() : IOCTL_FMD_SET_XIPMODE\r\n")));
		return FALSE;

	case  IOCTL_FMD_GET_XIPMODE:
		RETAILMSG(1, (TEXT("[FMD:ERR] FMD_OEMIoControl() : IOCTL_FMD_GET_XIPMODE\r\n")));
		return FALSE;

	case  IOCTL_DISK_FLUSH_CACHE:
		//RETAILMSG(1, (TEXT("[FMD:ERR] FMD_OEMIoControl() : IOCTL_DISK_FLUSH_CACHE\r\n")));
		return TRUE;

	default:
		RETAILMSG(1, (TEXT("[FMD:ERR] FMD_OEMIoControl() : Unknown IOCTL (0x%08x)\r\n"), dwIoControlCode));
		return FALSE;
	}

	return TRUE;
}

BOOL FMD_Deinit(PVOID hFMD)
{
#if (NAND_DEBUG)
	RETAILMSG(1, (TEXT("[FMD] FMD_Deinit() \r\n")));
#endif

	return(TRUE);
}


/*
    @func   BOOL | FMD_GetInfo | Provides information on the NAND flash.
    @rdesc  TRUE = Success, FALSE = Failure.
    @comm
    @xref
*/
BOOL FMD_GetInfo(PFlashInfo pFlashInfo)
{
	UINT32  nCnt;
	UINT32 nNandID;
	UINT8 nMID, nDID;

	if (pFlashInfo == NULL)
	{
		RETAILMSG(1, (TEXT("[FMD:ERR] FMD_GetInfo() : Invalid Parameter\r\n")));
		return(FALSE);
	}

	pFlashInfo->flashType = NAND;

#ifdef	SYNC_OP
	EnterCriticalSection(&g_csNandFlash);
#endif

	nNandID = ReadFlashID();

#ifdef	SYNC_OP
	LeaveCriticalSection(&g_csNandFlash);
#endif

	nMID = nNandID >> 8;
	nDID = nNandID & 0xff;

	for (nCnt = 0; astNandSpec[nCnt].nMID != 0; nCnt++)
	{
		if (nDID == astNandSpec[nCnt].nDID)
		{
			break;
		}
	}

	//  OK, instead of reading it from the chip, we use the hardcoded
	//  numbers here.

	pFlashInfo->dwNumBlocks         = NUM_OF_BLOCKS;
	pFlashInfo->wSectorsPerBlock    = PAGES_PER_BLOCK;
	pFlashInfo->wDataBytesPerSector = NAND_SECTOR_SIZE;
	pFlashInfo->dwBytesPerBlock     = (PAGES_PER_BLOCK * NAND_SECTOR_SIZE);

	RETAILMSG(1, (TEXT("[FMD] FMD_GetInfo() : 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));

	return TRUE;
}


/*
    @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;

#if (NAND_DEBUG)
	RETAILMSG(1, (TEXT("[FMD] ++FMD_GetBlockStatus(0x%08x) \r\n"), blockID));
#endif

#ifdef	SYNC_OP
	EnterCriticalSection(&g_csNandFlash);
#endif

	if ( IS_LB )
	{
		dwResult = FMD_LB_GetBlockStatus(blockID, USE_NFCE);
	}
	else
	{
		dwResult = FMD_SB_GetBlockStatus(blockID, USE_NFCE);
	}

#ifdef	SYNC_OP
	LeaveCriticalSection(&g_csNandFlash);
#endif

#if (NAND_DEBUG)
	RETAILMSG(1, (TEXT("[FMD] --FMD_GetBlockStatus()\r\n")));
#endif

	return dwResult;
}


/*
    @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;

#if (NAND_DEBUG)
	RETAILMSG(1, (TEXT("[FMD] ++FMD_SetBlockStatus(0x%08x, 0x%08x) \r\n"), blockID, dwStatus));
#endif

#ifdef	SYNC_OP
	EnterCriticalSection(&g_csNandFlash);
#endif

	if ( IS_LB )
	{
		bRet = FMD_LB_SetBlockStatus(blockID, dwStatus, USE_NFCE);
	}
	else
	{
		bRet = FMD_SB_SetBlockStatus(blockID, dwStatus, USE_NFCE);
	}

#ifdef	SYNC_OP
	LeaveCriticalSection(&g_csNandFlash);
#endif

#if (NAND_DEBUG)
	RETAILMSG(1, (TEXT("[FMD] --FMD_SetBlockStatus()\r\n")));
#endif

	return bRet;
}

BOOL ECC_CorrectData(SECTOR_ADDR sectoraddr, LPBYTE pData, UINT32 nRetEcc, ECC_CORRECT_TYPE nType)
{
	DWORD  nErrStatus;
	DWORD  nErrDataNo;
	DWORD  nErrBitNo;
	UINT32 nErrDataMask;
	UINT32 nErrBitMask = 0x7;
	BOOL bRet = TRUE;

	//RETAILMSG(1, (TEXT("#### FMD_DRIVER:::ECC_CorrectData %x, %x, %x\r\n"), sectoraddr, nRetEcc, nType));

	if (nType == ECC_CORRECT_MAIN)
	{
		nErrStatus   = 0;
		nErrDataNo   = 7;
		nErrBitNo    = 4;
		nErrDataMask = 0x7ff;
	}
	else if (nType == ECC_CORRECT_SPARE)
	{
		nErrStatus   = 2;
		nErrDataNo   = 21;
		nErrBitNo    = 18;
		nErrDataMask = 0xf;
	}
	else
	{
		return FALSE;
	}

	switch((nRetEcc>>nErrStatus) & 0x3)
	{

⌨️ 快捷键说明

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