📄 ssfdc.c
字号:
*unitNo = vol.roverUnit; return flOK; } } while (vol.roverUnit != originalUnit); return flGeneralFailure; /* Didn't find the free units */ } return flNotEnoughMemory;}#if defined(DEFRAGMENT_VOLUME) || defined(SINGLE_BUFFER)/*----------------------------------------------------------------------*//* d e f r a g m e n t *//* *//* Performs unit allocations to arrange a minimum number of writable *//* sectors. *//* *//* Parameters: *//* vol : Pointer identifying drive *//* sectorsNeeded : Minimum required sectors *//* *//* Returns: *//* FLStatus : 0 on success, failed otherwise *//*----------------------------------------------------------------------*/static FLStatus defragment(SSFDC vol, long FAR2 *sectorsNeeded){ UnitNo erasedUnits = 0, dummyUnit; while (erasedUnits * vol.sectorsPerUnit < *sectorsNeeded) { if (vol.badFormat) return flBadFormat; checkStatus(allocateUnit(&vol, &dummyUnit)); erasedUnits++; } *sectorsNeeded = erasedUnits * vol.sectorsPerUnit; return flOK;}#endif/*----------------------------------------------------------------------*//* a l l o c a t e A n d W r i t e S e c t o r *//* *//* Write to virtual sectorNo. If sectorsNo is not assigned to any *//* physical sector, allocate a new one and write it there. If sectorNo *//* is assigned, try to write in place, if impossible, replace this *//* sector in the transfer unit (finish the previous unit transfer *//* first). *//* *//* Parameters: *//* vol : Pointer identifying drive *//* sectorNo : Virtual sector no. to write *//* fromAddress : Address of sector data. *//* *//* Returns: *//* FLStatus : 0 on success, failed otherwise *//*----------------------------------------------------------------------*/static FLStatus allocateAndWriteSector(SSFDC vol, SectorNo sectorNo, void FAR1 *fromAddress){ UnitNo virtualUnitNo = sectorNo / vol.sectorsPerUnit; UnitNo unitNo = vol.virtualUnits[virtualUnitNo]; unsigned sectorInUnit = sectorNo % vol.sectorsPerUnit; unsigned unitOffset = sectorInUnit << SECTOR_SIZE_BITS; /* Find a unit to write this sector */ if ((unitNo != NO_UNIT) && ((vol.physicalUnits[unitNo].unitStatus & STATUS_MASK) == UNIT_AVAILABLE)) { if (vol.replacedUnit == unitNo) { /* this unit is replaced by the transfer unit */ if ((vol.replacementSectors[sectorInUnit] == SECTOR_REPLACED) || (vol.replacementSectors[sectorInUnit] == SECTOR_DELETED2)) { /* this sector was already replaced */ UnitNo oldTransferUnit = vol.transferUnit; checkStatus(finishUnitTransfer(&vol)); setReplacementUnit(&vol, oldTransferUnit); } if (vol.replacementSectors[sectorInUnit] != SECTOR_ERASED) { /* write to the transfer unit, mark deleted in the replaced unit, and mark replaced in the replaced sectors table. */ checkStatus(writeAndCheck(&vol, unitBaseAddress(&vol, vol.transferUnit) + unitOffset, fromAddress, 1)) checkStatus(markSectorDeleted(&vol, vol.replacedUnit, unitOffset)); vol.replacementSectors[sectorInUnit] = SECTOR_REPLACED; } else { /* sector erased, write inplace */ checkStatus(writeAndCheck(&vol, unitBaseAddress(&vol, vol.replacedUnit) + unitOffset, fromAddress, 1)); vol.replacementSectors[sectorInUnit] = SECTOR_ALLOCATED; } } else { if (vol.physicalUnits[unitNo].erasedSectors & (1 << (unitOffset / SECTOR_SIZE))) { /* sector is erased, write inplace */ checkStatus(writeAndCheck(&vol, unitBaseAddress(&vol, unitNo) + unitOffset, fromAddress, 1)); } else { /* finish the previous transfer first */ checkStatus(finishUnitTransfer(&vol)); setReplacementUnit(&vol, unitNo); /* write to the transfer unit, mark deleted in the replaced unit, and mark replaced in the replaced sectors table. */ checkStatus(writeAndCheck(&vol, unitBaseAddress(&vol, vol.transferUnit) + unitOffset, fromAddress, 1)) checkStatus(markSectorDeleted(&vol, vol.replacedUnit, unitOffset)); vol.replacementSectors[sectorInUnit] = SECTOR_REPLACED; } } } else { /* this sector is unassigned, find a free unit and write the sector there */ UnitNo toUnit; checkStatus(allocateUnit(&vol, &toUnit)); checkStatus(writeAndCheck(&vol, unitBaseAddress(&vol, toUnit) + unitOffset, fromAddress, 1)); checkStatus(assignUnit(&vol, toUnit, virtualUnitNo)); } return flOK;}/*----------------------------------------------------------------------*//* d e l e t e S e c t o r *//* *//* Marks contiguous sectors as deleted. *//* Update unassigned sectors counter in physical units table, and *//* deleted replaced sectors table. If all the sectors in a unit are *//* deleted, mark it as free. *//* *//* 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(SSFDC vol, SectorNo sectorNo, int noOfSectors){ int iSector; if (vol.badFormat) return flBadFormat; if (sectorNo + noOfSectors > vol.virtualSectors) return flSectorNotFound; for (iSector = 0; iSector < noOfSectors; iSector++, sectorNo++) { unsigned sectorInUnit = sectorNo % vol.sectorsPerUnit; CardAddress sectorAddress = virtual2Physical(&vol, sectorNo); if (sectorAddress != UNASSIGNED_ADDRESS) { UnitNo virtualUnitNo = sectorNo / vol.sectorsPerUnit; UnitNo unitNo = vol.virtualUnits[virtualUnitNo]; if (!(vol.physicalUnits[unitNo].unitStatus & UNIT_AVAILABLE) || (unitNo == NO_UNIT)) return flSectorNotFound; if (unitNo == vol.replacedUnit) { /* this sector was replaced, mark it in the transfer unit, and update the repleced sectors table. */ if (vol.replacementSectors[sectorInUnit] == SECTOR_REPLACED) { checkStatus(markSectorDeleted(&vol, vol.transferUnit, sectorInUnit << SECTOR_SIZE_BITS)); vol.replacementSectors[sectorInUnit] = SECTOR_DELETED2; } else { checkStatus(markSectorDeleted(&vol, unitNo, sectorInUnit << SECTOR_SIZE_BITS)); vol.replacementSectors[sectorInUnit] = SECTOR_DELETED1; } if (++vol.sectorsDeleted >= vol.sectorsPerUnit) { /* all the sectors in the replaced unit are deleted, no point to keep their deleted copy in the transfer unit. */ checkStatus(formatUnit(&vol, vol.transferUnit)); vol.physicalUnits[vol.replacedUnit].unitStatus &= ~STATUS_MASK; vol.physicalUnits[vol.replacedUnit].unitStatus |= UNIT_FREE; vol.virtualUnits[virtualUnitNo] = NO_UNIT; vol.replacedUnit = NO_UNIT; vol.freeUnits++; } } else { /* this sector is not in the replaced unit */ checkStatus(markSectorDeleted(&vol, unitNo, sectorInUnit << SECTOR_SIZE_BITS)); if ((vol.physicalUnits[unitNo].unitStatus & ~STATUS_MASK) == (int)vol.sectorsPerUnit) { /* all the sectors in this unit are unassigned, it can be marked as free. */ vol.physicalUnits[unitNo].unitStatus &= ~STATUS_MASK; vol.physicalUnits[unitNo].unitStatus |= UNIT_FREE; vol.freeUnits++; vol.virtualUnits[virtualUnitNo] = NO_UNIT; } } } } return flOK;}/*----------------------------------------------------------------------*//* w r i t e S e c t o r *//* *//* Writes a sector. *//* *//* Parameters: *//* vol : Pointer identifying drive *//* sectorNo : Sector no. to write *//* fromAddress : Data to write *//* *//* Returns: *//* FLStatus : 0 on success, failed otherwise *//*----------------------------------------------------------------------*/static FLStatus writeSector(SSFDC vol,SectorNo sectorNo, void FAR1 *fromAddress){ FLStatus status; int i; if (vol.badFormat) return flBadFormat; if (sectorNo > vol.virtualSectors) return flSectorNotFound; status = flWriteFault; for (i = 0; i < 4 && status == flWriteFault; i++) { if (vol.mappedSectorNo == sectorNo) vol.mappedSectorNo = UNASSIGNED_SECTOR; status = allocateAndWriteSector(&vol,sectorNo,fromAddress); } return status;}/*----------------------------------------------------------------------*//* m o u n t U n i t *//* *//* Mount one unit. Get the unit status (assigned, free or bad) and *//* update the tables. *//* *//* Parameters: *//* vol : Pointer identifying drive *//* unitNo : Unit to mount *//* *//* Returns: *//* FLStatus : 0 on success, failed otherwise *//*----------------------------------------------------------------------*/static FLStatus mountUnit(SSFDC vol, UnitNo unitNo){ StatusArea statusArea; UnitNo virtualUnitNo; /* initialize unassigned sectors counter */ vol.physicalUnits[unitNo].unitStatus &= STATUS_MASK; vol.flash.read(&vol.flash, unitBaseAddress(&vol, unitNo) + STATUS_AREA_OFFSET, &statusArea, sizeof statusArea, EXTRA); if (statusArea.unitStatus != 0xff) { vol.physicalUnits[unitNo].unitStatus &= ~STATUS_MASK; vol.physicalUnits[unitNo].unitStatus |= UNIT_BAD; return flOK; } virtualUnitNo = physical2Virtual(&vol, unitNo, OFFSET1); if (virtualUnitNo >= vol.noOfVirtualUnits) { vol.physicalUnits[unitNo].unitStatus = UNIT_FREE | vol.sectorsPerUnit; vol.freeUnits++; } else { if (vol.virtualUnits[virtualUnitNo] != NO_UNIT) { /* there is another unit with this virtual address */ vol.physicalUnits[unitNo].unitStatus = UNIT_FREE | vol.sectorsPerUnit; vol.freeUnits++; } else { /* this unit is assigned */ CardAddress unitBase; unsigned sector; vol.physicalUnits[unitNo].unitStatus &= ~STATUS_MASK; vol.physicalUnits[unitNo].unitStatus |= UNIT_AVAILABLE; vol.virtualUnits[virtualUnitNo] = unitNo; /* count the number of unassigned sectors and mark erased sectors */ vol.physicalUnits[unitNo].erasedSectors = 0; unitBase = unitBaseAddress(&vol, unitNo); for (sector = 0; sector < vol.sectorsPerUnit; sector++) { vol.flash.read(&vol.flash, unitBase + (sector << SECTOR_SIZE_BITS) + STATUS_AREA_OFFSET, &statusArea, sizeof statusArea, EXTRA); if (statusArea.sectorStatus != 0xff) vol.physicalUnits[unitNo].unitStatus++; else if (isErasedSector(&vol, unitNo, sector << SECTOR_SIZE_BITS)) { vol.physicalUnits[unitNo].unitStatus++; vol.physicalUnits[unitNo].erasedSectors |= (1 << sector); } } /* check if all the sectors are unassigned */ if ((vol.physicalUnits[unitNo].unitStatus & ~STATUS_MASK) == (int)vol.sectorsPerUnit) { vol.physicalUnits[unitNo].unitStatus &= ~STATUS_MASK; vol.physicalUnits[unitNo].unitStatus |= UNIT_FREE; vol.virtualUnits[virtualUnitNo] = NO_UNIT; vol.freeUnits++; } } } /* prepare a transfer unit */ if (((vol.physicalUnits[unitNo].unitStatus & STATUS_MASK) == UNIT_FREE) && (vol.transferUnit == NO_UNIT)) { checkStatus (formatUnit(&vol, unitNo)); vol.transferUnit = unitNo; } return flOK;}/*----------------------------------------------------------------------*//* i n i t S S F D C *//* *//* 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 initSSFDC(SSFDC vol){ long int size = 1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -