📄 fmd.cpp
字号:
if(dwStatus & BLOCK_STATUS_READONLY)
{
DEBUGMSG(ZONE_INFO, (TEXT("set block %d OEM readonly.\r\n"), blockID));
SI.bOEMReserved &= ~OEM_BLOCK_READONLY;
}
if(dwStatus & BLOCK_STATUS_RESERVED)
{
DEBUGMSG(ZONE_FUNCTION, (TEXT("set block %d OEM reserved.\r\n"), blockID));
SI.bOEMReserved &= ~OEM_BLOCK_RESERVED;
}
if(!FMD_WriteSector(Sector, NULL, &SI, 1))
{
ERRORMSG(ZONE_ERROR, (TEXT("write block %d OEM status failed.\r\n"), blockID));
return FALSE;
}
}
}
DEBUGMSG(ZONE_FUNCTION, (TEXT("FMD_SetBlockStatus-\r\n")));
return TRUE;
}
//-----------------------------------------------------------------------------
//
// Function: FMD_EraseBlock
//
// Function Erases the specified flash block.
//
// Parameters:
// blockID
// [in] block number to erase.
//
// Returns:
// TRUE/FALSE for success
//
//-----------------------------------------------------------------------------
BOOL FMD_EraseBlock(BLOCK_ID blockID)
{
ULONG BlockAddress;
ULONG Len;
BOOL bLastMode;
DEBUGMSG(ZONE_FUNCTION, (TEXT("FMD_EraseBlock+: blockID=0x%X\r\n"), blockID));
bLastMode = SetKMode(TRUE);
BlockAddress = (ULONG)g_pNORFlashBase + g_FMDInfo.FMDBaseOffset + (blockID * g_FMDInfo.EraseBlockSize);
Len = NORErase(BlockAddress, g_FMDInfo.EraseBlockSize);
DEBUGMSG(ZONE_FUNCTION, (TEXT("FMD_EraseBlock- len 0x%08X\r\n"), Len));
SetKMode(bLastMode);
if(Len != 0)
return TRUE;
else
return FALSE;
}
//-----------------------------------------------------------------------------
//
// Function: FMD_PowerUp
//
// Function Restores power to the flash memory device.
//
// Parameters:
// None
//
// Returns:
// None
//
//-----------------------------------------------------------------------------
VOID FMD_PowerUp(VOID)
{
DEBUGMSG(ZONE_FUNCTION, (TEXT("FMD_PowerUp+\r\n")));
DEBUGMSG(ZONE_FUNCTION, (TEXT("FMD_PowerUp-\r\n")));
}
//-----------------------------------------------------------------------------
//
// Function: FMD_PowerDown
//
// Function Suspends power to the flash memory device.
//
// Parameters:
// None
//
// Returns:
// None
//
//-----------------------------------------------------------------------------
VOID FMD_PowerDown(VOID)
{
DEBUGMSG(ZONE_FUNCTION, (TEXT("FMD_PowerDown+\r\n")));
DEBUGMSG(ZONE_FUNCTION, (TEXT("FMD_PowerDown-\r\n")));
}
//-----------------------------------------------------------------------------
//
// Function: FMD_GetPhysSectorAddr
//
// Function returns the physical address for the physical sector passed in.
//
// Parameters:
// dwSector
// [in] sector number
//
// pStartSectorAddr
// [out] physical address.
//
// Returns:
// None
//
//-----------------------------------------------------------------------------
VOID FMD_GetPhysSectorAddr(DWORD dwSector, PSECTOR_ADDR pStartSectorAddr)
{
DEBUGMSG(ZONE_FUNCTION, (TEXT("FMD_GetPhysSectorAddr+: dwSector 0x%08X\r\n"), dwSector));
GetPhysicalSectorAddress(dwSector, pStartSectorAddr, NULL);
DEBUGMSG(ZONE_FUNCTION, (TEXT("FMD_GetPhysSectorAddr-\r\n")));
}
//-----------------------------------------------------------------------------
//
// Function: FMD_OEMIoControl
//
// Function Implements user-defined commands for the flash memory device.
//
// Parameters:
// dwIoControlCode
// [in] control code specifying the command to execute.
//
// pInBuf
// [in] buffer that contains the data required to perform the operation
//
// nInBufSize
// [in] Size, in bytes, of the buffer pointed to by pInBuf
//
// pOutBuf
// [out] buffer that receives the output data for the operation.
//
// nOutBufSize
// [in] Size, in bytes, of the buffer pointed to by pOutBuf
//
// pBytesReturned
// [out] receives the size, in bytes of the data stored into the buffer
// pointed to by pOutBuf
//
// Returns:
// TRUE/FALSE for success
//
//-----------------------------------------------------------------------------
BOOL FMD_OEMIoControl(DWORD dwIoControlCode, PBYTE pInBuf, DWORD nInBufSize,
PBYTE pOutBuf, DWORD nOutBufSize, PDWORD pBytesReturned)
{
switch(dwIoControlCode)
{
case IOCTL_FMD_GET_INTERFACE:
{
if (!pOutBuf || nOutBufSize < sizeof(FMDInterface))
{
ERRORMSG(ZONE_ERROR, (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->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 = FMD_GetPhysSectorAddr;
break;
}
case IOCTL_FMD_SET_XIPMODE:
// Select between XIP mode or non-XIP mode. The difference from
// the FMD's standpoint is whether or not sector information is
// stored along with each sector. This should be called before
// FMD_Init.
if(!pInBuf || nInBufSize < sizeof(BOOL))
{
ERRORMSG(ZONE_ERROR, (TEXT("FMD_OEMIoControl: IOCTL_FMD_SET_XIPMODE bad parameter(s).\r\n")));
return FALSE;
}
g_bXIPMode = *(BOOL *)pInBuf;
break;
case IOCTL_FMD_GET_XIPMODE:
if(!pOutBuf || nOutBufSize < sizeof(BOOLEAN))
{
ERRORMSG(ZONE_ERROR, (TEXT("FMD_OEMIoControl: IOCTL_FMD_GET_XIPMODE bad parameter(s).\r\n")));
return FALSE;
}
*(BOOL *)pOutBuf = g_bXIPMode;
break;
case IOCTL_FMD_LOCK_BLOCKS:
// Lock one of more blocks in a specified range.
if(!pInBuf || nInBufSize < sizeof(BlockLockInfo))
{
ERRORMSG(ZONE_ERROR, (TEXT("FMD_OEMIoControl: IOCTL_FMD_LOCK_BLOCKS bad parameter(s).\r\n")));
return FALSE;
}
if(!SetBlockLock(((PBlockLockInfo)pInBuf)->StartBlock, ((PBlockLockInfo)pInBuf)->NumBlocks, TRUE))
{
ERRORMSG(ZONE_ERROR, (TEXT("FMD_OEMIoControl: IOCTL_FMD_LOCK_BLOCKS failed to lock blocks (start=0x%x, number=0x%x).\r\n"), ((PBlockLockInfo)pInBuf)->StartBlock, ((PBlockLockInfo)pInBuf)->NumBlocks));
return FALSE;
}
break;
case IOCTL_FMD_UNLOCK_BLOCKS:
// Unlock one of more blocks in a specified range.
if(!pInBuf || nInBufSize < sizeof(BlockLockInfo))
{
ERRORMSG(ZONE_ERROR, (TEXT("FMD_OEMIoControl: IOCTL_FMD_UNLOCK_BLOCKS bad parameter(s).\r\n")));
return FALSE;
}
if(!SetBlockLock(((PBlockLockInfo)pInBuf)->StartBlock, ((PBlockLockInfo)pInBuf)->NumBlocks, FALSE))
{
ERRORMSG(ZONE_ERROR, (TEXT("FMD_OEMIoControl: IOCTL_FMD_UNLOCK_BLOCKS failed to unlock blocks (start=0x%x, number=0x%x).\r\n"), ((PBlockLockInfo)pInBuf)->StartBlock, ((PBlockLockInfo)pInBuf)->NumBlocks));
return FALSE;
}
break;
default:
DEBUGMSG(ZONE_INFO, (TEXT("FMD_OEMIoControl: unrecognized IOCTL (0x%x).\r\n"), dwIoControlCode));
return FALSE;
}
return TRUE;
}
//-----------------------------------------------------------------------------
// PRIVATE FUNCTIONS
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
//
// Function: DefineLayout
//
//
// Notes:
// The FAL expects the Flash media to be broken up into Flash blocks
// which are then subdivided into physical sectors. Some types of
// Flash memory (i.e. NAND Flash) already have this layout. NOR Flash,
// on the other hand, DOES NOT breakup each Flash block into physical
// sectors. Instead, each byte is individually addressable (like RAM).
// Despite this characteristic, NOR Flash can still logically be broken
// up into discrete sectors as follows:
//
// NOR Flash
//
// Sector Data SectorInfo
// ---------------------------------
// |Sector(0) | |
// |Sector(1) | |
// |Sector(2) | | Block 0
// |... | |
// |Sector(k) | |
// | |-------|
// |Sector info | |
// |for all blocks | |
// | |-------|
// | XXXXXXXXX
// -------------------------------
// |Sector(k+1) | |
// |Sector(k+2) | |
// |Sector(k+3) | | Block 1
// |... | |
// |Sector(2k) | |
// | |-------|
// |Sector info | |
// |for all blocks | |
// | |-------|
// | XXXXXXXXX
// -------------------------------
// | | |
// | | |
// | | | Block 2
// | | |
// | | |
// | |-------|
// |Sector info | |
// |for all blocks | |
// | |-------|
// | XXXXXXXXX
// ------------------------------- ...
// | | |
// | | |
// | | | Block N
// | | |
// | | |
// | |-------|
// |Sector info | |
// |for all blocks | |
// | |-------|
// | XXXXXXXXX
// ---------------------------------
//
// That is, each NOR Flash block is logically subdivided into a "page",
// where each page contains space for sector data and SectorInfo metadata.
// Most often, Flash blocks are a power of 2 in size but the size of a page
// is not a power of 2 (i.e. 512 + 8 = 520 bytes).
// Thus, each Flash block DOES NOT evenly divide into an integral number of
// pages and some bytes in a block are left unused. These unused bytes are
// denoted above by XXXXX's.
//
// To help clarify how this process works, consider the following example:
// suppose you have a NOR Flash memory device that contains 256 Flash blocks
// each 256K in size. From these size characteristics, we find:
//
// (256K / (512+8)) ==> 504 sectors + 64 unused bytes
//
// Therefore, each Flash block can map 504 sectors (including SectorInfo
// metadata)and leave 64 unused bytes per block. Notice that 8 bytes is
// used for the SectorInfo metadata although the SectorInfo structure is
// currently only 6 bytes. The reason for this is to make sure that all
// sector addresses are DWORD aligned. (i.e. 520 divides by 4 evenly while
// 518 doesn't divide by 4 evenly).
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -