📄 nandmtd.c
字号:
/* address : Address of sector to write to. */
/* buffer : buffer to write from. */
/* length : number of bytes to write (up to sector size). */
/* modes : OVERWRITE, EDC flags etc. */
/* */
/* Returns: */
/* FLStatus: 0 on success, otherwise failed. */
/* */
/*----------------------------------------------------------------------*/
static FLStatus nandMTDWrite( FLFlash vol,
CardAddress address, /* target flash address*/
const void FAR1 *buffer, /* source RAM buffer */
int length, /* bytes to write */
int modes) /* Overwrite, EDC flags etc.*/
{
int writeNow;
const char FAR1 *temp;
FLStatus status = flOK;
#ifdef VERIFY_AFTER_WRITE
CardAddress saveAddress = address;
unsigned short flReadback[SECTOR_SIZE / sizeof(unsigned short)];
#endif
/* write in sectors; first and last might be partial*/
int page = modes & EXTRA ? 16 : 512;
#if 0
if(1==nand_is_bad_block((address&(~page))/32))/*坏块判断*/
{
address+=page;
}
#endif
writeNow = page - ((unsigned short)address & (page - 1));
temp = (const char FAR1 *)buffer;
for ( ; length > 0 ; )
{
if (writeNow > length)
{
writeNow = length;
}
/* turn off EDC on partial block write*/
status = writeOnePage(&vol, address, temp, writeNow,
writeNow != 512 ? (modes & ~EDC) : modes);
if (status != flOK)
{
break;
}
#ifdef VERIFY_AFTER_WRITE
status = readOnePage (&vol, address, (char FAR1 *)flReadback,
writeNow, (writeNow != SECTOR_SIZE ? (modes & ~EDC) : modes));
if((status != flOK) || (tffscmp(temp, flReadback, writeNow) != 0))
{
printf("nandMTDWrite:verify error! status=%d\n",status);
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: kuangyaowen Date:2007-11-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;
blockNo %= thisVars->noOfBlocks; /* within flash device */
if ( blockNo + blocksToErase > thisVars->noOfBlocks ) /* accross device boundary */
{
printf("blockNo + blocksToErase=0x%x,thisVars->noOfBlocks=0x%x\n",blockNo + blocksToErase,thisVars->noOfBlocks );
return flBadParameter;
}
#ifdef DEBUG_PRINT
DEBUG_PRINT("firstBlock = 0x%x, numOfBlock = 0x%x\n", blockNo, blocksToErase);
#endif
for ( i=0; i < blocksToErase; i++)
{
unsigned int pageNo = (blockNo+i) * PAGES_PER_BLOCK ;
#if 0
if(1==nand_is_bad_block(i))/*坏块判断*/
{
printf("nandMTDErase :block%d is bad\n",i);
continue;
}
#endif
nand_ce_low(); /*片选有效*/
nand_write_command(SETUP_ERASE);/* 发送块擦除命令0x60*/
nand_ale_high();
nand_write_address((unsigned char)(pageNo&0xff)); /* A9 ~ A16 */
nand_write_address((unsigned char)((pageNo>>8)&0xff)); /* A17 ~ A24 */
nand_write_address((unsigned char)((pageNo>>16)&0x01)); /* A25 */
nand_ale_low();
nand_write_command(CONFIRM_ERASE);/*0xd0*/
waitForReady();
if(readStatus() & FAIL)
{
status = flWriteFault; /* erase operation failed */
}
nand_ce_high(); /*片选取消*/
#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 K9F1208.\n");
#endif
nand_reset();/*reset*/
break ;
}
} /* block loop */
return status;
}
/*----------------------------------------------------------------------*/
/* nand 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 )
{
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. */
/* */
/*----------------------------------------------------------------------*/
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:
vol.type = K9F1208_FLASH; /*64M*/
vol.flags |= BIG_PAGE;
vol.chipSize = 0x04000000L;
return TRUE;
}
}
else if (vendorId_p == 0x8F) /* National */
{
switch (chipId_p)
{
case 0x64: /* 2M */
vol.type = NM29N16_FLASH;
vol.chipSize = 0x200000L;
return TRUE;
}
}
else if (vendorId_p == 0x98) /* Toshiba */
{
vol.flags |= FULL_PAGE; /* no partial page programming */
switch (chipId_p)
{
case 0x64: /* 2M */
case 0xEA:
vol.type = TC5816_FLASH;
vol.chipSize = 0x200000L;
return TRUE;
case 0x6B: /* 4M */
case 0xE5:
vol.type = TC5832_FLASH;
vol.flags |= BIG_PAGE;
vol.chipSize = 0x400000L;
return TRUE;
case 0xE6: /* 8M */
vol.type = TC5816_FLASH;
vol.flags |= BIG_PAGE;
vol.chipSize = 0x800000L;
return TRUE;
}
}
}
else if( (vendorId_p == thisVars->vendorID) && (chipId_p == thisVars->chipID) )
{
return TRUE ; /* dev != 0*/
}
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;
int id_code=0;
nand_init();/*reset flash*/
id_code = nand_get_id(); /*读出芯片的ID信息*/
vendorId_p = (id_code&0xff000000)>>24;/*manufacture ID*/
chipId_p = (id_code&0x00ff0000)>>16;/*device code*/
#ifdef DEBUG_PRINT
printf("manufacture id:0x%x,device code:0x%x\n",vendorId_p,chipId_p);
#endif
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
printf("Debug: Entering K9F1208 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
printf("Debug: did not identify K9F1208 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/*|NFTL_ENABLED*/;/*支持nand flash传输层*/
#ifdef DEBUG_PRINT
printf("Debug: Identified K9F1208.\n");
#endif
return flOK;
}
#if TRUE
/*----------------------------------------------------------------------*/
/* 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 + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -