📄 scsi_decoder.c
字号:
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 TRUE;
}
Bool sbc_read_capacity (void)
{
_MEM_TYPE_SLOW_ U32 mem_size_nb_sector;
switch ( mem_read_capacity( usb_LUN, &mem_size_nb_sector ) )
{
case CTRL_GOOD :
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);
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;
}
}
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();
}
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);
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;
}
}
}
else
{ // No data to transfer
sbc_lun_status_is_good();
}
return TRUE;
}
/**
* @brief This function manages the SCSI MODE SENSE command (0x1A)
*
* 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 none
*
* @return FALSE: result KO,
* TRUE: result OK
*
*/
Bool sbc_mode_sense_6 (void)
{
U8 page_control, page_code, dbd;
U8 allocation_length;
U8 gl_sbc_wr_protect = FALSE;
dbd = g_scsi_command[1] & SBC_MSK_DBD;
page_code = g_scsi_command[2];
page_control = page_code & SBC_MSK_PAGE_CONTROL;
page_code = page_code & SBC_MSK_PAGE_CODE;
allocation_length = g_scsi_command[4];
switch (page_code)
{
case SBC_PAGE_CODE_INFORMATIONAL_EXCEPTIONS: /* Page Code: Informational exceptions control page */
/* Mode Data Length */
Usb_write_byte(SBC_MODE_DATA_LENGTH_INFORMATIONAL_EXCEPTIONS);
Usb_write_byte(SBC_MEDIUM_TYPE); /* Device type */
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 */
}
Usb_write_byte(SBC_BLOCK_DESCRIPTOR_LENGTH); /* Block descriptor length */
send_informational_exceptions_page();
/* build sense data */
Sbc_build_sense(SBC_SENSE_KEY_NO_SENSE, 0x00, 0x00);
/* ack write */
Sbc_valid_write_usb(SBC_MODE_DATA_LENGTH_INFORMATIONAL_EXCEPTIONS + 1);
sbc_lun_status_is_good();
break;
#if 0
case SBC_PAGE_CODE_FORMAT_DEVICE:
Usb_write_byte(SBC_MODE_DATA_LENGTH_FORMAT_DEVICE);
Usb_write_byte(SBC_MEDIUM_TYPE); /* Device type */
Usb_write_byte(SBC_DEVICE_SPECIFIC_PARAMETER); /* Device specific parameter */
Usb_write_byte(SBC_BLOCK_DESCRIPTOR_LENGTH); /* Block descriptor length */
send_format_device_page();
send_informational_exceptions_page();
/* build sense data */
Sbc_build_sense(SBC_SENSE_KEY_NO_SENSE, 0x00, 0x00);
/* ack write */
Sbc_valid_write_usb(SBC_MODE_DATA_LENGTH_FORMAT_DEVICE + 1);
sbc_lun_status_is_good();
break;
#endif
case SBC_PAGE_CODE_READ_WRITE_ERROR_RECOVERY:
/* Mode Data Length */
Usb_write_byte(SBC_MODE_DATA_LENGTH_READ_WRITE_ERROR_RECOVERY);
Usb_write_byte(SBC_MEDIUM_TYPE); /* Device type */
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 */
}
Usb_write_byte(SBC_BLOCK_DESCRIPTOR_LENGTH); /* Block descriptor length */
send_read_write_error_recovery_page(allocation_length);
/* build sense data */
Sbc_build_sense(SBC_SENSE_KEY_NO_SENSE, 0x00, 0x00);
/* ack write */
Sbc_valid_write_usb(SBC_MODE_DATA_LENGTH_READ_WRITE_ERROR_RECOVERY + 1);
sbc_lun_status_is_good();
break;
#if 0
case SBC_PAGE_CODE_FLEXIBLE_DISK:
/* Mode Data Length */
Usb_write_byte(SBC_MODE_DATA_LENGTH_FLEXIBLE_DISK);
Usb_write_byte(SBC_MEDIUM_TYPE); /* Device type */
Usb_write_byte(SBC_DEVICE_SPECIFIC_PARAMETER); /* Device specific parameter */
Usb_write_byte(SBC_BLOCK_DESCRIPTOR_LENGTH); /* Block descriptor length */
send_flexible_disk_page();
/* build sense data */
Sbc_build_sense(SBC_SENSE_KEY_NO_SENSE, 0x00, 0x00);
/* ack write */
Sbc_valid_write_usb(SBC_MODE_DATA_LENGTH_FLEXIBLE_DISK + 1);
sbc_lun_status_is_good();
break;
#endif
case SBC_PAGE_CODE_ALL:
Usb_write_byte(SBC_MODE_DATA_LENGTH_CODE_ALL); /* Mode Data Length */
Usb_write_byte(SBC_MEDIUM_TYPE); /* Device type */
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 */
}
Usb_write_byte(SBC_BLOCK_DESCRIPTOR_LENGTH); /* Block descriptor length */
if (allocation_length == 4)
{
Sbc_valid_write_usb(4);
sbc_lun_status_is_good();
break;
}
/* send page by ascending order code */
send_read_write_error_recovery_page(allocation_length); /* 12 bytes */
// send_format_device_page(); /* 24 bytes */
if (allocation_length > 12)
{
// send_flexible_disk_page(); /* 32 bytes */
send_informational_exceptions_page(); /* 12 bytes */
}
/* build sense data */
Sbc_build_sense(SBC_SENSE_KEY_NO_SENSE, SBC_ASC_NO_ADDITIONAL_SENSE_INFORMATION, 0x00);
/* ack write */
if (allocation_length > 12)
{
Sbc_valid_write_usb(SBC_MODE_DATA_LENGTH_CODE_ALL + 1);
}
else
{
Sbc_valid_write_usb(allocation_length);
}
sbc_lun_status_is_good();
break;
default:
// Usb_enable_stall_handshake();
// Sbc_send_check_condition();
Sbc_send_failed();
Sbc_build_sense(SBC_SENSE_KEY_ILLEGAL_REQUEST, SBC_ASC_INVALID_FIELD_IN_CDB, 0x00);
return FALSE;
break;
}
return TRUE;
}
/**
* @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 (Byte 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 + -