📄 fmd.cpp
字号:
//
// 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 <s2440.h>
#include "cfnand.h"
#include <ethdbg.h>
#include <ceddk.h>
#include <Winreg.h>
#include <ddkreg.h>
#include <CRegEdit.h>
#include <drv_glob.h>//Added by Sky Xu to Control WinCE shut down on Jan 15
//#include <ethdbg.h>
//#if K9F1G08
//#define ADVANC 1
//#else
//#define ADVANC 0
//#endif
#define NAND_BASE 0xB4E00000
#define CLKPWR_BASE 0xB4C00000
#define INT_BASE 0xB4A00000 // 0x4A000000
#define DMA_BASE 0xB4B00000 // 0x4B0000000
//20080124 add nand flash driver
//static volatile S3C2440X_NAND_REG *s2440NAND = (S3C2440X_NAND_REG *)NAND_BASE;
//static volatile S3C2440X_CLKPWR_REG *s2440CLKPWR = (S3C2440X_CLKPWR_REG *)CLKPWR_BASE;
static volatile NANDreg *s2440NAND = (NANDreg *)NAND_BASE;
static volatile CLKPWRreg *s2440CLKPWR = (CLKPWRreg *)CLKPWR_BASE;
static volatile INTreg *s2440INT = (INTreg *)INT_BASE;
static volatile DMAreg *s2440DMAregs = (DMAreg *)DMA_BASE;
//20080124 by yqx
//added by yangrui 20080414
#define C_LANG 1
#define DMA 2
#define TRANS_MODE C_LANG
typedef struct _NAND_FLASH_PARTITION_INFO
{
ULONG PartitionStartBlock;
ULONG PartitionStartSector;
ULONG TotalPartitionBlocks;
ULONG TotalPartitionSector;
ULONG SectorsPerBlock;
ULONG wDataBytesPerSector;
ULONG BlockSize;
} NAND_FLASH_PARTITION_INFO, *PNAND_FLASH_PARTITION_INFO;
#define PC_REG_NAND_BLOCK_START_NAME128 (TEXT("NandStartBlock"))
#define PC_REG_NAND_BLOCK_START_LEN128 4
#define PC_REG_NAND_BLOCK_SIZE_NAME128 (TEXT("BlockNumber"))
#define PC_REG_NAND_BLOCK_SIZE_LEN128 4
static DWORD g_dwPartitionStartBlock;
static DWORD g_dwPartitionBlockNumber;
static NAND_FLASH_PARTITION_INFO NandPartitionInfo;
//for solve the Hive Register Block return false
static DWORD Register_Start_Block=260;
static DWORD Register_End_Block=275;
//added 20080414 end
#if (TRANS_MODE == DMA)
//added 20080416 for DMA
static PHYSICAL_ADDRESS phyAddr;
static LPBYTE pVirDMAbuf;
static LPBYTE pPhyDMAbuffer;
#define NFDATA 0x4E000010
#endif
//added by yangrui 20080603 for Mutex
static HANDLE g_hMutex = NULL;
void GRABMUTEX();
void RELEASEMUTEX();
//added 20080603 end
// External function
extern "C" {
BOOL ECC_CorrectData2048(LPBYTE pData, LPBYTE pExistingECC, LPBYTE pNewECC);
}
//20080229 by yqx
//#if K9F1G08
//void RdPage2048(unsigned char *bufPt,PULONG pReg);
extern "C" void RdPage2048(unsigned char *bufPt,PULONG pReg);
extern "C" void RdPage2048Unalign(unsigned char *bufPt,PULONG pReg);
extern "C" void WrPage2048(unsigned char *bufPt,PULONG pReg);
extern "C" void WrPage2048Unalign(unsigned char *bufPt,PULONG pReg);
BOOL FMD_ReadSector1G08(SECTOR_ADDR startSectorAddr, LPBYTE pSectorBuff, PSectorInfo pSectorInfoBuff, DWORD dwNumSectors);
BOOL FMD_WriteSector1G08(SECTOR_ADDR startSectorAddr, LPBYTE pSectorBuff, PSectorInfo pSectorInfoBuff, DWORD dwNumSectors);
BOOL FMD_EraseBlock1G08(BLOCK_ID blockID);
static BOOL IsBlockBad1G08(BLOCK_ID blockID);
static BOOL MarkBlockBad1G08(BLOCK_ID blockID);
typedef BOOL (*PFN_READSECTOR)(SECTOR_ADDR startSectorAddr, LPBYTE pSectorBuff, PSectorInfo pSectorInfoBuff, DWORD dwNumSectors);
typedef BOOL (*PFN_WRITESECTOR)(SECTOR_ADDR startSectorAddr, LPBYTE pSectorBuff, PSectorInfo pSectorInfoBuff, DWORD dwNumSectors);
typedef BOOL (*PFN_ERASEBLOCK)(BLOCK_ID blockID);
typedef BOOL (*PFN_ISBLOCKBAD)(BLOCK_ID blockID);
typedef BOOL (*PFN_MARKBLOCKBAD)(BLOCK_ID blockID);
typedef struct {
DWORD FlashID;
BOOL is16BitSize;
FlashInfo tFlashInfo;
PFN_READSECTOR pReadSector;
PFN_WRITESECTOR pWriteSector;
PFN_ERASEBLOCK pEraseBlock;
PFN_ISBLOCKBAD pIsBlockBad;
PFN_MARKBLOCKBAD pMarkBlockBad;
}NAND_Flash_Chip_t;
NAND_Flash_Chip_t g_NandFlash_Chip_set[]={
#if (K9F1G08_SUPPORT)
{0xECF1,/*K9F1G08U0M*/
FALSE,
{NAND,1024,2048*64,64,2048},
FMD_ReadSector1G08,
FMD_WriteSector1G08,
FMD_EraseBlock1G08,
IsBlockBad1G08,
MarkBlockBad1G08
},
#endif
#if K9F2G08_SUPPORT
{0xECDA,/*K9F2G08U0M*/
FALSE,
{NAND,2048,2048*64,64,2048},
FMD_ReadSector1G08,
FMD_WriteSector1G08,
FMD_EraseBlock1G08,
IsBlockBad1G08,
MarkBlockBad1G08
},
{0xECAA,/*K9F2G08Q0M*/
FALSE,
{NAND,2048,2048*64,64,2048},
FMD_ReadSector1G08,
FMD_WriteSector1G08,
FMD_EraseBlock1G08,
IsBlockBad1G08,
MarkBlockBad1G08
},
#endif
{
0,0,{NAND,0,0,0,0},NULL,NULL,NULL,NULL,NULL
}
};
NAND_Flash_Chip_t *g_pNandFlashChip=g_NandFlash_Chip_set;
#define FLASH_CHIP_COUNTS sizeof(g_NandFlash_Chip_set)/sizeof(NAND_Flash_Chip_t)
//added by yangrui 20080603 for Mutex
void GRABMUTEX()
{
// we can do a normal WaitForSingleObject
WaitForSingleObject(g_hMutex, INFINITE);
}
void RELEASEMUTEX()
{
ReleaseMutex(g_hMutex);
}
//added 20080603 end
void NF_Reset()
{
int i;
GRABMUTEX();
NF_nFCE_L();
NF_CLEAR_RB();
NF_CMD(CMD_RESET);
for(i=0;i<10;i++); //tWB = 100ns. //??????
NF_DETECT_RB();
NF_nFCE_H();
RELEASEMUTEX();
}
/*
@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;
GRABMUTEX();
NF_nFCE_L();
NF_WAITRnB();
// NF_CLEAR_RB();
NF_CMD(CMD_READID); // Send flash ID read command.
NF_ADDR(0); //
for (i=0; i<1000; i++);
// NF_DETECT_RB(); // Wait tR(max 12us)
Mfg = NF_RDDATA(); //
Dev = NF_RDDATA(); //
NF_nFCE_H();
RETAILMSG(0,(TEXT("FMD: ReadID (Mfg=%x, Dev=%x)\r\n"), Mfg, Dev));
RELEASEMUTEX();
return ((DWORD)Mfg*0x100+Dev);
}
/*
@func PVOID | FMD_Init | Initializes the Smart Media NAND flash controller.
@rdesc Pointer to S3C2440 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.
//
int i;
DWORD FlashId;
//added by yangrui 20080414
CRegistryEdit RegEdit(lpActiveReg);
//added 20080414 end
//Added by Sky Xu to shut down WinCE safe on Jan 19.2009 -Start
PELITE_GLOBALS peliteGlobal=NULL;
peliteGlobal = (PELITE_GLOBALS)(DRIVER_GLOBALS_PHYSICAL_MEMORY_START+ (DWORD)(&((PDRIVER_GLOBALS)0)->elite));
peliteGlobal->Control_ShutDown_WinCE = TRUE;
//Added by Sky Xu to shut down WinCE safe on Jan 19.2009 -End
if (g_hMutex == NULL)
{
g_hMutex = CreateMutex(NULL, FALSE, TEXT("_FLASH_MUTEX_"));
// was mutex creation successful?
if (g_hMutex == NULL)
{
RETAILMSG(1,(TEXT("FlashDrv!FMD!FMD_Init: Unable to create mutex\r\n")));
return(NULL);
}
}
RETAILMSG(0,(TEXT("FlashDrv!FMD!FMD_Init:Create Mutex Success!!\r\n")));
//added by yangrui 20080416 for DMA
#if (TRANS_MODE == DMA)
DMA_ADAPTER_OBJECT DmaAdapter;
int nBufferSize;
#endif
//added 20080416 end
GRABMUTEX(); //anywhere we set nand register should Mutex
// Enable the clock to NAND controller
s2440CLKPWR->rCLKCON |= (1<<4);
// Set up initial flash controller configuration.
//
s2440NAND->rNFCONF = (TACLS << 12) | /* CLE & ALE = HCLK * (TACLS) */
(TWRPH0 << 8) | /* TWRPH0 = HCLK * (TWRPH0 + 1) */
(TWRPH1 << 4) ; /* TWRPH1 = HCLK * (TWRPH1 + 1) */
s2440NAND->rNFCONT = (0<<13)|(0<<12)|(0<<10)|(0<<9)|(0<<8)|(0<<6)|(0<<5)|(1<<4)|(1<<1)|(1<<0);
s2440NAND->rNFSTAT = 0;
RELEASEMUTEX();
// NF_Reset(); //deleted 20080807
for(i=0;i<100;i++); //tWB = 100ns. //??????
// NF_DETECT_RB();
FlashId = ReadFlashID();
// Get manufacturer and device codes.
for(i=0;i<FLASH_CHIP_COUNTS;i++)
{
if (FlashId == g_pNandFlashChip->FlashID)
{
break;
}
g_pNandFlashChip++;
}
GRABMUTEX();
s2440NAND->rNFCONF|=(g_pNandFlashChip->is16BitSize);
RELEASEMUTEX();
/*added by yangrui 20080414*/
if(!RegEdit.GetRegValue(PC_REG_NAND_BLOCK_START_NAME128, (LPBYTE)&g_dwPartitionStartBlock, PC_REG_NAND_BLOCK_START_LEN128))
{
RETAILMSG(1,(TEXT("\r\nFMD_Init,get g_dwBaseAddress failed!!\r\n")));
return(NULL);
}
if(!RegEdit.GetRegValue(PC_REG_NAND_BLOCK_SIZE_NAME128, (LPBYTE)&g_dwPartitionBlockNumber, PC_REG_NAND_BLOCK_SIZE_LEN128))
{
RETAILMSG(1,(TEXT("\r\nFMD_Init,get g_dwFlashLength failed!!\r\n")));
return(NULL);
}
RETAILMSG(1,(TEXT("FMD_Init,g_dwPartitionStartBlock=%d,g_dwPartitionBlockNumber=%d!!\r\n"),g_dwPartitionStartBlock,g_dwPartitionBlockNumber));
NandPartitionInfo.PartitionStartBlock = g_dwPartitionStartBlock;
NandPartitionInfo.TotalPartitionBlocks = g_dwPartitionBlockNumber;
NandPartitionInfo.SectorsPerBlock = NAND_PAGE_CNT;
NandPartitionInfo.PartitionStartSector = (NandPartitionInfo.PartitionStartBlock) * (NandPartitionInfo.SectorsPerBlock);
NandPartitionInfo.TotalPartitionSector = (NandPartitionInfo.TotalPartitionBlocks) * (NandPartitionInfo.SectorsPerBlock);
NandPartitionInfo.wDataBytesPerSector = NAND_PAGE_SIZE;
NandPartitionInfo.BlockSize = (NandPartitionInfo.SectorsPerBlock) * (NandPartitionInfo.wDataBytesPerSector);
/*added 20080414 end*/
#if (TRANS_MODE == DMA)
//added by yangrui 20080416 for DMA
DmaAdapter.ObjectSize = sizeof(DMA_ADAPTER_OBJECT);
DmaAdapter.InterfaceType = Internal; //Bus;
DmaAdapter.BusNumber = 0;
nBufferSize = 2048; //buffer size is a page size
pVirDMAbuf = (LPBYTE)HalAllocateCommonBuffer(&DmaAdapter, nBufferSize, &phyAddr, FALSE);
if(!pVirDMAbuf)
{
RETAILMSG(1, (TEXT("FMD_Init: HalAllocateCommonBuffer (DMA Buffer) fail!\r\n")));
return(NULL);
}
pPhyDMAbuffer = (LPBYTE)phyAddr.QuadPart;
//added 20080416 end
#endif
RETAILMSG(0,(TEXT("FMD_Init: finished successful\r\n")));
return((PVOID)s2440NAND);
}
/*
@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)
{
/*added by yangrui 20080414*/
BOOL Return_Status=FALSE;
startSectorAddr = startSectorAddr + (NandPartitionInfo.PartitionStartSector);
if(startSectorAddr/64 > 2047)
{
RETAILMSG(1, (TEXT("FMD:FMD_ReadSector:This error block=%d!!\r\n"),startSectorAddr/64));
RETAILMSG(1, (TEXT("FMD:FMD_ReadSector:This error SectorAddr=%d!!\r\n"),startSectorAddr));
}
//RETAILMSG(1, (TEXT("FMD:FMD_ReadSector:This SectorAddr=%d!!\r\n"),startSectorAddr));
/*added 20080414 end*/
if(g_pNandFlashChip)
{
Return_Status = g_pNandFlashChip->pReadSector(startSectorAddr,pSectorBuff,pSectorInfoBuff,dwNumSectors);
return Return_Status;
}
return FALSE;
}
/*
@func BOOL | FMD_EraseBlock | Erases the specified flash block.
@rdesc TRUE = Success, FALSE = Failure.
@comm
@xref
*/
BOOL FMD_EraseBlock(BLOCK_ID blockID)
{
/*added by yangrui 20080414*/
BOOL Return_Status=FALSE;
blockID = blockID + (NandPartitionInfo.PartitionStartBlock);
//Added by Sky Xu to Control Shut down WinCE on Jan 15.2009 - Start
#if 1
PELITE_GLOBALS peliteGlobal=NULL;
peliteGlobal = (PELITE_GLOBALS)(DRIVER_GLOBALS_PHYSICAL_MEMORY_START+ (DWORD)(&((PDRIVER_GLOBALS)0)->elite));
if(FALSE == peliteGlobal->Control_ShutDown_WinCE)
{
RETAILMSG(1, (TEXT("<<<Sky Xu>>>FMD_EraseBlock:::Control_ShutDown_WinCE was setted as FALSE!!!\r\n")));
return FALSE;
}
#endif
//Added by Sky Xu to Control Shut down WinCE on Jan 15.2009 - Start
if(blockID > 2047)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -