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

📄 storage.c

📁 使用ISP1362芯片的USB_OTG参考设计源代码比较新的版本
💻 C
📖 第 1 页 / 共 3 页
字号:
	g_storage_device_ptr			= NULL;
	
	return ( no_error );
}



/*
==============================================================================
==============================================================================
====	Private functions for storage drive
====		Storage device maintenance
==============================================================================
==============================================================================
*/


static void strg_maintenance_routine_entry( void )
{
	static unsigned short	is_in_execution		= False;

	if ( is_in_execution )
		return;
	else
		is_in_execution		= True;


	if ( !g_storage_device_ptr )
		return;
	
	strg_maintenance_routine( g_storage_device_ptr );
	
	if ( is_in_execution )
		is_in_execution		= False;
}


static void strg_maintenance_routine( device_instance *dvi_ptr )
{
	static unsigned long			poll_timing		= 0;
	static unsigned char			wait_stable;
	static unsigned long			wait_stable_count;
	unsigned char					data[ 36 ];
	unsigned char					err;
	unsigned char					check;
	char							k;
	storage_instance				*si_ptr;
	
	if ( NULL == dvi_ptr )
		return;
	
	si_ptr		= (storage_instance *)(dvi_ptr->class_instance_ptr);

	switch ( si_ptr->state )
	{
		case IDLE :
			break;
			
		case WAIT_FOR_CARD_START :
		
			poll_timing		= 0;
			si_ptr->state	= WAIT_FOR_CARD;
			//break;
		
		case WAIT_FOR_CARD :
		
			if ( poll_timing < gp_sof_counter )
			{
				poll_timing		= gp_sof_counter + STORAGE_CARD_WAIT_POLLING_INTERVAL;

				for ( (si_ptr->target_LUN) = 0; (si_ptr->target_LUN) <= (si_ptr->max_LUN) ; )
				{
					check 	= check_the_card_exist();
					
					if ( (check == 0) || (check == 6) )
					{
						wait_stable			= 0xFF;
						wait_stable_count	= 0;
						si_ptr->state		= WAIT_STABILIZED;
						return;		//	return and wait for retry
					}
					(si_ptr->target_LUN)++;
				}
			}
			else if ( (poll_timing - gp_sof_counter) > 5000 )
			{
				si_ptr->state		= WAIT_FOR_CARD_START;
			}

			break;

		case WAIT_STABILIZED :
		
			if ( poll_timing < gp_sof_counter )
			{
				poll_timing		= gp_sof_counter + 10;
				
				if (wait_stable_count++ > 500)
				{
//					si_ptr->state	= IDLE;
					si_ptr->state	= WAIT_FOR_CARD_START;
					return;
				}
				
				wait_stable		= (wait_stable << 1) | ((strg_command( TEST_UNIT_READY, NULL, 0, 0 ) == 0) ? 0x0 : 0x1);
				
				if ( !wait_stable )
				{
					si_ptr->state	= MOUNT_PROCEED;
					return;		//	return and wait for retry
				}
			}

			break;
			
		case MOUNT_PROCEED :
		
			mprintf( WHITE, CONTINUE, "\r\n  storage class : Card ready.    " );
			
			strg_command( REQUEST_SENSE, data, 0, 18 );
			
			if ( data[ 2 ] && (data[ 2 ] != 0x5) )
			{
				mprintf( WHITE,    CONTINUE, "ATTENTION!!!!!!!!!   0x%X  %lu\r\n", data[ 2 ], gp_drive_parameter.block_length );
				mprintf( LIGHTRED, CONTINUE, "Non recoverable error in this version. Please re-attach USB device.\r\n" );
				
				si_ptr->state	= IDLE;
				return;
			}

			strg_command( INQUIRY,                      data, 0, 36 );
			strg_command( PREVENT_ALLOW_MEDIUM_REMOVAL, NULL, 0,  1 );
			strg_command( REQUEST_SENSE,                data, 0, 18 );		//	##	version1.2c
			strg_command( READ_CAPACITY,                data, 0,  0 );
			
			gp_drive_parameter.last_LBA			= long_swap( *(((unsigned long *)data) + 0) );
			gp_drive_parameter.block_length		= long_swap( *(((unsigned long *)data) + 1) );
			
			mprintf( LIGHTGRAY, CONTINUE, "size = %lu bytes ", gp_drive_parameter.last_LBA * gp_drive_parameter.block_length );
			mprintf( LIGHTGRAY, CONTINUE, "(%ld MB)\r\n", (gp_drive_parameter.last_LBA * gp_drive_parameter.block_length) >> 20 );
			
			if ( NULL == (si_ptr->volume_instance[ 0 ]		= fs_volume_open()) )
			{
				mprintf( WHITE, CONTINUE, "  storage class : Volume mount failed\r\n" );
				
				mprintf( WHITE, CONTINUE, "            Format? (y|n)  " );
				

				while ( 0 == (k	= ui_key_wait() & 0xFF) )
				{
					mprintf( WHITE, CONTINUE, "\r                               \r\n" );

					if ( !storage_volume_ready() )
						return;
						
					if ( si_ptr->state != MOUNT_PROCEED )
						return;
				}
					
				if ( 'y' == k )
				{
					mprintf( WHITE, CONTINUE, "\r\n  storage class : Format started..." );

					if ( si_ptr->volume_instance[ 0 ] != NULL )
						fs_volume_close( si_ptr->volume_instance[ 0 ] );			

					si_ptr->volume_instance[ 0 ]	= NULL;
					
					fs_format();
					si_ptr->state	= IDLE;
					return;
				}
				si_ptr->state	= IDLE;
				break;
			}
			
			mprintf( WHITE, CONTINUE, "  storage class : Volume mounted." );
			mprintf( LIGHTGRAY, CONTINUE, "   ...press" );
			mprintf( LIGHTRED, CONTINUE, " [s] " );
			mprintf( LIGHTGRAY, CONTINUE, "to go into test shell.\r\n" );
			
			si_ptr->state	= MOUNTED;
			
			break;
			
		case MOUNTED :
		
			if ( gp_sof_counter < poll_timing )
				return;
				
			poll_timing		= gp_sof_counter + STORAGE_MOUNT_MONITOR_POLLING_INTERVAL;
			
			if ( 0 == check_the_card_exist() )	//	0 : the card exists
				return;

			if ( si_ptr->volume_instance[ 0 ] != NULL )
				mprintf( RED, CONTINUE, "\r\n  storage class : error : volume removed before volume-close\r\n" );

			//	break;	//	process continued to next state...
			
		case UNMOUNT_PROCEED :
		
			if ( NULL != si_ptr->volume_instance[ 0 ] )
				fs_volume_close( si_ptr->volume_instance[ 0 ] );
				
			si_ptr->volume_instance[ 0 ]		= NULL;
			
			strg_command( PREVENT_ALLOW_MEDIUM_REMOVAL, NULL, 0, 0 );
			strg_command( START_STOP_UNIT,              NULL, 0, 2 );	//	UnLoad media

			mprintf( WHITE, CONTINUE, "  storage class : Volume unmounted\r\n" );

			if ( si_ptr->remount == False )
				si_ptr->state	= IDLE;
			else
				si_ptr->state	= WAIT_FOR_CARD;

			break;

	}
}


static unsigned char check_the_card_exist( void )
{
	unsigned char	data[ 18 ];

	if ( strg_command( TEST_UNIT_READY, NULL, 0, 0 ) )
	{
		strg_command( REQUEST_SENSE, data, 0, 18 );

		return ( data[ 2 ] );
	}

	return ( 0 );
}




/*
==============================================================================
==============================================================================
====	Private functions for storage drive
====		Data transfers (command level)
==============================================================================
==============================================================================
*/


static unsigned char strg_command( unsigned char command_index, unsigned char *buffer_ptr, unsigned long logical_block_address, unsigned short allocation_length )
{
#define		COMMAND_OUT		0x00
#define		COMMAND_IN		0x80

	static unsigned char		commands[ 9 ][ 2 ]		=	{
																{ 0x06, 0x03 },		//	REQUEST_SENSE
																{ 0x06, 0x12 },		//	INQUIRY	
																{ 0x06, 0x1A },		//	MODE_SENSE
																{ 0x0A, 0x25 },		//	READ_CAPACITY
																{ 0x0A, 0x28 },		//	ST_READ
																
																{ 0x06, 0x00 },		//	TEST_UNIT_READY
																{ 0x06, 0x1B },		//	START_STOP_UNIT
																{ 0x06, 0x1E },		//	PREVENT_ALLOW_MEDIUM_REMOVAL
																{ 0x0A, 0x2A } 		//	ST_WRITE
															};
	st_command_block_wrapper	cbw;
	st_command_status_wrapper	csw;
	unsigned char				comm_direction;
	unsigned char				CBWStatus_value;
	unsigned char				i;

	if ( commands[ command_index ][ 0 ] == 0x06 )
	{
		cbw.CBWCB.reserved					= 0;
		cbw.CBWCB.transfer_length			= 0;
		cbw.CBWCB.control					= 0;

		((st_command_block6 *)(&(cbw.CBWCB)))->logical_block_address	= long_swap( logical_block_address );
		((st_command_block6 *)(&(cbw.CBWCB)))->transfer_length			= (unsigned char)allocation_length;
		((st_command_block6 *)(&(cbw.CBWCB)))->control					= 0;
		*((unsigned char *)(&(cbw.CBWCB)))								= commands[ command_index ][ 1 ];

		for ( i = 0; i < 10; i++ )
			(((st_command_block6 *)(&(cbw.CBWCB)))->dummy)[ i ]			= 0;
		
	}
	else
	{
		cbw.CBWCB.opcode					= commands[ command_index ][ 1 ];
		cbw.CBWCB.service_action			= 0;
		cbw.CBWCB.logical_block_address		= long_swap( logical_block_address );
		cbw.CBWCB.reserved					= 0;

		if ( READ_CAPACITY == command_index )
			cbw.CBWCB.transfer_length		= 0;
		else
			cbw.CBWCB.transfer_length		= short_swap( allocation_length );
			
		cbw.CBWCB.control					= 0;
		
		for ( i = 0; i < 6; i++ )
			(cbw.CBWCB.dummy)[ i ]			= 0;
	}
	
	comm_direction		= (command_index < 5) ? COMMAND_IN : COMMAND_OUT;

	if ( PREVENT_ALLOW_MEDIUM_REMOVAL == command_index )
		allocation_length	= 0;
	else if ( START_STOP_UNIT == command_index )
		allocation_length	= 0;
	else if ( READ_CAPACITY == command_index )
		allocation_length	= 8;
	else if ( (ST_READ == command_index) || (ST_WRITE == command_index) )
		allocation_length	*= gp_drive_parameter.block_length;
	
	cbw.dCBWSignature				= 0x43425355;
//	cbw.dCBWTag						= command_tag;
	cbw.dCBWDataTransferLength		= allocation_length;
	cbw.bmCBWFlags					= comm_direction;
//	cbw.bmCBWLUN					= 0;
	cbw.bmCBWLength					= commands[ command_index ][ 0 ];

	CBWStatus_value		= bulk_only_transfer( &cbw, buffer_ptr, allocation_length, comm_direction );

	if ( CBWStatus_value == 2 )
		reset_recovery();
		
	return ( CBWStatus_value );
}


static unsigned char bulk_only_transfer( st_command_block_wrapper *cbw_ptr, unsigned char *buffer_ptr, unsigned short allocation_length, unsigned char direction )
{
	static unsigned long		command_tag		= 0;
	st_command_status_wrapper	csw;
	unsigned char				err;
	unsigned char				retry			= 0;
	unsigned char				return_code		= 0;

	command_tag++;
	
	cbw_ptr->dCBWTag	= command_tag;
	cbw_ptr->bmCBWLUN	= ((storage_instance *)(g_storage_device_ptr->class_instance_ptr))->target_LUN;

	//
	//	CBW
	//

	//if ( err	= storage_bulk_transfer( g_storage_device_ptr, (unsigned char *)cbw_ptr, sizeof( st_command_block_wrapper ), OUT ) )
	if ( 0 != (err	= strg_bulk_transfer( g_storage_device_ptr, (unsigned char *)cbw_ptr, sizeof( st_command_block_wrapper ), OUT )) )
	{	
		if ( err == 0x4 )
			un_stall( OUT );
		else
		{
			allocation_length	= 0;
			retry				= 2;
		}
	}

	//
	//	DATA
	//
	if ( allocation_length )
	{
		//if ( err	= storage_bulk_transfer( g_storage_device_ptr, buffer_ptr, allocation_length, (direction == COMMAND_OUT) ? OUT : IN ) )
		if ( 0 != (err	= strg_bulk_transfer( g_storage_device_ptr, buffer_ptr, allocation_length, (direction == COMMAND_OUT) ? OUT : IN )) )
		{
			if ( err == 0x4 )
				un_stall( (direction == COMMAND_OUT) ? OUT : IN );
			else
				retry	= 2;
		}
	}

	//
	//	CSW
	//
	while ( retry < 2 )
	{
		err		= strg_bulk_transfer( g_storage_device_ptr, (unsigned char *)(&csw), sizeof( st_command_status_wrapper ), IN );

		if ( err != 0x4 )
			break;
		else
		{
			if ( retry == 0 )
				un_stall( IN );
		}
		
		retry++;
	}
	
	if ( retry == 2 )
	{
		return_code		= 2;
	}
	else
	{
		if ( (err == 0) || (err == 4) )
			return_code		= csw.bmCBWStatus;
		else
			return_code		= 3;
	}


	if ( return_code == 3 )
	{
		if ( ((storage_instance *)(g_storage_device_ptr->class_instance_ptr))->volume_instance[ 0 ] != NULL )
		{
			mprintf( RED, CONTINUE, "error : un-recoverable error happened  err=0x%01X\r\n", err );
			fs_volume_close( ((storage_instance *)(g_storage_device_ptr->class_instance_ptr))->volume_instance[ 0 ] );
			
			((storage_instance *)(g_storage_device_ptr->class_instance_ptr))->volume_instance[ 0 ]	= NULL;
		}
	}
	
	return ( return_code );
}


static void un_stall( unsigned char direction )
{
	device_instance 	*dvi_ptr;
	storage_instance	*si_ptr;
	unsigned long		dummy;
	unsigned short		size;
	
	dvi_ptr		= g_storage_device_ptr;
	si_ptr		= (storage_instance *)(dvi_ptr->class_instance_ptr);
	
	size	= 0;
	devep_std_request( (unsigned char *)(&dummy), dvi_ptr, std_Dv_request_CLEAR_FEATURE_Ep, 0, (direction == OUT) ? si_ptr->ep_out : si_ptr->ep_in, &size );
}


static void reset_recovery( void )
{
	device_instance		*dvi_ptr;
	storage_instance	*si_ptr;
	unsigned char		buffer;

	dvi_ptr		= g_storage_device_ptr;

⌨️ 快捷键说明

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