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

📄 nandfblk.c

📁 PDA上的CF CARD 文件系统的建立程式
💻 C
📖 第 1 页 / 共 3 页
字号:
Description:
	flush the cache content
Input:
	cacheNum - the cache number
Output:
	0	flush ok
	-1	flush failed
**************************************************************/
int NAND_FFS_flushCache(int cacheNum)
{
  int targetBlock;

  /**** added by chilong 01/24/2002 ****/
  int i, j;
  char bNeed2Erase = 0;
  unsigned char *pData;
  int offset;
  int frameNO;
  
  /**** added by chilong 01/24/2002 ****/

  #ifdef NAND_FFS_DEBUG
	sprintf(NAND_FFS_DebugString, "[NAND_FFS_flushCache] cache = %d", cacheNum);
	SprintStringLn(NAND_FFS_DebugString);
  #endif

  // check if the cache number is out of bound
  if (cacheNum < 0 || cacheNum >= NAND_FFS_CACHE_BLOCK_NUM)
  {
	NAND_FFS_Errno = ERROR_INVALID_CACHE;
	return -1;
  }

  targetBlock = NAND_FFS_CacheStatus[cacheNum]->block;

  if (targetBlock == -1)
	return 0;	// unused cache block, no need to flush

  if ((NAND_FFS_CacheStatus[cacheNum]->flag & NAND_FFS_DIRTY_BIT_MASK) == 0)
	return 0;	// block not dirty, no need to flush

  if (NAND_FFS_checkBlock(targetBlock) == -1)
  {
	// errno set by NAND_FFS_checkBlock()
	return -1;	// invalid block
  }

#ifdef NAND_FFS_CACHE_DEBUG
   numFlush++;
#endif

  /**** added by chilong 01/24/2002 ****/
  // check if this block has been erased already
  pData = NAND_FlashAccessBuffer2;
  offset = (targetBlock + NAND_FFS_START_BLOCK) * NAND_FLASH_BLOCK_SIZE;
  for (i = 0; i < NAND_LumpNum; i++)
  {
	sc_disableInt();
	nfshReadFrame(offset, pData);
	sc_enableInt();
			
	// because sizeof(struct NAND_diskLump) is less than NFLASH_FRAME_SIZE
	// after the first frame has been read, we'll know from the lump header
	// whether or not this lump can programmed directly without being erased
	if ( ((struct NAND_diskLump*)pData)->type != NAND_LUMP_TYPE_FREE)
	{
		bNeed2Erase = 1;
		break;
	}
	offset += NAND_LUMP_SIZE;
	pData += NAND_LUMP_SIZE;
  }
  /**** added by chilong 01/24/2002 ****/
  
  // block is dirty, flush the cached block

  if (bNeed2Erase)
  {
  	// erase the flash block
  	if (NAND_FFS_eraseFlashBlock(targetBlock) == -1)
  	{
		// flash erase error
		#ifdef NAND_FFS_DEBUG
			sprintf(NAND_FFS_DebugString, "    erase failed! block = %d", targetBlock);
			SprintStringLn(NAND_FFS_DebugString);
		#endif

		// errno set by NAND_FFS_eraseFlashBlock()
		return -1;
  	}
  }

  /* marked by chilong 01/24/2002 
  // program the flash block
  if (NAND_FFS_programFlashBlock(targetBlock, NAND_FFS_BlockCache[cacheNum]) == -1)
  {
	// flash program error
	#ifdef NAND_FFS_DEBUG
		sprintf(NAND_FFS_DebugString, "    program failed! block = %d", targetBlock);
		SprintStringLn(NAND_FFS_DebugString);
	#endif

	// errno set by NAND_FFS_programFlashBlock()
	return -1;
  }
     marked by chilong 01/24/2002 */

  // program the flash block
//  pData = NAND_FlashAccessBuffer1;
  pData = NAND_FFS_BlockCache[cacheNum];
  frameNO = NAND_LUMP_SIZE / NFLASH_FRAME_SIZE;
  offset = (targetBlock + NAND_FFS_START_BLOCK) * NAND_FLASH_BLOCK_SIZE;
  for (i = 0; i < NAND_LumpNum; i++)
  {
	if ( ((struct NAND_diskLump*)pData)->type == NAND_LUMP_TYPE_FREE)
	{
		// this is a free lump!
		// only the lumps not in cache needs to be programmed
		offset += NAND_LUMP_SIZE;
		pData += NAND_LUMP_SIZE;
		continue;
	}
  	
  	// program the lump back to flash
  	for (j = 0; j < frameNO; j++)
  	{
		sc_disableInt();
		nfshProgramFrame(offset, pData);
		sc_enableInt();
		offset += NFLASH_FRAME_SIZE;
		pData += NFLASH_FRAME_SIZE;
  	}
  }

  // clear the dirty bit
  // this is done after erase & program to make sure that the data are written
  //   back to flash before we can say the cache block are no longer dirty
  NAND_FFS_CacheStatus[cacheNum]->flag &= ~NAND_FFS_DIRTY_BIT_MASK;

  return 0;
}



/*************************************************************
Function: NAND_FFS_flushCacheByHandle
Description:
	flush the cache blocks belonging to the specified handle
Input:
	handle - the file handle
Output:
	0	flush ok
	-1	flush failed
**************************************************************/
int NAND_FFS_flushCacheByHandle(int handle)
{
  int i;
  int returnValue;

  returnValue = 0;

  for (i = 0; i < NAND_FFS_CACHE_BLOCK_NUM; i++)
  {
	// note that the following line only works when there is only one lump per block
	if (NAND_FFS_CacheStatus[i]->handle == handle)
	{
		// cache block belongs to the specified handle, flush it
		if (NAND_FFS_flushCache(i) == -1)
			returnValue = -1;	// errno set by NAND_FFS_flushCache()
	}
  }

  return returnValue;
}



/*************************************************************
Function: NAND_FFS_flushAllCache
Description:
	flush the whole cache
Input:
	none
Output:
	0	all cache blocks flush ok
	-1	some cache blocks failed flushing
**************************************************************/
int NAND_FFS_flushAllCache(void)
{
  int i;
  int returnValue;

  returnValue = 0;

  for (i = 0; i < NAND_FFS_CACHE_BLOCK_NUM; i++)
  {
	if (NAND_FFS_flushCache(i) == -1)
		returnValue = -1;	// errno set by NAND_FFS_flushCache()
  }

  return returnValue;
}



/*************************************************************
Function: NAND_FFS_putBlockInCache
Description:
	Put a new block into the cache
Input:
	newBlock - the block to be cached
	readFlag - 1 = read data from flash to cache
		   0 = does not copy
Output:
	the cache number if swap ok
	-1 if swap failed
**************************************************************/
#ifdef NAND_FFS_CACHE_DEBUG
  int NAND_FFS_putBlockInCache(int newBlock, int readFlag, char bFromReadLump)
#else
  int NAND_FFS_putBlockInCache(int newBlock, int readFlag)
#endif
{
  int i;
  int cacheNum;
  unsigned long oldest;

/**** added by chilong 01/24/2002 ****/
#ifdef NAND_FFS_CACHE_DEBUG
  char bFreeCache = 0;
#endif
/**** added by chilong 01/24/2002 ****/

  #ifdef NAND_FFS_DEBUG
	sprintf(NAND_FFS_DebugString, "[NAND_FFS_putBlockInCache] block = %d", newBlock);
	SprintStringLn(NAND_FFS_DebugString);
  #endif

  // find the least recently modified cache block
  oldest = 0xFFFFFFFF;
  cacheNum = -1;
  for (i = 0; i < NAND_FFS_CACHE_BLOCK_NUM; i++)
  {
	if (NAND_FFS_CacheStatus[i]->block == newBlock)
	{
	#ifdef NAND_FFS_CACHE_DEBUG
		if (bFromReadLump)
			numReadHit++;
		else
			numWriteHit++;
	#endif
	
		return i;	// already in cache
	}

	if (NAND_FFS_CacheStatus[i]->block == -1)
	{
		// this cache block is free, just use it
		cacheNum = i;
	/**** added by chilong 01/24/2002 ****/
	#ifdef NAND_FFS_CACHE_DEBUG
		bFreeCache = 1;
	#endif
	/**** added by chilong 01/24/2002 ****/
		
		break;
	}

	if (NAND_FFS_CacheStatus[i]->lastModTime < oldest)
	{
		oldest = NAND_FFS_CacheStatus[i]->lastModTime;
		cacheNum = i;
	}
  }

  if (cacheNum == -1)
  {
	// unknown error
	NAND_FFS_Errno = ERROR_FILE_SYSTEM;
	return -1;
  }


  /**** added by chilong 01/24/2002 ****/
#ifdef NAND_FFS_CACHE_DEBUG
  if (bFromReadLump)
  	numReadMiss++;
  else
  	numWriteMiss++;
#endif
  /**** added by chilong 01/24/2002 ****/

  #ifdef NAND_FFS_DEBUG
	sprintf(NAND_FFS_DebugString, "    new block put in cache %d", cacheNum);
	SprintStringLn(NAND_FFS_DebugString);
  #endif

  // the cache block 'cacheNum' is least recent used, swap it out
  // flush the cache
  if (NAND_FFS_flushCache(cacheNum) == -1)
  {
	// flush failed, clear the cache
	NAND_FFS_clearCache(cacheNum);
  }

/**** added by chilong 01/24/2002 ****/
#ifdef NAND_FFS_CACHE_DEBUG
  if (bFreeCache != 1)
  	numSwap++;
#endif 
/**** added by chilong 01/24/2002 ****/

  if (readFlag == 1)
  {
	// read specified block to cache
	if (NAND_FFS_readFlashBlock(newBlock, NAND_FFS_BlockCache[cacheNum]) == -1)
	{
		// read failed
		#ifdef NAND_FFS_DEBUG
			sprintf(NAND_FFS_DebugString, "    read failed block = %d", newBlock);
			SprintStringLn(NAND_FFS_DebugString);
		#endif

		// errno set by NAND_FFS_readFlashBlock()
		return -1;
	}
  }

  // update cache status
  NAND_FFS_CacheStatus[cacheNum]->block = newBlock;
  NAND_FFS_CacheStatus[cacheNum]->handle = NAND_FFS_CurrentHandle;
//  NAND_FFS_CacheStatus[cacheNum]->checksum = calcrc32(NAND_FFS_BlockCache[cacheNum], NAND_FLASH_BLOCK_SIZE);

  // modified by chilong 01/24/2002
  NAND_FFS_CacheStatus[cacheNum]->checksum = calcrc32(NAND_FFS_BlockCache[cacheNum], NFLASH_FRAME_SIZE);
  NAND_FFS_CacheStatus[cacheNum]->lastModTime = sc_getTimeStamp();
  NAND_FFS_CacheStatus[cacheNum]->flag = 0;

  return cacheNum;
}



/*************************************************************
Function: NAND_FFS_modifyCache
Description:
	modify the cache content
Input:
	cacheNum - the target cache number
Output:
	none
**************************************************************/
void NAND_FFS_modifyCache(int cacheNum)
{

//  NAND_FFS_CacheStatus[cacheNum]->checksum = calcrc32(NAND_FFS_BlockCache[cacheNum], NAND_FLASH_BLOCK_SIZE);
  // modified by chilong 01/24/2002 
  NAND_FFS_CacheStatus[cacheNum]->checksum = calcrc32(NAND_FFS_BlockCache[cacheNum], NFLASH_FRAME_SIZE);
  NAND_FFS_CacheStatus[cacheNum]->lastModTime = sc_getTimeStamp();
  NAND_FFS_CacheStatus[cacheNum]->flag |= NAND_FFS_DIRTY_BIT_MASK;

  return;
}



/*************************************************************
Function: NAND_FFS_searchBlockInCache
Description:
	search the specified block in cache
Input:
	block - the specified block
Output:
	the cache number if found
	-1 if not found
**************************************************************/
int NAND_FFS_searchBlockInCache(int block)
{
  int i;

  for (i = 0; i < NAND_FFS_CACHE_BLOCK_NUM; i++)
  {
	if (NAND_FFS_CacheStatus[i]->block == block)
	{
		#ifdef NAND_FFS_DEBUG
			sprintf(NAND_FFS_DebugString, "[SEARCH: block in cache %d]", i);
			SprintStringLn(NAND_FFS_DebugString);
		#endif

		return i;
	}
  }

  // block not in cache
  #ifdef NAND_FFS_DEBUG
	sprintf(NAND_FFS_DebugString, "[SEARCH: block not in cache]");
	SprintStringLn(NAND_FFS_DebugString);
  #endif

  return -1;
}



#endif	// #ifdef NAND_FFS_USE_CACHE

#endif	// #ifdef FLASH_DISK_ID


⌨️ 快捷键说明

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