📄 s3c2450_fil.c
字号:
pSECCCxt pSpareCxt;
#ifdef USE_SETKMODE
BOOL bLastMode;
#endif
NAND_MSG((_T("[FIL]++NAND_Read(%d, %d, 0x%02x, 0x%02x, %d)\r\n"), nBank, nPpn, nSctBitmap, nPlaneBitmap, bCleanCheck));
// pDBuf & pSBuf can't be the NULL at the same time
if (nBank >= BANKS_TOTAL || nPpn >= PAGES_PER_BANK || (pDBuf == NULL && pSBuf == NULL))
{
NAND_ERR((_T("[FIL:ERR]--NAND_Read() : Parameter overflow\r\n")));
WMR_ASSERT(FALSE32);
return FIL_CRITICAL_ERROR;
}
WMR_ASSERT((nPlaneBitmap == enuBOTH_PLANE_BITMAP) || (nPlaneBitmap == enuLEFT_PLANE_BITMAP) || (nPlaneBitmap == enuRIGHT_PLANE_BITMAP));
nVBank = nBank; // Do not change nBank before copy to nVBank
// avoid r/b check error with internal interleaving
if (bInternalInterleaving == TRUE32)
{
nPairBank = ((nBank & 0x1) == 1) ? (nBank - 1) : (nBank + 1);
}
/*
In case of Internal Interleaving, the first address of the second bank should be
the half of toal block number of NAND.
For example, In 4Gbit DDP NAND, its total block number is 4096.
So, the bank 0 has 2048 blocks (Physical number : 0 ~ 2047),
the bank 1 has another 2048 blocks (Physical number : 2048 ~ 4095).
therefore, first block address of Bank 1 could be the physically 2048th block.
*/
if (bInternalInterleaving == TRUE32)
{
if ((nBank & 0x1) == 1)
{
nPpn += PAGES_PER_BANK;
}
nBank /= 2;
}
nSctBitmap &= FULL_SECTOR_BITMAP_PAGE;
#if (WMR_STDLIB_SUPPORT)
nPbn = nPpn / PAGES_PER_BLOCK;
nPOffset = nPpn % PAGES_PER_BLOCK;
#else
nPbn = DIV(nPpn, PAGES_PER_BLOCK_SHIFT);
nPOffset = REM(nPpn, PAGES_PER_BLOCK_SHIFT);
#endif
// In case of 2 Plane Program, re-calculate the page address
if (TWO_PLANE_PROGRAM == TRUE32)
{
nPpn = nPbn * 2 * PAGES_PER_BLOCK + nPOffset;
if (nPlaneBitmap == enuBOTH_PLANE_BITMAP)
{
if(pDBuf != NULL)
{
if ((nSctBitmap & LEFT_SECTOR_BITMAP_PAGE) > 0 && (nSctBitmap & RIGHT_SECTOR_BITMAP_PAGE) > 0)
{
// read from both plane
bLoopNeed = TRUE32;
}
else if ((nSctBitmap & LEFT_SECTOR_BITMAP_PAGE) > 0 && (nSctBitmap & RIGHT_SECTOR_BITMAP_PAGE) == 0)
{
// read from left plane
bLoopNeed = FALSE32;
}
else if ((nSctBitmap & LEFT_SECTOR_BITMAP_PAGE) == 0 && (nSctBitmap & RIGHT_SECTOR_BITMAP_PAGE) > 0)
{
// read from right plane
bLoopNeed = FALSE32;
bSecondRead = TRUE32;
}
}
else
{
// When read only the spare area, must read twice
bLoopNeed = TRUE32;
}
}
else if (nPlaneBitmap == enuRIGHT_PLANE_BITMAP)
{
nPpn += PAGES_PER_BLOCK;
}
}
nLoopCount = SECTORS_PER_PAGE;
NAND_Sync(nVBank, &nSyncRet);
if (bInternalInterleaving == TRUE32)
{
// avoid r/b check error with internal interleaving
aNeedSync[nVBank] = FALSE32;
}
_B_SecondRead: // back here again for read right plane
if(bSecondRead)
{
nPpn += PAGES_PER_BLOCK;
nSctBitmap = (nSctBitmap >> SECTORS_PER_PAGE);
if(pDBuf != NULL)
{
pDBuf += BYTES_PER_MAIN_PAGE;
}
else
{
// When read only the spare, read 64 + 64 bytes to check the Bad Block
pSBuf += BYTES_PER_SPARE_PAGE;
}
}
#if (WMR_READ_RECLAIM)
READ_ERR_FLAG = FALSE32;
#endif
if(pSBuf == NULL)
{
pSBuf = aTempSBuf;
bIsSBufNull = TRUE32;
}
pSpareCxt = (pSECCCxt)pSBuf;
//NAND_Sync(nVBank, &nSyncRet);
#ifdef USE_SETKMODE
bLastMode = SetKMode(TRUE);
#endif
// Chip Select
NF_CE_L(nBank);
NF_WAIT_RnB(nBank);
// Read Command (Always read spare area before main area in a page
NF_CMD(CMD_READ);
NF_SET_ADDR(nPpn, BYTES_PER_MAIN_PAGE);
NF_CMD(CMD_READ_CONFIRM);
if (bInternalInterleaving == TRUE32)
{
#if 1
_TRDelay(nPpn);
#else
if (nVBank%2)
{
NF_CMD(CMD_READ_STATUS_CHIP1);
}
else
{
NF_CMD(CMD_READ_STATUS_CHIP0);
}
while(!(NF_DATA_R()&0x40));
// Dummy Command to Set Proper Pointer to Read Position after NF_WAIT_RnB()
NF_CMD(CMD_READ);
#endif
}
else
{
NF_WAIT_RnB(nBank);
// Dummy Command to Set Proper Pointer to Read Position after NF_WAIT_RnB()
NF_CMD(CMD_READ);
}
// Read Spare Area
nRet = Read_Spare(nBank, nPpn, pSpareCxt);
if ((nRet & ECC_UNCORRECTABLE_ERROR) == 0)
{
nPageReadStatus = (nRet<<16);
if (WMR_GetChkSum(&pSpareCxt->cCleanMark, 1) >= 4)
{
// Not Clean Page
bPageClean = FALSE32;
}
// Read Main Area
if(pDBuf != NULL)
{
for (nCnt=0; nCnt<nLoopCount; nCnt++)
{
if (nSctBitmap&(0x1<<nCnt))
{
nRet = Read_Sector(nBank, nPpn, nCnt, pDBuf, pSpareCxt, bPageClean);
//nPageReadStatus |= (nRet<<(nCnt*4)); // if 2KByte/Page
nPageReadStatus |= (nRet<<(nCnt*2)); // if both non-case for all-ff and 4KByte/Page
}
}
}
}
// Chip Unselect
NF_CE_H(nBank);
#ifdef USE_SETKMODE
SetKMode(bLastMode);
#endif
if(bSecondRead)
{
nPageReadStatus2nd = nPageReadStatus;
}
else
{
nPageReadStatus1st = nPageReadStatus;
}
if(bLoopNeed && !bSecondRead)
{
bSecondRead = TRUE32;
goto _B_SecondRead;
}
if(nPageReadStatus1st&PAGE_UNCORRECTABLE_ERROR_MASK || nPageReadStatus2nd&PAGE_UNCORRECTABLE_ERROR_MASK)
{
// Uncorrectable ECC Error
NAND_ERR((_T("[FIL:ERR]--NAND_Read() : Uncorrectable Error in Bank %d, Page %d [0x%08x] [0x%08x]\r\n"), nBank, nPpn, nPageReadStatus1st, nPageReadStatus));
return FIL_U_ECC_ERROR;
}
else
{
#if (WMR_READ_RECLAIM)
if (nPageReadStatus1st&PAGE_CORRECTABLE_ERROR_MASK || nPageReadStatus2nd&PAGE_CORRECTABLE_ERROR_MASK)
{
READ_ERR_FLAG = TRUE32;
NAND_MSG((_T("[FIL:INF] NAND_Read() : Correctable Error in Bank %d, Page %d [0x%08x] [0x%08x]\r\n"), nBank, nPpn, nPageReadStatus1st, nPageReadStatus2nd));
}
#endif
if (bCleanCheck&&bPageClean)
{
if (bIsSBufNull == FALSE32)
{
BOOL32 bClean;
// Check 32 bytes is all 0xFF & don't care about ECC Value
if ((pDBuf == NULL) && (bECCIn))
{
// When the pMBuf is NULL, read 128 bytes(twice read) in the spare area
if (bSecondRead)
{
pSBuf -= BYTES_PER_SPARE_PAGE;
}
bClean = _IsAllFF(pSBuf, BYTES_PER_SPARE_SUPAGE);
}
else
{
// TODO: to be changed all FF check Size
bClean = _IsAllFF(pSBuf, ((SECTORS_PER_PAGE == 8) ? NAND_MECC_OFFSET_4K : NAND_MECC_OFFSET));
}
if (bClean)
{
NAND_MSG((_T("[FIL]--NAND_Read() : FIL_SUCCESS_CLEAN\r\n")));
return FIL_SUCCESS_CLEAN;
}
else
{
NAND_MSG((_T("[FIL]--NAND_Read()[bClean==FASLE32]\r\n")));
return FIL_SUCCESS;
}
}
else
{
NAND_MSG((_T("[FIL]--NAND_Read()[bIsSBufNull != FALSE32] : FIL_SUCCESS_CLEAN\r\n")));
return FIL_SUCCESS_CLEAN;
}
}
else
{
NAND_MSG((_T("[FIL]--NAND_Read()[bCleanCheck&&bPageClean == FASLE32]\r\n")));
return FIL_SUCCESS;
}
}
}
/*****************************************************************************/
/* */
/* NAME */
/* NAND_Write */
/* DESCRIPTION */
/* This function writes NAND page area */
/* PARAMETERS */
/* nBank [IN] Physical device number */
/* nPpn [IN] Physical page number */
/* nSctBitmap [IN] The indicator for the sector to write */
/* nPlaneBitmap[IN] The indicator of the plane */
/* pDBuf [IN] Buffer pointer of main area to write */
/* pSBuf [IN] Buffer pointer of spare area to write */
/* */
/* RETURN VALUES */
/* None */
/* NOTES */
/* */
/*****************************************************************************/
VOID
NAND_Write(UINT32 nBank, UINT32 nPpn, UINT32 nSctBitmap,
UINT32 nPlaneBitmap, UINT8* pDBuf, UINT8* pSBuf)
{
UINT32 nCnt;
UINT32 nPbn;
UINT32 nPOffset;
//BOOL32 bFirstWrite = TRUE32;
BOOL32 bSecondWrite = FALSE32;
BOOL32 bLoopNeed = FALSE32;
UINT32 nSyncRet;
pSECCCxt pSpareCxt = NULL;
#ifdef USE_SETKMODE
BOOL bLastMode;
#endif
NAND_MSG((_T("[FIL] ++NAND_Write(%d, %d, 0x%02x, 0x%02x)\r\n"), nBank, nPpn, nSctBitmap, nPlaneBitmap));
if (nBank >= BANKS_TOTAL || nPpn >= PAGES_PER_BANK || (pDBuf == NULL && pSBuf == NULL))
{
NAND_ERR((_T("[FIL:ERR]--NAND_Write() : Parameter Overflow\r\n")));
WMR_ASSERT(FALSE32);
return;
}
// avoid r/b check error with internal interleaving
if (bInternalInterleaving == TRUE32)
{
aNeedSync[nBank] = TRUE32;
}
/*
In case of Internal Interleaving, the first address of the second bank should be
the half of toal block number of NAND.
For example, In 4Gbit DDP NAND, its total block number is 4096.
So, the bank 0 has 2048 blocks (Physical number : 0 ~ 2047),
the bank 1 has another 2048 blocks (Physical number : 2048 ~ 4095).
therefore, first block address of Bank 1 could be the physically 2048th block.
*/
if (bInternalInterleaving == TRUE32)
{
if ((nBank & 0x1) == 1)
{
nPpn += PAGES_PER_BANK;
}
nBank /= 2;
}
#if (WMR_STDLIB_SUPPORT)
nPbn = nPpn / PAGES_PER_BLOCK;
nPOffset = nPpn % PAGES_PER_BLOCK;
#else
nPbn = DIV(nPpn, PAGES_PER_BLOCK_SHIFT);
nPOffset = REM(nPpn, PAGES_PER_BLOCK_SHIFT);
#endif
// In case of 2-Plane Program, re-calculate the page address
if(TWO_PLANE_PROGRAM == TRUE32)
{
nPpn = nPbn * 2 * PAGES_PER_BLOCK + nPOffset;
if (nPlaneBitmap == enuBOTH_PLANE_BITMAP)
{
bLoopNeed = TRUE32;
}
else if (nPlaneBitmap == enuRIGHT_PLANE_BITMAP)
{
nPpn += PAGES_PER_BLOCK;
//nSctBitmap = nSctBitmap>>4;
}
}
nSctBitmap &= FULL_SECTOR_BITMAP_PAGE;
#ifdef USE_SETKMODE
bLastMode = SetKMode(TRUE);
#endif
// CE Select
NF_CE_L(nBank);
_B_SecondWrite:
// 2-Plane Program, page address is changed
if (bSecondWrite)
{
nPpn += PAGES_PER_BLOCK;
nSctBitmap = nSctBitmap >> SECTORS_PER_PAGE;
}
if(pSBuf == NULL)
{
pSBuf = aTempSBuf;
memset(pSBuf, 0xFF, BYTES_PER_SPARE_PAGE); // Initialize the spare buffer
}
else
{
// Set 0xFF to ECC Area
if (IS_CHECK_SPARE_ECC == TRUE32)
{
pSBuf[2] = 0xff; // Reserved
pSBuf[3] = 0xff;
//WMR_MEMSET(pSBuf+2, 0xFF, 2); // Clear Reserved area in Spare Buffer
memset(pSBuf+((SECTORS_PER_PAGE == 8) ? NAND_MECC_OFFSET_4K : NAND_MECC_OFFSET),
0xFF,
BYTES_PER_SPARE_PAGE-((SECTORS_PER_PAGE == 8) ? NAND_MECC_OFFSET_4K : NAND_MECC_OFFSET)); // Clear ECC area in Spare Buffer
}
}
pSpareCxt = (pSECCCxt)pSBuf;
pSpareCxt->cCleanMark = 0x0; // Clean mark to 0. It means that page is written
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -