📄 ftllite.c
字号:
LEulong FAR0 *replacementPage = (LEulong FAR0 *) mapLogical(&vol,vol.replacementPageAddress); for(i = 0; (unsigned)i < ADDRESSES_PER_SECTOR; i++) { if(LE4(mapCache[i]) == DELETED_ADDRESS) toLE4(mapCache[i],LE4(replacementPage[i])); } } buffer.sectorNo = pageNo; buffer.owner = &vol;}#endif/*----------------------------------------------------------------------*//* v i r t u a l 2 L o g i c a l *//* *//* Translates virtual sector no. to logical sector no. *//* *//* Parameters: *//* vol : Pointer identifying drive *//* sectorNo : Virtual sector no. *//* *//* Returns: *//* Logical sector no. corresponding to virtual sector no. *//*----------------------------------------------------------------------*/static LogicalSectorNo virtual2Logical(Flare vol, VirtualSectorNo sectorNo){ LogicalAddress virtualMapEntry; if(sectorNo < vol.directAddressingSectors) return vol.pageTable[sectorNo]; else { unsigned pageNo; int sectorInPage; sectorNo -= vol.noOfPages; pageNo = (int) (sectorNo >> (PAGE_SIZE_BITS - SECTOR_SIZE_BITS)); sectorInPage = (int) (sectorNo) % ADDRESSES_PER_SECTOR; {#ifdef SINGLE_BUFFER LogicalAddress FAR0 *virtualMapPage; virtualMapPage = (LogicalAddress FAR0 *) mapLogical(&vol, vol.pageTable[pageNo]); if (pageNo == vol.replacementPageNo && virtualMapPage[sectorInPage] == DELETED_ADDRESS) virtualMapPage = (LogicalAddress FAR0 *) mapLogical(&vol, vol.replacementPageAddress); virtualMapEntry = LE4(virtualMapPage[sectorInPage]);#else if (buffer.sectorNo != pageNo || buffer.owner != &vol) setupMapCache(&vol,pageNo); virtualMapEntry = LE4(mapCache[sectorInPage]);#endif return (LogicalSectorNo) (virtualMapEntry >> SECTOR_SIZE_BITS); } }}/*----------------------------------------------------------------------*//* v e r i f y F o r m a t *//* *//* Verify an FTL unit header. *//* *//* Parameters: *//* unitHeader : Pointer to unit header *//* *//* Returns: *//* TRUE if header is correct. FALSE if not. *//*----------------------------------------------------------------------*/static FLBoolean verifyFormat(UnitHeader FAR0 *unitHeader){ /* MTD Detection has a potential of breaking the first bytes on erasable block 0. We ignore the first 4 bytes (4*8bit, 32bit access) to ignore this problem. ALR */ FORMAT_PATTERN[6] = unitHeader->formatPattern[6]; /* TPL_LINK */ return tffscmp(unitHeader->formatPattern + 4, FORMAT_PATTERN + 4, sizeof unitHeader->formatPattern - 4) == 0;}/* forward declaration. EAN */static void invalidateFormat(Flare vol, Unit *unit);/*----------------------------------------------------------------------*//* f o r m a t U n i t *//* *//* Formats a unit by erasing it and writing a unit header. *//* *//* Parameters: *//* vol : Pointer identifying drive *//* unit : Unit to format *//* *//* Returns: *//* FLStatus : 0 on success, failed otherwise *//*----------------------------------------------------------------------*/static FLStatus formatUnit(Flare vol, Unit *unit){ unsigned unitHeaderLength = allocEntryOffset(&vol,vol.unitHeaderSectors); /* invlaidate the header. Just to be sure. EAN */ invalidateFormat(&vol,unit); unit->noOfFreeSectors = FREE_UNIT; unit->noOfGarbageSectors = 0;#ifdef BACKGROUND { FLStatus status; vol.unitEraseInProgress = unit; status = vol.flash.erase(&vol.flash, (int) (physicalBase(&vol,unit) >> vol.erasableBlockSizeBits), 1 << (vol.unitSizeBits - vol.erasableBlockSizeBits)); vol.unitEraseInProgress = NULL; if (status != flOK) return status; /* Note: This suspend to the foreground is not only nice to have, it is necessary ! The reason is that we may have a write from the buffer waiting for the erase to complete. We are next going to overwrite the buffer, so this break enables the write to complete before the data is clobbered (what a relief). */ while (flForeground(1) == BG_SUSPEND) ; }#else checkStatus(vol.flash.erase(&vol.flash, (int) (physicalBase(&vol,unit) >> vol.erasableBlockSizeBits), 1 << (vol.unitSizeBits - vol.erasableBlockSizeBits)));#endif /* We will copy the unit header as far as the format entries of the BAM from another unit (logical unit 0) */#ifdef SINGLE_BUFFER if (buffer.dirty) return flBufferingError;#endif buffer.sectorNo = UNASSIGNED_SECTOR; /* Invalidate map cache so we can use it as a buffer */ if(vol.logicalUnits[vol.firstPhysicalEUN]) { vol.flash.read(&vol.flash, physicalBase(&vol,vol.logicalUnits[vol.firstPhysicalEUN]), uh, unitHeaderLength, 0); } else { dbgMsg(DEBUG_NORMAL,"formatUnit: vol.logicalUnits[vol.firstPhysicalEUN] is invalid using buffer.\n",0,0,0,0,0,0); } toLE4(uh->wearLevelingInfo,++vol.currWearLevelingInfo); toLE2(uh->logicalUnitNo,UNASSIGNED_UNIT_NO); /* change the order so the last thing written is what verifyFormat() checks. */ /* this will allow a power outage during formatUnit() without corrupting */ /* the volume. EAN */ /* Most of our MTDs have problems with unaligned writes (writes should be always 32bit aligned to support 4*8bit parallel writing. We therefore modify this to be aligned (offest 8 byts which is part of the format header... but still sufficient to allow verifyFormat() to detect broken format). ALR */#if 0 checkStatus(vol.flash.write(&vol.flash, physicalBase(&vol,unit)+sizeof(FORMAT_PATTERN)-1, (char*)uh+sizeof(FORMAT_PATTERN)-1, unitHeaderLength-sizeof(FORMAT_PATTERN)+1, 0)); checkStatus(vol.flash.write(&vol.flash, physicalBase(&vol,unit), uh, sizeof(FORMAT_PATTERN)-1, 0));#else checkStatus(vol.flash.write(&vol.flash, physicalBase(&vol,unit)+8, (char*)uh+8, unitHeaderLength-8, 0)); checkStatus(vol.flash.write(&vol.flash, physicalBase(&vol,unit), uh, 8, 0));#endif return flOK;}#ifdef BACKGROUND/*----------------------------------------------------------------------*//* f l a s h W r i t e *//* *//* Writes to flash through flash.write, but, if possible, allows a *//* background erase to continue while writing. *//* *//* Parameters: *//* Same as flash.write *//* *//* Returns: *//* Same as flash.write *//*----------------------------------------------------------------------*/static FLStatus flashWrite(Flare vol, CardAddress address, const void FAR1 *from, int length, FLBoolean overwrite){ if(vol.mirrorOffset != 0 && address >= vol.mirrorFrom && address < vol.mirrorTo) { checkStatus(flashWrite(&vol, address + vol.mirrorOffset, from, length, overwrite)); } if(vol.unitEraseInProgress) { CardAddress startChip = physicalBase(&vol,vol.unitEraseInProgress) & (-vol.flash.interleaving * vol.flash.chipSize); CardAddress endChip = startChip + vol.flash.interleaving * vol.flash.chipSize; if(address < startChip || address >= endChip) { flBackground(BG_RESUME); checkStatus(vol.flash.write(&vol.flash,address,from,length,overwrite)); flBackground(BG_SUSPEND); return flOK; } else if(!(vol.flash.flags & SUSPEND_FOR_WRITE)) { do { flBackground(BG_RESUME); } while (vol.unitEraseInProgress); } } return vol.flash.write(&vol.flash,address,from,length,overwrite);}#else#define flashWrite(v,address,from,length,overwrite) \ (v)->flash.write(&(v)->flash,address,from,length,overwrite)#endif /* BACKGROUND *//*----------------------------------------------------------------------*//* m o u n t U n i t *//* *//* Performs mount scan for a single unit *//* *//* Parameters: *//* vol : Pointer identifying drive *//* unit : Unit to mount *//* *//* Returns: *//* FLStatus : 0 on success, failed otherwise *//*----------------------------------------------------------------------*/static FLStatus mountUnit(Flare vol, Unit *unit){ unsigned i; LogicalSectorNo sectorAddress; LEulong FAR0 *blockAllocMap; UnitHeader FAR0 *unitHeader = mapUnitHeader(&vol,unit,&blockAllocMap); UnitNo logicalUnitNo = LE2(unitHeader->logicalUnitNo); unit->noOfGarbageSectors = 0; unit->noOfFreeSectors = FREE_UNIT; if (!verifyFormat(unitHeader) || ((logicalUnitNo != UNASSIGNED_UNIT_NO) && ((logicalUnitNo >= vol.noOfUnits) || (logicalUnitNo < vol.firstPhysicalEUN) || vol.logicalUnits[logicalUnitNo]))) { /* what is wrong. EAN */ if(!verifyFormat(unitHeader)) { dbgMsg(DEBUG_INSANE,"mountUnit: bad unit header unitNo %x logical %x unit %x.\n",(CardAddress) (unit - vol.physicalUnits), logicalUnitNo,(int) unit,0,0,0); } else if(logicalUnitNo == MARKED_FOR_ERASE) { dbgMsg(DEBUG_NORMAL,"mountUnit: marked for erase logical %x unit %x.\n",logicalUnitNo, (int) unit,0,0,0,0); } else if((logicalUnitNo >= vol.noOfUnits) || (logicalUnitNo < vol.firstPhysicalEUN)) { dbgMsg(DEBUG_LIGHT,"mountUnit: logical unit number out of range logical %x unit %x.\n",logicalUnitNo,(int) unit,0,0,0,0); } else if(vol.logicalUnits[logicalUnitNo]) { dbgMsg(DEBUG_LIGHT,"mountUnit: duplicate logical unit number logical %x unit %x.\n",logicalUnitNo,(int) unit,0,0,0,0); } if(vol.transferUnit == NULL) { dbgMsg(DEBUG_INSANE,"mountUnit: vol.transferUnit == NULL, setting to logical %x unit %x.\n",logicalUnitNo,(int) unit,0,0,0,0); vol.transferUnit = unit; } return flBadFormat; } if(logicalUnitNo == UNASSIGNED_UNIT_NO) { dbgMsg(DEBUG_INSANE,"mountUnit: logicalUnitNo == UNASSIGNED_UNIT_NO, setting to logical %x unit %x.\n",logicalUnitNo,(int) unit,0,0,0,0); vol.transferUnit = unit; return flOK; /* this is a transfer unit */ } if (LE4(unitHeader->wearLevelingInfo) > vol.currWearLevelingInfo && LE4(unitHeader->wearLevelingInfo) != 0xffffffffl) vol.currWearLevelingInfo = LE4(unitHeader->wearLevelingInfo); /* count sectors and setup virtual map */ sectorAddress = ((LogicalSectorNo) logicalUnitNo << (vol.unitSizeBits - SECTOR_SIZE_BITS)); unit->noOfFreeSectors = 0; for(i = 0; i < vol.sectorsPerUnit; i++, sectorAddress++) { VirtualAddress allocMapEntry = LE4(blockAllocMap[i]); if(allocMapEntry == GARBAGE_SECTOR || (unsigned long)allocMapEntry == ALLOCATED_SECTOR) unit->noOfGarbageSectors++; else if((unsigned long)allocMapEntry == FREE_SECTOR) { unit->noOfFreeSectors++; vol.totalFreeSectors++; } else if(allocMapEntry < vol.directAddressingMemory) { char signature = (short) (allocMapEntry) & SECTOR_OFFSET_MASK; if(signature == DATA_SECTOR || signature == REPLACEMENT_PAGE) { int pageNo = (int) (allocMapEntry >> SECTOR_SIZE_BITS) + vol.noOfPages; if(pageNo >= 0) { if(signature == DATA_SECTOR) { vol.pageTable[pageNo] = sectorAddress; } else { vol.replacementPageAddress = sectorAddress; vol.replacementPageNo = pageNo; } } } } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -