www.pudn.com > NAND.rar > NandFAT.c


/* 
 * FileName:	   fat.c 
 *Copyright(c) 2004 VIA Technologies, Inc. All Rights Reserved. 
 * 
 * Author:  	   penson  Version: 1.00  Date: 2004-10-25 
 * Description:   this file define  functions about sd card 
 * Version: 	    
 * Function List:   
 *  			   1. 
 * History: 	    
 *        <10-25>        
 */ 
 
 
//#define _DEBUG_ON_ 
 
 
//#include  
//#include  
 
//#include "driversys.h" 
#include "drivermmiif.h" 
#include "Driverosif.h" 
 
//#include "driverprim.h" 
//#include "type_zac.h" 
#include "NANDFAT.h" 
 
//#include "OSModule_MemoryManagement.h" 
//#include"BadBlockManagement.h"   
 
const UINT8 BPBTaBle[512] = 
/*{ 
	0xEB, 0x3C, 0x90, 'V' ,  'I', 'A', 'T', 'E', 'C', 'T', 'H', 0x00, 0x02, 0x02, 0x01, 0x00,  
	0x02, 0x00, 0x02, 0x00, 0x00, 0xF8, 0xFF, 0x00, 0x3F, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,  
	0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x29, 0xCA, 0x61, 0x58, 0x30, 0x4C, 0x4F, 0x56, 0x45, 0x42,  
	0x45, 0x4E, 0x46, 0x45, 0x4E, 0x20, 0x46, 0x41, 0x54, 0x31, 0x36, 0x20, 0x20, 0x20, 0x33, 0xC9,  
	0x8E, 0xD1, 0xBC, 0xF0, 0x7B, 0x8E, 0xD9, 0xB8, 0x00, 0x20, 0x8E, 0xC0, 0xFC, 0xBD, 0x00, 0x7C,  
	0x38, 0x4E, 0x24, 0x7D, 0x24, 0x8B, 0xC1, 0x99, 0xE8, 0x3C, 0x01, 0x72, 0x1C, 0x83, 0xEB, 0x3A,  
	0x66, 0xA1, 0x1C, 0x7C, 0x26, 0x66, 0x3B, 0x07, 0x26, 0x8A, 0x57, 0xFC, 0x75, 0x06, 0x80, 0xCA,  
	0x02, 0x88, 0x56, 0x02, 0x80, 0xC3, 0x10, 0x73, 0xEB, 0x33, 0xC9, 0x8A, 0x46, 0x10, 0x98, 0xF7,  
	0x66, 0x16, 0x03, 0x46, 0x1C, 0x13, 0x56, 0x1E, 0x03, 0x46, 0x0E, 0x13, 0xD1, 0x8B, 0x76, 0x11,  
	0x60, 0x89, 0x46, 0xFC, 0x89, 0x56, 0xFE, 0xB8, 0x20, 0x00, 0xF7, 0xE6, 0x8B, 0x5E, 0x0B, 0x03,  
	0xC3, 0x48, 0xF7, 0xF3, 0x01, 0x46, 0xFC, 0x11, 0x4E, 0xFE, 0x61, 0xBF, 0x00, 0x00, 0xE8, 0xE6,  
	0x00, 0x72, 0x39, 0x26, 0x38, 0x2D, 0x74, 0x17, 0x60, 0xB1, 0x0B, 0xBE, 0xA1, 0x7D, 0xF3, 0xA6,  
	0x61, 0x74, 0x32, 0x4E, 0x74, 0x09, 0x83, 0xC7, 0x20, 0x3B, 0xFB, 0x72, 0xE6, 0xEB, 0xDC, 0xA0,  
	0xFB, 0x7D, 0xB4, 0x7D, 0x8B, 0xF0, 0xAC, 0x98, 0x40, 0x74, 0x0C, 0x48, 0x74, 0x13, 0xB4, 0x0E,  
	0xBB, 0x07, 0x00, 0xCD, 0x10, 0xEB, 0xEF, 0xA0, 0xFD, 0x7D, 0xEB, 0xE6, 0xA0, 0xFC, 0x7D, 0xEB,  
	0xE1, 0xCD, 0x16, 0xCD, 0x19, 0x26, 0x8B, 0x55, 0x1A, 0x52, 0xB0, 0x01, 0xBB, 0x00, 0x00, 0xE8,  
	0x3B, 0x00, 0x72, 0xE8, 0x5B, 0x8A, 0x56, 0x24, 0xBE, 0x0B, 0x7C, 0x8B, 0xFC, 0xC7, 0x46, 0xF0,  
	0x3D, 0x7D, 0xC7, 0x46, 0xF4, 0x29, 0x7D, 0x8C, 0xD9, 0x89, 0x4E, 0xF2, 0x89, 0x4E, 0xF6, 0xC6,  
	0x06, 0x96, 0x7D, 0xCB, 0xEA, 0x03, 0x00, 0x00, 0x20, 0x0F, 0xB6, 0xC8, 0x66, 0x8B, 0x46, 0xF8,  
	0x66, 0x03, 0x46, 0x1C, 0x66, 0x8B, 0xD0, 0x66, 0xC1, 0xEA, 0x10, 0xEB, 0x5E, 0x0F, 0xB6, 0xC8,  
	0x4A, 0x4A, 0x8A, 0x46, 0x0D, 0x32, 0xE4, 0xF7, 0xE2, 0x03, 0x46, 0xFC, 0x13, 0x56, 0xFE, 0xEB,  
	0x4A, 0x52, 0x50, 0x06, 0x53, 0x6A, 0x01, 0x6A, 0x10, 0x91, 0x8B, 0x46, 0x18, 0x96, 0x92, 0x33,  
	0xD2, 0xF7, 0xF6, 0x91, 0xF7, 0xF6, 0x42, 0x87, 0xCA, 0xF7, 0x76, 0x1A, 0x8A, 0xF2, 0x8A, 0xE8,  
	0xC0, 0xCC, 0x02, 0x0A, 0xCC, 0xB8, 0x01, 0x02, 0x80, 0x7E, 0x02, 0x0E, 0x75, 0x04, 0xB4, 0x42,  
	0x8B, 0xF4, 0x8A, 0x56, 0x24, 0xCD, 0x13, 0x61, 0x61, 0x72, 0x0B, 0x40, 0x75, 0x01, 0x42, 0x03,  
	0x5E, 0x0B, 0x49, 0x75, 0x06, 0xF8, 0xC3, 0x41, 0xBB, 0x00, 0x00, 0x60, 0x66, 0x6A, 0x00, 0xEB,  
	0xB0, 0x4E, 0x54, 0x4C, 0x44, 0x52, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0D, 0x0A, 0x4E, 0x54,  
	0x4C, 0x44, 0x52, 0x20, 0x69, 0x73, 0x20, 0x6D, 0x69, 0x73, 0x73, 0x69, 0x6E, 0x67, 0xFF, 0x0D,  
	0x0A, 0x44, 0x69, 0x73, 0x6B, 0x20, 0x65, 0x72, 0x72, 0x6F, 0x72, 0xFF, 0x0D, 0x0A, 0x50, 0x72,  
	0x65, 0x73, 0x73, 0x20, 0x61, 0x6E, 0x79, 0x20, 0x6B, 0x65, 0x79, 0x20, 0x74, 0x6F, 0x20, 0x72,  
	0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xAC, 0xBF, 0xCC, 0x55, 0xAA 
}; 
*/ 
{ 
	0xEB, 0x3C, 0x90, 0x4D, 0x53, 0x44, 0x4F, 0x53, 0x35, 0x2E, 0x30, 0x00, 0x02, 0x02, 
	0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x00, 0xF8, 0xFB, 0x00, 0x3F, 0x00, 0xFF, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x01, 0x00, 0x00, 0x01, 0x29, 0xBE, 0x48, 0x2D, 
	0xF8, 0x4E, 0x4F, 0x20, 0x4E, 0x41, 0x4D, 0x45, 0x20, 0x20, 0x20, 0x20, 0x46, 0x41, 
	0x54, 0x31, 0x36, 0x20, 0x20, 0x20, 0x33, 0xC9, 0x8E, 0xD1, 0xBC, 0xF0, 0x7B, 0x8E, 
	0xD9, 0xB8, 0x00, 0x20, 0x8E, 0xC0, 0xFC, 0xBD, 0x00, 0x7C, 0x38, 0x4E, 0x24, 0x7D, 
	0x24, 0x8B, 0xC1, 0x99, 0xE8, 0x3C, 0x01, 0x72, 0x1C, 0x83, 0xEB, 0x3A, 0x66, 0xA1, 
	0x1C, 0x7C, 0x26, 0x66, 0x3B, 0x07, 0x26, 0x8A, 0x57, 0xFC, 0x75, 0x06, 0x80, 0xCA, 
	0x02, 0x88, 0x56, 0x02, 0x80, 0xC3, 0x10, 0x73, 0xEB, 0x33, 0xC9, 0x8A, 0x46, 0x10, 
	0x98, 0xF7, 0x66, 0x16, 0x03, 0x46, 0x1C, 0x13, 0x56, 0x1E, 0x03, 0x46, 0x0E, 0x13, 
	0xD1, 0x8B, 0x76, 0x11, 0x60, 0x89, 0x46, 0xFC, 0x89, 0x56, 0xFE, 0xB8, 0x20, 0x00, 
	0xF7, 0xE6, 0x8B, 0x5E, 0x0B, 0x03, 0xC3, 0x48, 0xF7, 0xF3, 0x01, 0x46, 0xFC, 0x11, 
	0x4E, 0xFE, 0x61, 0xBF, 0x00, 0x00, 0xE8, 0xE6, 0x00, 0x72, 0x39, 0x26, 0x38, 0x2D, 
	0x74, 0x17, 0x60, 0xB1, 0x0B, 0xBE, 0xA1, 0x7D, 0xF3, 0xA6, 0x61, 0x74, 0x32, 0x4E, 
	0x74, 0x09, 0x83, 0xC7, 0x20, 0x3B, 0xFB, 0x72, 0xE6, 0xEB, 0xDC, 0xA0, 0xFB, 0x7D, 
	0xB4, 0x7D, 0x8B, 0xF0, 0xAC, 0x98, 0x40, 0x74, 0x0C, 0x48, 0x74, 0x13, 0xB4, 0x0E, 
	0xBB, 0x07, 0x00, 0xCD, 0x10, 0xEB, 0xEF, 0xA0, 0xFD, 0x7D, 0xEB, 0xE6, 0xA0, 0xFC, 
	0x7D, 0xEB, 0xE1, 0xCD, 0x16, 0xCD, 0x19, 0x26, 0x8B, 0x55, 0x1A, 0x52, 0xB0, 0x01, 
	0xBB, 0x00, 0x00, 0xE8, 0x3B, 0x00, 0x72, 0xE8, 0x5B, 0x8A, 0x56, 0x24, 0xBE, 0x0B, 
	0x7C, 0x8B, 0xFC, 0xC7, 0x46, 0xF0, 0x3D, 0x7D, 0xC7, 0x46, 0xF4, 0x29, 0x7D, 0x8C, 
	0xD9, 0x89, 0x4E, 0xF2, 0x89, 0x4E, 0xF6, 0xC6, 0x06, 0x96, 0x7D, 0xCB, 0xEA, 0x03, 
	0x00, 0x00, 0x20, 0x0F, 0xB6, 0xC8, 0x66, 0x8B, 0x46, 0xF8, 0x66, 0x03, 0x46, 0x1C, 
	0x66, 0x8B, 0xD0, 0x66, 0xC1, 0xEA, 0x10, 0xEB, 0x5E, 0x0F, 0xB6, 0xC8, 0x4A, 0x4A, 
	0x8A, 0x46, 0x0D, 0x32, 0xE4, 0xF7, 0xE2, 0x03, 0x46, 0xFC, 0x13, 0x56, 0xFE, 0xEB, 
	0x4A, 0x52, 0x50, 0x06, 0x53, 0x6A, 0x01, 0x6A, 0x10, 0x91, 0x8B, 0x46, 0x18, 0x96, 
	0x92, 0x33, 0xD2, 0xF7, 0xF6, 0x91, 0xF7, 0xF6, 0x42, 0x87, 0xCA, 0xF7, 0x76, 0x1A, 
	0x8A, 0xF2, 0x8A, 0xE8, 0xC0, 0xCC, 0x02, 0x0A, 0xCC, 0xB8, 0x01, 0x02, 0x80, 0x7E, 
	0x02, 0x0E, 0x75, 0x04, 0xB4, 0x42, 0x8B, 0xF4, 0x8A, 0x56, 0x24, 0xCD, 0x13, 0x61, 
	0x61, 0x72, 0x0B, 0x40, 0x75, 0x01, 0x42, 0x03, 0x5E, 0x0B, 0x49, 0x75, 0x06, 0xF8, 
	0xC3, 0x41, 0xBB, 0x00, 0x00, 0x60, 0x66, 0x6A, 0x00, 0xEB, 0xB0, 0x4E, 0x54, 0x4C, 
	0x44, 0x52, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0D, 0x0A, 0x4E, 0x54, 0x4C, 0x44, 
	0x52, 0x20, 0x69, 0x73, 0x20, 0x6D, 0x69, 0x73, 0x73, 0x69, 0x6E, 0x67, 0xFF, 0x0D, 
	0x0A, 0x44, 0x69, 0x73, 0x6B, 0x20, 0x65, 0x72, 0x72, 0x6F, 0x72, 0xFF, 0x0D, 0x0A, 
	0x50, 0x72, 0x65, 0x73, 0x73, 0x20, 0x61, 0x6E, 0x79, 0x20, 0x6B, 0x65, 0x79, 0x20, 
	0x74, 0x6F, 0x20, 0x72, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x0D, 0x0A, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0x00, 0x00, 0x00, 0xAC, 0xBF, 0xCC, 0x55, 0xAA 
}; 
 
/* 
*THIS part is created according tro SD CARD file allocation system spec 
*/ 
 
 
FATSYS_STRUCT gNandFATSYS ; 
 
 
UINT32 gNandFFBuffAddr; 
UINT8 gNandFileName[14] ; 
 
 
UINT8 gNFLASHBuf[512] ; 
 
 
extern UINT8 HD_NFlashWrite(UINT32 src_addr, UINT32 dst_addr)  ; 
extern UINT8 HD_NFlashRead(UINT32 src_addr, UINT32 dst_addr) ; //cmd17 
 
 
 
/*----------------------------------------------------------------------*/ 
/* 
 * Function:	   NandValidFileChar() 
 * DeSCRiption:   Function to see if the character is a valid FILENAME character .please to refer microsoft datasheet 
 * Calls:   	    
 * Called By:       
 * Table Accessed:  
 * Table Updated:   
 * Input:    UINT8 file_char	   
 * Output:   none       
 * Return:   true and false 	  
 * Others:  	    
 */ 
UINT8 NandValidFileChar(UINT8 file_char) 
{ 
	if (file_char < 0x20) 
	{ 
		return (SW_PARA_ERR); 
	} 
	else if ((file_char == 0x22) || 
		(file_char == 0x2A) || 
		(file_char == 0x2B) || 
		(file_char == 0x2C) || 
		(file_char == 0x2E) || 
		(file_char == 0x2F) || 
		((file_char >= 0x3A) && (file_char <= 0x3F)) || 
		((file_char >= 0x5B) && (file_char <= 0x5D)) || 
		(file_char == 0x7C) || 
		(file_char == 0xE5)) 
	{ 
		return (SW_PARA_ERR); 
	} 
	else 
	{ 
		return (SW_PARA_OK); 
	} 
} 
 
 
 
/* 
 * Function:		clust_to_addr() 
 * DeSCRiption:    Convert a cluster number into a read address  
 * Calls:   	    
 * Called By:       
 * Table Accessed:  
 * Table Updated:   
 * Input:     UINT32 clust_no      
 * Output:   none       
 * Return:  UINT32 clust_addr       
 * Others:  	    
 */ 
UINT32 NandClusterToAddr(UINT16 clust_no) 
{ 
	UINT32 clust_addr; 
 
	if (clust_no < 2) 
	{ 
		return SW_PARA_ERR; 
	} 
 
	gNandFATSYS.FirstSectorofCluster = ((clust_no - 2) * (UINT32) 
		gNandFATSYS.Bpb50.bpbSecPerClust) + 
		(UINT32) 
		gNandFATSYS.FirstDataSector; 
	clust_addr = (UINT32) 
		gNandFATSYS.FirstSectorofCluster * (UINT32) 
		gNandFATSYS.Bpb50.bpbBytesPerSec + 
		gNandFATSYS.PartitionAddr; 
 
	return (clust_addr); 
} 
/* 
 * Function:	NandInitializeFat () 
 * DeSCRiption:  initial SD card  and reads the card's partition table and  
 *  				   boot sector, storing the card information needed to  
 *  				   handle the file system 
 * Calls:   	    
 * Called By:       
 * Table Accessed:  
 * Table Updated:   
 * Input:     none 
 * Output:   none 
 * Return:   true and flase 	  
 * Others:  	    
 */ 
#define  FAT_DEBUG 
 
UINT8 NandInitializeFat(void) 
{ 
	UINT32 i; 
	UINT8 error = HW_ERR_NONE ; 
 
	gNandFATSYS.Bpb50.bpbBytesPerSec = 512 ;// Initialize sector size to 512 (all SD cards have a 512 sector size) 
 
	// *(unsigned int *) (0x4003002c) = 1 ; 
	error = HD_NFlashRead(0,(UINT32) gNFLASHBuf) ; 
	if (error != HW_ERR_NONE) 
	{ 
#ifdef _DEBUG_ON_ 
#endif 
		return error; 
	} 
	// *(unsigned int *)(0x4003002c) = 0 ; 
 
	//get the relative sector from partition table 
	//gPartRecord.prStartLBA = ((UINT32) gNFLASHBuf[0x1c6] | (UINT32) gNFLASHBuf[0x1c7] << 8) ; 
	gNandFATSYS.PartRecord.prStartLBA = ((UINT32) gNFLASHBuf[0x1c6] | 
		(UINT32) gNFLASHBuf[0x1c7] << 
		8) ; 
	if ((((gNFLASHBuf[0] == 0xEB) && (gNFLASHBuf[2] == 0x90)) || (gNFLASHBuf[0] == 0xE9)) && 
		((gNFLASHBuf[510] == 0x55) && (gNFLASHBuf[511] == 0xAA))) 
	{ 
		//gPartRecord.prStartLBA = 0 ; 
		gNandFATSYS.PartRecord.prStartLBA = 0; 
	} 
 
	gNandFATSYS.PartitionAddr = gNandFATSYS.PartRecord.prStartLBA * gNandFATSYS.Bpb50.bpbBytesPerSec;  //GET THE PARTITION BOOT SECTOR ADDRESS 
	if (gNandFATSYS.PartRecord.prStartLBA) 
	{ 
		error = HD_NFlashRead(gNandFATSYS.PartitionAddr,(UINT32) gNFLASHBuf) ; 
		if (error != HW_ERR_NONE)  //READ THE  FDC DESCRIPTOR 
			//AND THE RESULT STORE IN  gNFLASHBuf 
		{ 
#ifdef _DEBUG_ON_ 
#endif 
			return error; 
		} 
	} 
 
	gNandFATSYS.BootSector.bsJump[0] = gNFLASHBuf[0] ; /* jump inst E9xxxx or EBxx90 */ 
	gNandFATSYS.BootSector.bsJump[1] = gNFLASHBuf[1] ; 
	gNandFATSYS.BootSector.bsJump[2] = gNFLASHBuf[2] ;  
	gNandFATSYS.Bpb50.bpbBytesPerSec = ((UINT16) gNFLASHBuf[0xC] << 8) | 
		(UINT16) gNFLASHBuf[0xB]; /* bytes per sector  (in sd card max=512bytes,so get the last two bytes)*/  
	gNandFATSYS.Bpb50.bpbSecPerClust = gNFLASHBuf[0xD] ;   /* sectors per cluster */ 
	gNandFATSYS.Bpb50.bpbResSectors = ((UINT16) gNFLASHBuf[0xF] << 8) | 
		(UINT16) gNFLASHBuf[0xE];	/* number of reserved sectors */ 
	gNandFATSYS.Bpb50.bpbFATs = (UINT8) gNFLASHBuf[0x10] ;  /* number of FATs */ 
	gNandFATSYS.Bpb50.bpbRootDirEnts = ((UINT16) gNFLASHBuf[0x12] << 8) | 
		(UINT16) gNFLASHBuf[0x11]; /* number of root directory entries */	 
	gNandFATSYS.Bpb50.bpbFATsecs = ((UINT16) gNFLASHBuf[0x17] << 8) | 
		(UINT16) gNFLASHBuf[0x16];   /* number of sectors per FAT */ 
	gNandFATSYS.Bpb50.bpbSectors = ((UINT16) gNFLASHBuf[0x14] << 8) | 
		(UINT16) gNFLASHBuf[0x13];  //* total number of sectors 16bits */ 
 
	//gFatTable.Total_FAT_Cluster_Number = (gBpb50.bpbFATsecs * gBpb50.bpbBytesPerSec / 2)  ;  
 
	if (gNandFATSYS.Bpb50.bpbSectors == 0) 
	{ 
		gNandFATSYS.Bpb50.bpbHugeSectors = ((UINT32) gNFLASHBuf[0x23] << 24)  //* total number of sectors 32bits */ 
		| 
			((UINT32) gNFLASHBuf[0x22] << 16) | 
			((UINT32) gNFLASHBuf[0x21] << 8) | 
			((UINT32) gNFLASHBuf[0x20]); 
	} 
 
	gNandFATSYS.ExtBoot.exVolumeID[3] = gNFLASHBuf[0x2A] ; /* volume ID number */ 
	gNandFATSYS.ExtBoot.exVolumeID[2] = gNFLASHBuf[0x29] ; 
	gNandFATSYS.ExtBoot.exVolumeID[1] = gNFLASHBuf[0x28] ; 
	gNandFATSYS.ExtBoot.exVolumeID[0] = gNFLASHBuf[0x27] ; 
 
	for (i = 0; i < 11; i++) 
		gNandFATSYS.ExtBoot.exVolumeLabel[i] = gNFLASHBuf[(0x2b + i)]; /* volume label */ 
 
	//get the the first fat address 
	gNandFATSYS.FAT1_addr = gNandFATSYS.PartitionAddr + 
		(UINT32) 
		gNandFATSYS.Bpb50.bpbResSectors * (UINT32) 
		gNandFATSYS.Bpb50.bpbBytesPerSec;  
	//gFatTable.FAT_Table_1 = (UINT32 *) gNandFATSYS.FAT1_addr ; 
	//get the the second fat address 
	gNandFATSYS.FAT2_addr = gNandFATSYS.FAT1_addr + 
		(UINT32) 
		gNandFATSYS.Bpb50.bpbFATsecs * (UINT32) 
		gNandFATSYS.Bpb50.bpbBytesPerSec ; 
	//gFatTable.FAT_Table_2 = (UINT32 *) gNandFATSYS.FAT2_addr ; 
	//get the root directory address 
 
	gNandFATSYS.RootAddr = (UINT32) 
		gNandFATSYS.Bpb50.bpbFATs * (UINT32) 
		gNandFATSYS.Bpb50.bpbFATsecs + 
		gNandFATSYS.Bpb50.bpbResSectors; 
	gNandFATSYS.RootAddr *= (UINT32) gNandFATSYS.Bpb50.bpbBytesPerSec;  
	gNandFATSYS.RootAddr += gNandFATSYS.PartitionAddr; 
 
	//determine the count of sectors occupied by the root directory: 
	gNandFATSYS.RootDirSectors = ((gNandFATSYS.Bpb50.bpbRootDirEnts * 32) + 
		gNandFATSYS.Bpb50.bpbBytesPerSec - 
		1) / 
		gNandFATSYS.Bpb50.bpbBytesPerSec; 
 
	//The start of the data region 
	gNandFATSYS.FirstDataSector = (gNandFATSYS.Bpb50.bpbFATs * gNandFATSYS.Bpb50.bpbFATsecs) + 
		gNandFATSYS.Bpb50.bpbResSectors + 
		gNandFATSYS.RootDirSectors ;  
 
	//get the data  cluster  total 
	if (gNandFATSYS.Bpb50.bpbSectors != 0) 
	{ 
		gNandFATSYS.DataClusTot = gNandFATSYS.Bpb50.bpbSectors - 
			gNandFATSYS.FirstDataSector; 
	} 
	else 
	{ 
		gNandFATSYS.DataClusTot = gNandFATSYS.Bpb50.bpbHugeSectors - 
			gNandFATSYS.FirstDataSector; 
	} 
	gNandFATSYS.DataClusTot /= gNandFATSYS.Bpb50.bpbSecPerClust; 
 
	//get the file allocation system infomation 
	if (gNandFATSYS.DataClusTot < 4085)				// FAT12 
	{ 
		gNandFATSYS.FAT_type = PART_TYPE_FAT12 ; 
	} 
	else if (gNandFATSYS.DataClusTot < 65525)		// FAT16 
	{ 
		gNandFATSYS.FAT_type = PART_TYPE_FAT16 ; 
	} 
	else 
	{ 
		gNandFATSYS.FAT_type = PART_TYPE_UNKNOWN	; 
		return SW_PARA_ERR; 
	} 
 
	gNandFATSYS.DIR_adrr = gNandFATSYS.RootAddr;		// Set current directory to root address 
 
	return SW_PARA_OK; 
} 
 
/* 
 * Function:	   NandNextCluster() 
 * DeSCRiption:    Find the cluster that the current cluster is pointing to 
 * Calls:   	    
 * Called By:       
 * Table Accessed:  
 * Table Updated:   
 * Input:   	 UINT32 current_cluster,  UINT8 mode   
 * Output:  	 none  
 * Return:  	 true and false   
 * Others:  		 
 */ 
UINT16 NandNextCluster(UINT32 current_cluster) 
{ 
	UINT16 calc_sec, calc_offset, next_clust; 
	UINT32 addr_temp; 
	UINT8 error = HW_ERR_NONE ; 
 
	if (current_cluster <= 1)   // If cluster is 0 or 1, its the wrong cluster 
	{ 
		return SW_PARA_ERR; 
	} 
 
	if (gNandFATSYS.FAT_type == PART_TYPE_FAT16)   // if FAT16 
	{ 
		// FAT16 table address calculations 
		calc_sec = current_cluster / 
			(gNandFATSYS.Bpb50.bpbBytesPerSec / 2) + 
			gNandFATSYS.Bpb50.bpbResSectors; 
		calc_offset = 2 * (current_cluster % (gNandFATSYS.Bpb50.bpbBytesPerSec / 2)); 
 
		addr_temp = gNandFATSYS.PartitionAddr + (calc_sec * 0x200); 
		if (addr_temp != gNandFFBuffAddr) 
		{ 
			error = HD_NFlashRead(addr_temp,(UINT32) gNFLASHBuf) ; 
			if (error != HW_ERR_NONE) 
			{ 
				return error; 
			} 
		}  
		next_clust = (((UINT16) gNFLASHBuf[calc_offset + 1]) << 8) | 
			gNFLASHBuf[calc_offset]; 
	} 
	else	// not FAT12 or FAT16, return 0 
	{ 
		return SW_PARA_ERR; 
	} 
 
	return (next_clust); 
} 
 
/* 
 * Function:	   NandQuickFormat 
 * DeSCRiption:   Quickformat of a card (erase cluster table and root directory) 
 * Calls:   	    
 * Called By:       
 * Table Accessed:  
 * Table Updated:   
 * Input:   	    
 * Output:  	    
 * Return:  	    
 * Others:  	    
 */ 
UINT8 NandQuickFormat(void) 
{ 
	UINT16 c ; 
	UINT32 temp_addr; 
	UINT32 temp_addr1 ; 
	UINT32 temp_addr2 ; 
	UINT32 temp_addr3 ; 
	UINT8 error = HW_ERR_NONE; 
 
	for (c = 0; 
		c < gNandFATSYS.Bpb50.bpbBytesPerSec; 
		c++)   // initialize  gNFLASHBuf to  all zero 
		gNFLASHBuf[c] = 0; 
 
	temp_addr = gNandFATSYS.FAT1_addr + 0x200;   
	temp_addr3 = gNandFATSYS.RootAddr + (0x200 * gNandFATSYS.RootDirSectors); 
	while (temp_addr < temp_addr3) 
	{ 
		error = HD_NFlashWrite((UINT32) gNFLASHBuf,temp_addr) ; 
		if (error != HW_ERR_NONE) 
		{ 
			return error; 
		} 
 
		temp_addr += 0x200; 
	}	 
	gNFLASHBuf[0] = 0xF8; 
	gNFLASHBuf[1] = 0xFF; 
	gNFLASHBuf[2] = 0xFF; 
	if (gNandFATSYS.FAT_type == PART_TYPE_FAT16) 
	{ 
		gNFLASHBuf[3] = 0xFF; 
	} 
 
	temp_addr1 = gNandFATSYS.FAT1_addr ; 
	temp_addr2 = gNandFATSYS.FAT2_addr ; 
 
	error = HD_NFlashWrite((UINT32) gNFLASHBuf,temp_addr1) ; 
	if (error != HW_ERR_NONE) 
	{ 
		return error ; 
	} 
	error = HD_NFlashWrite((UINT32) gNFLASHBuf,temp_addr2) ; 
	if (error != HW_ERR_NONE) 
	{ 
		return error ; 
	} 
 
	return HW_ERR_NONE; 
} 
 
/* 
 * Function:	   NandFatTableRecord 
 * DeSCRiption:   this function is used to write the value(NextNum) to the position(CurNum), 
						to update Fat table 
 * Calls:   	    
 * Called By:       
 * Table Accessed:  
 * Table Updated:   
 * Input:   	    
 * Output:  	    
 * Return:  	    
 * Others:  	    
 */ 
UINT8 NandFatTableRecord(UINT16 CurNum, UINT16 NextNum) 
{ 
	UINT32 tmp_addr = 0 ; 
	UINT32 tmp_addr1 = 0 ; 
	UINT32 tmp_addr2 = 0 ; 
	UINT16 offset = 0 ; 
	UINT8 error = HW_ERR_NONE; 
 
	tmp_addr = (CurNum * 2) / 512 ; 
	offset = (CurNum * 2) % 512  ; 
 
	tmp_addr1 = gNandFATSYS.FAT1_addr + tmp_addr * 256 ; 
	tmp_addr2 = gNandFATSYS.FAT2_addr + tmp_addr * 256 ; 
 
	error = HD_NFlashRead(tmp_addr1,(UINT32) (gNFLASHBuf)) ; 
	if (error != HW_ERR_NONE) 
	{ 
		return error ; 
	} 
	gNFLASHBuf[offset + 1] = (UINT8) ((NextNum & 0xff00) >> 8); 
	gNFLASHBuf[offset] = (UINT8) (NextNum & 0x00ff) ;	 
	error = HD_NFlashWrite((UINT32) (gNFLASHBuf),tmp_addr1) ; 
	if (error != HW_ERR_NONE) 
	{ 
		return error ; 
	} 
	error = HD_NFlashWrite((UINT32) (gNFLASHBuf),tmp_addr2) ; 
	if (error != HW_ERR_NONE) 
	{ 
		return error ; 
	} 
 
	return TRUE ; 
}  
 
/* 
 * Function:	   NandFileNameConversion() 
 * DeSCRiption:    this function is used to convert a constant string file name into the proper format 
 * Calls:   	    
 * Called By:       
 * Table Accessed:  
 * Table Updated:   
 * Input:   	   UINT8 *current_file 
 * Output:  	  none  
 * Return:  	  true and fasle  
 * Others:  	    
 */ 
UINT8 * NandFileNameConversion(UINT8 *current_file) 
{ 
	UINT8 n, c; 
	UINT8 filename[14] ; 
 
	c = 0; 
 
	for (n = 0; n < 14; n++) 
	{ 
		if (NandValidFileChar(current_file[n]) == TRUE) 
			// If the character is valid, save in uppeRCAse to file name buffer 
		{ 
			gNandFileName[c++] = toupper(current_file[n]); 
		} 
		else if (current_file[n] == '.') 
			// If it is a period, back fill buffer with [spaces], till 8 characters deep 
		{ 
			while (c < 8) 
				gNandFileName[c++] = 0x20; 
		} 
		else if (current_file[n] == 0) 
		{ 
			// If it is NULL, back fill buffer with [spaces], till 11 characters deep 
			while (c < 11) 
				gNandFileName[c++] = 0x20; 
			break; 
		} 
		else 
		{ 
			return FALSE; 
		} 
		if (c >= 11) 
		{ 
			break; 
		} 
	} 
	filename[c] = 0; 
	// Return the pointer of the filename 
	return (gNandFileName); 
} 
 
UINT32 NandGetFileEntry(INT8 *filename) 
{ 
	UINT8 n; 
	UINT16 s, calc_temp; 
	UINT32 addr_temp; 
	UINT8 *sp, *qp; 
	UINT8 error = HW_ERR_NONE ; 
 
	// Get the filename into a form we can use to compare 
	qp = NandFileNameConversion((UINT8 *) filename); 
	if (qp == FALSE)  //name error 
	{ 
		return (FALSE); 
	} 
 
	for (s = 0; s < gNandFATSYS.Bpb50.bpbBytesPerSec; s++) 
	{ 
		// Scan through directory entries to find file 
		addr_temp = gNandFATSYS.DIR_adrr + (0x200 * s); 
		error = HD_NFlashRead(addr_temp,(UINT32) gNFLASHBuf) ; 
		if (error != HW_ERR_NONE) 
		{ 
			return error; 
		} 
 
		for (n = 0; n < 16; n++) 
		{ 
			calc_temp = (UINT16) n * 0x20; 
			qp = &gNandFileName[0]; 
			sp = &gNFLASHBuf[calc_temp]; 
			if (*sp == 0) 
			{ 
				return (FALSE); 
			} 
			if (strncmp((INT8 *)qp,(INT8 *)sp,11) == 0)		// Does this entry == Filename 
			{ 
				return (calc_temp + addr_temp); 
			} 
		} 
	} 
	return(FALSE); 
} 
 
/* 
 * Function:   FatParaCaculate     
 * DeSCRiption:    this function is used to calculate the format parameter according to  the card capacivity 
 * Calls:   	  
 * Called By:       
 * Table Accessed:  
 * Table Updated:   
 * Input:      none   
 * Output:    gFsType   ,gNFLASHBuf ,gBpb50 
 * Return:    none   
 * Others:  	  
 */ 
#if 1 
static void FatParaCaculate(void) 
{ 
	UINT16 nbHeads ; 
	UINT16 SectorperTrack ; 
	UINT8 SectorperCluster ; 
	UINT32 HiddenSectors ; 
	UINT32 totalsize ; 
	UINT16 fatsec; 
	UINT16 i ; 
 
	gNandFATSYS.FAT_type = PART_TYPE_FAT16 ; 
 
	nbHeads = 8 ; 
	SectorperTrack = 2 ; 
	SectorperCluster = 2 ; 
	HiddenSectors = 39 ; 
	totalsize = 125440 ; 
	fatsec = 244 ; 
 
	//junp command 
	gNFLASHBuf[0] = 0xEB ; 
	gNFLASHBuf[1] = 0x00 ; 
	gNFLASHBuf[2] = 0x90 ; 
 
	//system indentifier 
	gNFLASHBuf[3] = 'V'  ; //  
	gNFLASHBuf[4] = 'I'  ; //  
	gNFLASHBuf[5] = 'A' ; //  
	gNFLASHBuf[6] = 'T' ; // 
	gNFLASHBuf[7] = 'E' ; //  
	gNFLASHBuf[8] = 'C' ; // 
	gNFLASHBuf[9] = 'T' ; // 
	gNFLASHBuf[10] = 'H' ;// 
 
	//sector size(bytes per sec ) 
	gNFLASHBuf[11] = (UINT8) (512 & 0xff) ; 
	gNFLASHBuf[12] = (UINT8) ((512 & 0xff00) >> 8); 
 
	//sector per cluster 
	gNFLASHBuf[13] = SectorperCluster ; 
 
	//reserved sector count  (for fat16 and fat12 this is 1 ) 
	gNFLASHBuf[14] = (UINT8) (1 & 0x00ff) ; 
	gNFLASHBuf[15] = 0 ; 
 
	//number of fats 
	gNFLASHBuf[16] = 2 ; 
 
	//number of root directory entries  
	gNFLASHBuf[17] = (UINT8) (512 & 0xff) ; 
	gNFLASHBuf[18] = (UINT8) ((512 & 0xff00) >> 8); 
 
	//total sectors (16bits) 
	gNFLASHBuf[19] = 0 ; 
	gNFLASHBuf[20] = 0 ; 
 
	//medium indentifier 
	gNFLASHBuf[21] = 0xf8 ; 
 
	//sectors per fat 
	gNFLASHBuf[22] = (UINT8) (fatsec & 0xff) ; 
	gNFLASHBuf[23] = (UINT8) ((fatsec & 0xff00) >> 8); 
 
	//sectors per track 
	gNFLASHBuf[24] = (UINT8) (SectorperTrack & 0xff) ; 
	gNFLASHBuf[25] = (UINT8) ((SectorperTrack & 0xff00) >> 8); 
 
	//number of slide(head) 
	gNFLASHBuf[26] = (UINT8) (nbHeads & 0xff) ; 
	gNFLASHBuf[27] = (UINT8) ((nbHeads & 0xff00) >> 8); 
 
	//number of hidden sectors    
	gNFLASHBuf[28] = (UINT8) (HiddenSectors & 0x000000ff) ; 
	gNFLASHBuf[29] = (UINT8) ((HiddenSectors & 0x0000ff00) >> 8); 
	gNFLASHBuf[30] = (UINT8) ((HiddenSectors & 0x00ff0000) >> 16); 
	gNFLASHBuf[31] = (UINT8) ((HiddenSectors & 0xff000000) >> 24); 
 
	//total sectors (32bits)	 
	gNFLASHBuf[32] = (UINT8) (totalsize & 0x000000ff) ; 
	gNFLASHBuf[33] = (UINT8) ((totalsize & 0x0000ff00) >> 8) ; 
	gNFLASHBuf[34] = (UINT8) ((totalsize & 0x00ff0000) >> 16) ; 
	gNFLASHBuf[35] = (UINT8) ((totalsize & 0xff000000) >> 24) ; 
 
	//physical disk number   
	gNFLASHBuf[36] = 0x80; 
 
	//reserved 
	gNFLASHBuf[37] = 0x00; 
 
	//extend boot record signature 
	gNFLASHBuf[38] = 0x29 ;  
 
	//volume ID number 
	gNFLASHBuf[39] = 0x01 ; 
	gNFLASHBuf[40] = 0x23 ; 
	gNFLASHBuf[41] = 0x45 ; 
	gNFLASHBuf[42] = 0x67 ; 
 
	//volume label 
	for (i = 0 ; i < 11; i++) 
	{ 
		gNFLASHBuf[43 + i] = (0x41 + i); 
	} //a~a+10)    
 
	//file system type   
	gNFLASHBuf[54] = 'F' ; 
	gNFLASHBuf[55] = 'A' ; 
	gNFLASHBuf[56] = 'T' ; 
	gNFLASHBuf[57] = '1' ; 
	gNFLASHBuf[58] = '6' ; 
 
	gNFLASHBuf[59] = 0 ; 
	gNFLASHBuf[60] = 0 ; 
	gNFLASHBuf[61] = 0 ; 
 
	//not restricted 
	for (i = 0 ; i < 448; i++) 
	{ 
		gNFLASHBuf[62 + i] = 0; 
	} 
	//signature word 
	gNFLASHBuf[510] = 0x55 ; 
	gNFLASHBuf[511] = 0xaa ; 
 
	gNandFATSYS.Bpb50.bpbBytesPerSec = 512 ;  
	gNandFATSYS.Bpb50.bpbResSectors = 1 ; 
	gNandFATSYS.Bpb50.bpbFATsecs = fatsec ; 
	gNandFATSYS.Bpb50.bpbFATs = 2 ; 
	gNandFATSYS.Bpb50.bpbRootDirEnts = 512 ; 
 
	return ; 
}  
#endif 
/* 
 * Function:   FAT_Format(void)   
 * DeSCRiption: format the sd card completely    
 * Calls:   	  
 * Called By:       
 * Table Accessed:  
 * Table Updated:   
 * Input:      none     
 * Output:    none      
 * Return:    true and false    
 * Others:  	  
 */ 
/***********************************************************************   
*-Sector size is 512 bytes  
*-2 fats management  
*-512 entries in the root directory  
*---------------------------------------------------------------------------- 
*REQUIREMENTS : need to call initial 
************************************************************************/ 
#if 1 
UINT8 NandFATFormat(void) 
{ 
	UINT32 c, i; 
	UINT32 temp_addr1 ; 
	UINT32 temp_addr2 ; 
	UINT8 error = HW_ERR_NONE; 
 
#if 0 
FatParaCaculate() ; 
error = HD_NFlashWrite((UINT32) gNFLASHBuf, 0) ; 
//error =NFTL_Write(0,  gNFLASHBuf) ; 
#endif 
#if 1 
	error = HD_NFlashWrite((UINT32) BPBTaBle,0) ; 
	gNandFATSYS.Bpb50.bpbBytesPerSec = 512 ;  
	gNandFATSYS.Bpb50.bpbResSectors = 1 ; 
	gNandFATSYS.Bpb50.bpbFATsecs = 251 ; //255 
	gNandFATSYS.Bpb50.bpbFATs = 2 ; 
	gNandFATSYS.Bpb50.bpbRootDirEnts = 512 ; 
#endif 
	if (error != HW_ERR_NONE) 
	{ 
		return error ; 
	} 
 
	gNandFATSYS.PartitionAddr = 0; 
	//get the the first fat address 
	gNandFATSYS.FAT1_addr = gNandFATSYS.PartitionAddr + 
		(UINT32) 
		gNandFATSYS.Bpb50.bpbResSectors * (UINT32) 
		gNandFATSYS.Bpb50.bpbBytesPerSec;  
 
	//get the the second fat address 
	gNandFATSYS.FAT2_addr = gNandFATSYS.FAT1_addr + 
		(UINT32) 
		gNandFATSYS.Bpb50.bpbFATsecs * (UINT32) 
		gNandFATSYS.Bpb50.bpbBytesPerSec ; 
 
	//get the root directory address 
	gNandFATSYS.RootAddr = (UINT32) 
		gNandFATSYS.Bpb50.bpbFATs * (UINT32) 
		gNandFATSYS.Bpb50.bpbFATsecs + 
		gNandFATSYS.Bpb50.bpbResSectors; 
	gNandFATSYS.RootAddr *= (UINT32) gNandFATSYS.Bpb50.bpbBytesPerSec;  
	gNandFATSYS.RootAddr += gNandFATSYS.PartitionAddr; 
 
	//determine the count of sectors occupied by the root directory: 
	gNandFATSYS.RootDirSectors = ((gNandFATSYS.Bpb50.bpbRootDirEnts * 32) + 
		gNandFATSYS.Bpb50.bpbBytesPerSec - 
		1) / 
		gNandFATSYS.Bpb50.bpbBytesPerSec; 
 
	for (c = 3; c < 512; c++)   // initialize  gNFLASHBuf to  all zero 
	{ 
		gNFLASHBuf[c] = 0; 
	} 
 
	gNFLASHBuf[0] = 0xF8; 
	gNFLASHBuf[1] = 0xFF; 
	gNFLASHBuf[2] = 0xFF; 
	if (gNandFATSYS.FAT_type == PART_TYPE_FAT16) 
	{ 
		gNFLASHBuf[3] = 0xFF; 
	} 
 
	temp_addr1 = gNandFATSYS.FAT1_addr ; 
	temp_addr2 = gNandFATSYS.FAT2_addr ; 
 
 
	error = HD_NFlashWrite((UINT32) gNFLASHBuf,temp_addr1) ; 
	if (error != HW_ERR_NONE) 
	{ 
		return error ; 
	} 
 
	error = HD_NFlashWrite((UINT32) gNFLASHBuf,temp_addr2) ; 
	if (error != HW_ERR_NONE) 
	{ 
		return error ; 
	} 
 
	gNFLASHBuf[0] = 0x0; 
	gNFLASHBuf[1] = 0x0; 
	gNFLASHBuf[2] = 0x0; 
	gNFLASHBuf[3] = 0x0; 
 
	for (i = 1 ; i < gNandFATSYS.Bpb50.bpbFATsecs ; i++) 
	{ 
		temp_addr1 = gNandFATSYS.FAT1_addr + i * 0x200 ; 
		temp_addr2 = gNandFATSYS.FAT2_addr + i * 0x200 ; 
		error = HD_NFlashWrite((UINT32) gNFLASHBuf,temp_addr1) ; 
		if (error != HW_ERR_NONE) 
		{ 
			return error ; 
		} 
		error = HD_NFlashWrite((UINT32) gNFLASHBuf,temp_addr2) ; 
		if (error != HW_ERR_NONE) 
		{ 
			return error ; 
		} 
	} 
 
	temp_addr1 = gNandFATSYS.RootAddr ; 
	for (i = 0 ; i < gNandFATSYS.RootDirSectors ; i++) 
	{ 
		error = HD_NFlashWrite((UINT32) gNFLASHBuf,temp_addr1) ; 
		if (error != HW_ERR_NONE) 
		{ 
			return error ; 
		} 
		temp_addr1 += 0x200 ; 
	} 
 
	return (TRUE); 
}  
#endif