/*- * Copyright 2016-2023 Microchip Technology, Inc. and/or its subsidiaries. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef _PQI_STRUCTURES_H #define _PQI_STRUCTURES_H #include "smartpqi_defines.h" struct bmic_host_wellness_driver_version { uint8_t start_tag[4]; uint8_t driver_version_tag[2]; uint16_t driver_version_length; char driver_version[32]; uint8_t end_tag[2]; }OS_ATTRIBUTE_PACKED; struct bmic_host_wellness_time { uint8_t start_tag[4]; uint8_t time_tag[2]; uint16_t time_length; uint8_t hour; uint8_t min; uint8_t sec; uint8_t reserved; uint8_t month; uint8_t day; uint8_t century; uint8_t year; uint8_t dont_write_tag[2]; uint8_t end_tag[2]; }OS_ATTRIBUTE_PACKED; /* As per PQI Spec pqi-2r00a , 6.2.2. */ /* device capability register , for admin q table 24 */ struct pqi_dev_adminq_cap { uint8_t max_admin_ibq_elem; uint8_t max_admin_obq_elem; uint8_t admin_ibq_elem_len; uint8_t admin_obq_elem_len; uint16_t max_pqi_dev_reset_tmo; uint8_t res[2]; }OS_ATTRIBUTE_PACKED; /* admin q parameter reg , table 36 */ struct admin_q_param { uint8_t num_iq_elements; uint8_t num_oq_elements; uint8_t intr_msg_num; uint8_t msix_disable; }OS_ATTRIBUTE_PACKED; struct pqi_registers { uint64_t signature; uint64_t admin_q_config; uint64_t pqi_dev_adminq_cap; uint32_t legacy_intr_status; uint32_t legacy_intr_mask_set; uint32_t legacy_intr_mask_clr; uint8_t res1[28]; uint32_t pqi_dev_status; uint8_t res2[4]; uint64_t admin_ibq_pi_offset; uint64_t admin_obq_ci_offset; uint64_t admin_ibq_elem_array_addr; uint64_t admin_obq_elem_array_addr; uint64_t admin_ibq_ci_addr; uint64_t admin_obq_pi_addr; uint32_t admin_q_param; uint8_t res3[4]; uint32_t pqi_dev_err; uint8_t res4[4]; uint64_t error_details; uint32_t dev_reset; uint32_t power_action; uint8_t res5[104]; }OS_ATTRIBUTE_PACKED; /* * IOA controller registers * Mapped in PCIe BAR 0. */ struct ioa_registers { uint8_t res1[0x18]; uint32_t host_to_ioa_db_mask_clr; /* 18h */ uint8_t res2[4]; uint32_t host_to_ioa_db; /* 20h */ uint8_t res3[4]; uint32_t host_to_ioa_db_clr; /* 28h */ uint8_t res4[8]; uint32_t ioa_to_host_glob_int_mask; /* 34h */ uint8_t res5[0x64]; uint32_t ioa_to_host_db; /* 9Ch */ uint32_t ioa_to_host_db_clr; /* A0h */ uint8_t res6[4]; uint32_t ioa_to_host_db_mask; /* A8h */ uint32_t ioa_to_host_db_mask_clr; /* ACh */ uint32_t scratchpad0; /* B0h */ uint32_t scratchpad1; /* B4h */ uint32_t scratchpad2; /* B8h */ uint32_t scratchpad3_fw_status; /* BCh */ uint8_t res7[8]; uint32_t scratchpad4; /* C8h */ uint8_t res8[0xf34]; /* 0xC8 + 4 + 0xf34 = 1000h */ uint32_t mb[8]; /* 1000h */ }OS_ATTRIBUTE_PACKED; /* PQI Preferred settings */ struct pqi_pref_settings { uint16_t max_cmd_size; uint16_t max_fib_size; }OS_ATTRIBUTE_PACKED; /* pqi capability by sis interface */ struct pqi_cap { uint32_t max_sg_elem; uint32_t max_transfer_size; uint32_t max_outstanding_io; uint32_t conf_tab_off; uint32_t conf_tab_sz; }OS_ATTRIBUTE_PACKED; struct pqi_conf_table { uint8_t sign[8]; /* "CFGTABLE" */ uint32_t first_section_off; }; struct pqi_conf_table_section_header { uint16_t section_id; uint16_t next_section_off; }; struct pqi_conf_table_general_info { struct pqi_conf_table_section_header header; uint32_t section_len; uint32_t max_outstanding_req; uint32_t max_sg_size; uint32_t max_sg_per_req; }; struct pqi_conf_table_debug { struct pqi_conf_table_section_header header; uint32_t scratchpad; }; struct pqi_conf_table_heartbeat { struct pqi_conf_table_section_header header; uint32_t heartbeat_counter; }; typedef union pqi_reset_reg { struct { uint32_t reset_type : 3; uint32_t reserved : 2; uint32_t reset_action : 3; uint32_t hold_in_pd1 : 1; uint32_t reserved2 : 23; } bits; uint32_t all_bits; }pqi_reset_reg_t; /* Memory descriptor for DMA memory allocation */ typedef struct dma_mem { void *virt_addr; dma_addr_t dma_addr; uint32_t size; uint32_t align; char tag[32]; bus_dma_tag_t dma_tag; bus_dmamap_t dma_map; }dma_mem_t; /* Lock should be 8 byte aligned TODO : need to apply aligned for lock alone ? */ #ifndef LOCKFREE_STACK typedef struct pqi_taglist { uint32_t max_elem; uint32_t num_elem; uint32_t head; uint32_t tail; uint32_t *elem_array; boolean_t lockcreated; char lockname[LOCKNAME_SIZE]; OS_LOCK_T lock OS_ATTRIBUTE_ALIGNED(8); }pqi_taglist_t; #else /* LOCKFREE_STACK */ union head_list { struct { uint32_t seq_no; /* To avoid aba problem */ uint32_t index; /* Index at the top of the stack */ }top; uint64_t data; }; /* lock-free stack used to push and pop the tag used for IO request */ typedef struct lockless_stack { uint32_t *next_index_array; uint32_t max_elem;/*No.of total elements*/ uint32_t num_elem;/*No.of present elements*/ volatile union head_list head OS_ATTRIBUTE_ALIGNED(8); }lockless_stack_t; #endif /* LOCKFREE_STACK */ /* * PQI SGL descriptor layouts. */ /* * SGL (Scatter Gather List) descriptor Codes */ #define SGL_DESCRIPTOR_CODE_DATA_BLOCK 0x0 #define SGL_DESCRIPTOR_CODE_BIT_BUCKET 0x1 #define SGL_DESCRIPTOR_CODE_STANDARD_SEGMENT 0x2 #define SGL_DESCRIPTOR_CODE_LAST_STANDARD_SEGMENT 0x3 #define SGL_DESCRIPTOR_CODE_LAST_ALTERNATIVE_SGL_SEGMENT 0x4 #define SGL_DESCRIPTOR_CODE_VENDOR_SPECIFIC 0xF typedef struct sgl_descriptor { uint64_t addr; /* !< Bytes 0-7. The starting 64-bit memory byte address of the data block. */ uint32_t length; /* !< Bytes 8-11. The length in bytes of the data block. Set to 0x00000000 specifies that no data be transferred. */ uint8_t res[3]; /* !< Bytes 12-14. */ uint8_t zero : 4; /* !< Byte 15, Bits 0-3. */ uint8_t type : 4; /* !< Byte 15, Bits 4-7. sgl descriptor type */ } sg_desc_t; /* PQI IUs */ typedef struct iu_header { uint8_t iu_type; uint8_t comp_feature; uint16_t iu_length; }OS_ATTRIBUTE_PACKED iu_header_t; typedef struct general_admin_request /* REPORT_PQI_DEVICE_CAPABILITY, REPORT_MANUFACTURER_INFO, REPORT_OPERATIONAL_IQ, REPORT_OPERATIONAL_OQ all same layout. */ { iu_header_t header; /* !< Bytes 0-3. */ uint16_t res1; uint16_t work; uint16_t req_id; /* !< Bytes 8-9. request identifier */ uint8_t fn_code; /* !< Byte 10. which administrator function */ union { struct { uint8_t res2[33]; /* !< Bytes 11-43. function specific */ uint32_t buf_size; /* !< Bytes 44-47. size in bytes of the Data-In/Out Buffer */ sg_desc_t sg_desc; /* !< Bytes 48-63. SGL */ } OS_ATTRIBUTE_PACKED general_func; struct { uint8_t res1; uint16_t qid; uint8_t res2[2]; uint64_t elem_arr_addr; uint64_t iq_ci_addr; uint16_t num_elem; uint16_t elem_len; uint8_t queue_proto; uint8_t arb_prio; uint8_t res3[22]; uint32_t vend_specific; } OS_ATTRIBUTE_PACKED create_op_iq; struct { uint8_t res1; uint16_t qid; uint8_t res2[2]; uint64_t elem_arr_addr; uint64_t ob_pi_addr; uint16_t num_elem; uint16_t elem_len; uint8_t queue_proto; uint8_t res3[3]; uint16_t intr_msg_num; uint16_t coales_count; uint32_t min_coales_time; uint32_t max_coales_time; uint8_t res4[8]; uint32_t vend_specific; } OS_ATTRIBUTE_PACKED create_op_oq; struct { uint8_t res1; uint16_t qid; uint8_t res2[50]; } OS_ATTRIBUTE_PACKED delete_op_queue; struct { uint8_t res1; uint16_t qid; uint8_t res2[46]; uint32_t vend_specific; } OS_ATTRIBUTE_PACKED change_op_iq_prop; } OS_ATTRIBUTE_PACKED req_type; }OS_ATTRIBUTE_PACKED gen_adm_req_iu_t; typedef struct general_admin_response { iu_header_t header; uint16_t res1; uint16_t work; uint16_t req_id; uint8_t fn_code; uint8_t status; union { struct { uint8_t status_desc[4]; uint64_t pi_offset; uint8_t res[40]; } OS_ATTRIBUTE_PACKED create_op_iq; struct { uint8_t status_desc[4]; uint64_t ci_offset; uint8_t res[40]; } OS_ATTRIBUTE_PACKED create_op_oq; } OS_ATTRIBUTE_PACKED resp_type; } OS_ATTRIBUTE_PACKED gen_adm_resp_iu_t ; /*report and set Event config IU*/ typedef struct pqi_event_config_request { iu_header_t header; uint16_t response_queue_id; /* specifies the OQ where the response IU is to be delivered */ uint8_t work_area[2]; /* reserved for driver use */ uint16_t request_id; union { uint16_t reserved; /* Report event config iu */ uint16_t global_event_oq_id; /* Set event config iu */ }iu_specific; uint32_t buffer_length; sg_desc_t sg_desc; }pqi_event_config_request_t; #if 0 typedef struct pqi_set_event_config_request { iu_header_t header; uint16_t response_queue_id; /* specifies the OQ where the response IU is to be delivered */ uint8_t work_area[2]; /* reserved for driver use */ uint16_t request_id; uint16_t global_event_oq_id; uint32_t buffer_length; sg_desc_t sg_desc; }pqi_set_event_config_request_t; #endif /* Report/Set event config data-in/data-out buffer structure */ #define PQI_MAX_EVENT_DESCRIPTORS 255 struct pqi_event_descriptor { uint8_t event_type; uint8_t reserved; uint16_t oq_id; }; typedef struct pqi_event_config { uint8_t reserved[2]; uint8_t num_event_descriptors; uint8_t reserved1; struct pqi_event_descriptor descriptors[PQI_MAX_EVENT_DESCRIPTORS]; }pqi_event_config_t; /*management response IUs */ typedef struct pqi_management_response{ iu_header_t header; uint16_t reserved1; uint8_t work_area[2]; uint16_t req_id; uint8_t result; uint8_t reserved[5]; uint64_t result_data; }pqi_management_response_t; /*Event response IU*/ typedef struct pqi_event_response { iu_header_t header; uint16_t reserved1; uint8_t work_area[2]; uint8_t event_type; uint8_t reserved2 : 7; uint8_t request_acknowledge : 1; uint16_t event_id; uint32_t additional_event_id; uint8_t data[16]; }pqi_event_response_t; /*event acknowledge IU*/ typedef struct pqi_event_acknowledge_request { iu_header_t header; uint16_t reserved1; uint8_t work_area[2]; uint8_t event_type; uint8_t reserved2; uint16_t event_id; uint32_t additional_event_id; }pqi_event_acknowledge_request_t; struct pqi_event { boolean_t pending; uint8_t event_type; uint16_t event_id; uint32_t additional_event_id; }; typedef struct pqi_vendor_general_response { iu_header_t header; uint16_t reserved1; uint8_t work_area[2]; uint16_t request_id; uint16_t function_code; uint16_t status; uint8_t reserved2[2]; } OS_ATTRIBUTE_PACKED pqi_vendor_general_response_t; typedef struct op_q_params { uint8_t fn_code; uint16_t qid; uint16_t num_elem; uint16_t elem_len; uint16_t int_msg_num; } OS_ATTRIBUTE_PACKED op_q_params; /* "Fixed Format Sense Data" (0x70 or 0x71) (Table 45 in SPC5) */ typedef struct sense_data_fixed { uint8_t response_code : 7; /* Byte 0, 0x70 or 0x71 */ uint8_t valid : 1; /* Byte 0, bit 7 */ uint8_t byte_1; /* Byte 1 */ uint8_t sense_key : 4; /* Byte 2, bit 0-3 (Key) */ uint8_t byte_2_other : 4; /* Byte 2, bit 4-7 */ uint32_t information; /* Byte 3-6, big-endian like block # in CDB */ uint8_t addtnl_length; /* Byte 7 */ uint8_t cmd_specific[4]; /* Byte 8-11 */ uint8_t sense_code; /* Byte 12 (ASC) */ uint8_t sense_qual; /* Byte 13 (ASCQ) */ uint8_t fru_code; /* Byte 14 */ uint8_t sense_key_specific[3]; /* Byte 15-17 */ uint8_t addtnl_sense[1]; /* Byte 18+ */ } OS_ATTRIBUTE_PACKED sense_data_fixed_t; /* Generic Sense Data Descriptor (Table 29 in SPC5) */ typedef struct descriptor_entry { uint8_t desc_type; /* Byte 9/0 */ uint8_t desc_type_length; /* Byte 10/1 */ union { /* Sense data descriptor specific */ uint8_t bytes[1]; /* Information (Type 0) (Table 31 is SPC5) */ struct { uint8_t byte_2_rsvd : 7; /* Byte 11/2 */ uint8_t valid : 1; /* Byte 11/2, bit 7 */ uint8_t byte_3; /* Byte 12/3 */ uint8_t information[8]; /* Byte 13-20/4-11 */ } OS_ATTRIBUTE_PACKED type_0; }u; } OS_ATTRIBUTE_PACKED descriptor_entry_t; /* "Descriptor Format Sense Data" (0x72 or 0x73) (Table 28 in SPC5) */ typedef struct sense_data_descriptor { uint8_t response_code : 7; /* Byte 0, 0x72 or 0x73 */ uint8_t byte_0_rsvd: 1; /* Byte 0, bit 7 */ uint8_t sense_key : 4; /* Byte 1, bit 0-3 (Key) */ uint8_t byte_1_other : 4; /* Byte 1, bit 4-7 */ uint8_t sense_code; /* Byte 2 (ASC) */ uint8_t sense_qual; /* Byte 3 (ASCQ) */ uint8_t byte4_6[3]; /* Byte 4-6 */ uint8_t more_length; /* Byte 7 */ descriptor_entry_t descriptor_list; /* Bytes 8+ */ } OS_ATTRIBUTE_PACKED sense_data_descriptor_t; typedef union sense_data_u { sense_data_fixed_t fixed_format; sense_data_descriptor_t descriptor_format; uint8_t data[256]; } sense_data_u_t; /* Driver will use this structure to interpret the error info element returned from a failed requests */ typedef struct raid_path_error_info_elem { uint8_t data_in_result; /* !< Byte 0. See SOP spec Table 77. */ uint8_t data_out_result; /* !< Byte 1. See SOP spec Table 78. */ uint8_t reserved[3]; /* !< Bytes 2-4. */ uint8_t status; /* !< Byte 5. See SAM-5 specification "Status" codes Table 40.*/ uint16_t status_qual; /* !< Bytes 6-7. See SAM-5 specification Table 43. */ uint16_t sense_data_len; /* !< Bytes 8-9. See SOP specification table 79. */ uint16_t resp_data_len; /* !< Bytes 10-11. See SOP specification table 79. */ uint32_t data_in_transferred; /* !< Bytes 12-15. If "dada_in_result = 0x01 (DATA_IN BUFFER UNDERFLOW)", Indicates the number of contiguous bytes starting with offset zero in Data-In buffer else Ignored. */ uint32_t data_out_transferred;/* !< Bytes 16-19. If "data_out_result = 0x01 (DATA_OUT BUFFER UNDERFLOW)", Indicates the number of contiguous bytes starting with offset zero in Data-Out buffer else Ignored. */ union { sense_data_u_t sense_data; uint8_t data[256]; /* !< Bytes 20-275. Response Data buffer or Sense Data buffer but not both. */ }; }OS_ATTRIBUTE_PACKED raid_path_error_info_elem_t; #define PQI_ERROR_BUFFER_ELEMENT_LENGTH sizeof(raid_path_error_info_elem_t) typedef enum error_data_present { DATA_PRESENT_NO_DATA = 0, /* !< No data present in Data buffer. */ DATA_PRESENT_RESPONSE_DATA = 1, /* !< Response data is present in Data buffer. */ DATA_PRESENT_SENSE_DATA = 2 /* !< Sense data is present in Data buffer. */ } error_data_present_t; typedef struct aio_path_error_info_elem { uint8_t status; /* !< Byte 0. See SAM-5 specification "SCSI Status" codes Table 40.*/ uint8_t service_resp; /* !< Byte 1. SCSI Service Response. */ uint8_t data_pres; /* !< Byte 2. Bits [7:2] reserved. Bits [1:0] - 0=No data, 1=Response data, 2=Sense data. */ uint8_t reserved1; /* !< Byte 3. Reserved. */ uint32_t resd_count; /* !< Bytes 4-7. The residual data length in bytes. Need the original transfer size and if Status is OverRun or UnderRun. */ uint16_t data_len; /* !< Bytes 8-9. The amount of Sense data or Response data returned in Response/Sense Data buffer. */ uint16_t reserved2; /* !< Bytes 10-11. Reserved. */ union { sense_data_u_t sense_data; /* */ uint8_t data[256]; /* !< Bytes 12-267. Response data buffer or Sense data buffer but not both. */ }; uint8_t padding[8]; /* !< Bytes 268-275. Padding to make AIO_PATH_ERROR_INFO_ELEMENT = RAID_PATH_ERROR_INFO_ELEMENT */ }OS_ATTRIBUTE_PACKED aio_path_error_info_elem_t; struct init_base_struct { uint32_t revision; /* revision of init structure */ uint32_t flags; /* reserved */ uint32_t err_buf_paddr_l; /* lower 32 bits of physical address of error buffer */ uint32_t err_buf_paddr_h; /* upper 32 bits of physical address of error buffer */ uint32_t err_buf_elem_len; /* length of each element in error buffer (in bytes) */ uint32_t err_buf_num_elem; /* number of elements in error buffer */ }OS_ATTRIBUTE_PACKED; /* Queue details */ typedef struct ib_queue { uint32_t q_id; uint32_t num_elem; uint32_t elem_size; char *array_virt_addr; dma_addr_t array_dma_addr; uint32_t pi_local; uint32_t pi_register_offset; uint32_t *pi_register_abs; uint32_t *ci_virt_addr; dma_addr_t ci_dma_addr; boolean_t created; boolean_t lockcreated; char lockname[LOCKNAME_SIZE]; OS_PQILOCK_T lock OS_ATTRIBUTE_ALIGNED(8); struct dma_mem alloc_dma; }ib_queue_t; typedef struct ob_queue { uint32_t q_id; uint32_t num_elem; uint32_t elem_size; uint32_t intr_msg_num; char *array_virt_addr; dma_addr_t array_dma_addr; uint32_t ci_local; uint32_t ci_register_offset; uint32_t *ci_register_abs; uint32_t *pi_virt_addr; dma_addr_t pi_dma_addr; boolean_t created; struct dma_mem alloc_dma; }ob_queue_t; typedef struct pqisrc_sg_desc{ uint64_t addr; uint32_t len; uint32_t flags; }sgt_t; typedef struct pqi_iu_layer_desc { uint8_t ib_spanning_supported : 1; uint8_t res1 : 7; uint8_t res2[5]; uint16_t max_ib_iu_len; uint8_t ob_spanning_supported : 1; uint8_t res3 : 7; uint8_t res4[5]; uint16_t max_ob_iu_len; }OS_ATTRIBUTE_PACKED pqi_iu_layer_desc_t; /* Response IU data */ typedef struct pqi_device_capabilities { uint16_t length; uint8_t res1[6]; uint8_t ibq_arb_priority_support_bitmask; uint8_t max_aw_a; uint8_t max_aw_b; uint8_t max_aw_c; uint8_t max_arb_burst : 3; uint8_t res2 : 4; uint8_t iqa : 1; uint8_t res3[2]; uint8_t iq_freeze : 1; uint8_t res4 : 7; uint16_t max_iqs; uint16_t max_iq_elements; uint8_t res5[4]; uint16_t max_iq_elem_len; uint16_t min_iq_elem_len; uint8_t res6[2]; uint16_t max_oqs; uint16_t max_oq_elements; uint16_t intr_coales_time_granularity; uint16_t max_oq_elem_len; uint16_t min_oq_elem_len; uint8_t res7[24]; pqi_iu_layer_desc_t iu_layer_desc[32]; }OS_ATTRIBUTE_PACKED pqi_dev_cap_t; /* IO path */ typedef struct iu_cmd_flags { uint8_t data_dir : 2; uint8_t partial : 1; uint8_t mem_type : 1; uint8_t fence : 1; uint8_t encrypt_enable : 1; uint8_t res2 : 2; }OS_ATTRIBUTE_PACKED iu_cmd_flags_t; typedef struct iu_attr_prio { uint8_t task_attr : 3; uint8_t cmd_prio : 4; uint8_t res3 : 1; }OS_ATTRIBUTE_PACKED iu_attr_prio_t; typedef struct pqi_aio_req { iu_header_t header; uint16_t response_queue_id; uint8_t work_area[2]; uint16_t req_id; uint8_t res1[2]; uint32_t nexus; uint32_t buf_len; iu_cmd_flags_t cmd_flags; iu_attr_prio_t attr_prio; uint16_t encrypt_key_index; uint32_t encrypt_twk_low; uint32_t encrypt_twk_high; uint8_t cdb[16]; uint16_t err_idx; uint8_t num_sg; uint8_t cdb_len; uint8_t lun[8]; uint8_t res4[4]; sgt_t sg_desc[4]; }OS_ATTRIBUTE_PACKED pqi_aio_req_t; typedef struct pqi_aio_raid1_write_req { iu_header_t header; uint16_t response_queue_id; uint8_t work_area[2]; uint16_t req_id; uint16_t volume_id; /* ID of raid volume */ uint32_t nexus_1; /* 1st drive in RAID 1 */ uint32_t nexus_2; /* 2nd drive in RAID 1 */ uint32_t nexus_3; /* 3rd drive in RAID 1 */ uint32_t buf_len; iu_cmd_flags_t cmd_flags; iu_attr_prio_t attr_prio; uint16_t encrypt_key_index; uint8_t cdb[16]; uint16_t err_idx; uint8_t num_sg; uint8_t cdb_len; uint8_t num_drives; /* drives in raid1 (2 or 3) */ uint8_t reserved_bytes[3]; uint32_t encrypt_twk_low; uint32_t encrypt_twk_high; sgt_t sg_desc[4]; }OS_ATTRIBUTE_PACKED pqi_aio_raid1_write_req_t; typedef struct pqi_aio_raid5or6_write_req { iu_header_t header; uint16_t response_queue_id; uint8_t work_area[2]; uint16_t req_id; uint16_t volume_id; /* ID of raid volume */ uint32_t data_it_nexus; /* IT nexus of data drive */ uint32_t p_parity_it_nexus;/* It nexus of p parity disk */ uint32_t q_parity_it_nexus;/* It nexus of q parity disk (R6) */ uint32_t buf_len; iu_cmd_flags_t cmd_flags; iu_attr_prio_t attr_prio; uint16_t encrypt_key_index; uint8_t cdb[16]; uint16_t err_idx; uint8_t num_sg; uint8_t cdb_len; uint8_t xor_multiplier; /* for generating RAID 6 Q parity */ uint8_t reserved[3]; uint32_t encrypt_twk_low; uint32_t encrypt_twk_high; uint64_t row; /* logical lba / blocks per row */ uint8_t reserved2[8]; /* changed to reserved, used to stripe_lba */ sgt_t sg_desc[3]; /* only 3 entries for R5/6 */ }OS_ATTRIBUTE_PACKED pqi_aio_raid5or6_write_req_t; typedef struct pqisrc_raid_request { iu_header_t header; uint16_t response_queue_id; /* specifies the OQ where the response IU is to be delivered */ uint8_t work_area[2]; /* reserved for driver use */ uint16_t request_id; uint16_t nexus_id; uint32_t buffer_length; uint8_t lun_number[8]; uint16_t protocol_spec; uint8_t data_direction : 2; uint8_t partial : 1; uint8_t reserved1 : 4; uint8_t fence : 1; uint16_t error_index; uint8_t reserved2; uint8_t task_attribute : 3; uint8_t command_priority : 4; uint8_t reserved3 : 1; uint8_t reserved4 : 2; uint8_t additional_cdb_bytes_usage : 3; uint8_t reserved5 : 3; union { uint8_t cdb[16]; struct { uint8_t op_code; /* Byte 0. SCSI opcode (0x26 or 0x27) */ uint8_t lun_lower; /* Byte 1 */ uint32_t detail; /* Byte 2-5 */ uint8_t cmd; /* Byte 6. Vendor specific op code. */ uint16_t xfer_len; /* Byte 7-8 */ uint8_t lun_upper; /* Byte 9 */ uint8_t unused[6]; /* Bytes 10-15. */ }OS_ATTRIBUTE_PACKED bmic_cdb; }OS_ATTRIBUTE_PACKED cmd; uint8_t reserved[11]; uint8_t ml_device_lun_number; uint32_t timeout_in_sec; sgt_t sg_descriptors[4]; }OS_ATTRIBUTE_PACKED pqisrc_raid_req_t; typedef struct pqi_raid_tmf_req { iu_header_t header; uint16_t resp_qid; uint8_t work_area[2]; uint16_t req_id; uint16_t nexus; uint8_t res1[1]; uint8_t ml_device_lun_number; uint16_t timeout_in_sec; uint8_t lun[8]; uint16_t protocol_spec; uint16_t obq_id_to_manage; uint16_t req_id_to_manage; uint8_t tmf; uint8_t res2 : 7; uint8_t fence : 1; } OS_ATTRIBUTE_PACKED pqi_raid_tmf_req_t; typedef struct pqi_aio_tmf_req { iu_header_t header; uint16_t resp_qid; uint8_t work_area[2]; uint16_t req_id; uint16_t res1; uint32_t nexus; uint8_t lun[8]; uint32_t req_id_to_manage; uint8_t tmf; uint8_t res2 : 7; uint8_t fence : 1; uint16_t error_idx; }OS_ATTRIBUTE_PACKED pqi_aio_tmf_req_t; typedef struct pqi_tmf_resp { iu_header_t header; uint16_t resp_qid; uint8_t work_area[2]; uint16_t req_id; uint16_t nexus; uint8_t add_resp_info[3]; uint8_t resp_code; }pqi_tmf_resp_t; struct pqi_io_response { iu_header_t header; uint16_t queue_id; uint8_t work_area[2]; uint16_t request_id; uint16_t error_index; uint8_t reserved[4]; }OS_ATTRIBUTE_PACKED; struct pqi_enc_info { uint16_t data_enc_key_index; uint32_t encrypt_tweak_lower; uint32_t encrypt_tweak_upper; }; typedef uint32_t os_ticks_t; struct pqi_stream_data { uint64_t next_lba; os_ticks_t last_accessed; }; typedef struct pqi_scsi_device { device_type_t devtype; /* as reported by INQUIRY command */ uint8_t device_type; /* as reported by BMIC_IDENTIFY_PHYSICAL_DEVICE - only valid for devtype = TYPE_DISK */ int bus; int target; int lun; uint8_t flags; uint8_t scsi3addr[8]; uint64_t wwid; uint8_t is_physical_device : 1; uint8_t is_external_raid_device : 1; uint8_t target_lun_valid : 1; uint8_t expose_device : 1; uint8_t no_uld_attach : 1; uint8_t is_obdr_device : 1; uint8_t aio_enabled : 1; uint8_t device_gone : 1; uint8_t new_device : 1; uint8_t volume_offline : 1; uint8_t is_nvme : 1; uint8_t scsi_rescan : 1; uint8_t vendor[8]; /* bytes 8-15 of inquiry data */ uint8_t model[16]; /* bytes 16-31 of inquiry data */ uint64_t sas_address; uint8_t raid_level; uint16_t queue_depth; /* max. queue_depth for this device */ uint32_t ioaccel_handle; uint8_t volume_status; uint8_t active_path_index; uint8_t path_map; uint8_t bay; uint8_t box[8]; uint16_t phys_connector[8]; int offload_config; /* I/O accel RAID offload configured */ int offload_enabled; /* I/O accel RAID offload enabled */ int offload_enabled_pending; int *offload_to_mirror; /* Send next I/O accelerator RAID offload request to mirror drive. */ struct raid_map *raid_map; /* I/O accelerator RAID map */ int reset_in_progress; int logical_unit_number; os_dev_info_t *dip; /*os specific scsi device information*/ boolean_t invalid; boolean_t path_destroyed; boolean_t firmware_queue_depth_set; OS_ATOMIC64_T active_requests; struct pqisrc_softstate *softs; boolean_t schedule_rescan; boolean_t in_remove; struct pqi_stream_data stream_data[NUM_STREAMS_PER_LUN]; boolean_t is_multi_lun; }pqi_scsi_dev_t; struct sense_header_scsi { /* See SPC-3 section 4.5 */ uint8_t response_code; /* permit: 0x0, 0x70, 0x71, 0x72, 0x73 */ uint8_t sense_key; uint8_t asc; uint8_t ascq; uint8_t byte4; uint8_t byte5; uint8_t byte6; uint8_t additional_length; /* always 0 for fixed sense format */ }OS_ATTRIBUTE_PACKED; typedef struct report_lun_header { uint32_t list_length; uint8_t extended_response; uint8_t reserved[3]; }OS_ATTRIBUTE_PACKED reportlun_header_t; typedef struct report_lun_ext_entry { uint8_t lunid[8]; uint64_t wwid; uint8_t device_type; uint8_t device_flags; uint8_t lun_count; /* number of LUNs in a multi-LUN device */ uint8_t redundant_paths; uint32_t ioaccel_handle; }OS_ATTRIBUTE_PACKED reportlun_ext_entry_t; typedef struct report_lun_data_ext { reportlun_header_t header; reportlun_ext_entry_t lun_entries[1]; }OS_ATTRIBUTE_PACKED reportlun_data_ext_t; typedef struct reportlun_queue_depth_entry { uint8_t logical_unit_num; uint8_t reserved_1:6; uint8_t address:2; uint8_t box_bus_num; uint8_t reserved_2:6; uint8_t mode:2; uint8_t bus_ident; /* Byte 5 */ uint8_t queue_depth:7; uint8_t multiplier:1; /* Byte 6 */ uint8_t drive_type_mix_flags; uint8_t level_2_bus:6; uint8_t level_2_mode:2; uint8_t unused_bytes[16]; }OS_ATTRIBUTE_PACKED reportlun_queue_depth_entry_t; typedef struct reportlun_queue_depth_data { reportlun_header_t header; reportlun_queue_depth_entry_t lun_entries[1]; /* lun list with Queue Depth values for each lun */ }OS_ATTRIBUTE_PACKED reportlun_queue_depth_data_t; typedef struct raidmap_data { uint32_t ioaccel_handle; uint8_t xor_mult[2]; uint8_t reserved[2]; }OS_ATTRIBUTE_PACKED raidmap_data_t; typedef struct raid_map { uint32_t structure_size; /* size of entire structure in bytes */ uint32_t volume_blk_size; /* bytes / block in the volume */ uint64_t volume_blk_cnt; /* logical blocks on the volume */ uint8_t phys_blk_shift; /* shift factor to convert between units of logical blocks and physical disk blocks */ uint8_t parity_rotation_shift; /* shift factor to convert between units of logical stripes and physical stripes */ uint16_t strip_size; /* blocks used on each disk / stripe */ uint64_t disk_starting_blk; /* first disk block used in volume */ uint64_t disk_blk_cnt; /* disk blocks used by volume / disk */ uint16_t data_disks_per_row; /* data disk entries / row in the map */ uint16_t metadata_disks_per_row; /* mirror/parity disk entries / row in the map */ uint16_t row_cnt; /* rows in each layout map */ uint16_t layout_map_count; /* layout maps (1 map per mirror/parity group) */ uint16_t flags; uint16_t data_encryption_key_index; uint8_t reserved[16]; raidmap_data_t dev_data[RAID_MAP_MAX_ENTRIES]; }OS_ATTRIBUTE_PACKED pqisrc_raid_map_t; typedef struct aio_row { uint32_t blks_per_row; /* blocks per row */ uint64_t first; /* first row */ uint64_t last; /* last row */ uint32_t offset_first; /* offset in first row */ uint32_t offset_last; /* offset in last row */ uint16_t data_disks; /* number of data disks per row */ uint16_t total_disks; /* data + parity disks per row. */ }OS_ATTRIBUTE_PACKED pqisrc_aio_row_t; typedef struct aio_column { uint32_t first; /* 1st column of req */ uint32_t last; /* last column of req */ }OS_ATTRIBUTE_PACKED pqisrc_aio_column_t; typedef struct aio_block { uint64_t first; /* 1st block number of req */ uint64_t last; /* last block number of req */ uint32_t cnt; /* total blocks in req */ uint64_t disk_block; /* block number of phys disk */ }OS_ATTRIBUTE_PACKED pqisrc_aio_block_t; typedef struct aio_r5or6_loc { struct aio_row row; /* row information */ struct aio_column col; /* column information */ }OS_ATTRIBUTE_PACKED pqisrc_aio_r5or6_loc_t; typedef struct aio_map { uint32_t row; uint32_t idx; /* index into array of handles */ uint16_t layout_map_count; }OS_ATTRIBUTE_PACKED pqisrc_aio_map_t; typedef struct aio_disk_group { uint32_t first; /* first group */ uint32_t last; /* last group */ uint32_t cur; /* current group */ }OS_ATTRIBUTE_PACKED pqisrc_aio_disk_group_t; typedef struct aio_req_locator { uint8_t raid_level; struct raid_map *raid_map; /* relevant raid map */ struct aio_block block; /* block range and count */ struct aio_row row; /* row range and offset info */ struct aio_column col; /* first/last column info */ struct aio_r5or6_loc r5or6; /* Raid 5/6-specific bits */ struct aio_map map; /* map row, count, and index */ struct aio_disk_group group; /* first, last, and curr group */ boolean_t is_write; uint32_t stripesz; uint16_t strip_sz; int offload_to_mirror; }OS_ATTRIBUTE_PACKED aio_req_locator_t; typedef struct bmic_ident_ctrl { uint8_t conf_ld_count; uint32_t conf_sign; uint8_t fw_version[4]; uint8_t rom_fw_rev[4]; uint8_t hw_rev; uint8_t reserved[140]; uint16_t extended_lun_count; uint8_t reserved1[34]; uint16_t fw_build_number; uint8_t reserved2[100]; uint8_t ctrl_mode; uint8_t reserved3[32]; }OS_ATTRIBUTE_PACKED bmic_ident_ctrl_t; typedef struct bmic_identify_physical_device { uint8_t scsi_bus; /* SCSI Bus number on controller */ uint8_t scsi_id; /* SCSI ID on this bus */ uint16_t block_size; /* sector size in bytes */ uint32_t total_blocks; /* number for sectors on drive */ uint32_t reserved_blocks; /* controller reserved (RIS) */ uint8_t model[40]; /* Physical Drive Model */ uint8_t serial_number[40]; /* Drive Serial Number */ uint8_t firmware_revision[8]; /* drive firmware revision */ uint8_t scsi_inquiry_bits; /* inquiry byte 7 bits */ uint8_t compaq_drive_stamp; /* 0 means drive not stamped */ uint8_t last_failure_reason; uint8_t flags; uint8_t more_flags; uint8_t scsi_lun; /* SCSI LUN for phys drive */ uint8_t yet_more_flags; uint8_t even_more_flags; uint32_t spi_speed_rules; uint8_t phys_connector[2]; /* connector number on controller */ uint8_t phys_box_on_bus; /* phys enclosure this drive resides */ uint8_t phys_bay_in_box; /* phys drv bay this drive resides */ uint32_t rpm; /* drive rotational speed in RPM */ uint8_t device_type; /* type of drive */ uint8_t sata_version; /* only valid when device_type = BMIC_DEVICE_TYPE_SATA */ uint64_t big_total_block_count; uint64_t ris_starting_lba; uint32_t ris_size; uint8_t wwid[20]; uint8_t controller_phy_map[32]; uint16_t phy_count; uint8_t phy_connected_dev_type[256]; uint8_t phy_to_drive_bay_num[256]; uint16_t phy_to_attached_dev_index[256]; uint8_t box_index; uint8_t reserved; uint16_t extra_physical_drive_flags; uint8_t negotiated_link_rate[256]; uint8_t phy_to_phy_map[256]; uint8_t redundant_path_present_map; uint8_t redundant_path_failure_map; uint8_t active_path_number; uint16_t alternate_paths_phys_connector[8]; uint8_t alternate_paths_phys_box_on_port[8]; uint8_t multi_lun_device_lun_count; uint8_t minimum_good_fw_revision[8]; uint8_t unique_inquiry_bytes[20]; uint8_t current_temperature_degreesC; uint8_t temperature_threshold_degreesC; uint8_t max_temperature_degreesC; uint8_t logical_blocks_per_phys_block_exp; uint16_t current_queue_depth_limit; uint8_t switch_name[10]; uint16_t switch_port; uint8_t alternate_paths_switch_name[40]; uint8_t alternate_paths_switch_port[8]; uint16_t power_on_hours; uint16_t percent_endurance_used; uint8_t drive_authentication; uint8_t smart_carrier_authentication; uint8_t smart_carrier_app_fw_version; uint8_t smart_carrier_bootloader_fw_version; uint8_t encryption_key_name[64]; uint32_t misc_drive_flags; uint16_t dek_index; uint8_t padding[112]; }OS_ATTRIBUTE_PACKED bmic_ident_physdev_t; typedef struct bmic_sense_feature { uint8_t opcode; uint8_t reserved1[1]; uint8_t page; uint8_t sub_page; uint8_t reserved2[2]; uint8_t cmd; uint16_t transfer_length; uint8_t reserved3[7]; }OS_ATTRIBUTE_PACKED bmic_sense_feature_t; typedef struct bmic_sense_feature_buffer_header { uint8_t page; uint8_t sub_page; uint16_t buffer_length; } OS_ATTRIBUTE_PACKED bmic_sense_feature_buffer_header_t; typedef struct bmic_sense_feature_page_header { uint8_t page; uint8_t sub_page; uint16_t total_length; /** Total length of the page. * The length is the same wheteher the request buffer is too short or not. * When printing out the page, only print the buffer length. */ } OS_ATTRIBUTE_PACKED bmic_sense_feature_page_header_t; typedef struct bmic_sense_feature_page_io { struct bmic_sense_feature_page_header header; uint8_t flags1; } OS_ATTRIBUTE_PACKED bmic_sense_feature_page_io_t; typedef struct bmic_sense_feature_page_io_aio_subpage { struct bmic_sense_feature_page_header header; uint8_t fw_aio_read_support; uint8_t driver_aio_read_support; uint8_t fw_aio_write_support; uint8_t driver_aio_write_support; uint16_t max_aio_rw_xfer_crypto_sas_sata; /* in kb */ uint16_t max_aio_rw_xfer_crypto_nvme; /* in kb */ uint16_t max_aio_write_raid5_6; /* in kb */ uint16_t max_aio_write_raid1_10_2drv; /* in kb */ uint16_t max_aio_write_raid1_10_3drv; /* in kb */ } OS_ATTRIBUTE_PACKED bmic_sense_feature_page_io_aio_subpage_t; typedef struct bmic_sense_feature_aio_buffer { struct bmic_sense_feature_buffer_header header; struct bmic_sense_feature_page_io_aio_subpage aio_subpage; } OS_ATTRIBUTE_PACKED bmic_sense_feature_aio_buffer_t; typedef struct pqisrc_bmic_flush_cache { uint8_t disable_cache; uint8_t power_action; uint8_t ndu_flush_cache; uint8_t halt_event; uint8_t reserved[28]; } OS_ATTRIBUTE_PACKED pqisrc_bmic_flush_cache_t; /* for halt_event member of pqisrc_bmic_flush_cache_t */ enum pqisrc_flush_cache_event_type { PQISRC_NONE_CACHE_FLUSH_ONLY = 0, PQISRC_SHUTDOWN = 1, PQISRC_HIBERNATE = 2, PQISRC_SUSPEND = 3, PQISRC_RESTART = 4 }; struct request_container_block; typedef void (*success_callback)(struct pqisrc_softstate *, struct request_container_block *); typedef void (*error_callback)(struct pqisrc_softstate *, struct request_container_block *, uint16_t); /* Request container block */ typedef struct request_container_block { void *req; void *error_info; int status; uint32_t tag; sgt_t *sg_chain_virt; dma_addr_t sg_chain_dma; uint32_t data_dir; pqi_scsi_dev_t *dvp; struct pqisrc_softstate *softs; success_callback success_cmp_callback; error_callback error_cmp_callback; uint8_t *cdbp; /* points to either the bypass_cdb below or original host cdb */ uint8_t bypass_cdb[16]; /* bypass cmds will use this cdb memory */ int cmdlen; uint32_t bcount; /* buffer size in byte */ uint32_t ioaccel_handle; boolean_t encrypt_enable; struct pqi_enc_info enc_info; uint32_t row_num; uint32_t blocks_per_row; uint32_t raid_map_index; uint32_t raid_map_row; ib_queue_t *req_q; IO_PATH_T path; int resp_qid; boolean_t req_pending; uint32_t it_nexus[PQISRC_MAX_SUPPORTED_MIRRORS]; boolean_t timedout; int tm_req; int aio_retry; boolean_t is_abort_cmd_from_host; /* true if this is a TMF abort */ boolean_t host_wants_to_abort_this; /* set to true to ID the request targeted by TMF */ uint64_t submit_time_user_secs; /* host submit time in user seconds */ uint64_t host_timeout_ms; /* original host timeout value in msec */ int cm_flags; void *cm_data; /* pointer to data in kernel space */ bus_dmamap_t cm_datamap; uint32_t nseg; union ccb *cm_ccb; sgt_t *sgt; /* sg table */ }rcb_t; typedef struct bit_map { boolean_t bit_vector[MAX_TARGET_BIT]; }bit_map_t; typedef enum _io_type { UNKNOWN_IO_TYPE, /* IO Type is TBD or cannot be determined */ NON_RW_IO_TYPE, /* IO Type is non-Read/Write opcode (could separate BMIC, etc. if we wanted) */ READ_IO_TYPE, /* IO Type is SCSI Read */ WRITE_IO_TYPE, /* IO Type is SCSI Write */ } io_type_t; typedef enum _counter_types { UNKNOWN_COUNTER, HBA_COUNTER, RAID0_COUNTER, RAID1_COUNTER, RAID5_COUNTER, RAID6_COUNTER, MAX_IO_COUNTER, } counter_types_t; typedef struct _io_counters { OS_ATOMIC64_T raid_read_cnt; OS_ATOMIC64_T raid_write_cnt; OS_ATOMIC64_T aio_read_cnt; OS_ATOMIC64_T aio_write_cnt; OS_ATOMIC64_T raid_non_read_write; OS_ATOMIC64_T aio_non_read_write; } io_counters_t; typedef struct pqisrc_softstate { OS_SPECIFIC_T os_specific; struct ioa_registers *ioa_reg; struct pqi_registers *pqi_reg; uint8_t *pci_mem_base_vaddr; PCI_ACC_HANDLE_T pci_mem_handle; struct pqi_cap pqi_cap; struct pqi_pref_settings pref_settings; char fw_version[11]; uint16_t fw_build_number; uint32_t card; /* index to aac_cards */ uint16_t vendid; /* vendor id */ uint16_t subvendid; /* sub vendor id */ uint16_t devid; /* device id */ uint16_t subsysid; /* sub system id */ controller_state_t ctlr_state; struct dma_mem err_buf_dma_mem; struct dma_mem sg_dma_desc[PQISRC_MAX_OUTSTANDING_REQ + 1]; ib_queue_t admin_ib_queue; ob_queue_t admin_ob_queue; ob_queue_t event_q; ob_queue_t op_ob_q[PQISRC_MAX_SUPPORTED_OP_OB_Q - 1];/* 1 event queue */ ib_queue_t op_raid_ib_q[PQISRC_MAX_SUPPORTED_OP_RAID_IB_Q]; ib_queue_t op_aio_ib_q[PQISRC_MAX_SUPPORTED_OP_AIO_IB_Q]; uint32_t max_outstanding_io; uint32_t max_io_for_scsi_ml; uint32_t num_op_raid_ibq; uint32_t num_op_aio_ibq; uint32_t num_op_obq; uint32_t num_elem_per_op_ibq; uint32_t num_elem_per_op_obq; uint32_t max_ibq_elem_size; uint32_t max_obq_elem_size; pqi_dev_cap_t pqi_dev_cap; uint16_t max_ib_iu_length_per_fw; uint16_t max_ib_iu_length; /* should be 1152 */ uint16_t max_spanning_elems; /* should be 9 spanning elements */ unsigned max_sg_per_single_iu_element; /* should be 8 */ unsigned max_sg_per_spanning_cmd; /* should be 68, 67 with AIO writes */ uint8_t ib_spanning_supported : 1; uint8_t ob_spanning_supported : 1; pqi_event_config_t event_config; struct pqi_event pending_events[PQI_NUM_SUPPORTED_EVENTS]; int intr_type; int intr_count; int num_cpus_online; int num_devs; boolean_t share_opq_and_eventq; rcb_t *rcb; #ifndef LOCKFREE_STACK pqi_taglist_t taglist; #else lockless_stack_t taglist; #endif /* LOCKFREE_STACK */ boolean_t devlist_lockcreated; OS_LOCK_T devlist_lock OS_ATTRIBUTE_ALIGNED(8); char devlist_lock_name[LOCKNAME_SIZE]; pqi_scsi_dev_t *device_list[PQI_MAX_DEVICES][PQI_MAX_MULTILUN]; pqi_scsi_dev_t *dev_list[PQI_MAX_DEVICES]; OS_SEMA_LOCK_T scan_lock; uint8_t lun_count[PQI_MAX_DEVICES]; uint64_t target_sas_addr[PQI_MAX_EXT_TARGETS]; uint64_t phys_list_pos; uint64_t prev_heartbeat_count; uint64_t *heartbeat_counter_abs_addr; uint64_t heartbeat_counter_off; uint32_t bus_id; uint32_t device_id; uint32_t func_id; uint8_t adapter_num; /* globally unique adapter number */ char *os_name; boolean_t ctrl_online; uint8_t pqi_reset_quiesce_allowed : 1; boolean_t ctrl_in_pqi_mode; bit_map_t bit_map; uint32_t adapterQDepth; uint32_t dma_mem_consumed; boolean_t adv_aio_capable; boolean_t aio_raid1_write_bypass; boolean_t aio_raid5_write_bypass; boolean_t aio_raid6_write_bypass; boolean_t enable_stream_detection; uint16_t max_aio_write_raid5_6; /* bytes */ uint16_t max_aio_write_raid1_10_2drv; /* bytes */ uint16_t max_aio_write_raid1_10_3drv; /* bytes */ uint16_t max_aio_rw_xfer_crypto_nvme; /* bytes */ uint16_t max_aio_rw_xfer_crypto_sas_sata; /* bytes */ io_counters_t counters[MAX_IO_COUNTER]; boolean_t log_io_counters; boolean_t ld_rescan; #ifdef PQI_NEED_RESCAN_TIMER_FOR_RBOD_HOTPLUG reportlun_data_ext_t *log_dev_list; size_t log_dev_data_length; uint32_t num_ptraid_targets; #endif boolean_t timeout_in_passthrough; boolean_t timeout_in_tmf; boolean_t sata_unique_wwn; boolean_t page83id_in_rpl; boolean_t err_resp_verbose; #ifdef DEVICE_HINT device_hint hint; #endif }pqisrc_softstate_t; struct pqi_config_table { uint8_t signature[8]; /* "CFGTABLE" */ uint32_t first_section_offset; /* offset in bytes from the base */ /* address of this table to the */ /* first section */ }OS_ATTRIBUTE_PACKED; struct pqi_config_table_section_header { uint16_t section_id; /* as defined by the */ /* PQI_CONFIG_TABLE_SECTION_* */ /* manifest constants above */ uint16_t next_section_offset; /* offset in bytes from base */ /* address of the table of the */ /* next section or 0 if last entry */ }OS_ATTRIBUTE_PACKED; struct pqi_config_table_general_info { struct pqi_config_table_section_header header; uint32_t section_length; /* size of this section in bytes */ /* including the section header */ uint32_t max_outstanding_requests; /* max. outstanding */ /* commands supported by */ /* the controller */ uint32_t max_sg_size; /* max. transfer size of a single */ /* command */ uint32_t max_sg_per_request; /* max. number of scatter-gather */ /* entries supported in a single */ /* command */ }OS_ATTRIBUTE_PACKED; struct pqi_config_table_firmware_features { struct pqi_config_table_section_header header; uint16_t num_elements; uint8_t features_supported[]; /* u8 features_requested_by_host[]; */ /* u8 features_enabled[]; */ /* The 2 fields below are only valid if the MAX_KNOWN_FEATURE bit is set. */ /* uint16_t firmware_max_known_feature; */ /* uint16_t host_max_known_feature; */ }OS_ATTRIBUTE_PACKED; typedef struct pqi_vendor_general_request { iu_header_t header; /* bytes 0-3 */ uint16_t response_id; /* bytes 4-5 */ uint16_t work; /* bytes 6-7 */ uint16_t request_id; uint16_t function_code; union { struct { uint16_t first_section; uint16_t last_section; uint8_t reserved[48]; } OS_ATTRIBUTE_PACKED config_table_update; struct { uint64_t buffer_address; uint32_t buffer_length; uint8_t reserved[40]; } OS_ATTRIBUTE_PACKED ofa_memory_allocation; } data; }OS_ATTRIBUTE_PACKED pqi_vendor_general_request_t; typedef struct vpd_logical_volume_status { uint8_t peripheral_info; uint8_t page_code; uint8_t reserved; uint8_t page_length; uint8_t volume_status; uint8_t reserved2[3]; uint32_t flags; }vpd_volume_status; #endif