📄 fmd.cpp
字号:
while (dwBlock < g_flashInfo.dwNumBlocks) {
if (!(FMD_GetBlockStatus(dwBlock) & (BLOCK_STATUS_BAD | BLOCK_STATUS_RESERVED))) {
break;
}
dwBlock++;
}
RETAILMSG(1, (TEXT("DefineLayout: dwBlock = 0x%x \r\n"), dwBlock));
DWORD dwSector = dwBlock * g_flashInfo.wSectorsPerBlock;
if (!FMD_ReadSector (dwSector, g_pFLSBuffer, NULL, 1)) {
return FALSE;
}
// compare the signatures
if (IS_VALID_BOOTSEC(g_pFLSBuffer))
{
if (!FMD_ReadSector (dwSector+1, g_pFLSBuffer, NULL, 1)) {
return FALSE;
}
if (IS_VALID_FLS(g_pFLSBuffer))
{
PFlashLayoutSector pFLS = (PFlashLayoutSector)(g_pFLSBuffer);
// Cache the flash layout sector information
g_dwNumRegions = pFLS->cbRegionEntries / sizeof(FlashRegion);
// RETAILMSG(1, (TEXT("DefineLayout: g_dwNumRegions = 0x%x \r\n"), g_dwNumRegions));
// FlashRegion table starts after the ReservedEntry table.
if (g_dwNumRegions)
{
pRegion = (PFlashRegion)((LPBYTE)pFLS + sizeof(FlashLayoutSector) + pFLS->cbReservedEntries);
}
}
}
if (!g_dwNumRegions)
{
g_dwNumRegions = 1;
}
if (g_dwNumRegions > MAX_REGIONS)
return FALSE;
if (pRegion)
{
memcpy (g_pRegionTable, pRegion, g_dwNumRegions * sizeof(FlashRegion));
}
else
{
g_pRegionTable[0].dwStartPhysBlock = 0;
g_pRegionTable[0].dwNumPhysBlocks = g_flashInfo.dwNumBlocks;
g_pRegionTable[0].dwNumLogicalBlocks = FIELD_NOT_IN_USE;
g_pRegionTable[0].dwBytesPerBlock = g_flashInfo.dwBytesPerBlock;
g_pRegionTable[0].regionType = FILESYS;
g_pRegionTable[0].dwSectorsPerBlock = g_flashInfo.wSectorsPerBlock;
g_pRegionTable[0].dwCompactBlocks = DEFAULT_COMPACTION_BLOCKS;
}
// RETAILMSG(1, (TEXT("DefineLayout: g_pRegionTable[0].dwNumPhysBlocks = 0x%x \r\n"), g_pRegionTable[0].dwNumPhysBlocks));
return TRUE;
}
// FMD_ReadSector
//
// Read the content of the sector.
//
// startSectorAddr: Starting page address
// pSectorBuff : Buffer for the data portion
// pSectorInfoBuff: Buffer for Sector Info structure
// dwNumSectors : Number of sectors
//
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*PAGES_PER_BLOCK )
{
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*PAGES_PER_BLOCK, pSectorBuff, pSectorInfoBuff, dwNumSectors, USE_GPIO);
else
bRet = FMD_SB_ReadSector(startSectorAddr-wPRIMARY_NAND_BLOCKS*PAGES_PER_BLOCK, pSectorBuff, pSectorInfoBuff, dwNumSectors, USE_GPIO);
}
// RETAILMSG(1, (TEXT("FMD::FMD_ReadSector -- \r\n")));
return bRet;
}
//
// IsBlockBad
//
// Check to see if the given block is bad. A block is bad if the 517th byte on
// the first or second page is not 0xff.
//
// blockID: The block address. We need to convert this to page address
//
//
BOOL IsBlockBad(BLOCK_ID blockID)
{
BOOL bRet = FALSE;
int i;
if ( blockID < wPRIMARY_NAND_BLOCKS )
{
if ( astNandSpec[dwPrimaryNandDevice].nSctsPerPg == 4 )
{
for ( i = 0; i < LB_BLOCK_LOOP; i++ )
{
bRet = LB_IsBlockBad(blockID*(LB_BLOCK_LOOP) + i, USE_NFCE);
if ( bRet == TRUE ) break;
}
}
else
{
for ( i = 0; i < SB_BLOCK_LOOP; i++ )
{
bRet = SB_IsBlockBad(blockID*(SB_BLOCK_LOOP) + i, USE_NFCE);
if ( bRet == TRUE ) break;
}
}
}
else
{
if ( astNandSpec[dwSecondaryNandDevice].nSctsPerPg == 4 )
{
for ( i = 0; i < LB_BLOCK_LOOP; i++ )
{
bRet = LB_IsBlockBad((blockID-wPRIMARY_NAND_BLOCKS)*(LB_BLOCK_LOOP) + i, USE_GPIO);
if ( bRet == TRUE ) break;
}
}
else
{
for ( i = 0; i < SB_BLOCK_LOOP; i++ )
{
bRet = SB_IsBlockBad((blockID-wPRIMARY_NAND_BLOCKS)*(SB_BLOCK_LOOP) + i, USE_GPIO);
if ( bRet == TRUE ) break;
}
}
}
return bRet;
}
//
// FMD_GetBlockStatus
//
// Returns the status of a block. The status information is stored in the spare area of the first sector for
// the respective block.
//
// A block is BAD if the bBadBlock byte on the first page is not equal to 0xff.
//
DWORD FMD_GetBlockStatus(BLOCK_ID blockID)
{
DWORD dwResult = 0;
int i;
if ( blockID < wPRIMARY_NAND_BLOCKS )
{
if ( astNandSpec[dwPrimaryNandDevice].nSctsPerPg == 4 )
{
for ( i = 0; i < LB_BLOCK_LOOP; i++ )
{
dwResult |= FMD_LB_GetBlockStatus(blockID*(LB_BLOCK_LOOP) + i, USE_NFCE);
}
}
else
{
for ( i = 0; i < SB_BLOCK_LOOP; i++ )
{
dwResult |= FMD_SB_GetBlockStatus(blockID*(SB_BLOCK_LOOP) + i, USE_NFCE);
}
}
}
else
{
if ( astNandSpec[dwSecondaryNandDevice].nSctsPerPg == 4 )
{
for ( i = 0; i < LB_BLOCK_LOOP; i++ )
{
dwResult |= FMD_LB_GetBlockStatus((blockID-wPRIMARY_NAND_BLOCKS)*(LB_BLOCK_LOOP) + i, USE_GPIO);
}
}
else
{
for ( i = 0; i < SB_BLOCK_LOOP; i++ )
{
dwResult |= FMD_SB_GetBlockStatus((blockID-wPRIMARY_NAND_BLOCKS)*(SB_BLOCK_LOOP) + i, USE_GPIO);
}
}
}
return dwResult;
}
// FMD_EraseBlock
//
// Erase the given block
//
BOOL FMD_EraseBlock(BLOCK_ID blockID)
{
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-wPRIMARY_NAND_BLOCKS)*(SB_BLOCK_LOOP) + i, USE_GPIO);
if ( bRet == FALSE ) break;
}
}
}
return bRet;
}
// FMD_WriteSector
//
// Write dwNumPages pages to the startSectorAddr
//
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*PAGES_PER_BLOCK )
{
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*PAGES_PER_BLOCK, pSectorBuff, pSectorInfoBuff, dwNumSectors, USE_GPIO);
else
bRet = FMD_SB_WriteSector(startSectorAddr-wPRIMARY_NAND_BLOCKS*PAGES_PER_BLOCK, pSectorBuff, pSectorInfoBuff, dwNumSectors, USE_GPIO);
}
return bRet;
}
/*
* MarkBlockBad
*
* Mark the block as a bad block. We need to write a 00 to the 517th byte
*/
BOOL MarkBlockBad(BLOCK_ID blockID)
{
BOOL bRet = TRUE;
int i;
if ( blockID < wPRIMARY_NAND_BLOCKS )
{
if ( astNandSpec[dwPrimaryNandDevice].nSctsPerPg == 4 )
{
for ( i = 0; i < LB_BLOCK_LOOP; i++ )
{
bRet = LB_MarkBlockBad(blockID*(LB_BLOCK_LOOP) + i, USE_NFCE);
if ( bRet == FALSE ) break;
}
}
else
{
for ( i = 0; i < SB_BLOCK_LOOP; i++ )
{
bRet = SB_MarkBlockBad(blockID*(SB_BLOCK_LOOP) + i, USE_NFCE);
if ( bRet == FALSE ) break;
}
}
}
else // if ( PRIMARY_NAND == SMALL_BLOCK_NAND )
{
if ( astNandSpec[dwSecondaryNandDevice].nSctsPerPg == 4 )
{
for ( i = 0; i < LB_BLOCK_LOOP; i++ )
{
bRet = LB_MarkBlockBad((blockID-wPRIMARY_NAND_BLOCKS)*(LB_BLOCK_LOOP) + i, USE_GPIO);
if ( bRet == FALSE ) break;
}
}
else
{
for ( i = 0; i < SB_BLOCK_LOOP; i++ )
{
bRet = SB_MarkBlockBad((blockID-wPRIMARY_NAND_BLOCKS)*(SB_BLOCK_LOOP) + i, USE_GPIO);
if ( bRet == FALSE ) break;
}
}
}
return bRet;
}
//
// FMD_SetBlockStatus
//
// Sets the status of a block. Only implement for bad blocks for now.
// Returns TRUE if no errors in setting.
//
BOOL FMD_SetBlockStatus(BLOCK_ID blockID, DWORD dwStatus)
{
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_SetBlockStatus(blockID*(LB_BLOCK_LOOP) + i, dwStatus, USE_NFCE);
if ( bRet == FALSE ) break;
}
}
else
{
for ( i = 0; i < SB_BLOCK_LOOP; i++ )
{
bRet = FMD_SB_SetBlockStatus(blockID*(SB_BLOCK_LOOP) + i, dwStatus, USE_NFCE);
if ( bRet == FALSE ) break;
}
}
}
else // if ( PRIMARY_NAND == SMALL_BLOCK_NAND )
{
if ( astNandSpec[dwSecondaryNandDevice].nSctsPerPg == 4 )
{
for ( i = 0; i < LB_BLOCK_LOOP; i++ )
{
bRet = FMD_LB_SetBlockStatus((blockID-wPRIMARY_NAND_BLOCKS)*(LB_BLOCK_LOOP) + i, dwStatus, USE_GPIO);
if ( bRet == FALSE ) break;
}
}
else
{
for ( i = 0; i < SB_BLOCK_LOOP; i++ )
{
bRet = FMD_SB_SetBlockStatus((blockID-wPRIMARY_NAND_BLOCKS)*(SB_BLOCK_LOOP) + i, dwStatus, USE_GPIO);
if ( bRet == FALSE ) break;
}
}
}
return bRet;
}
#ifndef NOSYSCALL
// We don't have to build the following interface functions for the
// bootloader.
//
// FMD_PowerUp
//
// Performs any necessary powerup procedures...
//
VOID FMD_PowerUp(VOID)
{
}
// FMD_PowerDown
//
// Performs any necessary powerdown procedures...
//
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;
switch(dwIoControlCode)
{
case IOCTL_FMD_GET_INTERFACE:
{
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 = 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:
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)));
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -