From 78daeaabc5e50f452ba081bbbde9c040eb277051 Mon Sep 17 00:00:00 2001 From: Sebastian Vater Date: Thu, 11 Sep 2025 15:06:57 +0200 Subject: Implemented remaining INQUIRY iSCSI SCSI emulation related stuff. Also fixed some bugs and finally did some code refactoring. --- src/server/iscsi.c | 640 +++++++++++++++++- src/server/iscsi.h | 1815 +++++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 2127 insertions(+), 328 deletions(-) diff --git a/src/server/iscsi.c b/src/server/iscsi.c index 8ba0c42..9c44f04 100644 --- a/src/server/iscsi.c +++ b/src/server/iscsi.c @@ -468,6 +468,33 @@ uint8_t *iscsi_sprintf_alloc(const char *format, ... ) return buf; } +/** + * @brief Copies a string with additional padding character to fill in a specified size. + * + * This function does NOT pad, but truncates + * instead if the string length equals or is + * larger than the maximum allowed size. + * + * @param[in] dst Pointer to destination string to copy + * with padding and may NOT be NULL, so be + * careful. + * @param[in] src Pointer to string for copying. NULL + * is NOT allowed here, take caution. + * @param[in] size Total size in bytes for padding. + * @param[in] pad Padding character to use. + */ +void iscsi_strcpy_pad(char *dst, const char *src, const size_t size, const int pad) +{ + const size_t len = strlen( src ); + + if ( len < size ) { + memcpy( dst, src, len ); + memset( (dst + len), pad, (size - len) ); + } else { + memcpy( dst, src, size ); + } +} + /** * @brief Creates an empty hash map with either specified or default capacity. * @@ -3949,8 +3976,8 @@ void iscsi_scsi_task_lun_process_none(iscsi_scsi_task *scsi_task) memset( &std_inquiry_data_pkt, 0, len ); - std_inquiry_data_pkt.peripheral_type_id = (ISCSI_SCSI_DATA_PUT_PERIPHERAL_TYPE(ISCSI_SCSI_DATA_PERIPHERAL_TYPE_UNKNOWN) | ISCSI_SCSI_DATA_PUT_PERIPHERAL_ID(ISCSI_SCSI_DATA_PERIPHERAL_ID_NEVER)); - std_inquiry_data_pkt.add_len = (uint8_t) (len - sizeof(struct iscsi_scsi_data_packet)); + std_inquiry_data_pkt.basic_inquiry.peripheral_type_id = (ISCSI_SCSI_BASIC_INQUIRY_DATA_PUT_PERIPHERAL_TYPE(ISCSI_SCSI_BASIC_INQUIRY_DATA_PERIPHERAL_TYPE_UNKNOWN) | ISCSI_SCSI_BASIC_INQUIRY_DATA_PUT_PERIPHERAL_ID(ISCSI_SCSI_BASIC_INQUIRY_DATA_PERIPHERAL_ID_NEVER)); + std_inquiry_data_pkt.basic_inquiry.add_len = (uint8_t) (len - sizeof(struct iscsi_scsi_basic_inquiry_data_packet)); const uint alloc_len = iscsi_get_be16(cdb->alloc_len); @@ -4859,6 +4886,23 @@ static inline uint64_t iscsi_scsi_emu_physical_block_get_count(const dnbd3_image return (image->virtualFilesize >> ISCSI_SCSI_EMU_PHYSICAL_BLOCK_SIZE_BITS); } +/** + * @brief Retrieves the bit shift of a physical block in bytes for a DNBB3 image. + * + * This function depends on DNBB3 image + * properties. + * + * @param[in] image Pointer to DNBD3 image to retrieve + * the physical bit shift size. May NOT + * be NULL, so be careful. + * @return The physical block size in bytes as a + * bit shift count. + */ +static inline uint32_t iscsi_scsi_emu_physical_block_get_size_shift(const dnbd3_image_t *image) +{ + return ISCSI_SCSI_EMU_PHYSICAL_BLOCK_SIZE_BITS; +} + /** * @brief Retrieves the size of a physical block in bytes for a DNBB3 image. * @@ -4891,6 +4935,23 @@ static inline uint64_t iscsi_scsi_emu_block_get_count(const dnbd3_image_t *image return (image->virtualFilesize >> ISCSI_SCSI_EMU_BLOCK_SIZE_BITS); } +/** + * @brief Retrieves the bit shift of a logical block in bytes for a DNBB3 image. + * + * This function depends on DNBB3 image + * properties. + * + * @param[in] image Pointer to DNBD3 image to retrieve + * the logical block bit shift size. + * May NOT be NULL, so be careful. + * @return The logical block size in bytes as a + * bit shift count. + */ +static inline uint32_t iscsi_scsi_emu_block_get_size_shift(const dnbd3_image_t *image) +{ + return ISCSI_SCSI_EMU_BLOCK_SIZE_BITS; +} + /** * @brief Retrieves the size of a logical block in bytes for a DNBB3 image. * @@ -4923,7 +4984,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_SIZE_BITS - ISCSI_SCSI_EMU_PHYSICAL_BLOCK_SIZE_BITS); + return (iscsi_scsi_emu_block_get_size_shift(image) - iscsi_scsi_emu_physical_block_get_size_shift(image)); } /** @@ -5309,6 +5370,124 @@ static int iscsi_scsi_emu_check_len(iscsi_scsi_task *scsi_task, const uint len, return -1; } +/** + * @brief Calculates the 64-bit IEEE Extended NAA for a name. + * + * @param[out] buf Pointer to 64-bit output buffer for + * storing the IEEE Extended NAA. May + * NOT be NULL, so be careful. + * @param[in] name Pointer to string containing the + * name to calculate the IEEE Extended + * NAA for. NULL is NOT allowed here, so + * take caution. + */ +static void iscsi_scsi_emu_naa_ieee_ext_set(uint64_t *buf, const uint8_t *name) +{ + uint64_t value = 0ULL; + int i = 0; + + while ( name[i] != '\0' ) { + value = (value * 131ULL) + name[i++]; + } + + const uint64_t id_a = ((value & 0xFFF000000ULL) << 24ULL); + + value = ((value & 0xFFFFFFULL) | 0x2000000347000000ULL | id_a); + + iscsi_put_be64( (uint8_t *) buf, value ); +} + +/** + * @brief Copies a SCSI name string and zero pads until total string length is aligned to DWORD boundary. + * + * @param[out] buf Pointer to copy the aligned SCSI + * string to. May NOT be NULL, so be + * careful. + * @param[in] name Pointer to string containing the + * SCSI name to be copied. NULL is NOT + * allowed here, so take caution. + * @return The aligned string length in bytes. + */ +static size_t iscsi_scsi_emu_pad_scsi_name(uint8_t *buf, const uint8_t *name) +{ + size_t len = strlen( (char *) name ); + + memcpy( buf, name, len ); + + do { + buf[len++] = '\0'; + } while ( (len & (ISCSI_ALIGN_SIZE - 1)) != 0 ); + + return len; +} + +/** + * @brief Fills in a single Vital Product Data (VPD) SCSI Port Designation Descriptor entry of an INQUIRY operation. + * + * Callback function for each element while iterating + * through the iSCSI SCSI device ports hash map.\n + * The iteration process is aborted when the + * remaining allocation length is not enough + * to hold the current VPD SCSI Port Designation + * Descriptor. + * + * @param[in] key Pointer to zero padded key. NULL is + * an invalid pointer here, so be careful. + * @param[in] key_size Number of bytes for the key. + * @param[in] value Value of the key, NULL creates an + * empty key assignment. + * @param[in,out] user_data Pointer to a data structure + * containing the current Vital Product Data + * (VPD) SCSI Port Designation Descriptor + * entry, the total length of all VPD SCSI Port + * Designation Descriptor entries in bytes, the + * remaining allocation length in bytes. May + * NOT be NULL, so be careful. + * @retval -1 Operation failure, ran out of + * allocation space during traversal. + * @retval 0 Successful operation, there is enough + * allocation space to store this + * reported Vital Product Data (VPD) SCSI Port + * Designation Descriptor entry. + */ +int iscsi_scsi_emu_primary_inquiry_callback(uint8_t *key, const size_t key_size, uint8_t *value, uint8_t *user_data) +{ + iscsi_scsi_emu_primary_inquiry_ports_fill *port_report_fill = (iscsi_scsi_emu_primary_inquiry_ports_fill *) user_data; + iscsi_port *port = (iscsi_port *) value; + + if ( (port->flags & ISCSI_PORT_FLAGS_IN_USE) == 0 ) + return 0; + + const uint port_name_len = (uint) strlen( (char *) port->name ) + 1U; + const uint len = (uint) (sizeof(struct iscsi_scsi_vpd_scsi_port_design_dec_inquiry_data_packet) + sizeof(struct iscsi_scsi_vpd_scsi_target_port_design_dec_inquiry_data_packet) + iscsi_align(port_name_len, ISCSI_ALIGN_SIZE)); + + port_report_fill->len -= len; + + if ( (int) port_report_fill->len < 0 ) + return -1; + + iscsi_scsi_vpd_scsi_port_design_dec_inquiry_data_packet *vpd_scsi_port_design_desc_inquiry_data_pkt = port_report_fill->port_entry; + + vpd_scsi_port_design_desc_inquiry_data_pkt->reserved = 0U; + iscsi_put_be16( (uint8_t *) &vpd_scsi_port_design_desc_inquiry_data_pkt->rel_port_id, port->index ); + vpd_scsi_port_design_desc_inquiry_data_pkt->reserved2 = 0U; + vpd_scsi_port_design_desc_inquiry_data_pkt->init_port_len = 0U; + vpd_scsi_port_design_desc_inquiry_data_pkt->reserved3 = 0U; + iscsi_put_be16( (uint8_t *) &vpd_scsi_port_design_desc_inquiry_data_pkt->target_desc_len, (uint16_t) (len - sizeof(struct iscsi_scsi_vpd_scsi_port_design_dec_inquiry_data_packet)) ); + + iscsi_scsi_vpd_scsi_target_port_design_dec_inquiry_data_packet *vpd_scsi_target_port_design_desc_inquiry_data_pkt = vpd_scsi_port_design_desc_inquiry_data_pkt->target_desc; + + vpd_scsi_target_port_design_desc_inquiry_data_pkt->protocol_id_code_set = ISCSI_SCSI_VPD_SCSI_TARGET_PORT_DESIGN_DESC_INQUIRY_DATA_PUT_PROTOCOL_ID(ISCSI_SCSI_VPD_SCSI_TARGET_PORT_DESIGN_DESC_INQUIRY_DATA_PROTOCOL_ID_ISCSI) | ISCSI_SCSI_VPD_SCSI_TARGET_PORT_DESIGN_DESC_INQUIRY_DATA_PUT_CODE_SET(ISCSI_SCSI_VPD_SCSI_TARGET_PORT_DESIGN_DESC_INQUIRY_DATA_CODE_SET_UTF8); + vpd_scsi_target_port_design_desc_inquiry_data_pkt->flags = (int8_t) (ISCSI_SCSI_VPD_SCSI_TARGET_PORT_DESIGN_DESC_INQUIRY_DATA_FLAGS_PUT_TYPE(ISCSI_SCSI_VPD_SCSI_TARGET_PORT_DESIGN_DESC_INQUIRY_DATA_FLAGS_TYPE_SCSI_NAME) | ISCSI_SCSI_VPD_SCSI_TARGET_PORT_DESIGN_DESC_INQUIRY_DATA_FLAGS_PUT_ASSOC(ISCSI_SCSI_VPD_SCSI_TARGET_PORT_DESIGN_DESC_INQUIRY_DATA_FLAGS_ASSOC_TARGET_PORT) | ISCSI_SCSI_VPD_SCSI_TARGET_PORT_DESIGN_DESC_INQUIRY_DATA_FLAGS_PIV); + vpd_scsi_target_port_design_desc_inquiry_data_pkt->reserved = 0U; + vpd_scsi_target_port_design_desc_inquiry_data_pkt->len = (uint8_t) iscsi_scsi_emu_pad_scsi_name( vpd_scsi_target_port_design_desc_inquiry_data_pkt->design, port->name ); + + port_report_fill->port_entry = (iscsi_scsi_vpd_scsi_port_design_dec_inquiry_data_packet *) (((uint8_t *) vpd_scsi_port_design_desc_inquiry_data_pkt) + len); + port_report_fill->alloc_len += len; + + return 0; +} + /** * @brief Executes an inquiry operation on a DNBD3 image. * @@ -5335,9 +5514,436 @@ static int iscsi_scsi_emu_check_len(iscsi_scsi_task *scsi_task, const uint len, */ static int iscsi_scsi_emu_primary_inquiry(dnbd3_image_t *image, iscsi_scsi_task *scsi_task, const iscsi_scsi_cdb_inquiry *cdb_inquiry, iscsi_scsi_std_inquiry_data_packet *std_inquiry_data_pkt, const uint len) { - // TODO: Implement SCSI emulation for DNBD3 image. + if ( len < sizeof(struct iscsi_scsi_std_inquiry_data_packet) ) { + scsi_task->pos = 0U; - return 0; + iscsi_scsi_task_status_set( scsi_task, ISCSI_SCSI_STATUS_CHECK_COND, ISCSI_SCSI_SENSE_KEY_NO_SENSE, ISCSI_SCSI_ASC_NO_ADDITIONAL_SENSE, ISCSI_SCSI_ASCQ_CAUSE_NOT_REPORTABLE ); + + return -1; + } + + const int evpd = (cdb_inquiry->lun_flags & ISCSI_SCSI_CDB_INQUIRY_FLAGS_EVPD); + const uint pc = cdb_inquiry->page_code; + + if ( (evpd == 0) && (pc != 0) ) { + 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 ); + + return -1; + } + + iscsi_scsi_lun *lun = scsi_task->lun; + iscsi_device *device = lun->device; + iscsi_port *port = scsi_task->target_port; + + if ( evpd != 0 ) { + iscsi_scsi_vpd_page_inquiry_data_packet *vpd_page_inquiry_data_pkt = (iscsi_scsi_vpd_page_inquiry_data_packet *) std_inquiry_data_pkt; + uint alloc_len; + const uint8_t pti = ISCSI_SCSI_VPD_PAGE_INQUIRY_DATA_PUT_PERIPHERAL_TYPE(ISCSI_SCSI_VPD_PAGE_INQUIRY_DATA_PERIPHERAL_TYPE_DIRECT) | ISCSI_SCSI_VPD_PAGE_INQUIRY_DATA_PUT_PERIPHERAL_ID(ISCSI_SCSI_VPD_PAGE_INQUIRY_DATA_PERIPHERAL_ID_POSSIBLE); + + vpd_page_inquiry_data_pkt->peripheral_type_id = pti; + vpd_page_inquiry_data_pkt->page_code = (uint8_t) pc; + + switch ( pc ) { + case ISCSI_SCSI_VPD_PAGE_INQUIRY_DATA_PAGE_CODE_SUPPORTED_VPD_PAGES : { + vpd_page_inquiry_data_pkt->params[0] = ISCSI_SCSI_VPD_PAGE_INQUIRY_DATA_PAGE_CODE_SUPPORTED_VPD_PAGES; + vpd_page_inquiry_data_pkt->params[1] = ISCSI_SCSI_VPD_PAGE_INQUIRY_DATA_PAGE_CODE_UNIT_SERIAL_NUMBER; + vpd_page_inquiry_data_pkt->params[2] = ISCSI_SCSI_VPD_PAGE_INQUIRY_DATA_PAGE_CODE_DEVICE_ID; + vpd_page_inquiry_data_pkt->params[3] = ISCSI_SCSI_VPD_PAGE_INQUIRY_DATA_PAGE_CODE_MANAGEMENT_NETWORK_ADDRS; + vpd_page_inquiry_data_pkt->params[4] = ISCSI_SCSI_VPD_PAGE_INQUIRY_DATA_PAGE_CODE_EXTENDED_INQUIRY_DATA; + vpd_page_inquiry_data_pkt->params[5] = ISCSI_SCSI_VPD_PAGE_INQUIRY_DATA_PAGE_CODE_MODE_PAGE_POLICY; + vpd_page_inquiry_data_pkt->params[6] = ISCSI_SCSI_VPD_PAGE_INQUIRY_DATA_PAGE_CODE_SCSI_PORTS; + vpd_page_inquiry_data_pkt->params[7] = ISCSI_SCSI_VPD_PAGE_INQUIRY_DATA_PAGE_CODE_BLOCK_LIMITS; + vpd_page_inquiry_data_pkt->params[8] = ISCSI_SCSI_VPD_PAGE_INQUIRY_DATA_PAGE_CODE_BLOCK_DEV_CHARS; + + alloc_len = 9U; + + if ( iscsi_scsi_emu_io_type_is_supported( image, ISCSI_SCSI_EMU_IO_TYPE_UNMAP ) ) { + vpd_page_inquiry_data_pkt->params[9] = ISCSI_SCSI_VPD_PAGE_INQUIRY_DATA_PAGE_CODE_THIN_PROVISION; + + alloc_len++; + } + + iscsi_put_be16( (uint8_t *) &vpd_page_inquiry_data_pkt->alloc_len, (uint16_t) alloc_len ); + + break; + } + case ISCSI_SCSI_VPD_PAGE_INQUIRY_DATA_PAGE_CODE_UNIT_SERIAL_NUMBER : { + const char *name = image->name; + + alloc_len = (uint) strlen( name ); + + if ( alloc_len >= (len - sizeof(struct iscsi_scsi_vpd_page_inquiry_data_packet)) ) + alloc_len = (uint) ((len - sizeof(struct iscsi_scsi_vpd_page_inquiry_data_packet)) - 1U); + + memcpy( vpd_page_inquiry_data_pkt->params, name, alloc_len ); + memset( (vpd_page_inquiry_data_pkt->params + alloc_len), '\0', (len - alloc_len - sizeof(struct iscsi_scsi_vpd_page_inquiry_data_packet)) ); + + alloc_len++; + + iscsi_put_be16( (uint8_t *) &vpd_page_inquiry_data_pkt->alloc_len, (uint16_t) alloc_len ); + + break; + } + case ISCSI_SCSI_VPD_PAGE_INQUIRY_DATA_PAGE_CODE_DEVICE_ID : { + const uint dev_name_len = (uint) strlen( (char *) device->name ) + 1U; + const uint port_name_len = (uint) strlen( (char *) port->name ) + 1U; + + alloc_len = (sizeof(struct iscsi_scsi_vpd_page_design_desc_inquiry_data_packet) + sizeof(struct iscsi_scsi_vpd_page_design_desc_ieee_naa_ext_inquiry_data_packet)); // 64-bit IEEE NAA Extended + alloc_len += (sizeof(struct iscsi_scsi_vpd_page_design_desc_inquiry_data_packet) + sizeof(struct iscsi_scsi_vpd_page_design_desc_t10_vendor_id_inquiry_data_packet)); // T10 Vendor ID + alloc_len += (uint) (sizeof(struct iscsi_scsi_vpd_page_design_desc_inquiry_data_packet) + iscsi_align(dev_name_len, ISCSI_ALIGN_SIZE)); // SCSI Device Name + alloc_len += (uint) (sizeof(struct iscsi_scsi_vpd_page_design_desc_inquiry_data_packet) + iscsi_align(port_name_len, ISCSI_ALIGN_SIZE)); // SCSI Target Port Name + alloc_len += (sizeof(struct iscsi_scsi_vpd_page_design_desc_inquiry_data_packet) + sizeof(struct iscsi_scsi_vpd_page_design_desc_rel_target_port_inquiry_data_packet)); // Relative Target Port + alloc_len += (sizeof(struct iscsi_scsi_vpd_page_design_desc_inquiry_data_packet) + sizeof(struct iscsi_scsi_vpd_page_design_desc_target_port_group_inquiry_data_packet)); // Target Port Group + alloc_len += (sizeof(struct iscsi_scsi_vpd_page_design_desc_inquiry_data_packet) + sizeof(struct iscsi_scsi_vpd_page_design_desc_logical_unit_group_inquiry_data_packet)); // Logical Unit Group + + if ( (alloc_len + sizeof(struct iscsi_scsi_vpd_page_inquiry_data_packet)) > len ) { + 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 ); + + return -1; + } + + iscsi_scsi_vpd_page_design_desc_inquiry_data_packet *vpd_page_design_desc_inquiry_data_pkt = (iscsi_scsi_vpd_page_design_desc_inquiry_data_packet *) vpd_page_inquiry_data_pkt->params; + + vpd_page_design_desc_inquiry_data_pkt->protocol_id_code_set = ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_PUT_CODE_SET(ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_CODE_SET_BINARY) | ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_PUT_PROTOCOL_ID(device->protocol_id); + vpd_page_design_desc_inquiry_data_pkt->flags = (int8_t) (ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_FLAGS_PUT_TYPE(ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_FLAGS_TYPE_NAA) | ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_FLAGS_PUT_ASSOC(ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_FLAGS_ASSOC_LOGICAL_UNIT) | ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_FLAGS_PIV); + vpd_page_design_desc_inquiry_data_pkt->reserved = 0U; + vpd_page_design_desc_inquiry_data_pkt->len = sizeof(struct iscsi_scsi_vpd_page_design_desc_ieee_naa_ext_inquiry_data_packet); + + iscsi_scsi_emu_naa_ieee_ext_set( (uint64_t *) vpd_page_design_desc_inquiry_data_pkt->desc, (uint8_t *) image->name ); + + alloc_len = (sizeof(struct iscsi_scsi_vpd_page_design_desc_inquiry_data_packet) + sizeof(struct iscsi_scsi_vpd_page_design_desc_ieee_naa_ext_inquiry_data_packet)); + + vpd_page_design_desc_inquiry_data_pkt = (iscsi_scsi_vpd_page_design_desc_inquiry_data_packet *) (((uint8_t *) vpd_page_design_desc_inquiry_data_pkt) + alloc_len); + vpd_page_design_desc_inquiry_data_pkt->protocol_id_code_set = ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_PUT_CODE_SET(ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_CODE_SET_ASCII) | ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_PUT_PROTOCOL_ID(device->protocol_id); + vpd_page_design_desc_inquiry_data_pkt->flags = (int8_t) (ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_FLAGS_PUT_TYPE(ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_FLAGS_TYPE_T10_VENDOR_ID) | ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_FLAGS_PUT_ASSOC(ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_FLAGS_ASSOC_LOGICAL_UNIT) | ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_FLAGS_PIV); + vpd_page_design_desc_inquiry_data_pkt->reserved = 0U; + vpd_page_design_desc_inquiry_data_pkt->len = sizeof(struct iscsi_scsi_vpd_page_design_desc_t10_vendor_id_inquiry_data_packet); + + iscsi_scsi_vpd_page_design_desc_t10_vendor_id_inquiry_data_packet *vpd_page_design_desc_t10_vendor_id_inquiry_data_pkt = (iscsi_scsi_vpd_page_design_desc_t10_vendor_id_inquiry_data_packet *) vpd_page_design_desc_inquiry_data_pkt->desc; + + iscsi_strcpy_pad( (char *) vpd_page_design_desc_t10_vendor_id_inquiry_data_pkt->vendor_id, ISCSI_SCSI_STD_INQUIRY_DATA_DISK_VENDOR_ID, sizeof(vpd_page_design_desc_t10_vendor_id_inquiry_data_pkt->vendor_id), ' ' ); + iscsi_strcpy_pad( (char *) vpd_page_design_desc_t10_vendor_id_inquiry_data_pkt->product_id, image->name, sizeof(vpd_page_design_desc_t10_vendor_id_inquiry_data_pkt->product_id), ' ' ); + iscsi_strcpy_pad( (char *) vpd_page_design_desc_t10_vendor_id_inquiry_data_pkt->unit_serial_num, image->path, sizeof(vpd_page_design_desc_t10_vendor_id_inquiry_data_pkt->unit_serial_num), ' ' ); + + alloc_len += (sizeof(struct iscsi_scsi_vpd_page_design_desc_inquiry_data_packet) + sizeof(struct iscsi_scsi_vpd_page_design_desc_t10_vendor_id_inquiry_data_packet)); + + vpd_page_design_desc_inquiry_data_pkt = (iscsi_scsi_vpd_page_design_desc_inquiry_data_packet *) (((uint8_t *) vpd_page_design_desc_inquiry_data_pkt) + (sizeof(struct iscsi_scsi_vpd_page_design_desc_inquiry_data_packet) + sizeof(struct iscsi_scsi_vpd_page_design_desc_t10_vendor_id_inquiry_data_packet))); + vpd_page_design_desc_inquiry_data_pkt->protocol_id_code_set = ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_PUT_CODE_SET(ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_CODE_SET_UTF8) | ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_PUT_PROTOCOL_ID(device->protocol_id); + vpd_page_design_desc_inquiry_data_pkt->flags = (int8_t) (ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_FLAGS_PUT_TYPE(ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_FLAGS_TYPE_SCSI_NAME) | ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_FLAGS_PUT_ASSOC(ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_FLAGS_ASSOC_TARGET_DEVICE) | ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_FLAGS_PIV); + vpd_page_design_desc_inquiry_data_pkt->reserved = 0U; + vpd_page_design_desc_inquiry_data_pkt->len = (uint8_t) iscsi_scsi_emu_pad_scsi_name( vpd_page_design_desc_inquiry_data_pkt->desc, device->name ); + + alloc_len += (uint) (sizeof(struct iscsi_scsi_vpd_page_design_desc_inquiry_data_packet) + vpd_page_design_desc_inquiry_data_pkt->len); + + vpd_page_design_desc_inquiry_data_pkt = (iscsi_scsi_vpd_page_design_desc_inquiry_data_packet *) (((uint8_t *) vpd_page_design_desc_inquiry_data_pkt) + (sizeof(struct iscsi_scsi_vpd_page_design_desc_inquiry_data_packet) + vpd_page_design_desc_inquiry_data_pkt->len)); + vpd_page_design_desc_inquiry_data_pkt->protocol_id_code_set = ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_PUT_CODE_SET(ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_CODE_SET_UTF8) | ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_PUT_PROTOCOL_ID(device->protocol_id); + vpd_page_design_desc_inquiry_data_pkt->flags = (int8_t) (ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_FLAGS_PUT_TYPE(ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_FLAGS_TYPE_SCSI_NAME) | ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_FLAGS_PUT_ASSOC(ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_FLAGS_ASSOC_TARGET_PORT) | ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_FLAGS_PIV); + vpd_page_design_desc_inquiry_data_pkt->reserved = 0U; + vpd_page_design_desc_inquiry_data_pkt->len = (uint8_t) iscsi_scsi_emu_pad_scsi_name( vpd_page_design_desc_inquiry_data_pkt->desc, port->name ); + + alloc_len += (uint) (sizeof(struct iscsi_scsi_vpd_page_design_desc_inquiry_data_packet) + vpd_page_design_desc_inquiry_data_pkt->len); + + vpd_page_design_desc_inquiry_data_pkt = (iscsi_scsi_vpd_page_design_desc_inquiry_data_packet *) (((uint8_t *) vpd_page_design_desc_inquiry_data_pkt) + (sizeof(struct iscsi_scsi_vpd_page_design_desc_inquiry_data_packet) + vpd_page_design_desc_inquiry_data_pkt->len)); + vpd_page_design_desc_inquiry_data_pkt->protocol_id_code_set = ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_PUT_CODE_SET(ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_CODE_SET_BINARY) | ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_PUT_PROTOCOL_ID(device->protocol_id); + vpd_page_design_desc_inquiry_data_pkt->flags = (int8_t) (ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_FLAGS_PUT_TYPE(ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_FLAGS_TYPE_REL_TARGET_PORT) | ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_FLAGS_PUT_ASSOC(ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_FLAGS_ASSOC_TARGET_PORT) | ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_FLAGS_PIV); + vpd_page_design_desc_inquiry_data_pkt->reserved = 0U; + vpd_page_design_desc_inquiry_data_pkt->len = sizeof(struct iscsi_scsi_vpd_page_design_desc_rel_target_port_inquiry_data_packet); + + iscsi_scsi_vpd_page_design_desc_rel_target_port_inquiry_data_packet *vpd_page_design_desc_rel_target_port_inquiry_data_pkt = (iscsi_scsi_vpd_page_design_desc_rel_target_port_inquiry_data_packet *) vpd_page_design_desc_inquiry_data_pkt->desc; + + vpd_page_design_desc_rel_target_port_inquiry_data_pkt->reserved = 0U; + iscsi_put_be16( (uint8_t *) &vpd_page_design_desc_rel_target_port_inquiry_data_pkt->index, port->index ); + + alloc_len += (sizeof(struct iscsi_scsi_vpd_page_design_desc_inquiry_data_packet) + sizeof(struct iscsi_scsi_vpd_page_design_desc_rel_target_port_inquiry_data_packet)); + + vpd_page_design_desc_inquiry_data_pkt = (iscsi_scsi_vpd_page_design_desc_inquiry_data_packet *) (((uint8_t *) vpd_page_design_desc_inquiry_data_pkt) + (sizeof(struct iscsi_scsi_vpd_page_design_desc_inquiry_data_packet) + sizeof(struct iscsi_scsi_vpd_page_design_desc_rel_target_port_inquiry_data_packet))); + vpd_page_design_desc_inquiry_data_pkt->protocol_id_code_set = ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_PUT_CODE_SET(ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_CODE_SET_BINARY) | ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_PUT_PROTOCOL_ID(device->protocol_id); + vpd_page_design_desc_inquiry_data_pkt->flags = (int8_t) (ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_FLAGS_PUT_TYPE(ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_FLAGS_TYPE_TARGET_PORT_GROUP) | ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_FLAGS_PUT_ASSOC(ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_FLAGS_ASSOC_TARGET_PORT) | ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_FLAGS_PIV); + vpd_page_design_desc_inquiry_data_pkt->reserved = 0U; + vpd_page_design_desc_inquiry_data_pkt->len = sizeof(struct iscsi_scsi_vpd_page_design_desc_target_port_group_inquiry_data_packet); + + iscsi_scsi_vpd_page_design_desc_target_port_group_inquiry_data_packet *vpd_page_design_desc_target_port_group_inquiry_data_pkt = (iscsi_scsi_vpd_page_design_desc_target_port_group_inquiry_data_packet *) vpd_page_design_desc_inquiry_data_pkt->desc; + + vpd_page_design_desc_target_port_group_inquiry_data_pkt->reserved = 0U; + vpd_page_design_desc_target_port_group_inquiry_data_pkt->index = 0U; + + alloc_len += (sizeof(struct iscsi_scsi_vpd_page_design_desc_inquiry_data_packet) + sizeof(struct iscsi_scsi_vpd_page_design_desc_target_port_group_inquiry_data_packet)); + + vpd_page_design_desc_inquiry_data_pkt = (iscsi_scsi_vpd_page_design_desc_inquiry_data_packet *) (((uint8_t *) vpd_page_design_desc_inquiry_data_pkt) + (sizeof(struct iscsi_scsi_vpd_page_design_desc_inquiry_data_packet) + sizeof(struct iscsi_scsi_vpd_page_design_desc_target_port_group_inquiry_data_packet))); + vpd_page_design_desc_inquiry_data_pkt->protocol_id_code_set = ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_PUT_CODE_SET(ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_CODE_SET_BINARY) | ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_PUT_PROTOCOL_ID(device->protocol_id); + vpd_page_design_desc_inquiry_data_pkt->flags = (int8_t) (ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_FLAGS_PUT_TYPE(ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_FLAGS_TYPE_LOGICAL_UNIT_GROUP) | ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_FLAGS_PUT_ASSOC(ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_FLAGS_ASSOC_LOGICAL_UNIT) | ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_FLAGS_PIV); + vpd_page_design_desc_inquiry_data_pkt->reserved = 0U; + vpd_page_design_desc_inquiry_data_pkt->len = sizeof(struct iscsi_scsi_vpd_page_design_desc_logical_unit_group_inquiry_data_packet); + + iscsi_scsi_vpd_page_design_desc_logical_unit_group_inquiry_data_packet *vpd_page_design_desc_logical_unit_group_inquiry_data_pkt = (iscsi_scsi_vpd_page_design_desc_logical_unit_group_inquiry_data_packet *) vpd_page_design_desc_inquiry_data_pkt->desc; + + vpd_page_design_desc_logical_unit_group_inquiry_data_pkt->reserved = 0U; + iscsi_put_be16( (uint8_t *) &vpd_page_design_desc_logical_unit_group_inquiry_data_pkt->id, (uint16_t) device->id ); + + alloc_len += (sizeof(struct iscsi_scsi_vpd_page_design_desc_inquiry_data_packet) + sizeof(struct iscsi_scsi_vpd_page_design_desc_logical_unit_group_inquiry_data_packet)); + + iscsi_put_be16( (uint8_t *) &vpd_page_inquiry_data_pkt->alloc_len, (uint16_t) alloc_len ); + + break; + } + case ISCSI_SCSI_VPD_PAGE_INQUIRY_DATA_PAGE_CODE_EXTENDED_INQUIRY_DATA : { + iscsi_scsi_vpd_page_ext_inquiry_data_packet *vpd_page_ext_inquiry_data_pkt = (iscsi_scsi_vpd_page_ext_inquiry_data_packet *) vpd_page_inquiry_data_pkt; + + alloc_len = (sizeof(iscsi_scsi_vpd_page_ext_inquiry_data_packet) - sizeof(iscsi_scsi_vpd_page_inquiry_data_packet)); + + if ( (alloc_len + sizeof(struct iscsi_scsi_vpd_page_inquiry_data_packet)) > len ) { + 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 ); + + return -1; + } + + vpd_page_ext_inquiry_data_pkt->reserved = 0U; + vpd_page_ext_inquiry_data_pkt->page_len = (uint8_t) alloc_len; + vpd_page_ext_inquiry_data_pkt->check_flags = 0; + vpd_page_ext_inquiry_data_pkt->support_flags = (ISCSI_SCSI_VPD_PAGE_EXT_INQUIRY_DATA_SUPPORT_FLAGS_SIMPSUP | ISCSI_SCSI_VPD_PAGE_EXT_INQUIRY_DATA_SUPPORT_FLAGS_HEADSUP); + vpd_page_ext_inquiry_data_pkt->support_flags_2 = 0; + vpd_page_ext_inquiry_data_pkt->luiclr = 0U; + vpd_page_ext_inquiry_data_pkt->cbcs = 0U; + vpd_page_ext_inquiry_data_pkt->micro_dl = 0U; + vpd_page_ext_inquiry_data_pkt->reserved2[0] = 0ULL; + vpd_page_ext_inquiry_data_pkt->reserved2[1] = 0ULL; + vpd_page_ext_inquiry_data_pkt->reserved2[2] = 0ULL; + vpd_page_ext_inquiry_data_pkt->reserved2[3] = 0ULL; + vpd_page_ext_inquiry_data_pkt->reserved2[4] = 0ULL; + vpd_page_ext_inquiry_data_pkt->reserved2[5] = 0ULL; + vpd_page_ext_inquiry_data_pkt->reserved3 = 0UL; + vpd_page_ext_inquiry_data_pkt->reserved4 = 0U; + + iscsi_put_be16( (uint8_t *) &vpd_page_inquiry_data_pkt->alloc_len, (uint16_t) alloc_len ); + + break; + } + case ISCSI_SCSI_VPD_PAGE_INQUIRY_DATA_PAGE_CODE_MANAGEMENT_NETWORK_ADDRS : { + alloc_len = 0U; + + vpd_page_inquiry_data_pkt->alloc_len = 0U; + + break; + } + case ISCSI_SCSI_VPD_PAGE_INQUIRY_DATA_PAGE_CODE_MODE_PAGE_POLICY : { + iscsi_scsi_vpd_mode_page_policy_desc_inquiry_data_packet *vpd_page_mode_page_policy_desc_inquiry_data_pkt = (iscsi_scsi_vpd_mode_page_policy_desc_inquiry_data_packet *) vpd_page_inquiry_data_pkt->params; + + alloc_len = sizeof(struct iscsi_scsi_vpd_mode_page_policy_desc_inquiry_data_packet); + + vpd_page_mode_page_policy_desc_inquiry_data_pkt->page_code = ISCSI_SCSI_VPD_MODE_PAGE_POLICY_DESC_INQUIRY_DATA_POLICY_PAGE_CODE_MASK; + vpd_page_mode_page_policy_desc_inquiry_data_pkt->sub_page_code = 0xFFU; + vpd_page_mode_page_policy_desc_inquiry_data_pkt->flags = 0U; + vpd_page_mode_page_policy_desc_inquiry_data_pkt->reserved = 0U; + + iscsi_put_be16( (uint8_t *) &vpd_page_inquiry_data_pkt->alloc_len, (uint16_t) alloc_len ); + + break; + } + case ISCSI_SCSI_VPD_PAGE_INQUIRY_DATA_PAGE_CODE_SCSI_PORTS : { + iscsi_scsi_emu_primary_inquiry_ports_fill port_report_fill = {(iscsi_scsi_vpd_scsi_port_design_dec_inquiry_data_packet *) vpd_page_inquiry_data_pkt->params, 0U, (uint) (len - sizeof(struct iscsi_scsi_vpd_page_inquiry_data_packet))}; + const int rc = iscsi_hashmap_iterate( device->ports, iscsi_scsi_emu_primary_inquiry_callback, (uint8_t *) &port_report_fill ); + + if ( rc < 0 ) { + 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 ); + + return -1; + } + + alloc_len = port_report_fill.alloc_len; + + iscsi_put_be16( (uint8_t *) &vpd_page_inquiry_data_pkt->alloc_len, (uint16_t) alloc_len ); + + break; + } + case ISCSI_SCSI_VPD_PAGE_INQUIRY_DATA_PAGE_CODE_BLOCK_LIMITS : { + iscsi_scsi_vpd_page_block_limits_inquiry_data_packet *vpd_page_block_limits_inquiry_data_pkt = (iscsi_scsi_vpd_page_block_limits_inquiry_data_packet *) vpd_page_inquiry_data_pkt->params; + + if ( (sizeof(struct iscsi_scsi_vpd_page_inquiry_data_packet) + sizeof(struct iscsi_scsi_vpd_page_block_limits_inquiry_data_packet)) > len ) { + 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 ); + + return -1; + } + + alloc_len = sizeof(struct iscsi_scsi_vpd_page_block_limits_inquiry_data_packet); + + uint32_t blocks = (ISCSI_SCSI_EMU_MAX_XFER_LEN >> iscsi_scsi_emu_block_get_size_shift( image )); + + if ( blocks > 255UL ) + blocks = 255UL; + + vpd_page_block_limits_inquiry_data_pkt->max_cmp_write_len = (uint8_t) blocks; + + uint32_t optimal_blocks = ISCSI_SCSI_EMU_BLOCK_SIZE >> iscsi_scsi_emu_block_get_size_shift( image ); + + if ( optimal_blocks == 0UL ) + optimal_blocks = 1UL; + + iscsi_put_be16( (uint8_t *) &vpd_page_block_limits_inquiry_data_pkt->optimal_granularity_xfer_len, (uint16_t) optimal_blocks ); + iscsi_put_be32( (uint8_t *) &vpd_page_block_limits_inquiry_data_pkt->max_xfer_len, blocks ); + iscsi_put_be32( (uint8_t *) &vpd_page_block_limits_inquiry_data_pkt->optimal_xfer_len, blocks ); + vpd_page_block_limits_inquiry_data_pkt->max_prefetch_len = 0UL; + + if ( iscsi_scsi_emu_io_type_is_supported( image, ISCSI_SCSI_EMU_IO_TYPE_UNMAP ) ) { + iscsi_put_be32( (uint8_t *) &vpd_page_block_limits_inquiry_data_pkt->max_unmap_lba_cnt, ISCSI_SCSI_EMU_MAX_UNMAP_LBA_COUNT ); + iscsi_put_be32( (uint8_t *) &vpd_page_block_limits_inquiry_data_pkt->max_unmap_block_desc_cnt, ISCSI_SCSI_EMU_MAX_UNMAP_BLOCK_DESC_COUNT ); + } else { + vpd_page_block_limits_inquiry_data_pkt->max_unmap_lba_cnt = 0UL; + vpd_page_block_limits_inquiry_data_pkt->max_unmap_block_desc_cnt = 0UL; + } + + vpd_page_block_limits_inquiry_data_pkt->optimal_unmap_granularity = 0UL; + vpd_page_block_limits_inquiry_data_pkt->unmap_granularity_align_ugavalid = 0UL; + iscsi_put_be64( (uint8_t *) &vpd_page_block_limits_inquiry_data_pkt->max_write_same_len, blocks ); + vpd_page_block_limits_inquiry_data_pkt->reserved[0] = 0ULL; + vpd_page_block_limits_inquiry_data_pkt->reserved[1] = 0ULL; + vpd_page_block_limits_inquiry_data_pkt->reserved2 = 0UL; + + iscsi_put_be16( (uint8_t *) &vpd_page_inquiry_data_pkt->alloc_len, (uint16_t) alloc_len ); + + break; + } + case ISCSI_SCSI_VPD_PAGE_INQUIRY_DATA_PAGE_CODE_BLOCK_DEV_CHARS : { + iscsi_scsi_vpd_page_block_dev_chars_inquiry_data_packet *vpd_page_block_dev_chars_inquiry_data_pkt = (iscsi_scsi_vpd_page_block_dev_chars_inquiry_data_packet *) vpd_page_inquiry_data_pkt->params; + + if ( (sizeof(struct iscsi_scsi_vpd_page_inquiry_data_packet) + sizeof(struct iscsi_scsi_vpd_page_block_dev_chars_inquiry_data_packet)) > len ) { + 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 ); + + return -1; + } + + alloc_len = sizeof(struct iscsi_scsi_vpd_page_block_dev_chars_inquiry_data_packet); + + vpd_page_block_dev_chars_inquiry_data_pkt->medium_rotation_rate = (iscsi_scsi_emu_io_type_is_supported( image, ISCSI_SCSI_EMU_IO_TYPE_NO_ROTATION ) ? ISCSI_SCSI_VPD_PAGE_BLOCK_DEV_CHARS_INQUIRY_DATA_MEDIUM_ROTATION_RATE_NONE : ISCSI_SCSI_VPD_PAGE_BLOCK_DEV_CHARS_INQUIRY_DATA_MEDIUM_ROTATION_RATE_NOT_REPORTED); + vpd_page_block_dev_chars_inquiry_data_pkt->product_type = ISCSI_SCSI_VPD_PAGE_BLOCK_DEV_CHARS_INQUIRY_DATA_PRODUCT_TYPE_NOT_INDICATED; + vpd_page_block_dev_chars_inquiry_data_pkt->flags = ISCSI_SCSI_VPD_PAGE_BLOCK_DEV_CHARS_INQUIRY_DATA_FLAGS_PUT_NOMINAL_FORM_FACTOR(ISCSI_SCSI_VPD_PAGE_BLOCK_DEV_CHARS_INQUIRY_DATA_FLAGS_NOMINAL_FORM_FACTOR_NOT_REPORTED); + vpd_page_block_dev_chars_inquiry_data_pkt->support_flags = 0U; + vpd_page_block_dev_chars_inquiry_data_pkt->reserved[0] = 0ULL; + vpd_page_block_dev_chars_inquiry_data_pkt->reserved[1] = 0ULL; + vpd_page_block_dev_chars_inquiry_data_pkt->reserved[2] = 0ULL; + vpd_page_block_dev_chars_inquiry_data_pkt->reserved[3] = 0ULL; + vpd_page_block_dev_chars_inquiry_data_pkt->reserved[4] = 0ULL; + vpd_page_block_dev_chars_inquiry_data_pkt->reserved[5] = 0ULL; + vpd_page_block_dev_chars_inquiry_data_pkt->reserved2 = 0UL; + vpd_page_block_dev_chars_inquiry_data_pkt->reserved3 = 0U; + vpd_page_block_dev_chars_inquiry_data_pkt->reserved4 = 0U; + + iscsi_put_be16( (uint8_t *) &vpd_page_inquiry_data_pkt->alloc_len, (uint16_t) alloc_len ); + + break; + } + case ISCSI_SCSI_VPD_PAGE_INQUIRY_DATA_PAGE_CODE_THIN_PROVISION : { + if ( !iscsi_scsi_emu_io_type_is_supported( image, ISCSI_SCSI_EMU_IO_TYPE_UNMAP ) ) { + scsi_task->pos = 0U; + + iscsi_scsi_task_status_set( scsi_task, ISCSI_SCSI_STATUS_CHECK_COND, ISCSI_SCSI_SENSE_KEY_NO_SENSE, ISCSI_SCSI_ASC_NO_ADDITIONAL_SENSE, ISCSI_SCSI_ASCQ_CAUSE_NOT_REPORTABLE ); + + return -1; + } + + iscsi_scsi_vpd_page_thin_provision_inquiry_data_packet *vpd_page_thin_provision_inquiry_data_pkt = (iscsi_scsi_vpd_page_thin_provision_inquiry_data_packet *) vpd_page_inquiry_data_pkt->params; + + alloc_len = sizeof(struct iscsi_scsi_vpd_page_thin_provision_inquiry_data_packet); + + vpd_page_thin_provision_inquiry_data_pkt->threshold_exponent = 0U; + vpd_page_thin_provision_inquiry_data_pkt->flags = (int8_t) ISCSI_SCSI_VPD_PAGE_THIN_PROVISION_INQUIRY_DATA_FLAGS_LBPU; + vpd_page_thin_provision_inquiry_data_pkt->provision_type = ISCSI_SCSI_VPD_PAGE_THIN_PROVISION_INQUIRY_DATA_PUT_PROVISION_TYPE(ISCSI_SCSI_VPD_PAGE_THIN_PROVISION_INQUIRY_DATA_PROVISION_TYPE_THIN_PROVISIONING); + vpd_page_thin_provision_inquiry_data_pkt->reserved = 0U; + + iscsi_put_be16( (uint8_t *) &vpd_page_inquiry_data_pkt->alloc_len, (uint16_t) alloc_len ); + + break; + } + default : { + scsi_task->pos = 0U; + + iscsi_scsi_task_status_set( scsi_task, ISCSI_SCSI_STATUS_CHECK_COND, ISCSI_SCSI_SENSE_KEY_NO_SENSE, ISCSI_SCSI_ASC_NO_ADDITIONAL_SENSE, ISCSI_SCSI_ASCQ_CAUSE_NOT_REPORTABLE ); + + return -1; + + break; + } + } + + return (int) (alloc_len + sizeof(struct iscsi_scsi_vpd_page_inquiry_data_packet)); + } else { + const uint8_t pti = ISCSI_SCSI_BASIC_INQUIRY_DATA_PUT_PERIPHERAL_TYPE(ISCSI_SCSI_BASIC_INQUIRY_DATA_PERIPHERAL_TYPE_DIRECT) | ISCSI_SCSI_BASIC_INQUIRY_DATA_PUT_PERIPHERAL_ID(ISCSI_SCSI_BASIC_INQUIRY_DATA_PERIPHERAL_ID_POSSIBLE); + + std_inquiry_data_pkt->basic_inquiry.peripheral_type_id = pti; + std_inquiry_data_pkt->basic_inquiry.peripheral_type_mod_flags = (int8_t) (iscsi_scsi_emu_io_type_is_supported( image, ISCSI_SCSI_EMU_IO_TYPE_REMOVABLE ) ? ISCSI_SCSI_BASIC_INQUIRY_DATA_PERIPHERAL_TYPE_MOD_FLAGS_REMOVABLE_MEDIA : 0); + std_inquiry_data_pkt->basic_inquiry.version = ISCSI_SCSI_BASIC_INQUIRY_DATA_PUT_VERSION_ANSI(ISCSI_SCSI_BASIC_INQUIRY_DATA_VERSION_ANSI_SPC3); + std_inquiry_data_pkt->basic_inquiry.response_data_fmt_flags = ISCSI_SCSI_BASIC_INQUIRY_DATA_PUT_RESPONSE_DATA_FMT_FLAGS(ISCSI_SCSI_BASIC_INQUIRY_DATA_RESPONSE_DATA_FMT_FLAGS_SCSI_2) | ISCSI_SCSI_BASIC_INQUIRY_DATA_RESPONSE_DATA_FMT_FLAGS_HISUP; + + std_inquiry_data_pkt->tpgs_flags = 0U; + std_inquiry_data_pkt->services_flags = ISCSI_SCSI_STD_INQUIRY_DATA_SERVICES_FLAGS_MULTIP; + std_inquiry_data_pkt->flags = ISCSI_SCSI_STD_INQUIRY_DATA_FLAGS_COMMAND_QUEUE; + + iscsi_strcpy_pad( (char *) std_inquiry_data_pkt->vendor_id, ISCSI_SCSI_STD_INQUIRY_DATA_DISK_VENDOR_ID, sizeof(std_inquiry_data_pkt->vendor_id), ' ' ); + iscsi_strcpy_pad( (char *) std_inquiry_data_pkt->product_id, image->name, sizeof(std_inquiry_data_pkt->product_id), ' ' ); + + char image_rev[sizeof(std_inquiry_data_pkt->product_rev_level) + 1]; + + sprintf( "%04X", image_rev, image->rid ); + iscsi_strcpy_pad( image_rev, (char *) std_inquiry_data_pkt->product_rev_level, sizeof(std_inquiry_data_pkt->product_rev_level), ' ' ); + + uint add_len = (sizeof(struct iscsi_scsi_std_inquiry_data_packet) - sizeof(struct iscsi_scsi_basic_inquiry_data_packet)); + iscsi_scsi_ext_inquiry_data_packet *ext_inquiry_data_pkt = (iscsi_scsi_ext_inquiry_data_packet *) std_inquiry_data_pkt; + + if ( len >= ISCSI_NEXT_OFFSET(iscsi_scsi_ext_inquiry_data_packet, vendor_spec) ) { + iscsi_strcpy_pad( (char *) ext_inquiry_data_pkt->vendor_spec, ISCSI_SCSI_EXT_INQUIRY_DATA_VENDOR_SPEC_ID, sizeof(ext_inquiry_data_pkt->vendor_spec), ' ' ); + + add_len += sizeof(ext_inquiry_data_pkt->vendor_spec); + } + + if ( len >= ISCSI_NEXT_OFFSET(iscsi_scsi_ext_inquiry_data_packet, flags) ) { + ext_inquiry_data_pkt->flags = 0; + + add_len += sizeof(ext_inquiry_data_pkt->flags); + } + + if ( len >= ISCSI_NEXT_OFFSET(iscsi_scsi_ext_inquiry_data_packet, reserved) ) { + ext_inquiry_data_pkt->reserved = 0; + + add_len += sizeof(ext_inquiry_data_pkt->reserved); + } + + if ( len >= ISCSI_NEXT_OFFSET(iscsi_scsi_ext_inquiry_data_packet, version_desc[0]) ) { + iscsi_put_be16( (uint8_t *) &ext_inquiry_data_pkt->version_desc[0], ISCSI_SCSI_EXT_INQUIRY_DATA_VERSION_DESC_ISCSI_NO_VERSION ); + + add_len += sizeof(ext_inquiry_data_pkt->version_desc[0]); + } + + if ( len >= ISCSI_NEXT_OFFSET(iscsi_scsi_ext_inquiry_data_packet, version_desc[1]) ) { + iscsi_put_be16( (uint8_t *) &ext_inquiry_data_pkt->version_desc[1], ISCSI_SCSI_EXT_INQUIRY_DATA_VERSION_DESC_SPC3_NO_VERSION ); + + add_len += sizeof(ext_inquiry_data_pkt->version_desc[1]); + } + + if ( len >= ISCSI_NEXT_OFFSET(iscsi_scsi_ext_inquiry_data_packet, version_desc[2]) ) { + iscsi_put_be16( (uint8_t *) &ext_inquiry_data_pkt->version_desc[2], ISCSI_SCSI_EXT_INQUIRY_DATA_VERSION_DESC_SBC2_NO_VERSION ); + + add_len += sizeof(ext_inquiry_data_pkt->version_desc[2]); + } + + if ( len >= ISCSI_NEXT_OFFSET(iscsi_scsi_ext_inquiry_data_packet, version_desc[3]) ) { + iscsi_put_be16( (uint8_t *) &ext_inquiry_data_pkt->version_desc[3], ISCSI_SCSI_EXT_INQUIRY_DATA_VERSION_DESC_SAM2_NO_VERSION ); + + add_len += sizeof(ext_inquiry_data_pkt->version_desc[3]); + } + + if ( len >= ISCSI_NEXT_OFFSET(iscsi_scsi_ext_inquiry_data_packet, version_desc[4]) ) { + uint alloc_len = (uint) (len - offsetof(iscsi_scsi_ext_inquiry_data_packet, version_desc[4])); + + if ( alloc_len > (sizeof(struct iscsi_scsi_ext_inquiry_data_packet) - offsetof(iscsi_scsi_ext_inquiry_data_packet, version_desc[4])) ) + alloc_len = (sizeof(struct iscsi_scsi_ext_inquiry_data_packet) - offsetof(iscsi_scsi_ext_inquiry_data_packet, version_desc[4])); + + memset( &ext_inquiry_data_pkt->version_desc[4], 0, alloc_len ); + add_len += alloc_len; + } + + std_inquiry_data_pkt->basic_inquiry.add_len = (uint8_t) add_len; + + return (int) (add_len + sizeof(struct iscsi_scsi_basic_inquiry_data_packet)); + } } /** @@ -6103,10 +6709,11 @@ int iscsi_port_transport_id_set(iscsi_port *port, const uint8_t *name, const uin * may NOT be NULL, so be careful. * @param[in] luns Maximum number of LUNs for this * iSCSI device. + * @param[in] protocol_id Protocol identifier. * @return Pointer to iSCSI device or NULL in * case of an error. */ -iscsi_device *iscsi_device_create(const uint8_t *name, const uint luns) +iscsi_device *iscsi_device_create(const uint8_t *name, const uint luns, const uint8_t protocol_id) { if ( luns == 0 ) return NULL; @@ -6186,9 +6793,10 @@ iscsi_device *iscsi_device_create(const uint8_t *name, const uint luns) return NULL; } - device->id = 0; - device->flags = 0; - device->num_ports = 0U; + device->id = 0; + device->flags = 0; + device->num_ports = 0U; + device->protocol_id = protocol_id; return device; } @@ -6456,7 +7064,7 @@ iscsi_target_node *iscsi_target_node_create(const uint8_t *name, const uint8_t * memcpy( target->alias, alias, alias_len ); } - target->device = iscsi_device_create( name, luns ); + target->device = iscsi_device_create( name, luns, ISCSI_TRANSPORT_ID_PROTOCOL_ID_ISCSI ); if ( target->device == NULL ) { logadd( LOG_ERROR, "iscsi_target_node_create: Out of memory allocating iSCSI target device" ); @@ -7769,35 +8377,35 @@ int iscsi_connection_copy_key_value_pairs(iscsi_connection *conn) conn->data_digest = (strcasecmp( (char *) value, "CRC32C" ) == 0) ? ISCSI_DIGEST_SIZE : 0; - rc = iscsi_get_int_key_value_pair( conn->key_value_pairs, ISCSI_LOGIN_AUTH_SESSION_TEXT_KEY_MAX_CONNECTIONS, &int_val); + rc = iscsi_get_int_key_value_pair( conn->session->key_value_pairs, ISCSI_LOGIN_AUTH_SESSION_TEXT_KEY_MAX_CONNECTIONS, &int_val); if ( rc != 0 ) return rc; conn->session->max_conns = int_val; - rc = iscsi_get_int_key_value_pair( conn->key_value_pairs, ISCSI_LOGIN_AUTH_SESSION_TEXT_KEY_MAX_OUTSTANDING_R2T, &int_val); + rc = iscsi_get_int_key_value_pair( conn->session->key_value_pairs, ISCSI_LOGIN_AUTH_SESSION_TEXT_KEY_MAX_OUTSTANDING_R2T, &int_val); if ( rc != 0 ) return rc; conn->session->max_outstanding_r2t = int_val; - rc = iscsi_get_int_key_value_pair( conn->key_value_pairs, ISCSI_LOGIN_AUTH_SESSION_TEXT_KEY_FIRST_BURST_LEN, &int_val); + rc = iscsi_get_int_key_value_pair( conn->session->key_value_pairs, ISCSI_LOGIN_AUTH_SESSION_TEXT_KEY_FIRST_BURST_LEN, &int_val); if ( rc != 0 ) return rc; conn->session->first_burst_len = int_val; - rc = iscsi_get_int_key_value_pair( conn->key_value_pairs, ISCSI_LOGIN_AUTH_SESSION_TEXT_KEY_MAX_BURST_LEN, &int_val); + rc = iscsi_get_int_key_value_pair( conn->session->key_value_pairs, ISCSI_LOGIN_AUTH_SESSION_TEXT_KEY_MAX_BURST_LEN, &int_val); if ( rc != 0 ) return rc; conn->session->max_burst_len = int_val; - rc = iscsi_get_bool_key_value_pair( conn->key_value_pairs, ISCSI_LOGIN_AUTH_SESSION_TEXT_KEY_INITIAL_R2T, &int_val); + rc = iscsi_get_bool_key_value_pair( conn->session->key_value_pairs, ISCSI_LOGIN_AUTH_SESSION_TEXT_KEY_INITIAL_R2T, &int_val); if ( rc != 0 ) return rc; @@ -7807,7 +8415,7 @@ int iscsi_connection_copy_key_value_pairs(iscsi_connection *conn) if ( int_val != 0 ) conn->session->flags |= ISCSI_SESSION_FLAGS_INIT_R2T; - rc = iscsi_get_bool_key_value_pair( conn->key_value_pairs, ISCSI_LOGIN_AUTH_SESSION_TEXT_KEY_IMMEDIATE_DATA, &int_val); + rc = iscsi_get_bool_key_value_pair( conn->session->key_value_pairs, ISCSI_LOGIN_AUTH_SESSION_TEXT_KEY_IMMEDIATE_DATA, &int_val); if ( rc != 0 ) return rc; diff --git a/src/server/iscsi.h b/src/server/iscsi.h index 315ad2c..91cb447 100644 --- a/src/server/iscsi.h +++ b/src/server/iscsi.h @@ -151,6 +151,10 @@ static inline void iscsi_put_be64(uint8_t *data, const uint64_t val) #endif +/// Determines the next offset after member b of struct a. +#define ISCSI_NEXT_OFFSET(a, b) (offsetof(struct a, b) + sizeof(((struct a *) 0)->b)) + + /// Bit sequence manipulation double word (32 bits) mask bits: Gets mask for filtering out a bit range between a and b, b may NOT exceed 30 bits range. #define ISCSI_BITS_GET_MASK(a, b) (((1U << (a)) - 1U) ^ ((1U << ((b) + 1U)) - 1U)) @@ -202,7 +206,7 @@ uint8_t *iscsi_vsprintf_append_realloc(char *buf, const char *format, va_list ar uint8_t *iscsi_sprintf_append_realloc(char *buf, const char *format, ...); // Allocates and appends a buffer and sprintf's it uint8_t *iscsi_vsprintf_alloc(const char *format, va_list args); // Allocates a buffer and sprintf's it uint8_t *iscsi_sprintf_alloc(const char *format, ... ); // Allocates a buffer and sprintf's it - +void iscsi_strcpy_pad(char *dst, const char *src, const size_t size, const int pad); // Copies a string with additional padding character to fill in a specified size /// Shift factor for default capacity. #define ISCSI_HASHMAP_DEFAULT_CAPACITY_SHIFT 5UL @@ -730,6 +734,13 @@ typedef struct __attribute__((packed)) iscsi_scsi_cdb { } iscsi_scsi_cdb; +/// iSCSI SCSI Command Descriptor Block (CDB) for INQUIRY command flags: Enable Vital Product Data (EVPD). +#define ISCSI_SCSI_CDB_INQUIRY_FLAGS_EVPD (1 << 0) + +/// iSCSI SCSI Command Descriptor Block (CDB) for INQUIRY command flags: Command Support Data (CMDDT). +#define ISCSI_SCSI_CDB_INQUIRY_FLAGS_CMDDT (1 << 1) + + /** * @brief iSCSI SCSI CDB packet data structure for SCSI INQUIRY command. * @@ -739,8 +750,8 @@ typedef struct __attribute__((packed)) iscsi_scsi_cdb_inquiry { /// SCSI opcode. iscsi_scsi_cdb cdb; - /// Logical Unit Number (LUN) and EVPD. - uint8_t lun_evpd; + /// Logical Unit Number (LUN), CMMDT and EVPD. + uint8_t lun_flags; /// Page code. uint8_t page_code; @@ -1375,470 +1386,1630 @@ typedef struct __attribute__((packed)) iscsi_scsi_cdb_pr_reserve_out { /// Service action. uint8_t action; - /// Scope and reservation type. - uint8_t scope_type; + /// Scope and reservation type. + uint8_t scope_type; + + /// Reserved for future usage (always MUST be 0 for now). + uint16_t reserved; + + /// Parameter list length in bytes. + uint32_t param_list_len; + + /// Control. + uint8_t control; +} iscsi_scsi_cdb_pr_reserve_out; + + +/// iSCSI SCSI Command Descriptor Block (CDB) for PERSISTENT RESERVE IN command service action: Read keys - Reads all registered reservation keys (i.e. registrations) as described in SPC5. +#define ISCSI_SCSI_CDB_PR_RESERVE_IN_ACTION_READ_KEYS 0x00 + +/// iSCSI SCSI Command Descriptor Block (CDB) for PERSISTENT RESERVE IN command service action: Read reservations - Reads the current persistent reservations as described in SPC5. +#define ISCSI_SCSI_CDB_PR_RESERVE_IN_ACTION_READ_RESERVATIONS 0x01 + +/// iSCSI SCSI Command Descriptor Block (CDB) for PERSISTENT RESERVE IN command service action: Report capabilities - Returns capability information. +#define ISCSI_SCSI_CDB_PR_RESERVE_IN_ACTION_READ_REPORT_CAPABILITIES 0x02 + +/// iSCSI SCSI Command Descriptor Block (CDB) for PERSISTENT RESERVE IN command service action: Read full status – Reads complete information about all registrations and the persistent reservations, if any. +#define ISCSI_SCSI_CDB_PR_RESERVE_IN_ACTION_READ_FULL_STATUS 0x03 + +/// iSCSI SCSI Command Descriptor Block (CDB) for PERSISTENT RESERVE IN command service action: First bit of the five bits. +#define ISCSI_SCSI_CDB_PR_RESERVE_IN_ACTION_FIRST_BIT 0 + +/// iSCSI SCSI Command Descriptor Block (CDB) for PERSISTENT RESERVE IN command service action: Last bit of the five bits. +#define ISCSI_SCSI_CDB_PR_RESERVE_IN_ACTION_LAST_BIT ((ISCSI_SCSI_CDB_PR_RESERVE_IN_ACTION_FIRST_BIT) + 5 - 1) + +/// iSCSI SCSI Command Descriptor Block (CDB) for PERSISTENT RESERVE IN command service action: Bit mask. +#define ISCSI_SCSI_CDB_PR_RESERVE_IN_ACTION_MASK (ISCSI_BITS_GET_MASK(ISCSI_SCSI_CDB_PR_RESERVE_IN_ACTION_FIRST_BIT, ISCSI_SCSI_CDB_PR_RESERVE_IN_ACTION_LAST_BIT)) + +/// iSCSI SCSI Command Descriptor Block (CDB) for PERSISTENT RESERVE IN command service action: Extracts the service action bits. +#define ISCSI_SCSI_CDB_PR_RESERVE_IN_GET_ACTION(x) (ISCSI_BITS_GET((x), ISCSI_SCSI_CDB_PR_RESERVE_IN_ACTION_FIRST_BIT, ISCSI_SCSI_CDB_PR_RESERVE_IN_ACTION_LAST_BIT)) + +/// iSCSI SCSI Command Descriptor Block (CDB) for PERSISTENT RESERVE IN command service action: Stores into the service action bits. +#define ISCSI_SCSI_CDB_PR_RESERVE_IN_PUT_ACTION(x) (ISCSI_BITS_PUT((x), ISCSI_SCSI_CDB_PR_RESERVE_IN_ACTION_FIRST_BIT, ISCSI_SCSI_CDB_PR_RESERVE_IN_ACTION_LAST_BIT)) + + +/** + * @brief iSCSI SCSI CDB packet data structure for SCSI PERSISTENT RESERVE IN command. + * + * There are 10 bytes in the CDB field for this command. + */ +typedef struct __attribute__((packed)) iscsi_scsi_cdb_pr_reserve_in { + /// SCSI opcode. + iscsi_scsi_cdb cdb; + + /// Service action. + uint8_t action; + + /// Reserved for future usage (always MUST be 0 for now). + uint32_t reserved; + + /// Reserved for future usage (always MUST be 0 for now). + uint8_t reserved2; + + /// Parameter list length in bytes. + uint16_t param_list_len; + + /// Control. + uint8_t control; +} iscsi_scsi_cdb_pr_reserve_in; + + +/** + * @brief iSCSI SCSI CDB packet data structure for SCSI RESERVE(6) command. + * + * There are 6 bytes in the CDB field for this command. + */ +typedef struct __attribute__((packed)) iscsi_scsi_cdb_pr_reserve_6 { + /// SCSI opcode. + iscsi_scsi_cdb cdb; + + /// Reserved for future usage (always MUST be 0 for now). + uint8_t reserved_obselete; + + /// Obselete byte. + uint8_t obselete; + + /// Obselete word. + uint16_t obselete2; + + /// Control. + uint8_t control; +} iscsi_scsi_cdb_pr_reserve_6; + + +/// iSCSI SCSI Command Descriptor Block (CDB) for RESERVE(10) command flags: Long identifier larger than 255 (LONGID). +#define ISCSI_SCSI_CDB_RESERVE_10_FLAGS_LONGID (1 << 1) + +/// iSCSI SCSI Command Descriptor Block (CDB) for RESERVE(10) command flags: Third-party reservation (3RDPTY). +#define ISCSI_SCSI_CDB_RESERVE_10_FLAGS_3RDPTY (1 << 4) + + +/** + * @brief iSCSI SCSI CDB packet data structure for SCSI RESERVE(10) command. + * + * There are 10 bytes in the CDB field for this command. + */ +typedef struct __attribute__((packed)) iscsi_scsi_cdb_pr_reserve_10 { + /// SCSI opcode. + iscsi_scsi_cdb cdb; + + /// Flags. + int8_t flags; + + /// Obselete. + uint8_t obselete; + + /// Third-party device identifier. + uint8_t third_party_dev_id; + + /// Reserved for future usage (always MUST be 0 for now). + uint16_t reserved; + + /// Reserved for future usage (always MUST be 0 for now). + uint8_t reserved2; + + /// Parameter list length in bytes. + uint16_t param_list_len; + + /// Control. + uint8_t control; +} iscsi_scsi_cdb_pr_reserve_10; + + +/** + * @brief iSCSI SCSI CDB packet data structure for SCSI RELEASE(6) command. + * + * There are 6 bytes in the CDB field for this command. + */ +typedef struct __attribute__((packed)) iscsi_scsi_cdb_pr_release_6 { + /// SCSI opcode. + iscsi_scsi_cdb cdb; + + /// Reserved for future usage (always MUST be 0 for now). + uint8_t reserved_obselete; + + /// Obselete byte. + uint8_t obselete; + + /// Obselete word. + uint16_t obselete2; + + /// Control. + uint8_t control; +} iscsi_scsi_cdb_pr_release_6; + + +/// iSCSI SCSI Command Descriptor Block (CDB) for RELEASE(10) command flags: Long identifier larger than 255 (LONGID). +#define ISCSI_SCSI_CDB_RELEASE_10_FLAGS_LONGID (1 << 1) + +/// iSCSI SCSI Command Descriptor Block (CDB) for RELEASE(10) command flags: Third-party reservation (3RDPTY). +#define ISCSI_SCSI_CDB_RELEASE_10_FLAGS_3RDPTY (1 << 4) + + +/** + * @brief iSCSI SCSI CDB packet data structure for SCSI RELEASE(10) command. + * + * There are 10 bytes in the CDB field for this command. + */ +typedef struct __attribute__((packed)) iscsi_scsi_cdb_pr_release_10 { + /// SCSI opcode. + iscsi_scsi_cdb cdb; + + /// Flags. + int8_t flags; + + /// Obselete. + uint8_t obselete; + + /// Third-party device identifier. + uint8_t third_party_dev_id; + + /// Reserved for future usage (always MUST be 0 for now). + uint16_t reserved; + + /// Reserved for future usage (always MUST be 0 for now). + uint8_t reserved2; + + /// Parameter list length in bytes. + uint16_t param_list_len; + + /// Control. + uint8_t control; +} iscsi_scsi_cdb_pr_release_10; + + +/** + * @brief iSCSI SCSI DataSegment Command packet structure. + * + * iSCSI targets MUST support and enable Autosense. If Status is CHECK + * CONDITION (0x02), then the data segment MUST contain sense data for + * the failed command. + * + * For some iSCSI responses, the response data segment MAY contain some + * response-related information (e.g., for a target failure, it may + * contain a vendor-specific detailed description of the failure). + */ +typedef struct __attribute__((packed)) iscsi_scsi_ds_cmd_data { + /// SenseLength: This field indicates the length of Sense Data. + uint16_t len; + + /// The Sense Data contains detailed information about a CHECK CONDITION. SPC3 specifies the format and content of the Sense Data. + uint8_t sense_data[0]; + + /// Response Data. + uint8_t res_data[0]; +} iscsi_scsi_ds_cmd_data; + + +/// iSCSI SCSI Basic Inquiry Data peripheral type: Direct access device. +#define ISCSI_SCSI_BASIC_INQUIRY_DATA_PERIPHERAL_TYPE_DIRECT 0x00 + +/// iSCSI SCSI Basic Inquiry Data peripheral type: Sequential access device. +#define ISCSI_SCSI_BASIC_INQUIRY_DATA_PERIPHERAL_TYPE_SEQ 0x01 + +/// iSCSI SCSI Basic Inquiry Data peripheral type: Printer device. +#define ISCSI_SCSI_BASIC_INQUIRY_DATA_PERIPHERAL_TYPE_PRINTER 0x02 + +/// iSCSI SCSI Basic Inquiry Data peripheral type: Processor device. +#define ISCSI_SCSI_BASIC_INQUIRY_DATA_PERIPHERAL_TYPE_PROCESSOR 0x03 + +/// iSCSI SCSI Basic Inquiry Data peripheral type: Write once device. +#define ISCSI_SCSI_BASIC_INQUIRY_DATA_PERIPHERAL_TYPE_WORM 0x04 + +/// iSCSI SCSI Basic Inquiry Data peripheral type: Read only direct access (e.g. CD-ROM) device. +#define ISCSI_SCSI_BASIC_INQUIRY_DATA_PERIPHERAL_TYPE_RO_DIRECT 0x05 + +/// iSCSI SCSI Basic Inquiry Data peripheral type: Scanner device. +#define ISCSI_SCSI_BASIC_INQUIRY_DATA_PERIPHERAL_TYPE_SCANNER 0x06 + +/// iSCSI SCSI Basic Inquiry Data peripheral type: Optical memory device. +#define ISCSI_SCSI_BASIC_INQUIRY_DATA_PERIPHERAL_TYPE_OPTICAL 0x07 + +/// iSCSI SCSI Basic Inquiry Data peripheral type: Medium changer device. +#define ISCSI_SCSI_BASIC_INQUIRY_DATA_PERIPHERAL_TYPE_CHANGER 0x08 + +/// iSCSI SCSI Basic Inquiry Data peripheral type: Communications device. +#define ISCSI_SCSI_BASIC_INQUIRY_DATA_PERIPHERAL_TYPE_COMM 0x09 + +/// iSCSI SCSI Basic Inquiry Data peripheral type: Unknown or no device. +#define ISCSI_SCSI_BASIC_INQUIRY_DATA_PERIPHERAL_TYPE_UNKNOWN 0x1F + +/// iSCSI SCSI Basic Inquiry Data peripheral type: First bit of the five bits. +#define ISCSI_SCSI_BASIC_INQUIRY_DATA_PERIPHERAL_TYPE_FIRST_BIT 0 + +/// iSCSI SCSI Basic Inquiry Data peripheral type: Last bit of the five bits. +#define ISCSI_SCSI_BASIC_INQUIRY_DATA_PERIPHERAL_TYPE_LAST_BIT ((ISCSI_SCSI_BASIC_INQUIRY_DATA_PERIPHERAL_TYPE_FIRST_BIT) + 5 - 1) + +/// iSCSI SCSI Basic Inquiry Data peripheral type: Bit mask. +#define ISCSI_SCSI_BASIC_INQUIRY_DATA_PERIPHERAL_TYPE_MASK (ISCSI_BITS_GET_MASK(ISCSI_SCSI_BASIC_INQUIRY_DATA_PERIPHERAL_TYPE_FIRST_BIT, ISCSI_SCSI_BASIC_INQUIRY_DATA_PERIPHERAL_TYPE_LAST_BIT)) + +/// iSCSI SCSI Basic Inquiry Data peripheral type: Extracts the peripheral device type bits. +#define ISCSI_SCSI_BASIC_INQUIRY_DATA_GET_PERIPHERAL_TYPE(x) (ISCSI_BITS_GET((x), ISCSI_SCSI_BASIC_INQUIRY_DATA_PERIPHERAL_TYPE_FIRST_BIT, ISCSI_SCSI_BASIC_INQUIRY_DATA_PERIPHERAL_TYPE_LAST_BIT)) + +/// iSCSI SCSI Basic Inquiry Data peripheral type: Stores into the peripheral device type bits. +#define ISCSI_SCSI_BASIC_INQUIRY_DATA_PUT_PERIPHERAL_TYPE(x) (ISCSI_BITS_PUT((x), ISCSI_SCSI_BASIC_INQUIRY_DATA_PERIPHERAL_TYPE_FIRST_BIT, ISCSI_SCSI_BASIC_INQUIRY_DATA_PERIPHERAL_TYPE_LAST_BIT)) + +/// iSCSI SCSI Basic Inquiry Data peripheral identifier: The specified peripheral device type is currently connected to this logical unit, or connection state could not be determined. +#define ISCSI_SCSI_BASIC_INQUIRY_DATA_PERIPHERAL_ID_POSSIBLE 0x0 + +/// iSCSI SCSI Basic Inquiry Data peripheral identifier: The target is capable of supporting the specified peripheral device type on this logical unit, but not connected. +#define ISCSI_SCSI_BASIC_INQUIRY_DATA_PERIPHERAL_ID_SUPPORTED 0x1 + +/// iSCSI SCSI Basic Inquiry Data peripheral identifier: The target is not capable of supporting a physical device on this logical unit. +#define ISCSI_SCSI_BASIC_INQUIRY_DATA_PERIPHERAL_ID_NEVER 0x3 + +/// iSCSI SCSI Basic Inquiry Data peripheral identifier: Vendor specific. +#define ISCSI_SCSI_BASIC_INQUIRY_DATA_PERIPHERAL_ID_VENDOR_UNIQ 0x4 + +/// iSCSI SCSI Basic Inquiry Data peripheral identifier: First bit of the three bits. +#define ISCSI_SCSI_BASIC_INQUIRY_DATA_PERIPHERAL_ID_FIRST_BIT 5 + +/// iSCSI SCSI Basic Inquiry Data peripheral identifier: Last bit of the three bits. +#define ISCSI_SCSI_BASIC_INQUIRY_DATA_PERIPHERAL_ID_LAST_BIT ((ISCSI_SCSI_BASIC_INQUIRY_DATA_PERIPHERAL_ID_FIRST_BIT) + 3 - 1) + +/// iSCSI SCSI Basic Inquiry Data peripheral identifier: Bit mask. +#define ISCSI_SCSI_BASIC_INQUIRY_DATA_PERIPHERAL_ID_MASK (ISCSI_BITS_GET_MASK(ISCSI_SCSI_BASIC_INQUIRY_DATA_PERIPHERAL_ID_FIRST_BIT, ISCSI_SCSI_BASIC_INQUIRY_DATA_PERIPHERAL_ID_LAST_BIT)) + +/// iSCSI SCSI Basic Inquiry Data peripheral identifier: Extracts the peripheral device identifier bits. +#define ISCSI_SCSI_BASIC_INQUIRY_DATA_GET_PERIPHERAL_ID(x) (ISCSI_BITS_GET((x), ISCSI_SCSI_BASIC_INQUIRY_DATA_PERIPHERAL_ID_FIRST_BIT, ISCSI_SCSI_BASIC_INQUIRY_DATA_PERIPHERAL_ID_LAST_BIT)) + +/// iSCSI SCSI Basic Inquiry Data peripheral identifier: Stores into the peripheral device identifier bits. +#define ISCSI_SCSI_BASIC_INQUIRY_DATA_PUT_PERIPHERAL_ID(x) (ISCSI_BITS_PUT((x), ISCSI_SCSI_BASIC_INQUIRY_DATA_PERIPHERAL_ID_FIRST_BIT, ISCSI_SCSI_BASIC_INQUIRY_DATA_PERIPHERAL_ID_LAST_BIT)) + + +/// iSCSI SCSI Basic Inquiry Data peripheral type modifier: First bit of the seven bits. +#define ISCSI_SCSI_BASIC_INQUIRY_DATA_PERIPHERAL_TYPE_MOD_FIRST_BIT 0 + +/// iSCSI SCSI Basic Inquiry Data peripheral type modifier: Last bit of the seven bits. +#define ISCSI_SCSI_BASIC_INQUIRY_DATA_PERIPHERAL_TYPE_MOD_LAST_BIT ((ISCSI_SCSI_BASIC_INQUIRY_DATA_PERIPHERAL_TYPE_MOD_FIRST_BIT) + 7 - 1) + +/// iSCSI SCSI Basic Inquiry Data peripheral type modifier: Bit mask. +#define ISCSI_SCSI_BASIC_INQUIRY_DATA_PERIPHERAL_TYPE_MOD_MASK (ISCSI_BITS_GET_MASK(ISCSI_SCSI_BASIC_INQUIRY_DATA_PERIPHERAL_TYPE_MOD_FIRST_BIT, ISCSI_SCSI_BASIC_INQUIRY_DATA_PERIPHERAL_TYPE_MOD_LAST_BIT)) + +/// iSCSI SCSI Basic Inquiry Data peripheral identifier: Extracts the peripheral type modifier bits. +#define ISCSI_SCSI_BASIC_INQUIRY_DATA_GET_PERIPHERAL_TYPE_MOD(x) (ISCSI_BITS_GET((x), ISCSI_SCSI_BASIC_INQUIRY_DATA_PERIPHERAL_TYPE_MOD_FIRST_BIT, ISCSI_SCSI_BASIC_INQUIRY_DATA_PERIPHERAL_TYPE_MOD_LAST_BIT)) + +/// iSCSI SCSI Basic Inquiry Data peripheral identifier: Stores into the peripheral type modifier bits. +#define ISCSI_SCSI_BASIC_INQUIRY_DATA_PUT_PERIPHERAL_TYPE_MOD(x) (ISCSI_BITS_PUT((x), ISCSI_SCSI_BASIC_INQUIRY_DATA_PERIPHERAL_TYPE_MOD_FIRST_BIT, ISCSI_SCSI_BASIC_INQUIRY_DATA_PERIPHERAL_TYPE_MOD_LAST_BIT)) + +/// iSCSI SCSI Basic Inquiry Data peripheral type modifier: Removable media. +#define ISCSI_SCSI_BASIC_INQUIRY_DATA_PERIPHERAL_TYPE_MOD_FLAGS_REMOVABLE_MEDIA (1 << 7) + + +/// iSCSI SCSI Basic Inquiry Data ANSI version: None. +#define ISCSI_SCSI_BASIC_INQUIRY_DATA_VERSION_ANSI_NONE 0x0 + +/// iSCSI SCSI Basic Inquiry Data ANSI version: SPC. +#define ISCSI_SCSI_BASIC_INQUIRY_DATA_VERSION_ANSI_SPC 0x3 + +/// iSCSI SCSI Basic Inquiry Data ANSI version: SPC2. +#define ISCSI_SCSI_BASIC_INQUIRY_DATA_VERSION_ANSI_SPC2 0x4 + +/// iSCSI SCSI Basic Inquiry Data ANSI version: SPC3. +#define ISCSI_SCSI_BASIC_INQUIRY_DATA_VERSION_ANSI_SPC3 0x5 + +/// iSCSI SCSI Basic Inquiry Data ANSI version: SPC4. +#define ISCSI_SCSI_BASIC_INQUIRY_DATA_VERSION_ANSI_SPC4 0x6 + +/// iSCSI SCSI Basic Inquiry Data ANSI version: SPC5. +#define ISCSI_SCSI_BASIC_INQUIRY_DATA_VERSION_ANSI_SPC5 0x7 + +/// iSCSI SCSI Basic Inquiry Data ANSI version: First bit of the three bits. +#define ISCSI_SCSI_BASIC_INQUIRY_DATA_VERSION_ANSI_FIRST_BIT 0 + +/// iSCSI SCSI Basic Inquiry Data ANSI version: Last bit of the three bits. +#define ISCSI_SCSI_BASIC_INQUIRY_DATA_VERSION_ANSI_LAST_BIT ((ISCSI_SCSI_BASIC_INQUIRY_DATA_VERSION_ANSI_FIRST_BIT) + 3 - 1) + +/// iSCSI SCSI Basic Inquiry Data ANSI version: Bit mask. +#define ISCSI_SCSI_BASIC_INQUIRY_DATA_VERSION_ANSI_MASK (ISCSI_BITS_GET_MASK(ISCSI_SCSI_BASIC_INQUIRY_DATA_VERSION_ANSI_FIRST_BIT, ISCSI_SCSI_BASIC_INQUIRY_DATA_VERSION_ANSI_LAST_BIT)) + +/// iSCSI SCSI Basic Inquiry Data ANSI version: Extracts the ANSI version bits. +#define ISCSI_SCSI_BASIC_INQUIRY_DATA_GET_VERSION_ANSI(x) (ISCSI_BITS_GET((x), ISCSI_SCSI_BASIC_INQUIRY_DATA_VERSION_ANSI_FIRST_BIT, ISCSI_SCSI_BASIC_INQUIRY_DATA_VERSION_ANSI_LAST_BIT)) + +/// iSCSI SCSI Basic Inquiry Data ANSI version: Stores into the ANSI version bits. +#define ISCSI_SCSI_BASIC_INQUIRY_DATA_PUT_VERSION_ANSI(x) (ISCSI_BITS_PUT((x), ISCSI_SCSI_BASIC_INQUIRY_DATA_VERSION_ANSI_FIRST_BIT, ISCSI_SCSI_BASIC_INQUIRY_DATA_VERSION_ANSI_LAST_BIT)) + +/// iSCSI SCSI Basic Inquiry Data ECMA version: First bit of the three bits. +#define ISCSI_SCSI_BASIC_INQUIRY_DATA_VERSION_ECMA_FIRST_BIT 3 + +/// iSCSI SCSI Basic Inquiry Data ECMA version: Last bit of the three bits. +#define ISCSI_SCSI_BASIC_INQUIRY_DATA_VERSION_ECMA_LAST_BIT ((ISCSI_SCSI_BASIC_INQUIRY_DATA_VERSION_ECMA_FIRST_BIT) + 3 - 1) + +/// iSCSI SCSI Basic Inquiry Data ECMA version: Bit mask. +#define ISCSI_SCSI_BASIC_INQUIRY_DATA_VERSION_ECMA_MASK (ISCSI_BITS_GET_MASK(ISCSI_SCSI_BASIC_INQUIRY_DATA_VERSION_ECMA_FIRST_BIT, ISCSI_SCSI_BASIC_INQUIRY_DATA_VERSION_ECMA_LAST_BIT)) + +/// iSCSI SCSI Basic Inquiry Data ECMA version: Extracts the ECMA version bits. +#define ISCSI_SCSI_BASIC_INQUIRY_DATA_GET_VERSION_ECMA(x) (ISCSI_BITS_GET((x), ISCSI_SCSI_BASIC_INQUIRY_DATA_VERSION_ECMA_FIRST_BIT, ISCSI_SCSI_BASIC_INQUIRY_DATA_VERSION_ECMA_LAST_BIT)) + +/// iSCSI SCSI Basic Inquiry Data ECMA version: Stores into the ECMA version bits. +#define ISCSI_SCSI_BASIC_INQUIRY_DATA_PUT_VERSION_ECMA(x) (ISCSI_BITS_PUT((x), ISCSI_SCSI_BASIC_INQUIRY_DATA_VERSION_ECMA_FIRST_BIT, ISCSI_SCSI_BASIC_INQUIRY_DATA_VERSION_ECMA_LAST_BIT)) + +/// iSCSI SCSI Basic Inquiry Data ISO version: First bit of the two bits. +#define ISCSI_SCSI_BASIC_INQUIRY_DATA_VERSION_ISO_FIRST_BIT 6 + +/// iSCSI SCSI Basic Inquiry Data ISO version: Last bit of the two bits. +#define ISCSI_SCSI_BASIC_INQUIRY_DATA_VERSION_ISO_LAST_BIT ((ISCSI_SCSI_BASIC_INQUIRY_DATA_VERSION_ISO_FIRST_BIT) + 2 - 1) + +/// iSCSI SCSI Basic Inquiry Data ISO version: Bit mask. +#define ISCSI_SCSI_BASIC_INQUIRY_DATA_VERSION_ISO_MASK (ISCSI_BITS_GET_MASK(ISCSI_SCSI_BASIC_INQUIRY_DATA_VERSION_ISO_FIRST_BIT, ISCSI_SCSI_BASIC_INQUIRY_DATA_VERSION_ISO_LAST_BIT)) + +/// iSCSI SCSI Basic Inquiry Data ISO version: Extracts the ISO version bits. +#define ISCSI_SCSI_BASIC_INQUIRY_DATA_GET_VERSION_ISO(x) (ISCSI_BITS_GET((x), ISCSI_SCSI_BASIC_INQUIRY_DATA_VERSION_ISO_FIRST_BIT, ISCSI_SCSI_BASIC_INQUIRY_DATA_VERSION_ISO_LAST_BIT)) + +/// iSCSI SCSI Basic Inquiry Data ISO version: Stores into the ISO version bits. +#define ISCSI_SCSI_BASIC_INQUIRY_DATA_PUT_VERSION_ISO(x) (ISCSI_BITS_PUT((x), ISCSI_SCSI_BASIC_INQUIRY_DATA_VERSION_ISO_FIRST_BIT, ISCSI_SCSI_BASIC_INQUIRY_DATA_VERSION_ISO_LAST_BIT)) + + +/// iSCSI SCSI Basic Inquiry Data response data format flags: This structure complies with SCSI-1 specifications. +#define ISCSI_SCSI_BASIC_INQUIRY_DATA_RESPONSE_DATA_FMT_FLAGS_LEVEL_0 0x00 + +/// iSCSI SCSI Basic Inquiry Data response data format flags: This structure complies with CCS pseudo specifications. +#define ISCSI_SCSI_BASIC_INQUIRY_DATA_RESPONSE_DATA_FMT_FLAGS_CCS 0x01 + +/// iSCSI SCSI Basic Inquiry Data response data format flags: This structure complies with SCSI-2/3 specifications. +#define ISCSI_SCSI_BASIC_INQUIRY_DATA_RESPONSE_DATA_FMT_FLAGS_SCSI_2 0x02 + +/// iSCSI SCSI Basic Inquiry Data response data format flags: First bit of the four bits. +#define ISCSI_SCSI_BASIC_INQUIRY_DATA_RESPONSE_DATA_FMT_FLAGS_FIRST_BIT 0 + +/// iSCSI SCSI Basic Inquiry Data response data format flags: Last bit of the four bits. +#define ISCSI_SCSI_BASIC_INQUIRY_DATA_RESPONSE_DATA_FMT_FLAGS_LAST_BIT ((ISCSI_SCSI_BASIC_INQUIRY_DATA_RESPONSE_DATA_FMT_FLAGS_FIRST_BIT) + 4 - 1) + +/// iSCSI SCSI Basic Inquiry Data response data format flags: Bit mask. +#define ISCSI_SCSI_BASIC_INQUIRY_DATA_RESPONSE_DATA_FMT_FLAGS_MASK (ISCSI_BITS_GET_MASK(ISCSI_SCSI_BASIC_INQUIRY_DATA_RESPONSE_DATA_FMT_FLAGS_FIRST_BIT, ISCSI_SCSI_BASIC_INQUIRY_DATA_RESPONSE_DATA_FMT_FLAGS_LAST_BIT)) + +/// iSCSI SCSI Basic Inquiry Data response data format flags: Extracts the response data format flags bits. +#define ISCSI_SCSI_BASIC_INQUIRY_DATA_GET_RESPONSE_DATA_FMT_FLAGS(x) (ISCSI_BITS_GET((x), ISCSI_SCSI_BASIC_INQUIRY_DATA_RESPONSE_DATA_FMT_FLAGS_FIRST_BIT, ISCSI_SCSI_BASIC_INQUIRY_DATA_RESPONSE_DATA_FMT_FLAGS_LAST_BIT)) + +/// iSCSI SCSI Basic Inquiry Data response data format flags: Stores into the response data format flags bits. +#define ISCSI_SCSI_BASIC_INQUIRY_DATA_PUT_RESPONSE_DATA_FMT_FLAGS(x) (ISCSI_BITS_PUT((x), ISCSI_SCSI_BASIC_INQUIRY_DATA_RESPONSE_DATA_FMT_FLAGS_FIRST_BIT, ISCSI_SCSI_BASIC_INQUIRY_DATA_RESPONSE_DATA_FMT_FLAGS_LAST_BIT)) + +/// iSCSI SCSI Basic Inquiry Data response data format flags: Hierarchical Support. +#define ISCSI_SCSI_BASIC_INQUIRY_DATA_RESPONSE_DATA_FMT_FLAGS_HISUP (1 << 4) + +/// iSCSI SCSI Basic Inquiry Data response data format flags: Normal ACA Supported. +#define ISCSI_SCSI_BASIC_INQUIRY_DATA_RESPONSE_DATA_FMT_FLAGS_NORMACA (1 << 5) + +/// iSCSI SCSI Basic Inquiry Data response data format flags: TERMINATE I/O PROCESS message device support. +#define ISCSI_SCSI_BASIC_INQUIRY_DATA_RESPONSE_DATA_FMT_FLAGS_TERMINATE_IO_PROC_MSG (1 << 6) + +/// iSCSI SCSI Basic Inquiry Data response data format flags: Asynchronous Event Notification device support. +#define ISCSI_SCSI_BASIC_INQUIRY_DATA_RESPONSE_DATA_FMT_FLAGS_ASYNC_EVENT_NOTIFY (1 << 7) + + +/** + * @brief iSCSI SCSI basic inquiry data packet. + * + * This structure is used by the SCSI INQUIRY command + * in order to fill in the result if the EVPD bit is + * cleared. + */ +typedef struct __attribute__((packed)) iscsi_scsi_basic_inquiry_data_packet { + /// Peripheral device type and qualifier. + uint8_t peripheral_type_id; + + /// Peripheral device type modifier and removable media bit. + int8_t peripheral_type_mod_flags; + + /// ANSI-Approved, ECMA and ISO version. + uint8_t version; + + /// Response data format, HISUP, NORMACA, AENC and TrmIOP flags. + int8_t response_data_fmt_flags; + + /// Additional length in bytes. + uint8_t add_len; +} iscsi_scsi_basic_inquiry_data_packet; + + +/// iSCSI SCSI Standard Inquiry Data vendor identifier for disk. +#define ISCSI_SCSI_STD_INQUIRY_DATA_DISK_VENDOR_ID "UNI FRBG" + + +/// iSCSI SCSI Standard Inquiry Data TPGS flags: Protect. +#define ISCSI_SCSI_STD_INQUIRY_DATA_TPGS_FLAGS_PROTECT (1 << 0) + +/// iSCSI SCSI Standard Inquiry Data TPGS flags: Third-Party Copy (3PC). +#define ISCSI_SCSI_STD_INQUIRY_DATA_TPGS_FLAGS_3PC (1 << 3) + +/// iSCSI SCSI Standard Inquiry Data TPGS flags: First bit of the two bits. +#define ISCSI_SCSI_STD_INQUIRY_DATA_TPGS_FLAGS_TPGS_FIRST_BIT 4 + +/// iSCSI SCSI Standard Inquiry Data TPGS flags: Last bit of the two bits. +#define ISCSI_SCSI_STD_INQUIRY_DATA_TPGS_FLAGS_TPGS_LAST_BIT ((ISCSI_SCSI_STD_INQUIRY_DATA_TPGS_FLAGS_TPGS_FIRST_BIT) + 2 - 1) + +/// iSCSI SCSI Standard Inquiry Data TPGS flags: Bit mask. +#define ISCSI_SCSI_STD_INQUIRY_DATA_TPGS_FLAGS_TPGS_MASK (ISCSI_BITS_GET_MASK(ISCSI_SCSI_STD_INQUIRY_DATA_TPGS_FLAGS_TPGS_FIRST_BIT, ISCSI_SCSI_STD_INQUIRY_DATA_TPGS_FLAGS_TPGS_LAST_BIT)) + +/// iSCSI SCSI Standard Inquiry Data TPGS flags: Extracts the Target Port Group Support (TPGS) bits. +#define ISCSI_SCSI_STD_INQUIRY_DATA_TPGS_FLAGS_GET_TPGS(x) (ISCSI_BITS_GET((x), ISCSI_SCSI_STD_INQUIRY_DATA_TPGS_FLAGS_TPGS_FIRST_BIT, ISCSI_SCSI_STD_INQUIRY_DATA_TPGS_FLAGS_TPGS_LAST_BIT)) + +/// iSCSI SCSI Standard Inquiry Data TPGS flags: Stores into the Target Port Group Support (TPGS) bits. +#define ISCSI_SCSI_STD_INQUIRY_DATA_TPGS_FLAGS_PUT_TPGS(x) (ISCSI_BITS_PUT((x), ISCSI_SCSI_STD_INQUIRY_DATA_TPGS_FLAGS_TPGS_FIRST_BIT, ISCSI_SCSI_STD_INQUIRY_DATA_TPGS_FLAGS_TPGS_LAST_BIT)) + +/// iSCSI SCSI Standard Inquiry Data TPGS flags: Access Controls Coordinator (ACC). +#define ISCSI_SCSI_STD_INQUIRY_DATA_TPGS_FLAGS_ACC (1 << 6) + +/// iSCSI SCSI Standard Inquiry Data TPGS flags: SCC Supported (SCCS). +#define ISCSI_SCSI_STD_INQUIRY_DATA_TPGS_FLAGS_SCCS (1 << 7) + + +/// iSCSI SCSI Standard Inquiry Data services flags: Multi Port (MULTIP). +#define ISCSI_SCSI_STD_INQUIRY_DATA_SERVICES_FLAGS_MULTIP (1 << 4) + +/// iSCSI SCSI Standard Inquiry Data services flags: VS. +#define ISCSI_SCSI_STD_INQUIRY_DATA_SERVICES_FLAGS_VS (1 << 5) + +/// iSCSI SCSI Standard Inquiry Data services flags: Enclosure Services (ENCSERV). +#define ISCSI_SCSI_STD_INQUIRY_DATA_SERVICES_FLAGS_ENCSERV (1 << 6) + + +/// iSCSI SCSI Standard Inquiry Data flags: Device responds with soft reset instead of hard reset to reset condition. +#define ISCSI_SCSI_STD_INQUIRY_DATA_FLAGS_SOFT_RESET (1 << 0) + +/// iSCSI SCSI Standard Inquiry Data flags: Device supports tagged command queueing. +#define ISCSI_SCSI_STD_INQUIRY_DATA_FLAGS_COMMAND_QUEUE (1 << 1) + +/// iSCSI SCSI Standard Inquiry Data flags: Device supports linked commands for this logical unit. +#define ISCSI_SCSI_STD_INQUIRY_DATA_FLAGS_LINKED_CMDS (1 << 3) + +/// iSCSI SCSI Standard Inquiry Data flags: Device supports synchronous data transfers. +#define ISCSI_SCSI_STD_INQUIRY_DATA_FLAGS_SYNC (1 << 4) + +/// iSCSI SCSI Standard Inquiry Data flags: Device supports 16-bit wide data transfers. +#define ISCSI_SCSI_STD_INQUIRY_DATA_FLAGS_WIDE_16_BIT (1 << 5) + +/// iSCSI SCSI Standard Inquiry Data flags: Device supports 32-bit wide data transfers. +#define ISCSI_SCSI_STD_INQUIRY_DATA_FLAGS_WIDE_32_BIT (1 << 6) + +/// iSCSI SCSI Standard Inquiry Data flags: Device supports relative addressing mode of this logical unit. +#define ISCSI_SCSI_STD_INQUIRY_DATA_FLAGS_REL_ADDR (1 << 7) + + +/** + * @brief iSCSI SCSI standard inquiry data packet. + * + * This structure is used by the SCSI INQUIRY command + * in order to fill in the result if the EVPD bit is + * cleared. + */ +typedef struct __attribute__((packed)) iscsi_scsi_std_inquiry_data_packet { + /// iSCSI SCSI basic inquiry data packet. + iscsi_scsi_basic_inquiry_data_packet basic_inquiry; + + /// PROTECT, 3PC, TPGS, ACC and SCCS. + uint8_t tpgs_flags; + + /// MULTIP, VS and ENCSERV. + int8_t services_flags; + + /// Flags. + int8_t flags; + + /// Vendor identification. + uint8_t vendor_id[8]; + + /// Product identification. + uint8_t product_id[16]; + + /// Product revision level. + uint8_t product_rev_level[4]; +} iscsi_scsi_std_inquiry_data_packet; + + +/// iSCSI SCSI Extended Inquiry Data vendor specific. +#define ISCSI_SCSI_EXT_INQUIRY_DATA_VENDOR_SPEC_ID "UNI FREIBURG DNBD3" + + +/// iSCSI SCSI Extended Inquiry Data version descriptor: iSCSI (no version claimed). +#define ISCSI_SCSI_EXT_INQUIRY_DATA_VERSION_DESC_ISCSI_NO_VERSION 0x0960 + +/// iSCSI SCSI Extended Inquiry Data version descriptor: SPC3 (no version claimed). +#define ISCSI_SCSI_EXT_INQUIRY_DATA_VERSION_DESC_SPC3_NO_VERSION 0x0300 + +/// iSCSI SCSI Extended Inquiry Data version descriptor: SBC2 (no version claimed). +#define ISCSI_SCSI_EXT_INQUIRY_DATA_VERSION_DESC_SBC2_NO_VERSION 0x0320 + +/// iSCSI SCSI Extended Inquiry Data version descriptor: SAM2 (no version claimed). +#define ISCSI_SCSI_EXT_INQUIRY_DATA_VERSION_DESC_SAM2_NO_VERSION 0x0040 + + +/** + * @brief iSCSI SCSI extended inquiry data packet. + * + * This structure is used by the SCSI INQUIRY command + * in order to fill in the result if the EVPD bit is + * cleared. + */ +typedef struct __attribute__((packed)) iscsi_scsi_ext_inquiry_data_packet { + /// iSCSI SCSI standard inquiry data packet. + iscsi_scsi_std_inquiry_data_packet std_inquiry; + + /// Vendor specific. + uint8_t vendor_spec[20]; + + /// Flags. + int8_t flags; + + /// Reserved for future usage (always MUST be 0). + uint8_t reserved; + + /// Version descriptors. + uint16_t version_desc[8]; + + /// Reserved for future usage (always MUST be 0). + uint64_t reserved2[2]; + + /// Reserved for future usage (always MUST be 0). + uint32_t reserved3; + + /// Reserved for future usage (always MUST be 0). + uint16_t reserved4; +} iscsi_scsi_ext_inquiry_data_packet; + + +/// iSCSI SCSI Vital Product Data (VPD) Page Inquiry Data peripheral type: Direct access device. +#define ISCSI_SCSI_VPD_PAGE_INQUIRY_DATA_PERIPHERAL_TYPE_DIRECT 0x00 + +/// iSCSI SCSI Vital Product Data (VPD) Page Inquiry Data peripheral type: Sequential access device. +#define ISCSI_SCSI_VPD_PAGE_INQUIRY_DATA_PERIPHERAL_TYPE_SEQ 0x01 + +/// iSCSI SCSI Vital Product Data (VPD) Page Inquiry Data peripheral type: Printer device. +#define ISCSI_SCSI_VPD_PAGE_INQUIRY_DATA_PERIPHERAL_TYPE_PRINTER 0x02 + +/// iSCSI SCSI Vital Product Data (VPD) Page Inquiry Data peripheral type: Processor device. +#define ISCSI_SCSI_VPD_PAGE_INQUIRY_DATA_PERIPHERAL_TYPE_PROCESSOR 0x03 + +/// iSCSI SCSI Vital Product Data (VPD) Page Inquiry Data peripheral type: Write once device. +#define ISCSI_SCSI_VPD_PAGE_INQUIRY_DATA_PERIPHERAL_TYPE_WORM 0x04 + +/// iSCSI SCSI Vital Product Data (VPD) Page Inquiry Data peripheral type: Read only direct access (e.g. CD-ROM) device. +#define ISCSI_SCSI_VPD_PAGE_INQUIRY_DATA_PERIPHERAL_TYPE_RO_DIRECT 0x05 + +/// iSCSI SCSI Vital Product Data (VPD) Page Inquiry Data peripheral type: Scanner device. +#define ISCSI_SCSI_VPD_PAGE_INQUIRY_DATA_PERIPHERAL_TYPE_SCANNER 0x06 + +/// iSCSI SCSI Vital Product Data (VPD) Page Inquiry Data peripheral type: Optical memory device. +#define ISCSI_SCSI_VPD_PAGE_INQUIRY_DATA_PERIPHERAL_TYPE_OPTICAL 0x07 + +/// iSCSI SCSI Vital Product Data (VPD) Page Inquiry Data peripheral type: Medium changer device. +#define ISCSI_SCSI_VPD_PAGE_INQUIRY_DATA_PERIPHERAL_TYPE_CHANGER 0x08 + +/// iSCSI SCSI Vital Product Data (VPD) Page Inquiry Data peripheral type: Communications device. +#define ISCSI_SCSI_VPD_PAGE_INQUIRY_DATA_PERIPHERAL_TYPE_COMM 0x09 + +/// iSCSI SCSI Vital Product Data (VPD) Page Inquiry Data peripheral type: Unknown or no device. +#define ISCSI_SCSI_VPD_PAGE_INQUIRY_DATA_PERIPHERAL_TYPE_UNKNOWN 0x1F + +/// iSCSI SCSI Vital Product Data (VPD) Page Inquiry Data peripheral type: First bit of the five bits. +#define ISCSI_SCSI_VPD_PAGE_INQUIRY_DATA_PERIPHERAL_TYPE_FIRST_BIT 0 + +/// iSCSI SCSI Vital Product Data (VPD) Page Inquiry Data peripheral type: Last bit of the five bits. +#define ISCSI_SCSI_VPD_PAGE_INQUIRY_DATA_PERIPHERAL_TYPE_LAST_BIT ((ISCSI_SCSI_VPD_PAGE_INQUIRY_DATA_PERIPHERAL_TYPE_FIRST_BIT) + 5 - 1) + +/// iSCSI SCSI Vital Product Data (VPD) Page Inquiry Data peripheral type: Bit mask. +#define ISCSI_SCSI_VPD_PAGE_INQUIRY_DATA_PERIPHERAL_TYPE_MASK (ISCSI_BITS_GET_MASK(ISCSI_SCSI_VPD_PAGE_INQUIRY_DATA_PERIPHERAL_TYPE_FIRST_BIT, ISCSI_SCSI_VPD_PAGE_INQUIRY_DATA_PERIPHERAL_TYPE_LAST_BIT)) + +/// iSCSI SCSI Vital Product Data (VPD) Page Inquiry Data peripheral type: Extracts the peripheral device type bits. +#define ISCSI_SCSI_VPD_PAGE_INQUIRY_DATA_GET_PERIPHERAL_TYPE(x) (ISCSI_BITS_GET((x), ISCSI_SCSI_VPD_PAGE_INQUIRY_DATA_PERIPHERAL_TYPE_FIRST_BIT, ISCSI_SCSI_VPD_PAGE_INQUIRY_DATA_PERIPHERAL_TYPE_LAST_BIT)) + +/// iSCSI SCSI Vital Product Data (VPD) Page Inquiry Data peripheral type: Stores into the peripheral device type bits. +#define ISCSI_SCSI_VPD_PAGE_INQUIRY_DATA_PUT_PERIPHERAL_TYPE(x) (ISCSI_BITS_PUT((x), ISCSI_SCSI_VPD_PAGE_INQUIRY_DATA_PERIPHERAL_TYPE_FIRST_BIT, ISCSI_SCSI_VPD_PAGE_INQUIRY_DATA_PERIPHERAL_TYPE_LAST_BIT)) + +/// iSCSI SCSI Vital Product Data (VPD) Page Inquiry Data peripheral identifier: The specified peripheral device type is currently connected to this logical unit, or connection state could not be determined. +#define ISCSI_SCSI_VPD_PAGE_INQUIRY_DATA_PERIPHERAL_ID_POSSIBLE 0x0 + +/// iSCSI SCSI Vital Product Data (VPD) Page Inquiry Data peripheral identifier: The target is capable of supporting the specified peripheral device type on this logical unit, but not connected. +#define ISCSI_SCSI_VPD_PAGE_INQUIRY_DATA_PERIPHERAL_ID_SUPPORTED 0x1 + +/// iSCSI SCSI Vital Product Data (VPD) Page Inquiry Data peripheral identifier: The target is not capable of supporting a physical device on this logical unit. +#define ISCSI_SCSI_VPD_PAGE_INQUIRY_DATA_PERIPHERAL_ID_NEVER 0x3 + +/// iSCSI SCSI Vital Product Data (VPD) Page Inquiry Data peripheral identifier: Vendor specific. +#define ISCSI_SCSI_VPD_PAGE_INQUIRY_DATA_PERIPHERAL_ID_VENDOR_UNIQ 0x4 + +/// iSCSI SCSI Vital Product Data (VPD) Page Inquiry Data peripheral identifier: First bit of the three bits. +#define ISCSI_SCSI_VPD_PAGE_INQUIRY_DATA_PERIPHERAL_ID_FIRST_BIT 5 + +/// iSCSI SCSI Vital Product Data (VPD) Page Inquiry Data peripheral identifier: Last bit of the three bits. +#define ISCSI_SCSI_VPD_PAGE_INQUIRY_DATA_PERIPHERAL_ID_LAST_BIT ((ISCSI_SCSI_VPD_PAGE_INQUIRY_DATA_PERIPHERAL_ID_FIRST_BIT) + 3 - 1) + +/// iSCSI SCSI Vital Product Data (VPD) Page Inquiry Data peripheral identifier: Bit mask. +#define ISCSI_SCSI_VPD_PAGE_INQUIRY_DATA_PERIPHERAL_ID_MASK (ISCSI_BITS_GET_MASK(ISCSI_SCSI_VPD_PAGE_INQUIRY_DATA_PERIPHERAL_ID_FIRST_BIT, ISCSI_SCSI_VPD_PAGE_INQUIRY_DATA_PERIPHERAL_ID_LAST_BIT)) + +/// iSCSI SCSI Vital Product Data (VPD) Page Inquiry Data peripheral identifier: Extracts the peripheral device identifier bits. +#define ISCSI_SCSI_VPD_PAGE_INQUIRY_DATA_GET_PERIPHERAL_ID(x) (ISCSI_BITS_GET((x), ISCSI_SCSI_VPD_PAGE_INQUIRY_DATA_PERIPHERAL_ID_FIRST_BIT, ISCSI_SCSI_VPD_PAGE_INQUIRY_DATA_PERIPHERAL_ID_LAST_BIT)) + +/// iSCSI SCSI Vital Product Data (VPD) Page Inquiry Data peripheral identifier: Stores into the peripheral device identifier bits. +#define ISCSI_SCSI_VPD_PAGE_INQUIRY_DATA_PUT_PERIPHERAL_ID(x) (ISCSI_BITS_PUT((x), ISCSI_SCSI_VPD_PAGE_INQUIRY_DATA_PERIPHERAL_ID_FIRST_BIT, ISCSI_SCSI_VPD_PAGE_INQUIRY_DATA_PERIPHERAL_ID_LAST_BIT)) + + +/// iSCSI SCSI Vital Product Data (VPD) Page Inquiry Data page code: Supported VPD pages. +#define ISCSI_SCSI_VPD_PAGE_INQUIRY_DATA_PAGE_CODE_SUPPORTED_VPD_PAGES 0x00 + +/// iSCSI SCSI Vital Product Data (VPD) Page Inquiry Data page code: Unit serial number. +#define ISCSI_SCSI_VPD_PAGE_INQUIRY_DATA_PAGE_CODE_UNIT_SERIAL_NUMBER 0x80 + +/// iSCSI SCSI Vital Product Data (VPD) Page Inquiry Data page code: Device identification. +#define ISCSI_SCSI_VPD_PAGE_INQUIRY_DATA_PAGE_CODE_DEVICE_ID 0x83 + +/// iSCSI SCSI Vital Product Data (VPD) Page Inquiry Data page code: Software interface identification. +#define ISCSI_SCSI_VPD_PAGE_INQUIRY_DATA_PAGE_CODE_SOFTWARE_IFACE_ID 0x84 + +/// iSCSI SCSI Vital Product Data (VPD) Page Inquiry Data page code: Management network addresses. +#define ISCSI_SCSI_VPD_PAGE_INQUIRY_DATA_PAGE_CODE_MANAGEMENT_NETWORK_ADDRS 0x85 + +/// iSCSI SCSI Vital Product Data (VPD) Page Inquiry Data page code: Extended inquiry data. +#define ISCSI_SCSI_VPD_PAGE_INQUIRY_DATA_PAGE_CODE_EXTENDED_INQUIRY_DATA 0x86 + +/// iSCSI SCSI Vital Product Data (VPD) Page Inquiry Data page code: Mode page policy. +#define ISCSI_SCSI_VPD_PAGE_INQUIRY_DATA_PAGE_CODE_MODE_PAGE_POLICY 0x87 + +/// iSCSI SCSI Vital Product Data (VPD) Page Inquiry Data page code: SCSI ports. +#define ISCSI_SCSI_VPD_PAGE_INQUIRY_DATA_PAGE_CODE_SCSI_PORTS 0x88 + +/// iSCSI SCSI Vital Product Data (VPD) Page Inquiry Data page code: Block limits. +#define ISCSI_SCSI_VPD_PAGE_INQUIRY_DATA_PAGE_CODE_BLOCK_LIMITS 0xB0 + +/// iSCSI SCSI Vital Product Data (VPD) Page Inquiry Data page code: Block device characteristics. +#define ISCSI_SCSI_VPD_PAGE_INQUIRY_DATA_PAGE_CODE_BLOCK_DEV_CHARS 0xB1 + +/// iSCSI SCSI Vital Product Data (VPD) Page Inquiry Data page code: Thin provisioning. +#define ISCSI_SCSI_VPD_PAGE_INQUIRY_DATA_PAGE_CODE_THIN_PROVISION 0xB2 + + +/// iSCSI SCSI Vital Product Data (VPD) Page Inquiry Data page code: Maximum serial string length in bytes. +#define ISCSI_SCSI_VPD_PAGE_INQUIRY_DATA_PAGE_CODE_MAX_SERIAL_STRING 32 + + +/** + * @brief iSCSI SCSI Vital Product Data (VPD) Page Inquiry data packet. + * + * This structure is used by the SCSI INQUIRY command + * in order to fill in the result if the EVPD bit is + * set. + */ +typedef struct __attribute__((packed)) iscsi_scsi_vpd_page_inquiry_data_packet { + /// Peripheral device type and qualifier. + uint8_t peripheral_type_id; + + /// Page code. + uint8_t page_code; + + /// Allocation length in bytes. + uint16_t alloc_len; + + /// Parameters. + uint8_t params[0]; +} iscsi_scsi_vpd_page_inquiry_data_packet; + + +/// iSCSI SCSI Vital Product Data (VPD) Page Designation Descriptor Inquiry data protocol identifier: iSCSI. +#define ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_PROTOCOL_ID_ISCSI 0x05 + +/// iSCSI SCSI Vital Product Data (VPD) Page Designation Descriptor Inquiry data protocol identifier: First bit of the four bits. +#define ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_PROTOCOL_ID_FIRST_BIT 0 + +/// iSCSI SCSI Vital Product Data (VPD) Page Designation Descriptor Inquiry data protocol identifier: Last bit of the four bits. +#define ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_PROTOCOL_ID_LAST_BIT ((ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_PROTOCOL_ID_FIRST_BIT) + 4 - 1) + +/// iSCSI SCSI Vital Product Data (VPD) Page Designation Descriptor Inquiry data protocol identifier: Bit mask. +#define ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_PROTOCOL_ID_MASK (ISCSI_BITS_GET_MASK(ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_PROTOCOL_ID_FIRST_BIT, ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_PROTOCOL_ID_LAST_BIT)) + +/// iSCSI SCSI Vital Product Data (VPD) Page Designation Descriptor Inquiry data protocol identifier: Extracts the protocol identifier bits. +#define ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_GET_PROTOCOL_ID(x) (ISCSI_BITS_GET((x), ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_PROTOCOL_ID_FIRST_BIT, ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_PROTOCOL_ID_LAST_BIT)) + +/// iSCSI SCSI Vital Product Data (VPD) Page Designation Descriptor Inquiry data protocol identifier: Stores into the protocol identifier bits. +#define ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_PUT_PROTOCOL_ID(x) (ISCSI_BITS_PUT((x), ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_PROTOCOL_ID_FIRST_BIT, ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_PROTOCOL_ID_LAST_BIT)) + +/// iSCSI SCSI Vital Product Data (VPD) Page Designation Descriptor Inquiry data code set: Binary encoding. +#define ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_CODE_SET_BINARY 0x01 + +/// iSCSI SCSI Vital Product Data (VPD) Page Designation Descriptor Inquiry data code set: ASCII encoding. +#define ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_CODE_SET_ASCII 0x02 + +/// iSCSI SCSI Vital Product Data (VPD) Page Designation Descriptor Inquiry data code set: UTF-8 encoding. +#define ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_CODE_SET_UTF8 0x03 + +/// iSCSI SCSI Vital Product Data (VPD) Page Designation Descriptor Inquiry data code set: First bit of the four bits. +#define ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_CODE_SET_FIRST_BIT 4 + +/// iSCSI SCSI Vital Product Data (VPD) Page Designation Descriptor Inquiry data code set: Last bit of the four bits. +#define ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_CODE_SET_LAST_BIT ((ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_CODE_SET_FIRST_BIT) + 8 - 1) + +/// iSCSI SCSI Vital Product Data (VPD) Page Designation Descriptor Inquiry data code set: Bit mask. +#define ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_CODE_SET_MASK (ISCSI_BITS_GET_MASK(ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_CODE_SET_FIRST_BIT, ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_CODE_SET_LAST_BIT)) + +/// iSCSI SCSI Vital Product Data (VPD) Page Designation Descriptor Inquiry data code set: Extracts the protocol identifier bits. +#define ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_GET_CODE_SET(x) (ISCSI_BITS_GET((x), ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_CODE_SET_FIRST_BIT, ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_CODE_SET_LAST_BIT)) + +/// iSCSI SCSI Vital Product Data (VPD) Page Designation Descriptor Inquiry data code set: Stores into the protocol identifier bits. +#define ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_PUT_CODE_SET(x) (ISCSI_BITS_PUT((x), ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_CODE_SET_FIRST_BIT, ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_CODE_SET_LAST_BIT)) + + +/// iSCSI SCSI Vital Product Data (VPD) Page Designation Descriptor Inquiry data flags type: Vendor specific. +#define ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_FLAGS_TYPE_VENDOR_SPEC 0x00 + +/// iSCSI SCSI Vital Product Data (VPD) Page Designation Descriptor Inquiry data flags type: T10 vendor identifier. +#define ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_FLAGS_TYPE_T10_VENDOR_ID 0x01 + +/// iSCSI SCSI Vital Product Data (VPD) Page Designation Descriptor Inquiry data flags type: EUI64. +#define ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_FLAGS_TYPE_EUI64 0x02 + +/// iSCSI SCSI Vital Product Data (VPD) Page Designation Descriptor Inquiry data flags type: NAA. +#define ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_FLAGS_TYPE_NAA 0x03 + +/// iSCSI SCSI Vital Product Data (VPD) Page Designation Descriptor Inquiry data flags type: Relative target port. +#define ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_FLAGS_TYPE_REL_TARGET_PORT 0x04 + +/// iSCSI SCSI Vital Product Data (VPD) Page Designation Descriptor Inquiry data flags type: Target port group. +#define ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_FLAGS_TYPE_TARGET_PORT_GROUP 0x05 + +/// iSCSI SCSI Vital Product Data (VPD) Page Designation Descriptor Inquiry data flags type: Logical unit group. +#define ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_FLAGS_TYPE_LOGICAL_UNIT_GROUP 0x06 + +/// iSCSI SCSI Vital Product Data (VPD) Page Designation Descriptor Inquiry data flags type: MD5 logical unit. +#define ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_FLAGS_TYPE_MD5_LOGICAL_UNIT 0x07 + +/// iSCSI SCSI Vital Product Data (VPD) Page Designation Descriptor Inquiry data flags type: SCSI name. +#define ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_FLAGS_TYPE_SCSI_NAME 0x08 + +/// iSCSI SCSI Vital Product Data (VPD) Page Designation Descriptor Inquiry data flags type: First bit of the four bits. +#define ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_FLAGS_TYPE_FIRST_BIT 0 + +/// iSCSI SCSI Vital Product Data (VPD) Page Designation Descriptor Inquiry data flags type: Last bit of the four bits. +#define ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_FLAGS_TYPE_LAST_BIT ((ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_FLAGS_TYPE_FIRST_BIT) + 4 - 1) + +/// iSCSI SCSI Vital Product Data (VPD) Page Designation Descriptor Inquiry data flags type: Bit mask. +#define ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_FLAGS_TYPE_MASK (ISCSI_BITS_GET_MASK(ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_FLAGS_TYPE_FIRST_BIT, ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_FLAGS_TYPE_LAST_BIT)) + +/// iSCSI SCSI Vital Product Data (VPD) Page Designation Descriptor Inquiry data flags type: Extracts the type bits. +#define ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_FLAGS_GET_TYPE(x) (ISCSI_BITS_GET((x), ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_FLAGS_TYPE_FIRST_BIT, ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_FLAGS_TYPE_LAST_BIT)) + +/// iSCSI SCSI Vital Product Data (VPD) Page Designation Descriptor Inquiry data flags type: Stores into the type bits. +#define ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_FLAGS_PUT_TYPE(x) (ISCSI_BITS_PUT((x), ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_FLAGS_TYPE_FIRST_BIT, ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_FLAGS_TYPE_LAST_BIT)) + +/// iSCSI SCSI Vital Product Data (VPD) Page Designation Descriptor Inquiry data flags association: Logical unit. +#define ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_FLAGS_ASSOC_LOGICAL_UNIT 0x0 + +/// iSCSI SCSI Vital Product Data (VPD) Page Designation Descriptor Inquiry data flags association: Target port. +#define ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_FLAGS_ASSOC_TARGET_PORT 0x1 + +/// iSCSI SCSI Vital Product Data (VPD) Page Designation Descriptor Inquiry data flags association: Target device. +#define ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_FLAGS_ASSOC_TARGET_DEVICE 0x2 + +/// iSCSI SCSI Vital Product Data (VPD) Page Designation Descriptor Inquiry data flags association: First bit of the two bits. +#define ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_FLAGS_ASSOC_FIRST_BIT 4 + +/// iSCSI SCSI Vital Product Data (VPD) Page Designation Descriptor Inquiry data flags association: Last bit of the two bits. +#define ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_FLAGS_ASSOC_LAST_BIT ((ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_FLAGS_ASSOC_FIRST_BIT) + 6 - 1) + +/// iSCSI SCSI Vital Product Data (VPD) Page Designation Descriptor Inquiry data flags association: Bit mask. +#define ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_FLAGS_ASSOC_MASK (ISCSI_BITS_GET_MASK(ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_FLAGS_ASSOC_FIRST_BIT, ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_FLAGS_ASSOC_LAST_BIT)) + +/// iSCSI SCSI Vital Product Data (VPD) Page Designation Descriptor Inquiry data flags association: Extracts the association bits. +#define ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_FLAGS_GET_ASSOC(x) (ISCSI_BITS_GET((x), ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_FLAGS_ASSOC_FIRST_BIT, ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_FLAGS_ASSOC_LAST_BIT)) + +/// iSCSI SCSI Vital Product Data (VPD) Page Designation Descriptor Inquiry data flags association: Stores into the association bits. +#define ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_FLAGS_PUT_ASSOC(x) (ISCSI_BITS_PUT((x), ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_FLAGS_ASSOC_FIRST_BIT, ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_FLAGS_ASSOC_LAST_BIT)) + +/// iSCSI SCSI Vital Product Data (VPD) Page Designation Descriptor Inquiry data flags: Protocol Identifier Valid (PIV). +#define ISCSI_SCSI_VPD_PAGE_DESIGN_DESC_INQUIRY_DATA_FLAGS_PIV (1 << 7) + + +/** + * @brief iSCSI SCSI Vital Product Data (VPD) Page Designation Descriptor Inquiry data packet. + * + * This structure is used by the SCSI INQUIRY command + * in order to fill in the result if the EVPD bit is + * set. + */ +typedef struct __attribute__((packed)) iscsi_scsi_vpd_page_design_desc_inquiry_data_packet { + /// Protocol identifier and code set. + uint8_t protocol_id_code_set; + + /// Flags. + int8_t flags; + + /// Reserved for future usage (always MUST be 0). + uint8_t reserved; + + /// Length in bytes. + uint8_t len; + + /// Designation descriptor. + uint8_t desc[0]; +} iscsi_scsi_vpd_page_design_desc_inquiry_data_packet; + + +/** + * @brief iSCSI SCSI Vital Product Data (VPD) Page Designation Descriptor IEEE NAA Extended Inquiry data packet. + * + * This structure is used by the SCSI INQUIRY command + * in order to fill in the result if the EVPD bit is + * set. + */ +typedef struct __attribute__((packed)) iscsi_scsi_vpd_page_design_desc_ieee_naa_ext_inquiry_data_packet { + /// IEEE NAA Extended. + uint64_t ieee_naa_ext; +} iscsi_scsi_vpd_page_design_desc_ieee_naa_ext_inquiry_data_packet; + + +/** + * @brief iSCSI SCSI Vital Product Data (VPD) Page Designation Descriptor T10 Vendor ID Inquiry data packet. + * + * This structure is used by the SCSI INQUIRY command + * in order to fill in the result if the EVPD bit is + * set. + */ +typedef struct __attribute__((packed)) iscsi_scsi_vpd_page_design_desc_t10_vendor_id_inquiry_data_packet { + /// Vendor identification. + uint8_t vendor_id[8]; + + /// Product identification. + uint8_t product_id[16]; + + /// Unit serial number. + uint8_t unit_serial_num[32]; +} iscsi_scsi_vpd_page_design_desc_t10_vendor_id_inquiry_data_packet; + + +/** + * @brief iSCSI SCSI Vital Product Data (VPD) Page Designation Descriptor Relative Target Port Inquiry data packet. + * + * This structure is used by the SCSI INQUIRY command + * in order to fill in the result if the EVPD bit is + * set. + */ +typedef struct __attribute__((packed)) iscsi_scsi_vpd_page_design_desc_rel_target_port_inquiry_data_packet { + /// Reserved for future usage (always MUST be 0). + uint16_t reserved; + + /// Port index. + uint16_t index; +} iscsi_scsi_vpd_page_design_desc_rel_target_port_inquiry_data_packet; + + +/** + * @brief iSCSI SCSI Vital Product Data (VPD) Page Designation Descriptor Target Port Group Inquiry data packet. + * + * This structure is used by the SCSI INQUIRY command + * in order to fill in the result if the EVPD bit is + * set. + */ +typedef struct __attribute__((packed)) iscsi_scsi_vpd_page_design_desc_target_port_group_inquiry_data_packet { + /// Reserved for future usage (always MUST be 0). + uint16_t reserved; + + /// Port group index. + uint16_t index; +} iscsi_scsi_vpd_page_design_desc_target_port_group_inquiry_data_packet; + + +/** + * @brief iSCSI SCSI Vital Product Data (VPD) Page Designation Descriptor Logical Unit Group Inquiry data packet. + * + * This structure is used by the SCSI INQUIRY command + * in order to fill in the result if the EVPD bit is + * set. + */ +typedef struct __attribute__((packed)) iscsi_scsi_vpd_page_design_desc_logical_unit_group_inquiry_data_packet { + /// Reserved for future usage (always MUST be 0). + uint16_t reserved; + + /// Logical unit identifier. + uint16_t id; +} iscsi_scsi_vpd_page_design_desc_logical_unit_group_inquiry_data_packet; + + +/// iSCSI SCSI Vital Product Data (VPD) Page Extended Inquiry Data peripheral type: Direct access device. +#define ISCSI_SCSI_VPD_PAGE_EXT_INQUIRY_DATA_PERIPHERAL_TYPE_DIRECT 0x00 + +/// iSCSI SCSI Vital Product Data (VPD) Page Extended Inquiry Data peripheral type: Sequential access device. +#define ISCSI_SCSI_VPD_PAGE_EXT_INQUIRY_DATA_PERIPHERAL_TYPE_SEQ 0x01 + +/// iSCSI SCSI Vital Product Data (VPD) Page Extended Inquiry Data peripheral type: Printer device. +#define ISCSI_SCSI_VPD_PAGE_EXT_INQUIRY_DATA_PERIPHERAL_TYPE_PRINTER 0x02 + +/// iSCSI SCSI Vital Product Data (VPD) Page Extended Inquiry Data peripheral type: Processor device. +#define ISCSI_SCSI_VPD_PAGE_EXT_INQUIRY_DATA_PERIPHERAL_TYPE_PROCESSOR 0x03 + +/// iSCSI SCSI Vital Product Data (VPD) Page Extended Inquiry Data peripheral type: Write once device. +#define ISCSI_SCSI_VPD_PAGE_EXT_INQUIRY_DATA_PERIPHERAL_TYPE_WORM 0x04 + +/// iSCSI SCSI Vital Product Data (VPD) Page Extended Inquiry Data peripheral type: Read only direct access (e.g. CD-ROM) device. +#define ISCSI_SCSI_VPD_PAGE_EXT_INQUIRY_DATA_PERIPHERAL_TYPE_RO_DIRECT 0x05 + +/// iSCSI SCSI Vital Product Data (VPD) Page Extended Inquiry Data peripheral type: Scanner device. +#define ISCSI_SCSI_VPD_PAGE_EXT_INQUIRY_DATA_PERIPHERAL_TYPE_SCANNER 0x06 + +/// iSCSI SCSI Vital Product Data (VPD) Page Extended Inquiry Data peripheral type: Optical memory device. +#define ISCSI_SCSI_VPD_PAGE_EXT_INQUIRY_DATA_PERIPHERAL_TYPE_OPTICAL 0x07 + +/// iSCSI SCSI Vital Product Data (VPD) Page Extended Inquiry Data peripheral type: Medium changer device. +#define ISCSI_SCSI_VPD_PAGE_EXT_INQUIRY_DATA_PERIPHERAL_TYPE_CHANGER 0x08 + +/// iSCSI SCSI Vital Product Data (VPD) Page Extended Inquiry Data peripheral type: Communications device. +#define ISCSI_SCSI_VPD_PAGE_EXT_INQUIRY_DATA_PERIPHERAL_TYPE_COMM 0x09 + +/// iSCSI SCSI Vital Product Data (VPD) Page Extended Inquiry Data peripheral type: Unknown or no device. +#define ISCSI_SCSI_VPD_PAGE_EXT_INQUIRY_DATA_PERIPHERAL_TYPE_UNKNOWN 0x1F + +/// iSCSI SCSI Vital Product Data (VPD) Page Extended Inquiry Data peripheral type: First bit of the five bits. +#define ISCSI_SCSI_VPD_PAGE_EXT_INQUIRY_DATA_PERIPHERAL_TYPE_FIRST_BIT 0 + +/// iSCSI SCSI Vital Product Data (VPD) Page Extended Inquiry Data peripheral type: Last bit of the five bits. +#define ISCSI_SCSI_VPD_PAGE_EXT_INQUIRY_DATA_PERIPHERAL_TYPE_LAST_BIT ((ISCSI_SCSI_VPD_PAGE_EXT_INQUIRY_DATA_PERIPHERAL_TYPE_FIRST_BIT) + 5 - 1) + +/// iSCSI SCSI Vital Product Data (VPD) Page Extended Inquiry Data peripheral type: Bit mask. +#define ISCSI_SCSI_VPD_PAGE_EXT_INQUIRY_DATA_PERIPHERAL_TYPE_MASK (ISCSI_BITS_GET_MASK(ISCSI_SCSI_VPD_PAGE_EXT_INQUIRY_DATA_PERIPHERAL_TYPE_FIRST_BIT, ISCSI_SCSI_VPD_PAGE_EXT_INQUIRY_DATA_PERIPHERAL_TYPE_LAST_BIT)) + +/// iSCSI SCSI Vital Product Data (VPD) Page Extended Inquiry Data peripheral type: Extracts the peripheral device type bits. +#define ISCSI_SCSI_VPD_PAGE_EXT_INQUIRY_DATA_GET_PERIPHERAL_TYPE(x) (ISCSI_BITS_GET((x), ISCSI_SCSI_VPD_PAGE_EXT_INQUIRY_DATA_PERIPHERAL_TYPE_FIRST_BIT, ISCSI_SCSI_VPD_PAGE_EXT_INQUIRY_DATA_PERIPHERAL_TYPE_LAST_BIT)) + +/// iSCSI SCSI Vital Product Data (VPD) Page Extended Inquiry Data peripheral type: Stores into the peripheral device type bits. +#define ISCSI_SCSI_VPD_PAGE_EXT_INQUIRY_DATA_PUT_PERIPHERAL_TYPE(x) (ISCSI_BITS_PUT((x), ISCSI_SCSI_VPD_PAGE_EXT_INQUIRY_DATA_PERIPHERAL_TYPE_FIRST_BIT, ISCSI_SCSI_VPD_PAGE_EXT_INQUIRY_DATA_PERIPHERAL_TYPE_LAST_BIT)) + +/// iSCSI SCSI Vital Product Data (VPD) Page Extended Inquiry Data peripheral identifier: The specified peripheral device type is currently connected to this logical unit, or connection state could not be determined. +#define ISCSI_SCSI_VPD_PAGE_EXT_INQUIRY_DATA_PERIPHERAL_ID_POSSIBLE 0x0 + +/// iSCSI SCSI Vital Product Data (VPD) Page Extended Inquiry Data peripheral identifier: The target is capable of supporting the specified peripheral device type on this logical unit, but not connected. +#define ISCSI_SCSI_VPD_PAGE_EXT_INQUIRY_DATA_PERIPHERAL_ID_SUPPORTED 0x1 + +/// iSCSI SCSI Vital Product Data (VPD) Page Extended Inquiry Data peripheral identifier: The target is not capable of supporting a physical device on this logical unit. +#define ISCSI_SCSI_VPD_PAGE_EXT_INQUIRY_DATA_PERIPHERAL_ID_NEVER 0x3 + +/// iSCSI SCSI Vital Product Data (VPD) Page Extended Inquiry Data peripheral identifier: Vendor specific. +#define ISCSI_SCSI_VPD_PAGE_EXT_INQUIRY_DATA_PERIPHERAL_ID_VENDOR_UNIQ 0x4 + +/// iSCSI SCSI Vital Product Data (VPD) Page Extended Inquiry Data peripheral identifier: First bit of the three bits. +#define ISCSI_SCSI_VPD_PAGE_EXT_INQUIRY_DATA_PERIPHERAL_ID_FIRST_BIT 5 + +/// iSCSI SCSI Vital Product Data (VPD) Page Extended Inquiry Data peripheral identifier: Last bit of the three bits. +#define ISCSI_SCSI_VPD_PAGE_EXT_INQUIRY_DATA_PERIPHERAL_ID_LAST_BIT ((ISCSI_SCSI_VPD_PAGE_EXT_INQUIRY_DATA_PERIPHERAL_ID_FIRST_BIT) + 3 - 1) + +/// iSCSI SCSI Vital Product Data (VPD) Page Extended Inquiry Data peripheral identifier: Bit mask. +#define ISCSI_SCSI_VPD_PAGE_EXT_INQUIRY_DATA_PERIPHERAL_ID_MASK (ISCSI_BITS_GET_MASK(ISCSI_SCSI_VPD_PAGE_EXT_INQUIRY_DATA_PERIPHERAL_ID_FIRST_BIT, ISCSI_SCSI_VPD_PAGE_EXT_INQUIRY_DATA_PERIPHERAL_ID_LAST_BIT)) + +/// iSCSI SCSI Vital Product Data (VPD) Page Extended Inquiry Data peripheral identifier: Extracts the peripheral device identifier bits. +#define ISCSI_SCSI_VPD_PAGE_EXT_INQUIRY_DATA_GET_PERIPHERAL_ID(x) (ISCSI_BITS_GET((x), ISCSI_SCSI_VPD_PAGE_EXT_INQUIRY_DATA_PERIPHERAL_ID_FIRST_BIT, ISCSI_SCSI_VPD_PAGE_EXT_INQUIRY_DATA_PERIPHERAL_ID_LAST_BIT)) + +/// iSCSI SCSI Vital Product Data (VPD) Page Extended Inquiry Data peripheral identifier: Stores into the peripheral device identifier bits. +#define ISCSI_SCSI_VPD_PAGE_EXT_INQUIRY_DATA_PUT_PERIPHERAL_ID(x) (ISCSI_BITS_PUT((x), ISCSI_SCSI_VPD_PAGE_EXT_INQUIRY_DATA_PERIPHERAL_ID_FIRST_BIT, ISCSI_SCSI_VPD_PAGE_EXT_INQUIRY_DATA_PERIPHERAL_ID_LAST_BIT)) + + +/// iSCSI SCSI Vital Product Data (VPD) Page Extended Inquiry Data page code: Supported VPD pages. +#define ISCSI_SCSI_VPD_PAGE_EXT_INQUIRY_DATA_PAGE_CODE_SUPPORTED_VPD_PAGES 0x00 + +/// iSCSI SCSI Vital Product Data (VPD) Page Extended Inquiry Data page code: Unit serial number. +#define ISCSI_SCSI_VPD_PAGE_EXT_INQUIRY_DATA_PAGE_CODE_UNIT_SERIAL_NUMBER 0x80 + +/// iSCSI SCSI Vital Product Data (VPD) Page Extended Inquiry Data page code: Device identification. +#define ISCSI_SCSI_VPD_PAGE_EXT_INQUIRY_DATA_PAGE_CODE_DEVICE_ID 0x83 + +/// iSCSI SCSI Vital Product Data (VPD) Page Extended Inquiry Data page code: Software interface identification. +#define ISCSI_SCSI_VPD_PAGE_EXT_INQUIRY_DATA_PAGE_CODE_SOFTWARE_IFACE_ID 0x84 + +/// iSCSI SCSI Vital Product Data (VPD) Page Extended Inquiry Data page code: Management network addresses. +#define ISCSI_SCSI_VPD_PAGE_EXT_INQUIRY_DATA_PAGE_CODE_MANAGEMENT_NETWORK_ADDRS 0x85 + +/// iSCSI SCSI Vital Product Data (VPD) Page Extended Inquiry Data page code: Extended inquiry data. +#define ISCSI_SCSI_VPD_PAGE_EXT_INQUIRY_DATA_PAGE_CODE_EXTENDED_INQUIRY_DATA 0x86 + +/// iSCSI SCSI Vital Product Data (VPD) Page Extended Inquiry Data page code: Mode page policy. +#define ISCSI_SCSI_VPD_PAGE_EXT_INQUIRY_DATA_PAGE_CODE_MODE_PAGE_POLICY 0x87 + +/// iSCSI SCSI Vital Product Data (VPD) Page Extended Inquiry Data page code: SCSI ports. +#define ISCSI_SCSI_VPD_PAGE_EXT_INQUIRY_DATA_PAGE_CODE_SCSI_PORTS 0x88 + +/// iSCSI SCSI Vital Product Data (VPD) Page Extended Inquiry Data page code: Block limits. +#define ISCSI_SCSI_VPD_PAGE_EXT_INQUIRY_DATA_PAGE_CODE_BLOCK_LIMITS 0xB0 + +/// iSCSI SCSI Vital Product Data (VPD) Page Extended Inquiry Data page code: Block device characteristics. +#define ISCSI_SCSI_VPD_PAGE_EXT_INQUIRY_DATA_PAGE_CODE_BLOCK_DEV_CHARS 0xB1 + +/// iSCSI SCSI Vital Product Data (VPD) Page Extended Inquiry Data page code: Thin provisioning. +#define ISCSI_SCSI_VPD_PAGE_EXT_INQUIRY_DATA_PAGE_CODE_THIN_PROVISION 0xB2 + + +/// iSCSI SCSI Vital Product Data (VPD) Page Extended Inquiry Data check flags: RFTG check. +#define ISCSI_SCSI_VPD_PAGE_EXT_INQUIRY_DATA_CHECK_FLAGS_RFTG_CHK (1 << 0) + +/// iSCSI SCSI Vital Product Data (VPD) Page Extended Inquiry Data check flags: APTG check. +#define ISCSI_SCSI_VPD_PAGE_EXT_INQUIRY_DATA_CHECK_FLAGS_APTG_CHK (1 << 1) + +/// iSCSI SCSI Vital Product Data (VPD) Page Extended Inquiry Data check flags: GRD check. +#define ISCSI_SCSI_VPD_PAGE_EXT_INQUIRY_DATA_CHECK_FLAGS_GRD_CHK (1 << 2) + + +/// iSCSI SCSI Vital Product Data (VPD) Page Extended Inquiry Data support flags: SIMP support. +#define ISCSI_SCSI_VPD_PAGE_EXT_INQUIRY_DATA_SUPPORT_FLAGS_SIMPSUP (1 << 0) + +/// iSCSI SCSI Vital Product Data (VPD) Page Extended Inquiry Data support flags: ORD support. +#define ISCSI_SCSI_VPD_PAGE_EXT_INQUIRY_DATA_SUPPORT_FLAGS_ORDSUP (1 << 1) + +/// iSCSI SCSI Vital Product Data (VPD) Page Extended Inquiry Data support flags: HEAD support. +#define ISCSI_SCSI_VPD_PAGE_EXT_INQUIRY_DATA_SUPPORT_FLAGS_HEADSUP (1 << 2) + +/// iSCSI SCSI Vital Product Data (VPD) Page Extended Inquiry Data support flags: PRIOR support. +#define ISCSI_SCSI_VPD_PAGE_EXT_INQUIRY_DATA_SUPPORT_FLAGS_PRIOR_SUP (1 << 3) + +/// iSCSI SCSI Vital Product Data (VPD) Page Extended Inquiry Data support flags: GROUP support. +#define ISCSI_SCSI_VPD_PAGE_EXT_INQUIRY_DATA_SUPPORT_FLAGS_GROUP_SUP (1 << 4) + + +/** + * @brief iSCSI SCSI Vital Product Data (VPD) Extended Inquiry data packet. + * + * This structure is used by the SCSI INQUIRY command + * in order to fill in the result if the EVPD bit is + * set. + */ +typedef struct __attribute__((packed)) iscsi_scsi_vpd_page_ext_inquiry_data_packet { + /// Peripheral device type and qualifier. + uint8_t peripheral_type_id; + + /// Page code. + uint8_t page_code; + + /// Reserved for future usage (always MUST be 0). + uint8_t reserved; + + /// Page length in bytes. + uint8_t page_len; + + /// Check flags. + int8_t check_flags; + + /// Support flags. + int8_t support_flags; + + /// More support flags. + int8_t support_flags_2; + + /// LUICLR. + uint8_t luiclr; + + /// CBCS. + uint8_t cbcs; + + /// Micro DL. + uint8_t micro_dl; + + /// Reserved for future usage (always MUST be 0). + uint64_t reserved2[6]; + + /// Reserved for future usage (always MUST be 0). + uint32_t reserved3; + + /// Reserved for future usage (always MUST be 0). + uint16_t reserved4; +} iscsi_scsi_vpd_page_ext_inquiry_data_packet; - /// Reserved for future usage (always MUST be 0 for now). - uint16_t reserved; - /// Parameter list length in bytes. - uint32_t param_list_len; +/// iSCSI SCSI Vital Product Data (VPD) Mode Page Policy Descriptor Inquiry Data policy page code: First bit of the six bits. +#define ISCSI_SCSI_VPD_MODE_PAGE_POLICY_DESC_INQUIRY_DATA_POLICY_PAGE_CODE_FIRST_BIT 0 - /// Control. - uint8_t control; -} iscsi_scsi_cdb_pr_reserve_out; +/// iSCSI SCSI Vital Product Data (VPD) Mode Page Policy Descriptor Inquiry Data policy page code: Last bit of the six bits. +#define ISCSI_SCSI_VPD_MODE_PAGE_POLICY_DESC_INQUIRY_DATA_POLICY_PAGE_CODE_LAST_BIT ((ISCSI_SCSI_VPD_MODE_PAGE_POLICY_DESC_INQUIRY_DATA_POLICY_PAGE_CODE_FIRST_BIT) + 6 - 1) +/// iSCSI SCSI Vital Product Data (VPD) Mode Page Policy Descriptor Inquiry Data policy page code: Bit mask. +#define ISCSI_SCSI_VPD_MODE_PAGE_POLICY_DESC_INQUIRY_DATA_POLICY_PAGE_CODE_MASK (ISCSI_BITS_GET_MASK(ISCSI_SCSI_VPD_MODE_PAGE_POLICY_DESC_INQUIRY_DATA_POLICY_PAGE_CODE_FIRST_BIT, ISCSI_SCSI_VPD_MODE_PAGE_POLICY_DESC_INQUIRY_DATA_POLICY_PAGE_CODE_LAST_BIT)) -/// iSCSI SCSI Command Descriptor Block (CDB) for PERSISTENT RESERVE IN command service action: Read keys - Reads all registered reservation keys (i.e. registrations) as described in SPC5. -#define ISCSI_SCSI_CDB_PR_RESERVE_IN_ACTION_READ_KEYS 0x00 +/// iSCSI SCSI Vital Product Data (VPD) Mode Page Policy Descriptor Inquiry Data policy page code: Extracts the policy page code bits. +#define ISCSI_SCSI_VPD_MODE_PAGE_POLICY_DESC_INQUIRY_DATA_GET_POLICY_PAGE_CODE(x) (ISCSI_BITS_GET((x), ISCSI_SCSI_VPD_MODE_PAGE_POLICY_DESC_INQUIRY_DATA_POLICY_PAGE_CODE_FIRST_BIT, ISCSI_SCSI_VPD_MODE_PAGE_POLICY_DESC_INQUIRY_DATA_POLICY_PAGE_CODE_LAST_BIT)) -/// iSCSI SCSI Command Descriptor Block (CDB) for PERSISTENT RESERVE IN command service action: Read reservations - Reads the current persistent reservations as described in SPC5. -#define ISCSI_SCSI_CDB_PR_RESERVE_IN_ACTION_READ_RESERVATIONS 0x01 +/// iSCSI SCSI Vital Product Data (VPD) Mode Page Policy Descriptor Inquiry Data policy page code: Stores into the policy page code bits. +#define ISCSI_SCSI_VPD_MODE_PAGE_POLICY_DESC_INQUIRY_DATA_PUT_POLICY_PAGE_CODE(x) (ISCSI_BITS_PUT((x), ISCSI_SCSI_VPD_MODE_PAGE_POLICY_DESC_INQUIRY_DATA_POLICY_PAGE_CODE_FIRST_BIT, ISCSI_SCSI_VPD_MODE_PAGE_POLICY_DESC_INQUIRY_DATA_POLICY_PAGE_CODE_LAST_BIT)) -/// iSCSI SCSI Command Descriptor Block (CDB) for PERSISTENT RESERVE IN command service action: Report capabilities - Returns capability information. -#define ISCSI_SCSI_CDB_PR_RESERVE_IN_ACTION_READ_REPORT_CAPABILITIES 0x02 -/// iSCSI SCSI Command Descriptor Block (CDB) for PERSISTENT RESERVE IN command service action: Read full status – Reads complete information about all registrations and the persistent reservations, if any. -#define ISCSI_SCSI_CDB_PR_RESERVE_IN_ACTION_READ_FULL_STATUS 0x03 +/// iSCSI SCSI Vital Product Data (VPD) Mode Page Policy Descriptor Inquiry Data flags mode page policy: First bit of the two bits. +#define ISCSI_SCSI_VPD_MODE_PAGE_POLICY_DESC_INQUIRY_DATA_FLAGS_MODE_PAGE_POLICY_FIRST_BIT 0 -/// iSCSI SCSI Command Descriptor Block (CDB) for PERSISTENT RESERVE IN command service action: First bit of the five bits. -#define ISCSI_SCSI_CDB_PR_RESERVE_IN_ACTION_FIRST_BIT 0 +/// iSCSI SCSI Vital Product Data (VPD) Mode Page Policy Descriptor Inquiry Data flags mode page policy: Last bit of the two bits. +#define ISCSI_SCSI_VPD_MODE_PAGE_POLICY_DESC_INQUIRY_DATA_FLAGS_MODE_PAGE_POLICY_LAST_BIT ((ISCSI_SCSI_VPD_MODE_PAGE_POLICY_DESC_INQUIRY_DATA_FLAGS_MODE_PAGE_POLICY_FIRST_BIT) + 2 - 1) -/// iSCSI SCSI Command Descriptor Block (CDB) for PERSISTENT RESERVE IN command service action: Last bit of the five bits. -#define ISCSI_SCSI_CDB_PR_RESERVE_IN_ACTION_LAST_BIT ((ISCSI_SCSI_CDB_PR_RESERVE_IN_ACTION_FIRST_BIT) + 5 - 1) +/// iSCSI SCSI Vital Product Data (VPD) Mode Page Policy Descriptor Inquiry Data flags mode page policy: Bit mask. +#define ISCSI_SCSI_VPD_MODE_PAGE_POLICY_DESC_INQUIRY_DATA_FLAGS_MODE_PAGE_POLICY_MASK (ISCSI_BITS_GET_MASK(ISCSI_SCSI_VPD_MODE_PAGE_POLICY_DESC_INQUIRY_DATA_FLAGS_MODE_PAGE_POLICY_FIRST_BIT, ISCSI_SCSI_VPD_MODE_PAGE_POLICY_DESC_INQUIRY_DATA_FLAGS_MODE_PAGE_POLICY_LAST_BIT)) -/// iSCSI SCSI Command Descriptor Block (CDB) for PERSISTENT RESERVE IN command service action: Bit mask. -#define ISCSI_SCSI_CDB_PR_RESERVE_IN_ACTION_MASK (ISCSI_BITS_GET_MASK(ISCSI_SCSI_CDB_PR_RESERVE_IN_ACTION_FIRST_BIT, ISCSI_SCSI_CDB_PR_RESERVE_IN_ACTION_LAST_BIT)) +/// iSCSI SCSI Vital Product Data (VPD) Mode Page Policy Descriptor Inquiry Data flags mode page policy: Extracts the mode page policy bits. +#define ISCSI_SCSI_VPD_MODE_PAGE_POLICY_DESC_INQUIRY_DATA_FLAGS_GET_MODE_PAGE_POLICY(x) (ISCSI_BITS_GET((x), ISCSI_SCSI_VPD_MODE_PAGE_POLICY_DESC_INQUIRY_DATA_FLAGS_MODE_PAGE_POLICY_FIRST_BIT, ISCSI_SCSI_VPD_MODE_PAGE_POLICY_DESC_INQUIRY_DATA_FLAGS_MODE_PAGE_POLICY_LAST_BIT)) -/// iSCSI SCSI Command Descriptor Block (CDB) for PERSISTENT RESERVE IN command service action: Extracts the service action bits. -#define ISCSI_SCSI_CDB_PR_RESERVE_IN_GET_ACTION(x) (ISCSI_BITS_GET((x), ISCSI_SCSI_CDB_PR_RESERVE_IN_ACTION_FIRST_BIT, ISCSI_SCSI_CDB_PR_RESERVE_IN_ACTION_LAST_BIT)) +/// iSCSI SCSI Vital Product Data (VPD) Mode Page Policy Descriptor Inquiry Data flags mode page policy: Stores into the mode page policy bits. +#define ISCSI_SCSI_VPD_MODE_PAGE_POLICY_DESC_INQUIRY_DATA_FLAGS_PUT_MODE_PAGE_POLICY(x) (ISCSI_BITS_PUT((x), ISCSI_SCSI_VPD_MODE_PAGE_POLICY_DESC_INQUIRY_DATA_FLAGS_MODE_PAGE_POLICY_FIRST_BIT, ISCSI_SCSI_VPD_MODE_PAGE_POLICY_DESC_INQUIRY_DATA_FLAGS_MODE_PAGE_POLICY_LAST_BIT)) -/// iSCSI SCSI Command Descriptor Block (CDB) for PERSISTENT RESERVE IN command service action: Stores into the service action bits. -#define ISCSI_SCSI_CDB_PR_RESERVE_IN_PUT_ACTION(x) (ISCSI_BITS_PUT((x), ISCSI_SCSI_CDB_PR_RESERVE_IN_ACTION_FIRST_BIT, ISCSI_SCSI_CDB_PR_RESERVE_IN_ACTION_LAST_BIT)) +/// iSCSI SCSI Vital Product Data (VPD) Mode Page Policy Descriptor Inquiry Data flag: Multiple Logical Units Share (MLUS). +#define ISCSI_SCSI_VPD_MODE_PAGE_POLICY_DESC_INQUIRY_DATA_FLAGS_MLUS (1 << 7) /** - * @brief iSCSI SCSI CDB packet data structure for SCSI PERSISTENT RESERVE IN command. + * @brief iSCSI SCSI Vital Product Data (VPD) Mode Page Policy Descriptor Inquiry data packet. * - * There are 10 bytes in the CDB field for this command. + * This structure is used by the SCSI INQUIRY command + * in order to fill in the result if the EVPD bit is + * set. */ -typedef struct __attribute__((packed)) iscsi_scsi_cdb_pr_reserve_in { - /// SCSI opcode. - iscsi_scsi_cdb cdb; +typedef struct __attribute__((packed)) iscsi_scsi_vpd_mode_page_policy_desc_inquiry_data_packet { + /// Policy page code. + uint8_t page_code; - /// Service action. - uint8_t action; + /// Policy sub page code. + uint8_t sub_page_code; - /// Reserved for future usage (always MUST be 0 for now). - uint32_t reserved; + /// Policy flags. + int8_t flags; - /// Reserved for future usage (always MUST be 0 for now). - uint8_t reserved2; + /// Reserved for future usage (always MUST be 0). + uint8_t reserved; +} iscsi_scsi_vpd_mode_page_policy_desc_inquiry_data_packet; - /// Parameter list length in bytes. - uint16_t param_list_len; - /// Control. - uint8_t control; -} iscsi_scsi_cdb_pr_reserve_in; +/// iSCSI SCSI Vital Product Data (VPD) SCSI Target Port Designation Descriptor Inquiry data protocol identifier: iSCSI. +#define ISCSI_SCSI_VPD_SCSI_TARGET_PORT_DESIGN_DESC_INQUIRY_DATA_PROTOCOL_ID_ISCSI 0x05 +/// iSCSI SCSI Vital Product Data (VPD) SCSI Target Port Designation Descriptor Inquiry data protocol identifier: First bit of the four bits. +#define ISCSI_SCSI_VPD_SCSI_TARGET_PORT_DESIGN_DESC_INQUIRY_DATA_PROTOCOL_ID_FIRST_BIT 0 -/** - * @brief iSCSI SCSI CDB packet data structure for SCSI RESERVE(6) command. - * - * There are 6 bytes in the CDB field for this command. - */ -typedef struct __attribute__((packed)) iscsi_scsi_cdb_pr_reserve_6 { - /// SCSI opcode. - iscsi_scsi_cdb cdb; +/// iSCSI SCSI Vital Product Data (VPD) SCSI Target Port Designation Descriptor Inquiry data protocol identifier: Last bit of the four bits. +#define ISCSI_SCSI_VPD_SCSI_TARGET_PORT_DESIGN_DESC_INQUIRY_DATA_PROTOCOL_ID_LAST_BIT ((ISCSI_SCSI_VPD_SCSI_TARGET_PORT_DESIGN_DESC_INQUIRY_DATA_PROTOCOL_ID_FIRST_BIT) + 4 - 1) - /// Reserved for future usage (always MUST be 0 for now). - uint8_t reserved_obselete; +/// iSCSI SCSI Vital Product Data (VPD) SCSI Target Port Designation Descriptor Inquiry data protocol identifier: Bit mask. +#define ISCSI_SCSI_VPD_SCSI_TARGET_PORT_DESIGN_DESC_INQUIRY_DATA_PROTOCOL_ID_MASK (ISCSI_BITS_GET_MASK(ISCSI_SCSI_VPD_SCSI_TARGET_PORT_DESIGN_DESC_INQUIRY_DATA_PROTOCOL_ID_FIRST_BIT, ISCSI_SCSI_VPD_SCSI_TARGET_PORT_DESIGN_DESC_INQUIRY_DATA_PROTOCOL_ID_LAST_BIT)) - /// Obselete byte. - uint8_t obselete; +/// iSCSI SCSI Vital Product Data (VPD) SCSI Target Port Designation Descriptor Inquiry data protocol identifier: Extracts the protocol identifier bits. +#define ISCSI_SCSI_VPD_SCSI_TARGET_PORT_DESIGN_DESC_INQUIRY_DATA_GET_PROTOCOL_ID(x) (ISCSI_BITS_GET((x), ISCSI_SCSI_VPD_SCSI_TARGET_PORT_DESIGN_DESC_INQUIRY_DATA_PROTOCOL_ID_FIRST_BIT, ISCSI_SCSI_VPD_SCSI_TARGET_PORT_DESIGN_DESC_INQUIRY_DATA_PROTOCOL_ID_LAST_BIT)) - /// Obselete word. - uint16_t obselete2; +/// iSCSI SCSI Vital Product Data (VPD) SCSI Target Port Designation Descriptor Inquiry data protocol identifier: Stores into the protocol identifier bits. +#define ISCSI_SCSI_VPD_SCSI_TARGET_PORT_DESIGN_DESC_INQUIRY_DATA_PUT_PROTOCOL_ID(x) (ISCSI_BITS_PUT((x), ISCSI_SCSI_VPD_SCSI_TARGET_PORT_DESIGN_DESC_INQUIRY_DATA_PROTOCOL_ID_FIRST_BIT, ISCSI_SCSI_VPD_SCSI_TARGET_PORT_DESIGN_DESC_INQUIRY_DATA_PROTOCOL_ID_LAST_BIT)) - /// Control. - uint8_t control; -} iscsi_scsi_cdb_pr_reserve_6; +/// iSCSI SCSI Vital Product Data (VPD) SCSI Target Port Designation Descriptor Inquiry data code set: Binary encoding. +#define ISCSI_SCSI_VPD_SCSI_TARGET_PORT_DESIGN_DESC_INQUIRY_DATA_CODE_SET_BINARY 0x01 +/// iSCSI SCSI Vital Product Data (VPD) SCSI Target Port Designation Descriptor Inquiry data code set: ASCII encoding. +#define ISCSI_SCSI_VPD_SCSI_TARGET_PORT_DESIGN_DESC_INQUIRY_DATA_CODE_SET_ASCII 0x02 -/// iSCSI SCSI Command Descriptor Block (CDB) for RESERVE(10) command flags: Long identifier larger than 255 (LONGID). -#define ISCSI_SCSI_CDB_RESERVE_10_FLAGS_LONGID (1 << 1) +/// iSCSI SCSI Vital Product Data (VPD) SCSI Target Port Designation Descriptor Inquiry data code set: UTF-8 encoding. +#define ISCSI_SCSI_VPD_SCSI_TARGET_PORT_DESIGN_DESC_INQUIRY_DATA_CODE_SET_UTF8 0x03 -/// iSCSI SCSI Command Descriptor Block (CDB) for RESERVE(10) command flags: Third-party reservation (3RDPTY). -#define ISCSI_SCSI_CDB_RESERVE_10_FLAGS_3RDPTY (1 << 4) +/// iSCSI SCSI Vital Product Data (VPD) SCSI Target Port Designation Descriptor Inquiry data code set: First bit of the four bits. +#define ISCSI_SCSI_VPD_SCSI_TARGET_PORT_DESIGN_DESC_INQUIRY_DATA_CODE_SET_FIRST_BIT 4 +/// iSCSI SCSI Vital Product Data (VPD) SCSI Target Port Designation Descriptor Inquiry data code set: Last bit of the four bits. +#define ISCSI_SCSI_VPD_SCSI_TARGET_PORT_DESIGN_DESC_INQUIRY_DATA_CODE_SET_LAST_BIT ((ISCSI_SCSI_VPD_SCSI_TARGET_PORT_DESIGN_DESC_INQUIRY_DATA_CODE_SET_FIRST_BIT) + 8 - 1) -/** - * @brief iSCSI SCSI CDB packet data structure for SCSI RESERVE(10) command. - * - * There are 10 bytes in the CDB field for this command. - */ -typedef struct __attribute__((packed)) iscsi_scsi_cdb_pr_reserve_10 { - /// SCSI opcode. - iscsi_scsi_cdb cdb; +/// iSCSI SCSI Vital Product Data (VPD) SCSI Target Port Designation Descriptor Inquiry data code set: Bit mask. +#define ISCSI_SCSI_VPD_SCSI_TARGET_PORT_DESIGN_DESC_INQUIRY_DATA_CODE_SET_MASK (ISCSI_BITS_GET_MASK(ISCSI_SCSI_VPD_SCSI_TARGET_PORT_DESIGN_DESC_INQUIRY_DATA_CODE_SET_FIRST_BIT, ISCSI_SCSI_VPD_SCSI_TARGET_PORT_DESIGN_DESC_INQUIRY_DATA_CODE_SET_LAST_BIT)) - /// Flags. - int8_t flags; +/// iSCSI SCSI Vital Product Data (VPD) SCSI Target Port Designation Descriptor Inquiry data code set: Extracts the protocol identifier bits. +#define ISCSI_SCSI_VPD_SCSI_TARGET_PORT_DESIGN_DESC_INQUIRY_DATA_GET_CODE_SET(x) (ISCSI_BITS_GET((x), ISCSI_SCSI_VPD_SCSI_TARGET_PORT_DESIGN_DESC_INQUIRY_DATA_CODE_SET_FIRST_BIT, ISCSI_SCSI_VPD_SCSI_TARGET_PORT_DESIGN_DESC_INQUIRY_DATA_CODE_SET_LAST_BIT)) - /// Obselete. - uint8_t obselete; +/// iSCSI SCSI Vital Product Data (VPD) SCSI Target Port Designation Descriptor Inquiry data code set: Stores into the protocol identifier bits. +#define ISCSI_SCSI_VPD_SCSI_TARGET_PORT_DESIGN_DESC_INQUIRY_DATA_PUT_CODE_SET(x) (ISCSI_BITS_PUT((x), ISCSI_SCSI_VPD_SCSI_TARGET_PORT_DESIGN_DESC_INQUIRY_DATA_CODE_SET_FIRST_BIT, ISCSI_SCSI_VPD_SCSI_TARGET_PORT_DESIGN_DESC_INQUIRY_DATA_CODE_SET_LAST_BIT)) - /// Third-party device identifier. - uint8_t third_party_dev_id; - /// Reserved for future usage (always MUST be 0 for now). - uint16_t reserved; +/// iSCSI SCSI Vital Product Data (VPD) SCSI Target Port Designation Descriptor Inquiry data flags type: Vendor specific. +#define ISCSI_SCSI_VPD_SCSI_TARGET_PORT_DESIGN_DESC_INQUIRY_DATA_FLAGS_TYPE_VENDOR_SPEC 0x00 - /// Reserved for future usage (always MUST be 0 for now). - uint8_t reserved2; +/// iSCSI SCSI Vital Product Data (VPD) SCSI Target Port Designation Descriptor Inquiry data flags type: T10 vendor identifier. +#define ISCSI_SCSI_VPD_SCSI_TARGET_PORT_DESIGN_DESC_INQUIRY_DATA_FLAGS_TYPE_T10_VENDOR_ID 0x01 - /// Parameter list length in bytes. - uint16_t param_list_len; +/// iSCSI SCSI Vital Product Data (VPD) SCSI Target Port Designation Descriptor Inquiry data flags type: EUI64. +#define ISCSI_SCSI_VPD_SCSI_TARGET_PORT_DESIGN_DESC_INQUIRY_DATA_FLAGS_TYPE_EUI64 0x02 - /// Control. - uint8_t control; -} iscsi_scsi_cdb_pr_reserve_10; +/// iSCSI SCSI Vital Product Data (VPD) SCSI Target Port Designation Descriptor Inquiry data flags type: NAA. +#define ISCSI_SCSI_VPD_SCSI_TARGET_PORT_DESIGN_DESC_INQUIRY_DATA_FLAGS_TYPE_NAA 0x03 +/// iSCSI SCSI Vital Product Data (VPD) SCSI Target Port Designation Descriptor Inquiry data flags type: Relative target port. +#define ISCSI_SCSI_VPD_SCSI_TARGET_PORT_DESIGN_DESC_INQUIRY_DATA_FLAGS_TYPE_REL_TARGET_PORT 0x04 -/** - * @brief iSCSI SCSI CDB packet data structure for SCSI RELEASE(6) command. - * - * There are 6 bytes in the CDB field for this command. - */ -typedef struct __attribute__((packed)) iscsi_scsi_cdb_pr_release_6 { - /// SCSI opcode. - iscsi_scsi_cdb cdb; +/// iSCSI SCSI Vital Product Data (VPD) SCSI Target Port Designation Descriptor Inquiry data flags type: Target port group. +#define ISCSI_SCSI_VPD_SCSI_TARGET_PORT_DESIGN_DESC_INQUIRY_DATA_FLAGS_TYPE_TARGET_PORT_GROUP 0x05 - /// Reserved for future usage (always MUST be 0 for now). - uint8_t reserved_obselete; +/// iSCSI SCSI Vital Product Data (VPD) SCSI Target Port Designation Descriptor Inquiry data flags type: Logical unit group. +#define ISCSI_SCSI_VPD_SCSI_TARGET_PORT_DESIGN_DESC_INQUIRY_DATA_FLAGS_TYPE_LOGICAL_UNIT_GROUP 0x06 - /// Obselete byte. - uint8_t obselete; +/// iSCSI SCSI Vital Product Data (VPD) SCSI Target Port Designation Descriptor Inquiry data flags type: MD5 logical unit. +#define ISCSI_SCSI_VPD_SCSI_TARGET_PORT_DESIGN_DESC_INQUIRY_DATA_FLAGS_TYPE_MD5_LOGICAL_UNIT 0x07 - /// Obselete word. - uint16_t obselete2; +/// iSCSI SCSI Vital Product Data (VPD) SCSI Target Port Designation Descriptor Inquiry data flags type: SCSI name. +#define ISCSI_SCSI_VPD_SCSI_TARGET_PORT_DESIGN_DESC_INQUIRY_DATA_FLAGS_TYPE_SCSI_NAME 0x08 - /// Control. - uint8_t control; -} iscsi_scsi_cdb_pr_release_6; +/// iSCSI SCSI Vital Product Data (VPD) SCSI Target Port Designation Descriptor Inquiry data flags type: First bit of the four bits. +#define ISCSI_SCSI_VPD_SCSI_TARGET_PORT_DESIGN_DESC_INQUIRY_DATA_FLAGS_TYPE_FIRST_BIT 0 +/// iSCSI SCSI Vital Product Data (VPD) SCSI Target Port Designation Descriptor Inquiry data flags type: Last bit of the four bits. +#define ISCSI_SCSI_VPD_SCSI_TARGET_PORT_DESIGN_DESC_INQUIRY_DATA_FLAGS_TYPE_LAST_BIT ((ISCSI_SCSI_VPD_SCSI_TARGET_PORT_DESIGN_DESC_INQUIRY_DATA_FLAGS_TYPE_FIRST_BIT) + 4 - 1) -/// iSCSI SCSI Command Descriptor Block (CDB) for RELEASE(10) command flags: Long identifier larger than 255 (LONGID). -#define ISCSI_SCSI_CDB_RELEASE_10_FLAGS_LONGID (1 << 1) +/// iSCSI SCSI Vital Product Data (VPD) SCSI Target Port Designation Descriptor Inquiry data flags type: Bit mask. +#define ISCSI_SCSI_VPD_SCSI_TARGET_PORT_DESIGN_DESC_INQUIRY_DATA_FLAGS_TYPE_MASK (ISCSI_BITS_GET_MASK(ISCSI_SCSI_VPD_SCSI_TARGET_PORT_DESIGN_DESC_INQUIRY_DATA_FLAGS_TYPE_FIRST_BIT, ISCSI_SCSI_VPD_SCSI_TARGET_PORT_DESIGN_DESC_INQUIRY_DATA_FLAGS_TYPE_LAST_BIT)) -/// iSCSI SCSI Command Descriptor Block (CDB) for RELEASE(10) command flags: Third-party reservation (3RDPTY). -#define ISCSI_SCSI_CDB_RELEASE_10_FLAGS_3RDPTY (1 << 4) +/// iSCSI SCSI Vital Product Data (VPD) SCSI Target Port Designation Descriptor Inquiry data flags type: Extracts the type bits. +#define ISCSI_SCSI_VPD_SCSI_TARGET_PORT_DESIGN_DESC_INQUIRY_DATA_FLAGS_GET_TYPE(x) (ISCSI_BITS_GET((x), ISCSI_SCSI_VPD_SCSI_TARGET_PORT_DESIGN_DESC_INQUIRY_DATA_FLAGS_TYPE_FIRST_BIT, ISCSI_SCSI_VPD_SCSI_TARGET_PORT_DESIGN_DESC_INQUIRY_DATA_FLAGS_TYPE_LAST_BIT)) + +/// iSCSI SCSI Vital Product Data (VPD) SCSI Target Port Designation Descriptor Inquiry data flags type: Stores into the type bits. +#define ISCSI_SCSI_VPD_SCSI_TARGET_PORT_DESIGN_DESC_INQUIRY_DATA_FLAGS_PUT_TYPE(x) (ISCSI_BITS_PUT((x), ISCSI_SCSI_VPD_SCSI_TARGET_PORT_DESIGN_DESC_INQUIRY_DATA_FLAGS_TYPE_FIRST_BIT, ISCSI_SCSI_VPD_SCSI_TARGET_PORT_DESIGN_DESC_INQUIRY_DATA_FLAGS_TYPE_LAST_BIT)) + +/// iSCSI SCSI Vital Product Data (VPD) SCSI Target Port Designation Descriptor Inquiry data flags association: Logical unit. +#define ISCSI_SCSI_VPD_SCSI_TARGET_PORT_DESIGN_DESC_INQUIRY_DATA_FLAGS_ASSOC_LOGICAL_UNIT 0x0 + +/// iSCSI SCSI Vital Product Data (VPD) SCSI Target Port Designation Descriptor Inquiry data flags association: Target port. +#define ISCSI_SCSI_VPD_SCSI_TARGET_PORT_DESIGN_DESC_INQUIRY_DATA_FLAGS_ASSOC_TARGET_PORT 0x1 + +/// iSCSI SCSI Vital Product Data (VPD) SCSI Target Port Designation Descriptor Inquiry data flags association: Target device. +#define ISCSI_SCSI_VPD_SCSI_TARGET_PORT_DESIGN_DESC_INQUIRY_DATA_FLAGS_ASSOC_TARGET_DEVICE 0x2 + +/// iSCSI SCSI Vital Product Data (VPD) SCSI Target Port Designation Descriptor Inquiry data flags association: First bit of the two bits. +#define ISCSI_SCSI_VPD_SCSI_TARGET_PORT_DESIGN_DESC_INQUIRY_DATA_FLAGS_ASSOC_FIRST_BIT 4 + +/// iSCSI SCSI Vital Product Data (VPD) SCSI Target Port Designation Descriptor Inquiry data flags association: Last bit of the two bits. +#define ISCSI_SCSI_VPD_SCSI_TARGET_PORT_DESIGN_DESC_INQUIRY_DATA_FLAGS_ASSOC_LAST_BIT ((ISCSI_SCSI_VPD_SCSI_TARGET_PORT_DESIGN_DESC_INQUIRY_DATA_FLAGS_ASSOC_FIRST_BIT) + 6 - 1) + +/// iSCSI SCSI Vital Product Data (VPD) SCSI Target Port Designation Descriptor Inquiry data flags association: Bit mask. +#define ISCSI_SCSI_VPD_SCSI_TARGET_PORT_DESIGN_DESC_INQUIRY_DATA_FLAGS_ASSOC_MASK (ISCSI_BITS_GET_MASK(ISCSI_SCSI_VPD_SCSI_TARGET_PORT_DESIGN_DESC_INQUIRY_DATA_FLAGS_ASSOC_FIRST_BIT, ISCSI_SCSI_VPD_SCSI_TARGET_PORT_DESIGN_DESC_INQUIRY_DATA_FLAGS_ASSOC_LAST_BIT)) + +/// iSCSI SCSI Vital Product Data (VPD) SCSI Target Port Designation Descriptor Inquiry data flags association: Extracts the association bits. +#define ISCSI_SCSI_VPD_SCSI_TARGET_PORT_DESIGN_DESC_INQUIRY_DATA_FLAGS_GET_ASSOC(x) (ISCSI_BITS_GET((x), ISCSI_SCSI_VPD_SCSI_TARGET_PORT_DESIGN_DESC_INQUIRY_DATA_FLAGS_ASSOC_FIRST_BIT, ISCSI_SCSI_VPD_SCSI_TARGET_PORT_DESIGN_DESC_INQUIRY_DATA_FLAGS_ASSOC_LAST_BIT)) + +/// iSCSI SCSI Vital Product Data (VPD) SCSI Target Port Designation Descriptor Inquiry data flags association: Stores into the association bits. +#define ISCSI_SCSI_VPD_SCSI_TARGET_PORT_DESIGN_DESC_INQUIRY_DATA_FLAGS_PUT_ASSOC(x) (ISCSI_BITS_PUT((x), ISCSI_SCSI_VPD_SCSI_TARGET_PORT_DESIGN_DESC_INQUIRY_DATA_FLAGS_ASSOC_FIRST_BIT, ISCSI_SCSI_VPD_SCSI_TARGET_PORT_DESIGN_DESC_INQUIRY_DATA_FLAGS_ASSOC_LAST_BIT)) + +/// iSCSI SCSI Vital Product Data (VPD) SCSI Target Port Designation Descriptor Inquiry data flags: Protocol Identifier Valid (PIV). +#define ISCSI_SCSI_VPD_SCSI_TARGET_PORT_DESIGN_DESC_INQUIRY_DATA_FLAGS_PIV (1 << 7) /** - * @brief iSCSI SCSI CDB packet data structure for SCSI RELEASE(10) command. + * @brief iSCSI SCSI Vital Product Data (VPD) SCSI Target Port Designation Descriptor Inquiry data packet. * - * There are 10 bytes in the CDB field for this command. + * This structure is used by the SCSI INQUIRY command + * in order to fill in the result if the EVPD bit is + * set. */ -typedef struct __attribute__((packed)) iscsi_scsi_cdb_pr_release_10 { - /// SCSI opcode. - iscsi_scsi_cdb cdb; +typedef struct __attribute__((packed)) iscsi_scsi_vpd_scsi_target_port_design_dec_inquiry_data_packet { + /// Protocol identifier and code set. + uint8_t protocol_id_code_set; /// Flags. int8_t flags; - /// Obselete. - uint8_t obselete; - - /// Third-party device identifier. - uint8_t third_party_dev_id; - - /// Reserved for future usage (always MUST be 0 for now). - uint16_t reserved; - - /// Reserved for future usage (always MUST be 0 for now). - uint8_t reserved2; + /// Reserved for future usage (always MUST be 0). + uint8_t reserved; - /// Parameter list length in bytes. - uint16_t param_list_len; + /// Length in bytes. + uint8_t len; - /// Control. - uint8_t control; -} iscsi_scsi_cdb_pr_release_10; + /// Designator. + uint8_t design[0]; +} iscsi_scsi_vpd_scsi_target_port_design_dec_inquiry_data_packet; /** - * @brief iSCSI SCSI DataSegment Command packet structure. - * - * iSCSI targets MUST support and enable Autosense. If Status is CHECK - * CONDITION (0x02), then the data segment MUST contain sense data for - * the failed command. + * @brief iSCSI SCSI Vital Product Data (VPD) SCSI Port Designation Descriptor Inquiry data packet. * - * For some iSCSI responses, the response data segment MAY contain some - * response-related information (e.g., for a target failure, it may - * contain a vendor-specific detailed description of the failure). + * This structure is used by the SCSI INQUIRY command + * in order to fill in the result if the EVPD bit is + * set. */ -typedef struct __attribute__((packed)) iscsi_scsi_ds_cmd_data { - /// SenseLength: This field indicates the length of Sense Data. - uint16_t len; +typedef struct __attribute__((packed)) iscsi_scsi_vpd_scsi_port_design_dec_inquiry_data_packet { + /// Reserved for future usage (always MUST be 0). + uint16_t reserved; - /// The Sense Data contains detailed information about a CHECK CONDITION. SPC3 specifies the format and content of the Sense Data. - uint8_t sense_data[0]; + /// Relative port identifier. + uint16_t rel_port_id; - /// Response Data. - uint8_t res_data[0]; -} iscsi_scsi_ds_cmd_data; + /// Reserved for future usage (always MUST be 0). + uint16_t reserved2; + /// Initiator port length in bytes. + uint16_t init_port_len; -/// iSCSI SCSI Data peripheral type: Direct access device. -#define ISCSI_SCSI_DATA_PERIPHERAL_TYPE_DIRECT 0x00 + /// Initiator port identifier. + uint16_t init_port_id[0]; -/// iSCSI SCSI Data peripheral type: Sequential access device. -#define ISCSI_SCSI_DATA_PERIPHERAL_TYPE_SEQ 0x01 + /// Reserved for future usage (always MUST be 0). + uint16_t reserved3; -/// iSCSI SCSI Data peripheral type: Printer device. -#define ISCSI_SCSI_DATA_PERIPHERAL_TYPE_PRINTER 0x02 + /// SCSI Target Port Designation Descriptor length in bytes. + uint16_t target_desc_len; -/// iSCSI SCSI Data peripheral type: Processor device. -#define ISCSI_SCSI_DATA_PERIPHERAL_TYPE_PROCESSOR 0x03 + /// SCSI Target Port Designation Descriptor. + iscsi_scsi_vpd_scsi_target_port_design_dec_inquiry_data_packet target_desc[0]; +} iscsi_scsi_vpd_scsi_port_design_dec_inquiry_data_packet; -/// iSCSI SCSI Data peripheral type: Write once device. -#define ISCSI_SCSI_DATA_PERIPHERAL_TYPE_WORM 0x04 -/// iSCSI SCSI Data peripheral type: Read only direct access (e.g. CD-ROM) device. -#define ISCSI_SCSI_DATA_PERIPHERAL_TYPE_RO_DIRECT 0x05 +/** + * @brief iSCSI SCSI command INQUIRY Vital Product Data (VPD) SCSI Port Designation Descriptor entry fill. + * + * This structure is used by iterating through + * all iSCSI device ports in order to fill in + * the INQUIRY Vital Product Data (VPD) SCSI + * Port Designation Descriptor structure. + */ +typedef struct iscsi_scsi_emu_primary_inquiry_ports_fill { + /// Pointer to current Vital Product Data (VPD) SCSI Port Designation Descriptor entry packet data. + iscsi_scsi_vpd_scsi_port_design_dec_inquiry_data_packet *port_entry; -/// iSCSI SCSI Data peripheral type: Scanner device. -#define ISCSI_SCSI_DATA_PERIPHERAL_TYPE_SCANNER 0x06 + /// Total length of Vital Product Data (VPD) SCSI Port Designation Descriptor entry packet data in bytes. + uint alloc_len; -/// iSCSI SCSI Data peripheral type: Optical memory device. -#define ISCSI_SCSI_DATA_PERIPHERAL_TYPE_OPTICAL 0x07 + /// Total remaining allocation length for packet data in bytes. + uint len; +} iscsi_scsi_emu_primary_inquiry_ports_fill; -/// iSCSI SCSI Data peripheral type: Medium changer device. -#define ISCSI_SCSI_DATA_PERIPHERAL_TYPE_CHANGER 0x08 -/// iSCSI SCSI Data peripheral type: Communications device. -#define ISCSI_SCSI_DATA_PERIPHERAL_TYPE_COMM 0x09 +/// iSCSI SCSI Vital Product Data (VPD) Page Block Limits Inquiry data UNMAP Granularity Alignment: First bit of the thirty one bits. +#define ISCSI_SCSI_VPD_PAGE_BLOCK_LIMITS_INQUIRY_DATA_UNMAP_GRANULARITY_ALIGN_FIRST_BIT 0L -/// iSCSI SCSI Data peripheral type: Unknown or no device. -#define ISCSI_SCSI_DATA_PERIPHERAL_TYPE_UNKNOWN 0x1F +/// iSCSI SCSI Vital Product Data (VPD) Page Block Limits Inquiry data UNMAP Granularity Alignment: Last bit of the thirty one bits. +#define ISCSI_SCSI_VPD_PAGE_BLOCK_LIMITS_INQUIRY_DATA_UNMAP_GRANULARITY_ALIGN_LAST_BIT ((ISCSI_SCSI_VPD_PAGE_BLOCK_LIMITS_INQUIRY_DATA_UNMAP_GRANULARITY_ALIGN_FIRST_BIT) + 31L - 1L) -/// iSCSI SCSI Data peripheral type: First bit of the five bits. -#define ISCSI_SCSI_DATA_PERIPHERAL_TYPE_FIRST_BIT 0 +/// iSCSI SCSI Vital Product Data (VPD) Page Block Limits Inquiry data UNMAP Granularity Alignment: Bit mask. +#define ISCSI_SCSI_VPD_PAGE_BLOCK_LIMITS_INQUIRY_DATA_UNMAP_GRANULARITY_ALIGN_MASK (ISCSI_BITS_GET_MASK(ISCSI_SCSI_VPD_PAGE_BLOCK_LIMITS_INQUIRY_DATA_UNMAP_GRANULARITY_ALIGN_FIRST_BIT, ISCSI_SCSI_VPD_PAGE_BLOCK_LIMITS_INQUIRY_DATA_UNMAP_GRANULARITY_ALIGN_LAST_BIT)) -/// iSCSI SCSI Data peripheral type: Last bit of the five bits. -#define ISCSI_SCSI_DATA_PERIPHERAL_TYPE_LAST_BIT ((ISCSI_SCSI_DATA_PERIPHERAL_TYPE_FIRST_BIT) + 5 - 1) +/// iSCSI SCSI Vital Product Data (VPD) Page Block Limits Inquiry data UNMAP Granularity Alignment: Extracts the UNMAP granularity alignment bits. +#define ISCSI_SCSI_VPD_PAGE_BLOCK_LIMITS_INQUIRY_DATA_GET_UNMAP_GRANULARITY_ALIGN(x) (ISCSI_BITS_GET((x), ISCSI_SCSI_VPD_PAGE_BLOCK_LIMITS_INQUIRY_DATA_UNMAP_GRANULARITY_ALIGN_FIRST_BIT, ISCSI_SCSI_VPD_PAGE_BLOCK_LIMITS_INQUIRY_DATA_UNMAP_GRANULARITY_ALIGN_LAST_BIT)) -/// iSCSI SCSI Data peripheral type: Bit mask. -#define ISCSI_SCSI_DATA_PERIPHERAL_TYPE_MASK (ISCSI_BITS_GET_MASK(ISCSI_SCSI_DATA_PERIPHERAL_TYPE_FIRST_BIT, ISCSI_SCSI_DATA_PERIPHERAL_TYPE_LAST_BIT)) +/// iSCSI SCSI Vital Product Data (VPD) Page Block Limits Inquiry data UNMAP Granularity Alignment: Stores into the UNMAP granularity alignment bits. +#define ISCSI_SCSI_VPD_PAGE_BLOCK_LIMITS_INQUIRY_DATA_PUT_UNMAP_GRANULARITY_ALIGN(x) (ISCSI_BITS_PUT((x), ISCSI_SCSI_VPD_PAGE_BLOCK_LIMITS_INQUIRY_DATA_UNMAP_GRANULARITY_ALIGN_FIRST_BIT, ISCSI_SCSI_VPD_PAGE_BLOCK_LIMITS_INQUIRY_DATA_UNMAP_GRANULARITY_ALIGN_LAST_BIT)) -/// iSCSI SCSI Data peripheral type: Extracts the peripheral device type bits. -#define ISCSI_SCSI_DATA_GET_PERIPHERAL_TYPE(x) (ISCSI_BITS_GET((x), ISCSI_SCSI_DATA_PERIPHERAL_TYPE_FIRST_BIT, ISCSI_SCSI_DATA_PERIPHERAL_TYPE_LAST_BIT)) +/// iSCSI SCSI Vital Product Data (VPD) Page Block Limits Inquiry data UNMAP Granularity Alignment: UNMAP Granularity Alignment Valid (UGVALID). +#define ISCSI_SCSI_VPD_PAGE_BLOCK_LIMITS_INQUIRY_DATA_UNMAP_GRANULARITY_ALIGN_UGAVALID (1L << 31L) -/// iSCSI SCSI Data peripheral type: Stores into the peripheral device type bits. -#define ISCSI_SCSI_DATA_PUT_PERIPHERAL_TYPE(x) (ISCSI_BITS_PUT((x), ISCSI_SCSI_DATA_PERIPHERAL_TYPE_FIRST_BIT, ISCSI_SCSI_DATA_PERIPHERAL_TYPE_LAST_BIT)) -/// iSCSI SCSI Data peripheral identifier: The specified peripheral device type is currently connected to this logical unit, or connection state could not be determined. -#define ISCSI_SCSI_DATA_PERIPHERAL_ID_POSSIBLE 0x0 +/** + * @brief iSCSI SCSI Vital Product Data (VPD) Page Block Limits Inquiry data packet. + * + * This structure is used by the SCSI INQUIRY command + * in order to fill in the result if the EVPD bit is + * set. + */ +typedef struct __attribute__((packed)) iscsi_scsi_vpd_page_block_limits_inquiry_data_packet { + /// Flags. + int8_t flags; -/// iSCSI SCSI Data peripheral identifier: The target is capable of supporting the specified peripheral device type on this logical unit, but not connected. -#define ISCSI_SCSI_DATA_PERIPHERAL_ID_SUPPORTED 0x1 + /// Maximum COMPARE AND WRITE length in logical blocks. + uint8_t max_cmp_write_len; -/// iSCSI SCSI Data peripheral identifier: The target is not capable of supporting a physical device on this logical unit. -#define ISCSI_SCSI_DATA_PERIPHERAL_ID_NEVER 0x3 + /// Optimal transfer length granularity in logical blocks. + uint16_t optimal_granularity_xfer_len; -/// iSCSI SCSI Data peripheral identifier: Vendor specific. -#define ISCSI_SCSI_DATA_PERIPHERAL_ID_VENDOR_UNIQ 0x4 + /// Maximum transfer length in logical blocks. + uint32_t max_xfer_len; -/// iSCSI SCSI Data peripheral identifier: First bit of the three bits. -#define ISCSI_SCSI_DATA_PERIPHERAL_ID_FIRST_BIT 5 + /// Optimal transfer length in logical blocks. + uint32_t optimal_xfer_len; -/// iSCSI SCSI Data peripheral identifier: Last bit of the three bits. -#define ISCSI_SCSI_DATA_PERIPHERAL_ID_LAST_BIT ((ISCSI_SCSI_DATA_PERIPHERAL_ID_FIRST_BIT) + 3 - 1) + /// Maximum prefetch length in logical blocks. + uint32_t max_prefetch_len; -/// iSCSI SCSI Data peripheral identifier: Bit mask. -#define ISCSI_SCSI_DATA_PERIPHERAL_ID_MASK (ISCSI_BITS_GET_MASK(ISCSI_SCSI_DATA_PERIPHERAL_ID_FIRST_BIT, ISCSI_SCSI_DATA_PERIPHERAL_ID_LAST_BIT)) + /// Maximum UNMAP LBA count in LBAs. + uint32_t max_unmap_lba_cnt; -/// iSCSI SCSI Data peripheral identifier: Extracts the peripheral device identifier bits. -#define ISCSI_SCSI_DATA_GET_PERIPHERAL_ID(x) (ISCSI_BITS_GET((x), ISCSI_SCSI_DATA_PERIPHERAL_ID_FIRST_BIT, ISCSI_SCSI_DATA_PERIPHERAL_ID_LAST_BIT)) + /// Maximum UNMAP block descriptor count in block descriptors. + uint32_t max_unmap_block_desc_cnt; -/// iSCSI SCSI Data peripheral identifier: Stores into the peripheral device identifier bits. -#define ISCSI_SCSI_DATA_PUT_PERIPHERAL_ID(x) (ISCSI_BITS_PUT((x), ISCSI_SCSI_DATA_PERIPHERAL_ID_FIRST_BIT, ISCSI_SCSI_DATA_PERIPHERAL_ID_LAST_BIT)) + /// Optimal UNMAP granularity in logical blocks. + uint32_t optimal_unmap_granularity; + /// UNMAP granularity alignment (first LBA) and UGAVALID bit. + uint32_t unmap_granularity_align_ugavalid; -/// iSCSI SCSI Data peripheral type modifier: First bit of the seven bits. -#define ISCSI_SCSI_DATA_PERIPHERAL_TYPE_MOD_FIRST_BIT 0 + /// Maximum WRITE SAME length in logical blocks. + uint64_t max_write_same_len; -/// iSCSI SCSI Data peripheral type modifier: Last bit of the seven bits. -#define ISCSI_SCSI_DATA_PERIPHERAL_TYPE_MOD_LAST_BIT ((ISCSI_SCSI_DATA_PERIPHERAL_TYPE_MOD_FIRST_BIT) + 7 - 1) + /// Reserved for future usage (always MUST be 0). + uint64_t reserved[2]; -/// iSCSI SCSI Data peripheral type modifier: Bit mask. -#define ISCSI_SCSI_DATA_PERIPHERAL_TYPE_MOD_MASK (ISCSI_BITS_GET_MASK(ISCSI_SCSI_DATA_PERIPHERAL_TYPE_MOD_FIRST_BIT, ISCSI_SCSI_DATA_PERIPHERAL_TYPE_MOD_LAST_BIT)) + /// Reserved for future usage (always MUST be 0). + uint32_t reserved2; +} iscsi_scsi_vpd_page_block_limits_inquiry_data_packet; -/// iSCSI SCSI Data peripheral identifier: Extracts the peripheral type modifier bits. -#define ISCSI_SCSI_DATA_GET_PERIPHERAL_TYPE_MOD(x) (ISCSI_BITS_GET((x), ISCSI_SCSI_DATA_PERIPHERAL_TYPE_MOD_FIRST_BIT, ISCSI_SCSI_DATA_PERIPHERAL_TYPE_MOD_LAST_BIT)) +/// iSCSI SCSI Vital Product Data (VPD) Page Block Device Characteristics Inquiry data medium rotation rate: Medium rotation rate is not reported. +#define ISCSI_SCSI_VPD_PAGE_BLOCK_DEV_CHARS_INQUIRY_DATA_MEDIUM_ROTATION_RATE_NOT_REPORTED 0x0000 -/// iSCSI SCSI Data peripheral identifier: Stores into the peripheral type modifier bits. -#define ISCSI_SCSI_DATA_PUT_PERIPHERAL_TYPE_MOD(x) (ISCSI_BITS_PUT((x), ISCSI_SCSI_DATA_PERIPHERAL_TYPE_MOD_FIRST_BIT, ISCSI_SCSI_DATA_PERIPHERAL_TYPE_MOD_LAST_BIT)) +/// iSCSI SCSI Vital Product Data (VPD) Page Block Device Characteristics Inquiry data medium rotation rate: Non-rotating medium (e.g., solid state). +#define ISCSI_SCSI_VPD_PAGE_BLOCK_DEV_CHARS_INQUIRY_DATA_MEDIUM_ROTATION_RATE_NONE 0x0001 -/// iSCSI SCSI Data peripheral type modifier: Removable media. -#define ISCSI_SCSI_DATA_PERIPHERAL_TYPE_MOD_FLAGS_REMOVABLE_MEDIA (1 << 7) +/// iSCSI SCSI Vital Product Data (VPD) Page Block Device Characteristics Inquiry data product type: Not indicated. +#define ISCSI_SCSI_VPD_PAGE_BLOCK_DEV_CHARS_INQUIRY_DATA_PRODUCT_TYPE_NOT_INDICATED 0x00 -/// iSCSI SCSI Data ANSI version: First bit of the three bits. -#define ISCSI_SCSI_DATA_VERSION_ANSI_FIRST_BIT 0 +/// iSCSI SCSI Vital Product Data (VPD) Page Block Device Characteristics Inquiry data product type: Not specified first value. +#define ISCSI_SCSI_VPD_PAGE_BLOCK_DEV_CHARS_INQUIRY_DATA_PRODUCT_TYPE_NOT_SPECIFIED_FIRST 0xF0 -/// iSCSI SCSI Data ANSI version: Last bit of the three bits. -#define ISCSI_SCSI_DATA_VERSION_ANSI_LAST_BIT ((ISCSI_SCSI_DATA_VERSION_ANSI_FIRST_BIT) + 3 - 1) +/// iSCSI SCSI Vital Product Data (VPD) Page Block Device Characteristics Inquiry data product type: Not specified last value. +#define ISCSI_SCSI_VPD_PAGE_BLOCK_DEV_CHARS_INQUIRY_DATA_PRODUCT_TYPE_NOT_SPECIFIED_LAST 0xFF -/// iSCSI SCSI Data ANSI version: Bit mask. -#define ISCSI_SCSI_DATA_VERSION_ANSI_MASK (ISCSI_BITS_GET_MASK(ISCSI_SCSI_DATA_VERSION_ANSI_FIRST_BIT, ISCSI_SCSI_DATA_VERSION_ANSI_LAST_BIT)) -/// iSCSI SCSI Data ANSI version: Extracts the ANSI version bits. -#define ISCSI_SCSI_DATA_GET_VERSION_ANSI(x) (ISCSI_BITS_GET((x), ISCSI_SCSI_DATA_VERSION_ANSI_FIRST_BIT, ISCSI_SCSI_DATA_VERSION_ANSI_LAST_BIT)) +/// iSCSI SCSI Vital Product Data (VPD) Page Block Device Characteristics Inquiry data flags nominal form factor: Nominal form factor is not reported. +#define ISCSI_SCSI_VPD_PAGE_BLOCK_DEV_CHARS_INQUIRY_DATA_FLAGS_NOMINAL_FORM_FACTOR_NOT_REPORTED 0x0 -/// iSCSI SCSI Data ANSI version: Stores into the ANSI version bits. -#define ISCSI_SCSI_DATA_PUT_VERSION_ANSI(x) (ISCSI_BITS_PUT((x), ISCSI_SCSI_DATA_VERSION_ANSI_FIRST_BIT, ISCSI_SCSI_DATA_VERSION_ANSI_LAST_BIT)) +/// iSCSI SCSI Vital Product Data (VPD) Page Block Device Characteristics Inquiry data flags nominal form factor: 5.25 inch. +#define ISCSI_SCSI_VPD_PAGE_BLOCK_DEV_CHARS_INQUIRY_DATA_FLAGS_NOMINAL_FORM_FACTOR_525_INCH 0x1 -/// iSCSI SCSI Data ECMA version: First bit of the three bits. -#define ISCSI_SCSI_DATA_VERSION_ECMA_FIRST_BIT 3 +/// iSCSI SCSI Vital Product Data (VPD) Page Block Device Characteristics Inquiry data flags nominal form factor: 3.5 inch. +#define ISCSI_SCSI_VPD_PAGE_BLOCK_DEV_CHARS_INQUIRY_DATA_FLAGS_NOMINAL_FORM_FACTOR_35_INCH 0x2 -/// iSCSI SCSI Data ECMA version: Last bit of the three bits. -#define ISCSI_SCSI_DATA_VERSION_ECMA_LAST_BIT ((ISCSI_SCSI_DATA_VERSION_ECMA_FIRST_BIT) + 3 - 1) +/// iSCSI SCSI Vital Product Data (VPD) Page Block Device Characteristics Inquiry data flags nominal form factor: 2.5 inch. +#define ISCSI_SCSI_VPD_PAGE_BLOCK_DEV_CHARS_INQUIRY_DATA_FLAGS_NOMINAL_FORM_FACTOR_25_INCH 0x3 -/// iSCSI SCSI Data ECMA version: Bit mask. -#define ISCSI_SCSI_DATA_VERSION_ECMA_MASK (ISCSI_BITS_GET_MASK(ISCSI_SCSI_DATA_VERSION_ECMA_FIRST_BIT, ISCSI_SCSI_DATA_VERSION_ECMA_LAST_BIT)) +/// iSCSI SCSI Vital Product Data (VPD) Page Block Device Characteristics Inquiry data flags nominal form factor: 1.8 inch. +#define ISCSI_SCSI_VPD_PAGE_BLOCK_DEV_CHARS_INQUIRY_DATA_FLAGS_NOMINAL_FORM_FACTOR_18_INCH 0x4 -/// iSCSI SCSI Data ECMA version: Extracts the ECMA version bits. -#define ISCSI_SCSI_DATA_GET_VERSION_ECMA(x) (ISCSI_BITS_GET((x), ISCSI_SCSI_DATA_VERSION_ECMA_FIRST_BIT, ISCSI_SCSI_DATA_VERSION_ECMA_LAST_BIT)) +/// iSCSI SCSI Vital Product Data (VPD) Page Block Device Characteristics Inquiry data flags nominal form factor: Less than 1.8 inch. +#define ISCSI_SCSI_VPD_PAGE_BLOCK_DEV_CHARS_INQUIRY_DATA_FLAGS_NOMINAL_FORM_FACTOR_LT_18_INCH 0x5 -/// iSCSI SCSI Data ECMA version: Stores into the ECMA version bits. -#define ISCSI_SCSI_DATA_PUT_VERSION_ECMA(x) (ISCSI_BITS_PUT((x), ISCSI_SCSI_DATA_VERSION_ECMA_FIRST_BIT, ISCSI_SCSI_DATA_VERSION_ECMA_LAST_BIT)) +/// iSCSI SCSI Vital Product Data (VPD) Page Block Device Characteristics Inquiry data flags nominal form factor: First bit of the four bits. +#define ISCSI_SCSI_VPD_PAGE_BLOCK_DEV_CHARS_INQUIRY_DATA_FLAGS_NOMINAL_FORM_FACTOR_FIRST_BIT 0 -/// iSCSI SCSI Data ISO version: First bit of the two bits. -#define ISCSI_SCSI_DATA_VERSION_ISO_FIRST_BIT 6 +/// iSCSI SCSI Vital Product Data (VPD) Page Block Device Characteristics Inquiry data flags nominal form factor: Last bit of the four bits. +#define ISCSI_SCSI_VPD_PAGE_BLOCK_DEV_CHARS_INQUIRY_DATA_FLAGS_NOMINAL_FORM_FACTOR_LAST_BIT ((ISCSI_SCSI_VPD_PAGE_BLOCK_DEV_CHARS_INQUIRY_DATA_FLAGS_NOMINAL_FORM_FACTOR_FIRST_BIT) + 4 - 1) -/// iSCSI SCSI Data ISO version: Last bit of the two bits. -#define ISCSI_SCSI_DATA_VERSION_ISO_LAST_BIT ((ISCSI_SCSI_DATA_VERSION_ISO_FIRST_BIT) + 2 - 1) +/// iSCSI SCSI Vital Product Data (VPD) Page Block Device Characteristics Inquiry data flags nominal form factor: Bit mask. +#define ISCSI_SCSI_VPD_PAGE_BLOCK_DEV_CHARS_INQUIRY_DATA_FLAGS_NOMINAL_FORM_FACTOR_MASK (ISCSI_BITS_GET_MASK(ISCSI_SCSI_VPD_PAGE_BLOCK_DEV_CHARS_INQUIRY_DATA_FLAGS_NOMINAL_FORM_FACTOR_FIRST_BIT, ISCSI_SCSI_VPD_PAGE_BLOCK_DEV_CHARS_INQUIRY_DATA_FLAGS_NOMINAL_FORM_FACTOR_LAST_BIT)) -/// iSCSI SCSI Data ISO version: Bit mask. -#define ISCSI_SCSI_DATA_VERSION_ISO_MASK (ISCSI_BITS_GET_MASK(ISCSI_SCSI_DATA_VERSION_ISO_FIRST_BIT, ISCSI_SCSI_DATA_VERSION_ISO_LAST_BIT)) +/// iSCSI SCSI Vital Product Data (VPD) Page Block Device Characteristics Inquiry data flags nominal form factor: Extracts the nominal form factor bits. +#define ISCSI_SCSI_VPD_PAGE_BLOCK_DEV_CHARS_INQUIRY_DATA_FLAGS_GET_NOMINAL_FORM_FACTOR(x) (ISCSI_BITS_GET((x), ISCSI_SCSI_VPD_PAGE_BLOCK_DEV_CHARS_INQUIRY_DATA_FLAGS_NOMINAL_FORM_FACTOR_FIRST_BIT, ISCSI_SCSI_VPD_PAGE_BLOCK_DEV_CHARS_INQUIRY_DATA_FLAGS_NOMINAL_FORM_FACTOR_LAST_BIT)) -/// iSCSI SCSI Data ISO version: Extracts the ISO version bits. -#define ISCSI_SCSI_DATA_GET_VERSION_ISO(x) (ISCSI_BITS_GET((x), ISCSI_SCSI_DATA_VERSION_ISO_FIRST_BIT, ISCSI_SCSI_DATA_VERSION_ISO_LAST_BIT)) +/// iSCSI SCSI Vital Product Data (VPD) Page Block Device Characteristics Inquiry data flags nominal form factor: Stores into the nominal form factor bits. +#define ISCSI_SCSI_VPD_PAGE_BLOCK_DEV_CHARS_INQUIRY_DATA_FLAGS_PUT_NOMINAL_FORM_FACTOR(x) (ISCSI_BITS_PUT((x), ISCSI_SCSI_VPD_PAGE_BLOCK_DEV_CHARS_INQUIRY_DATA_FLAGS_NOMINAL_FORM_FACTOR_FIRST_BIT, ISCSI_SCSI_VPD_PAGE_BLOCK_DEV_CHARS_INQUIRY_DATA_FLAGS_NOMINAL_FORM_FACTOR_LAST_BIT)) -/// iSCSI SCSI Data ISO version: Stores into the ISO version bits. -#define ISCSI_SCSI_DATA_PUT_VERSION_ISO(x) (ISCSI_BITS_PUT((x), ISCSI_SCSI_DATA_VERSION_ISO_FIRST_BIT, ISCSI_SCSI_DATA_VERSION_ISO_LAST_BIT)) +/// iSCSI SCSI Vital Product Data (VPD) Page Block Device Characteristics Inquiry data flags Write After Cryptographic Erase REQuired (WACEREQ): First bit of the two bits. +#define ISCSI_SCSI_VPD_PAGE_BLOCK_DEV_CHARS_INQUIRY_DATA_FLAGS_WACEREQ_FIRST_BIT 4 +/// iSCSI SCSI Vital Product Data (VPD) Page Block Device Characteristics Inquiry data flags Write After Cryptographic Erase REQuired (WACEREQ): Last bit of the two bits. +#define ISCSI_SCSI_VPD_PAGE_BLOCK_DEV_CHARS_INQUIRY_DATA_FLAGS_WACEREQ_LAST_BIT ((ISCSI_SCSI_VPD_PAGE_BLOCK_DEV_CHARS_INQUIRY_DATA_FLAGS_WACEREQ_FIRST_BIT) + 6 - 1) -/// iSCSI SCSI Data response data format flags: This structure complies with SCSI-1 specifications. -#define ISCSI_SCSI_DATA_RESPONSE_DATA_FMT_FLAGS_LEVEL_0 0x00 +/// iSCSI SCSI Vital Product Data (VPD) Page Block Device Characteristics Inquiry data flags Write After Cryptographic Erase REQuired (WACEREQ): Bit mask. +#define ISCSI_SCSI_VPD_PAGE_BLOCK_DEV_CHARS_INQUIRY_DATA_FLAGS_WACEREQ_MASK (ISCSI_BITS_GET_MASK(ISCSI_SCSI_VPD_PAGE_BLOCK_DEV_CHARS_INQUIRY_DATA_FLAGS_WACEREQ_FIRST_BIT, ISCSI_SCSI_VPD_PAGE_BLOCK_DEV_CHARS_INQUIRY_DATA_FLAGS_WACEREQ_LAST_BIT)) -/// iSCSI SCSI Data response data format flags: This structure complies with CCS pseudo specifications. -#define ISCSI_SCSI_DATA_RESPONSE_DATA_FMT_FLAGS_CCS 0x01 +/// iSCSI SCSI Vital Product Data (VPD) Page Block Device Characteristics Inquiry data flags Write After Cryptographic Erase REQuired (WACEREQ): Extracts the Write After Block Erase REQuired (WACEREQ) bits. +#define ISCSI_SCSI_VPD_PAGE_BLOCK_DEV_CHARS_INQUIRY_DATA_FLAGS_GET_WACEREQ(x) (ISCSI_BITS_GET((x), ISCSI_SCSI_VPD_PAGE_BLOCK_DEV_CHARS_INQUIRY_DATA_FLAGS_WACEREQ_FIRST_BIT, ISCSI_SCSI_VPD_PAGE_BLOCK_DEV_CHARS_INQUIRY_DATA_FLAGS_WACEREQ_LAST_BIT)) -/// iSCSI SCSI Data response data format flags: This structure complies with SCSI-2/3 specifications. -#define ISCSI_SCSI_DATA_RESPONSE_DATA_FMT_FLAGS_SCSI_2 0x02 +/// iSCSI SCSI Vital Product Data (VPD) Page Block Device Characteristics Inquiry data flags Write After Cryptographic Erase REQuired (WACEREQ): Stores into the Write After Block Erase REQuired (WACEREQ) bits. +#define ISCSI_SCSI_VPD_PAGE_BLOCK_DEV_CHARS_INQUIRY_DATA_FLAGS_PUT_WACEREQ(x) (ISCSI_BITS_PUT((x), ISCSI_SCSI_VPD_PAGE_BLOCK_DEV_CHARS_INQUIRY_DATA_FLAGS_WACEREQ_FIRST_BIT, ISCSI_SCSI_VPD_PAGE_BLOCK_DEV_CHARS_INQUIRY_DATA_FLAGS_WACEREQ_LAST_BIT)) -/// iSCSI SCSI Data response data format flags: First bit of the four bits. -#define ISCSI_SCSI_DATA_RESPONSE_DATA_FMT_FLAGS_FIRST_BIT 0 +/// iSCSI SCSI Vital Product Data (VPD) Page Block Device Characteristics Inquiry data flags Write After Block Erase REQuired (WABEREQ): First bit of the two bits. +#define ISCSI_SCSI_VPD_PAGE_BLOCK_DEV_CHARS_INQUIRY_DATA_FLAGS_WABEREQ_FIRST_BIT 6 -/// iSCSI SCSI Data response data format flags: Last bit of the four bits. -#define ISCSI_SCSI_DATA_RESPONSE_DATA_FMT_FLAGS_LAST_BIT ((ISCSI_SCSI_DATA_RESPONSE_DATA_FMT_FLAGS_FIRST_BIT) + 4 - 1) +/// iSCSI SCSI Vital Product Data (VPD) Page Block Device Characteristics Inquiry data flags Write After Block Erase REQuired (WABEREQ): Last bit of the two bits. +#define ISCSI_SCSI_VPD_PAGE_BLOCK_DEV_CHARS_INQUIRY_DATA_FLAGS_WABEREQ_LAST_BIT ((ISCSI_SCSI_VPD_PAGE_BLOCK_DEV_CHARS_INQUIRY_DATA_FLAGS_WABEREQ_FIRST_BIT) + 8 - 1) -/// iSCSI SCSI Data response data format flags: Bit mask. -#define ISCSI_SCSI_DATA_RESPONSE_DATA_FMT_FLAGS_MASK (ISCSI_BITS_GET_MASK(ISCSI_SCSI_DATA_RESPONSE_DATA_FMT_FLAGS_FIRST_BIT, ISCSI_SCSI_DATA_RESPONSE_DATA_FMT_FLAGS_LAST_BIT)) +/// iSCSI SCSI Vital Product Data (VPD) Page Block Device Characteristics Inquiry data flags Write After Block Erase REQuired (WABEREQ): Bit mask. +#define ISCSI_SCSI_VPD_PAGE_BLOCK_DEV_CHARS_INQUIRY_DATA_FLAGS_WABEREQ_MASK (ISCSI_BITS_GET_MASK(ISCSI_SCSI_VPD_PAGE_BLOCK_DEV_CHARS_INQUIRY_DATA_FLAGS_WABEREQ_FIRST_BIT, ISCSI_SCSI_VPD_PAGE_BLOCK_DEV_CHARS_INQUIRY_DATA_FLAGS_WABEREQ_LAST_BIT)) -/// iSCSI SCSI Data response data format flags: Extracts the response data format flags bits. -#define ISCSI_SCSI_DATA_GET_RESPONSE_DATA_FMT_FLAGS(x) (ISCSI_BITS_GET((x), ISCSI_SCSI_DATA_RESPONSE_DATA_FMT_FLAGS_FIRST_BIT, ISCSI_SCSI_DATA_RESPONSE_DATA_FMT_FLAGS_LAST_BIT)) +/// iSCSI SCSI Vital Product Data (VPD) Page Block Device Characteristics Inquiry data flags Write After Block Erase REQuired (WABEREQ): Extracts the Write After Block Erase REQuired (WABEREQ) bits. +#define ISCSI_SCSI_VPD_PAGE_BLOCK_DEV_CHARS_INQUIRY_DATA_FLAGS_GET_WABEREQ(x) (ISCSI_BITS_GET((x), ISCSI_SCSI_VPD_PAGE_BLOCK_DEV_CHARS_INQUIRY_DATA_FLAGS_WABEREQ_FIRST_BIT, ISCSI_SCSI_VPD_PAGE_BLOCK_DEV_CHARS_INQUIRY_DATA_FLAGS_WABEREQ_LAST_BIT)) -/// iSCSI SCSI Data response data format flags: Stores into the response data format flags bits. -#define ISCSI_SCSI_DATA_PUT_RESPONSE_DATA_FMT_FLAGS(x) (ISCSI_BITS_PUT((x), ISCSI_SCSI_DATA_RESPONSE_DATA_FMT_FLAGS_FIRST_BIT, ISCSI_SCSI_DATA_RESPONSE_DATA_FMT_FLAGS_LAST_BIT)) +/// iSCSI SCSI Vital Product Data (VPD) Page Block Device Characteristics Inquiry data flags Write After Block Erase REQuired (WABEREQ): Stores into the Write After Block Erase REQuired (WABEREQ) bits. +#define ISCSI_SCSI_VPD_PAGE_BLOCK_DEV_CHARS_INQUIRY_DATA_FLAGS_PUT_WABEREQ(x) (ISCSI_BITS_PUT((x), ISCSI_SCSI_VPD_PAGE_BLOCK_DEV_CHARS_INQUIRY_DATA_FLAGS_WABEREQ_FIRST_BIT, ISCSI_SCSI_VPD_PAGE_BLOCK_DEV_CHARS_INQUIRY_DATA_FLAGS_WABEREQ_LAST_BIT)) -/// iSCSI SCSI Data response data format flags: TERMINATE I/O PROCESS message device support. -#define ISCSI_SCSI_DATA_RESPONSE_DATA_FMT_FLAGS_TERMINATE_IO_PROC_MSG (1 << 6) -/// iSCSI SCSI Data response data format flags: Asynchronous Event Notification device support. -#define ISCSI_SCSI_DATA_RESPONSE_DATA_FMT_FLAGS_ASYNC_EVENT_NOTIFY (1 << 7) +/// iSCSI SCSI Vital Product Data (VPD) Page Block Device Characteristics Inquiry data support flags: Verify Byte Check Unmapped LBA Supported (VBULS). +#define ISCSI_SCSI_VPD_PAGE_BLOCK_DEV_CHARS_INQUIRY_DATA_SUPPORT_FLAGS_VBULS (1 << 0) -typedef struct __attribute__((packed)) iscsi_scsi_data_packet { - /// Peripheral device type and qualifier. - uint8_t peripheral_type_id; +/** + * @brief iSCSI SCSI Vital Product Data (VPD) Page Block Device Characteristics Inquiry data packet. + * + * This structure is used by the SCSI INQUIRY command + * in order to fill in the result if the EVPD bit is + * set. + */ +typedef struct __attribute__((packed)) iscsi_scsi_vpd_page_block_dev_chars_inquiry_data_packet { + /// Medium rotation rate. + uint16_t medium_rotation_rate; - /// Peripheral device type modifier and removable media flag. - int8_t peripheral_type_mod_flags; + /// Product type. + uint8_t product_type; - /// ANSI-Approved, ECMA and ISO version. - uint8_t version; + /// Flags. + int8_t flags; - /// Response data format, AENC and TrmIOP flags. - int8_t response_data_fmt_flags; + /// Support flags. + uint8_t support_flags; - /// Additional length in bytes. - uint8_t add_len; -} iscsi_scsi_data_packet; + /// Reserved for future usage (always MUST be 0). + uint64_t reserved[6]; + /// Reserved for future usage (always MUST be 0). + uint32_t reserved2; -/// iSCSI SCSI Standard Inquiry Data flags: Device responds with soft reset instead of hard reset to reset condition. -#define ISCSI_SCSI_STD_INQUIRY_DATA_FLAGS_SOFT_RESET (1 << 0) + /// Reserved for future usage (always MUST be 0). + uint16_t reserved3; -/// iSCSI SCSI Standard Inquiry Data flags: Device supports tagged command queueing. -#define ISCSI_SCSI_STD_INQUIRY_DATA_FLAGS_COMMAND_QUEUE (1 << 1) + /// Reserved for future usage (always MUST be 0). + uint8_t reserved4; +} iscsi_scsi_vpd_page_block_dev_chars_inquiry_data_packet; -/// iSCSI SCSI Standard Inquiry Data flags: Reserved for future usage. -#define ISCSI_SCSI_STD_INQUIRY_DATA_FLAGS_RESERVED (1 << 2) -/// iSCSI SCSI Standard Inquiry Data flags: Device supports linked commands for this logical unit. -#define ISCSI_SCSI_STD_INQUIRY_DATA_FLAGS_LINKED_CMDS (1 << 3) +/// iSCSI SCSI Vital Product Data (VPD) Page Thin Provision Inquiry data flags: Descriptor Present (DP). +#define ISCSI_SCSI_VPD_PAGE_THIN_PROVISION_INQUIRY_DATA_FLAGS_DP (1 << 0) -/// iSCSI SCSI Standard Inquiry Data flags: Device supports synchronous data transfers. -#define ISCSI_SCSI_STD_INQUIRY_DATA_FLAGS_SYNC (1 << 4) +/// iSCSI SCSI Vital Product Data (VPD) Page Thin Provision Inquiry data flags: Anchor Supported (ANC_SUP). +#define ISCSI_SCSI_VPD_PAGE_THIN_PROVISION_INQUIRY_DATA_FLAGS_ANC_SUP (1 << 1) -/// iSCSI SCSI Standard Inquiry Data flags: Device supports 16-bit wide data transfers. -#define ISCSI_SCSI_STD_INQUIRY_DATA_FLAGS_WIDE_16_BIT (1 << 5) +/// iSCSI SCSI Vital Product Data (VPD) Page Thin Provision Inquiry data flags: Logical Block Provisioning Read Zeros (LBPRZ). +#define ISCSI_SCSI_VPD_PAGE_THIN_PROVISION_INQUIRY_DATA_FLAGS_LBPRZ (1 << 2) -/// iSCSI SCSI Standard Inquiry Data flags: Device supports 32-bit wide data transfers. -#define ISCSI_SCSI_STD_INQUIRY_DATA_FLAGS_WIDE_32_BIT (1 << 6) +/// iSCSI SCSI Vital Product Data (VPD) Page Thin Provision Inquiry data flags: Logical Block Provisioning WRITE SAME(10) (LBPWS10). +#define ISCSI_SCSI_VPD_PAGE_THIN_PROVISION_INQUIRY_DATA_FLAGS_LBPWS10 (1 << 5) -/// iSCSI SCSI Standard Inquiry Data flags: Device supports relative addressing mode of this logical unit. -#define ISCSI_SCSI_STD_INQUIRY_DATA_FLAGS_REL_ADDR (1 << 7) +/// iSCSI SCSI Vital Product Data (VPD) Page Thin Provision Inquiry data flags: Logical Block Provisioning WRITE SAME (LBPWS). +#define ISCSI_SCSI_VPD_PAGE_THIN_PROVISION_INQUIRY_DATA_FLAGS_LBPWS (1 << 6) +/// iSCSI SCSI Vital Product Data (VPD) Page Thin Provision Inquiry data flags: Logical Block Provisioning UNMAP (LBPU). +#define ISCSI_SCSI_VPD_PAGE_THIN_PROVISION_INQUIRY_DATA_FLAGS_LBPU (1 << 7) -typedef struct __attribute__((packed)) iscsi_scsi_std_inquiry_data_packet { - /// iSCSI SCSI data packet. - iscsi_scsi_data_packet scsi_data; - /// Peripheral device type and qualifier. - uint8_t peripheral_type_id; +/// iSCSI SCSI Vital Product Data (VPD) Page Thin Provision Inquiry data provision type: The device server does NOT report a provisioning type. +#define ISCSI_SCSI_VPD_PAGE_THIN_PROVISION_INQUIRY_DATA_PROVISION_TYPE_PROVISIONING_NOT_REPORTED 0x0 - /// Peripheral device type modifier and removable media flag. - int8_t peripheral_type_mod_flags; +/// iSCSI SCSI Vital Product Data (VPD) Page Thin Provision Inquiry data provision type: The logical unit is resource provisioned (see SBC3). +#define ISCSI_SCSI_VPD_PAGE_THIN_PROVISION_INQUIRY_DATA_PROVISION_TYPE_RESOURCE_PROVISIONING 0x1 - /// ANSI-Approved, ECMA and ISO version. - uint8_t version; +/// iSCSI SCSI Vital Product Data (VPD) Page Thin Provision Inquiry data provision type: The logical unit is thin provisioned (see SBC3). +#define ISCSI_SCSI_VPD_PAGE_THIN_PROVISION_INQUIRY_DATA_PROVISION_TYPE_THIN_PROVISIONING 0x2 - /// Response data format, AENC and TrmIOP flags. - int8_t response_data_fmt_flags; +/// iSCSI SCSI Vital Product Data (VPD) Page Thin Provision Inquiry data provision type: First bit of the three bits. +#define ISCSI_SCSI_VPD_PAGE_THIN_PROVISION_INQUIRY_DATA_PROVISION_TYPE_FIRST_BIT 0 - /// Additional length in bytes. - uint8_t add_len; +/// iSCSI SCSI Vital Product Data (VPD) Page Thin Provision Inquiry data provision type: Last bit of the three bits. +#define ISCSI_SCSI_VPD_PAGE_THIN_PROVISION_INQUIRY_DATA_PROVISION_TYPE_LAST_BIT ((ISCSI_SCSI_VPD_PAGE_THIN_PROVISION_INQUIRY_DATA_PROVISION_TYPE_FIRST_BIT) + 3 - 1) - /// Reserved for future usage (always MUST be 0 for now). - uint16_t reserved; +/// iSCSI SCSI Vital Product Data (VPD) Page Thin Provision Inquiry data provision type: Bit mask. +#define ISCSI_SCSI_VPD_PAGE_THIN_PROVISION_INQUIRY_DATA_PROVISION_TYPE_MASK (ISCSI_BITS_GET_MASK(ISCSI_SCSI_VPD_PAGE_THIN_PROVISION_INQUIRY_DATA_PROVISION_TYPE_FIRST_BIT, ISCSI_SCSI_VPD_PAGE_THIN_PROVISION_INQUIRY_DATA_PROVISION_TYPE_LAST_BIT)) + +/// iSCSI SCSI Vital Product Data (VPD) Page Thin Provision Inquiry data provision type: Extracts the provision type bits. +#define ISCSI_SCSI_VPD_PAGE_THIN_PROVISION_INQUIRY_DATA_GET_PROVISION_TYPE(x) (ISCSI_BITS_GET((x), ISCSI_SCSI_VPD_PAGE_THIN_PROVISION_INQUIRY_DATA_PROVISION_TYPE_FIRST_BIT, ISCSI_SCSI_VPD_PAGE_THIN_PROVISION_INQUIRY_DATA_PROVISION_TYPE_LAST_BIT)) + +/// iSCSI SCSI Vital Product Data (VPD) Page Thin Provision Inquiry data provision type: Stores into the provision type bits. +#define ISCSI_SCSI_VPD_PAGE_THIN_PROVISION_INQUIRY_DATA_PUT_PROVISION_TYPE(x) (ISCSI_BITS_PUT((x), ISCSI_SCSI_VPD_PAGE_THIN_PROVISION_INQUIRY_DATA_PROVISION_TYPE_FIRST_BIT, ISCSI_SCSI_VPD_PAGE_THIN_PROVISION_INQUIRY_DATA_PROVISION_TYPE_LAST_BIT)) + + +/** + * @brief iSCSI SCSI Vital Product Data (VPD) Page Thin Provision Inquiry data packet. + * + * This structure is used by the SCSI INQUIRY command + * in order to fill in the result if the EVPD bit is + * set. + */ +typedef struct __attribute__((packed)) iscsi_scsi_vpd_page_thin_provision_inquiry_data_packet { + /// Threshold exponent. + uint8_t threshold_exponent; /// Flags. int8_t flags; - /// Vendor identification. - uint8_t vendor_id[8]; + /// Provision type. + uint8_t provision_type; - /// Product identification. - uint8_t product_id[16]; + /// Reserved for future usage (always MUST be 0). + uint8_t reserved; + + /// Provision group descriptors. + uint8_t provision_group_desc[0]; +} iscsi_scsi_vpd_page_thin_provision_inquiry_data_packet; - /// Product revision level. - uint8_t product_rev_level[4]; -} iscsi_scsi_std_inquiry_data_packet; /** * @brief iSCSI SCSI Sense Event data packet. @@ -7989,8 +9160,24 @@ typedef struct iscsi_scsi_task { #define ISCSI_SCSI_EMU_BLOCK_SIZE (1UL << ISCSI_SCSI_EMU_BLOCK_SIZE_BITS) +/// iSCSI SCSI emulation maximum tansfer length in logical blocks. +#define ISCSI_SCSI_EMU_MAX_XFER_LEN (ISCSI_DEFAULT_MAX_RECV_DS_LEN * ISCSI_DEFAULT_MAX_DATA_OUT_PER_CONNECTION) + +/// iSCSI SCSI emulation maximum UNMAP LBA count in LBAs. +#define ISCSI_SCSI_EMU_MAX_UNMAP_LBA_COUNT (ISCSI_DEFAULT_MAX_RECV_DS_LEN * ISCSI_DEFAULT_MAX_DATA_IN_PER_CONNECTION) + +/// iSCSI SCSI emulation maximum UNMAP block descriptor count in block descriptors. +#define ISCSI_SCSI_EMU_MAX_UNMAP_BLOCK_DESC_COUNT 256UL + + +/// iSCSI SCSI emulation I/O type: Removable. +#define ISCSI_SCSI_EMU_IO_TYPE_REMOVABLE (1 << 0) + /// iSCSI SCSI emulation I/O type: Unmap. -#define ISCSI_SCSI_EMU_IO_TYPE_UNMAP (1 << 0) +#define ISCSI_SCSI_EMU_IO_TYPE_UNMAP (1 << 1) + +/// 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 block flags: Write operation. @@ -8031,6 +9218,7 @@ int iscsi_scsi_pr_in(iscsi_scsi_task *scsi_task, iscsi_scsi_pr_reserve_in_parame int iscsi_scsi_pr_reserve_scsi2(iscsi_scsi_task *scsi_task, const iscsi_scsi_cdb_pr_reserve_6 *cdb_pr_reserve_6); // Reserves an iSCSI SCSI Persistent Reservation (PR) of an iSCSI SCSI task int iscsi_scsi_pr_release_scsi2(iscsi_scsi_task *scsi_task); // Releases an iSCSI SCSI Persistent Reservation (PR) of an iSCSI SCSI task +int iscsi_scsi_emu_primary_inquiry_callback(uint8_t *key, const size_t key_size, uint8_t *value, uint8_t *user_data); // Fills in a single Vital Product Data (VPD) SCSI Port Designation Descriptor entry of an INQUIRY operation int iscsi_scsi_emu_exec(iscsi_scsi_task *scsi_task); // Executes the iSCSI SCSI emulation for an iSCSI SCSI task @@ -8207,6 +9395,9 @@ typedef struct iscsi_device { /// Number of ports. uint num_ports; + + /// Protocol identifier. + uint8_t protocol_id; } iscsi_device; @@ -8908,7 +10099,7 @@ void iscsi_task_xfer_complete_process_other(iscsi_connection *conn, iscsi_task * void iscsi_task_response(iscsi_connection *conn, iscsi_task *task); // Creates, initializes and sends an iSCSI task reponse PDU. -iscsi_device *iscsi_device_create(const uint8_t *name, const uint luns); // Creates and initializes an iSCSI device with a maximum number of LUNs +iscsi_device *iscsi_device_create(const uint8_t *name, const uint luns, const uint8_t protocol_id); // Creates and initializes an iSCSI device with a maximum number of LUNs void iscsi_device_destroy(iscsi_device *device); // Deallocates all resources acquired by iscsi_device_create iscsi_port *iscsi_device_find_port_by_portal_group_tag(const iscsi_device *device, const uint64_t id); // Gets an iSCSI device being in use by portal group identifier -- cgit v1.2.3-55-g7522