📄 fmd.cpp
字号:
// OK, instead of reading it from the chip, we use the hardcoded
// numbers here.
pFlashInfo->dwNumBlocks = wNUM_BLOCKS;
pFlashInfo->wSectorsPerBlock = NAND_PAGE_CNT;
pFlashInfo->wDataBytesPerSector = NAND_PAGE_SIZE;
pFlashInfo->dwBytesPerBlock = (pFlashInfo->wSectorsPerBlock * pFlashInfo->wDataBytesPerSector);
RETAILMSG(1, (TEXT("NUMBLOCKS : %d(0x%x), SECTORSPERBLOCK = %d(0x%x), BYTESPERSECTOR = %d(0x%x) \r\n"), pFlashInfo->dwNumBlocks, pFlashInfo->dwNumBlocks, pFlashInfo->wSectorsPerBlock, pFlashInfo->wSectorsPerBlock, pFlashInfo->wDataBytesPerSector, pFlashInfo->wDataBytesPerSector));
//SetKMode(bLastMode);
return TRUE;
}
#define VALIDADDR 0x05 // S3C2443NAND
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;
// ULONG MECC;
DWORD i;
BYTE eccBuf[8];
volatile DWORD rddata;
int NewSpareAddr = 2048 + 16*(startSectorAddr%4);
int NewDataAddr = 512*(startSectorAddr%4);
int NewSectorAddr = startSectorAddr/4;
//RETAILMSG(1,(TEXT("#### FMD_DRIVER:::FMD_LB_READSECTOR %x %x\r\n"),startSectorAddr,NewDataAddr));
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;
}
// BOOL bLastMode = SetKMode(TRUE);
if (!pSectorBuff)
{
NAND_LB_ReadSectorInfo(startSectorAddr, pSectorInfoBuff, mode);
return TRUE;
}
NF_RSTECC();
NF_MECC_UnLock();
NF_nFCE_L();
NF_CLEAR_RB();
NF_CMD(CMD_READ); // Send read command.
NF_ADDR((NewDataAddr)&0xff);
NF_ADDR(((NewDataAddr)>>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( ((DWORD) pSectorBuff) & 0x3)
{
for(i=0; i<NAND_PAGE_SIZE/sizeof(DWORD); i++) {
rddata = (DWORD) NF_RDDATA_WORD();
pSectorBuff[i*4+0] = (BYTE)(rddata & 0xff);
pSectorBuff[i*4+1] = (BYTE)(rddata>>8 & 0xff);
pSectorBuff[i*4+2] = (BYTE)(rddata>>16 & 0xff);
pSectorBuff[i*4+3] = (BYTE)(rddata>>24 & 0xff);
}
}
else
{
#if 1
RdPage512(pSectorBuff); // Read page/sector data.
#else
for(volatile int i=0; i<512; i++)
{
for(volatile int j=0; j<5; j++);
*pSectorBuff++ = (BYTE)s2443NAND->NFDATA;
}
#endif
}
NF_MECC_Lock();
NF_CMD(CMD_RDO);
// Set up address
NF_ADDR((NewSpareAddr)&0xff);
NF_ADDR(((NewSpareAddr)>>8)&0xff);
NF_CMD(CMD_RDO2);
#if 0
if (pSectorInfoBuff)
{
RdPageInfo((PBYTE)pSectorInfoBuff); // Read page/sector information.
pSectorInfoBuff ++;
}
#else
if (pSectorInfoBuff)
{
// RdPageInfo((PBYTE)pSectorInfoBuff); // Read page/sector information.
rddata= NF_RDDATA_WORD();
pSectorInfoBuff->dwReserved1 = rddata;
//RETAILMSG(1, (TEXT("111Spare DATA you want it 0x%x\r\n"),rddata));
rddata= NF_RDDATA_WORD();
//RETAILMSG(1, (TEXT("Spare DATA you want it 0x%x\r\n"),rddata));
pSectorInfoBuff->bOEMReserved = (BYTE) (rddata & 0xff);;
// Read the bad block mark
pSectorInfoBuff->bBadBlock = (BYTE) ((rddata>>8) & 0xff);
// Second reserved field (WORD)
pSectorInfoBuff->wReserved2 = (WORD) ((rddata>>16) & 0xffff);
// pSectorInfoBuff->wReserved2 |= ((BYTE) NF_DATA_R());
}
#endif
else
{
#if 0 // hsjang 060613
BYTE TempInfo[8];
RdPageInfo(TempInfo); // Read page/sector information.
#endif
for(i=0; i<sizeof(SectorInfo)/sizeof(DWORD); i++)
rddata = (DWORD) NF_RDDATA_WORD(); // read and trash the data
}
for(i=0; i<2; i++) {
rddata = (DWORD) NF_RDDATA_WORD();
//RETAILMSG(1, (TEXT("333Spare DATA you want it 0x%x\r\n"),rddata));
// RETAILMSG(1, (TEXT("rddata 0x%x \r\n"), rddata));
eccBuf[i*4+0] = (BYTE)(rddata & 0xff);
eccBuf[i*4+1] = (BYTE)(rddata>>8 & 0xff);
eccBuf[i*4+2] = (BYTE)(rddata>>16 & 0xff);
eccBuf[i*4+3] = (BYTE)(rddata>>24 & 0xff);
}
// Mecc0 = READ_REGISTER_ULONG(pNFMECC0);
// Compare with the ECC generated from the HW
NF_WRMECCD0( (DWORD)((DWORD)(eccBuf[3]<<24) | (DWORD)(eccBuf[2]<<16) |(DWORD)(eccBuf[1]<<8) | (DWORD)(eccBuf[0]&0xff)));
//NF_WRMECCD1( (DWORD)((DWORD)(eccBuf[3]<<8) | (DWORD)(eccBuf[2]&0xff)));
if (NF_RDESTST & 0x3)
{
RETAILMSG(1,(TEXT("ECC error reg:%x rd:%x(NF_RDESTST:%x)\r\n"),NF_RDMECC0(),rddata, NF_RDESTST));
NF_nFCE_H(); // Deselect the flash chip.
// SetKMode (bLastMode);
return FALSE;
}
NF_nFCE_H();
//RETAILMSG(1, (TEXT(".")));
// SetKMode (bLastMode);
return(TRUE);
}
void NAND_LB_ReadSectorInfo(SECTOR_ADDR sectorAddr, PSectorInfo pInfo, int mode)
{
volatile DWORD rddata;
int NewSpareAddr = 2048 + 16*(sectorAddr%4);
int NewSectorAddr = sectorAddr/4;
// BOOL bLastMode = SetKMode(TRUE);
#if 1
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 1 // hsjang 060613
if (NEED_EXT_ADDR)
NF_ADDR((NewSectorAddr >> 16) & 0xff);
#endif
NF_CMD(CMD_READ3);
NF_DETECT_RB();
pInfo->dwReserved1 = NF_RDDATA_WORD();
rddata = NF_RDDATA_WORD();
// OEM byte
pInfo->bOEMReserved = (BYTE) (rddata & 0xff);
// Read the bad block mark
pInfo->bBadBlock = (BYTE) ((rddata>>8) & 0xff);
// Second reserved field (WORD)
pInfo->wReserved2 = (WORD) ((rddata>>16) & 0xffff);
NF_nFCE_H();
#endif
//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);
//RETAILMSG(1,(TEXT("#### FMD_DRIVER:::FMD_sbreadT \r\n")));
while (dwNumSectors--)
{
ULONG blockPage = (((SectorAddr / NAND_PAGE_CNT) * NAND_PAGE_CNT) | (SectorAddr % NAND_PAGE_CNT));
NF_RSTECC();
NF_MECC_UnLock();
NF_nFCE_L();
if (!pSectorBuff)
{
NF_CLEAR_RB();
NF_CMD(CMD_READ2); // Send read confirm command.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -