diff options
| author | Sebastian Vater | 2025-09-16 11:36:25 +0200 |
|---|---|---|
| committer | Sebastian Vater | 2025-09-16 11:36:25 +0200 |
| commit | f1f80edca93172c173123d3e2f4936de433b62ac (patch) | |
| tree | e67ac01eaa5111b14e380b8b1aedf3bb15850454 | |
| parent | Fixed iSCSI SCSI emulation and implemented adding target port to iSCSI device... (diff) | |
| download | dnbd3-f1f80edca93172c173123d3e2f4936de433b62ac.tar.gz dnbd3-f1f80edca93172c173123d3e2f4936de433b62ac.tar.xz dnbd3-f1f80edca93172c173123d3e2f4936de433b62ac.zip | |
Implemented iSCSI SCSI MODE SENSE command. Also did code refactoring. Finally, fixed some bugs.
| -rw-r--r-- | src/server/iscsi.c | 517 | ||||
| -rw-r--r-- | src/server/iscsi.h | 856 |
2 files changed, 1250 insertions, 123 deletions
diff --git a/src/server/iscsi.c b/src/server/iscsi.c index 0ab6f1e..f58a6cd 100644 --- a/src/server/iscsi.c +++ b/src/server/iscsi.c @@ -27,6 +27,7 @@ #include <stdlib.h> #include <string.h> #include <inttypes.h> +#include <limits.h> #include <strings.h> #include <sys/socket.h> #include <sys/types.h> @@ -4334,7 +4335,7 @@ void iscsi_scsi_lun_task_run(iscsi_scsi_lun *lun, iscsi_scsi_task *scsi_task) int rc = iscsi_hashmap_put( lun->tasks, (uint8_t *) &scsi_task->id, sizeof(scsi_task->id), (uint8_t *) scsi_task ); if ( rc < 0 ) { - iscsi_scsi_task_status_set( scsi_task, ISCSI_SCSI_STATUS_CHECK_COND, ISCSI_SCSI_SENSE_KEY_HARDWARE_ERR, ISCSI_SCSI_ASC_WARNING, ISCSI_SCSI_ASCQ_POWER_LOSS_EXPECTED ); + iscsi_scsi_task_status_set( scsi_task, ISCSI_SCSI_STATUS_CHECK_COND, ISCSI_SCSI_SENSE_KEY_NOT_READY, ISCSI_SCSI_ASC_LOGICAL_UNIT_NOT_READY, ISCSI_SCSI_ASCQ_BECOMING_READY ); return; } @@ -4871,6 +4872,64 @@ static inline bool iscsi_scsi_emu_io_type_is_supported(const dnbd3_image_t *imag } /** + * @brief Checks whether a specified block size is a power of two. + * + * This function is used to determine + * if shift operations can be used for + * calculating Logical Block Addresses + * (LBAs). + * + * @param[in] block_size Block size to check for a power of two. + * @retval true Block size is a power of two. + * @retval false Block size is NOT a power of two, + * hence slow division is required. + */ +static inline bool iscsi_scsi_emu_block_size_is_pow2(const uint32_t block_size) +{ + return ((block_size & (block_size - 1UL)) == 0UL); +} + +/** + * @brief Calculates the shift factor for a power of two block size. + * + * This function is used to determine + * the shift factor for caclulating + * the byte offset of a Logical + * Block Address (LBA). + * + * @param[in] block_size Block size in bytes + * to calculate the shift factor + * for. May NOT be zero in which + * case the result is undefined. + * @return The shift count for Logical Block + * Address (LBA) calculation. + */ +static inline uint32_t iscsi_scsi_emu_get_block_size_shift(const uint32_t block_size) +{ +#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) || defined(__INTEL_COMPILER) || defined(__ECC) +// GCC, CLang or Intel Compiler + return (((sizeof(uint32_t) * CHAR_BIT) - 1UL) - __builtin_clz( block_size )); +#elif defined(_MSC_VER) +// MSVC + uint32_t shift; + + _BitScanReverse( &shift, block_size ); + + return (((sizeof(uint32_t) * CHAR_BIT) - 1UL) - shift); +#else +// Other compilers (use slow parallel calculation method with logical OR, bit shift, logcal AND) + uint32_t shift = ((block_size & 0xAAAAAAAAUL) != 0UL); + + shift |= ((block_size & 0xCCCCCCCCUL) != 0UL) << 1UL; + shift |= ((block_size & 0xF0F0F0F0UL) != 0UL) << 2UL; + shift |= ((block_size & 0xFF00FF00UL) != 0UL) << 3UL; + shift |= ((block_size & 0xFFFF0000UL) != 0UL) << 4UL; + + return shift; +#endif +} + +/** * @brief Retrieves the number of total physical blocks for a DNBB3 image. * * This function depends on DNBB3 image @@ -4984,7 +5043,7 @@ static inline uint32_t iscsi_scsi_emu_block_get_size(const dnbd3_image_t *image) */ static inline uint32_t iscsi_scsi_emu_block_get_ratio_shift(const dnbd3_image_t *image) { - return (iscsi_scsi_emu_block_get_size_shift(image) - iscsi_scsi_emu_physical_block_get_size_shift(image)); + return (iscsi_scsi_emu_physical_block_get_size_shift(image) - iscsi_scsi_emu_block_get_size_shift(image)); } /** @@ -5137,7 +5196,7 @@ static bool iscsi_scsi_emu_image_init(iscsi_scsi_task *scsi_task, const bool acc iscsi_scsi_lun *lun = scsi_task->lun; if ( lun->image == NULL ) { - lun->image = image_getOrLoad( lun->device->name, (uint16_t) lun->id ); + lun->image = image_getOrLoad( (char *) lun->device->name, (uint16_t) lun->id ); if ( lun->image == NULL ) { iscsi_scsi_task_status_set( scsi_task, ISCSI_SCSI_STATUS_CHECK_COND, ISCSI_SCSI_SENSE_KEY_NOT_READY, ISCSI_SCSI_ASC_LOGICAL_UNIT_NOT_READY, ISCSI_SCSI_ASCQ_MANUAL_INTERVENTION_REQUIRED ); @@ -5265,7 +5324,7 @@ static int iscsi_scsi_emu_block_process(iscsi_scsi_task *scsi_task) iscsi_scsi_read_capacity_10_parameter_data_packet *buf = (iscsi_scsi_read_capacity_10_parameter_data_packet *) malloc( sizeof(struct iscsi_scsi_read_capacity_10_parameter_data_packet) ); if ( buf == NULL ) { - iscsi_scsi_task_status_set( scsi_task, ISCSI_SCSI_STATUS_CHECK_COND, ISCSI_SCSI_SENSE_KEY_HARDWARE_ERR, ISCSI_SCSI_ASC_WARNING, ISCSI_SCSI_ASCQ_POWER_LOSS_EXPECTED ); + iscsi_scsi_task_status_set( scsi_task, ISCSI_SCSI_STATUS_CHECK_COND, ISCSI_SCSI_SENSE_KEY_NOT_READY, ISCSI_SCSI_ASC_LOGICAL_UNIT_NOT_READY, ISCSI_SCSI_ASCQ_BECOMING_READY ); return ISCSI_SCSI_TASK_RUN_COMPLETE; } @@ -5303,7 +5362,7 @@ static int iscsi_scsi_emu_block_process(iscsi_scsi_task *scsi_task) iscsi_scsi_service_action_in_16_parameter_data_packet *buf = (iscsi_scsi_service_action_in_16_parameter_data_packet *) malloc( sizeof(struct iscsi_scsi_service_action_in_16_parameter_data_packet) ); if ( buf == NULL ) { - iscsi_scsi_task_status_set( scsi_task, ISCSI_SCSI_STATUS_CHECK_COND, ISCSI_SCSI_SENSE_KEY_HARDWARE_ERR, ISCSI_SCSI_ASC_WARNING, ISCSI_SCSI_ASCQ_POWER_LOSS_EXPECTED ); + iscsi_scsi_task_status_set( scsi_task, ISCSI_SCSI_STATUS_CHECK_COND, ISCSI_SCSI_SENSE_KEY_NOT_READY, ISCSI_SCSI_ASC_LOGICAL_UNIT_NOT_READY, ISCSI_SCSI_ASCQ_BECOMING_READY ); return ISCSI_SCSI_TASK_RUN_COMPLETE; } @@ -6130,28 +6189,330 @@ static int iscsi_scsi_emu_primary_report_luns(iscsi_scsi_lun *lun, iscsi_scsi_re } /** + * @brief Initializes a mode sense page or sub page and zero fills the parameter data. + * + * This function also sets the correct + * page length and flags either for + * the page or sub page. If a sub page + * is initialized, the sub page code + * will also be set. + * + * @param[in] mode_sense_mode_page_pkt Pointer to mode sense parameter + * mode page or sub page data packet + * to initialize. If this is NULL, + * this function does nothing. + * @param[in] len Length in bytes to initialize with zeroes. + * @param[in] page Page code. + * @param[in] sub_page Sub page code. + */ +static void iscsi_scsi_emu_primary_mode_sense_page_init(iscsi_scsi_mode_sense_mode_page_data_packet *mode_sense_mode_page_pkt, const uint len, const uint page, const uint sub_page) +{ + if ( mode_sense_mode_page_pkt == NULL ) + return; + + if ( sub_page == 0 ) { + mode_sense_mode_page_pkt->page_code_flags = (uint8_t) ISCSI_SCSI_MODE_SENSE_MODE_PAGE_PUT_PAGE_CODE(page); + mode_sense_mode_page_pkt->page_len = (uint8_t) (len - sizeof(struct iscsi_scsi_mode_sense_mode_page_data_packet)); + + memset( mode_sense_mode_page_pkt->params, 0, (len - offsetof(struct iscsi_scsi_mode_sense_mode_page_data_packet, params)) ); + } else { + iscsi_scsi_mode_sense_mode_sub_page_data_packet *mode_sense_mode_sub_page_pkt = (iscsi_scsi_mode_sense_mode_sub_page_data_packet *) mode_sense_mode_page_pkt; + + mode_sense_mode_sub_page_pkt->page_code_flags = (uint8_t) (ISCSI_SCSI_MODE_SENSE_MODE_PAGE_PUT_PAGE_CODE(page) | ISCSI_SCSI_MODE_SENSE_MODE_PAGE_FLAGS_SPF); + mode_sense_mode_sub_page_pkt->sub_page_code = (uint8_t) sub_page; + iscsi_put_be16( (uint8_t *) &mode_sense_mode_sub_page_pkt->page_len, (uint16_t) (len - sizeof(struct iscsi_scsi_mode_sense_mode_sub_page_data_packet)) ); + + memset( mode_sense_mode_sub_page_pkt->params, 0, (len - offsetof(struct iscsi_scsi_mode_sense_mode_sub_page_data_packet, params)) ); + } +} + +/** + * @brief Handles a specific mode sense page or sub page. + * + * This function also sets the SCSI + * status result code accordingly. + * + * @param[in] image Pointer to DNBD3 image to get + * the mode sense data from. May NOT be + * NULL, so be careful. + * @param[in] scsi_task Pointer to iSCSI SCSI task + * responsible for this mode sense + * task. NULL is NOT allowed here, + * take caution. + * @param[in] mode_sense_mode_page_pkt Pointer to mode sense parameter + * mode page or sub page data packet + * to process. If this is NULL, only + * the length of page is calculated. + * @param[in] pc Page control (PC). + * @param[in] page Page code. + * @param[in] sub_page Sub page code. + * @return Number of bytes occupied or a + * negative error code otherwise. + */ +static int iscsi_scsi_emu_primary_mode_sense_page(dnbd3_image_t *image, iscsi_scsi_task *scsi_task, iscsi_scsi_mode_sense_mode_page_data_packet *mode_sense_mode_page_pkt, const uint pc, const uint page, const uint sub_page) +{ + uint page_len; + int len = 0; + + switch ( pc ) { + case ISCSI_SCSI_CDB_MODE_SENSE_6_PAGE_CONTROL_CURRENT_VALUES : + case ISCSI_SCSI_CDB_MODE_SENSE_6_PAGE_CONTROL_CHG_VALUES : + case ISCSI_SCSI_CDB_MODE_SENSE_6_PAGE_CONTROL_DEFAULT_VALUES : { + break; + } + default : { + iscsi_scsi_task_status_set( scsi_task, ISCSI_SCSI_STATUS_CHECK_COND, ISCSI_SCSI_SENSE_KEY_ILLEGAL_REQ, ISCSI_SCSI_ASC_SAVING_PARAMETERS_NOT_SUPPORTED, ISCSI_SCSI_ASCQ_CAUSE_NOT_REPORTABLE ); + + return -1; + + break; + } + } + + switch ( page ) { + case ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_VENDOR_SPEC : + case ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_FORMAT_DEVICE : + case ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_RIGID_DISK_GEOMETRY : + case ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_RIGID_DISK_GEOMETRY_2 : + case ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_RESERVED : + case ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_OBSELETE : + case ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_MEDIUM_TYPES_SUPPORTED : + case ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_NOTCH_AND_PARTITION : + case ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_OBSELETE_2 : + case ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_RESERVED_2 : + case ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_RESERVED_3 : + case ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_RESERVED_4 : + case ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_RESERVED_5 : + case ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_RESERVED_6 : + case ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_ENCLOSURE_SERVICES_MGMT : + case ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_RESERVED_7 : + case ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_RESERVED_8 : + case ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_RESERVED_9 : + case ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_PROTOCOL_SPEC_LUN : + case ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_PROTOCOL_SPEC_PORT : + case ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_RESERVED_10 : + case ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_RESERVED_11 : + case ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_RESERVED_12 : + case ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_RESERVED_13 : + case ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_VENDOR_SPEC_2 : + case ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_VENDOR_SPEC_3 : + case ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_VENDOR_SPEC_4 : + case ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_VENDOR_SPEC_5 : + case ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_VENDOR_SPEC_6 : + case ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_VENDOR_SPEC_7 : + case ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_VENDOR_SPEC_8 : + case ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_VENDOR_SPEC_9 : + case ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_VENDOR_SPEC_10 : + case ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_VENDOR_SPEC_11 : + case ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_VENDOR_SPEC_12 : + case ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_VENDOR_SPEC_13 : + case ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_VENDOR_SPEC_14 : + case ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_VENDOR_SPEC_15 : + case ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_VENDOR_SPEC_16 : + case ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_VENDOR_SPEC_17 : + case ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_VENDOR_SPEC_18 : + case ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_VENDOR_SPEC_19 : + case ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_VENDOR_SPEC_20 : + case ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_VENDOR_SPEC_21 : + case ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_VENDOR_SPEC_22 : + case ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_VENDOR_SPEC_23 : + case ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_VENDOR_SPEC_24 : + case ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_VENDOR_SPEC_25 : + case ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_VENDOR_SPEC_26 : + case ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_VENDOR_SPEC_27 : + case ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_VENDOR_SPEC_28 : + case ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_VENDOR_SPEC_29 : + case ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_VENDOR_SPEC_30 : + case ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_VENDOR_SPEC_31 : + case ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_VENDOR_SPEC_32 : { + break; + } + case ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_READ_WRITE_ERR_RECOVERY : { + if ( sub_page != 0 ) + break; + + page_len = sizeof(struct iscsi_scsi_mode_sense_read_write_err_recovery_mode_page_data_packet); + + iscsi_scsi_emu_primary_mode_sense_page_init( mode_sense_mode_page_pkt, page_len, page, sub_page ); + + len += page_len; + + break; + } + case ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_DISCONNECT_RECONNECT : { + if ( sub_page != 0 ) + break; + + page_len = sizeof(struct iscsi_scsi_mode_sense_disconnect_reconnect_mode_page_data_packet); + + iscsi_scsi_emu_primary_mode_sense_page_init( mode_sense_mode_page_pkt, page_len, page, sub_page ); + + len += page_len; + + break; + } + case ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_VERIFY_ERR_RECOVERY : { + if ( sub_page != 0 ) + break; + + page_len = sizeof(struct iscsi_scsi_mode_sense_verify_err_recovery_mode_page_data_packet); + + iscsi_scsi_emu_primary_mode_sense_page_init( mode_sense_mode_page_pkt, page_len, page, sub_page ); + + len += page_len; + + break; + } + case ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_CACHING : { + if ( sub_page != 0 ) + break; + + iscsi_scsi_mode_sense_caching_mode_page_data_packet *mode_sense_caching_mode_page_pkt = (iscsi_scsi_mode_sense_caching_mode_page_data_packet *) mode_sense_mode_page_pkt; + + page_len = sizeof(struct iscsi_scsi_mode_sense_caching_mode_page_data_packet); + + iscsi_scsi_emu_primary_mode_sense_page_init( mode_sense_mode_page_pkt, page_len, page, sub_page ); + + if ( (mode_sense_mode_page_pkt != NULL) && iscsi_scsi_emu_io_type_is_supported( image, ISCSI_SCSI_EMU_IO_TYPE_WRITE_CACHE ) && (pc != ISCSI_SCSI_CDB_MODE_SENSE_6_PAGE_CONTROL_CHG_VALUES) ) + mode_sense_caching_mode_page_pkt->flags |= ISCSI_SCSI_MODE_SENSE_CACHING_MODE_PAGE_FLAGS_WCE; + + if ( (mode_sense_mode_page_pkt != NULL) && (pc != ISCSI_SCSI_CDB_MODE_SENSE_6_PAGE_CONTROL_CHG_VALUES) ) + mode_sense_caching_mode_page_pkt->flags |= ISCSI_SCSI_MODE_SENSE_CACHING_MODE_PAGE_FLAGS_RCD; + + len += page_len; + + break; + } + case ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_CONTROL : { + switch ( sub_page ) { + case ISCSI_SCSI_MODE_SENSE_MODE_SUB_PAGE_CODE_CONTROL : { + page_len = sizeof(struct iscsi_scsi_mode_sense_control_mode_page_data_packet); + + iscsi_scsi_emu_primary_mode_sense_page_init( mode_sense_mode_page_pkt, page_len, page, sub_page ); + + len += page_len; + + break; + } + case ISCSI_SCSI_MODE_SENSE_MODE_SUB_PAGE_CODE_CONTROL_EXT : { + /* Control Extension */ + + page_len = sizeof(struct iscsi_scsi_mode_sense_control_ext_mode_page_data_packet); + + iscsi_scsi_emu_primary_mode_sense_page_init( mode_sense_mode_page_pkt, page_len, page, sub_page ); + + len += page_len; + + break; + } + case ISCSI_SCSI_MODE_SENSE_MODE_SUB_PAGE_CODE_CONTROL_ALL : { + len += iscsi_scsi_emu_primary_mode_sense_page( image, scsi_task, ((mode_sense_mode_page_pkt != NULL) ? (iscsi_scsi_mode_sense_mode_page_data_packet *) (((uint8_t *) mode_sense_mode_page_pkt) + len) : NULL), pc, page, ISCSI_SCSI_MODE_SENSE_MODE_SUB_PAGE_CODE_CONTROL ); + len += iscsi_scsi_emu_primary_mode_sense_page( image, scsi_task, ((mode_sense_mode_page_pkt != NULL) ? (iscsi_scsi_mode_sense_mode_page_data_packet *) (((uint8_t *) mode_sense_mode_page_pkt) + len) : NULL), pc, page, ISCSI_SCSI_MODE_SENSE_MODE_SUB_PAGE_CODE_CONTROL_EXT ); + + break; + } + default : { + break; + } + } + + break; + } + case ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_XOR_CONTROL : { + if ( sub_page != 0 ) + break; + + page_len = sizeof(struct iscsi_scsi_mode_sense_xor_ext_mode_page_data_packet); + + iscsi_scsi_emu_primary_mode_sense_page_init( mode_sense_mode_page_pkt, page_len, page, sub_page ); + + len += page_len; + + break; + } + case ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_POWER_COND : { + if ( sub_page != 0 ) + break; + + page_len = sizeof(struct iscsi_scsi_mode_sense_power_cond_mode_page_data_packet); + + iscsi_scsi_emu_primary_mode_sense_page_init( mode_sense_mode_page_pkt, page_len, page, sub_page ); + + len += page_len; + + break; + } + case ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_INFO_EXCEPTIOS_CONTROL : { + if ( sub_page != 0 ) + break; + + page_len = sizeof(struct iscsi_scsi_mode_sense_info_exceptions_control_mode_page_data_packet); + + iscsi_scsi_emu_primary_mode_sense_page_init( mode_sense_mode_page_pkt, page_len, page, sub_page ); + + len += page_len; + + break; + } + case ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_REPORT_ALL_MODE_PAGES : { + uint i; + + switch ( sub_page ) { + case ISCSI_SCSI_MODE_SENSE_MODE_SUB_PAGE_CODE_REPORT_ALL_MODE_PAGES : { + for ( i = ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_VENDOR_SPEC; i < ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_REPORT_ALL_MODE_PAGES; i++ ) { + len += iscsi_scsi_emu_primary_mode_sense_page( image, scsi_task, ((mode_sense_mode_page_pkt != NULL) ? (iscsi_scsi_mode_sense_mode_page_data_packet *) (((uint8_t *) mode_sense_mode_page_pkt) + len) : NULL), pc, i, ISCSI_SCSI_MODE_SENSE_MODE_SUB_PAGE_CODE_REPORT_ALL_MODE_PAGES ); + } + + break; + } + case ISCSI_SCSI_MODE_SENSE_MODE_SUB_PAGE_CODE_REPORT_ALL_MODE_SUB_PAGES : { + for ( i = ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_VENDOR_SPEC; i < ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_REPORT_ALL_MODE_PAGES; i++ ) { + len += iscsi_scsi_emu_primary_mode_sense_page( image, scsi_task, ((mode_sense_mode_page_pkt != NULL) ? (iscsi_scsi_mode_sense_mode_page_data_packet *) (((uint8_t *) mode_sense_mode_page_pkt) + len) : NULL), pc, i, ISCSI_SCSI_MODE_SENSE_MODE_SUB_PAGE_CODE_REPORT_ALL_MODE_PAGES ); + } + + for ( i = ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_VENDOR_SPEC; i < ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_REPORT_ALL_MODE_PAGES; i++ ) { + len += iscsi_scsi_emu_primary_mode_sense_page( image, scsi_task, ((mode_sense_mode_page_pkt != NULL) ? (iscsi_scsi_mode_sense_mode_page_data_packet *) (((uint8_t *) mode_sense_mode_page_pkt) + len) : NULL), pc, i, ISCSI_SCSI_MODE_SENSE_MODE_SUB_PAGE_CODE_REPORT_ALL_MODE_SUB_PAGES ); + } + + break; + } + default : { + break; + } + } + + break; + } + default : { + break; + } + } + + return len; +} + +/** * @brief Executes a mode sense operation on a DNBD3 image. * * This function also sets the SCSI * status result code accordingly. * - * @param[in] image Pointer to DNBD3 image to sense. - * May NOT be NULL, so be careful. + * @param[in] image Pointer to DNBD3 image to get + * the mode sense data from. May + * NOT be NULL, so be careful. * @param[in] scsi_task Pointer to iSCSI SCSI task - * responsible for this sense task. - * NULL is NOT allowed here, take - * caution. - * @param[in] cdb_mode_sense Pointer to Command Descriptor - * Block (CDB) and may NOT be NULL, be - * careful. - * @param[in] mode_sense_parameter_data_pkt Pointer to mode sense parameter - * data packet to fill the mode sense - * data with. If this is NULL, only the - * length of sense data is calculated. - * @param[in] len Length of sense result buffer - * in bytes. - * @param[in] dbd Disable Block Descriptors (DBD). - * @param[in] llba Long LBA Accepted (LLBAA). + * responsible for this mode sense + * task. NULL is NOT allowed here, + * take caution. + * @param[in] mode_sense_6_parameter_hdr_data_pkt Pointer to mode sense parameter + * header data packet to fill the + * mode sense data with. If this is + * NULL, only the length of sense + * data is calculated. + * @param[in] hdr_len Length of parameter header in bytes. + * @param[in] block_desc_len Length of LBA parameter block + * descriptor in bytes. + * @param[in] long_lba Long Logical Block Address (LONG_LBA) bit. * @param[in] pc Page control (PC). * @param[in] page_code Page code. * @param[in] sub_page_code Sub page code. @@ -6159,11 +6520,57 @@ static int iscsi_scsi_emu_primary_report_luns(iscsi_scsi_lun *lun, iscsi_scsi_re * operation, a negative error code * otherwise. */ -static int iscsi_scsi_emu_primary_mode_sense(dnbd3_image_t *image, iscsi_scsi_task *scsi_task, const iscsi_scsi_cdb_mode_sense_6 *cdb_mode_sense, iscsi_scsi_mode_sense_parameter_data_packet *mode_sense_parameter_data_pkt, const uint len, const int dbd, const int llba, const uint pc, const uint page_code, const uint sub_page_code) +static int iscsi_scsi_emu_primary_mode_sense(dnbd3_image_t *image, iscsi_scsi_task *scsi_task, iscsi_scsi_mode_sense_6_parameter_header_data_packet *mode_sense_6_parameter_hdr_data_pkt, const uint hdr_len, const uint block_desc_len, const uint long_lba, const uint pc, const uint page_code, const uint sub_page_code) { - // TODO: Implement SCSI emulation for DNBD3 image. + iscsi_scsi_mode_sense_mode_page_data_packet *mode_sense_mode_page_pkt = (iscsi_scsi_mode_sense_mode_page_data_packet *) ((mode_sense_6_parameter_hdr_data_pkt != NULL) ? (((uint8_t *) mode_sense_6_parameter_hdr_data_pkt) + hdr_len + block_desc_len) : NULL); + const int page_len = iscsi_scsi_emu_primary_mode_sense_page( image, scsi_task, mode_sense_mode_page_pkt, pc, page_code, sub_page_code ); - return 0; + if ( page_len < 0 ) + return -1; + + const uint alloc_len = (hdr_len + block_desc_len + page_len); + + if ( mode_sense_6_parameter_hdr_data_pkt == NULL ) + return alloc_len; + + if ( hdr_len == sizeof(struct iscsi_scsi_mode_sense_6_parameter_header_data_packet) ) { + mode_sense_6_parameter_hdr_data_pkt->mode_data_len = (uint8_t) (alloc_len - sizeof(uint8_t)); + mode_sense_6_parameter_hdr_data_pkt->medium_type = 0U; + mode_sense_6_parameter_hdr_data_pkt->flags = 0; + mode_sense_6_parameter_hdr_data_pkt->block_desc_len = (uint8_t) block_desc_len; + } else { + iscsi_scsi_mode_sense_10_parameter_header_data_packet *mode_sense_10_parameter_hdr_data_pkt = (iscsi_scsi_mode_sense_10_parameter_header_data_packet *) mode_sense_6_parameter_hdr_data_pkt; + + iscsi_put_be16( (uint8_t *) &mode_sense_10_parameter_hdr_data_pkt->mode_data_len, (uint16_t) (alloc_len - sizeof(uint16_t)) ); + mode_sense_10_parameter_hdr_data_pkt->medium_type = 0U; + mode_sense_10_parameter_hdr_data_pkt->flags = 0; + mode_sense_10_parameter_hdr_data_pkt->long_lba = (uint8_t) long_lba; + mode_sense_10_parameter_hdr_data_pkt->reserved = 0U; + iscsi_put_be16( (uint8_t *) &mode_sense_10_parameter_hdr_data_pkt->block_desc_len, (uint16_t) block_desc_len ); + } + + const uint64_t num_blocks = iscsi_scsi_emu_block_get_count( image ); + const uint32_t block_size = iscsi_scsi_emu_block_get_size( image ); + + if ( block_desc_len == sizeof(struct iscsi_scsi_mode_sense_lba_parameter_block_desc_data_packet) ) { + iscsi_scsi_mode_sense_lba_parameter_block_desc_data_packet *lba_parameter_block_desc = (iscsi_scsi_mode_sense_lba_parameter_block_desc_data_packet *) (((uint8_t *) mode_sense_6_parameter_hdr_data_pkt) + hdr_len); + + if ( num_blocks > 0xFFFFFFFFULL ) + lba_parameter_block_desc->num_blocks = 0xFFFFFFFFUL; // Minus one does not require endianess conversion + else + iscsi_put_be32( (uint8_t *) &lba_parameter_block_desc->num_blocks, (uint32_t) num_blocks ); + + lba_parameter_block_desc->reserved = 0U; + iscsi_put_be24( (uint8_t *) &lba_parameter_block_desc->block_len, block_size ); + } else if ( block_desc_len == sizeof(struct iscsi_scsi_mode_sense_long_lba_parameter_block_desc_data_packet) ) { + iscsi_scsi_mode_sense_long_lba_parameter_block_desc_data_packet *long_lba_parameter_block_desc = (iscsi_scsi_mode_sense_long_lba_parameter_block_desc_data_packet *) (((uint8_t *) mode_sense_6_parameter_hdr_data_pkt) + hdr_len); + + iscsi_put_be64( (uint8_t *) &long_lba_parameter_block_desc->num_blocks, num_blocks ); + long_lba_parameter_block_desc->reserved = 0UL; + iscsi_put_be32( (uint8_t *) &long_lba_parameter_block_desc->block_len, block_size ); + } + + return alloc_len; } /** @@ -6206,7 +6613,7 @@ static int iscsi_scsi_emu_primary_process(iscsi_scsi_task *scsi_task) std_inquiry_data_pkt = (iscsi_scsi_std_inquiry_data_packet *) malloc( len ); if ( std_inquiry_data_pkt == NULL ) { - iscsi_scsi_task_status_set( scsi_task, ISCSI_SCSI_STATUS_CHECK_COND, ISCSI_SCSI_SENSE_KEY_HARDWARE_ERR, ISCSI_SCSI_ASC_WARNING, ISCSI_SCSI_ASCQ_POWER_LOSS_EXPECTED ); + iscsi_scsi_task_status_set( scsi_task, ISCSI_SCSI_STATUS_CHECK_COND, ISCSI_SCSI_SENSE_KEY_NOT_READY, ISCSI_SCSI_ASC_LOGICAL_UNIT_NOT_READY, ISCSI_SCSI_ASCQ_BECOMING_READY ); break; } @@ -6249,7 +6656,7 @@ static int iscsi_scsi_emu_primary_process(iscsi_scsi_task *scsi_task) report_luns_parameter_data_pkt = (iscsi_scsi_report_luns_parameter_data_lun_list_packet *) malloc( len ); if ( report_luns_parameter_data_pkt == NULL ) { - iscsi_scsi_task_status_set( scsi_task, ISCSI_SCSI_STATUS_CHECK_COND, ISCSI_SCSI_SENSE_KEY_HARDWARE_ERR, ISCSI_SCSI_ASC_WARNING, ISCSI_SCSI_ASCQ_POWER_LOSS_EXPECTED ); + iscsi_scsi_task_status_set( scsi_task, ISCSI_SCSI_STATUS_CHECK_COND, ISCSI_SCSI_SENSE_KEY_NOT_READY, ISCSI_SCSI_ASC_LOGICAL_UNIT_NOT_READY, ISCSI_SCSI_ASCQ_BECOMING_READY ); break; } @@ -6342,30 +6749,30 @@ static int iscsi_scsi_emu_primary_process(iscsi_scsi_task *scsi_task) alloc_len = cdb_mode_sense_6->alloc_len; - const int dbd = (cdb_mode_sense_6->flags & ISCSI_SCSI_CDB_MODE_SENSE_6_FLAGS_DBD); - const uint pc = ISCSI_SCSI_CDB_MODE_SENSE_6_GET_PAGE_CONTROL(cdb_mode_sense_6->page_code_control); - const uint page = ISCSI_SCSI_CDB_MODE_SENSE_6_GET_PAGE_CODE(cdb_mode_sense_6->page_code_control); - const uint sub_page = cdb_mode_sense_6->sub_page_code; + const uint block_desc_len = ((cdb_mode_sense_6->flags & ISCSI_SCSI_CDB_MODE_SENSE_6_FLAGS_DBD) == 0) ? sizeof(struct iscsi_scsi_mode_sense_lba_parameter_block_desc_data_packet) : 0U; + const uint pc = ISCSI_SCSI_CDB_MODE_SENSE_6_GET_PAGE_CONTROL(cdb_mode_sense_6->page_code_control); + const uint page = ISCSI_SCSI_CDB_MODE_SENSE_6_GET_PAGE_CODE(cdb_mode_sense_6->page_code_control); + const uint sub_page = cdb_mode_sense_6->sub_page_code; - rc = iscsi_scsi_emu_primary_mode_sense( lun->image, scsi_task, cdb_mode_sense_6, NULL, sizeof(struct iscsi_scsi_cdb_mode_sense_6), dbd, 0U, pc, page, sub_page ); + rc = iscsi_scsi_emu_primary_mode_sense( lun->image, scsi_task, NULL, sizeof(struct iscsi_scsi_mode_sense_6_parameter_header_data_packet), block_desc_len, 0U, pc, page, sub_page ); if ( rc < 0 ) break; len = rc; - iscsi_scsi_mode_sense_parameter_data_packet *mode_sense_parameter_data_pkt = (iscsi_scsi_mode_sense_parameter_data_packet *) malloc( len ); + iscsi_scsi_mode_sense_6_parameter_header_data_packet *mode_sense_6_parameter_hdr_data_pkt = (iscsi_scsi_mode_sense_6_parameter_header_data_packet *) malloc( len ); - if ( mode_sense_parameter_data_pkt == NULL ) { - iscsi_scsi_task_status_set( scsi_task, ISCSI_SCSI_STATUS_CHECK_COND, ISCSI_SCSI_SENSE_KEY_HARDWARE_ERR, ISCSI_SCSI_ASC_WARNING, ISCSI_SCSI_ASCQ_POWER_LOSS_EXPECTED ); + if ( mode_sense_6_parameter_hdr_data_pkt == NULL ) { + iscsi_scsi_task_status_set( scsi_task, ISCSI_SCSI_STATUS_CHECK_COND, ISCSI_SCSI_SENSE_KEY_NOT_READY, ISCSI_SCSI_ASC_LOGICAL_UNIT_NOT_READY, ISCSI_SCSI_ASCQ_BECOMING_READY ); break; } - rc = iscsi_scsi_emu_primary_mode_sense( lun->image, scsi_task, cdb_mode_sense_6, mode_sense_parameter_data_pkt, sizeof(struct iscsi_scsi_cdb_mode_sense_6), dbd, 0U, pc, page, sub_page ); + rc = iscsi_scsi_emu_primary_mode_sense( lun->image, scsi_task, mode_sense_6_parameter_hdr_data_pkt, sizeof(struct iscsi_scsi_mode_sense_6_parameter_header_data_packet), block_desc_len, 0U, pc, page, sub_page ); if ( rc < 0 ) { - free( mode_sense_parameter_data_pkt ); + free( mode_sense_6_parameter_hdr_data_pkt ); iscsi_scsi_task_status_set( scsi_task, ISCSI_SCSI_STATUS_CHECK_COND, ISCSI_SCSI_SENSE_KEY_ILLEGAL_REQ, ISCSI_SCSI_ASC_INVALID_FIELD_IN_CDB, ISCSI_SCSI_ASCQ_CAUSE_NOT_REPORTABLE ); break; @@ -6375,7 +6782,7 @@ static int iscsi_scsi_emu_primary_process(iscsi_scsi_task *scsi_task) if ( len > alloc_len ) len = alloc_len; - scsi_task->buf = (uint8_t *) mode_sense_parameter_data_pkt; + scsi_task->buf = (uint8_t *) mode_sense_6_parameter_hdr_data_pkt; rc = len; } @@ -6394,31 +6801,31 @@ static int iscsi_scsi_emu_primary_process(iscsi_scsi_task *scsi_task) alloc_len = iscsi_get_be16(cdb_mode_sense_10->alloc_len); - const int dbd10 = (cdb_mode_sense_10->flags & ISCSI_SCSI_CDB_MODE_SENSE_10_FLAGS_DBD); - const int llba = (cdb_mode_sense_10->flags & ISCSI_SCSI_CDB_MODE_SENSE_10_FLAGS_LLBAA); - const uint pc10 = ISCSI_SCSI_CDB_MODE_SENSE_10_GET_PAGE_CONTROL(cdb_mode_sense_10->page_code_control); - const uint page10 = ISCSI_SCSI_CDB_MODE_SENSE_10_GET_PAGE_CODE(cdb_mode_sense_10->page_code_control); - const uint sub_page10 = cdb_mode_sense_10->sub_page_code; + const uint long_lba = (((cdb_mode_sense_10->flags & ISCSI_SCSI_CDB_MODE_SENSE_10_FLAGS_LLBAA) != 0) ? ISCSI_SCSI_MODE_SENSE_10_PARAM_HDR_DATA_LONGLBA : 0U); + const uint block_desc_len = (((cdb_mode_sense_10->flags & ISCSI_SCSI_CDB_MODE_SENSE_10_FLAGS_DBD) == 0) ? ((long_lba != 0) ? sizeof(struct iscsi_scsi_mode_sense_long_lba_parameter_block_desc_data_packet) : sizeof(struct iscsi_scsi_mode_sense_lba_parameter_block_desc_data_packet)) : 0U); + const uint pc10 = ISCSI_SCSI_CDB_MODE_SENSE_10_GET_PAGE_CONTROL(cdb_mode_sense_10->page_code_control); + const uint page10 = ISCSI_SCSI_CDB_MODE_SENSE_10_GET_PAGE_CODE(cdb_mode_sense_10->page_code_control); + const uint sub_page10 = cdb_mode_sense_10->sub_page_code; - rc = iscsi_scsi_emu_primary_mode_sense( lun->image, scsi_task, (iscsi_scsi_cdb_mode_sense_6 *) cdb_mode_sense_10, NULL, sizeof(struct iscsi_scsi_cdb_mode_sense_10), dbd10, llba, pc10, page10, sub_page10 ); + rc = iscsi_scsi_emu_primary_mode_sense( lun->image, scsi_task, NULL, sizeof(struct iscsi_scsi_mode_sense_10_parameter_header_data_packet), block_desc_len, long_lba, pc10, page10, sub_page10 ); if ( rc < 0 ) break; len = rc; - iscsi_scsi_mode_sense_parameter_data_packet *mode_sense_parameter_data_pkt = (iscsi_scsi_mode_sense_parameter_data_packet *) malloc( len ); + iscsi_scsi_mode_sense_10_parameter_header_data_packet *mode_sense_10_parameter_hdr_data_pkt = (iscsi_scsi_mode_sense_10_parameter_header_data_packet *) malloc( len ); - if ( mode_sense_parameter_data_pkt == NULL ) { - iscsi_scsi_task_status_set( scsi_task, ISCSI_SCSI_STATUS_CHECK_COND, ISCSI_SCSI_SENSE_KEY_HARDWARE_ERR, ISCSI_SCSI_ASC_WARNING, ISCSI_SCSI_ASCQ_POWER_LOSS_EXPECTED ); + if ( mode_sense_10_parameter_hdr_data_pkt == NULL ) { + iscsi_scsi_task_status_set( scsi_task, ISCSI_SCSI_STATUS_CHECK_COND, ISCSI_SCSI_SENSE_KEY_NOT_READY, ISCSI_SCSI_ASC_LOGICAL_UNIT_NOT_READY, ISCSI_SCSI_ASCQ_BECOMING_READY ); break; } - rc = iscsi_scsi_emu_primary_mode_sense( lun->image, scsi_task, (iscsi_scsi_cdb_mode_sense_6 *) cdb_mode_sense_10, mode_sense_parameter_data_pkt, sizeof(struct iscsi_scsi_cdb_mode_sense_10), dbd10, llba, pc10, page10, sub_page10 ); + rc = iscsi_scsi_emu_primary_mode_sense( lun->image, scsi_task, (iscsi_scsi_mode_sense_6_parameter_header_data_packet *) mode_sense_10_parameter_hdr_data_pkt, sizeof(struct iscsi_scsi_mode_sense_10_parameter_header_data_packet), block_desc_len, long_lba, pc10, page10, sub_page10 ); if ( rc < 0 ) { - free( mode_sense_parameter_data_pkt ); + free( mode_sense_10_parameter_hdr_data_pkt ); iscsi_scsi_task_status_set( scsi_task, ISCSI_SCSI_STATUS_CHECK_COND, ISCSI_SCSI_SENSE_KEY_ILLEGAL_REQ, ISCSI_SCSI_ASC_INVALID_FIELD_IN_CDB, ISCSI_SCSI_ASCQ_CAUSE_NOT_REPORTABLE ); break; @@ -6428,7 +6835,7 @@ static int iscsi_scsi_emu_primary_process(iscsi_scsi_task *scsi_task) if ( len > alloc_len ) len = alloc_len; - scsi_task->buf = (uint8_t *) mode_sense_parameter_data_pkt; + scsi_task->buf = (uint8_t *) mode_sense_10_parameter_hdr_data_pkt; rc = len; } @@ -6458,7 +6865,7 @@ static int iscsi_scsi_emu_primary_process(iscsi_scsi_task *scsi_task) iscsi_scsi_sense_data_check_cond_packet *sense_data = (iscsi_scsi_sense_data_check_cond_packet *) malloc( len ); if ( sense_data == NULL ) { - iscsi_scsi_task_status_set( scsi_task, ISCSI_SCSI_STATUS_CHECK_COND, ISCSI_SCSI_SENSE_KEY_HARDWARE_ERR, ISCSI_SCSI_ASC_WARNING, ISCSI_SCSI_ASCQ_POWER_LOSS_EXPECTED ); + iscsi_scsi_task_status_set( scsi_task, ISCSI_SCSI_STATUS_CHECK_COND, ISCSI_SCSI_SENSE_KEY_NOT_READY, ISCSI_SCSI_ASC_LOGICAL_UNIT_NOT_READY, ISCSI_SCSI_ASCQ_BECOMING_READY ); break; } @@ -6516,7 +6923,7 @@ static int iscsi_scsi_emu_primary_process(iscsi_scsi_task *scsi_task) iscsi_scsi_pr_reserve_out_parameter_list_packet *pr_reserve_out_parameter_list = (iscsi_scsi_pr_reserve_out_parameter_list_packet *) malloc( len ); if ( pr_reserve_out_parameter_list == NULL ) { - iscsi_scsi_task_status_set( scsi_task, ISCSI_SCSI_STATUS_CHECK_COND, ISCSI_SCSI_SENSE_KEY_HARDWARE_ERR, ISCSI_SCSI_ASC_WARNING, ISCSI_SCSI_ASCQ_POWER_LOSS_EXPECTED ); + iscsi_scsi_task_status_set( scsi_task, ISCSI_SCSI_STATUS_CHECK_COND, ISCSI_SCSI_SENSE_KEY_NOT_READY, ISCSI_SCSI_ASC_LOGICAL_UNIT_NOT_READY, ISCSI_SCSI_ASCQ_BECOMING_READY ); break; } @@ -6551,7 +6958,7 @@ static int iscsi_scsi_emu_primary_process(iscsi_scsi_task *scsi_task) iscsi_scsi_pr_reserve_in_parameter_data_packet *pr_reserve_in_parameter_data = (iscsi_scsi_pr_reserve_in_parameter_data_packet *) malloc( len ); if ( pr_reserve_in_parameter_data == NULL ) { - iscsi_scsi_task_status_set( scsi_task, ISCSI_SCSI_STATUS_CHECK_COND, ISCSI_SCSI_SENSE_KEY_HARDWARE_ERR, ISCSI_SCSI_ASC_WARNING, ISCSI_SCSI_ASCQ_POWER_LOSS_EXPECTED ); + iscsi_scsi_task_status_set( scsi_task, ISCSI_SCSI_STATUS_CHECK_COND, ISCSI_SCSI_SENSE_KEY_NOT_READY, ISCSI_SCSI_ASC_LOGICAL_UNIT_NOT_READY, ISCSI_SCSI_ASCQ_BECOMING_READY ); break; } @@ -9521,7 +9928,7 @@ static int iscsi_connection_handle_reject(iscsi_connection *conn, iscsi_pdu *pdu reject_pkt->flags |= -0x80; reject_pkt->reason = (uint8_t) reason_code; iscsi_put_be24( (uint8_t *) &reject_pkt->ds_len, ds_len ); - reject_pkt->tag = 0xFFFFFFFFUL; + reject_pkt->tag = 0xFFFFFFFFUL; // Minus one does not require endianess conversion iscsi_put_be32( (uint8_t *) &reject_pkt->stat_sn, conn->stat_sn++ ); if ( conn->session != NULL ) { @@ -10465,7 +10872,7 @@ static int iscsi_connection_pdu_data_handle_nop_out(iscsi_connection *conn, iscs nop_in_pkt->flags = -0x80; iscsi_put_be24( (uint8_t *) &nop_in_pkt->ds_len, ds_len ); iscsi_put_be64( (uint8_t *) &nop_in_pkt->lun, lun ); - nop_in_pkt->target_xfer_tag = 0xFFFFFFFFUL; + nop_in_pkt->target_xfer_tag = 0xFFFFFFFFUL; // Minus one does not require endianess conversion iscsi_put_be32( (uint8_t *) &nop_in_pkt->init_task_tag, init_task_tag ); iscsi_put_be32( (uint8_t *) &nop_in_pkt->stat_sn, conn->stat_sn++ ); @@ -11472,7 +11879,7 @@ static int iscsi_connection_pdu_data_handle_text_req(iscsi_connection *conn, isc text_response_pkt->init_task_tag = text_req_pkt->init_task_tag; // Copying over doesn't change endianess. if ( (text_req_pkt->flags & ISCSI_TEXT_REQ_FLAGS_FINAL) != 0 ) { - text_response_pkt->target_xfer_tag = 0xFFFFFFFFUL; + text_response_pkt->target_xfer_tag = 0xFFFFFFFFUL; // Minus one does not require endianess conversion conn->session->current_text_init_task_tag = 0xFFFFFFFFUL; } else { diff --git a/src/server/iscsi.h b/src/server/iscsi.h index bd6e0b7..40f6438 100644 --- a/src/server/iscsi.h +++ b/src/server/iscsi.h @@ -48,25 +48,26 @@ #define iscsi_get_be32(x) (x) #define iscsi_get_be64(x) (x) -static inline void iscsi_put_be16(uint8_t *data, const uint16_t val) +static inline void iscsi_put_be16(uint8_t *data, const uint16_t value) { - (*(uint16_t *) data) = val; + (*(uint16_t *) data) = value; } -static inline void iscsi_put_be24(uint8_t *data, const uint32_t val) +static inline void iscsi_put_be24(uint8_t *data, const uint32_t value) { - (*(uint16_t *) data) = (uint16_t) (val >> 8U); - data[2] = (uint8_t) val; + data--; + + (*(uint32_t *) data) = (((uint32_t ) *data << 24UL) | (value & 0xFFFFFFUL)); } -static inline void iscsi_put_be32(uint8_t *data, const uint32_t val) +static inline void iscsi_put_be32(uint8_t *data, const uint32_t value) { - (*(uint32_t *) *data) = val; + (*(uint32_t *) data) = value; } -static inline void iscsi_put_be64(uint8_t *data, const uint64_t val) +static inline void iscsi_put_be64(uint8_t *data, const uint64_t value) { - (*(uint64_t *) data) = val; + (*(uint64_t *) data) = value; } #elif defined(__LITTLE_ENDIAN__) || (defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && __BYTE_ORDER == __LITTLE_ENDIAN) || (defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) || defined(__i386__) || defined(__i386) || defined(__x86_64) #if defined(__GNUC__) && (defined(__x86_64__) || defined(__i386__)) @@ -96,7 +97,7 @@ static inline void iscsi_put_be64(uint8_t *data, const uint64_t val) #define iscsi_get_be32(x) (__builtin_bswap32(x)) #define iscsi_get_be64(x) (__builtin_bswap64(x)) #elif defined(_MSC_VER) -// MVSC +// MSVC #define iscsi_get_be16(x) (_byteswap_ushort(x)) #define iscsi_get_be24(x) (iscsi_get_be32((*(uint32_t *) ((uint8_t *) x - 1))) & 0xFFFFFFUL) #define iscsi_get_be32(x) (_byteswap_ulong(x)) @@ -114,37 +115,27 @@ static inline void iscsi_put_be64(uint8_t *data, const uint64_t val) #define iscsi_get_be32(x) ((((uint32_t) (x) & 0xFFUL) << 24UL) | (((uint32_t) (x) & 0xFF00UL) << 8UL) | (((uint32_t) (x) & 0xFF0000UL) >> 8UL) | (((uint32_t) (x) >> 24UL))) #define iscsi_get_be64(x) ((uint64_t)((((x) & 0xFFULL) << 56ULL) | (((x) & 0xFF00ULL) << 40ULL) | (((x) & 0xFF0000ull) << 24ULL) | (((x) & 0xFF000000ULL) << 8ULL) | (((x) & 0xFF00000000ULL) >> 8ULL) | (((x) & 0xFF0000000000ULL) >> 24ULL) | (((x) & 0xFF000000000000ULL) >> 40ULL) | (((x) & 0xFF00000000000000ULL) >> 56ULL))) #endif -static inline void iscsi_put_be16(uint8_t *data, const uint16_t val) + +static inline void iscsi_put_be16(uint8_t *data, const uint16_t value) { - data[0] = (uint8_t) (val >> 8U); - data[1] = (uint8_t) val; + (*(uint16_t *) data) = iscsi_get_be16(value); } -static inline void iscsi_put_be24(uint8_t *data, const uint32_t val) +static inline void iscsi_put_be24(uint8_t *data, const uint32_t value) { - data[0] = (uint8_t) (val >> 16UL); - data[1] = (uint8_t) (val >> 8UL); - data[2] = (uint8_t) val; + data--; + + (*(uint32_t *) data) = ((uint32_t ) *data | (iscsi_get_be32(value) & 0xFFFFFF00UL)); } -static inline void iscsi_put_be32(uint8_t *data, const uint32_t val) +static inline void iscsi_put_be32(uint8_t *data, const uint32_t value) { - data[0] = (uint8_t) (val >> 24UL); - data[1] = (uint8_t) (val >> 16UL); - data[2] = (uint8_t) (val >> 8UL); - data[3] = (uint8_t) val; + (*(uint32_t *) data) = iscsi_get_be32(value); } -static inline void iscsi_put_be64(uint8_t *data, const uint64_t val) +static inline void iscsi_put_be64(uint8_t *data, const uint64_t value) { - data[0] = (uint8_t) (val >> 56ULL); - data[1] = (uint8_t) (val >> 48ULL); - data[2] = (uint8_t) (val >> 40ULL); - data[3] = (uint8_t) (val >> 32ULL); - data[4] = (uint8_t) (val >> 24ULL); - data[5] = (uint8_t) (val >> 16ULL); - data[6] = (uint8_t) (val >> 8ULL); - data[7] = (uint8_t) val; + (*(uint64_t *) data) = iscsi_get_be64(value); } #else #error "Unknown CPU endianness" @@ -1181,34 +1172,46 @@ typedef struct __attribute__((packed)) iscsi_scsi_cdb_mode_select_10 { /// iSCSI SCSI Command Descriptor Block (CDB) for MODE SENSE(6) command page code: First bit of the six bits. -#define ISCSI_SCSI_CDB_MODE_SENSE_6_PAGE_CODE_FIRST_BIT 0 +#define ISCSI_SCSI_CDB_MODE_SENSE_6_PAGE_CODE_FIRST_BIT 0 /// iSCSI SCSI Command Descriptor Block (CDB) for MODE SENSE(6) command page code: Last bit of the six bits. -#define ISCSI_SCSI_CDB_MODE_SENSE_6_PAGE_CODE_LAST_BIT ((ISCSI_SCSI_CDB_MODE_SENSE_6_PAGE_CODE_FIRST_BIT) + 6 - 1) +#define ISCSI_SCSI_CDB_MODE_SENSE_6_PAGE_CODE_LAST_BIT ((ISCSI_SCSI_CDB_MODE_SENSE_6_PAGE_CODE_FIRST_BIT) + 6 - 1) /// iSCSI SCSI Command Descriptor Block (CDB) for MODE SENSE(6) command page code: Bit mask. -#define ISCSI_SCSI_CDB_MODE_SENSE_6_PAGE_CODE_MASK (ISCSI_BITS_GET_MASK(ISCSI_SCSI_CDB_MODE_SENSE_6_PAGE_CODE_FIRST_BIT, ISCSI_SCSI_CDB_MODE_SENSE_6_PAGE_CODE_LAST_BIT)) +#define ISCSI_SCSI_CDB_MODE_SENSE_6_PAGE_CODE_MASK (ISCSI_BITS_GET_MASK(ISCSI_SCSI_CDB_MODE_SENSE_6_PAGE_CODE_FIRST_BIT, ISCSI_SCSI_CDB_MODE_SENSE_6_PAGE_CODE_LAST_BIT)) /// iSCSI SCSI Command Descriptor Block (CDB) for MODE SENSE(6) command page code: Extracts the page code bits. -#define ISCSI_SCSI_CDB_MODE_SENSE_6_GET_PAGE_CODE(x) (ISCSI_BITS_GET((x), ISCSI_SCSI_CDB_MODE_SENSE_6_PAGE_CODE_FIRST_BIT, ISCSI_SCSI_CDB_MODE_SENSE_6_PAGE_CODE_LAST_BIT)) +#define ISCSI_SCSI_CDB_MODE_SENSE_6_GET_PAGE_CODE(x) (ISCSI_BITS_GET((x), ISCSI_SCSI_CDB_MODE_SENSE_6_PAGE_CODE_FIRST_BIT, ISCSI_SCSI_CDB_MODE_SENSE_6_PAGE_CODE_LAST_BIT)) /// iSCSI SCSI Command Descriptor Block (CDB) for MODE SENSE(6) command page code: Stores into the page code bits. -#define ISCSI_SCSI_CDB_MODE_SENSE_6_PUT_PAGE_CODE(x) (ISCSI_BITS_PUT((x), ISCSI_SCSI_CDB_MODE_SENSE_6_PAGE_CODE_FIRST_BIT, ISCSI_SCSI_CDB_MODE_SENSE_6_PAGE_CODE_LAST_BIT)) +#define ISCSI_SCSI_CDB_MODE_SENSE_6_PUT_PAGE_CODE(x) (ISCSI_BITS_PUT((x), ISCSI_SCSI_CDB_MODE_SENSE_6_PAGE_CODE_FIRST_BIT, ISCSI_SCSI_CDB_MODE_SENSE_6_PAGE_CODE_LAST_BIT)) + +/// iSCSI SCSI Command Descriptor Block (CDB) for MODE SENSE(6) command page control: Current values. +#define ISCSI_SCSI_CDB_MODE_SENSE_6_PAGE_CONTROL_CURRENT_VALUES 0x0 + +/// iSCSI SCSI Command Descriptor Block (CDB) for MODE SENSE(6) command page control: Changeable values. +#define ISCSI_SCSI_CDB_MODE_SENSE_6_PAGE_CONTROL_CHG_VALUES 0x1 + +/// iSCSI SCSI Command Descriptor Block (CDB) for MODE SENSE(6) command page control: Default values. +#define ISCSI_SCSI_CDB_MODE_SENSE_6_PAGE_CONTROL_DEFAULT_VALUES 0x2 + +/// iSCSI SCSI Command Descriptor Block (CDB) for MODE SENSE(6) command page control: Saved values. +#define ISCSI_SCSI_CDB_MODE_SENSE_6_PAGE_CONTROL_SAVED_VALUES 0x3 /// iSCSI SCSI Command Descriptor Block (CDB) for MODE SENSE(6) command page control: First bit of the two bits. -#define ISCSI_SCSI_CDB_MODE_SENSE_6_PAGE_CONTROL_FIRST_BIT 6 +#define ISCSI_SCSI_CDB_MODE_SENSE_6_PAGE_CONTROL_FIRST_BIT 6 /// iSCSI SCSI Command Descriptor Block (CDB) for MODE SENSE(6) command page control: Last bit of the two bits. -#define ISCSI_SCSI_CDB_MODE_SENSE_6_PAGE_CONTROL_LAST_BIT ((ISCSI_SCSI_CDB_MODE_SENSE_6_PAGE_CONTROL_FIRST_BIT) + 2 - 1) +#define ISCSI_SCSI_CDB_MODE_SENSE_6_PAGE_CONTROL_LAST_BIT ((ISCSI_SCSI_CDB_MODE_SENSE_6_PAGE_CONTROL_FIRST_BIT) + 2 - 1) /// iSCSI SCSI Command Descriptor Block (CDB) for MODE SENSE(6) command page control: Bit mask. -#define ISCSI_SCSI_CDB_MODE_SENSE_6_PAGE_CONTROL_MASK (ISCSI_BITS_GET_MASK(ISCSI_SCSI_CDB_MODE_SENSE_6_PAGE_CONTROL_FIRST_BIT, ISCSI_SCSI_CDB_MODE_SENSE_6_PAGE_CONTROL_LAST_BIT)) +#define ISCSI_SCSI_CDB_MODE_SENSE_6_PAGE_CONTROL_MASK (ISCSI_BITS_GET_MASK(ISCSI_SCSI_CDB_MODE_SENSE_6_PAGE_CONTROL_FIRST_BIT, ISCSI_SCSI_CDB_MODE_SENSE_6_PAGE_CONTROL_LAST_BIT)) /// iSCSI SCSI Command Descriptor Block (CDB) for MODE SENSE(6) command page control: Extracts the page control bits. -#define ISCSI_SCSI_CDB_MODE_SENSE_6_GET_PAGE_CONTROL(x) (ISCSI_BITS_GET((x), ISCSI_SCSI_CDB_MODE_SENSE_6_PAGE_CONTROL_FIRST_BIT, ISCSI_SCSI_CDB_MODE_SENSE_6_PAGE_CONTROL_LAST_BIT)) +#define ISCSI_SCSI_CDB_MODE_SENSE_6_GET_PAGE_CONTROL(x) (ISCSI_BITS_GET((x), ISCSI_SCSI_CDB_MODE_SENSE_6_PAGE_CONTROL_FIRST_BIT, ISCSI_SCSI_CDB_MODE_SENSE_6_PAGE_CONTROL_LAST_BIT)) /// iSCSI SCSI Command Descriptor Block (CDB) for MODE SENSE(6) command page control: Stores into the page control bits. -#define ISCSI_SCSI_CDB_MODE_SENSE_6_PUT_PAGE_CONTROL(x) (ISCSI_BITS_PUT((x), ISCSI_SCSI_CDB_MODE_SENSE_6_PAGE_CONTROL_FIRST_BIT, ISCSI_SCSI_CDB_MODE_SENSE_6_PAGE_CONTROL_LAST_BIT)) +#define ISCSI_SCSI_CDB_MODE_SENSE_6_PUT_PAGE_CONTROL(x) (ISCSI_BITS_PUT((x), ISCSI_SCSI_CDB_MODE_SENSE_6_PAGE_CONTROL_FIRST_BIT, ISCSI_SCSI_CDB_MODE_SENSE_6_PAGE_CONTROL_LAST_BIT)) /** @@ -1245,34 +1248,46 @@ typedef struct __attribute__((packed)) iscsi_scsi_cdb_mode_sense_6 { /// iSCSI SCSI Command Descriptor Block (CDB) for MODE SENSE(10) command page code: First bit of the six bits. -#define ISCSI_SCSI_CDB_MODE_SENSE_10_PAGE_CODE_FIRST_BIT 0 +#define ISCSI_SCSI_CDB_MODE_SENSE_10_PAGE_CODE_FIRST_BIT 0 /// iSCSI SCSI Command Descriptor Block (CDB) for MODE SENSE(10) command page code: Last bit of the six bits. -#define ISCSI_SCSI_CDB_MODE_SENSE_10_PAGE_CODE_LAST_BIT ((ISCSI_SCSI_CDB_MODE_SENSE_10_PAGE_CODE_FIRST_BIT) + 6 - 1) +#define ISCSI_SCSI_CDB_MODE_SENSE_10_PAGE_CODE_LAST_BIT ((ISCSI_SCSI_CDB_MODE_SENSE_10_PAGE_CODE_FIRST_BIT) + 6 - 1) /// iSCSI SCSI Command Descriptor Block (CDB) for MODE SENSE(10) command page code: Bit mask. -#define ISCSI_SCSI_CDB_MODE_SENSE_10_PAGE_CODE_MASK (ISCSI_BITS_GET_MASK(ISCSI_SCSI_CDB_MODE_SENSE_10_PAGE_CODE_FIRST_BIT, ISCSI_SCSI_CDB_MODE_SENSE_10_PAGE_CODE_LAST_BIT)) +#define ISCSI_SCSI_CDB_MODE_SENSE_10_PAGE_CODE_MASK (ISCSI_BITS_GET_MASK(ISCSI_SCSI_CDB_MODE_SENSE_10_PAGE_CODE_FIRST_BIT, ISCSI_SCSI_CDB_MODE_SENSE_10_PAGE_CODE_LAST_BIT)) /// iSCSI SCSI Command Descriptor Block (CDB) for MODE SENSE(10) command page code: Extracts the page code bits. -#define ISCSI_SCSI_CDB_MODE_SENSE_10_GET_PAGE_CODE(x) (ISCSI_BITS_GET((x), ISCSI_SCSI_CDB_MODE_SENSE_10_PAGE_CODE_FIRST_BIT, ISCSI_SCSI_CDB_MODE_SENSE_10_PAGE_CODE_LAST_BIT)) +#define ISCSI_SCSI_CDB_MODE_SENSE_10_GET_PAGE_CODE(x) (ISCSI_BITS_GET((x), ISCSI_SCSI_CDB_MODE_SENSE_10_PAGE_CODE_FIRST_BIT, ISCSI_SCSI_CDB_MODE_SENSE_10_PAGE_CODE_LAST_BIT)) /// iSCSI SCSI Command Descriptor Block (CDB) for MODE SENSE(10) command page code: Stores into the page code bits. -#define ISCSI_SCSI_CDB_MODE_SENSE_10_PUT_PAGE_CODE(x) (ISCSI_BITS_PUT((x), ISCSI_SCSI_CDB_MODE_SENSE_10_PAGE_CODE_FIRST_BIT, ISCSI_SCSI_CDB_MODE_SENSE_10_PAGE_CODE_LAST_BIT)) +#define ISCSI_SCSI_CDB_MODE_SENSE_10_PUT_PAGE_CODE(x) (ISCSI_BITS_PUT((x), ISCSI_SCSI_CDB_MODE_SENSE_10_PAGE_CODE_FIRST_BIT, ISCSI_SCSI_CDB_MODE_SENSE_10_PAGE_CODE_LAST_BIT)) + +/// iSCSI SCSI Command Descriptor Block (CDB) for MODE SENSE(10) command page control: Current values. +#define ISCSI_SCSI_CDB_MODE_SENSE_10_PAGE_CONTROL_CURRENT_VALUES 0x0 + +/// iSCSI SCSI Command Descriptor Block (CDB) for MODE SENSE(10) command page control: Changeable values. +#define ISCSI_SCSI_CDB_MODE_SENSE_10_PAGE_CONTROL_CHG_VALUES 0x1 + +/// iSCSI SCSI Command Descriptor Block (CDB) for MODE SENSE(10) command page control: Default values. +#define ISCSI_SCSI_CDB_MODE_SENSE_10_PAGE_CONTROL_DEFAULT_VALUES 0x2 + +/// iSCSI SCSI Command Descriptor Block (CDB) for MODE SENSE(10) command page control: Saved values. +#define ISCSI_SCSI_CDB_MODE_SENSE_10_PAGE_CONTROL_SAVED_VALUES 0x3 /// iSCSI SCSI Command Descriptor Block (CDB) for MODE SENSE(10) command page control: First bit of the two bits. -#define ISCSI_SCSI_CDB_MODE_SENSE_10_PAGE_CONTROL_FIRST_BIT 6 +#define ISCSI_SCSI_CDB_MODE_SENSE_10_PAGE_CONTROL_FIRST_BIT 6 /// iSCSI SCSI Command Descriptor Block (CDB) for MODE SENSE(10) command page control: Last bit of the two bits. -#define ISCSI_SCSI_CDB_MODE_SENSE_10_PAGE_CONTROL_LAST_BIT ((ISCSI_SCSI_CDB_MODE_SENSE_10_PAGE_CONTROL_FIRST_BIT) + 2 - 1) +#define ISCSI_SCSI_CDB_MODE_SENSE_10_PAGE_CONTROL_LAST_BIT ((ISCSI_SCSI_CDB_MODE_SENSE_10_PAGE_CONTROL_FIRST_BIT) + 2 - 1) /// iSCSI SCSI Command Descriptor Block (CDB) for MODE SENSE(10) command page control: Bit mask. -#define ISCSI_SCSI_CDB_MODE_SENSE_10_PAGE_CONTROL_MASK (ISCSI_BITS_GET_MASK(ISCSI_SCSI_CDB_MODE_SENSE_10_PAGE_CONTROL_FIRST_BIT, ISCSI_SCSI_CDB_MODE_SENSE_10_PAGE_CONTROL_LAST_BIT)) +#define ISCSI_SCSI_CDB_MODE_SENSE_10_PAGE_CONTROL_MASK (ISCSI_BITS_GET_MASK(ISCSI_SCSI_CDB_MODE_SENSE_10_PAGE_CONTROL_FIRST_BIT, ISCSI_SCSI_CDB_MODE_SENSE_10_PAGE_CONTROL_LAST_BIT)) /// iSCSI SCSI Command Descriptor Block (CDB) for MODE SENSE(10) command page control: Extracts the page control bits. -#define ISCSI_SCSI_CDB_MODE_SENSE_10_GET_PAGE_CONTROL(x) (ISCSI_BITS_GET((x), ISCSI_SCSI_CDB_MODE_SENSE_10_PAGE_CONTROL_FIRST_BIT, ISCSI_SCSI_CDB_MODE_SENSE_10_PAGE_CONTROL_LAST_BIT)) +#define ISCSI_SCSI_CDB_MODE_SENSE_10_GET_PAGE_CONTROL(x) (ISCSI_BITS_GET((x), ISCSI_SCSI_CDB_MODE_SENSE_10_PAGE_CONTROL_FIRST_BIT, ISCSI_SCSI_CDB_MODE_SENSE_10_PAGE_CONTROL_LAST_BIT)) /// iSCSI SCSI Command Descriptor Block (CDB) for MODE SENSE(10) command page control: Stores into the page control bits. -#define ISCSI_SCSI_CDB_MODE_SENSE_10_PUT_PAGE_CONTROL(x) (ISCSI_BITS_PUT((x), ISCSI_SCSI_CDB_MODE_SENSE_10_PAGE_CONTROL_FIRST_BIT, ISCSI_SCSI_CDB_MODE_SENSE_10_PAGE_CONTROL_LAST_BIT)) +#define ISCSI_SCSI_CDB_MODE_SENSE_10_PUT_PAGE_CONTROL(x) (ISCSI_BITS_PUT((x), ISCSI_SCSI_CDB_MODE_SENSE_10_PAGE_CONTROL_FIRST_BIT, ISCSI_SCSI_CDB_MODE_SENSE_10_PAGE_CONTROL_LAST_BIT)) /** @@ -3381,20 +3396,20 @@ typedef struct __attribute__((packed)) iscsi_scsi_read_capacity_10_parameter_dat #define ISCSI_SCSI_SERVICE_ACTION_IN_16_PARAM_DATA_PUT_P_I_EXPONENT(x) (ISCSI_BITS_PUT((x), ISCSI_SCSI_SERVICE_ACTION_IN_16_PARAM_DATA_P_I_EXPONENT_FIRST_BIT, ISCSI_SCSI_SERVICE_ACTION_IN_16_PARAM_DATA_P_I_EXPONENT_LAST_BIT)) -/// iSCSI SCSI command SERVICE ACTION IN(16) parameter data protection information intervals exponent: First bit of the four bits. +/// iSCSI SCSI command SERVICE ACTION IN(16) parameter logical block provisioning Lowest Aligned Logical Block Address (LALBA): First bit of the fourteen bits. #define ISCSI_SCSI_SERVICE_ACTION_IN_16_PARAM_DATA_LALBA_FIRST_BIT 0 -/// iSCSI SCSI command SERVICE ACTION IN(16) parameter data protection information intervals exponent: Last bit of the four bits. +/// iSCSI SCSI command SERVICE ACTION IN(16) parameter logical block provisioning Lowest Aligned Logical Block Address (LALBA): Last bit of the fourteen bits. #define ISCSI_SCSI_SERVICE_ACTION_IN_16_PARAM_DATA_LALBA_LAST_BIT ((ISCSI_SCSI_SERVICE_ACTION_IN_16_PARAM_DATA_LALBA_FIRST_BIT) + 14 - 1) -/// iSCSI SCSI command SERVICE ACTION IN(16) parameter logical block provisioning: Lowest Aligned Logical Block Address mask (LALBA). +/// iSCSI SCSI command SERVICE ACTION IN(16) parameter logical block provisioning Lowest Aligned Logical Block Address (LALBA): Bit mask. #define ISCSI_SCSI_SERVICE_ACTION_IN_16_PARAM_DATA_LALBA_MASK (ISCSI_BITS_GET_MASK(ISCSI_SCSI_SERVICE_ACTION_IN_16_PARAM_DATA_LALBA_FIRST_BIT, ISCSI_SCSI_SERVICE_ACTION_IN_16_PARAM_DATA_LALBA_LAST_BIT)) -/// iSCSI SCSI command SERVICE ACTION IN(16) parameter logical block provisioning: Extracts the Lowest Aligned Logical Block Address (LALBA) bits. -#define ISCSI_SCSI_SERVICE_ACTION_IN_16_PARAM_DATA_GET_LABLA (ISCSI_BITS_GET((x), ISCSI_SCSI_SERVICE_ACTION_IN_16_PARAM_DATA_LALBA_FIRST_BIT, ISCSI_SCSI_SERVICE_ACTION_IN_16_PARAM_DATA_LALBA_LAST_BIT)) +/// iSCSI SCSI command SERVICE ACTION IN(16) parameter logical block provisioning Lowest Aligned Logical Block Address (LALBA): Extracts the Lowest Aligned Logical Block Address (LALBA) bits. +#define ISCSI_SCSI_SERVICE_ACTION_IN_16_PARAM_DATA_GET_LABLA(x) (ISCSI_BITS_GET((x), ISCSI_SCSI_SERVICE_ACTION_IN_16_PARAM_DATA_LALBA_FIRST_BIT, ISCSI_SCSI_SERVICE_ACTION_IN_16_PARAM_DATA_LALBA_LAST_BIT)) -/// iSCSI SCSI command SERVICE ACTION IN(16) parameter logical block provisioning: Stores into the Lowest Aligned Logical Block Address (LALBA) bits. -#define ISCSI_SCSI_SERVICE_ACTION_IN_16_PARAM_DATA_PUT_LABLA (ISCSI_BITS_PUT((x), ISCSI_SCSI_SERVICE_ACTION_IN_16_PARAM_DATA_LALBA_FIRST_BIT, ISCSI_SCSI_SERVICE_ACTION_IN_16_PARAM_DATA_LALBA_LAST_BIT)) +/// iSCSI SCSI command SERVICE ACTION IN(16) parameter logical block provisioning Lowest Aligned Logical Block Address (LALBA): Stores into the Lowest Aligned Logical Block Address (LALBA) bits. +#define ISCSI_SCSI_SERVICE_ACTION_IN_16_PARAM_DATA_PUT_LABLA(x) (ISCSI_BITS_PUT((x), ISCSI_SCSI_SERVICE_ACTION_IN_16_PARAM_DATA_LALBA_FIRST_BIT, ISCSI_SCSI_SERVICE_ACTION_IN_16_PARAM_DATA_LALBA_LAST_BIT)) /// iSCSI SCSI command SERVICE ACTION IN(16) parameter logical block provisioning: Logical Block Provisioning Read Zeros (LBPRZ). #define ISCSI_SCSI_SERVICE_ACTION_IN_16_PARAM_DATA_LBPRZ (1 << 14) @@ -3504,15 +3519,711 @@ typedef struct __attribute__((packed)) iscsi_scsi_mode_select_10_parameter_list_ } iscsi_scsi_mode_select_10_parameter_list_packet; +/// iSCSI SCSI command MODE SENSE(6) parameter header data flags: DPO and FUA support (DPOFUA). +#define ISCSI_SCSI_MODE_SENSE_6_PARAM_HDR_DATA_FLAGS_DPOFUA (1 << 4) + +/// iSCSI SCSI command MODE SENSE(6) parameter header data flags: Write Protect (WP). +#define ISCSI_SCSI_MODE_SENSE_6_PARAM_HDR_DATA_FLAGS_WP (1 << 7) + + /** - * @brief iSCSI SCSI command MODE SENSE(6) parameter list packet data. + * @brief iSCSI SCSI command MODE SENSE(6) parameter header packet data. * - * This returns 32-bit vendor specific data. + * This returns the mode parameter header + * data. */ -typedef struct __attribute__((packed)) iscsi_scsi_mode_sense_parameter_data_packet { - /// Vendor specific data. - uint32_t vendor_data; -} iscsi_scsi_mode_sense_parameter_data_packet; +typedef struct __attribute__((packed)) iscsi_scsi_mode_sense_6_parameter_header_data_packet { + /// Mode data length in bytes. + uint8_t mode_data_len; + + /// Medium type. + uint8_t medium_type; + + /// Flags. + int8_t flags; + + /// Block descriptor length in bytes. + uint8_t block_desc_len; +} iscsi_scsi_mode_sense_6_parameter_header_data_packet; + + +/// iSCSI SCSI command MODE SENSE(10) parameter header data flags: DPO and FUA support (DPOFUA). +#define ISCSI_SCSI_MODE_SENSE_10_PARAM_HDR_DATA_FLAGS_DPOFUA (1 << 4) + +/// iSCSI SCSI command MODE SENSE(10) parameter header data flags: Write Protect (WP). +#define ISCSI_SCSI_MODE_SENSE_10_PARAM_HDR_DATA_FLAGS_WP (1 << 7) + + +/// iSCSI SCSI command MODE SENSE(10) parameter header data Long Logical Block Address (LONGLBA). +#define ISCSI_SCSI_MODE_SENSE_10_PARAM_HDR_DATA_LONGLBA (1 << 0) + + +/** + * @brief iSCSI SCSI command MODE SENSE(10) parameter header packet data. + * + * This returns the mode parameter header + * data. + */ +typedef struct __attribute__((packed)) iscsi_scsi_mode_sense_10_parameter_header_data_packet { + /// Mode data length in bytes. + uint16_t mode_data_len; + + /// Medium type. + uint8_t medium_type; + + /// Flags. + int8_t flags; + + /// Long Logical Block Address (LONGLBA). + uint8_t long_lba; + + /// Reserved for future usage (always MUST be 0 for now). + uint8_t reserved; + + /// Block descriptor length in bytes. + uint16_t block_desc_len; +} iscsi_scsi_mode_sense_10_parameter_header_data_packet; + + +/** + * @brief iSCSI SCSI command MODE SENSE(6) short LBA mode parameter block descriptor packet data. + * + * This returns the short Logical Block + * Address (LBA) mode parameter block + * descriptor data. + */ +typedef struct __attribute__((packed)) iscsi_scsi_mode_sense_lba_parameter_block_desc_data_packet { + /// Number of blocks in logical blocks. + uint32_t num_blocks; + + /// Reserved for future usage (always MUST be 0 for now). + uint8_t reserved; + + /// Logical blcok length in bytes. + uint8_t block_len[3]; +} iscsi_scsi_mode_sense_lba_parameter_block_desc_data_packet; + + +/** + * @brief iSCSI SCSI command MODE SENSE(10) long LBA mode parameter block descriptor packet data. + * + * This returns the long Logical Block + * Address (LBA) mode parameter block + * descriptor data. + */ +typedef struct __attribute__((packed)) iscsi_scsi_mode_sense_long_lba_parameter_block_desc_data_packet { + /// Number of blocks in logical blocks. + uint64_t num_blocks; + + /// Reserved for future usage (always MUST be 0 for now). + uint32_t reserved; + + /// Logical blcok length in bytes. + uint32_t block_len; +} iscsi_scsi_mode_sense_long_lba_parameter_block_desc_data_packet; + + +/// iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) mode page code: Vendor specific. +#define ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_VENDOR_SPEC 0x00 + +/// iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) mode page code: Read/Write error recovery. +#define ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_READ_WRITE_ERR_RECOVERY 0x01 + +/// iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) mode page code: Disconnect / Reconnect. +#define ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_DISCONNECT_RECONNECT 0x02 + +/// iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) mode page code: Format device. +#define ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_FORMAT_DEVICE 0x03 + +/// iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) mode page code: Rigid disk geometry. +#define ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_RIGID_DISK_GEOMETRY 0x04 + +/// iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) mode page code: Rigid disk geometry. +#define ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_RIGID_DISK_GEOMETRY_2 0x05 + +/// iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) mode page code: Reserved. +#define ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_RESERVED 0x06 + +/// iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) mode page code: Verify error recovery. +#define ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_VERIFY_ERR_RECOVERY 0x07 + +/// iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) mode page code: Caching. +#define ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_CACHING 0x08 + +/// iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) mode page code: Obselete. +#define ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_OBSELETE 0x09 + +/// iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) mode page code: Control. +#define ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_CONTROL 0x0A + +/// iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) mode page code: Medium types supported. +#define ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_MEDIUM_TYPES_SUPPORTED 0x0B + +/// iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) mode page code: Notch and partition. +#define ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_NOTCH_AND_PARTITION 0x0C + +/// iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) mode page code: Obselete. +#define ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_OBSELETE_2 0x0D + +/// iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) mode page code: Reserved. +#define ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_RESERVED_2 0x0E + +/// iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) mode page code: Reserved. +#define ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_RESERVED_3 0x0F + +/// iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) mode page code: XOR control. +#define ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_XOR_CONTROL 0x10 + +/// iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) mode page code: Reserved. +#define ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_RESERVED_4 0x11 + +/// iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) mode page code: Reserved. +#define ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_RESERVED_5 0x12 + +/// iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) mode page code: Reserved. +#define ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_RESERVED_6 0x13 + +/// iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) mode page code: Enclosure services management. +#define ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_ENCLOSURE_SERVICES_MGMT 0x14 + +/// iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) mode page code: Reserved. +#define ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_RESERVED_7 0x15 + +/// iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) mode page code: Reserved. +#define ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_RESERVED_8 0x16 + +/// iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) mode page code: Reserved. +#define ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_RESERVED_9 0x17 + +/// iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) mode page code: Protocol specific LUN. +#define ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_PROTOCOL_SPEC_LUN 0x18 + +/// iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) mode page code: Protocol specific Port. +#define ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_PROTOCOL_SPEC_PORT 0x19 + +/// iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) mode page code: Power condition. +#define ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_POWER_COND 0x1A + +/// iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) mode page code: Reserved. +#define ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_RESERVED_10 0x1B + +/// iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) mode page code: Informational exceptions control. +#define ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_INFO_EXCEPTIOS_CONTROL 0x1C + +/// iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) mode page code: Reserved. +#define ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_RESERVED_11 0x1D + +/// iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) mode page code: Reserved. +#define ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_RESERVED_12 0x1E + +/// iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) mode page code: Reserved. +#define ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_RESERVED_13 0x1F + +/// iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) mode page code: Vendor specific. +#define ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_VENDOR_SPEC_2 0x20 + +/// iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) mode page code: Vendor specific. +#define ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_VENDOR_SPEC_3 0x21 + +/// iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) mode page code: Vendor specific. +#define ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_VENDOR_SPEC_4 0x22 + +/// iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) mode page code: Vendor specific. +#define ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_VENDOR_SPEC_5 0x23 + +/// iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) mode page code: Vendor specific. +#define ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_VENDOR_SPEC_6 0x24 + +/// iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) mode page code: Vendor specific. +#define ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_VENDOR_SPEC_7 0x25 + +/// iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) mode page code: Vendor specific. +#define ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_VENDOR_SPEC_8 0x26 + +/// iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) mode page code: Vendor specific. +#define ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_VENDOR_SPEC_9 0x27 + +/// iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) mode page code: Vendor specific. +#define ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_VENDOR_SPEC_10 0x28 + +/// iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) mode page code: Vendor specific. +#define ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_VENDOR_SPEC_11 0x29 + +/// iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) mode page code: Vendor specific. +#define ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_VENDOR_SPEC_12 0x2A + +/// iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) mode page code: Vendor specific. +#define ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_VENDOR_SPEC_13 0x2B + +/// iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) mode page code: Vendor specific. +#define ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_VENDOR_SPEC_14 0x2C + +/// iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) mode page code: Vendor specific. +#define ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_VENDOR_SPEC_15 0x2D + +/// iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) mode page code: Vendor specific. +#define ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_VENDOR_SPEC_16 0x2E + +/// iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) mode page code: Vendor specific. +#define ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_VENDOR_SPEC_17 0x2F + +/// iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) mode page code: Vendor specific. +#define ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_VENDOR_SPEC_18 0x30 + +/// iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) mode page code: Vendor specific. +#define ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_VENDOR_SPEC_19 0x31 + +/// iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) mode page code: Vendor specific. +#define ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_VENDOR_SPEC_20 0x32 + +/// iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) mode page code: Vendor specific. +#define ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_VENDOR_SPEC_21 0x33 + +/// iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) mode page code: Vendor specific. +#define ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_VENDOR_SPEC_22 0x34 + +/// iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) mode page code: Vendor specific. +#define ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_VENDOR_SPEC_23 0x35 + +/// iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) mode page code: Vendor specific. +#define ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_VENDOR_SPEC_24 0x36 + +/// iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) mode page code: Vendor specific. +#define ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_VENDOR_SPEC_25 0x37 + +/// iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) mode page code: Vendor specific. +#define ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_VENDOR_SPEC_26 0x38 + +/// iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) mode page code: Vendor specific. +#define ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_VENDOR_SPEC_27 0x39 + +/// iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) mode page code: Vendor specific. +#define ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_VENDOR_SPEC_28 0x3A + +/// iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) mode page code: Vendor specific. +#define ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_VENDOR_SPEC_29 0x3B + +/// iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) mode page code: Vendor specific. +#define ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_VENDOR_SPEC_30 0x3C + +/// iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) mode page code: Vendor specific. +#define ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_VENDOR_SPEC_31 0x3D + +/// iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) mode page code: Vendor specific. +#define ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_VENDOR_SPEC_32 0x3E + +/// iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) mode page code: Report all mode pages. +#define ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_REPORT_ALL_MODE_PAGES 0x3F + +/// iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) mode sub page code: Control. +#define ISCSI_SCSI_MODE_SENSE_MODE_SUB_PAGE_CODE_CONTROL 0x00 + +/// iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) mode sub page code: Control extension. +#define ISCSI_SCSI_MODE_SENSE_MODE_SUB_PAGE_CODE_CONTROL_EXT 0x01 + +/// iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) mode sub page code: All sub pages. +#define ISCSI_SCSI_MODE_SENSE_MODE_SUB_PAGE_CODE_CONTROL_ALL 0xFF + +/// iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) mode sub page code: Report all mode pages. +#define ISCSI_SCSI_MODE_SENSE_MODE_SUB_PAGE_CODE_REPORT_ALL_MODE_PAGES 0x00 + +/// iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) mode sub page code: Report all mode pages and sub pages. +#define ISCSI_SCSI_MODE_SENSE_MODE_SUB_PAGE_CODE_REPORT_ALL_MODE_SUB_PAGES 0xFF + +/// iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) mode page code: First bit of the six bits. +#define ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_FIRST_BIT 0 + +/// iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) mode page code: Last bit of the six bits. +#define ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_LAST_BIT ((ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_FIRST_BIT) + 6 - 1) + +/// iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) mode page code: Bit mask. +#define ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_MASK (ISCSI_BITS_GET_MASK(ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_FIRST_BIT, ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_LAST_BIT)) + +/// iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) mode page code: Extracts the page code bits. +#define ISCSI_SCSI_MODE_SENSE_MODE_PAGE_GET_PAGE_CODE(x) (ISCSI_BITS_GET((x), ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_FIRST_BIT, ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_LAST_BIT)) + +/// iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) mode page code: Stores into the page code bits. +#define ISCSI_SCSI_MODE_SENSE_MODE_PAGE_PUT_PAGE_CODE(x) (ISCSI_BITS_PUT((x), ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_FIRST_BIT, ISCSI_SCSI_MODE_SENSE_MODE_PAGE_CODE_LAST_BIT)) + +/// iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) mode page flags: Sub Page Format (SPF). +#define ISCSI_SCSI_MODE_SENSE_MODE_PAGE_FLAGS_SPF (1 << 6) + +/// iSCSI SCSI command MODE SENSE(10) parameter header data flags: Parameters Saveable (PS). +#define ISCSI_SCSI_MODE_SENSE_MODE_PAGE_FLAGS_PS (1 << 7) + + +/** + * @brief iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) mode page packet data. + * + * This returns mode page specific data. + */ +typedef struct __attribute__((packed)) iscsi_scsi_mode_sense_mode_page_data_packet { + /// Page code and flags. + int8_t page_code_flags; + + /// Page length in bytes. + uint8_t page_len; + + /// Mode parameters. + uint8_t params[0]; +} iscsi_scsi_mode_sense_mode_page_data_packet; + + +/** + * @brief iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) mode sub page packet data. + * + * This returns mode sub page specific data. + */ +typedef struct __attribute__((packed)) iscsi_scsi_mode_sense_mode_sub_page_data_packet { + /// Page code and flags. + int8_t page_code_flags; + + /// Sub page code. + uint8_t sub_page_code; + + /// Page length in bytes. + uint16_t page_len; + + /// Mode parameters. + uint8_t params[0]; +} iscsi_scsi_mode_sense_mode_sub_page_data_packet; + + +/** + * @brief iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) read/write error recovery mode page packet data. + * + * This returns mode page specific data. + */ +typedef struct __attribute__((packed)) iscsi_scsi_mode_sense_read_write_err_recovery_mode_page_data_packet { + /// Mode page. + iscsi_scsi_mode_sense_mode_page_data_packet mode_page; + + /// Flags. + int8_t flags; + + /// Read retry count. + uint8_t read_retry_cnt; + + /// Obselete. + uint8_t obselete[3]; + + /// Restricted for MMC-6. + uint8_t restrict_mmc_6; + + /// Write_retry count. + uint8_t write_retry_cnt; + + /// Reserved for future usage (always MUST be 0 for now). + uint8_t reserved; + + /// Recovery time limit. + uint16_t recovery_time_limit; +} iscsi_scsi_mode_sense_read_write_err_recovery_mode_page_data_packet; + + +/** + * @brief iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) disconnect / reconnect mode page packet data. + * + * This returns mode page specific data. + */ +typedef struct __attribute__((packed)) iscsi_scsi_mode_sense_disconnect_reconnect_mode_page_data_packet { + /// Mode page. + iscsi_scsi_mode_sense_mode_page_data_packet mode_page; + + /// Reserved for future usage (always MUST be 0 for now). + uint16_t reserved; + + /// Bus inactivity time limit. + uint16_t bus_inactivity_time_limit; + + /// Reserved for future usage (always MUST be 0 for now). + uint16_t reserved2; + + /// Maximum connect time limit. + uint16_t max_connect_time_limit; + + /// Maximum burst size. + uint16_t max_burst_size; + + /// Restricted. + uint8_t restricted; + + /// Reserved for future usage (always MUST be 0 for now). + uint8_t reserved3; + + /// First burst size. + uint16_t first_burst_size; +} iscsi_scsi_mode_sense_disconnect_reconnect_mode_page_data_packet; + + +/** + * @brief iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) verify error recovery mode page packet data. + * + * This returns mode page specific data. + */ +typedef struct __attribute__((packed)) iscsi_scsi_mode_sense_verify_err_recovery_mode_page_data_packet { + /// Mode page. + iscsi_scsi_mode_sense_mode_page_data_packet mode_page; + + /// Flags. + int8_t flags; + + /// Verify retry count. + uint8_t verify_retry_cnt; + + /// Obselete. + uint8_t obselete; + + /// Head offset count. + uint8_t head_offset_cnt; + + /// Data strobe offset count. + uint8_t data_strobe_offset_cnt; + + /// Reserved for future usage (always MUST be 0 for now). + uint8_t reserved; + + /// Write retry count. + uint8_t write_retry_cnt; + + /// Reserved for future usage (always MUST be 0 for now). + uint8_t reserved2; + + /// Verify_recovery time limit. + uint16_t verify_recovery_time_limit; +} iscsi_scsi_mode_sense_verify_err_recovery_mode_page_data_packet; + + +/// iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) caching mode page flags: READ Cache Disable (RCD). +#define ISCSI_SCSI_MODE_SENSE_CACHING_MODE_PAGE_FLAGS_RCD (1 << 0) + +/// iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) caching mode page flags: Multiplication factor (MF). +#define ISCSI_SCSI_MODE_SENSE_CACHING_MODE_PAGE_FLAGS_MF (1 << 1) + +/// iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) caching mode page flags: Write Cache Enable (WCE). +#define ISCSI_SCSI_MODE_SENSE_CACHING_MODE_PAGE_FLAGS_WCE (1 << 2) + +/// iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) caching mode page flags: Size Enable (SIZE). +#define ISCSI_SCSI_MODE_SENSE_CACHING_MODE_PAGE_FLAGS_SIZE (1 << 3) + +/// iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) caching mode page flags: Discontinuity (DISC). +#define ISCSI_SCSI_MODE_SENSE_CACHING_MODE_PAGE_FLAGS_DISC (1 << 4) + +/// iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) caching mode page flags: Caching Analysis Permitted (CAP). +#define ISCSI_SCSI_MODE_SENSE_CACHING_MODE_PAGE_FLAGS_CAP (1 << 5) + +/// iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) caching mode page flags: Abort Prefetch (ABPF). +#define ISCSI_SCSI_MODE_SENSE_CACHING_MODE_PAGE_FLAGS_ABPF (1 << 6) + +/// iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) caching mode page flags: Initiator Control (IC). +#define ISCSI_SCSI_MODE_SENSE_CACHING_MODE_PAGE_FLAGS_IC (1 << 7) + + +/** + * @brief iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) caching mode page packet data. + * + * This returns mode page specific data. + */ +typedef struct __attribute__((packed)) iscsi_scsi_mode_sense_caching_mode_page_data_packet { + /// Mode page. + iscsi_scsi_mode_sense_mode_page_data_packet mode_page; + + /// Flags. + int8_t flags; + + /// Retention priority. + uint8_t retention_pri; + + /// Disable prefetch transfer length. + uint16_t disable_prefetch_xfer_len; + + /// Minimum prefetch. + uint16_t min_prefetch; + + /// Maximum prefetch. + uint16_t max_prefetch; + + /// Maximum prefetch ceiling. + uint16_t max_prefetch_ceil; + + /// Cache flags. + int8_t cache_flags; + + /// Number of cache segments. + uint8_t num_cache_segs; + + /// Cache segment size. + uint16_t cache_seg_size; + + /// Reserved for future usage (always MUST be 0 for now). + uint8_t reserved; + + /// Obselete. + uint8_t obselete[3]; +} iscsi_scsi_mode_sense_caching_mode_page_data_packet; + + +/** + * @brief iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) control mode page packet data. + * + * This returns mode page specific data. + */ +typedef struct __attribute__((packed)) iscsi_scsi_mode_sense_control_mode_page_data_packet { + /// Mode page. + iscsi_scsi_mode_sense_mode_page_data_packet mode_page; + + /// Flags. + int8_t flags; + + /// Queue flags. + int8_t queue_flags; + + /// Control flags. + int8_t control_flags; + + /// Application task flags. + int8_t app_task_flags; + + /// Ready AER holdoff period. + uint16_t ready_aer_holdoff_period; + + /// Busy timeout period. + uint16_t busy_timeout_period; + + /// Extended self-test completition time. + uint16_t ext_self_test_complete_time; +} iscsi_scsi_mode_sense_control_mode_page_data_packet; + + +/** + * @brief iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) control extension mode sub page packet data. + * + * This returns mode sub page specific data. + */ +typedef struct __attribute__((packed)) iscsi_scsi_mode_sense_control_ext_mode_page_data_packet { + /// Mode page. + iscsi_scsi_mode_sense_mode_sub_page_data_packet mode_sub_page; + + /// Flags. + int8_t flags; + + /// Initial command priority. + uint8_t init_cmd_pri; + + /// Maximum sense data length in bytes. + uint8_t max_sense_data_len; + + /// Reserved for future usage (always MUST be 0 for now). + uint64_t reserved[3]; + + /// Reserved for future usage (always MUST be 0 for now). + uint8_t reserved2; +} iscsi_scsi_mode_sense_control_ext_mode_page_data_packet; + + +/** + * @brief iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) XOR extension mode page packet data. + * + * This returns mode page specific data. + */ +typedef struct __attribute__((packed)) iscsi_scsi_mode_sense_xor_ext_mode_page_data_packet { + /// Mode page. + iscsi_scsi_mode_sense_mode_page_data_packet mode_page; + + /// Flags. + int8_t flags; + + /// Reserved for future usage (always MUST be 0 for now). + uint8_t reserved; + + /// Maximum XOR write size in logical blocks. + uint32_t max_xor_write_size; + + /// Reserved for future usage (always MUST be 0 for now). + uint32_t reserved2; + + /// Maximum regenerate size in logical blocks. + uint32_t max_regenerate_size; + + /// Reserved for future usage (always MUST be 0 for now). + uint32_t reserved3; + + /// Reserved for future usage (always MUST be 0 for now). + uint16_t reserved4; + + /// Rebuild delay. + uint16_t rebuild_delay; +} iscsi_scsi_mode_sense_xor_ext_mode_page_data_packet; + + +/** + * @brief iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) power condition mode page packet data. + * + * This returns mode page specific data. + */ +typedef struct __attribute__((packed)) iscsi_scsi_mode_sense_power_cond_mode_page_data_packet { + /// Mode page. + iscsi_scsi_mode_sense_mode_page_data_packet mode_page; + + /// Flags. + int8_t flags; + + /// Idle and standby flags. + int8_t idle_standby_flags; + + /// idle_a condition timer. + uint32_t idle_a_cond_timer; + + /// standby_z condition timer. + uint32_t standby_z_cond_timer; + + /// idle_b condition timer. + uint32_t idle_b_cond_timer; + + /// idle_c condition timer. + uint32_t idle_c_cond_timer; + + /// standby_y condition timer. + uint32_t standby_y_cond_timer; + + /// Reserved for future usage (always MUST be 0 for now). + uint64_t reserved; + + /// Reserved for future usage (always MUST be 0 for now). + uint32_t reserved2; + + /// Reserved for future usage (always MUST be 0 for now). + uint16_t reserved3; + + /// Reserved for future usage (always MUST be 0 for now). + uint8_t reserved4; + + /// Check Condition From (CCF) flags. + int8_t ccf_flags; +} iscsi_scsi_mode_sense_power_cond_mode_page_data_packet; + + +/** + * @brief iSCSI SCSI command MODE SENSE(6) and MODE SENSE(10) informational exceptions control mode page packet data. + * + * This returns mode page specific data. + */ +typedef struct __attribute__((packed)) iscsi_scsi_mode_sense_info_exceptions_control_mode_page_data_packet { + /// Mode page. + iscsi_scsi_mode_sense_mode_page_data_packet mode_page; + + /// Flags. + int8_t flags; + + /// Method Of Reporting Informational Exceptions (MRIE) flags. + uint8_t mrie; + + /// Interval timer. + uint32_t interval_timer; + + /// Report count. + uint32_t report_cnt; +} iscsi_scsi_mode_sense_info_exceptions_control_mode_page_data_packet; /** @@ -8582,6 +9293,12 @@ typedef struct __attribute__((packed)) iscsi_nop_in_packet { #define ISCSI_TRANSPORT_ID_PUT_FORMAT(x) (ISCSI_BITS_PUT((x), ISCSI_TRANSPORT_ID_FORMAT_FIRST_BIT, ISCSI_TRANSPORT_ID_FORMAT_LAST_BIT)) +/** + * @brief iSCSI SCSI Transport ID structure. + * + * This structure handles the iSCSI SCSI transport + * identifier data. + */ typedef struct __attribute__((packed)) iscsi_transport_id { /// First 4 bits are protocol ID and last 2 bits are format. uint8_t id; @@ -9284,16 +10001,16 @@ typedef struct iscsi_scsi_task { /// iSCSI SCSI emulation physical block size in bits. -#define ISCSI_SCSI_EMU_PHYSICAL_BLOCK_SIZE_BITS 9UL +#define ISCSI_SCSI_EMU_PHYSICAL_BLOCK_SIZE_BITS 12UL /// iSCSI SCSI emulation physical block size in bytes. #define ISCSI_SCSI_EMU_PHYSICAL_BLOCK_SIZE (1UL << ISCSI_SCSI_EMU_PHYSICAL_BLOCK_SIZE_BITS) -/// iSCSI SCSI emulation block size in bits. -#define ISCSI_SCSI_EMU_BLOCK_SIZE_BITS 12UL +/// iSCSI SCSI emulation logical block size in bits. +#define ISCSI_SCSI_EMU_BLOCK_SIZE_BITS 9UL -/// iSCSI SCSI emulation block size in bytes. +/// iSCSI SCSI emulation logical block size in bytes. #define ISCSI_SCSI_EMU_BLOCK_SIZE (1UL << ISCSI_SCSI_EMU_BLOCK_SIZE_BITS) @@ -9316,6 +10033,9 @@ typedef struct iscsi_scsi_task { /// iSCSI SCSI emulation I/O type: Non-rotating medium (e.g., solid state). #define ISCSI_SCSI_EMU_IO_TYPE_NO_ROTATION (1 << 2) +/// iSCSI SCSI emulation I/O type: Write cache available. +#define ISCSI_SCSI_EMU_IO_TYPE_WRITE_CACHE (1 << 3) + /// iSCSI SCSI emulation block flags: Write operation. #define ISCSI_SCSI_EMU_BLOCK_FLAGS_WRITE (1 << 0) |
