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

📄 inftl.c

📁 DOC文件系统驱动源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/*************************************************/
/* T r u e F F S   5.0   S o u r c e   F i l e s */
/* --------------------------------------------- */
/*************************************************/

/*****************************************************************************
* File Header                                                                *
* -----------                                                                *
* Name : inftl.c                                                             *
*                                                                            *
* Description : Implementation of INFTL flash translation layer.             *
*                                                                            *
*****************************************************************************/

/* Internal compilation flags */

/* #define CHAINS_DEBUG  */ /* Prints unit chains after mount routine   */
/* #define CHECK_MOUNT   */ /* Print serious tl debug warnings to       */
                            /* tl_out global file handle                */
/* #define MAKE_SURE_IGNORE_HAS_BAD_EDC */ /* Make sure the ignore mark was */
                                           /* written. If not fill sector   */
                                           /* with 0's.                     */
/* List of included files */

#include "inftl.h"

/* Private variables */

static Bnand vols[VOLUMES];
#ifndef FL_MALLOC
#ifdef NFTL_CACHE
static ucacheEntry   socketUcache[SOCKETS][U_CACHE_SIZE];
static byte socketScache[SOCKETS][S_CACHE_SIZE];
#endif /* NFTL_CACHE */
static Sbyte socketHeap[SOCKETS][ANAND_HEAP_SIZE];
static byte multiSectorBuf[SOCKETS][SECTOR_SIZE<<1];
#else
static byte *multiSectorBuf[SOCKETS];
static Sbyte multiSectorBufCounter[SOCKETS];
#endif /* FL_MALLOC */
#ifdef NFTL_CACHE
/* translation table for Sector Flags cache */
static byte scacheTable[4] = { SECTOR_DELETED, /* 0 */
            SECTOR_IGNORE,  /* 1 */
            SECTOR_USED,    /* 2 */
            SECTOR_FREE };  /* 3 */
#endif /* NFTL_CACHE */

/* Macros */
#define roundToUnits(var) ((var > 0) ? ((ANANDUnitNo)((var - 1) >> vol.unitSizeBits) + 1) : 0)
#define NextGoodUnit(addr,bbt) for(;bbt[(addr >> vol.unitSizeBits) - vol.firstQuickMountUnit]!=ANAND_UNIT_FREE;addr+=1L<<vol.unitSizeBits)
#define countOf(unitNo)      (vol.physicalUnits[unitNo] & UNIT_COUNT)
#define isAvailable(unitNo)  ((vol.physicalUnits[unitNo] == ANAND_UNIT_FREE) || (countOf(unitNo) <= UNIT_MAX_COUNT))
#define setUnavail(unitNo)   (vol.physicalUnits[unitNo]  = UNIT_UNAVAIL)

#define setUnitCount(unitNo,unitCount) { vol.physicalUnits[unitNo] &= ~UNIT_COUNT; vol.physicalUnits[unitNo] |= (ANANDPhysUnit)unitCount; }
#define isLegalUnit(unitNo)  ((unitNo < vol.noOfUnits) || (unitNo == ANAND_NO_UNIT))
#define isValidSectorFlag(sectorFlag) ((sectorFlag==SECTOR_FREE)||(sectorFlag==SECTOR_USED)||(sectorFlag==SECTOR_DELETED))
#define badParityResult(parityResult)   (parityResult != ALL_PARITY_BITS_OK)
#define consecutiveNumbers(first,second) ((byte)(second+1)==first)
#define unitBaseAddress(vol,unitNo) ((CardAddress)((ANANDUnitNo)unitNo+(ANANDUnitNo)vol.firstUnit) << vol.unitSizeBits)
#define distanceOf(read, expected) (onesCount((byte)(read ^ expected)))
#define MarkSectorAsChecked(addr) (scannedBlocks[((addr)>>SECTOR_SIZE_BITS) & vol.sectorsPerUnitMask] = TRUE)
#define WasSectorChecked(addr)     scannedBlocks[((addr)>>SECTOR_SIZE_BITS) & vol.sectorsPerUnitMask]

/* M-Systems INFTL debug routines */
#ifndef CHECK_MOUNT
#define TL_DEBUG_PRINT(x,y,z)
#define SET_EXIT(x)
#define DID_MOUNT_FAIL 1
#endif /* CHECK_MOUNT */
#if (defined(CHECK_MOUNT) || defined (CHAINS_DEBUG))
#include "inftldbg.c"
#endif /* CHECK_MOUNT || CHAINS_DEBUG */


/*------------------------------------------------------*/
/*                o n e s C o u n t                     */
/*                                                      */
/*  counts number of bits that valued 1 in a given byte */
/*------------------------------------------------------*/

static byte onesCount(byte flag)
{
   byte counter;

   for (counter = 0; flag; flag >>= 1)
          if (flag & 1)
           counter++;

   return counter;
}


/*----------------------------------------------------------------------*/
/*                       g e t U n i t T a i l e r                      */
/*                                                                      */
/* Get the erase record of a unit.                                      */
/*                                                                      */
/* Parameters:                                                          */
/*      vol             : Pointer identifying drive                     */
/*      unitNo          : Physical unit number                          */
/*      eraseMark       : Receives the erase mark of the unit           */
/*      eraseCount      : Receives the erase count of the unit          */
/*      offset          : offset in unit                                */
/*                                                                      */
/* Returns:                                                             */
/*      FLStatus        : 0 on success, failed otherwise                */
/*                                                                      */
/*----------------------------------------------------------------------*/

static FLStatus getUnitTailer(Bnand vol,
          ANANDUnitNo unitNo,
          word *eraseMark,
          dword *eraseCount,
          dword offset)
{
  UnitTailer unitTailer;
  FLStatus status;

  status = vol.flash->read(vol.flash,
      unitBaseAddress(vol,unitNo) + offset,
      &unitTailer,
      sizeof(UnitTailer),
      EXTRA);

  /* Mask out any 1 -> 0 bit faults by or'ing with spare data */
  *eraseMark = (word)(LE2(unitTailer.eraseMark) | LE2(unitTailer.eraseMark1));
  *eraseCount = LE4(unitTailer.eraseCount);
  return status;
}


#ifndef FL_READ_ONLY

/*----------------------------------------------------------------------*/
/*                       s e t U n i t T a i l e r                      */
/*                                                                      */
/* Set the erase record of a unit.                                      */
/*                                                                      */
/* Parameters:                                                          */
/*      vol             : Pointer identifying drive                     */
/*      unitNo          : Physical unit number                          */
/*      eraseMark       : Erase mark to set                             */
/*      eraseCount      : Erase count to set                            */
/*      offset          : offset in unit                                */
/*                                                                      */
/* Returns:                                                             */
/*      FLStatus        : 0 on success, failed otherwise                */
/*                                                                      */
/*----------------------------------------------------------------------*/

static FLStatus setUnitTailer(Bnand vol,
        ANANDUnitNo unitNo,
        word eraseMark,
        dword eraseCount,
        dword offset)
{
  UnitTailer unitTailer;

  toLE2(unitTailer.eraseMark,eraseMark);
  toLE2(unitTailer.eraseMark1,eraseMark);
  toLE4(unitTailer.eraseCount,eraseCount);

  return vol.flash->write(vol.flash,
          unitBaseAddress(vol,unitNo) + offset,
          &unitTailer,
          sizeof(UnitTailer),
          EXTRA);
}


/*----------------------------------------------------------------------*/
/*                          m a r k U n i t B a d                       */
/*                                                                      */
/* Mark a unit as bad in the conversion table and the bad units table.  */
/*                                                                      */
/* Parameters:                                                          */
/*      vol             : Pointer identifying drive                     */
/*      unitNo          : Physical number of bad unit                   */
/*                                                                      */
/* Returns:                                                             */
/*      FLStatus        : 0 on success, failed otherwise                */
/*----------------------------------------------------------------------*/

static FLStatus markUnitBad(Bnand vol, ANANDUnitNo unitNo)
{
  word eraseMark;
  dword eraseCount;
  FLStatus status;

  vol.physicalUnits[unitNo] = UNIT_BAD;
  if(vol.freeUnits)
    vol.freeUnits--;

  status = getUnitTailer(&vol,unitNo,&eraseMark,&eraseCount,UNIT_TAILER_OFFSET);
  if (status == flOK)
     status = setUnitTailer(&vol,unitNo,FL_BAD_ERASE_MARK,eraseCount,UNIT_TAILER_OFFSET);

#ifdef NFTL_CACHE
  if (vol.ucache != NULL) /* Mark unit cache as unavaialbel */
  {
     vol.ucache[unitNo].virtualUnitNo = 0xDEAD;
     vol.ucache[unitNo].prevUnitNo    = 0xDEAD;
  }
#endif /* NFTL_CACHE */
  return status;
}


/*----------------------------------------------------------------------*/
/*                        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          : Physical unit to format                       */
/*      eraseMarkOffset : Offset to place erase mark                    */
/*                                                                      */
/* Returns:                                                             */
/*      FLStatus        : 0 on success, failed otherwise                */
/*----------------------------------------------------------------------*/

static FLStatus formatUnit(Bnand vol, ANANDUnitNo unitNo,
                           dword eraseMarkOffset)
{
  word eraseMark;
  dword eraseCount;
  FLStatus status;
#ifndef RAM_MTD
  static const 
#endif /* RAM_MTD */
  byte discard = (byte)CLEAR_DISCARD;

  status = getUnitTailer(&vol,unitNo,&eraseMark,&eraseCount,UNIT_TAILER_OFFSET);
  if(status != flOK)
    return status;

#ifdef NFTL_CACHE
  /* Update ANANDUnitHeader cache to prevent re-filling from flash */
  if (vol.ucache != NULL) {
      vol.ucache[unitNo].virtualUnitNo     = ANAND_NO_UNIT;
      vol.ucache[unitNo].prevUnitNo        = ANAND_NO_UNIT;
      vol.ucache[unitNo].ANAC              = ANAND_UNIT_FREE;
      vol.ucache[unitNo].NAC               = ANAND_UNIT_FREE;
  }

  /*
   * Purge the Sector Flags cache (set entries for all the unit's
   * sectors to SECTOR_FREE).
   */

  if(vol.scache!=NULL)
  {
    tffsset(&(vol.scache[unitNo << (vol.unitSizeBits - SECTOR_SIZE_BITS-2)]),
    S_CACHE_4_SECTORS_FREE, 1 << (vol.unitSizeBits - SECTOR_SIZE_BITS - 2));
  }
#endif /* NFTL_CACHE */

  /* Mark unit as unusable before erase */
  vol.flash->write(vol.flash,(((dword)(vol.firstUnit + unitNo))<<vol.unitSizeBits)+DISCARD_UNIT_OFFSET,&discard,1,EXTRA);

  /* Physicaly erase unit */
  status = vol.flash->erase(vol.flash,(word)((word)(vol.firstUnit + unitNo)
           << vol.blockMultiplierBits),(word)(1 << vol.blockMultiplierBits));

  vol.eraseSum++;
  eraseCount++;
  if (eraseCount == 0)          /* was hex FF's */
    eraseCount++;

  if (status == flOK)
     status = setUnitTailer(&vol,unitNo,ERASE_MARK,eraseCount,eraseMarkOffset);

  if (status != flOK) {
    markUnitBad(&vol,unitNo);   /* make sure unit format is not valid */
    return status;
  }

  if (vol.physicalUnits[unitNo] != ANAND_UNIT_FREE)
  {
     vol.physicalUnits[unitNo] = ANAND_UNIT_FREE;
     vol.freeUnits++;
  }

  return status;
}

⌨️ 快捷键说明

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