📄 scsi_decoder.c
字号:
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); 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_sense_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_sense_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) * * @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 length The length of * * @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) * * @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 + -