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

📄 nftllite.c

📁 Nandflash翻译层源代码,在论坛上下载的
💻 C
📖 第 1 页 / 共 5 页
字号:

  return lastUnit;
}


/*----------------------------------------------------------------------*/
/*		           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(Anand vol, UnitNo unitNo, UnitNo virtualUnitNo)
{
  UnitNo newVirtualUnitNo, newReplacementUnitNo;
  UnitNo oldVirtualUnitNo, oldReplacementUnitNo;
  FLStatus status;
  UnitNo firstUnitNo = vol.virtualUnits[virtualUnitNo];

  /* Assign the new unit */
  newVirtualUnitNo = virtualUnitNo;
  if (firstUnitNo != NO_UNIT)
    newVirtualUnitNo |= REPLACING_UNIT;
  newReplacementUnitNo = NO_UNIT;
  vol.physicalUnits[unitNo] = UNIT_AVAILABLE;
  vol.freeUnits--;
  status = setUnitData(&vol,unitNo,newVirtualUnitNo,newReplacementUnitNo);
  if (status != flOK) {
    markUnitBad(&vol,unitNo);
    return status;
  }

  /* Add unit to chain */
  if (firstUnitNo != NO_UNIT) {
    UnitNo oldUnitNo;

    /* If unit is frozen, don't attempt to chain (folding not-in-place) */
    if (!(vol.physicalUnits[firstUnitNo] & UNIT_AVAILABLE))
      return flOK;

    oldUnitNo = lastInChain(&vol,firstUnitNo);
    getUnitData(&vol,oldUnitNo,&oldVirtualUnitNo,&oldReplacementUnitNo);
    if (oldReplacementUnitNo != NO_UNIT)
      status = flWriteFault;	/* can't write here, so assume failure */
    else {
      oldReplacementUnitNo = unitNo;
      vol.physicalUnits[oldUnitNo] |= UNIT_REPLACED;
      status = setUnitData(&vol,oldUnitNo,oldVirtualUnitNo,oldReplacementUnitNo);
    }
    if (status != flOK) {
      formatUnit(&vol,unitNo); /* Get rid of the allocated unit quickly */
      vol.physicalUnits[firstUnitNo] &= ~UNIT_AVAILABLE; /* freeze the chain */

      return status;
    }
    if (vol.countsValid > virtualUnitNo && firstUnitNo != oldUnitNo)
      if ((vol.physicalUnits[firstUnitNo] & UNIT_COUNT) +
	  (vol.physicalUnits[oldUnitNo] & UNIT_COUNT) <= UNIT_COUNT)
	vol.physicalUnits[firstUnitNo] += (vol.physicalUnits[oldUnitNo] & UNIT_COUNT);
      else
	return flGeneralFailure;
  }
  else
    vol.virtualUnits[virtualUnitNo] = unitNo;

  return flOK;
}


/*----------------------------------------------------------------------*/
/*		           f o r m a t C h a i n			*/
/*									*/
/* Format all the units in a chain. Start from the last one and go	*/
/* backwards until unitNo is reached.					*/
/*                                                                      */
/* Parameters:                                                          */
/*	vol		: Pointer identifying drive			*/
/*	unitNo		: Format the chain from this unit onwards	*/
/*                                                                      */
/* Returns:                                                             */
/*	FLStatus	: 0 on success, failed otherwise		*/
/*----------------------------------------------------------------------*/

static FLStatus formatChain(Anand vol, UnitNo unitNo)
{
  /* Erase the chain from end to start */
  vol.physicalUnits[unitNo] |= UNIT_AVAILABLE;  /* Reenable erase of this unit */
  for (;;) {
    /* Find last unit in chain */
    UnitNo unitToErase = lastInChain(&vol,unitNo);

    formatUnit(&vol,unitToErase);

    if (unitToErase == unitNo)
      break;    /* Erased everything */
  }

  return flOK;
}


static FLStatus allocateUnit(Anand vol, UnitNo *);


/*----------------------------------------------------------------------*/
/*      	             f o l d U n i t				*/
/*									*/
/* Copy all the sectors that hold valid data in the chain to the last   */
/* unit of the chain and erase the chain. 				*/
/*									*/
/* Parameters:                                                          */
/*	vol		: Pointer identifying drive			*/
/*	virtualUnitNo	: Virtual unit number of the first unit in 	*/
/*			  chain.					*/
/*									*/
/* Returns:								*/
/*	FLStatus	: 0 on success, failed otherwise		*/
/*----------------------------------------------------------------------*/

static FLStatus foldUnit(Anand vol, UnitNo virtualUnitNo)
{
  UnitNo unitNo = vol.virtualUnits[virtualUnitNo];
  UnitNo targetUnitNo;
  unsigned long foldMark;
  SectorNo virtualSectorNo;
  CardAddress targetSectorAddress;
  unsigned newSectorCount, i;

  vol.unitsFolded++;

/* Find target unit */
  if (!(vol.physicalUnits[unitNo] & UNIT_AVAILABLE)) {
			/* If this unit is frozen, */
			/* allocate a new unit to fold into */
    checkStatus(allocateUnit(&vol,&targetUnitNo));
    checkStatus(assignUnit(&vol,targetUnitNo,virtualUnitNo));
  }
  else {		/* Default. Fold into end of chain */
    targetUnitNo = unitNo;

    for (;;) {
      UnitNo nextUnitNo = getNextUnit(&vol,targetUnitNo);
      if (nextUnitNo == NO_UNIT)
	break;
      targetUnitNo = nextUnitNo;
    }
  }

/* Mark unit as currently folded */
  foldMark = FOLDING_IN_PROGRESS * 0x10001l;


  vol.flash.write(&vol.flash,
		   unitBaseAddress(&vol,unitNo) + FOLD_MARK_OFFSET,
		   &foldMark,
		   sizeof foldMark,
		   EXTRA);

  vol.physicalUnits[unitNo] &= ~UNIT_AVAILABLE;	/* Freeze this unit chain */

  /* Copy all sectors to target unit */
  virtualSectorNo = (SectorNo)virtualUnitNo * vol.sectorsPerUnit;
  targetSectorAddress = unitBaseAddress(&vol,targetUnitNo);
  newSectorCount = 0;
  for (i = 0; i < vol.sectorsPerUnit; i++, virtualSectorNo++,
       targetSectorAddress += SECTOR_SIZE) {
    CardAddress sourceSectorAddress = virtual2Physical(&vol,virtualSectorNo);
    if (sourceSectorAddress != UNASSIGNED_ADDRESS) {
      newSectorCount++;
      if (sourceSectorAddress != targetSectorAddress) {
	checkStatus(copySector(&vol,sourceSectorAddress,targetSectorAddress));
	vol.parasiteWrites++;
      }
    }
  }

  if (newSectorCount > 0) {	/* Some sectors remaining*/
    /* Mark target unit as original */
    checkStatus(setUnitData(&vol,targetUnitNo,virtualUnitNo,NO_UNIT));
    /* Set target unit in virtual unit table */
    vol.virtualUnits[virtualUnitNo] = targetUnitNo;
    vol.physicalUnits[targetUnitNo] &= ~UNIT_COUNT;
    vol.physicalUnits[targetUnitNo] |= newSectorCount;
  }
  else {
    if (unitNo != targetUnitNo) {
/*    If there is a chain to delete ... */
/*    mark unit as completed folding, pending erase */
      unsigned long foldMark = FOLDING_COMPLETE * 0x10001l;

      vol.flash.write(&vol.flash,
		       unitBaseAddress(&vol,unitNo) + FOLD_MARK_OFFSET,
		       &foldMark,
		       sizeof foldMark,
		       EXTRA);
    }

    vol.virtualUnits[virtualUnitNo] = NO_UNIT;
  }

  /* Erase source units */
  return formatChain(&vol,unitNo);
}


/*----------------------------------------------------------------------*/
/*		           s e t U n i t C o u n t			*/
/*									*/
/* Count the number of sectors in a unit that hold valid data.		*/
/*                                                                      */
/* Parameters:                                                          */
/*	vol		: Pointer identifying drive			*/
/*	unitNo		: Physical unit number				*/
/*                                                                      */
/*----------------------------------------------------------------------*/

static void setUnitCount(Anand vol, UnitNo unitNo)
{
  unsigned int i;
  SectorNo sectorNo;
  UnitNo physicalUnitNo = vol.virtualUnits[unitNo];
  if (physicalUnitNo == NO_UNIT)
    return;

  /* Get a count of the valid sector in this unit */
  vol.physicalUnits[physicalUnitNo] &= ~UNIT_COUNT;

  sectorNo = (SectorNo)unitNo * vol.sectorsPerUnit;
  for (i = 0; i < vol.sectorsPerUnit; i++, sectorNo++) {
    CardAddress sectorAddress = virtual2Physical(&vol,sectorNo);
    if (sectorAddress != UNASSIGNED_ADDRESS) {
      UnitNo currUnitNo = (UnitNo)(sectorAddress >> vol.unitSizeBits);
      if (vol.physicalUnits[currUnitNo] & UNIT_REPLACED)
	currUnitNo = physicalUnitNo;
      vol.physicalUnits[currUnitNo]++;
    }
  }
}


/*----------------------------------------------------------------------*/
/*      	             f o l d B e s t C h a i n			*/
/*									*/
/* Find the best chain to fold and fold it.A good chain to fold is a	*/
/* long chain with a small number of sectors that hold valid data.	*/
/*									*/
/* Parameters:                                                          */
/*	vol		: Pointer identifying drive			*/
/*	unitNo		: Receives the physical unit no. of the first 	*/
/*			  unit in the chain that was folded.		*/
/*									*/
/* Returns:								*/
/*	FLStatus	: 0 on success, failed otherwise		*/
/*----------------------------------------------------------------------*/

static FLStatus foldBestChain(Anand vol, UnitNo *unitNo)
{
  unsigned leastCount = vol.sectorsPerUnit + 1;
  unsigned longestChain = 0;
  UnitNo virtualUnitNo = (UnitNo)0, u;

  for (u = 0; u < vol.noOfVirtualUnits; u++) {
    if (vol.countsValid <= u) {
      setUnitCount(&vol,u);
      vol.countsValid = u + 1;
    }

    if (vol.virtualUnits[u] != NO_UNIT) {
      unsigned char pU = vol.physicalUnits[vol.virtualUnits[u]];
      unsigned unitCount = pU & UNIT_COUNT;

      if (leastCount >= unitCount &&
	 (pU & UNIT_AVAILABLE) &&
	 ((pU & UNIT_REPLACED) || unitCount == 0)) {
	if (unitCount > 0) {
	  int chainLength = 0;

	  /* Compare chain length */
	  UnitNo nextUnitNo = getNextUnit(&vol,vol.virtualUnits[u]);
	  while (nextUnitNo != NO_UNIT) {
	    chainLength++;
	    nextUnitNo = getNextUnit(&vol,nextUnitNo);
	  }
	  if (leastCount == unitCount && longestChain >= (unsigned)chainLength)
	    continue;
	  longestChain = chainLength;
	}
	leastCount = unitCount;
	virtualUnitNo = u;
	if (leastCount == 0)
	  break;
      }
    }
  }

  if (leastCount > vol.sectorsPerUnit)
    return flNotEnoughMemory;	/* No space at all */
  else {
    *unitNo = vol.virtualUnits[virtualUnitNo];
    return foldUnit(&vol,virtualUnitNo);
  }
}


/*----------------------------------------------------------------------*/
/*      	             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(Anand vol, UnitNo *unitNo)
{
  UnitNo originalUnit = vol.roverUnit;

  if (vol.freeUnits) {
    do {
      unsigned char unitFlags;

      if (++vol.roverUnit >= vol.noOfUnits)
	vol.roverUnit = vol.bootUnits;

      unitFlags = vol.physicalUnits[vol.roverUnit];

      if (unitFlags == UNIT_FREE) { /* found a free unit, if not erased, */
	unsigned short eraseMark;
	unsigned long eraseCount;

	getUnitTailer(&vol,vol.roverUnit,&eraseMark,&eraseCount);
	if (eraseMark != ERASE_MARK) {
	  if (formatUnit(&vol,vol.roverUnit) != flOK)
	    continue;	/* this unit is bad, find another */
	}

	*unitNo = vol.roverUnit;
	return flOK;
      }
    } while (vol.roverUnit != originalUnit);
  }

  return foldBestChain(&vol,unitNo);  /* make free units by folding the best chain */
}


/*----------------------------------------------------------------------*/
/*      	             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.							*/
/*----------------------------------------------------------------------*/

static const void FAR0 *mapSector(Anand 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_SECTOR)
	vol.mappedSector = NULL;	/* no such sector */

⌨️ 快捷键说明

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