📄 storage.c
字号:
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 + -