📄 nandlump.c
字号:
/*************************************************************
Function: RD_freeLump_r
Description:
release a disk lump back to the NAND_FFS
Input:
lumpNo - the number of the lump that is going to be released
Output:
**************************************************************/
void NAND_FFS_freeLump_r(int lumpNo)
{
int i;
int block, nthEntry;
unsigned char *base;
int *src;
#ifdef NAND_FFS_DEBUG
sprintf(NAND_FFS_DebugString, "[NAND_FFS_freeLump] lumpNo: %d", lumpNo);
SprintStringLn(NAND_FFS_DebugString);
#endif
if (lumpNo == NAND_END_LUMP)
return;
NAND_lump2Block(lumpNo, &block, &nthEntry);
if (block == -1 || nthEntry == -1)
{
// errno set by NAND_lump2Block()
return;
}
// continue next block if the current one is not usable for AP storage
if (NAND_FFS_Block[block] == NAND_FB_UNUSED)
return;
#ifdef NAND_FFS_DEBUG
sprintf(NAND_FFS_DebugString, "[NAND_FFS_freeLump] Erasing block %d", lumpNo);
SprintStringLn(NAND_FFS_DebugString);
#endif
if (NAND_FFS_readBlock(block, &base, 0) == -1)
return;
if (NAND_FFS_eraseFlashBlock(block) == -1)
{
#ifdef NAND_FFS_DEBUG
sprintf(NAND_FFS_DebugString, "[NAND_FFS_freeLump] Erase block %d error", lumpNo);
SprintStringLn(NAND_FFS_DebugString);
#endif
// errno set by NAND_FFS_eraseFlashBlock()
return;
}
// !!NOTE: we assume any int type contains 4 bytes
src = (int *) ((unsigned long)base + NAND_LUMP_SIZE * nthEntry);
for (i = 0; i < NAND_LUMP_SIZE; i+=sizeof(int))
*src++ = 0xFFFFFFFF;
// set NAND_FFS_lumpMapTable
NAND_FFS_lumpMapTable[lumpNo/8] &= ~(1 << (lumpNo%8));
// restore those used lumps
for (i = 0; i < NAND_LumpNum; i++)
{
if (i != nthEntry)
{
if (NAND_FFS_writeLump(block*NAND_LumpNum+i, base + i*NAND_LUMP_SIZE) == -1)
return;
}
}
NAND_FFS_Block[block] = NAND_FB_OK;
}
/*************************************************************
Function: NAND_getNextLump
Description:
get the total data size in a link of lumps
Input:
lump - the target lump
Output:
the next lump
**************************************************************/
/* marked by chilong 12/20/2001 temporarily
int NAND_getNextLump(int lump)
{
// int block;
// int nthEntry;
struct NAND_diskLump *lumpPtr;
lumpPtr = NAND_readLumpStructure(lump, 0);
if (lumpPtr == NULL)
{
// errno set by NAND_readLumpStructure()
return NAND_END_LUMP;
}
return(lumpPtr->nextLump);
}
marked by chilong 12/20/2001 temporarily */
/*************************************************************
Function: NAND_totalDataSizeInLumpLink
Description:
get the total data size in a link of lumps
Input:
lump - the beginning lump
Output:
the total data size
**************************************************************/
/* marked by chilong 12/20/2001 temporarily
unsigned long NAND_totalDataSizeInLumpLink(int lump)
{
unsigned long totalSize = 0;
// int block;
// int nthEntry;
struct NAND_diskLump *lumpPtr;
#ifdef NAND_FFS_DEBUG
sprintf(NAND_FFS_DebugString, "[NAND_totalDataSizeInLumpLink] lump=%d", lump);
SprintStringLn(NAND_FFS_DebugString);
#endif
// loop through the lump link
while (lump != NAND_END_LUMP)
{
lumpPtr = NAND_readLumpStructure(lump, 0);
if (lumpPtr == NULL)
{
// errno set by NAND_readLumpStructure()
return totalSize;
}
totalSize += lumpPtr->dataSize;
lump = lumpPtr->nextLump;
}
#ifdef NAND_FFS_DEBUG
sprintf(NAND_FFS_DebugString, " size=%d", totalSize);
SprintStringLn(NAND_FFS_DebugString);
#endif
return totalSize;
}
marked by chilong 12/20/2001 temporarily */
/*************************************************************
Function: NAND_deleteLumpChain
Description:
delete the lumps in the chain
Input:
beginLump - the beginning lump
keepFirst - keep the first lump in the link?
0: no
1: yes
dataSize - the size of data to be kept if keepFirst is 1
Output:
0 succeeded
1 failed - memory allocation error
2 failed - flash write error
3 failed - flash read error
4 failed - invalid block
**************************************************************/
/* marked by chilong 12/20/2001 temporarily
int NAND_deleteLumpChain(int beginLump, int keepFirst, unsigned long dataSize)
{
struct dLinkList lumpList;
struct dLinkList *currLumpNode;
struct dLinkList *prevLumpNode;
int currLump;
int prevFBlock;
int *des;
int i;
int block;
int nthEntry;
int *base;
struct NAND_diskLump *lumpPtr;
initDLinkList(&lumpList);
// build the lump list sorted by lump addresses in ascending order
// this list allows the lumps located in the same flash block to be
// easily located and handled as a batch
currLump = beginLump;
if (keepFirst == 1)
keepFirst = beginLump;
else
keepFirst = NAND_END_LUMP;
while (currLump != NAND_END_LUMP)
{
// insert the current lump into the lump list
currLumpNode = lumpList.back;
prevLumpNode = &lumpList;
// find a appropriate position in the list for the current lump
while (currLumpNode != NULL)
{
if ((unsigned long)currLump < (unsigned long)(currLumpNode->elementPointer))
{
// the address in the current node is larger
// the new node should be inserted before the current node
break;
}
prevLumpNode = currLumpNode;
currLumpNode = currLumpNode->back;
}
// the new node is inserted behind prevLumpNode
currLumpNode = (struct dLinkList *)sc_malloc(sizeof(struct dLinkList));
if (currLumpNode == NULL)
{
// allocation failed
freeDLinkList(&lumpList);
NAND_FFS_Errno = ERROR_ALLOC_MEM;
return 1;
}
// setup lump node information for the current lump
currLumpNode->elementPointer = (void *)currLump;
currLumpNode->prev = prevLumpNode;
currLumpNode->back = prevLumpNode->back;
// update links
prevLumpNode->back = currLumpNode;
if (currLumpNode->back != NULL)
((struct dLinkList *)(currLumpNode->back))->prev = currLumpNode;
// get next lump
currLump = NAND_getNextLump(currLump);
}
// the lump list has been built, start erasing
prevFBlock = NAND_END_LUMP;
currLumpNode = lumpList.back;
base = NULL;
while (currLumpNode != NULL)
{
// find the flash block in which the lump is stored and its location in the block
NAND_lump2Block((int)currLumpNode->elementPointer, &block, &nthEntry);
if (block != -1 && nthEntry != -1)
{
// flash block number is valid, proceed with delete
// To limit erase count, we collect all lumps stored in the same flash block
// and delete them all in one erase.
// Note that all lumps are already sorted ascendingly according to their addresses
// in above.
if (prevFBlock != block)
{
// a new block will be needed, write back the previous block
if (prevFBlock != NAND_END_LUMP && base != NULL)
{
// the previous block has been completed
// write the block back to flash
if (NAND_FFS_writeBlock(prevFBlock, (unsigned char *)base) == -1)
{
// flash erase error
freeDLinkList(&lumpList);
// errno set by NAND_FFS_writeBlock()
return 2;
}
}
// read the new flash block in buffer
prevFBlock = block;
if (NAND_FFS_readBlock(block, (unsigned char **)&base) == -1)
{
freeDLinkList(&lumpList);
// errno set by NAND_FFS_readBlock()
return 3;
}
if (base == NULL)
{
NAND_FFS_Errno = ERROR_FLASH_BLOCK_READ;
return -1;
}
}
// the corresponding flash block is within the buffer, erase the part that
// belongs to the current lump if it needs not be spared
if (keepFirst == (int)currLumpNode->elementPointer && keepFirst != NAND_END_LUMP)
{
sysTime now;
// have to keep this first lump, but the lump information have to be updated
lumpPtr = (struct NAND_diskLump *)((unsigned long)base + NAND_LUMP_SIZE * nthEntry);
lumpPtr->dataSize = dataSize;
sc_getTime(&now);
lumpPtr->updateTime = (now.hour << 11) + (now.minute << 5) + (now.second >> 1);
lumpPtr->updateDate = (now.year << 9) + (now.month << 5) + now.day;
lumpPtr->nextLump = NAND_END_LUMP;
keepFirst = NAND_END_LUMP;
}
else
{
// this block can be totally deleted
des = (int *)((unsigned long)base + NAND_LUMP_SIZE * nthEntry);
for (i = 0; i < NAND_LUMP_SIZE; i += sizeof(int))
*des++ = 0xFFFFFFFF;
// at least one lump in the current block is freed, the block is
// absolutely not full
// NAND_FFS_EraseCount[block] = NAND_FFS_EraseCount[block] & (~NAND_BLOCK_FULL_BIT_MASK);
NAND_FFS_Block[block] = NAND_FB_OK;
}
}
currLumpNode = currLumpNode->back;
}
// the last flash block has not yet been written to flash
if (prevFBlock != NAND_END_LUMP && base != NULL)
{
// the previous block has been completed
// write the block back to flash
if (NAND_FFS_writeBlock(prevFBlock, (unsigned char *)base) == -1)
{
// flash erase error
freeDLinkList(&lumpList);
// errno set by NAND_FFS_writeBlock()
return 2;
}
}
freeDLinkList(&lumpList);
return 0;
}
marked by chilong 12/20/2001 temporarily */
/*************************************************************
Function: NAND_checkBadLump
Description:
check if the requested lump can be used
Input:
lumpNo - the lump number
Output:
0 - ok
-1 - bad
Note:
**************************************************************/
int NAND_checkBadLump(int lumpNo)
{
#if 0
int i;
int numPagesOfLump;
numPagesOfLump = NAND_LUMP_SIZE / NFLASH_FRAME_SIZE;
for ( i=0;i< numPagesOfLump;i++ )
{
//jason if (!(nfshCheckBadPage(NAND_FFS_START_BLOCK*NAND_FLASH_BLOCK_SIZE + lumpNo*NAND_LUMP_SIZE+i*NFLASH_FRAME_SIZE)) )
// return -1;
}
return 0;
#endif
if ( nfshCheckBadBlock( (unsigned long) NAND_FFS_START_BLOCK*NAND_FLASH_BLOCK_SIZE + lumpNo*NAND_LUMP_SIZE ) )
return 0;
else
return -1;
}
/*************************************************************
Function: NAND_countFreeLumpsInBlock
Description:
counts the number of free lumps in a flash block
Input:
block - the specified flash block
pNthLumpEntry - the pointer to the lump entry which will
be used in NAND_findFreeLump()
Output:
number of free lumps
-1 if the block is invalid
Note:
Note that NAND_FFS_readBlock() read block content into
its internal buffer.
**************************************************************/
/**** modified by chilong 01/17/2002 ****/
int NAND_countFreeLumpsInBlock(int block, int *pNthLumpEntry)
{
int count;
int i;
int lump;
// marked by chilong 01/25/2002
struct NAND_diskLump *lumpPtr;
count = 0;
// lump now points to the head of the internal buffer of NAND_FFS_readBlock()
// check every lump in the buffer
lump = block * NAND_LumpNum;
for (i = 0; i < NAND_LumpNum; i++)
{
if( ((NAND_FFS_lumpMapTable[(lump+i)/8] >> ((lump+i)%8)) & 0x01) == 0x01)
continue;
// added by chilong 01/25/2002
count++;
/* marked by chilong 01/25/2002
// chilong: NAND_readLumpStructe has invoked checkLump() to check
// if the lump is bad or out of bound
lumpPtr = NAND_readLumpStructure(lump+i, 2);
if (lumpPtr != NULL)
{
count++;
if (*pNthLumpEntry == NAND_END_LUMP)
*pNthLumpEntry = i;
}
lumpPtr = (struct NAND_diskLump *)((unsigned long)lumpPtr + NAND_LUMP_SIZE);
marked by chilong 01/25/2002 */
}
if (count == 0)
{
// the block is full
// NAND_FFS_EraseCount[block] = NAND_FFS_EraseCount[block] | NAND_BLOCK_FULL_BIT_MASK;
NAND_FFS_Block[block] = NAND_FB_FULL;
}
return count;
}
/**** modified by chilong 01/17/2002 ****/
/* marked by chilong 01/17/2002
int NAND_countFreeLumpsInBlock(int block)
{
int count;
int i;
int lump;
struct NAND_diskLump *lumpPtr;
count = 0;
// lump now points to the head of the internal buffer of NAND_FFS_readBlock()
// check every lump in the buffer
lump = block * NAND_LumpNum;
for (i = 0; i < NAND_LumpNum; i++)
{
lumpPtr = NAND_readLumpStructure(lump, 2);
if (lumpPtr != NULL)
// if (lumpPtr->type == NAND_LUMP_TYPE_FREE)
count++;
// lumpPtr = (struct NAND_diskLump *)((unsigned long)lumpPtr + NAND_LUMP_SIZE);
}
if (count == 0)
{
// the block is full
// NAND_FFS_EraseCount[block] = NAND_FFS_EraseCount[block] | NAND_BLOCK_FULL_BIT_MASK;
NAND_FFS_Block[block] = NAND_FB_FULL;
}
return count;
}
marked by chilong 01/17/2002 */
/*************************************************************
Function: NAND_findFreeLump
Description:
find a free lump
Input:
none
Output:
the lump number
NAND_END_LUMP if error
**************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -