⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fs.c

📁 使用ISP1362芯片的USB_OTG参考设计源代码比较新的版本
💻 C
📖 第 1 页 / 共 5 页
字号:

	if ( !(flags & FLAG_REMOVE_SCAN_ONLY) && !(!depth && (flags & FLAG_LEAVE_CURR_DIR)) )
	{
		*((unsigned char *)dp)	= 0xE5;
		write_back_directory_entry();

#if BIG_ENDIAN
		clear_FAT_chain( swap16( dp->cluster ) );
#else
		clear_FAT_chain( dp->cluster );
#endif
	}

	return ( no_error );
}









//
//	FAT operation
//
static unsigned short count_free_cluster( void )
{
	unsigned short	count	= 0;
	unsigned short	i;
	
	volume_param	*vpp;

	vpp		= &g_volume_parameter;

	for ( i = 0; i < vpp->number_of_clasters; i++ )
		if ( !read_FAT( i + 2 ) )
			count++;
	
	return ( count );
}


static unsigned short find_free_cluster( unsigned short start_cluster )
{
	unsigned short	i;
	
	volume_param	*vpp;

	vpp		= &g_volume_parameter;

	for ( i = start_cluster; i < (vpp->number_of_clasters + 2); i++ )
		if ( !read_FAT( i ) )
			return ( i );
	
	return ( 0 );
}


static unsigned char clear_FAT_chain( unsigned short cluster )
{
	unsigned short	count;
	unsigned short	i;
	volume_param	*vpp;

	vpp		= &g_volume_parameter;

	count	= 0;
	while ( valid_cluster( cluster, vpp ) )
	{
		cluster		= write_FAT( cluster, 0x0000 );

		if ( count++ == 0xFFFF )
			break;
	}

	flush_FAT_cache( vpp );
	
	if ( (i == 0xFFFF) || (cluster == 0x0000) )
		return ( error );

	return ( no_error );
}


static unsigned char valid_cluster( unsigned short cluster, volume_param *vpp )
{
	if ( (cluster - 2) < vpp->number_of_clasters )
		return ( True );
	
	return ( False );
}


static unsigned short read_FAT( unsigned short current_cluster )
{
	volume_param			*vpp;

	vpp				= &g_volume_parameter;

	if ( vpp->file_system == FILE_SYSTEM_FAT16 )
		return ( access_FAT16( FAT_READ, current_cluster, NULL ) );
		
	else if ( vpp->file_system == FILE_SYSTEM_FAT12 )
		return ( access_FAT12( FAT_READ, current_cluster, NULL ) );
	
	return ( 0 );
}


static unsigned short write_FAT( unsigned short cluster, unsigned short value )
{
	volume_param			*vpp;

	vpp				= &g_volume_parameter;

	if ( vpp->file_system == FILE_SYSTEM_FAT16 )
		return ( access_FAT16( FAT_WRITE, cluster, value ) );
		
	else if ( vpp->file_system == FILE_SYSTEM_FAT12 )
		return ( access_FAT12( FAT_WRITE, cluster, value ) );

	return ( 0 );
}


static unsigned short flush_FAT_cache( volume_param *vpp )
{
	if ( vpp->file_system == FILE_SYSTEM_FAT16 )
		return ( flush_FAT16_cache( vpp ) );
		
	else if ( vpp->file_system == FILE_SYSTEM_FAT12 )
		return ( flush_FAT12_cache( vpp ) );

	return ( 0 );
}


static unsigned short flush_FAT16_cache( volume_param *vpp )
{
	if ( vpp->FAT_cached_sector == FAT_CACHE_NOT_VALID )
		return ( 0 );
		
	storage_write_sector( (unsigned char *)(vpp->FAT_cache), vpp->start_sector_FAT1 + vpp->FAT_cached_sector, 1 );
	storage_write_sector( (unsigned char *)(vpp->FAT_cache), vpp->start_sector_FAT2 + vpp->FAT_cached_sector, 1 );
	
	vpp->FAT_cached_sector		= FAT_CACHE_NOT_VALID;
	vpp->FAT_cache_dirty		= False;

	return ( 0 );
}


static unsigned short flush_FAT12_cache( volume_param *vpp )
{
	if ( !(vpp->FAT_cache_dirty) )
		return ( 0 );

	storage_write_sector( (unsigned char *)(vpp->FAT_cache), vpp->start_sector_FAT1, vpp->number_of_FAT_sectors );
	storage_write_sector( (unsigned char *)(vpp->FAT_cache), vpp->start_sector_FAT2, vpp->number_of_FAT_sectors );
	
	vpp->FAT_cache_dirty		= False;

	return ( 0 );
}


static unsigned short access_FAT16( unsigned char mode, unsigned short cluster, unsigned short value )
{
	unsigned long			target_sector;
	unsigned long			entry_offset;
	unsigned short			previous_value;
	volume_param			*vpp;

	vpp				= &g_volume_parameter;

	target_sector	= cluster / (vpp->bytes_per_sector >> 1);
	entry_offset	= cluster % (vpp->bytes_per_sector >> 1);
	
	if ( vpp->FAT_cached_sector != target_sector )
	{
		if ( vpp->FAT_cache_dirty )
			flush_FAT_cache( vpp );

		storage_read_sector( (unsigned char *)(vpp->FAT_cache), vpp->start_sector_FAT1 + target_sector, 1 );
		vpp->FAT_cached_sector		= target_sector;
	}
	
	if ( mode == FAT_WRITE )
	{
#if BIG_ENDIAN

		previous_value		= *(vpp->FAT_cache + entry_offset);
		*(vpp->FAT_cache + entry_offset)	= swap16( value );
		vpp->FAT_cache_dirty				= True;
		return ( swap16( previous_value ) );
		
#else

		previous_value		= *(vpp->FAT_cache + entry_offset);
		*(vpp->FAT_cache + entry_offset)	= value;
		vpp->FAT_cache_dirty				= True;
		return ( previous_value );
		
#endif
	}		
	
	//else if ( mode == FAT_READ  )
#if BIG_ENDIAN
		return ( swap16( *(vpp->FAT_cache + entry_offset) ) );
#else
		return ( *(vpp->FAT_cache + entry_offset) );
#endif
}


static unsigned short access_FAT12( unsigned char mode, unsigned short cluster, unsigned short value )
{
	unsigned long			*target;
	unsigned long			offset;
	unsigned char			odd;
	unsigned long			tmp;
	unsigned short			target_cluster;
	volume_param			*vpp;

	vpp				 = &g_volume_parameter;

	odd				 = cluster & 0x1;
	cluster			&= 0xFFF;
	offset			 = (cluster >> 1) * 3;

	target	= (unsigned long *)(((unsigned char *)vpp->FAT_cache) + offset);

#if BIG_ENDIAN
	tmp		= swap32( *target );
#else
	tmp		= *target;
#endif
	
	target_cluster	 = odd ? ((tmp >> 12) & 0xFFF) : (tmp & 0xFFF);
	
	target_cluster	|= (target_cluster & 0x0800) ? 0xF000 : 0x0000;

	if ( mode == FAT_WRITE )
	{
		value			&= 0xFFF;
		
		if ( odd )
		{
			tmp		&= 0xFF000FFF;
			tmp		|= (unsigned long)value << 12;
		}
		else
		{
			tmp		&= 0xFFFFF000;
			tmp		|= (unsigned long)value;
		}

#if BIG_ENDIAN
		*target					= swap32( tmp );
#else
		*target					= tmp;
#endif

		vpp->FAT_cache_dirty	= True;
	}
	
	return ( target_cluster );
}


//
//	Sector operation
//
static unsigned long cluster_to_sector( unsigned short cluster )
{
	volume_param			*vpp;

	vpp				= &g_volume_parameter;

	if ( cluster == ROOT_DIRECTORY_CLUSTER )
		return ( vpp->start_sector_root_directory );
	else if ( valid_cluster( cluster, vpp ) )
		return ( vpp->start_sector_claster_region + ((((unsigned long)cluster) - 2) * (unsigned long)(vpp->sector_per_cluster)) );
	else
		return ( 0xFFFFFFFF );
}

//
//	Cluster operation
//
static directory_entry *find_entry( char *path )
{
	unsigned short dummy_c;
	unsigned short dummy_i;
	
	return ( find_file_entry( path, &dummy_c, &dummy_i ) );
}


static directory_entry *find_file_entry( char *path, unsigned short *dir_cluster_ptr, unsigned short *index_ptr )
{
	char				full_path[ MAX_PATH_STRING_LENGTH ];
	char				*fpp;
	char				file_entry_string[ 12 ];
	directory_entry		*dp;
	volume_param		*vpp;

	vpp					= &g_volume_parameter;

	dp					= &g_root_dumy;
	
#if BIG_ENDIAN
	*dir_cluster_ptr	= swap16( dp->cluster );
#else
	*dir_cluster_ptr	= dp->cluster;
#endif

	fpp		= full_path;
	
	make_full_path( fpp, path, vpp->current_dir );

	while ( 1 )
	{
		if ( *fpp == '/' )
			fpp++;

		if ( !(*fpp) )
			break;
			
		format_file_name_directory_entry( file_entry_string, fpp );	//	This formats the name first directory name in the path

#if BIG_ENDIAN

		*dir_cluster_ptr	= swap16( dp->cluster );

		if ( NULL == (dp	= find_directory_index( index_ptr, swap16( dp->cluster ), file_entry_string )) )
			break;
#else
		*dir_cluster_ptr	= dp->cluster;

		if ( NULL == (dp	= find_directory_index( index_ptr, dp->cluster, file_entry_string )) )
			break;
#endif


		fpp			+= first_char_position( fpp, '/' );
	}
	
	return ( dp );
}


static directory_entry *find_directory_index( unsigned short *found_index, unsigned short base_cluster, char *name )
{
	directory_entry		*dp;
	
	*found_index	= 0;

	while ( 1 )
	{
		dp		= get_directory_entry( base_cluster, *found_index, NO_MAKE_NEW_DIR_ENT );
		
		if ( NULL == dp )
			return ( NULL );

		if ( *((unsigned char *)dp) == 0 )
			return ( NULL );
			
		if ( str_match( (char *)dp, name, 11 ) )
			return ( dp );
		
		(*found_index)++;
	}
}


static directory_entry *find_free_directory_entry( unsigned short *found_index, unsigned short base_cluster, char *name )
{
	directory_entry		*dp;
	
	*found_index	= 0;
	
	while ( 1 )
	{
		dp		= get_directory_entry( base_cluster, *found_index, OK_MAKE_NEW_DIR_ENT );
		
		if ( NULL == dp )
			return ( NULL );

		if ( *((unsigned char *)dp) == 0 )
			return ( dp );
			
		if ( str_match( (char *)dp, name, 11 ) )
			return ( NULL );
		
		if ( *((unsigned char *)dp) == 0xE5 )
			return ( dp );
			
		(*found_index)++;
	}
}


static directory_entry *get_directory_entry( unsigned short base_cluster, unsigned short index, unsigned char new_entry_ok )
{
	unsigned short			cluster_offset;
	unsigned short			entry_offset;
	unsigned short			target_cluster;
	unsigned short			new_cluster;
	unsigned long			read_start_sector		= 0;
	unsigned char			new_sector_allocated	= False;
	unsigned short			i;
	volume_param			*vpp;

	vpp					= &g_volume_parameter;
	
	entry_offset		= index % (vpp->bytes_per_cluster / sizeof(directory_entry));
	cluster_offset		= index / (vpp->bytes_per_cluster / sizeof(directory_entry));

	if ( base_cluster == ROOT_DIRECTORY_CLUSTER )
	{
		read_start_sector	= vpp->start_sector_root_directory + vpp->sector_per_cluster * cluster_offset;
	}
	else
	{
		target_cluster	= base_cluster;
		
		for ( i = 0; i < cluster_offset; i++ )
		{
			new_cluster		= read_FAT( target_cluster );
			
			if ( new_cluster == 0xFFFF )
			{
				if ( new_entry_ok )
				{
					new_cluster		= find_free_cluster( target_cluster );
					
					if ( !valid_cluster( new_cluster, vpp ) )
						return ( NULL );
						
					write_FAT( target_cluster, new_cluster );
					write_FAT( new_cluster, 0xFFFF );
					new_sector_allocated	= True;
				}
				else
				{
					return ( NULL );
				}
			}
			
			target_cluster	= new_cluster;
		}
	
		read_start_sector	= cluster_to_sector( target_cluster );
	}
	
	if ( read_start_sector != vpp->dir_cached_sector )
	{
		if ( new_sector_allocated )
			for ( i = 0; i < vpp->bytes_per_cluster; i++ )
				*(vpp->dir_cache + i)	= 0;
		else
			storage_read_sector( vpp->dir_cache, read_start_sector, vpp

⌨️ 快捷键说明

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