⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ftllite.c

📁 cpc-1631的BSP包for VxWorks操作系统
💻 C
📖 第 1 页 / 共 5 页
字号:
}


/*----------------------------------------------------------------------*/
/*		           a s s i g n U n i t				*/
/*									*/
/* Assigns a logical unit no. to a unit					*/
/*                                                                      */
/* Parameters:                                                          */
/*	vol		: Pointer identifying drive			*/
/*	unit		: Unit to assign				*/
/*                                                                      */
/* Returns:                                                             */
/*	FLStatus	: 0 on success, failed otherwise		*/
/*----------------------------------------------------------------------*/

static FLStatus assignUnit(Flare vol,  Unit *unit, UnitNo logicalUnitNo)
{
  LEushort unitNoToWrite;

  toLE2(unitNoToWrite,logicalUnitNo);

  return flashWrite(&vol,
		    physicalBase(&vol,unit) + logicalUnitNoOffset,
		    &unitNoToWrite,
		    sizeof unitNoToWrite,
		    OVERWRITE);
}


/*----------------------------------------------------------------------*/
/*		    b e s t U n i t T o T r a n s f e r			*/
/*									*/
/* Find best candidate for unit transfer, usually on the basis of which	*/
/* unit has the most garbage space. A lower wear-leveling info serves	*/
/* as a tie-breaker. If 'leastUsed' is NOT specified, then the least	*/
/* wear-leveling info is the only criterion.				*/
/*                                                                      */
/* Parameters:                                                          */
/*	vol		: Pointer identifying drive			*/
/*	leastUsed	: Whether most garbage space is the criterion	*/
/*                                                                      */
/* Returns:                                                             */
/*	Best unit to transfer						*/
/*----------------------------------------------------------------------*/

static UnitNo bestUnitToTransfer(Flare vol,  FLBoolean leastUsed)
{
  UnitNo i;

  int mostGarbageSectors = 1;
  unsigned long int leastWearLevelingInfo = 0xffffffffl;
  UnitNo bestUnitSoFar = UNASSIGNED_UNIT_NO;

  for (i = 0; i < vol.noOfUnits; i++) {
    Unit *unit = vol.logicalUnits[i];
    if (unit && (!leastUsed || (unit->noOfGarbageSectors >= mostGarbageSectors))) {
      UnitHeader FAR0 *unitHeader = mapUnitHeader(&vol,unit,NULL);
      if ((leastUsed && (unit->noOfGarbageSectors > mostGarbageSectors)) ||
	  (LE4(unitHeader->wearLevelingInfo) < leastWearLevelingInfo)) {
	mostGarbageSectors = unit->noOfGarbageSectors;
	leastWearLevelingInfo = LE4(unitHeader->wearLevelingInfo);
	bestUnitSoFar = i;
      }
    }
  }

  return bestUnitSoFar;
}


/*----------------------------------------------------------------------*/
/*		           u n i t T r a n s f e r			*/
/*									*/
/* Performs a unit transfer from a selected unit to a tranfer unit.	*/
/*                                                                      */
/* A side effect is to invalidate the map cache (reused as buffer).	*/
/*									*/
/* Parameters:                                                          */
/*	vol		: Pointer identifying drive			*/
/*	toUnit          : Target transfer unit				*/
/*	fromUnitNo:	: Source logical unit no.			*/
/*                                                                      */
/* Returns:                                                             */
/*	FLStatus	: 0 on success, failed otherwise		*/
/*----------------------------------------------------------------------*/

static FLStatus unitTransfer(Flare vol,  Unit *toUnit, UnitNo fromUnitNo)
{
  unsigned i;
  Unit *fromUnit = vol.logicalUnits[fromUnitNo];

  UnitHeader FAR0 *transferUnitHeader = mapUnitHeader(&vol,toUnit,NULL);
  if (!verifyFormat(transferUnitHeader) ||
      LE2(transferUnitHeader->logicalUnitNo) != UNASSIGNED_UNIT_NO)
    /* previous formatting failed or did not complete. 		*/
    checkStatus(formatUnit(&vol,toUnit));

  /* Should the transfer not complete, the unit is marked to be erased */
  checkStatus(assignUnit(&vol,toUnit,MARKED_FOR_ERASE));

#ifdef BACKGROUND
  vol.mirrorFrom = vol.mirrorTo = physicalBase(&vol,fromUnit);
  vol.mirrorOffset = physicalBase(&vol,toUnit) - vol.mirrorFrom;
#endif

  /* copy the block allocation table and the good sectors */
  for (i = 0; i < vol.sectorsPerUnit;) {
    int j;

    FLBoolean needToWrite = FALSE;
    int firstOffset = allocEntryOffset(&vol,i);

    /* Up to 128 bytes of the BAM are processed per loop */
    int nEntries = (128 - (firstOffset & 127)) / sizeof(VirtualAddress);

    /* We are going to use the Virtual Map cache as our sector buffer in the */
    /* transfer, so let's better invalidate the cache first.		   */
#ifdef SINGLE_BUFFER
    if (buffer.dirty)
      return flBufferingError;
#endif
    buffer.sectorNo = UNASSIGNED_SECTOR;

    /* Read some of the BAM */
    vol.flash.read(&vol.flash,
	       physicalBase(&vol,fromUnit) + firstOffset,
	       sectorCopy,
	       nEntries * sizeof(VirtualAddress),
	       0);

    /* Convert garbage entries to free entries */
    for (j = 0; j < nEntries && i+j < vol.sectorsPerUnit; j++) {
      unsigned bamSignature = (unsigned) LE4(sectorCopy[j]) & SECTOR_OFFSET_MASK;
      if (bamSignature == DATA_SECTOR ||
	  bamSignature == REPLACEMENT_PAGE)
	needToWrite = TRUE;
      else if (bamSignature != FORMAT_SECTOR)
	toLE4(sectorCopy[j],FREE_SECTOR);
    }

    if (needToWrite) {
      FLStatus status;

      /* Write new BAM, and copy sectors that need to be copied */
      status = flashWrite(&vol,
			  physicalBase(&vol,toUnit) + firstOffset,
			  sectorCopy,
			  nEntries * sizeof(VirtualAddress),
			  0);
      if (status != flOK) {
#ifdef BACKGROUND
	vol.mirrorOffset = 0;	/* no more mirroring */
#endif
	return status;
      }

      for (j = 0; j < nEntries && i+j < vol.sectorsPerUnit; j++) {
	unsigned bamSignature = (unsigned) LE4(sectorCopy[j]) & SECTOR_OFFSET_MASK;
	if (bamSignature == DATA_SECTOR ||
	    bamSignature == REPLACEMENT_PAGE) { /* a good sector */
	  CardAddress sectorOffset = (CardAddress) (i+j) << SECTOR_SIZE_BITS;

	  vol.flash.read(&vol.flash,
		     physicalBase(&vol,fromUnit) + sectorOffset,
		     sectorCopy,SECTOR_SIZE,0);
	  status = flashWrite(&vol,
			      physicalBase(&vol,toUnit) + sectorOffset,
			      sectorCopy,
			      SECTOR_SIZE,
			      0);
	  if (status != flOK) {
#ifdef BACKGROUND
	    vol.mirrorOffset = 0;	/* no more mirroring */
#endif
	    return status;
	  }
	  vol.flash.read(&vol.flash,
		     physicalBase(&vol,fromUnit) + firstOffset,
		     sectorCopy,
		     nEntries * sizeof(VirtualAddress),0);
	}
      }

#ifdef BACKGROUND
      vol.mirrorTo = vol.mirrorFrom +
		     ((CardAddress) (i + nEntries) << SECTOR_SIZE_BITS);
      while (flForeground(1) == BG_SUSPEND)
	;
#endif
    }

    i += nEntries;
  }

#ifdef BACKGROUND
  vol.mirrorOffset = 0;	/* no more mirroring */
#endif

  /* Write the new logical unit no. */
  checkStatus(assignUnit(&vol,toUnit,fromUnitNo));

  /* Mount the new unit in place of old one */
  vol.logicalUnits[fromUnitNo] = NULL;
  if (mountUnit(&vol,toUnit) == flOK) {
    vol.totalFreeSectors -= fromUnit->noOfFreeSectors;

    /* Finally, format the source unit (the new transfer unit) */
    vol.transferUnit = fromUnit;
    formatUnit(&vol,fromUnit);	/* nothing we can or should do if this fails */
  }
  else {		/* Something went wrong */
    vol.logicalUnits[fromUnitNo] = fromUnit;	/* reinstate original unit */
    return flGeneralFailure;
  }

  return flOK;
}


/*----------------------------------------------------------------------*/
/*		         g a r b a g e C o l l e c t			*/
/*									*/
/* Performs a unit transfer, selecting a unit to transfer and a		*/
/* transfer unit.                                                       */
/*                                                                      */
/* Parameters:                                                          */
/*	vol		: Pointer identifying drive			*/
/*                                                                      */
/* Returns:                                                             */
/*	FLStatus	: 0 on success, failed otherwise		*/
/*----------------------------------------------------------------------*/

static FLStatus garbageCollect(Flare vol)
{
  FLStatus status;
  UnitNo fromUnitNo;

  if (vol.transferUnit == NULL)
    return flWriteProtect;	/* Cannot recover space without a spare unit */

  fromUnitNo = bestUnitToTransfer(&vol,flRandByte() >= 4);
  if (fromUnitNo == UNASSIGNED_UNIT_NO)
    return flGeneralFailure;	/* nothing to collect */

  /* Find a unit we can transfer to.				*/
  status = unitTransfer(&vol,vol.transferUnit,fromUnitNo);
  if (status == flWriteFault) {
    int i;
    Unit *unit = vol.physicalUnits;

    for (i = 0; i < vol.noOfUnits; i++, unit++) {
      if (unit->noOfGarbageSectors == 0 && unit->noOfFreeSectors < 0) {
	if (unitTransfer(&vol,unit,fromUnitNo) == flOK)
	  return flOK;	/* found a good one */
      }
    }
  }

  return status;
}


#ifdef BACKGROUND

/*----------------------------------------------------------------------*/
/*		        b g G a r b a g e C o l l e c t			*/
/*									*/
/* Entry point for garbage collection in the background.		*/
/*                                                                      */
/* Status is returned in vol.garbageCollectStatus			*/
/*                                                                      */
/* Parameters:                                                          */
/*	vol		: Pointer identifying drive			*/
/*          								*/
/* Returns:                                                             */
/*	None								*/
/*----------------------------------------------------------------------*/

static void bgGarbageCollect(void * object)
{
  Flare vol = (Flare *)object;

  vol.garbageCollectStatus = flIncomplete;
  vol.garbageCollectStatus = garbageCollect(&vol);
}

#endif


/*----------------------------------------------------------------------*/
/*      	            d e f r a g m e n t				*/
/*									*/
/* Performs unit transfers to arrange a minimum number of writable	*/
/* sectors.                                                             */
/*									*/
/* Parameters:                                                          */
/*	vol		: Pointer identifying drive			*/
/*	sectorsNeeded	: Minimum required sectors			*/
/*                                                                      */
/* Returns:                                                             */
/*	FLStatus	: 0 on success, failed otherwise		*/
/*----------------------------------------------------------------------*/

#define GARBAGE_COLLECT_THRESHOLD	20

static FLStatus defragment(Flare vol, long FAR2 *sectorsNeeded)
{
  while ((long)(vol.totalFreeSectors) < *sectorsNeeded
#ifdef BACKGROUND
	 || vol.totalFreeSectors < GARBAGE_COLLECT_THRESHOLD
#endif
	 ) {
    if (vol.badFormat)
      return flBadFormat;

#ifdef BACKGROUND
    if (vol.garbageCollectStatus == flIncomplete)
      flBackground(BG_RESUME);
    else
      flStartBackground(&vol - vols,bgGarbageCollect,&vol);
    if (vol.garbageCollectStatus != flOK &&
	vol.garbageCollectStatus != flIncomplete)
      return vol.garbageCollectStatus;

    if (vol.totalFreeSectors >= *sectorsNeeded)
      break;
  }

  if (vol.unitEraseInProgress)
    flBackground(BG_SUSPEND);
#else
    checkStatus(garbageCollect(&vol));
  }
#endif

  *sectorsNeeded = vol.totalFreeSectors;

  return flOK;
}


/*----------------------------------------------------------------------*/
/*		    b e s t U n i t T o A l l o c a t e			*/
/*									*/
/* Finds the best unit from which to allocate a sector. The unit	*/
/* selected is the one with most free space.				*/
/*									*/
/* Parameters:                                                          */
/*	vol		: Pointer identifying drive			*/
/*                                                                      */
/* Returns:                                                             */
/*	Best unit to allocate						*/
/*----------------------------------------------------------------------*/

static Unit *bestUnitToAllocate(Flare vol)
{
  int i;

  int mostFreeSectors = 0;
  Unit *bestUnitSoFar = NULL;

  for (i = 0; i < vol.noOfUnits; i++) {
    Unit *unit = vol.logicalUnits[i];

    if (unit && unit->noOfFreeSectors > mostFreeSectors) {
      mostFreeSectors = unit->noOfFreeSectors;
      bestUnitSoFar = unit;
    }
  }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -