fmd.cpp
来自「SAMSUNG S3C6410 CPU BSP for winmobile6」· C++ 代码 · 共 2,345 行 · 第 1/4 页
CPP
2,345 行
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;
}
#if 0
case IOCTL_FMD_LOCK_BLOCKS:
// LOCK is not supported.!!!!
BlockLockInfo * pLockInfo;
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("S3C6410 Does not support IOCTL_FMD_UNLOCK_BLOCKS !!!! \r\n")));
return(FALSE);
#endif
default:
RETAILMSG(1, (TEXT("FMD_OEMIoControl: unrecognized IOCTL (0x%x).\r\n"), dwIoControlCode));
return(FALSE);
}
return TRUE;
}
#endif // NOSYSCALL
#endif // MAGNETO
//#define VALIDADDR 0x05 // S3C6410NAND
static 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;
}
/*
@func DWORD | FMD_GetBlockStatus | Returns the status of the specified block.
@rdesc Block status (see fmd.h).
@comm
@xref
*/
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;
}
/*
@func BOOL | MarkBlockBad | Marks the specified block as bad.
@rdesc TRUE = Success, FALSE = Failure.
@comm
@xref
*/
static 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;
}
/*
@func BOOL | FMD_SetBlockStatus | Marks the block with the specified block status.
@rdesc TRUE = Success, FALSE = Failure.
@comm
@xref
*/
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;
}
BOOL FMD_LB_ReadSector(SECTOR_ADDR startSectorAddr, LPBYTE pSectorBuff, PSectorInfo pSectorInfoBuff, DWORD dwNumSectors,int mode)
{
ULONG SectorAddr = (ULONG)startSectorAddr;
DWORD i;
volatile DWORD rddata;
UINT32 nRetEcc = 0;
DWORD MECCBuf[4];
UINT16 nSectorLoop;
int NewSpareAddr = 2048;
int NewDataAddr = 0;
int NewSectorAddr = startSectorAddr;
#if CHECK_SPAREECC
DWORD SECCBuf;
#endif
if (!pSectorBuff && !pSectorInfoBuff) return(FALSE);
if ( dwNumSectors > 1 )
{
RETAILMSG(1, (TEXT("######## FATAL ERROR => FMD::FMD_ReadSector->dwNumsectors is bigger than 1. \r\n")));
return FALSE;
}
if (!pSectorBuff)
{
NAND_LB_ReadSectorInfo(startSectorAddr, pSectorInfoBuff, mode);
return TRUE;
}
BOOL bLastMode = SetKMode(TRUE);
NF_nFCE_L();
NF_CLEAR_RB();
NF_CMD(CMD_READ); // Send read command.
NF_ADDR((NewSpareAddr)&0xff);
NF_ADDR(((NewSpareAddr)>>8)&0xff);
NF_ADDR((NewSectorAddr) & 0xff);
NF_ADDR((NewSectorAddr >> 8) & 0xff);
#if 1 // hsjang 060613
if (NEED_EXT_ADDR)
NF_ADDR((NewSectorAddr >> 16) & 0xff);
#endif
NF_CMD(CMD_READ3); // 2nd command
NF_DETECT_RB(); // Wait for command to complete.
if (pSectorInfoBuff)
{
#if CHECK_SPAREECC
NF_RSTECC();
NF_SECC_UnLock();
#endif
pSectorInfoBuff->bBadBlock = NF_RDDATA_BYTE();
pSectorInfoBuff->dwReserved1 = NF_RDDATA_WORD();
pSectorInfoBuff->bOEMReserved = NF_RDDATA_BYTE();
#if CHECK_SPAREECC
NF_SECC_Lock();
#endif
pSectorInfoBuff->wReserved2 = NF_RDDATA_BYTE();
pSectorInfoBuff->wReserved2 |= (NF_RDDATA_BYTE()<<8);
}
else
{
for(i=0; i<sizeof(SectorInfo)/sizeof(DWORD); i++)
{
rddata = (DWORD) NF_RDDATA_WORD(); // read and trash the data
}
}
for (nSectorLoop = 0; nSectorLoop < astNandSpec[dwPrimaryNandDevice].nSctsPerPg; nSectorLoop++)
{
MECCBuf[nSectorLoop] = NF_RDDATA_WORD();
}
#if CHECK_SPAREECC
if (pSectorInfoBuff)
{
SECCBuf = NF_RDDATA_WORD();
NF_WRSECCD((SECCBuf&0xff)|((SECCBuf<<8)&0xff0000));
nRetEcc = NF_ECC_ERR0;
if (!ECC_CorrectData(startSectorAddr, (LPBYTE)pSectorInfoBuff, nRetEcc, ECC_CORRECT_SPARE))
{
return FALSE;
}
}
#endif
for (nSectorLoop = 0; nSectorLoop < astNandSpec[dwPrimaryNandDevice].nSctsPerPg; nSectorLoop++)
{
NewDataAddr = nSectorLoop * SECTOR_SIZE;
NF_CMD(CMD_RDO); // Send read command.
NF_ADDR((NewDataAddr)&0xff);
NF_ADDR((NewDataAddr>>8)&0xff);
NF_CMD(CMD_RDO2); // 2nd command
NF_RSTECC();
NF_MECC_UnLock();
if( ((DWORD) (pSectorBuff+nSectorLoop*SECTOR_SIZE)) & 0x3)
{
for(i=0; i<SECTOR_SIZE/sizeof(DWORD); i++)
{
rddata = (DWORD) NF_RDDATA_WORD();
(pSectorBuff+nSectorLoop*SECTOR_SIZE)[i*4+0] = (BYTE)(rddata & 0xff);
(pSectorBuff+nSectorLoop*SECTOR_SIZE)[i*4+1] = (BYTE)(rddata>>8 & 0xff);
(pSectorBuff+nSectorLoop*SECTOR_SIZE)[i*4+2] = (BYTE)(rddata>>16 & 0xff);
(pSectorBuff+nSectorLoop*SECTOR_SIZE)[i*4+3] = (BYTE)(rddata>>24 & 0xff);
}
}
else
{
RdPage512(pSectorBuff+nSectorLoop*SECTOR_SIZE); // Read page/sector data.
}
NF_MECC_Lock();
NF_WRMECCD0( ((MECCBuf[nSectorLoop]&0xff00)<<8)|(MECCBuf[nSectorLoop]&0xff) );
NF_WRMECCD1( ((MECCBuf[nSectorLoop]&0xff000000)>>8)|((MECCBuf[nSectorLoop]&0xff0000)>>16) );
nRetEcc = NF_ECC_ERR0;
if (!ECC_CorrectData(startSectorAddr, pSectorBuff+nSectorLoop*SECTOR_SIZE, nRetEcc, ECC_CORRECT_MAIN))
{
return FALSE;
}
}
NF_nFCE_H();
SetKMode (bLastMode);
return(TRUE);
}
#if 0
BOOL RAW_LB_ReadSector(UINT32 startSectorAddr, LPBYTE pSectorBuff, LPBYTE pSectorInfoBuff)
{
ULONG SectorAddr = (ULONG)startSectorAddr;
DWORD i;
volatile DWORD rddata;
UINT32 nRetEcc = 0;
// DWORD MECCBuf[4];
UINT16 nSectorLoop;
int NewDataAddr = 0;
if (!pSectorBuff && !pSectorInfoBuff) return(FALSE);
BOOL bLastMode = SetKMode(TRUE);
NF_nFCE_L();
NF_CLEAR_RB();
NF_CMD(CMD_READ); // Send read command.
NF_ADDR((NewDataAddr)&0xff);
NF_ADDR(((NewDataAddr)>>8)&0xff);
NF_ADDR((SectorAddr) & 0xff);
NF_ADDR((SectorAddr >> 8) & 0xff);
if (NEED_EXT_ADDR)
NF_ADDR((SectorAddr >> 16) & 0xff);
NF_CMD(CMD_READ3); // 2nd command
NF_DETECT_RB(); // Wait for command to complete.
for (nSectorLoop = 0; nSectorLoop < 4; nSectorLoop++)
{
if( ((DWORD) (pSectorBuff+nSectorLoop*SECTOR_SIZE)) & 0x3)
{
for(i=0; i<SECTOR_SIZE/sizeof(DWORD); i++)
{
rddata = (DWORD) NF_RDDATA_WORD();
(pSectorBuff+nSectorLoop*SECTOR_SIZE)[i*4+0] = (BYTE)(rddata & 0xff);
(pSectorBuff+nSectorLoop*SECTOR_SIZE)[i*4+1] = (BYTE)(rddata>>8 & 0xff);
(pSectorBuff+nSectorLoop*SECTOR_SIZE)[i*4+2] = (BYTE)(rddata>>16 & 0xff);
(pSectorBuff+nSectorLoop*SECTOR_SIZE)[i*4+3] = (BYTE)(rddata>>24 & 0xff);
}
}
else
{
RdPage512(pSectorBuff+nSectorLoop*SECTOR_SIZE); // Read page/sector data.
}
}
for(i=0; i<64; i++)
{
*pSectorInfoBuff = NF_RDDATA_BYTE(); // read and trash the data
pSectorInfoBuff+=1;
}
NF_nFCE_H();
SetKMode (bLastMode);
return(TRUE);
}
#endif
void NAND_LB_ReadSectorInfo(SECTOR_ADDR sectorAddr, PSectorInfo pInfo, int mode)
{
BOOL bRet = TRUE;
int NewSpareAddr = 2048;
int NewSectorAddr = sectorAddr;
#if CHECK_SPAREECC
DWORD SECCBuf;
UINT32 nRetEcc = 0;
#endif
BOOL bLastMode = SetKMode(TRUE);
NF_nFCE_L();
NF_CLEAR_RB();
NF_CMD(CMD_READ); // Send read confirm command.
NF_ADDR((NewSpareAddr)&0xff);
NF_ADDR((NewSpareAddr>>8)&0xff);
NF_ADDR((NewSectorAddr)&0xff);
NF_ADDR((NewSectorAddr>>8) & 0xff);
if (NEED_EXT_ADDR)
NF_ADDR((NewSectorAddr >> 16) & 0xff);
NF_CMD(CMD_READ3);
NF_DETECT_RB();
#if CHECK_SPAREECC
NF_RSTECC();
NF_SECC_UnLock();
#endif
pInfo->bBadBlock = NF_RDDATA_BYTE();
pInfo->dwReserved1 = NF_RDDATA_WORD();
pInfo->bOEMReserved = NF_RDDATA_BYTE();
#if CHECK_SPAREECC
NF_SECC_Lock();
#endif
pInfo->wReserved2 = NF_RDDATA_BYTE();
pInfo->wReserved2 |= (NF_RDDATA_BYTE()<<8);
#if CHECK_SPAREECC
SECCBuf = NF_RDSECC();
NF_WRSECCD((SECCBuf&0xff)|((SECCBuf<<8)&0xff0000));
nRetEcc = NF_ECC_ERR0;
bRet = ECC_CorrectData(sectorAddr, (LPBYTE)pInfo, nRetEcc, ECC_CORRECT_SPARE);
#endif
NF_nFCE_H();
SetKMode(bLastMode);
}
BOOL FMD_SB_ReadSector(SECTOR_ADDR startSectorAddr, LPBYTE pSectorBuff, PSectorInfo pSectorInfoBuff, DWORD dwNumSectors,int mode)
{
ULONG SectorAddr = (ULONG)startSectorAddr;
ULONG MECC;
if (!pSectorBuff && !pSectorInfoBuff) return(FALSE);
BOOL bLastMode = SetKMode(TRUE);
#if (NAND_DEBUG)
RETAILMSG(1,(TEXT("#### FMD_DRIVER:::FMD_sbreadT \r\n")));
#endif
while (dwNumSectors--)
{
ULONG blockPage = (((SectorAddr / PAGES_PER_BLOCK) * PAGES_PER_BLOCK) | (SectorAddr % PAGES_PER_BLOCK));
NF_RSTECC();
NF_MECC_UnLock();
NF_nFCE_L();
if (!pSectorBuff)
{
NF_CLEAR_RB();
NF_CMD(CMD_READ2); // Send read confirm command.
NF_ADDR(0); // Ignored.
NF_ADDR(blockPage & 0xff); // Page address.
NF_ADDR((blockPage >> 8) & 0xff);
if (NEED_EXT_ADDR)
NF_ADDR((blockPage >> 16) & 0xff);
NF_DETECT_RB();
RdPageInfo((PBYTE)pSectorInfoBuff); // Read page/sector information.
pSectorInfoBuff++;
}
else
{
NF_CLEAR_RB();
NF_CMD(CMD_READ); // Send read command.
NF_ADDR(0); // Column = 0.
NF_ADDR(blockPage & 0xff); // Page address.
NF_ADDR((blockPage >> 8) & 0xff);
if (NEED_EXT_ADDR)
NF_ADDR((blockPage >> 16) & 0xff);
NF_DETECT_RB(); // Wait for command to complete.
if( ((DWORD) pSectorBuff) & 0x3)
{
RdPage512Unalign (pSectorBuff);
}
else
{
RdPage512(pSectorBuff); // Read page/sector data.
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?