📄 ftllite.c
字号:
sectorInPage * sizeof(LogicalAddress);
oldAddress = LE4(*(LEulong FAR0 *)
vol.flash.map(&vol.flash,virtualMapEntryAddress,sizeof(LogicalAddress)));
}
if (newAddress == DELETED_ADDRESS && ((unsigned long)oldAddress == UNASSIGNED_ADDRESS))
return flOK;
toLE4(addressToWrite,(LogicalAddress) newAddress << SECTOR_SIZE_BITS);
if (cannotWriteOver(LE4(addressToWrite),oldAddress)) {
FLStatus status;
if (pageNo != vol.replacementPageNo ||
updatedPage == vol.replacementPageAddress) {
if (vol.replacementPageNo != UNASSIGNED_SECTOR)
checkStatus(closeReplacementPage(&vol));
checkStatus(allocateAndWriteSector(&vol,pageNo,NULL,TRUE));
}
status = flashWrite(&vol,
logical2Physical(&vol,vol.replacementPageAddress) +
sectorInPage * sizeof(LogicalAddress),
&addressToWrite,
sizeof addressToWrite,
0);
if (status != flOK) {
closeReplacementPage(&vol);
/* we may get a write-error because a
previous cache update did not complete. */
return status;
}
toLE4(addressToWrite,DELETED_ADDRESS);
updatedPage = vol.pageTable[pageNo];
}
checkStatus(flashWrite(&vol,
logical2Physical(&vol,updatedPage) +
sectorInPage * sizeof(LogicalAddress),
&addressToWrite,
sizeof addressToWrite,
(unsigned long)oldAddress != UNASSIGNED_ADDRESS));
#ifndef SINGLE_BUFFER
if (buffer.sectorNo == pageNo && buffer.owner == &vol)
toLE4(mapCache[sectorInPage],(LogicalAddress) newAddress << SECTOR_SIZE_BITS);
#endif
return deleteLogicalSector(&vol,(LogicalSectorNo) (oldAddress >> SECTOR_SIZE_BITS));
}
/*----------------------------------------------------------------------*/
/* c h e c k F o r W r i t e I n p l a c e */
/* */
/* Checks possibility for writing Flash data inplace. */
/* */
/* Parameters: */
/* newData : New data to write. */
/* oldData : Old data at this location. */
/* */
/* Returns: */
/* < 0 => Writing inplace not possible */
/* >= 0 => Writing inplace is possible. Value indicates */
/* how many bytes at the start of data are */
/* identical and may be skipped. */
/*----------------------------------------------------------------------*/
static int checkForWriteInplace(long FAR1 *newData,
long FAR0 *oldData)
{
int i;
int skipBytes = 0;
FLBoolean stillSame = TRUE;
for (i = SECTOR_SIZE / sizeof *newData; i > 0; i--, newData++, oldData++) {
if (cannotWriteOver(*newData,*oldData))
return -1;
if (stillSame && *newData == *oldData)
skipBytes += sizeof *newData;
else
stillSame = FALSE;
}
return skipBytes;
}
/*----------------------------------------------------------------------*/
/* i n i t F T L */
/* */
/* Initializes essential volume data as a preparation for mount or */
/* format. */
/* */
/* Parameters: */
/* vol : Pointer identifying drive */
/* */
/* Returns: */
/* FLStatus : 0 on success, failed otherwise */
/*----------------------------------------------------------------------*/
static FLStatus initFTL(Flare vol)
{
long int size = 1;
for (vol.erasableBlockSizeBits = 0; size < vol.flash.erasableBlockSize;
vol.erasableBlockSizeBits++, size <<= 1);
vol.unitSizeBits = vol.erasableBlockSizeBits;
if (vol.unitSizeBits < 16)
vol.unitSizeBits = 16; /* At least 64 KB */
vol.noOfUnits = (unsigned) ((vol.flash.noOfChips * vol.flash.chipSize) >> vol.unitSizeBits);
vol.unitOffsetMask = (1L << vol.unitSizeBits) - 1;
vol.sectorsPerUnit = 1 << (vol.unitSizeBits - SECTOR_SIZE_BITS);
vol.bamOffset = sizeof(UnitHeader);
vol.unitHeaderSectors = ((allocEntryOffset(&vol,vol.sectorsPerUnit) - 1) >>
SECTOR_SIZE_BITS) + 1;
vol.transferUnit = NULL;
vol.replacementPageNo = UNASSIGNED_SECTOR;
vol.badFormat = TRUE; /* until mount completes */
vol.mappedSectorNo = UNASSIGNED_SECTOR;
vol.currWearLevelingInfo = 0;
#ifdef BACKGROUND
vol.unitEraseInProgress = NULL;
vol.garbageCollectStatus = flOK;
vol.mirrorOffset = 0;
#endif
return flOK;
}
/*----------------------------------------------------------------------*/
/* i n i t T a b l e s */
/* */
/* Allocates and initializes the dynamic volume table, including the */
/* unit tables and secondary virtual map. */
/* */
/* Parameters: */
/* vol : Pointer identifying drive */
/* */
/* Returns: */
/* FLStatus : 0 on success, failed otherwise */
/*----------------------------------------------------------------------*/
static FLStatus initTables(Flare vol)
{
VirtualSectorNo iSector;
UnitNo iUnit;
/* Allocate the conversion tables */
#ifdef MALLOC_TFFS
vol.physicalUnits = (Unit *) MALLOC_TFFS(vol.noOfUnits * sizeof(Unit));
vol.logicalUnits = (UnitPtr *) MALLOC_TFFS(vol.noOfUnits * sizeof(UnitPtr));
vol.pageTable = (LogicalSectorNo *)
MALLOC_TFFS(vol.directAddressingSectors * sizeof(LogicalSectorNo));
if (vol.physicalUnits == NULL ||
vol.logicalUnits == NULL ||
vol.pageTable == NULL)
return flNotEnoughMemory;
#else
char *heapPtr;
heapPtr = vol.heap;
vol.physicalUnits = (Unit *) heapPtr;
heapPtr += vol.noOfUnits * sizeof(Unit);
vol.logicalUnits = (UnitPtr *) heapPtr;
heapPtr += vol.noOfUnits * sizeof(UnitPtr);
vol.pageTable = (LogicalSectorNo *) heapPtr;
heapPtr += vol.directAddressingSectors * sizeof(LogicalSectorNo);
if (heapPtr > vol.heap + sizeof vol.heap)
return flNotEnoughMemory;
#endif
#ifndef SINGLE_BUFFER
vol.volBuffer = flBufferOf(flSocketNoOf(vol.flash.socket));
#endif
buffer.sectorNo = UNASSIGNED_SECTOR;
for (iSector = 0; iSector < vol.directAddressingSectors; iSector++)
vol.pageTable[iSector] = UNASSIGNED_SECTOR;
for (iUnit = 0; iUnit < vol.noOfUnits; iUnit++)
vol.logicalUnits[iUnit] = NULL;
return flOK;
}
/*----------------------------------------------------------------------*/
/* m a p S e c t o r */
/* */
/* Maps and returns location of a given sector no. */
/* NOTE: This function is used in place of a read-sector operation. */
/* */
/* A one-sector cache is maintained to save on map operations. */
/* */
/* Parameters: */
/* vol : Pointer identifying drive */
/* sectorNo : Sector no. to read */
/* physAddress : Optional pointer to receive sector address */
/* */
/* Returns: */
/* Pointer to physical sector location. NULL returned if sector */
/* does not exist. */
/*----------------------------------------------------------------------*/
static const void FAR0 *mapSector(Flare vol, SectorNo sectorNo, CardAddress *physAddress)
{
if (sectorNo != vol.mappedSectorNo || vol.flash.socket->remapped) {
LogicalSectorNo sectorAddress;
if (sectorNo >= vol.virtualSectors)
vol.mappedSector = NULL;
else {
sectorAddress = virtual2Logical(&vol,sectorNo + vol.noOfPages);
if (sectorAddress == UNASSIGNED_SECTOR || sectorAddress == DELETED_SECTOR)
vol.mappedSector = NULL; /* no such sector */
else {
vol.mappedSectorAddress = logical2Physical(&vol,sectorAddress);
vol.mappedSector = vol.flash.map(&vol.flash,
vol.mappedSectorAddress,
SECTOR_SIZE);
}
}
vol.mappedSectorNo = sectorNo;
vol.flash.socket->remapped = FALSE;
}
if (physAddress)
*physAddress = vol.mappedSectorAddress;
return vol.mappedSector;
}
/*----------------------------------------------------------------------*/
/* w r i t e S e c t o r */
/* */
/* Writes a sector. */
/* */
/* Parameters: */
/* vol : Pointer identifying drive */
/* sectorNo : Sector no. to write */
/* */
/* Returns: */
/* FLStatus : 0 on success, failed otherwise */
/*----------------------------------------------------------------------*/
static FLStatus writeSector(Flare vol, SectorNo sectorNo, void FAR1 *fromAddress)
{
LogicalSectorNo oldSectorAddress;
int skipBytes;
FLStatus status;
if (vol.badFormat)
return flBadFormat;
if (sectorNo >= vol.virtualSectors)
return flSectorNotFound;
sectorNo += vol.noOfPages;
oldSectorAddress = virtual2Logical(&vol,sectorNo);
if (oldSectorAddress != UNASSIGNED_SECTOR && oldSectorAddress != DELETED_SECTOR &&
(skipBytes = checkForWriteInplace((long FAR1 *) fromAddress,
(long FAR0 *) mapLogical(&vol,oldSectorAddress))) >= 0) {
if (skipBytes < SECTOR_SIZE)
status = flashWrite(&vol,
logical2Physical(&vol,oldSectorAddress) + skipBytes,
(char FAR1 *) fromAddress + skipBytes,
SECTOR_SIZE - skipBytes,
OVERWRITE);
else
status = flOK; /* nothing to write */
}
else
status = allocateAndWriteSector(&vol,sectorNo,fromAddress,FALSE);
if (status == flWriteFault) /* Automatic retry */
status = allocateAndWriteSector(&vol,sectorNo,fromAddress,FALSE);
return status;
}
/*----------------------------------------------------------------------*/
/* t l S e t B u s y */
/* */
/* Notifies the start and end of a file-system operation. */
/* */
/* Parameters: */
/* vol : Pointer identifying drive */
/* state : TFFS_ON (1) = operation entry */
/* TFFS_OFF(0) = operation exit */
/* */
/*----------------------------------------------------------------------*/
static void tlSetBusy(Flare vol, FLBoolean state)
{
#ifdef BACKGROUND
if (vol.unitEraseInProgress)
flBackground(state == TFFS_ON ? BG_SUSPEND : BG_RESUME);
#endif
}
/*----------------------------------------------------------------------*/
/* d e l e t e S e c t o r */
/* */
/* Marks contiguous sectors as deleted */
/* */
/* Parameters: */
/* vol : Pointer identifying drive */
/* sectorNo : First sector no. to delete */
/* noOfSectors : No. of sectors to delete */
/* */
/* Returns: */
/* FLStatus : 0 on success, failed otherwise */
/*----------------------------------------------------------------------*/
static FLStatus deleteSector(Flare vol, SectorNo sectorNo, int noOfSectors)
{
int iSector;
if (vol.badFormat)
return flBadFormat;
if (sectorNo + noOfSectors > vol.virtualSectors)
return flSectorNotFound;
sectorNo += vol.noOfPages;
for (iSector = 0; iSector < noOfSectors; iSector++, sectorNo++)
checkStatus(setVirtualMap(&vol,sectorNo,DELETED_SECTOR));
return flOK;
}
#ifdef FORMAT_VOLUME
/*----------------------------------------------------------------------*/
/* s e c t o r s I n V o l u m e */
/* */
/* Gets the total number of sectors in the volume */
/* */
/* Parameters: */
/* vol : Pointer identifying drive */
/* */
/* Returns: */
/* Number of sectors in the volume */
/*----------------------------------------------------------------------*/
static SectorNo sectorsInVolume(Flare vol)
{
return vol.virtualSectors;
}
/*----------------------------------------------------------------------*/
/* f o r m a t F T L */
/* */
/* Formats the Flash volume for FTL */
/* */
/* Parameters: */
/* volNo : Volume no. */
/* formatParams : Address of FormatParams structure to use */
/*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -