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

📄 nftllite.c

📁 Nandflash翻译层源代码,在论坛上下载的
💻 C
📖 第 1 页 / 共 5 页
字号:
    unsigned char sectorFlags = getSectorFlags(&vol,sectorAddress);

    if (sectorFlags == SECTOR_FREE)
      break;

    if (sectorFlags != SECTOR_IGNORE)
      prevSectorAddress = sectorFlags != SECTOR_DELETED ? sectorAddress :
						    UNASSIGNED_ADDRESS;
  }

  return prevSectorAddress;
}


/*----------------------------------------------------------------------*/
/*		         g e t F o l d M a r k				*/
/*									*/
/* Get the fold mark a unit.						*/
/*                                                                      */
/* Parameters:                                                          */
/*	vol		: Pointer identifying drive			*/
/*	unitNo		: Physical unit number				*/
/*                                                                      */
/* Returns:                                                             */
/*	Return the OR of the two words in the fold mark area (the words	*/
/*	should be identical)						*/
/*----------------------------------------------------------------------*/

static unsigned short getFoldMark(Anand vol, UnitNo unitNo)
{
  unsigned short foldMark[2];

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

  return foldMark[0] | foldMark[1];
}


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

static void getUnitTailer(Anand vol,
			  UnitNo unitNo,
			  unsigned short *eraseMark,
			  unsigned long *eraseCount)
{
  UnitTailer unitTailer;

  vol.flash.read(&vol.flash,
		  unitBaseAddress(&vol,unitNo) + UNIT_TAILER_OFFSET,
		  &unitTailer,
		  sizeof(UnitTailer),
		  EXTRA);

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


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

static FLStatus setUnitTailer(Anand vol,
			    UnitNo unitNo,
			    unsigned short eraseMark,
			    unsigned long eraseCount)
{
  UnitTailer unitTailer;

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

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


/*----------------------------------------------------------------------*/
/*      	             i n i t N F T L				*/
/*									*/
/* Initializes essential volume data as a preparation for mount or	*/
/* format.								*/
/*									*/
/* Parameters:                                                          */
/*	vol		: Pointer identifying drive			*/
/*                                                                      */
/* Returns:                                                             */
/*	FLStatus	: 0 on success, failed otherwise		*/
/*----------------------------------------------------------------------*/

static FLStatus initNFTL(Anand vol)
{
  long int size = 1;

  if (!(vol.flash.flags & NFTL_ENABLED)) {
  #ifdef DEBUG_PRINT
    DEBUG_PRINT("Debug: media is not fit for NFTL format.\n");
  #endif
    return flUnknownMedia;
  }

  vol.physicalUnits = NULL;
  vol.virtualUnits = NULL;

  for (vol.erasableBlockSizeBits = 0; size < vol.flash.erasableBlockSize;
       vol.erasableBlockSizeBits++, size <<= 1);
  vol.unitSizeBits = vol.erasableBlockSizeBits;

  vol.noOfUnits = (unsigned short)((vol.flash.noOfChips * vol.flash.chipSize) >> vol.unitSizeBits);

  /* Adjust unit size so header unit fits in one unit */
  while (vol.noOfUnits * sizeof(PhysUnit) + SECTOR_SIZE > (1UL << vol.unitSizeBits)) {
    vol.unitSizeBits++;
    vol.noOfUnits >>= 1;
  }

  vol.badFormat = TRUE;	/* until mount completes*/
  vol.mappedSectorNo = UNASSIGNED_SECTOR;
  /*get pointer to buffer (we assume SINGLE_BUFFER is not defined) */
  vol.buffer = flBufferOf(flSocketNoOf(vol.flash.socket));
  vol.countsValid = 0;		/* No units have a valid count yet */

  return flOK;
}


/*----------------------------------------------------------------------*/
/*      	            i n i t T a b l e s				*/
/*									*/
/* Allocates and initializes the dynamic volume table, including the	*/
/* unit tables and secondary virtual map.				*/
/*									*/
/* Parameters:                                                          */
/*	vol		: Pointer identifying drive			*/
/*                                                                      */
/* Returns:                                                             */
/*	FLStatus	: 0 on success, failed otherwise		*/
/*----------------------------------------------------------------------*/

static FLStatus initTables(Anand vol)
{
  /* Allocate the conversion tables */
#ifdef MALLOC_TFFS
  vol.physicalUnits = (PhysUnit *) MALLOC_TFFS(vol.noOfUnits * sizeof(PhysUnit));
  vol.virtualUnits = (UnitNo *) MALLOC_TFFS(vol.noOfVirtualUnits * sizeof(UnitNo));
  if (vol.physicalUnits == NULL ||
      vol.virtualUnits == NULL) {
  #ifdef DEBUG_PRINT
    DEBUG_PRINT("Debug: failed allocating conversion tables for NFTL.\n");
  #endif
    return flNotEnoughMemory;
  }
#else
  char *heapPtr;

  heapPtr = vol.heap;
  vol.physicalUnits = (PhysUnit *) heapPtr;
  heapPtr += vol.noOfUnits * sizeof(PhysUnit);
  vol.virtualUnits = (UnitNo *) heapPtr;
  heapPtr += vol.noOfVirtualUnits * sizeof(UnitNo);
  if (heapPtr > vol.heap + sizeof vol.heap) {
  #ifdef DEBUG_PRINT
    DEBUG_PRINT("Debug: not enough memory for NFTL conversion tables.\n");
  #endif
    return flNotEnoughMemory;
  }
#endif

  return flOK;
}

/*----------------------------------------------------------------------*/
/*      	            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(Anand vol, UnitNo unitNo)
{
  unsigned short eraseMark;
  unsigned long eraseCount;

  vol.physicalUnits[unitNo] = UNIT_BAD_MARKED;

  getUnitTailer(&vol,unitNo,&eraseMark,&eraseCount);

  return setUnitTailer(&vol,unitNo,0,eraseCount);
}


/*----------------------------------------------------------------------*/
/*		          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(Anand vol, UnitNo unitNo)
{
  unsigned short eraseMark;
  unsigned long eraseCount;
  FLStatus status;

  if (!(vol.physicalUnits[unitNo] & UNIT_AVAILABLE))
    return flWriteFault;

  if (vol.physicalUnits[unitNo] == UNIT_FREE)
    vol.freeUnits--;
  vol.physicalUnits[unitNo] &= ~UNIT_AVAILABLE;

  getUnitTailer(&vol,unitNo,&eraseMark,&eraseCount);

  status = vol.flash.erase(&vol.flash,
			    unitNo << (vol.unitSizeBits - vol.erasableBlockSizeBits),
			    1 << (vol.unitSizeBits - vol.erasableBlockSizeBits));
  if (status != flOK) {
    markUnitBad(&vol,unitNo);	/* make sure unit format is not valid */
    return status;
  }

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

  checkStatus(setUnitTailer(&vol,unitNo,ERASE_MARK,eraseCount));

  vol.physicalUnits[unitNo] = UNIT_FREE;
  vol.freeUnits++;

  return flOK;
}


/*----------------------------------------------------------------------*/
/*      	        w r i t e A n d C h e c k 			*/
/*									*/
/* Write one sector. 							*/
/*									*/
/* Parameters:                                                          */
/*	vol		: Pointer identifying drive			*/
/*	address		: Physical address of the sector to write to	*/
/*	fromAddress	: Buffer of data to write			*/
/*	flags		: Write flags (ECC, overwrite etc.)		*/
/*									*/
/* Returns:                                                             */
/* 	Status 		: 0 on success, failed otherwise.		*/
/*----------------------------------------------------------------------*/

static FLStatus writeAndCheck(Anand vol,
			    CardAddress address,
			    void FAR1 *fromAddress,
			    unsigned flags)
{
  FLStatus status = vol.flash.write(&vol.flash,address,fromAddress,SECTOR_SIZE,flags);
  if (status == flWriteFault) {  /* write failed, ignore this sector */
    unsigned char sectorFlags[2];

    sectorFlags[0] = sectorFlags[1] = SECTOR_IGNORE;
    vol.flash.write(&vol.flash,address + SECTOR_DATA_OFFSET,sectorFlags,sizeof sectorFlags,EXTRA);
  }

  return status;
}


/*----------------------------------------------------------------------*/
/*      	        c o p y S e c t o r	 			*/
/*									*/
/* Copy one sector to another.						*/
/*									*/
/* Parameters:                                                          */
/*	vol		: Pointer identifying drive			*/
/*	sourceSectorAddress	: Physical address of Sector to copy 	*/
/*				  from.					*/
/*	targetSectorAddress	: Physical address of sector to copy	*/
/*				  to.					*/
/*                                                                      */
/* Returns:                                                             */
/* 	FLStatus       		: 0 on success, failed otherwise.	*/
/*----------------------------------------------------------------------*/

static FLStatus copySector(Anand vol,
			 CardAddress sourceSectorAddress,
			 CardAddress targetSectorAddress)
{
  unsigned flags = EDC;

  vol.flash.socket->remapped = TRUE;
  if (vol.flash.read(&vol.flash,
		     sourceSectorAddress,
		     nftlBuffer,
		     SECTOR_SIZE,
		     EDC) == flDataError) {
    /* If there is an uncorrectable ECC error, copy the data as is */
    unsigned short sectorDataInfo[4];

    vol.flash.read(&vol.flash,
		    sourceSectorAddress,
		    sectorDataInfo,
		    sizeof sectorDataInfo,
		    EXTRA);
    checkStatus(vol.flash.write(&vol.flash,
				 sourceSectorAddress,
				 sectorDataInfo,
				 sizeof sectorDataInfo,
				 EXTRA));
    flags &= ~EDC;
  }

  return writeAndCheck(&vol,targetSectorAddress,nftlBuffer,flags);
}


/*----------------------------------------------------------------------*/
/*      	        l a s t I n C h a i n	 			*/
/*									*/
/* Find last unit in chain.						*/
/*									*/
/* Parameters:                                                          */
/*	vol		: Pointer identifying drive			*/
/* 	unitNo		: Start the search from this unit		*/
/*                                                                      */
/* Returns:                                                             */
/* 	Physical unit number of the last unit in chain.			*/
/*----------------------------------------------------------------------*/

static UnitNo lastInChain(Anand vol, UnitNo unitNo)
{
  UnitNo firstVirtualUnitNo, firstReplacementUnitNo;
  UnitNo lastUnit = unitNo, nextUnitNo;;

  getUnitData(&vol,unitNo,&firstVirtualUnitNo,&firstReplacementUnitNo);
  nextUnitNo = firstReplacementUnitNo;

  while (nextUnitNo < vol.noOfUnits) {  /* Validate replacement unit no. */
    UnitNo nextVirtualUnitNo, nextReplacementUnitNo;

    getUnitData(&vol,nextUnitNo,&nextVirtualUnitNo,&nextReplacementUnitNo);
    if (nextVirtualUnitNo !=
	(firstVirtualUnitNo | REPLACING_UNIT))
      break;        /* Virtual unit no. not validated */
    lastUnit = nextUnitNo;
    nextUnitNo = nextReplacementUnitNo;
  }

⌨️ 快捷键说明

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