nandmtd.c

来自「nandMtd源码 适用于WIN CE操作系统」· C语言 代码 · 共 1,002 行 · 第 1/3 页

C
1,002
字号
    if((status != flOK) || (tffscmp(temp, flReadback, writeNow) != 0))
      { status = flWriteFault;  break; }
#endif

    length -= writeNow;
    address += writeNow;
    temp += writeNow;

    /* align at sector */
    writeNow = page;
  }

  return flOK ;
}


/*----------------------------------------------------------------------*/
/*		          n a n d E r a s e				*/
/*									*/
/* Erase number of blocks. This routine will be registered as the	*/
/* erase routine for this MTD.						*/
/*                                                                      */
/* Author: 王辉              Date:2004-8-21                            */
/*									*/
/* Parameters:								*/
/*	vol		: Pointer identifying drive			*/
/*	blockNo		: First block to erase.				*/
/*	blocksToErase   : Number of blocks to erase.			*/
/*									*/
/* Returns:                                                          	*/
/*	FLStatus	: 0 on success, otherwise failed.		*/
/*									*/
/*----------------------------------------------------------------------*/

static FLStatus nandMTDErase( FLFlash vol,
			 int blockNo,              /* start' block (0 .. chipNoOfBlocks-1)*/
			 int blocksToErase)        /* Number of blocks to be erased */
{
  int i;
  FLStatus status   = flOK;
  
  NAND_InitECC(); /*初始化ECC编/解码器*/
  NAND_ENABLE_CE(); /*使能NAND Flash的片选*/
  NAND_ENABLE_CONT();   /*置位NFCONT第0位(Mode),NAND Flash controller enable*/
  NAND_BW8();       /*NFCONF的第0位(BusWidth(R/W))置0,即8位总线宽度*/


  if (flWriteProtected(vol.socket))
    return flWriteProtect;

 /* blockNo %= thisVars->noOfBlocks; */                       /* within flash device  */

  if ( blockNo + blocksToErase > thisVars->noOfBlocks )    /* accross device boundary */
    return flBadParameter;
  
  #ifdef DEBUG_PRINT
    DEBUG_PRINT("firstBlock = 0x%x, numOfBlock = 0x%x\n", blockNo, blocksToErase);
  #endif

  for ( i=0; i < blocksToErase; i++, blockNo++ )
  {
    unsigned short pageNo = blockNo * PAGES_PER_BLOCK ;

    WRITE_COMMAND(SETUP_ERASE);
    
    WRITE_ADDRESS((unsigned char)pageNo);        /* A9 ~ A16 */
    WRITE_ADDRESS((unsigned char)(pageNo >> 8));   /* A17 ~ A22 */
    WRITE_ADDRESS((unsigned char)(pageNo >> 16));            /* A25 */

    WRITE_COMMAND(CONFIRM_ERASE);
    
    waitForReady();
    
    if(readStatus() & FAIL)
    {    
      status = flWriteFault;  /* erase operation failed */
    }
  
  #ifdef DEBUG_PRINT
    DEBUG_PRINT("ERASE: blockNo = 0x%x\n", blockNo);
  #endif
   
    if (status != flOK)       /* reset flash device and abort */
    {                              
    #ifdef DEBUG_PRINT
      DEBUG_PRINT("Debug: erase failed in K9F1208U0C.\n");
    #endif
      WRITE_COMMAND(RESET_FLASH);
      waitForReady();

      break ;
    }
  }       /* block loop */

  return status;
}


/*----------------------------------------------------------------------*/
/*		          c d s n M a p					*/
/*									*/
/* Map through buffer. This routine will be registered as the map	*/
/* routine for this MTD.						*/
/*									*/
/* Parameters:								*/
/*	vol	: Pointer identifying drive		                */
/*	address	: Flash address to be mapped.				*/
/*	length	: number of bytes to map.				*/
/*									*/
/* Returns:                                                          	*/
/* 	Pointer to the buffer data was mapped to.			*/
/*									*/
/*----------------------------------------------------------------------*/

static void FAR0 * nandMTDMap ( FLFlash vol,
			    CardAddress address,
			    int length )
{
  /* address -= 0x1000000;*/
  nandMTDRead(&vol,address,thisBuffer,length, 0);
  vol.socket->remapped = TRUE;
  return (void FAR0 *)thisBuffer;
}


/*----------------------------------------------------------------------*/
/*		          i s K n o w n M e d i a			*/
/*									*/
/* Check if this flash media is supported. Initialize relevant fields	*/
/* in data structures.							*/
/*									*/
/* Parameters:								*/
/*	vol		: Pointer identifying drive			*/
/*	vendorId_P	: vendor ID read from chip.			*/
/*	chipId_p	: chip ID read from chip.			*/
/*	dev		: dev chips were accessed before this one.	*/
/*									*/
/* Returns:                                                          	*/
/* 	TRUE if this media is supported, FALSE otherwise.		*/
/*									*/
/*----------------------------------------------------------------------*/
#define KM29N16000_FLASH 0xec64
#define KM29N32000_FLASH 0xece5
#define K9F6408X0C_FLASH  0xece6
#define K9F1208U0M_FLASH 0xec76
 

static FLBoolean isKnownMedia( FLFlash vol,
			 unsigned short vendorId_p,
			 unsigned short chipId_p,
			 int dev )
{
  if (dev == 1)
  {
    thisVars->vendorID = vendorId_p;  /* remember for next chips */
    thisVars->chipID = chipId_p;

    if (vendorId_p == 0xEC)                  /* Samsung */
    {
      switch (chipId_p)
      {
	case 0x64:                         /* 2M */
	case 0xEA:
	  vol.type = KM29N16000_FLASH ;
	  vol.chipSize = 0x200000L;
	  return TRUE;

	case 0xE5:
	case 0xE3:				/* 4M */
	  vol.type = KM29N32000_FLASH;
	  vol.flags |= BIG_PAGE;
	  vol.chipSize = 0x400000L;
	  return TRUE;

	case 0xE6:				/* 8M */
	  vol.type = K9F6408X0C_FLASH;
	  vol.flags |= BIG_PAGE;
	  vol.chipSize = 0x800000L;
	  return TRUE;
	  
	case 0x76:				/* 64M */
	  vol.type = K9F1208U0M_FLASH;
	  vol.flags |= BIG_PAGE;
	  vol.chipSize = 0x4000000L;
	  return TRUE;
      }
    }
    
  }
  else		     /* dev != 0*/
  if( (vendorId_p == thisVars->vendorID) && (chipId_p == thisVars->chipID) )
    return TRUE ;
 
  return FALSE ;
}


/*----------------------------------------------------------------------*/
/*		          r e a d F l a s h I D				*/
/*									*/
/* Read vendor and chip IDs, count flash devices. Initialize relevant	*/
/* fields in data structures.						*/
/*									*/
/* Parameters:								*/
/*	vol		: Pointer identifying drive			*/
/*	interface	: Pointer to window.				*/
/*	dev		: dev chips were accessed before this one.	*/
/*									*/
/* Returns:                                                          	*/
/* 	TRUE if this media is supported, FALSE otherwise.		*/
/*									*/
/*----------------------------------------------------------------------*/

static int readFlashID (FLFlash vol, int dev)
{
  unsigned char vendorId_p, chipId_p;

  NAND_ENABLE_CONT();       /*NFCONF的第0位(BusWidth(R/W))置0,即8位总线宽度*/
  
  
  NAND_INIT1();
  NAND_INIT();
  NAND_ENABLE_CE(); /*使能NAND Flash的片选*/
  NAND_ENABLE_CONT();   /*置位NFCONT第0位(Mode),NAND Flash controller enable*/
  NAND_BW8();       /*NFCONF的第0位(BusWidth(R/W))置0,即8位总线宽度*/
  
  WRITE_COMMAND(RESET_FLASH);
  waitForReady();
  
  NAND_InitECC(); /*初始化ECC编/解码器*/
  
  WRITE_COMMAND(READ_ID);

  WRITE_ADDRESS(0x00);  /* Address. 1cycle */

  READ_DATA(vendorId_p);
  READ_DATA(chipId_p);

  if (isKnownMedia(&vol, vendorId_p, chipId_p, dev) != TRUE)    /* no chip or diff.*/
    return  FALSE ;                                         /* type of flash  */

	    /* set flash parameters*/

  if ( dev == 1 )
  {
    thisVars->pageAreaSize   = 0x100 * vol.interleaving;
    thisVars->pageSize = (vol.flags & BIG_PAGE ? 0x200 : 0x100) * vol.interleaving;
    thisVars->tailSize = (vol.flags & BIG_PAGE ? 16 : 8) * vol.interleaving;
    thisVars->pageMask = thisVars->pageSize - 1 ;
    vol.erasableBlockSize = PAGES_PER_BLOCK * thisVars->pageSize;
    thisVars->noOfBlocks = (unsigned short)( (vol.chipSize * vol.interleaving)
				/ vol.erasableBlockSize ) ;
  }

  return TRUE ;
}


/*----------------------------------------------------------------------*/
/*		     n a n d M T D I d e n t i f y			*/
/*									*/
/* Identify flash. This routine will be registered as the		*/
/* identification routine for this MTD.                                 */
/*									*/
/* Returns:                                                          	*/
/*	FLStatus: 0 on success, otherwise failed.			*/
/*									*/
/*----------------------------------------------------------------------*/

FLStatus nandMTDIdentify(FLFlash vol)
{
#ifdef DEBUG_PRINT
  DEBUG_PRINT("Debug: Entering K9F1208U0C identification routine\n");
#endif

  flSetWindowBusWidth(vol.socket,8);/* use 16-bits */
  flSetWindowSpeed(vol.socket,120);  /* 120 nsec. */
  flSetWindowSize(vol.socket,2);	/* 4 KBytes */

  vol.mtdVars = &mtdVars[flSocketNoOf(vol.socket)];
  /* get pointer to buffer (we assume SINGLE_BUFFER is not defined) */
  thisVars->buffer = flBufferOf(flSocketNoOf(vol.socket));

  vol.interleaving = 1;
  vol.noOfChips = 1;  /* 以1为起始 */
  
  if(readFlashID(&vol, vol.noOfChips) != TRUE )
  {
  #ifdef DEBUG_PRINT
    DEBUG_PRINT("Debug: did not identify K9F1208U0C flash media.\n");
  #endif
    return flUnknownMedia;
  }
  
  /* Register our flash handlers */
  vol.write = nandMTDWrite;
  vol.erase = nandMTDErase;
  vol.read = nandMTDRead;
  vol.map = nandMTDMap;

  vol.flags |= SUSPEND_FOR_WRITE;

#ifdef DEBUG_PRINT
  DEBUG_PRINT("Debug: Identified K9F1208U0C.\n");
#endif

  return flOK;
}


#if	FALSE
/*----------------------------------------------------------------------*/
/*                      f l R e g i s t e r N A N D 			*/
/*									*/
/* Registers this MTD for use						*/
/*									*/
/* Parameters:                                                          */
/*	None								*/
/*                                                                      */
/* Returns:								*/
/*	FLStatus	: 0 on success, otherwise failure		*/
/*----------------------------------------------------------------------*/

FLStatus flRegisterNAND(void)
{
  if (noOfMTDs >= MTDS)
    return flTooManyComponents;

  mtdTable[noOfMTDs++] = nandMTDIdentify;

  return flOK;
}
#endif	/* FALSE */

⌨️ 快捷键说明

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