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; 
}