📄 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 <s3c2443_nand.h>
#include <args.h>
#include <ethdbg.h>
#include "Cfnand.h"
#include <image_cfg.h>
#define IO_INDICATE 0
#if IO_INDICATE==1
#include <s3c2443_ioport.h> //DonGo
#endif //IO_INDICATE
#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);
#ifdef USE_MUTEX
static HANDLE g_hMutex;
HANDLE InitMutex(LPCTSTR name)
{
HANDLE hMutex;
hMutex = CreateMutex (
NULL, // No security attributes
FALSE, // Initially not owned
name); // Name of mutex object
if (NULL == hMutex)
{
// Your code to deal with the error goes here.
RETAILMSG(1, (_T("[DRVLIB]Cann't initialize mutex %s\r\n"),name));
}
return hMutex;
}
DWORD GetMutex(HANDLE handle)
{
DWORD result;
result = WaitForSingleObject( handle, INFINITE);
switch(result)
{
case WAIT_OBJECT_0:
break;
case WAIT_TIMEOUT:
RETAILMSG(1, (_T("[DRVLIB]ERROR:Mutex Timeout\r\n")));
break;
case WAIT_ABANDONED:
RETAILMSG(1, (_T("[DRVLIB]ERROR:Mutex abandoned\r\n")));
break;
default:
RETAILMSG(1, (_T("[DRVLIB]ERROR:others\r\n")));
break;
}
return result;
}
#endif // USE_MUTEX
/*
@func DWORD | ReadFlashID | Reads the flash manufacturer and device codes.
@rdesc Manufacturer and device codes.
@comm
@xref
*/
static DWORD ReadFlashID(void)
{
BYTE Mfg, Dev;
volatile BYTE i;
#ifdef USE_MUTEX
GetMutex(g_hMutex);
#endif // USE_MUTEX
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(); //
Dev = NF_RDDATA_BYTE(); //
NF_nFCE_H(); // Deselect the flash chip.
#ifdef USE_MUTEX
ReleaseMutex(g_hMutex);
#endif // USE_MUTEX
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;
#ifdef USE_MUTEX
RETAILMSG(1,(TEXT("#### FMD_DRIVER:::MUTEX INIT. \r\n")));
g_hMutex = InitMutex(TEXT("SSMCBusMutex"));
#endif // USE_MUTEX
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();
RETAILMSG(1, (TEXT(" (NAND ID:0x%x)\n"), rdid)); //+ ksk dbg
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%0x200 == 0) RETAILMSG(1, (TEXT("\r\n R : 0x%x, %d \r\n"), startSectorAddr, dwNumSectors)); //+ ksk dbg
// else RETAILMSG(1, (TEXT(".")));
#ifdef USE_MUTEX
GetMutex(g_hMutex);
#endif // USE_MUTEX
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")));
#ifdef USE_MUTEX
ReleaseMutex(g_hMutex);
#endif // USE_MUTEX
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%0x200 == 0) RETAILMSG(1, (TEXT(" W : 0x%x, %d \r\n"), startSectorAddr, dwNumSectors)); //+ ksk dbg
// else RETAILMSG(1, (TEXT(".")));
#ifdef USE_MUTEX
GetMutex(g_hMutex);
#endif // USE_MUTEX
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);
}
#ifdef USE_MUTEX
ReleaseMutex(g_hMutex);
#endif // USE_MUTEX
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")));
// RETAILMSG(1, (TEXT(" E : %d \r\n"), blockID)); //+ ksk dbg
BOOL bRet = TRUE;
int i;
#ifdef USE_MUTEX
GetMutex(g_hMutex);
#endif // USE_MUTEX
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;
}
}
}
#ifdef USE_MUTEX
ReleaseMutex(g_hMutex);
#endif // USE_MUTEX
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)
{
}
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)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -