📄 ssfdc.c
字号:
/* mark sector as assigned and not erased */ vol.physicalUnits[address >> vol.unitSizeBits].unitStatus--; sectorInUnit = (address % (1 << vol.unitSizeBits)) / SECTOR_SIZE; vol.physicalUnits[address >> vol.unitSizeBits].erasedSectors &= ~(1 << sectorInUnit); return status;}/*----------------------------------------------------------------------*//* 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, or holds invalid data. *//*----------------------------------------------------------------------*/static const void FAR0 *mapSector(SSFDC vol, SectorNo sectorNo, CardAddress *physAddress){ if (sectorNo != vol.mappedSectorNo || vol.flash.socket->remapped) { if (sectorNo >= vol.virtualSectors) vol.mappedSector = NULL; else { vol.mappedSectorAddress = virtual2Physical(&vol, sectorNo); if (vol.mappedSectorAddress == UNASSIGNED_ADDRESS) vol.mappedSector = NULL; /* no such sector */ else { vol.mappedSector = vol.flash.map(&vol.flash, vol.mappedSectorAddress, SECTOR_SIZE);#ifdef ECC_ON_READ if (!eccOnRead(&vol, sectorAddress)) /* check and fix errors */ return NULL; /* a non-fixable error */#endif } } vol.mappedSectorNo = sectorNo; vol.flash.socket->remapped = FALSE; } if (physAddress) *physAddress = vol.mappedSectorAddress; return vol.mappedSector;}/*----------------------------------------------------------------------*//* f o r m a t U n i t *//* *//* Format one unit. Erase the unit, and mark the physical units table. *//* *//* Parameters: *//* vol : Pointer identifying drive *//* unitNo : Unit to format *//* *//* Returns: *//* FLStatus : 0 on success, failed otherwise *//*----------------------------------------------------------------------*/static FLStatus formatUnit(SSFDC vol, UnitNo unitNo){ if (!(vol.physicalUnits[unitNo].unitStatus & UNIT_AVAILABLE)) return flWriteFault; if (((vol.physicalUnits[unitNo].unitStatus & STATUS_MASK) == UNIT_FREE) || ((vol.physicalUnits[unitNo].unitStatus & STATUS_MASK) == UNIT_ERASED)) vol.freeUnits--; vol.physicalUnits[unitNo].unitStatus &= ~UNIT_AVAILABLE; /* protect the unit */ checkStatus(vol.flash.erase(&vol.flash, unitNo << (vol.unitSizeBits - vol.erasableBlockSizeBits), 1 << (vol.unitSizeBits - vol.erasableBlockSizeBits))); /* mark unit erased */ vol.physicalUnits[unitNo].unitStatus = UNIT_ERASED | vol.sectorsPerUnit;/* VF: Updated next line: */#if (TFFS_SECTORS_PER_UNIT < 32) /* VF */ vol.physicalUnits[unitNo].erasedSectors = 0xffff; /* all sectors are erased */#else vol.physicalUnits[unitNo].erasedSectors = 0xffffffff; /* all sectors are erased */#endif vol.freeUnits++; return flOK;}/*----------------------------------------------------------------------*//* a s s i g n U n i t *//* *//* Assigns a virtual unit no. to a unit *//* *//* Parameters: *//* vol : Pointer identifying drive *//* unitNo : Physical unit number *//* virtualUnitNo : Virtual unit number to assign *//* *//* Returns: *//* FLStatus : 0 on success, failed otherwise *//*----------------------------------------------------------------------*/static FLStatus assignUnit(SSFDC vol, UnitNo unitNo, UnitNo virtualUnitNo){ unsigned char blockAddressArea[2], parityBit = 1; /* bit 12 is always 1 */ FLStatus status; UnitNo un; unsigned sector; /* create the block address area */ /* calculate parity bit */ for (un = virtualUnitNo; un; un >>= 1) parityBit ^= un & 0x01; blockAddressArea[0] = (virtualUnitNo >> 7) | 0x10; blockAddressArea[1] = (virtualUnitNo << 1) | parityBit; /* write the block address to the block address areas in all the sectors of the unit.*/ for (sector = 0; sector < vol.sectorsPerUnit; sector++) { CardAddress sectorAddress; sectorAddress = unitBaseAddress(&vol, unitNo) + (sector << SECTOR_SIZE_BITS); /* write to first address area */ status = vol.flash.write(&vol.flash, sectorAddress + BLOCK_ADDRESS_OFFSET1, &blockAddressArea, sizeof blockAddressArea, EXTRA); if (status == flOK) /* write to second address area */ status = vol.flash.write(&vol.flash, sectorAddress + BLOCK_ADDRESS_OFFSET2, &blockAddressArea, sizeof blockAddressArea, EXTRA); if (status != flOK) { /* write failed, mark unit as bad */ vol.physicalUnits[unitNo].unitStatus &= ~STATUS_MASK; vol.physicalUnits[unitNo].unitStatus |= UNIT_BAD; vol.freeUnits--; return status; } } /* mark unit assigned */ vol.physicalUnits[unitNo].unitStatus &= ~STATUS_MASK; vol.physicalUnits[unitNo].unitStatus |= UNIT_AVAILABLE; vol.freeUnits--; vol.virtualUnits[virtualUnitNo] = unitNo; return flOK;}/*----------------------------------------------------------------------*//* f i n i s h U n i t T r a n s f e r *//* *//* Finish unit transfer from replaced unit to transfer unit. *//* copy all the sectors that were not replaced from the replaced unit *//* to the transfer unit. This routine is called when either another *//* unit needs replacement, or we finished the current Flie function. *//* *//* Parameters: *//* vol : Pointer identifying drive *//* *//* Returns: *//* FLStatus : 0 on success, failed otherwise *//*----------------------------------------------------------------------*/static FLStatus finishUnitTransfer(SSFDC vol){ unsigned char ecc[3]; UnitNo virtualUnitNo; unsigned freeSectors = 0, sector; /* count the number of free sectors */ if (vol.replacedUnit == NO_UNIT) /* no unit to fold */ return flOK; for (sector = 0; sector < vol.sectorsPerUnit; sector++) { if (vol.replacementSectors[sector] == SECTOR_ALLOCATED) { /* copy only sectors that holds valid data */ CardAddress fromSectorAddress, toSectorAddress; fromSectorAddress = unitBaseAddress(&vol, vol.replacedUnit) + (sector << SECTOR_SIZE_BITS); toSectorAddress = unitBaseAddress(&vol, vol.transferUnit) + (sector << SECTOR_SIZE_BITS); vol.flash.read(&vol.flash, fromSectorAddress, ssfdcBuffer,SECTOR_SIZE,0); vol.flash.socket->remapped = TRUE; checkStatus(writeAndCheck(&vol, toSectorAddress, ssfdcBuffer, 0)); /* copy ecc fields instead of recalculating them */ vol.flash.read(&vol.flash, fromSectorAddress + ECC1, ecc, sizeof ecc, EXTRA); checkStatus(vol.flash.write(&vol.flash, toSectorAddress + ECC1, ecc, sizeof ecc, EXTRA)); vol.flash.read(&vol.flash, fromSectorAddress + ECC2, ecc, sizeof ecc, EXTRA); checkStatus(vol.flash.write(&vol.flash, toSectorAddress + ECC2, ecc, sizeof ecc, EXTRA)); } if ((vol.replacementSectors[sector] == SECTOR_ERASED) || (vol.replacementSectors[sector] == SECTOR_DELETED1)) freeSectors++; } /* the old transfer unit gets the virtual number of the replaced unit */ virtualUnitNo = physical2Virtual(&vol, vol.replacedUnit, OFFSET1); if (virtualUnitNo >= vol.noOfVirtualUnits) { /* first address area is not good try the second address area */ virtualUnitNo = physical2Virtual(&vol, vol.replacedUnit, OFFSET2); if (virtualUnitNo >= vol.noOfVirtualUnits) return flGeneralFailure; } if (freeSectors < vol.sectorsPerUnit) { checkStatus(assignUnit(&vol, vol.transferUnit, virtualUnitNo)); checkStatus(formatUnit(&vol, vol.replacedUnit)); vol.transferUnit = vol.replacedUnit; /* The old transfer unit is dead, long live the new one */ } vol.replacedUnit = NO_UNIT; return flOK;}/*----------------------------------------------------------------------*//* t l s e t B u s y *//* *//* Notifies the start and end of a file-system operation. *//* On exit, finish unit transfer (if necessary). *//* *//* Parameters: *//* vol : Pointer identifying drive *//* state : TFFS_ON (1) = operation entry *//* TFFS_OFF(0) = operation exit *//* *//*----------------------------------------------------------------------*/static void tlSetBusy(SSFDC vol, FLBoolean state){ if (state == TFFS_ON) vol.replacedUnit = NO_UNIT; /* in case we exit without doing anything */ else finishUnitTransfer(&vol); /* I ignore the returned status */}/*----------------------------------------------------------------------*//* s e t R e p l a c e m e n t U n i t *//* *//* Set a replaced unit. From now on, if write inplace to this unit *//* is impossible, write to the transfer unit instead. this routine *//* reads the status of each sector in the unit and updates the replaced *//* sectors table. *//* *//* Parameters: *//* vol : Pointer identifying drive *//* unitNo : The new replaced unit *//* *//*----------------------------------------------------------------------*/static void setReplacementUnit(SSFDC vol, UnitNo unitNo){ int iSector; StatusArea statusArea; vol.replacedUnit = unitNo; vol.sectorsDeleted = 0; for (iSector = 0; (unsigned)iSector < vol.sectorsPerUnit; iSector++) { vol.flash.read(&vol.flash, unitBaseAddress(&vol, unitNo) + (iSector << SECTOR_SIZE_BITS) + STATUS_AREA_OFFSET, &statusArea, sizeof statusArea, EXTRA); if (statusArea.sectorStatus != 0xff) { vol.replacementSectors[iSector] = SECTOR_DELETED1; vol.sectorsDeleted++; continue; } if (vol.physicalUnits[unitNo].erasedSectors & (1 << iSector)) vol.replacementSectors[iSector] = SECTOR_ERASED; else vol.replacementSectors[iSector] = SECTOR_ALLOCATED; }}/*----------------------------------------------------------------------*//* m a r k S e c t o r D e l e t e d *//* *//* Mark a sector as deleted on the media, and update the unassigned *//* sectors counter in the physical units table. *//* *//* Parameters: *//* vol : Pointer identifying drive *//* unitNo : The sector is in this unit *//* unitOffset : The offset of the sector in the unit *//* *//* Returns: *//* FLStatus : 0 on success, failed otherwise *//*----------------------------------------------------------------------*/static FLStatus markSectorDeleted(SSFDC vol, UnitNo unitNo, unsigned unitOffset){ StatusArea statusArea; /* check if this sector is already deleted or erased */ vol.flash.read(&vol.flash, unitBaseAddress(&vol, unitNo) + unitOffset + STATUS_AREA_OFFSET, &statusArea, sizeof statusArea, EXTRA); if ((statusArea.sectorStatus != 0xff) || (vol.physicalUnits[unitNo].erasedSectors & (1 << (unitOffset / SECTOR_SIZE)))) return flOK; /* sector is erased or already deleted */ statusArea.sectorStatus = 0; statusArea.unitStatus = 0xff; vol.physicalUnits[unitNo].unitStatus++; return vol.flash.write(&vol.flash, unitBaseAddress(&vol, unitNo) + unitOffset + STATUS_AREA_OFFSET, &statusArea, sizeof statusArea, EXTRA);}/*----------------------------------------------------------------------*//* a l l o c a t e U n i t *//* *//* Find a free unit to allocate, erase it if necessary. *//* *//* Parameters: *//* vol : Pointer identifying drive *//* unitNo : Receives the physical number of the allocated *//* unit *//* Returns: *//* FLStatus : 0 on success, failed otherwise *//*----------------------------------------------------------------------*/static FLStatus allocateUnit(SSFDC vol, UnitNo *unitNo){ UnitNo originalUnit = vol.roverUnit; if (vol.freeUnits > 1) { /* the transfer unit is always free */ do {/* VF: Take 8- vs. 16-bit PhysUnit quantity into account: */#if (TFFS_SECTORS_PER_UNIT < 32) unsigned char unitFlags;#else unsigned short unitFlags;#endif if (++vol.roverUnit == vol.transferUnit) /* we don't want to allocate this one */ vol.roverUnit++; if (vol.roverUnit >= vol.noOfUnits) /* we got to the end, wrap around */ vol.roverUnit = vol.CISblock; unitFlags = vol.physicalUnits[vol.roverUnit].unitStatus; if (((unitFlags & STATUS_MASK) == UNIT_FREE) || ((unitFlags & STATUS_MASK) == UNIT_ERASED)) { if ((unitFlags & STATUS_MASK) == UNIT_FREE) checkStatus(formatUnit(&vol, vol.roverUnit));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -