📄 scsi_decoder.c
字号:
Usb_write_byte(MSB0(mem_size_nb_sector)); // return nb block
Usb_write_byte(MSB1(mem_size_nb_sector));
Usb_write_byte(MSB2(mem_size_nb_sector));
Usb_write_byte(MSB3(mem_size_nb_sector));
Usb_write_byte( 0 ); // return block size (= 512B)
Usb_write_byte( 0 );
Usb_write_byte( (U8)(512 >> 8) );
Usb_write_byte( (U8)(512 & 0xFF));
Sbc_valid_write_usb(SBC_READ_CAPACITY_LENGTH);
sbc_lun_status_is_good();
return TRUE;
break;
case CTRL_NO_PRESENT :
sbc_lun_status_is_not_present();
break;
case CTRL_BUSY :
sbc_lun_status_is_busy_or_change();
break;
case CTRL_FAIL :
default :
sbc_lun_status_is_fail();
break;
}
return FALSE;
}
Bool sbc_read_10 (void)
{
U32 mass_addr; // rd or wr block address
U16 mass_size; // rd or write nb of blocks
MSB0(mass_addr) = g_scsi_command[2]; // read address
MSB1(mass_addr) = g_scsi_command[3];
MSB2(mass_addr) = g_scsi_command[4];
MSB3(mass_addr) = g_scsi_command[5];
MSB(mass_size) = g_scsi_command[7]; // read size
LSB(mass_size) = g_scsi_command[8];
if (mass_size != 0)
{
switch ( memory_2_usb( usb_LUN , mass_addr, mass_size ) )
{
case CTRL_GOOD :
sbc_lun_status_is_good();
g_scsi_data_remaining = g_scsi_data_remaining - (512 * (Uint32)mass_size);
return TRUE;
break;
case CTRL_NO_PRESENT :
sbc_lun_status_is_not_present();
return FALSE;
break;
case CTRL_BUSY :
sbc_lun_status_is_busy_or_change();
return FALSE;
break;
case CTRL_FAIL :
default :
sbc_lun_status_is_fail();
return FALSE;
break;
}
}
else
{ // No data to transfer
sbc_lun_status_is_good();
}
return TRUE;
}
Bool sbc_write_10 (void)
{
U32 mass_addr; // rd or wr block address
U16 mass_size; // rd or write nb of blocks
MSB0(mass_addr) = g_scsi_command[2]; // read address
MSB1(mass_addr) = g_scsi_command[3];
MSB2(mass_addr) = g_scsi_command[4];
MSB3(mass_addr) = g_scsi_command[5];
MSB(mass_size) = g_scsi_command[7]; // read size
LSB(mass_size) = g_scsi_command[8];
if (mass_size != 0)
{
if( TRUE == mem_wr_protect( usb_LUN ) )
{
sbc_lun_status_is_protected();
return FALSE;
#warning For Win98 data must be read to avoid blocking
}
else
{
switch (usb_2_memory( usb_LUN , mass_addr, mass_size ))
{
case CTRL_GOOD :
sbc_lun_status_is_good();
g_scsi_data_remaining = g_scsi_data_remaining - (512 * (Uint32)mass_size);
return TRUE;
break;
case CTRL_NO_PRESENT :
sbc_lun_status_is_not_present();
return FALSE;
break;
case CTRL_BUSY :
sbc_lun_status_is_busy_or_change();
return FALSE;
break;
case CTRL_FAIL :
default :
sbc_lun_status_is_fail();
return FALSE;
break;
}
}
}
else
{ // No data to transfer
sbc_lun_status_is_good();
}
return TRUE;
}
/**
* @brief This function manages the SCSI MODE SENSE command (0x1A for sense 6 and 0x5A for sense 10)
*
* The SCSI mode sense function returns parameters to an application client.
* It is a complementary command to the SCSI MODE SELECT command.
*
* @warning Code:.. bytes (function code length)
*
* @param b_sens_10 ( TRUE = sense 10, TRUE = sense 6)
*
* @return FALSE: result KO,
* TRUE: result OK
*
*/
Bool sbc_mode_sense( Bool b_sense_10 )
{
U8 allocation_length;
if( b_sense_10 )
allocation_length = g_scsi_command[8];
else
allocation_length = g_scsi_command[4];
// switch for page code
switch ( g_scsi_command[2] & SBC_MSK_PAGE_CODE )
{
case SBC_PAGE_CODE_INFORMATIONAL_EXCEPTIONS: /* Page Code: Informational exceptions control page */
sbc_header_mode_sense( b_sense_10 , SBC_MODE_DATA_LENGTH_INFORMATIONAL_EXCEPTIONS );
send_informational_exceptions_page();
Sbc_valid_write_usb(SBC_MODE_DATA_LENGTH_INFORMATIONAL_EXCEPTIONS + 1);
break;
case SBC_PAGE_CODE_READ_WRITE_ERROR_RECOVERY:
sbc_header_mode_sense( b_sense_10 , SBC_MODE_DATA_LENGTH_READ_WRITE_ERROR_RECOVERY );
send_read_write_error_recovery_page(allocation_length);
Sbc_valid_write_usb(SBC_MODE_DATA_LENGTH_READ_WRITE_ERROR_RECOVERY + 1);
break;
case SBC_PAGE_CODE_ALL:
sbc_header_mode_sense( b_sense_10 , SBC_MODE_DATA_LENGTH_CODE_ALL );
if( b_sense_10 )
{
if (allocation_length == 8)
{
Sbc_valid_write_usb(8);
break;
}
}
else
{
if (allocation_length == 4)
{
Sbc_valid_write_usb(4);
break;
}
}
// send page by ascending order code
send_read_write_error_recovery_page(allocation_length); // 12 bytes
if (allocation_length > 12)
{
send_informational_exceptions_page(); // 12 bytes
Sbc_valid_write_usb(SBC_MODE_DATA_LENGTH_CODE_ALL + 1);
}
else
{
Sbc_valid_write_usb(allocation_length);
}
break;
default:
Sbc_send_failed();
Sbc_build_sense(SBC_SENSE_KEY_ILLEGAL_REQUEST, SBC_ASC_INVALID_FIELD_IN_CDB, 0x00);
return FALSE;
break;
}
sbc_lun_status_is_good();
return TRUE;
}
/**
* @brief This function send the header of the SCSI MODE SENSE command
*
* @param b_sens_10 ( TRUE = sense 10, FALSE = sense 6)
* @param u8_data_length ( data length in byte )
*
*/
void sbc_header_mode_sense( Bool b_sense_10 , U8 u8_data_length )
{
// Send Data length
if( b_sense_10 )
{
Usb_write_byte(0);
}
Usb_write_byte( u8_data_length );
// Send device type
Usb_write_byte(SBC_MEDIUM_TYPE);
// Write protect status
if (mem_wr_protect( usb_LUN ))
{
Usb_write_byte(SBC_DEV_SPEC_PARAM_WR_PROTECT); // Device is write protected
}
else
{
Usb_write_byte(SBC_DEV_SPEC_PARAM_WR_ENABLE); // Device is write enabled
}
if( b_sense_10 )
{ // Reserved
Usb_write_byte(0);
Usb_write_byte(0);
}
// Send Block descriptor length
if( b_sense_10 )
{
Usb_write_byte(0);
}
Usb_write_byte(SBC_BLOCK_DESCRIPTOR_LENGTH);
}
/**
* @brief This function writes informational exceptions page parameters
*
* @warning Code:.. bytes (function code length)
*
* @param none
*
* @return FALSE: result KO,
* TRUE: result OK
*
*/
void send_informational_exceptions_page (void)
{
Usb_write_byte(SBC_PAGE_CODE_INFORMATIONAL_EXCEPTIONS); /* Page Code: Informational exceptions control page */
/* See chapter 8.3.8 on SPC-2 specification */
Usb_write_byte(SBC_PAGE_LENGTH_INFORMATIONAL_EXCEPTIONS); /* Page Length */
Usb_write_byte(0x00); /* ..., Test bit = 0, ... */
Usb_write_byte(SBC_MRIE); /* MRIE = 0x05 */
Usb_write_byte(0x00); /* Interval Timer (MSB) */
Usb_write_byte(0x00);
Usb_write_byte(0x00);
Usb_write_byte(0x00); /* Interval Timer (LSB) */
Usb_write_byte(0x00); /* Report Count (MSB) */
Usb_write_byte(0x00);
Usb_write_byte(0x00);
Usb_write_byte(0x01); /* Report Count (LSB) */
}
/**
* @brief This function writes error recovery page
*
* @warning Code:.. bytes (function code length)
*
* @param none
*
* @return FALSE: result KO,
* TRUE: result OK
*
*/
void send_read_write_error_recovery_page (U8 length)
{
Usb_write_byte(SBC_PAGE_CODE_READ_WRITE_ERROR_RECOVERY);
Usb_write_byte(SBC_PAGE_LENGTH_READ_WRITE_ERROR_RECOVERY); /* Page Length */
Usb_write_byte(0x80);
Usb_write_byte(SBC_READ_RETRY_COUNT);
Usb_write_byte(SBC_CORRECTION_SPAN);
Usb_write_byte(SBC_HEAD_OFFSET_COUNT);
Usb_write_byte(SBC_DATA_STROBE_OFFSET);
Usb_write_byte(0x00); /* Reserved */
if (length > 12)
{
Usb_write_byte(SBC_WRITE_RETRY_COUNT);
Usb_write_byte(0x00);
Usb_write_byte(SBC_RECOVERY_LIMIT_MSB);
Usb_write_byte(SBC_RECOVERY_LIMIT_LSB);
}
}
/**
* @brief This function manages the SCSI PREVENT ALLOW MEDIUM REMOVAL
* command (0x1E)
*
* The SCSI prevent allow medium removal command requests that the target
* enable or disable the removal of the medium in the logical unit.
*
* @warning Code:.. bytes (function code length)
*
* @param none
*
* @return FALSE: result KO,
* TRUE: result OK
*
*/
Bool sbc_prevent_allow_medium_removal(void)
{
sbc_lun_status_is_good();
return TRUE;
}
//! This fonction send the UFI status GOOD
//!
void sbc_lun_status_is_good(void)
{
Sbc_send_good();
Sbc_build_sense(SBC_SENSE_KEY_NO_SENSE, SBC_ASC_NO_ADDITIONAL_SENSE_INFORMATION, 0x00);
}
//! This fonction send the UFI status "lun not present"
//!
void sbc_lun_status_is_not_present(void)
{
Sbc_send_failed();
Sbc_build_sense(SBC_SENSE_KEY_NOT_READY, SBC_ASC_MEDIUM_NOT_PRESENT, 0x00);
}
//! This fonction send the UFI status busy and change
//!
void sbc_lun_status_is_busy_or_change(void)
{
Sbc_send_failed();
Sbc_build_sense(SBC_SENSE_KEY_UNIT_ATTENTION, SBC_ASC_NOT_READY_TO_READY_CHANGE, 0x00 );
}
//! This fonction send the UFI status FAIL
//!
void sbc_lun_status_is_fail(void)
{
Sbc_send_failed();
Sbc_build_sense(SBC_SENSE_KEY_HARDWARE_ERROR, SBC_ASC_NO_ADDITIONAL_SENSE_INFORMATION, 0x00);
}
//! This fonction send the UFI status FAIL because write protection
//!
void sbc_lun_status_is_protected(void)
{
Sbc_send_failed();
Sbc_build_sense(SBC_SENSE_KEY_DATA_PROTECT, SBC_ASC_WRITE_PROTECTED, 0x00);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -