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

📄 fmd.cpp

📁 S3C2443 WINCE6.0 BSP
💻 CPP
📖 第 1 页 / 共 4 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
#include <fmd.h>
#include <s3c2443_nand.h>
#include <args.h>
#include <ethdbg.h>
#include "Cfnand.h"
#define IO_INDICATE 0
#if IO_INDICATE==1
#include <s3c2443_ioport.h>	//DonGo
#endif //IO_INDICATE 
#include "image_cfg.h"

#define NAND_BASE 0xB1400000	// PA:0x4e00_0000
#if IO_INDICATE==1
#define IOPORT_BASE	0xB2100000	// PA:0x56000000 //DonGo
#endif //IO_INDICATE 
BOOL NEED_EXT_ADDR = TRUE;

static volatile S3C2443_NAND_REG *s2443NAND = (S3C2443_NAND_REG *)NAND_BASE;
#if IO_INDICATE==1
static volatile S3C2443_IOPORT_REG *s2443IOPORT = (S3C2443_IOPORT_REG *)IOPORT_BASE; //DonGo
#endif //IO_INDICATE 

#if MAGNETO
BSP_ARGS *pBSPArgs;
#endif

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

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

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

	NF_ADDR(0);							//

	Mfg	= NF_RDDATA_BYTE();				// 
	Dev	= NF_RDDATA_BYTE();				// 
	
	NF_nFCE_H();						// Deselect the flash chip.
	
	return ((DWORD)(Mfg<<8)+Dev);
}

/*
	@func   PVOID | FMD_Init | Initializes the Smart Media NAND flash controller.
	@rdesc  Pointer to S3C2443 NAND controller registers.
	@comm	
	@xref   
*/
PVOID FMD_Init(LPCTSTR lpActiveReg, PPCI_REG_INFO pRegIn, PPCI_REG_INFO pRegOut)
{

	// Caller should have specified NAND controller address.
	//

	//BOOL bLastMode = SetKMode(TRUE);
	volatile DWORD rdid;

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

#if MAGNETO
	pBSPArgs = ((BSP_ARGS *) IMAGE_SHARE_ARGS_UA_START);
#endif

	if (pRegIn && pRegIn->MemBase.Num && pRegIn->MemBase.Reg[0])
		s2443NAND = (S3C2443_NAND_REG *)(pRegIn->MemBase.Reg[0]);
	else
		s2443NAND = (S3C2443_NAND_REG *)NAND_BASE;

#if IO_INDICATE==1
s2443IOPORT = (S3C2443_IOPORT_REG *)IOPORT_BASE;	//DonGo
s2443IOPORT->GPGCON = (s2443IOPORT->GPGCON & ~(0x3<<2)) | (0x1<<2); // GPG1 //DonGo
//s2443IOPORT->DSC1 = (s2443IOPORT->DSC1 & ~(0x3<<10)) | (0x3<<10); // Drive strength
#endif 
	// Set up initial flash controller configuration.
	//
	s2443NAND->NFCONF =  (TACLS  <<  12) | /* CLE & ALE = HCLK * (TACLS  + 1)   */
							(TWRPH0 <<  8) | /* TWRPH0	= HCLK * (TWRPH0 + 1)   */
							(TWRPH1 <<  4);
	s2443NAND->NFCONT = (0<<17)|(0<<16)|(0<<10)|(0<<9)|(0<<8)|(1<<7)|(1<<6)|(1<<5)|(1<<4)|(0x3<<1)|(1<<0);
	s2443NAND->NFSTAT = (1<<4);

	RETAILMSG(1, (TEXT("NAND Read ID...")));
/*	
	NF_CLEAR_RB();
	NF_nFCE_L();						// Select the flash chip.
	NF_CLEAR_RB();
	NF_CMD(CMD_RESET);					// Send reset command.
	//for(volatile int i=0; i<30; i++);
	NF_DETECT_RB();						// Wait for flash to complete command.
	NF_nFCE_H();						// Deselect the flash chip.
*/
	// Get manufacturer and device codes.
	rdid = ReadFlashID();
	if (rdid != 0xEC76 && rdid!= 0x9876 && rdid!=0x9879 && rdid!=0xecda && rdid!=0x987e )	
	// 0xec76: SOP, 0x9876:64MB XD, 0x9879:64MB XD, 0x987e:64MB XD, 0xecda:256MB SOP
	{
		RETAILMSG(1, (TEXT("Error!!!(%x)\n"), rdid));
		//NF_nFCE_H();					// Deselect the flash chip.
		//SetKMode (bLastMode);
		return(NULL);
	}
	else
	{
		RETAILMSG(1, (TEXT("OK(%x).\n"), rdid));
	}

	//SetKMode (bLastMode);

	return((PVOID)s2443NAND);
}


/*
	@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("FMD::FMD_ReadSector 0x%x \r\n"), startSectorAddr));

	if ( startSectorAddr < (unsigned)wPRIMARY_NAND_BLOCKS*NAND_PAGE_CNT )
	{
		if ( astNandSpec[dwPrimaryNandDevice].nSctsPerPg == 4 )
			bRet = FMD_LB_ReadSector(startSectorAddr, pSectorBuff, pSectorInfoBuff, dwNumSectors, USE_NFCE);
		else
			bRet = FMD_SB_ReadSector(startSectorAddr, pSectorBuff, pSectorInfoBuff, dwNumSectors, USE_NFCE);
	}
	else
	{
		if ( astNandSpec[dwSecondaryNandDevice].nSctsPerPg == 4 )
			bRet = FMD_LB_ReadSector(startSectorAddr-wPRIMARY_NAND_BLOCKS*NAND_PAGE_CNT, pSectorBuff, pSectorInfoBuff, dwNumSectors, USE_GPIO);
		else
			bRet = FMD_SB_ReadSector(startSectorAddr-wPRIMARY_NAND_BLOCKS*NAND_PAGE_CNT, pSectorBuff, pSectorInfoBuff, dwNumSectors, USE_GPIO);
	}

//	RETAILMSG(1, (TEXT("FMD::FMD_ReadSector -- \r\n")));

	return bRet;
}


BOOL FMD_WriteSector(SECTOR_ADDR startSectorAddr, LPBYTE pSectorBuff, PSectorInfo pSectorInfoBuff,
                        DWORD dwNumSectors)
{
    BOOL    bRet = TRUE;

//	RETAILMSG(1, (TEXT("FMD::FMD_WriteSector 0x%x \r\n"), startSectorAddr));

	if ( startSectorAddr < (unsigned)wPRIMARY_NAND_BLOCKS*NAND_PAGE_CNT )
	{
		if ( astNandSpec[dwPrimaryNandDevice].nSctsPerPg == 4 )
			bRet = FMD_LB_WriteSector(startSectorAddr, pSectorBuff, pSectorInfoBuff, dwNumSectors, USE_NFCE);
		else
			bRet = FMD_SB_WriteSector(startSectorAddr, pSectorBuff, pSectorInfoBuff, dwNumSectors, USE_NFCE);
	}
	else	// if ( PRIMARY_NAND == SMALL_BLOCK_NAND )
	{
		if ( astNandSpec[dwSecondaryNandDevice].nSctsPerPg == 4 )
			bRet = FMD_LB_WriteSector(startSectorAddr-wPRIMARY_NAND_BLOCKS*NAND_PAGE_CNT, pSectorBuff, pSectorInfoBuff, dwNumSectors, USE_GPIO);
		else
			bRet = FMD_SB_WriteSector(startSectorAddr-wPRIMARY_NAND_BLOCKS*NAND_PAGE_CNT, pSectorBuff, pSectorInfoBuff, dwNumSectors, USE_GPIO);
	}

    return bRet;
}

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

//	RETAILMSG(1, (TEXT("FMD::FMD_EraseBlock 0x%x \r\n")));
	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_EraseBlock(blockID*(LB_BLOCK_LOOP) + i, USE_NFCE);
				if ( bRet == FALSE ) break;
			}
		}
		else
		{
			for ( i = 0; i < SB_BLOCK_LOOP; i++ )
			{
				bRet = FMD_SB_EraseBlock(blockID*(SB_BLOCK_LOOP) + i, USE_NFCE);
				if ( bRet == FALSE ) break;
			}
		}
	}
	else
	{
		if ( astNandSpec[dwSecondaryNandDevice].nSctsPerPg == 4 )
		{
			for ( i = 0; i < LB_BLOCK_LOOP; i++ )
			{
				bRet = FMD_LB_EraseBlock((blockID-wPRIMARY_NAND_BLOCKS)*(LB_BLOCK_LOOP) + i, USE_GPIO);
				if ( bRet == FALSE ) break;
			}
		}
		else
		{
			for ( i = 0; i < SB_BLOCK_LOOP; i++ )
			{
				bRet = FMD_SB_EraseBlock(blockID*(SB_BLOCK_LOOP) + i, USE_GPIO);
				if ( bRet == FALSE ) break;
			}
		}
	}

    return bRet;
}



VOID FMD_PowerUp(VOID)
{
	// Set up initial flash controller configuration.
	//
	s2443NAND->NFCONF =  (TACLS  <<  12) | /* CLE & ALE = HCLK * (TACLS  + 1)   */
						 (TWRPH0 <<  8) | /* TWRPH0	= HCLK * (TWRPH0 + 1)   */
						 (TWRPH1 <<  4);

	s2443NAND->NFCONT = (0<<17)|(0<<16)|(0<<10)|(0<<9)|(0<<8)|(1<<7)|(1<<6)|(1<<5)|(1<<4)|(0x3<<1)|(1<<0);
	s2443NAND->NFSTAT = (1<<4);
}


VOID FMD_PowerDown(VOID)
{
}

//  FMD_OEMIoControl
//
//  Used for any OEM defined IOCTL operations
//
BOOL  FMD_OEMIoControl(DWORD dwIoControlCode, PBYTE pInBuf, DWORD nInBufSize,
                       PBYTE pOutBuf, DWORD nOutBufSize, PDWORD pBytesReturned)
{
    BSP_ARGS *pBSPArgs = ((BSP_ARGS *) IMAGE_SHARE_ARGS_UA_START);
	BlockLockInfo * pLockInfo;
	
	RETAILMSG(1,(TEXT("#### FMD_DRIVER:::FMD_OEMIoControl \r\n")));

    switch(dwIoControlCode)
    {
	    case IOCTL_FMD_GET_INTERFACE:
	    {
	    	   RETAILMSG(1, (TEXT("FMD_OEMIoControl: IOCTL_FMD_GET_INTERFACE \r\n")));
	            
	        if (!pOutBuf || nOutBufSize < sizeof(FMDInterface))
	        {
	            RETAILMSG(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;        
#if defined (MAGNETO)
//	        pInterface->pGetInfoEx = FMD_GetInfoEx;
#endif
	        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:
			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("S3C2443 Does not support IOCTL_FMD_UNLOCK_BLOCKS !!!! \r\n")));
	        return(FALSE);
			/*
			pLockInfo = (BlockLockInfo *)pInBuf;
			RETAILMSG(1, (TEXT("IOCTL_FMD_UNLOCK_BLOCKS!!!!(0x%x,0x%x) \r\n"), pLockInfo->StartBlock, pLockInfo->NumBlocks));

			if ( astNandSpec[dwPrimaryNandDevice].nSctsPerPg == 4 )		// Large Block
			{
				if ( READ_REGISTER_BYTE(pNFSBLK) >> 5 > (ULONG)(pLockInfo->StartBlock - 1) )
					WRITE_REGISTER_USHORT(pNFSBLK, (pLockInfo->StartBlock - 1)<<5 );
			}
			else	// Small Block
			{
				if ( READ_REGISTER_BYTE(pNFSBLK) >> 5 > (ULONG)(pLockInfo->StartBlock - 1)*8 )
					WRITE_REGISTER_USHORT(pNFSBLK, ((ULONG)(pLockInfo->StartBlock - 1)*8)<<5 );
			}
			pBSPArgs->nfsblk = pLockInfo->StartBlock - 1;
			*/

			break;
			
		case IOCTL_FMD_READ_RESERVED:
			RETAILMSG(1,(TEXT("IOCTL_FMD_READ_RESERVED\r\n")));
			return(FALSE);	
			break;
		case IOCTL_FMD_WRITE_RESERVED:
			RETAILMSG(1,(TEXT("IOCTL_FMD_WRITE_RESERVED\r\n")));
			return(FALSE);	
			break;
		case IOCTL_FMD_GET_RESERVED_TABLE:
			RETAILMSG(1,(TEXT("IOCTL_FMD_GET_RESERVED_TABLE\r\n")));
			return(FALSE);	
			break;
		case IOCTL_FMD_SET_REGION_TABLE:
			RETAILMSG(1,(TEXT("IOCTL_FMD_SET_REGION_TABLE\r\n")));
			return(FALSE);	
			break;
		case IOCTL_FMD_SET_SECTORSIZE:
			RETAILMSG(1,(TEXT("IOCTL_FMD_SET_SECTORSIZE\r\n")));
			return(FALSE);	
			break;			
		case IOCTL_FMD_RAW_WRITE_BLOCKS:
			RETAILMSG(1,(TEXT("IOCTL_FMD_RAW_WRITE_BLOCKS\r\n")));
			return(FALSE);	
			break;	
		case IOCTL_FMD_GET_RAW_BLOCK_SIZE:
			RETAILMSG(1,(TEXT("IOCTL_FMD_GET_RAW_BLOCK_SIZE\r\n")));
			return(FALSE);	
			break;	
		case IOCTL_FMD_GET_INFO:
			RETAILMSG(1,(TEXT("IOCTL_FMD_GET_INFO\r\n")));
			return(FALSE);	
			break;	
																					
	    default:
	        RETAILMSG(1, (TEXT("FMD_OEMIoControl: unrecognized IOCTL (0x%x).\r\n"), dwIoControlCode));
	        return(FALSE);
    }

    return TRUE; 
}

BOOL FMD_Deinit(PVOID hFMD)
{
	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)
        return(FALSE);
	//BOOL bLastMode = SetKMode(TRUE); // for READFlashID();

    pFlashInfo->flashType = NAND;

	nNandID = ReadFlashID();

	nMID = nNandID >> 8;
	nDID = nNandID & 0xff;
	
    for (nCnt = 0; astNandSpec[nCnt].nMID != 0; nCnt++)
    {
        if (nDID == astNandSpec[nCnt].nDID)
        {
            break;
        }
    }

	dwPrimaryNandDevice = nCnt;
	wPRIMARY_REAL_NAND_BLOCKS = astNandSpec[dwPrimaryNandDevice].nNumOfBlks;
	wSECONDARY_NAND_BLOCKS = 0;
	wSECONDARY_REAL_NAND_BLOCKS = 0;

//	RETAILMSG(1, (TEXT("dwPrimaryNandDevice : %d(0x%x) \r\n"), dwPrimaryNandDevice, dwPrimaryNandDevice));
//	RETAILMSG(1, (TEXT("astNandSpec[dwPrimaryNandDevice].nSctsPerPg: %d(0x%x) \r\n"), astNandSpec[dwPrimaryNandDevice].nSctsPerPg, astNandSpec[dwPrimaryNandDevice].nSctsPerPg));
//	RETAILMSG(1, (TEXT("wPRIMARY_REAL_NAND_BLOCKS : %d(0x%x) \r\n"), wPRIMARY_REAL_NAND_BLOCKS, wPRIMARY_REAL_NAND_BLOCKS));

	if ( astNandSpec[dwPrimaryNandDevice].nSctsPerPg == 4 )	// Primary NAND is Large Block...
	{
		wPRIMARY_NAND_BLOCKS = wPRIMARY_REAL_NAND_BLOCKS;
	}
	else
	{
		wPRIMARY_NAND_BLOCKS = wPRIMARY_REAL_NAND_BLOCKS / 8;
	}
	wNUM_BLOCKS = wPRIMARY_NAND_BLOCKS + wSECONDARY_NAND_BLOCKS;

⌨️ 快捷键说明

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