📄 ftllite.c
字号:
{ unsigned iSector; LEulong FAR0 *blockAllocMap; UnitHeader FAR0 *unitHeader; Unit *allocationUnit = NULL; LogicalSectorNo previousSectorAddress = sectorNo > 0 ? virtual2Logical(&vol,sectorNo - 1) : UNASSIGNED_SECTOR;#ifdef DEBUG_PRINT DEBUG_PRINT("Debug: findFreeSector -> %d !!\n", sectorNo);#endif if (previousSectorAddress != UNASSIGNED_SECTOR && previousSectorAddress != DELETED_SECTOR) { allocationUnit = vol.logicalUnits[previousSectorAddress >> (vol.unitSizeBits - SECTOR_SIZE_BITS)]; if (allocationUnit->noOfFreeSectors > 0) { unsigned int sectorIndex = ((unsigned) previousSectorAddress & (vol.sectorsPerUnit - 1)) + 1; LEulong FAR0 *nextSectorAddress = (LEulong FAR0 *) vol.flash.map(&vol.flash, physicalBase(&vol,allocationUnit) + allocEntryOffset(&vol, sectorIndex), sizeof(VirtualAddress)); if (sectorIndex < vol.sectorsPerUnit && LE4(*nextSectorAddress) == FREE_SECTOR) { /* can write sequentially */ *newAddress = previousSectorAddress + 1; return flOK; } } else allocationUnit = NULL; /* no space here, try elsewhere */ } if (allocationUnit == NULL) allocationUnit = bestUnitToAllocate(&vol); if (allocationUnit == NULL) /* No ? then all is lost */ {#ifdef DEBUG_PRINT DEBUG_PRINT("Debug: findFreeSector -> Unable to find free sector!!\n");#endif return flGeneralFailure; } unitHeader = mapUnitHeader(&vol,allocationUnit,&blockAllocMap); for (iSector = vol.unitHeaderSectors; iSector < vol.sectorsPerUnit; iSector++) { if (LE4(blockAllocMap[iSector]) == FREE_SECTOR) { *newAddress = ((LogicalSectorNo) (LE2(unitHeader->logicalUnitNo)) << (vol.unitSizeBits - SECTOR_SIZE_BITS)) + iSector; return flOK; } }#ifdef DEBUG_PRINT DEBUG_PRINT("Debug: findFreeSector -> Problem marking allocation map!!\n");#endif return flGeneralFailure; /* what are we doing here ? */}/*----------------------------------------------------------------------*//* m a r k A l l o c M a p *//* *//* Writes a new value to a BAM entry. *//* *//* This routine also updates the free & garbage sector counts. *//* *//* Parameters: *//* vol : Pointer identifying drive *//* sectorAddress : Logical sector no. whose BAM entry to mark *//* allocMapEntry : New BAM entry value *//* overwrite : Whether we are overwriting some old value *//* *//* Returns: *//* FLStatus : 0 on success, failed otherwise *//*----------------------------------------------------------------------*/static FLStatus markAllocMap(Flare vol, LogicalSectorNo sectorAddress, VirtualAddress allocMapEntry, FLBoolean overwrite){ UnitNo unitNo = (UnitNo) (sectorAddress >> (vol.unitSizeBits - SECTOR_SIZE_BITS)); Unit *unit = vol.logicalUnits[unitNo]; int sectorInUnit = (unsigned) sectorAddress & (vol.sectorsPerUnit - 1); LEulong bamEntry; if (unitNo >= vol.noOfUnits - vol.noOfTransferUnits) return flGeneralFailure; if (allocMapEntry == GARBAGE_SECTOR) unit->noOfGarbageSectors++; else if (!overwrite) { unit->noOfFreeSectors--; vol.totalFreeSectors--; } toLE4(bamEntry,allocMapEntry); return flashWrite(&vol, physicalBase(&vol,unit) + allocEntryOffset(&vol,sectorInUnit), &bamEntry, sizeof bamEntry, overwrite);}/*----------------------------------------------------------------------*//* d e l e t e L o g i c a l S e c t o r *//* *//* Marks a logical sector as deleted. *//* *//* Parameters: *//* vol : Pointer identifying drive *//* sectorAddress : Logical sector no. to delete *//* *//* Returns: *//* FLStatus : 0 on success, failed otherwise *//*----------------------------------------------------------------------*/static FLStatus deleteLogicalSector(Flare vol, LogicalSectorNo sectorAddress){ if (sectorAddress == UNASSIGNED_SECTOR || sectorAddress == DELETED_SECTOR) return flOK; return markAllocMap(&vol,sectorAddress,GARBAGE_SECTOR,TRUE);}/* forward definition */static FLStatus setVirtualMap(Flare vol, VirtualSectorNo sectorNo, LogicalSectorNo newAddress);/*----------------------------------------------------------------------*//* a l l o c a t e A n d W r i t e S e c t o r *//* *//* Allocates a sector or replacement page and (optionally) writes it. *//* *//* An allocated replacement page also becomes the active replacement *//* page. *//* *//* Parameters: *//* vol : Pointer identifying drive *//* sectorNo : Virtual sector no. to write *//* fromAddress : Address of sector data. If NULL, sector is *//* not written. *//* replacementPage : This is a replacement page sector. *//* *//* Returns: *//* FLStatus : 0 on success, failed otherwise *//*----------------------------------------------------------------------*/static FLStatus allocateAndWriteSector(Flare vol, VirtualSectorNo sectorNo, void FAR1 *fromAddress, FLBoolean replacementPage){ FLStatus status; LogicalSectorNo sectorAddress; VirtualAddress bamEntry = ((VirtualAddress) sectorNo - vol.noOfPages) << SECTOR_SIZE_BITS; long sectorsNeeded = 1;#ifdef DEBUG_PRINT DEBUG_PRINT("Debug: calling defrgment routine!!\n");#endif checkStatus(defragment(&vol,§orsNeeded)); /* Organize a free sector */#ifdef DEBUG_PRINT DEBUG_PRINT("Debug: calling routine findFreeSector !!\n");#endif checkStatus(findFreeSector(&vol,sectorNo,§orAddress)); if (replacementPage) bamEntry |= REPLACEMENT_PAGE; else bamEntry |= DATA_SECTOR; status = markAllocMap(&vol, sectorAddress, sectorNo < vol.directAddressingSectors ? ALLOCATED_SECTOR : bamEntry, FALSE); if (status == flOK && fromAddress) status = flashWrite(&vol, logical2Physical(&vol,sectorAddress), fromAddress, SECTOR_SIZE, 0); if (sectorNo < vol.directAddressingSectors && status == flOK) status = markAllocMap(&vol, sectorAddress, bamEntry, TRUE); if (status == flOK) if (replacementPage) { vol.replacementPageAddress = sectorAddress; vol.replacementPageNo = sectorNo; } else status = setVirtualMap(&vol,sectorNo,sectorAddress); if (status != flOK) status = markAllocMap(&vol,sectorAddress,GARBAGE_SECTOR,TRUE);#ifdef DEBUG_PRINT if (status != flOK) DEBUG_PRINT("Debug: Bad status code at Allocate and Write sector !\n"); DEBUG_PRINT("Debug: MarkAllocMap returned %d !\n", status);#endif return status;}/*----------------------------------------------------------------------*//* c l o s e R e p l a c e m e n t P a g e *//* *//* Closes the replacement page by merging it with the primary page. *//* *//* Parameters: *//* vol : Pointer identifying drive *//* *//* Returns: *//* FLStatus : 0 on success, failed otherwise *//*----------------------------------------------------------------------*/static FLStatus closeReplacementPage(Flare vol){ FLStatus status;#ifdef SINGLE_BUFFER int i; LogicalSectorNo nextReplacementPageAddress = vol.replacementPageAddress; VirtualSectorNo firstSectorNo = ((VirtualSectorNo) vol.replacementPageNo << (PAGE_SIZE_BITS - SECTOR_SIZE_BITS)) + vol.noOfPages;pageRetry: for (i = 0; i < ADDRESSES_PER_SECTOR; i++) { LogicalSectorNo logicalSectorNo = virtual2Logical(&vol,firstSectorNo + i); LEulong entryToWrite; toLE4(entryToWrite,logicalSectorNo == UNASSIGNED_SECTOR ? UNASSIGNED_ADDRESS : (LogicalAddress) logicalSectorNo << SECTOR_SIZE_BITS); if (flashWrite(&vol, logical2Physical(&vol,nextReplacementPageAddress) + i * sizeof(LogicalAddress), &entryToWrite, sizeof entryToWrite, OVERWRITE) != flOK) break; } if (i < ADDRESSES_PER_SECTOR && nextReplacementPageAddress == vol.replacementPageAddress) { /* Uh oh. Trouble. Let's replace this replacement page. */ LogicalSectorNo prevReplacementPageAddress = vol.replacementPageAddress; checkStatus(allocateAndWriteSector(&vol,vol.replacementPageNo,NULL,TRUE)); nextReplacementPageAddress = vol.replacementPageAddress; vol.replacementPageAddress = prevReplacementPageAddress; goto pageRetry; } if (nextReplacementPageAddress != vol.replacementPageAddress) { LogicalSectorNo prevReplacementPageAddress = vol.replacementPageAddress; vol.replacementPageAddress = nextReplacementPageAddress; checkStatus(deleteLogicalSector(&vol,prevReplacementPageAddress)); }#else setupMapCache(&vol,vol.replacementPageNo); /* read replacement page into map cache */ status = flashWrite(&vol, logical2Physical(&vol,vol.replacementPageAddress), mapCache,SECTOR_SIZE,OVERWRITE); if (status != flOK) { /* Uh oh. Trouble. Let's replace this replacement page. */ LogicalSectorNo prevReplacementPageAddress = vol.replacementPageAddress; checkStatus(allocateAndWriteSector(&vol,vol.replacementPageNo,mapCache,TRUE)); checkStatus(deleteLogicalSector(&vol,prevReplacementPageAddress)); }#endif checkStatus(setVirtualMap(&vol,vol.replacementPageNo,vol.replacementPageAddress)); checkStatus(markAllocMap(&vol, vol.replacementPageAddress, (((VirtualAddress) vol.replacementPageNo - vol.noOfPages) << SECTOR_SIZE_BITS) | DATA_SECTOR, TRUE)); vol.replacementPageNo = UNASSIGNED_SECTOR; return flOK;}/*----------------------------------------------------------------------*//* s e t V i r t u a l M a p *//* *//* Changes an entry in the virtual map *//* *//* Parameters: *//* vol : Pointer identifying drive *//* sectorNo : Virtual sector no. whose entry is changed. *//* newAddress : Logical sector no. to assign in Virtual Map. *//* *//* Returns: *//* FLStatus : 0 on success, failed otherwise *//*----------------------------------------------------------------------*/static FLStatus setVirtualMap(Flare vol, VirtualSectorNo sectorNo, LogicalSectorNo newAddress){ unsigned pageNo; int sectorInPage; CardAddress virtualMapEntryAddress; LEulong addressToWrite; LogicalAddress oldAddress; LogicalSectorNo updatedPage; vol.mappedSectorNo = UNASSIGNED_SECTOR; if (sectorNo < vol.directAddressingSectors) { checkStatus(deleteLogicalSector(&vol,vol.pageTable[sectorNo])); vol.pageTable[sectorNo] = newAddress; return flOK; } sectorNo -= vol.noOfPages; pageNo = sectorNo >> (PAGE_SIZE_BITS - SECTOR_SIZE_BITS); sectorInPage = (int) (sectorNo) % ADDRESSES_PER_SECTOR; updatedPage = vol.pageTable[pageNo]; virtualMapEntryAddress = logical2Physical(&vol,updatedPage) + sectorInPage * sizeof(LogicalAddress); oldAddress = LE4(*(LEulong FAR0 *) vol.flash.map(&vol.flash,virtualMapEntryAddress,sizeof(LogicalAddress))); if (oldAddress == DELETED_ADDRESS && vol.replacementPageNo == pageNo) { updatedPage = vol.replacementPageAddress; virtualMapEntryAddress = logical2Physical(&vol,updatedPage) + 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));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -