summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Vater2025-09-16 11:36:25 +0200
committerSebastian Vater2025-09-16 11:36:25 +0200
commitf1f80edca93172c173123d3e2f4936de433b62ac (patch)
treee67ac01eaa5111b14e380b8b1aedf3bb15850454
parentFixed iSCSI SCSI emulation and implemented adding target port to iSCSI device... (diff)
downloaddnbd3-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.c517
-rw-r--r--src/server/iscsi.h856
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)