www.pudn.com > NAND.rar > HardwareAdaptationLayer.c
#include "OSModule_MemoryManagement.h"
#include "HardwareAdaptationLayer.h"
#include "LLD.h"
//Struct LLDHandler, the entry point to HAL advanced function
//*********************************************************
typedef struct lldHandler
{
NFTL_Return (*ReadPage)(UINT16, UINT8, UINT8 *);
NFTL_Return (*WritePage)(UINT16, UINT8, UINT8 *);
NFTL_Return (*CopyPage)(UINT16, UINT8, UINT16, UINT8);
NFTL_Return (*GetPageStatus)(UINT16, UINT8, UINT8 *);
NFTL_Return (*SetPageStatus)(UINT16, UINT8, UINT8 *);
NFTL_Return (*BlockErase)(UINT16);
}LLDHandler;
//*********************************************************
//struct used when write buffering is enabled
//******************************************************
typedef struct WriteDBuffer
{
UINT8 **Buffer;
INT16 LastBlock;
INT8 NoOfChunks;
INT8 *ChunkStatus;
INT8 NoOfSequentialWrite;
INT8 *PageNumber;
INT8 NoOfPages;
UINT8 ChunkWithError;
}WriteDataBuffer;
//*****************************************************
//struct used when read buffering is enabled
//******************************************************
typedef struct ReadDBuffer
{
UINT8 *Buffer;//[LLD_PAGE_FAMILY];
INT16 LastBlockRead;
INT8 LastPageRead;
UINT8 PendingRead;
}ReadDataBuffer;
//*****************************************************
static DeviceArchitecture *currentDevice = NULL;
//************************************************************
// CalculateAddress *
//************************************************************
// retrieve the address of a page from block and page number *
//-----------------------------------------------------------*
// PARAMETERS: *
// blockNumber : number of block *
// pageNumber : number of page *
// returnAddress : the addres searched *
// RETURN VALUES: *
// SUCCESS : ADDRESS CALCULATED *
//************************************************************
//#define mCalculateAddress(BlockNumber,PageNumber) (((UINT32)(BlockNumber)<<14)+(((UINT32)(PageNumber))<<9))
void CalculateAddress(UINT16 blockNumber, UINT8 pageNumber, UINT32 *returnAddress)
{
//UINT32 blockStart;
//blockStart = blockNumber*BLOCK_SIZE;
//*returnAddress = blockStart + (512 * pageNumber);
*returnAddress=(((UINT32)(blockNumber)<<14)+(((UINT32)(pageNumber))<<9));
}
//************** FUNCTION DEFINITION *********************************
NFTL_Return CopyWithCopyBack(UINT16 sourceBlock, UINT8 sourcePage,
UINT16 destinationBlock, UINT8 destinationPage);
NFTL_Return CopyWithoutCopyBack(UINT16 sourceBlock, UINT8 sourcePage,
UINT16 destinationBlock, UINT8 destinationPage);
NFTL_Return Read(UINT16 blockNumber, UINT8 pageNumber, UINT8 *buffer);
NFTL_Return CalculateChunkPosition(UINT16 blockNumber, UINT8 pageNumber,
UINT8 *pageOffset, UINT8 *chunkPosition);
NFTL_Return EraseBlock(UINT16 BlockNumber);
NFTL_Return ReadSpare528(UINT16 BlockNumber, UINT8 PageNumber, UINT8 *buffer);
NFTL_Return WriteSpare528(UINT16 BlockNumber, UINT8 PageNumber, UINT8 *buffer);
NFTL_Return Write528(UINT16 BlockNumber, UINT8 PageNumber, UINT8 *buffer);
NFTL_Return FlushBuffer(void);
NFTL_Return Write528Cached(UINT16 BlockNumber, UINT8 PageNumber, UINT8 *buffer);
//********************************************************************
static LLDHandler Handler =
{
NULL, NULL, NULL, NULL, NULL, NULL
};
static WriteDataBuffer *WDBuffer=NULL;
//static ReadDataBuffer *RDBuffer;
//**********************************************************************
// Handled Function
//*********************************************************************
// The following functions are available to upper layer
//**********************************************************************
// ReadPage *
//**********************************************************************
// Read the page (or chunk) from required position *
//----------------------------------------------------------------------
// PARAMETERS *
// BlockNumber : the number of block where read *
// PageNumber : the page (or chunk ) to read *
// buffer : 528 bytes (data+spare) read *
//**********************************************************************
NFTL_Return ReadPage(UINT16 BlockNumber, UINT8 PageNumber, UINT8 *buffer)
{
return Handler.ReadPage(BlockNumber,PageNumber,buffer);
}
//**********************************************************************
// WritePage *
//**********************************************************************
// Write the page (or chunk) in required position *
// *
// PARAMETERS *
// BlockNumber : the number of block where write *
// PageNumber : the page (or chunk ) to write *
// buffer : 528 bytes (data+spare) to write *
//**********************************************************************
NFTL_Return WritePage(UINT16 BlockNumber, UINT8 PageNumber, UINT8 *buffer)
{
return Handler.WritePage(BlockNumber,PageNumber,buffer);
}
//*****************************************************************************
// CopyPage *
//*****************************************************************************
// Copy a page (or chunk) in another position *
//----------------------------------------------------------------------------*
// PARAMETERS *
// SourceBlockNumber : the number of block containing source page *
// SourcePageNumber : the page (or chunk ) to copy *
// DestinationBlockNumber : the number of destination block *
// DestinationPageNumber : the offset of page (or chunk) in destination block *
//*****************************************************************************
NFTL_Return CopyPage(UINT16 SourceBlockNumber, UINT8 SourcePageNumber,
UINT32 DestinationBlockNumber, UINT8 DestinationPageNumber)
{
return Handler.CopyPage(SourceBlockNumber,SourcePageNumber,DestinationBlockNumber,
DestinationPageNumber);
}
//**********************************************************************
// GetPageStatus *
//**********************************************************************
// Retrieve the spare area of a page (or chunk) *
//---------------------------------------------------------------------*
// PARAMETERS *
// BlockNumber : the number of block where read *
// PageNumber : the offset of page whose read the spare *
// buffer : contain the spare read *
//**********************************************************************
NFTL_Return GetPageStatus(UINT16 BlockNumber, UINT8 PageNumber, UINT8 *buffer)
{
return Handler.GetPageStatus(BlockNumber,PageNumber,buffer);
}
//**********************************************************************
// SetPageStatus *
//**********************************************************************
// Write the spare area of a page (or chunk) *
//---------------------------------------------------------------------*
// PARAMETERS *
// BlockNumber : the number of block where write *
// PageNumber : the offset of page whose write the spare *
// buffer : contain the spare to write *
//**********************************************************************
NFTL_Return SetPageStatus(UINT16 BlockNumber, UINT8 PageNumber, UINT8 *buffer)
{
return Handler.SetPageStatus(BlockNumber,PageNumber,buffer);
}
//**********************************************************************
// SetPageStatus *
//**********************************************************************
// Erase a block on flash *
//---------------------------------------------------------------------*
// PARAMETERS *
// BlockNumber : the number of block to erase *
//**********************************************************************
NFTL_Return BlockErase(UINT16 BlockNumber)
{
return Handler.BlockErase(BlockNumber);
}
//************************************END************************************
//******************************************************************
// ResetWriteBuffer
//****************************************************************
//Resete the buffer,remove page numnres and chunk status
//*****************************************************************
void ResetWriteBuffer()
{
UINT8 i;
for (i = 0; i < WDBuffer->NoOfPages; i++)
WDBuffer->PageNumber[i] = -1;
for (i = 0; i < WDBuffer->NoOfChunks; i++)
{
OS_MemSet(WDBuffer->Buffer[i], 0xFF, sizeof(UINT8) * CHUNK_SIZE);
WDBuffer->ChunkStatus[i] = 0;
}
WDBuffer->NoOfSequentialWrite = 0;
//WDBuffer->LastBlock=-1;
}
//set the handler with the right functions
//*******************************************************************************
// HALInitialization *
//*******************************************************************************
//Initialize each HAL structure, setting function pointers in LLDHandler *
//------------------------------------------------------------------------------*
// RETURN VALUES *
// SUCCESS: Initialization completed *
// FAILURE: an error is occured
//*******************************************************************************
NFTL_Return HALInitialization(void)
{
NFTL_Return RetValue ;
RetValue = NAND_Init() ;
if (RetValue != SUCCESS)
{
return FAILURE ;
}
RecognizeDevice();
//test buffer enabled
//test cache program directive
#if 0
if(UD_BUFFER_ENABLED)
{
INT32 i=0;
// check that buffer size is multiple of 528
if((UD_BUFFER_SIZE%CHUNK_SIZE)!=0)
return FAILURE;
//additional check for 2k page
WDBuffer=(WriteDataBuffer*)OS_DRIVER_Malloc(sizeof(WriteDataBuffer));
if(WDBuffer==NULL)
return FAILURE;
WDBuffer->Buffer=OS_DRIVER_Malloc((sizeof(UINT8*)*UD_BUFFER_SIZE/CHUNK_SIZE));
//error on OS_DRIVER_Malloc
if(WDBuffer->Buffer==NULL)
{
return FAILURE;
}
for(i=0;iBuffer[i]=OS_DRIVER_Malloc(sizeof(UINT8)*CHUNK_SIZE);
if(WDBuffer->Buffer[i]==NULL)
{
return FAILURE;
}
}
WDBuffer->NoOfChunks=UD_BUFFER_SIZE/CHUNK_SIZE;
WDBuffer->ChunkStatus=OS_DRIVER_Malloc(WDBuffer->NoOfChunks);
if(WDBuffer->ChunkStatus==NULL)
{
return FAILURE;
}
WDBuffer->PageNumber=OS_DRIVER_Malloc(UD_BUFFER_SIZE/currentDevice->pageSize);
if(WDBuffer->PageNumber==NULL)
{
return FAILURE;
}
WDBuffer->LastBlock=-1;
WDBuffer->NoOfPages=UD_BUFFER_SIZE/currentDevice->pageSize;
ResetWriteBuffer();
}
#endif
//Handler.WritePage = Write528;
//if (UD_BUFFER_ENABLED)
// Handler.WritePage = Write528Cached;
//else
Handler.WritePage = Write528;
Handler.ReadPage = Read;
Handler.GetPageStatus = ReadSpare528;
Handler.SetPageStatus = WriteSpare528;
if (UD_COPY_BACK)
{
Handler.CopyPage = CopyWithCopyBack;
}
else
{
Handler.CopyPage = CopyWithoutCopyBack;
}
Handler.BlockErase = EraseBlock;
return SUCCESS;
}
//********************************************************************************
// BlockErase *
//********************************************************************************
// Erase a block *
//-------------------------------------------------------------------------------*
//PARAMETERS : *
// BlockNumber : physical block number of block to erase *
//RETURN VALUE *
// SUCCESS : erase completed *
// FAILURE : erase failed *
//********************************************************************************
NFTL_Return EraseBlock(UINT16 BlockNumber)
{
UINT32 returnAddress;
//CalculateAddress(BlockNumber,0,&returnAddress) ;
returnAddress = mCalculateAddress(BlockNumber,0) ;
if (NAND_BlockErase(returnAddress) != NAND_PASS)
{
return FAILURE;
}
return SUCCESS;
}
//********************************************************************************
// Write528 *
//********************************************************************************
// Execute page program in device with 528 bytes page size when write buffering *
// is disabled *
//-------------------------------------------------------------------------------*
// PARAMETERS: *
// BlockNumber : number of bloc where write *
// PageNumber : page offset where write *
// buffer : data that must be write *
// RETURN VALUES: *
// SUCCESS : write completed *
// FAILURE : write failed *
// WRONG_ADDRESS : address not valid *
//********************************************************************************
NFTL_Return Write528(UINT16 BlockNumber, UINT8 PageNumber, UINT8 *buffer)
{
UINT32 returnAddress;
//CalculateAddress(BlockNumber,PageNumber,&returnAddress) ;
returnAddress=mCalculateAddress(BlockNumber,PageNumber) ;
return NAND_PageProgramWithEcc(returnAddress,buffer,currentDevice->pageSize);
}
//********************************************************************************
// IsSamePlan *
//********************************************************************************
// Test if two addresses are on the same plan on device *
//-------------------------------------------------------------------------------*
// PARAMETERS: *
// sourceAddress : first address *
// destinationAddress : second address *
// RETURN VALUES: *
// 1 : addresses are on the same plan *
// 0 : addresses are on different plans *
//********************************************************************************
UINT8 IsSamePlan(UINT32 sourceAddress, UINT32 destinationAddress)
{
UINT32 bitpos;
if ((currentDevice->deviceFamily == 512) && (currentDevice->busWidth == 8))
{
bitpos = 0x3000000;
}//mask (bits 24&25)
//if same plan
if ((sourceAddress & bitpos) == (destinationAddress & bitpos))
{
return 1;
}
else
{
return 0;
}
}
//********************************************************************************
// CopyWithCopyBack *
//********************************************************************************
// Copy a page in another page in device using copyback feature. *
//When source and destination addresses are on different plan the source page *
//is read in ram and later written in flash *
//-------------------------------------------------------------------------------*
// PARAMETERS: *
// sourceBlock : number of physical block containing the source page *
// sourcePage : source page offest *
// destinationBlock : number of physical block where write the page *
// destinationPage : destination page offser *
// RETURN VALUES: *
// 1 : addresses are on the same plan *
// 0 : addresses are on different plans *
//********************************************************************************
NFTL_Return CopyWithCopyBack(UINT16 sourceBlock, UINT8 sourcePage,
UINT16 destinationBlock, UINT8 destinationPage)
{
//single plan or same plan , copy back is always executed
UINT32 sourceAddress;
UINT32 destinationAddress;
//CalculateAddress(sourceBlock,sourcePage,&sourceAddress);
//CalculateAddress(destinationBlock,destinationPage,&destinationAddress) ;
sourceAddress =mCalculateAddress(sourceBlock,sourcePage);
destinationAddress =mCalculateAddress(destinationBlock,destinationPage) ;
{
NAND_Ret ret;
if (IsSamePlan(sourceAddress,destinationAddress))
{
ret = NAND_CopyBack(sourceAddress,destinationAddress);
if (ret != NAND_PASS)
{
return FAILURE;
}
return SUCCESS;
}
else
{
return CopyWithoutCopyBack(sourceBlock,sourcePage,destinationBlock,
destinationPage);
}
}
return SUCCESS;
}
//********************************************************************************
// CopyWithoutCopyBack *
//********************************************************************************
// Copy a page in another page in device without using copyback feature. *
//The source page is read in ram and later written in flash *
//-------------------------------------------------------------------------------*
// PARAMETERS: *
// sourceBlock : number of physical block containing the source page *
// sourcePage : source page offest *
// destinationBlock : number of physical block where write the page *
// destinationPage : destination page offser *
// RETURN VALUES: *
// 1 : addresses are on the same plan *
// 0 : addresses are on different plans *
//********************************************************************************
NFTL_Return CopyWithoutCopyBack(UINT16 sourceBlock, UINT8 sourcePage,
UINT16 destinationBlock, UINT8 destinationPage)
{
//same page
if ((sourceBlock == destinationBlock) && (sourcePage == destinationPage))
{
return FAILURE;
}
if (currentDevice->pageSize == 528)
{
UINT8 buffer[CHUNK_SIZE];
UINT32 sourceAddress;
UINT32 destinationAddress;
//CalculateAddress(sourceBlock,sourcePage,&sourceAddress);
sourceAddress = mCalculateAddress(sourceBlock,sourcePage);
if (NAND_PageRead(sourceAddress,buffer,CHUNK_SIZE) != NAND_PASS)
{
return FAILURE;
}
//CalculateAddress(destinationBlock,destinationPage,&destinationAddress);
destinationAddress =mCalculateAddress(destinationBlock,destinationPage);
return NAND_PageProgram(destinationAddress,buffer,CHUNK_SIZE);
}
return SUCCESS;
}
//********************************************************************************
// Read
//********************************************************************************
// Execute the read of page in device with page size 528 or 2112(cache read disable)
//****************************************************************************** *
// PARAMETERS: *
// blockNumber: block number where the page to read is *
// pageNumber: the number of page to read *
// buffer: will contains read data *
// RETURN VALUES: *
// SUCCESS : read executed correctly *
// FAILURE : error during read *
// WRONG_ADDRESS: addren not valid *
//********************************************************************************
NFTL_Return Read(UINT16 blockNumber, UINT8 pageNumber, UINT8 *buffer)
{
UINT32 sourceAddress;
if (WDBuffer != NULL)
if (WDBuffer->NoOfSequentialWrite > 0)
{
NFTL_Return ret;
ret = FlushBuffer();
if (ret != SUCCESS)
return ret;
}
//CalculateAddress(blockNumber,pageNumber,&sourceAddress);
sourceAddress =mCalculateAddress(blockNumber,pageNumber);
if (NAND_PageReadWithEcc(sourceAddress,buffer,currentDevice->pageSize) != NAND_PASS)
{
return FAILURE;
}
return SUCCESS;
}
NFTL_Return Read512(UINT16 blockNumber, UINT8 pageNumber, UINT8 *buffer)
{
UINT32 sourceAddress;
//CalculateAddress(blockNumber,pageNumber,&sourceAddress);
sourceAddress =mCalculateAddress(blockNumber,pageNumber);
if (NAND_PageRead512(sourceAddress,buffer) != NAND_PASS)
{
return FAILURE;
}
return SUCCESS;
}
INT8 IsPageInBuffer(UINT8 pageNumber)
{
UINT8 i;
for(i=0;iNoOfPages;i++)
{
if(WDBuffer->PageNumber[i]==pageNumber)
return i;
}
return -1;
}
//********************************************************************************
// ReadSpare528 *
//********************************************************************************
// Exexute the read of spare area in page of 528 bytes size *
//--------------------------------------------------------------------------------
// PARAMETERS: *
// blockNumber: block number where the spare to read is *
// pageNumber: the number of page to read *
// buffer: will contains read data *
// RETURN VALUES: *
// SUCCESS : read executed correctly *
// FAILURE : error during read *
//********************************************************************************
NFTL_Return ReadSpare528(UINT16 BlockNumber, UINT8 PageNumber, UINT8 *buffer)
{
INT8 pageInBuffer;
UINT32 returnAddress;
//if cache program enabled
#if 0
if(UD_BUFFER_ENABLED)
{
if(WDBuffer->LastBlock==BlockNumber)
{
pageInBuffer=IsPageInBuffer(PageNumber);
//is in write buffer
if(pageInBuffer!=-1)
{
OS_MemCopy(buffer,(WDBuffer->Buffer[pageInBuffer])+currentDevice->mainSize,CHUNK_SPARE_SIZE);
return SUCCESS;
}
}
}
#endif
//CalculateAddress(BlockNumber,PageNumber,&returnAddress);
returnAddress=mCalculateAddress(BlockNumber,PageNumber);
if (NAND_SpareRead(returnAddress,buffer,CHUNK_SPARE_SIZE) != NAND_PASS)
return FAILURE ;
return SUCCESS;
}
void WriteChunkInBuffer(UINT8 pagePos, UINT8 PageNum, UINT16 BlockNumber, UINT8 *buffer,
UINT16 bufferLength, UINT16 offsetInBuffer, UINT16 chunkPosition)
{
WDBuffer->PageNumber[pagePos] = PageNum;
WDBuffer->LastBlock = BlockNumber;
WDBuffer->ChunkStatus[chunkPosition] = 1;
OS_MemCopy((WDBuffer->Buffer[chunkPosition]) + offsetInBuffer, buffer, bufferLength);
WDBuffer->NoOfSequentialWrite++;
}
NFTL_Return RecognizeDevice()
{
//read the man code and id of device and autoset the device details
if (currentDevice != NULL)
{
return SUCCESS;
}
currentDevice = (DeviceArchitecture *) OS_DRIVER_Malloc(sizeof(DeviceArchitecture));
if (currentDevice == NULL)
{
return FAILURE;
}
currentDevice->blockSize = 16 * 1024;/*16k*/
currentDevice->pagesInBlock = 32;
currentDevice->manCode = 0xec;
currentDevice->devCode = 0x76;
currentDevice->numOfBlocks = 4096;
currentDevice->mainSize = 512;
currentDevice->spareSize = 16;
currentDevice->pageSize = 528;
currentDevice->planNumber = 2;
currentDevice->deviceFamily = 512;
currentDevice->devicesNumber = 1;
currentDevice->busWidth = 8;
return SUCCESS;
}
//******************************************************************************
// GetDeviceArchitecture
//******************************************************************************
//Retrieve the nand device detail an fill a DeviceArchitecture struct with them
//-----------------------------------------------------------------------------
// PARAMETERS:
// deviceArchitecture : the struct that will contains the device details
//*****************************************************************************
DeviceArchitecture GetDeviceArchitecture()
{
DeviceArchitecture devArch;
devArch.blockSize = currentDevice->blockSize;
devArch.pagesInBlock = currentDevice->pagesInBlock;
devArch.manCode = currentDevice->manCode;
devArch.devCode = currentDevice->devCode;
devArch.numOfBlocks = currentDevice->numOfBlocks;
devArch.mainSize = currentDevice->mainSize;
devArch.spareSize = currentDevice->spareSize;
devArch.pageSize = currentDevice->mainSize + currentDevice->spareSize;
devArch.planNumber = currentDevice->planNumber;
devArch.deviceFamily = currentDevice->deviceFamily;
devArch.devicesNumber = currentDevice->devicesNumber;
devArch.busWidth = currentDevice->busWidth;
return devArch;
}
//******************************************************************************
// CalculateChunkPosition
//******************************************************************************
// Retrieve the position of a chunk in the write buffer
//******************************************************************************
// PARAMETERS:
// blockNumber: the block physical number
// pageNumber : the number of page containing the chunk
// pageOffset : it will contains the offset of the page in the buffer array
// chunkPosition : it will contains the position of the chunk in the chunk array
//
// RETURN VALUES:
// SUCCESS : no problem have occurs
// WRONG_ADDRESS : the address is not in the device
// FAILURE : the chunk is not present in buffer
//*********************************************************************************
NFTL_Return CalculateChunkPosition(UINT16 blockNumber, UINT8 pageNumber,
UINT8 *pageOffset, UINT8 *chunkPosition)
{
if (pageNumber >=
currentDevice->pagesInBlock * (currentDevice->mainSize / CHUNK_DATA_SIZE))
{
return WRONG_ADDRESS;
}
//calculate the physical page number containing the chunk pageNumber
if (pageNumber <= ((currentDevice->pageSize / CHUNK_SIZE) - 1))
{
*pageOffset = 0;
*chunkPosition = pageNumber;
return SUCCESS;
}
else
{
*pageOffset = pageNumber / (currentDevice->pageSize / CHUNK_SIZE);
*chunkPosition = pageNumber -
(currentDevice->pageSize / CHUNK_SIZE) * (*pageOffset);
return SUCCESS;
}
return FAILURE;
}
NFTL_Return Unmount_HAL()
{
#if 0
int i;
if (UD_BUFFER_ENABLED)
{
if (WDBuffer != NULL)
{
for (i = 0; i < UD_BUFFER_SIZE / CHUNK_SIZE; i++)
{
if (WDBuffer->Buffer[i] != NULL)
{
OS_DRIVER_Free(WDBuffer->Buffer[i]);
WDBuffer->Buffer[i] = NULL;
}
}
if (WDBuffer->Buffer != NULL)
{
OS_DRIVER_Free(WDBuffer->Buffer);
WDBuffer->Buffer = NULL;
}
if (WDBuffer->ChunkStatus != NULL)
{
OS_DRIVER_Free(WDBuffer->ChunkStatus);
WDBuffer->ChunkStatus = NULL;
}
if (WDBuffer->PageNumber != NULL)
{
OS_DRIVER_Free(WDBuffer->PageNumber);
WDBuffer->PageNumber = NULL;
}
OS_DRIVER_Free(WDBuffer);
WDBuffer = NULL;
}
}
#endif
return SUCCESS;
}
//***********************************************************************************
// FlushBuffer *
//***********************************************************************************
// Flush the write buffer *
//----------------------------------------------------------------------------------*
// On error (FLUSH_ERROR) do not empty the buffer for future recovery *
// RETURN VALUES: *
// SUCCESS : flush executed without errors *
// FLUSH_ERROR : error during cache program, ChunkWithError in WDBuffer contain *
// the page number where programming is failed *
// FAILURE : error in program of page,ChunkWithError in WDBuffer contain *
// the page number where programming is failed *
//***********************************************************************************
NFTL_Return FlushBuffer(void)
{
//buffer not allocated
//return
if (WDBuffer == NULL)
return SUCCESS;
{
INT32 i;
for (i = 0; i < WDBuffer->NoOfSequentialWrite; i++)
{
UINT32 address;
NFTL_Return returnValue;
CalculateAddress(WDBuffer->LastBlock, WDBuffer->PageNumber[i], &address);
//execute the page program
returnValue = NAND_PageProgramWithEcc(address, WDBuffer->Buffer[i],
currentDevice->pageSize);
if (returnValue != NAND_PASS)
{
WDBuffer->ChunkWithError = i;
return FLUSH_ERROR;
}
}
}
WDBuffer->LastBlock = -1;
ResetWriteBuffer();
return SUCCESS;
}
INT8 FirstFreePageInBuffer()
{
INT8 i;
for (i = 0; i < WDBuffer->NoOfPages; i++)
{
if (WDBuffer->PageNumber[i] == -1)
return i;
}
//no OS_Free page
return -1;
}
//********************************************************************************
// Write528Cached *
//********************************************************************************
// Execute page program in device with 528 bytes page size when write buffering *
// is enabled *
//********************************************************************************
// PARAMETERS: *
// BlockNumber : number of block where write *
// PageNumber : number of page where write *
// buffer : number of page where write *
//********************************************************************************
NFTL_Return Write528Cached(UINT16 BlockNumber, UINT8 PageNumber, UINT8 *buffer)
{
NFTL_Return ret;
if (WDBuffer->LastBlock == -1)
{
WriteChunkInBuffer(0, PageNumber, BlockNumber, buffer, CHUNK_SIZE, 0, 0);
return SUCCESS;
}
//buffer must be flushed
if (WDBuffer->LastBlock != BlockNumber)
{
ret = FlushBuffer();
if (ret != SUCCESS)
return ret;
WriteChunkInBuffer(0, PageNumber, BlockNumber, buffer, CHUNK_SIZE, 0, 0);
return SUCCESS;
}
else
{
//check if page is yet present in buffer
INT8 pageNum;
pageNum = IsPageInBuffer(PageNumber);
//page is in buffer
if (pageNum != -1)
{
OS_MemCopy((WDBuffer->Buffer[pageNum]) , buffer, CHUNK_SIZE);
return SUCCESS;
}
else
{
pageNum = FirstFreePageInBuffer();
//there is no space in buffer
if (pageNum == -1)
{
ret = FlushBuffer();
if (ret != SUCCESS)
return ret;
pageNum = 0;
}
}
WriteChunkInBuffer(pageNum, PageNumber, BlockNumber, buffer, CHUNK_SIZE, 0, pageNum);
}
return SUCCESS;
}
//******************************************************************************
// WriteSpare528
//******************************************************************************
// Exexute the write of spare area in page of 528 bytes size
//--------------------------------------------------------------------------------
// PARAMETERS: *
// BlockNumber: block number where the spare to write is *
// PageNumber: the number of page to write *
// buffer: contains data to write *
// *
// RETURN VALUES: *
// SUCCESS : read executed correctly *
// FAILURE : error during read *
// FLUSH_ERROR : error during buffer flush *
//******************************************************************************
NFTL_Return WriteSpare528(UINT16 BlockNumber, UINT8 PageNumber, UINT8 *buffer)
{
UINT32 returnAddress;
#if 0
if (UD_BUFFER_ENABLED)
{
//buffer is empty
if (WDBuffer->LastBlock == -1)
{
WriteChunkInBuffer(0, PageNumber, BlockNumber, buffer, CHUNK_SIZE,
currentDevice->mainSize, 0);
return SUCCESS;
}
//buffer must be flushed
if (WDBuffer->LastBlock != BlockNumber)
{
NFTL_Return ret;
ret = FlushBuffer();
if (ret != SUCCESS)
return ret;
WriteChunkInBuffer(0, PageNumber, BlockNumber, buffer, CHUNK_SIZE,
currentDevice->mainSize, 0);
return SUCCESS;
}
else
{
//check if page is yet present in buffer
INT8 pageNum;
pageNum = IsPageInBuffer(PageNumber);
if (pageNum != -1)
{
NFTL_Return ret;
ret = FlushBuffer();
if (ret != SUCCESS)
return ret;
}
WriteChunkInBuffer(WDBuffer->NoOfSequentialWrite, PageNumber, BlockNumber, buffer,
CHUNK_SIZE, currentDevice->mainSize, 0);
//buffer is full,flush the buffer
if (WDBuffer->NoOfSequentialWrite == WDBuffer->NoOfChunks)
{
return FlushBuffer();
}
return SUCCESS;
}
}
#endif
//CalculateAddress(BlockNumber,PageNumber,&returnAddress) ;
returnAddress = mCalculateAddress(BlockNumber,PageNumber) ;
if (NAND_SpareProgram(returnAddress,buffer,CHUNK_SPARE_SIZE) != NAND_PASS)
{
return FAILURE;
}
return SUCCESS;
}