📄 saftl.c
字号:
(wCacheIndex != volPrmPtr->singleUnitListHead))
{
/* Remove unit from its queue */
if(cachePtr->newerUnit != SAFTL_UNUSED_UNIT)
volPrmPtr->CT[cachePtr->newerUnit].olderUnit = cachePtr->olderUnit;
if(cachePtr->olderUnit != SAFTL_UNUSED_UNIT)
volPrmPtr->CT[cachePtr->olderUnit].newerUnit = cachePtr->newerUnit;
/* Place unit at the queue's head */
if(wChainsLength > 1) /* Unit belongs to the multi unit queue */
{
if(volPrmPtr->multiUnitListTail == wCacheIndex)
volPrmPtr->multiUnitListTail = cachePtr->newerUnit;
cachePtr->olderUnit = volPrmPtr->multiUnitListHead;
volPrmPtr->multiUnitListHead = wCacheIndex;
}
else /* Unit belongs to the single unit queue */
{
if(volPrmPtr->singleUnitListTail == wCacheIndex)
volPrmPtr->singleUnitListTail = cachePtr->newerUnit;
cachePtr->olderUnit = volPrmPtr->singleUnitListHead;
volPrmPtr->singleUnitListHead = wCacheIndex;
}
volPrmPtr->CT[cachePtr->olderUnit].newerUnit = wCacheIndex;
cachePtr->newerUnit = SAFTL_UNUSED_UNIT;
}
return cachePtr;
}
#ifndef FL_READ_ONLY
/*----------------------------------------------------------------------*/
/* m o v e F r o m M u l t i Q u e T o S i n g l e Q u e */
/* */
/* Move unit cache entry from multi unit queue to the single unit queue */
/* */
/* Parameters: */
/* volPrmPtr : Pointer identifying drive */
/* wCacheIndex : Index of cache entry to move */
/* */
/*----------------------------------------------------------------------*/
static void moveFromMultiqueueToSinglequeue(Cnand * volPrmPtr, FLWord wCacheIndex)
{
CNANDCache FAR1 * cachePtr = volPrmPtr->CT + wCacheIndex;
/* Remove cache unit from single unit cache queue */
/* Update chain pointers */
if(cachePtr->newerUnit != SAFTL_UNUSED_UNIT)
volPrmPtr->CT[cachePtr->newerUnit].olderUnit = cachePtr->olderUnit;
if(cachePtr->olderUnit != SAFTL_UNUSED_UNIT)
volPrmPtr->CT[cachePtr->olderUnit].newerUnit = cachePtr->newerUnit;
/* Update chains head\tail */
if(volPrmPtr->multiUnitListHead == wCacheIndex)
volPrmPtr->multiUnitListHead = cachePtr->olderUnit;
if(volPrmPtr->multiUnitListTail == wCacheIndex)
volPrmPtr->multiUnitListTail = cachePtr->newerUnit;
/* Place as new head of single unit cache queue */
cachePtr->olderUnit = volPrmPtr->singleUnitListHead;
if(volPrmPtr->singleUnitListHead != SAFTL_UNUSED_UNIT)
{
volPrmPtr->CT[volPrmPtr->singleUnitListHead].newerUnit = wCacheIndex;
volPrmPtr->singleUnitListHead = wCacheIndex;
}
else /* There are no units in the multi unit cache queue */
{
volPrmPtr->singleUnitListHead = wCacheIndex;
volPrmPtr->singleUnitListTail = wCacheIndex;
}
cachePtr->newerUnit = SAFTL_UNUSED_UNIT;
}
/*----------------------------------------------------------------------*/
/* m o v e F r o m S i n g l e Q u e T o M u l t i Q u e */
/* */
/* Move unit cache entry from single unit queue to the multi unit queue */
/* */
/* Parameters: */
/* volPrmPtr : Pointer identifying drive */
/* wCacheIndex : Index of cache entry to move */
/* */
/*----------------------------------------------------------------------*/
static void moveFromSinglequeueToMultiqueue(Cnand * volPrmPtr, FLWord wCacheIndex)
{
CNANDCache FAR1* cachePtr = volPrmPtr->CT + wCacheIndex;
/* Remove cache unit from single unit cache queue */
if(cachePtr->newerUnit != SAFTL_UNUSED_UNIT)
volPrmPtr->CT[cachePtr->newerUnit].olderUnit = cachePtr->olderUnit;
if(cachePtr->olderUnit != SAFTL_UNUSED_UNIT)
volPrmPtr->CT[cachePtr->olderUnit].newerUnit = cachePtr->newerUnit;
if(volPrmPtr->singleUnitListHead == wCacheIndex)
volPrmPtr->singleUnitListHead = cachePtr->olderUnit;
if(volPrmPtr->singleUnitListTail == wCacheIndex)
volPrmPtr->singleUnitListTail = cachePtr->newerUnit;
/* Place as new head of multi unit cache queue */
cachePtr->olderUnit = volPrmPtr->multiUnitListHead;
cachePtr->newerUnit = SAFTL_UNUSED_UNIT;
if(volPrmPtr->multiUnitListHead != SAFTL_UNUSED_UNIT)
{
volPrmPtr->CT[volPrmPtr->multiUnitListHead].newerUnit = wCacheIndex;
volPrmPtr->multiUnitListHead = wCacheIndex;
}
else /* There are no units in the multi unit cache queue */
{
volPrmPtr->multiUnitListHead = wCacheIndex;
volPrmPtr->multiUnitListTail = volPrmPtr->multiUnitListHead;
}
}
#endif /* FL_READ_ONLY */
/*----------------------------------------------------------------------*/
/* a l l o c a t e C a c h e U n i t */
/* */
/* Find a free index in the cache , allocate it and initialized it. */
/* */
/* Note - The routine also makes sure the last used sector of the unit */
/* is valid and in case the unit contains more then 1 unit it */
/* will be fully loaded into cache. This operation mitgh cause */
/* folding. */
/* */
/* Parameters: */
/* volPrmPtr : Pointer identifying drive */
/* wVirtualUnit : virtual unit to be cached */
/* fDoNotFold : Prevent folding in case of errors */
/* */
/* Returns: */
/* cachePtr : Pointer to virtual unit cache entry. */
/* FLStatus : flOK on success, any other value on failure. */
/*----------------------------------------------------------------------*/
static FLStatus allocateCacheUnit(Cnand * volPrmPtr,
FLWord wVirtualUnit,
FLBoolean fDoNotFold,
CNANDCache FAR1 ** cachePtr)
{
CNANDCache FAR1 * myCacheEntryPtr;
FLWord FAR1 * wSectorsPtr;
FLStatus status = flOK;
FLWord wCacheIndex,wOldestUnit;
FLWord wChainsLength = GetChainLength(volPrmPtr,wVirtualUnit);
FLWord i;
DBG_PRINT_FLOW(FLZONE_TL,"Flow debug SAFTL : Enter allocateCacheUnit routine.\r\n");
DBG_PRINT_FLOW_PRM(FLZONE_TL,(FLTXT("On virtual unit %u.\r\n"),wVirtualUnit));
/***************************/
/* Find a free cache entry */
/***************************/
if(volPrmPtr->freeCacheUnitList != SAFTL_UNUSED_UNIT)
{
/* Use a cache entry from the free cache units queue */
wCacheIndex = volPrmPtr->freeCacheUnitList;
myCacheEntryPtr = volPrmPtr->CT + wCacheIndex;
/* Remove this cache entry from the free cache units queue */
}
else /* Must remove a unit from the cache first */
{
if(volPrmPtr->singleUnitListTail != SAFTL_UNUSED_UNIT)
{
/* Use the tail of the single unit list */
wCacheIndex = volPrmPtr->singleUnitListTail;
}
else /* No single unit in the cache - remove a multi unit cache entry */
{
wCacheIndex = volPrmPtr->multiUnitListTail;
}
myCacheEntryPtr = volPrmPtr->CT + wCacheIndex;
/* Remove the current cached unit */
removeFromCache(volPrmPtr,myCacheEntryPtr);
}
volPrmPtr->freeCacheUnitList = myCacheEntryPtr->newerUnit;
/***************************************/
/* Link the new unit to its proper queue */
/***************************************/
if(wChainsLength > 1) /* Multi unit chains queues */
{
/* Place new unit at the head of the multi unit queue */
myCacheEntryPtr->olderUnit = volPrmPtr->multiUnitListHead;
volPrmPtr->multiUnitListHead = wCacheIndex;
/* Make sure the queue has a tail */
if(volPrmPtr->multiUnitListTail == SAFTL_UNUSED_UNIT)
volPrmPtr->multiUnitListTail = volPrmPtr->multiUnitListHead;
}
else
{
/* Place new unit at the head of the single unit queue */
myCacheEntryPtr->olderUnit = volPrmPtr->singleUnitListHead;
volPrmPtr->singleUnitListHead = wCacheIndex;
/* Make sure the queue has a tail */
if(volPrmPtr->singleUnitListTail == SAFTL_UNUSED_UNIT)
volPrmPtr->singleUnitListTail = volPrmPtr->singleUnitListHead;
}
myCacheEntryPtr->newerUnit = SAFTL_UNUSED_UNIT;
/* Fix previous queue head newer link */
if(myCacheEntryPtr->olderUnit != SAFTL_UNUSED_UNIT)
volPrmPtr->CT[myCacheEntryPtr->olderUnit].newerUnit = wCacheIndex;
/* Set unit cache entries */
myCacheEntryPtr->VUN = wVirtualUnit;
myCacheEntryPtr->LUN = volPrmPtr->VUT[wVirtualUnit];
DBG_PRINT_FLOW_PRM(FLZONE_TL,(FLTXT("allocateCacheUnit() allocated cache index %u.\r\n"),wCacheIndex));
/* Initialize sector cache entries */
wSectorsPtr = SectorCacheEntry(volPrmPtr,myCacheEntryPtr);
if(wChainsLength > 0) /* An existing chain */
{
/* Set all entries to uninitialzied sector entries */
for(i=0;i<volPrmPtr->sectorsInUnit;i++)
wSectorsPtr[i] = SAFTL_SECTOR_NOT_VALID;
/* Mark unit as NOT fully cached */
myCacheEntryPtr->oldGrade = SAFTL_UNUSED_UNIT;
myCacheEntryPtr->newGrade = SAFTL_UNUSED_UNIT;
/* Find last used sector and initialzied flashPtr->args.startSector with it */
if(getLastUsedSectorRAM(volPrmPtr,wVirtualUnit,myCacheEntryPtr->LUN,&wOldestUnit) == FALSE)
{
DBG_PRINT_FLOW(FLZONE_TL,"Flow debug SAFTL : Last used sector was un-initialized.\r\n");
/* Last used sector entry is not initialized - search the flash */
status = findLastUsedSectorFlash(volPrmPtr,wVirtualUnit,myCacheEntryPtr->LUN,wOldestUnit);
switch(status)
{
case flOK:
case flDataError:
/* Re-check LUN in case newest unit was erase by */
myCacheEntryPtr->LUN = volPrmPtr->VUT[wVirtualUnit];
wChainsLength = GetChainLength(volPrmPtr,wVirtualUnit);
break;
default:
/* Clear unit and last used sector entry */
DBG_PRINT_ERR(FLZONE_TL,"ERROR failed finding the last used sector.\r\n");
DBG_PRINT_ERR_PRM(FLZONE_TL,(FLTXT("On virtual unit %u.\r\n"),wVirtualUnit));
if(volPrmPtr->LUT != NULL) /* Dismount was not called */
{
volPrmPtr->LUT[wOldestUnit] = SAFTL_UNINITIALIZED_OLDEST;
removeFromCache(volPrmPtr,myCacheEntryPtr);
}
return status;
}
} /* End if - was last used sector initialized */
/* Finish loading the unit - multi unit is full loaded into cache */
/* and in case last sector is bad fold out of place */
if((wChainsLength > 1 ) /* Multi unit chain */
#ifndef FL_READ_ONLY
|| (status == flDataError) /* Bad last used sector */
#endif /* FL_READ_ONLY */
)
{
DBG_PRINT_FLOW(FLZONE_TL,"Flow debug SAFTL : Loading the unit into the cache.\r\n");
checkStatus(loadUnitIntoCache(volPrmPtr,myCacheEntryPtr));
#ifndef FL_READ_ONLY
if(status == flDataError)
{
/* Force last used sector to be updated */
volPrmPtr->LUT[wOldestUnit] = SAFTL_UNINITIALIZED_OLDEST;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -