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

📄 nftllite.c

📁 DOC文件系统驱动源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Applies wear leveling.                                               */
/* A rover unit dictates the current unit to level. If a unit chain     */
/* fold, if single unit chain , append a unit and then fold.            */
/*                                                                      */
/* Parameters:                                                          */
/*    vol        : Pointer identifying drive                            */
/*                                                                      */
/* Returns:                                                             */
/*    FLStatus    : 0 on success, failed otherwise                      */
/*----------------------------------------------------------------------*/

FLStatus swapUnits(Anand vol)
{
  ANANDUnitNo i,unitNo,virtualUnitNo,replacementUnitNo;
  FLStatus    status;

  if(vol.wearLevel.currUnit>=vol.noOfVirtualUnits)
    return flOK;

  for(i=0,unitNo=vol.virtualUnits[vol.wearLevel.currUnit];
      (unitNo==ANAND_NO_UNIT) && (i<vol.noOfVirtualUnits);i++) {

    vol.wearLevel.currUnit++;
    if(vol.wearLevel.currUnit>=vol.noOfVirtualUnits)
      vol.wearLevel.currUnit = 0;

    unitNo=vol.virtualUnits[vol.wearLevel.currUnit];
  }

  if(unitNo==ANAND_NO_UNIT) /*The media is empty*/
    return flOK;

  virtualUnitNo = vol.wearLevel.currUnit;

  vol.wearLevel.currUnit++;
  if(vol.wearLevel.currUnit>=vol.noOfVirtualUnits)
    vol.wearLevel.currUnit = 0;

  if((vol.physicalUnits[unitNo] & UNIT_REPLACED) ||
     (!isAvailable(unitNo)                     )   )
  {
     status = foldUnit(&vol,virtualUnitNo,FALSE);
  }
  else 
  {
     checkStatus(allocateUnit(&vol,&replacementUnitNo));
     return assignUnit(&vol,replacementUnitNo,virtualUnitNo);
  }

  /* If folding failed make sure there are enough units and call again */
  if(status == flCanNotFold)
    return checkFolding(&vol,virtualUnitNo);

  return status;
}


/*----------------------------------------------------------------------*/
/*                       f i n d F r e e U n i t                        */
/*                                                                      */
/* Find a free unit from the physical unit pool.                        */
/*                                                                      */
/* Parameters:                                                          */
/*    vol        : Pointer identifying drive                            */
/*    unitNo     : Receives the physical unit no.                       */
/*                                                                      */
/* Returns:                                                             */
/*    FLStatus    : 0 on success, failed otherwise                      */
/*----------------------------------------------------------------------*/

static FLStatus findFreeUnit(Anand vol, ANANDUnitNo *unitNo)
{
   ANANDUnitNo originalUnit = vol.roverUnit;
   unsigned short eraseMark;
   unsigned long eraseCount;

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

       if (vol.physicalUnits[vol.roverUnit] == ANAND_UNIT_FREE) 
            { 
          /* found a free unit, if not erased, */
          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 flNotEnoughMemory;      /* Report no space at all  */  
}


/*----------------------------------------------------------------------*/
/*                       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.   */
/*    forceFolding  : Boolean flag stating wether to force folding even */
/*                    at the cost of loosing sector data.               */
/*                                                                      */
/* Returns:                                                             */
/*    FLStatus    : 0 on success, failed otherwise                      */
/*----------------------------------------------------------------------*/

static FLStatus foldUnit(Anand vol, ANANDUnitNo virtualUnitNo, FLBoolean forceFolding)
{
  ANANDUnitNo unitNo = vol.virtualUnits[virtualUnitNo];
  ANANDUnitNo targetUnitNo, chainBound;
  unsigned long foldMark;
  SectorNo    virtualSectorNo = (SectorNo)virtualUnitNo * vol.sectorsPerUnit;
  CardAddress endSectorAddress;
  CardAddress targetSectorAddress;
  CardAddress sourceSectorAddress;
  unsigned    newSectorCount, i;
  FLBoolean   partialFoldingFlag = FALSE;
  FLStatus    status;

  /* Force remapping of internal catched sector */
  vol.flash->socket->remapped = TRUE;
  vol.unitsFolded++;

/* When using FL_OFF option the media is scanned in the folding operation */
#if (defined(VERIFY_WRITE) || defined(VERIFY_ERASED_SECTOR))
  if(flVerifyWrite[flSocketNoOf(vol.flash->socket)][vol.flash->socket->curPartition]==FL_OFF)
  {
     checkStatus(verifySectors(&vol,SECTORS_VERIFIED_PER_FOLDING));
     vol.curSectorWrite = virtualSectorNo;
  }
#endif /* VERIFY_WRITE || VERIFY_ERASED_SECTOR */

/* Find target unit */
  if (!isAvailable(unitNo)) /* If this unit is frozen, */
  {
     if(vol.freeUnits > 0)
     {
         /* allocate a new unit to fold into */
         checkStatus(findFreeUnit(&vol,&targetUnitNo));
         checkStatus(assignUnit(&vol,targetUnitNo,virtualUnitNo));
     }
     else
     {
        if(forceFolding==FALSE)
           return flCanNotFold;        
        partialFoldingFlag = TRUE;
     }
  }
 
  if((isAvailable(unitNo)) || (partialFoldingFlag == TRUE))
  {        /* Default. Fold into end of chain */
    targetUnitNo = unitNo;

    for (chainBound=0;( chainBound < DOUBLE_MAX_UNIT_CHAIN );chainBound++) 
    {
      ANANDUnitNo nextUnitNo = getNextUnit(&vol,targetUnitNo,virtualUnitNo);
      if (nextUnitNo == ANAND_NO_UNIT)
         break;
      targetUnitNo = nextUnitNo;
    }
    if(chainBound == DOUBLE_MAX_UNIT_CHAIN)
    {
      targetUnitNo = findEndOfEndlessChain(&vol, virtualUnitNo);
    }
  }

  /***********************************/
  /* Copy all sectors to target unit */
  /***********************************/

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

  if( getFoldMark(&vol,unitNo) != FOLDING_IN_PROGRESS )
    vol.flash->write(vol.flash,
                     unitBaseAddress(&vol,unitNo) + FOLD_MARK_OFFSET,
                     &foldMark,
                     sizeof foldMark,
                     EXTRA);

  setUnavail(unitNo);    /* Freeze this unit chain */

  /* Copy all sectors to target unit */
  targetSectorAddress = unitBaseAddress(&vol,targetUnitNo);
  newSectorCount = 0;

  for (i = 0; i < vol.sectorsPerUnit; i++, virtualSectorNo++,
#if (defined(VERIFY_WRITE) || defined(VERIFY_ERASED_SECTOR))
       vol.curSectorWrite++,
#endif /* VERIFY_WRITE || VERIFY_ERASED_SECTOR */
       targetSectorAddress += SECTOR_SIZE)
  {
     endSectorAddress = ANAND_UNASSIGNED_ADDRESS;
     for(chainBound=0;chainBound<DOUBLE_MAX_UNIT_CHAIN;chainBound++)
     {        
        sourceSectorAddress = virtual2Physical(&vol,virtualSectorNo,&endSectorAddress);        
        if(sourceSectorAddress == targetSectorAddress)
        {
           /* Sector resides on the last unit of the virtual chain and */
           /* does not need to be copied                               */
#if (defined(VERIFY_WRITE) || defined(VERIFY_ERASED_SECTOR))
           switch(flVerifyWrite[flSocketNoOf(vol.flash->socket)][vol.flash->socket->curPartition])
           {
              case FL_UPS:
                 newSectorCount++;
                 goto nextSectorLable;

              case FL_OFF:
                 if(vol.verifiedSectorNo > virtualSectorNo)
                 {
                    newSectorCount++;
                    goto nextSectorLable;
                 }
              default: /* FL_ON */
                 break;
           }

           /* Validate the sector has valid EDC/ECC */
           status = vol.flash->read(vol.flash,sourceSectorAddress,nftlBuffer,SECTOR_SIZE,EDC);
           if(status!=flOK)
           {  /* Last sector of chain has EDC errors - can not fold there */
              if(forceFolding!=TRUE)
              {
                 return flCanNotFold;
              }
              else
              {
                 goto nextSectorLable;
              }
           }
#endif /* VERIFY_WRITE || VERIFY_ERASED_SECTOR */
           newSectorCount++;
           goto nextSectorLable;
        }
        else if(sourceSectorAddress != ANAND_UNASSIGNED_ADDRESS)
        {
           /* Check that area is free (ignore flag) */
           if(getSectorFlags(&vol,targetSectorAddress) != SECTOR_FREE)
           {
              if(forceFolding!=TRUE) 
              {
                 return flCanNotFold;
              }
              else
              {
                 break;
              }
           }          

           /* Copy sector to target sector */
           status = vol.flash->read(vol.flash,sourceSectorAddress,nftlBuffer,SECTOR_SIZE,EDC);
           if (status != flOK) /* Try reading previous sector */
           {
              endSectorAddress = sourceSectorAddress;
              continue; 
           }
           status = writeAndCheck(&vol,targetSectorAddress,nftlBuffer,EDC);
           switch (status)
           {
              case flOK:         /* Success */
                 vol.parasiteWrites++;
                 newSectorCount++;
                 goto nextSectorLable;

              case flWriteFault: /* Faild in verify write */
                 if (forceFolding == FALSE)
                    return flCanNotFold;
                 goto nextSectorLable;

              default :          /* Protection error or any other */
                 return status;
           }
        }
        else /* ANAND_UNASSIGNED_ADDRESS - Sector not used */
        {
            goto nextSectorLable;
        }
     }
     return flGeneralFailure;
nextSectorLable:;
  } /* End of copy sector loop */

  /*****************************/
  /* Add unit to virtual chain */
  /*****************************/

  if (newSectorCount > 0) {    /* Some sectors remaining*/
    /* Mark target unit as original */
    if( (setUnitData(&vol,targetUnitNo,virtualUnitNo,ANAND_NO_UNIT) != flOK ) ||
        (partialFoldingFlag == TRUE))
    {
      setUnavail(targetUnitNo);  /* freeze this unit */
    }
    else
    {
      

⌨️ 快捷键说明

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