📄 celltable.c
字号:
* allow a check to make sure there is only one of these
* blocks.
* If there are more then something went wrong.
*/
if (lpBlockInProcess == NULL){
lwCellIndexOfBlockInProcess = awCellIndex;
lpBlockInProcess = pTmpEntry;
return No_Error;
} else {
free(pTmpEntry);
return More_Than_Two_Dirty_Cells;
}
}
return No_Error;
}
/**
* dms_CellTableAddAvailableBlock
* Adds block to BlockAlloc's AvailableBlockList.
* Interface function so only CellTable interfaces with BlockAlloc.
*
* Prerequisites:
* dms_CellTableInitialize()
* Uses:
* dms_BlockAddAvailable()
* Used By:
* dms_SectorInitialize()
*/
DMS_STATUS dms_CellTableAddAvailableBlock(WORD awSectorIndex, WORD awSectorBlockIndex){
return dms_BlockAddAvailable(awSectorIndex,awSectorBlockIndex);
}
/**
* dms_CellTableAddGarbageBlock
* Adds block to BlockAlloc's AvailableBlockList.
* Interface function so only CellTable interfaces with BlockAlloc.
*
* Prerequisites:
* dms_CellTableInitialize()
* Uses:
* dms_BlockAddAvailable()
* Used By:
* dms_SectorInitialize()
*/
void dms_CellTableAddGarbageBlock(WORD awSectorIndex, WORD awSectorBlockIndex){
dms_BlockIncrementGarbageCount(awSectorIndex);
}
/**
* dms_CellTableGetBestSectorToErase
* Computes the best sector to erase based on the dirty count in each
* sector.
* Interface function so only CellTable interfaces with BlockAlloc.
*
* Prerequisites:
* dms_CellTableInitialize()
* dms_CellTableCheckValidity()
* Uses:
* dms_BlockGetBestSectorToErase()
* Used By:
* dms_SectorCleanup()
*/
DMS_STATUS dms_CellTableGetBestSectorToErase(WORD *apwSectorIndex){
return dms_BlockGetBestSectorToErase(apwSectorIndex);
}
/**
* dms_CellTableIsBlockAvailable()
* Returns non-zero if the number of available blocks is above the minimum
* allowable free blocks.
* Interface function so only CellTable interfaces with BlockAlloc.
*
* Prerequisites:
* dms_CellTableInitialize()
* dms_CellTableCheckValidity()
* Uses:
* dms_BlockAllocIsAvailable()
* Used By:
* dms_CellInitialize()
*/
BYTE dms_CellTableIsBlockAvailable(void){
return dms_BlockAllocIsAvailable();
}
/**
* dms_CellTableGetAvailableBlock
* Puts new block in CellTable.
* Returns Duplicate_Block if block already exists.
* Returns No_Available_Blocks if minumum free block threshold is reached
* and a cleanup is needed.
*
* Prerequisites:
* dms_CellTableInitialize()
* dms_CellTableCheckValidity()
* Uses:
* dms_BlockAlloc()
* dms_lCellTableInsertBlock()
* Used By:
* dms_CellWrite()
*/
DMS_STATUS dms_CellTableGetAvailableBlock(WORD awCellIndex, WORD awBlockIndex,
WORD *apwSectorIndex, WORD *apwSectorBlockIndex){
CELL_TABLE_ENTRY *pEntry;
DMS_STATUS eStatus;
pEntry = dms_BlockAlloc();
if (pEntry == NULL){
return No_Available_Blocks;
}
pEntry->wBlockIndex = awBlockIndex;
*apwSectorIndex = pEntry->wSectorIndex;
*apwSectorBlockIndex = pEntry->wSectorBlockIndex;
eStatus = dms_lCellTableInsertBlock(&lpCellTable[awCellIndex],pEntry);
if (eStatus != No_Error){
return eStatus;
}
return No_Error;
}
/**
* dms_CellTableCheckValidity
* Determines which version of cell should be deleted if one was in
* process during a power failure.
* Defines cell size for each cell by counting the blocks that were added
* by dms_CellTableAddBlock()
* Checks:
* 1. missing blocks in a cell.
* 2. each cell has at least one block.
*
* Prerequisites:
* dms_CellTableInitialize()
* Uses:
* dms_lCellTableCheckCellInProcess()
* dms_CellInfoGetCount()
* dms_lCellTableCountAndCheckBlocks()
* dms_CellInfoDefineCellBlockCount()
* dms_CellInfoCheckValidity()
* dms_BlockAllocComputeMinimumAllowableBlocksFree()
* dms_SectorInfoGetLargestSectorBlockCount()
* dms_CellInfoGetTotalBlockCount()
* dms_SectorInfoGetTotalBlockCount()
* Used By:
* dms_CellInitialize()
*/
DMS_STATUS dms_CellTableCheckValidity(void){
DMS_STATUS eStatus;
WORD wCellIndex;
WORD wBlockCount;
/* Move any in process blocks or cells to the in process location. */
dms_lCellTableCheckCellInProcess();
/*
* Check each block of each cell and make sure no blocks are missing
* If cell is completly empty then that will be caught later by
* dms_CellInfoCheckValidity
*/
for (wCellIndex = 0; wCellIndex < dms_CellInfoGetCount(); wCellIndex++){
eStatus = dms_lCellTableCountAndCheckBlocks(lpCellTable[wCellIndex], &wBlockCount);
if (eStatus != No_Error) {
return eStatus;
}
dms_CellInfoDefineCellBlockCount(wCellIndex,wBlockCount);
}
/* Check cell size */
eStatus = dms_CellInfoCheckValidity();
if (eStatus != No_Error){
return eStatus;
}
/* calculate the minimum number of free blocks allowed. */
/* This can be done now because the largest cell size is known at this time. */
dms_BlockAllocComputeMinimumAllowableBlocksFree( dms_SectorInfoGetLargestSectorBlockCount(),
dms_CellInfoGetLargestCellBlockCount());
if (dms_CellInfoGetTotalBlockCount() >= (WORD) (dms_SectorInfoGetTotalBlockCount()
- dms_SectorInfoGetLargestSectorBlockCount()
- dms_CellInfoGetLargestCellBlockCount())){
return Not_Enough_Free_Blocks;
}
/* Validity Check Passed */
return No_Error;
}
/**
* dms_CellTableSetCellInProcess
* Moves list of the specified cell from the CellTable
* to CellInProcessList.
* This is done during a cell write where the new cell blocks
* are added to the CellTable and the CellInProcess cell
* is deleted after all new blocks are written.
* The CellInProcess is deleted by dms_CellTableDeleteCellInProcess().
*
* Prerequisites:
* dms_CellTableInitialize()
* dms_CellTableCheckValidity()
* Uses:
* Nothing outside this file.
* Used By:
* dms_CellWrite();
*/
DMS_STATUS dms_CellTableSetCellInProcess(WORD awCellIndex){
if (lpCellInProcess != NULL) {
return Cell_Already_In_Process;
}
/* Move cell to cell in process */
lpCellInProcess = lpCellTable[awCellIndex];
lpCellTable[awCellIndex] = NULL;
lwCellIndexOfCellInProcess = awCellIndex;
return No_Error;
}
/**
* dms_CellTableMoveBlock
* Called during Cleanups to move blocks. It removes
* the specified block from the CellTable or CellInProcessList, gets a new
* block using dms_BlockAllocNoMinimum() inserts the new block in the
* CellTable or CellInProcessList, and provides the SectorIndex and
* SectorBlockIndex of the new Block.
* It does not add the old block to the GarbageCount because it assums
* that this is being called during a cleanup where the GarbageCount is
* already set to zero by dms_CellTableGetBestSectorToErase().
*
* Prerequisites:
* dms_CellTableInitialize()
* dms_CellTableCheckValidity()
* Uses:
* dms_lCellTableRemoveExactBlock()
* dms_BlockAllocNoMinimum()
* dms_lCellTableInsertBlock()
* free()
* Used By:
* dms_SectorCleanup()
*/
DMS_STATUS dms_CellTableMoveBlock(WORD awSectorIndex, WORD awSectorBlockIndex,
WORD awCellIndex,
WORD *apwNewSectorIndex, WORD *apwNewSectorBlockIndex){
CELL_TABLE_ENTRY *pEntry;
DMS_STATUS eStatus;
CELL_TABLE_ENTRY **ppTablePointer;
/* Set Block as block in process */
if (lpBlockInProcess != NULL) {
return Block_Already_In_Process;
}
/* Move block to block in process */
ppTablePointer = &lpCellTable[awCellIndex];
lpBlockInProcess = dms_lCellTableRemoveExactBlock(ppTablePointer,awSectorIndex,awSectorBlockIndex);
if (lpBlockInProcess == NULL) {
/* the requested block must be in the cell in process */
if (lwCellIndexOfCellInProcess != awCellIndex){
return Block_Not_Found;
}
ppTablePointer = &lpCellInProcess; /* ppTablePointer is used below to insert the new block into the correct table */
lpBlockInProcess = dms_lCellTableRemoveExactBlock(ppTablePointer,awSectorIndex,awSectorBlockIndex);
if (lpBlockInProcess == NULL) {
return Block_Not_Found;
}
}
lwCellIndexOfBlockInProcess = awCellIndex;
/* Get New Block */
pEntry = dms_BlockAllocNoMinimum();
if (pEntry == NULL){
return No_Available_Blocks;
}
pEntry->wBlockIndex = lpBlockInProcess->wBlockIndex;
*apwNewSectorIndex = pEntry->wSectorIndex;
*apwNewSectorBlockIndex = pEntry->wSectorBlockIndex;
eStatus = dms_lCellTableInsertBlock(ppTablePointer,pEntry);
if (eStatus != No_Error){
free(pEntry);
return eStatus;
}
/*
* Do not call dms_BlockFree because the sector dirty block count was set to zero
* earlier when the best sector to erase was gotten. calling dms_BlockFree
* will cause the sector dirty block count to increment.
*/
free(lpBlockInProcess);
lpBlockInProcess = NULL;
return No_Error;
}
/**
* dms_CellTableDeleteCellInProcess
* Returns zero if CellInProcess is empty.
* If there are blocks in CellInProcess then the first block in the cell
* is deleted from the list, added to the garbage count, apwSectorIndex and
* apwSectorBlockIndex are set so the caller can write the erase status in
* the flash.
* This function should be called repeatly untill it returns 0 (all blocks
* are removed from the list)
*
* Prerequisites:
* dms_CellTableInitialize()
* dms_CellTableCheckValidity()
* Uses:
* dms_BlockFree()
* Used By:
* dms_CellInitialize()
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -