1 /* 2 * This file and its contents are supplied under the terms of the 3 * Common Development and Distribution License ("CDDL"), version 1.0. 4 * You may only use this file in accordance with the terms of version 5 * 1.0 of the CDDL. 6 * 7 * A full copy of the text of the CDDL should have accompanied this 8 * source. A copy of the CDDL is also available via the Internet at 9 * http://www.illumos.org/license/CDDL. 10 */ 11 12 /* 13 * Copyright (C) 2013 Hewlett-Packard Development Company, L.P. 14 * Copyright (c) 2017 Joyent, Inc. 15 */ 16 17 #ifndef _SMRT_SCSI_H 18 #define _SMRT_SCSI_H 19 20 #include <sys/types.h> 21 22 #include <sys/scsi/adapters/smrt/smrt_ciss.h> 23 24 #ifdef __cplusplus 25 extern "C" { 26 #endif 27 28 /* CISS LUN Addressing MODEs */ 29 #define PERIPHERIAL_DEV_ADDR 0x0 30 #define LOGICAL_VOL_ADDR 0x1 31 #define MASK_PERIPHERIAL_DEV_ADDR 0x3 32 #define CISS_PHYS_MODE 0x0 33 34 /* 35 * Vendor-specific SCSI Commands 36 * 37 * These command opcodes are for use in the opcode byte of the CDB in a request 38 * of type CISS_TYPE_CMD. They are custom SCSI commands, using the 39 * vendor-specific part of the opcode space; i.e., 0xC0 through 0xFF. 40 */ 41 #define CISS_SCMD_READ 0xC0 42 #define CISS_SCMD_WRITE 0xC1 43 #define CISS_SCMD_REPORT_LOGICAL_LUNS 0xC2 44 #define CISS_SCMD_REPORT_PHYSICAL_LUNS 0xC3 45 46 /* 47 * These command opcodes are _not_ in the usual vendor-specific space, but are 48 * nonetheless vendor-specific. They allow BMIC commands to be written to and 49 * read from the controller. If a command transfers no data, the specification 50 * suggests that BMIC_WRITE (0x27) is appropriate. 51 */ 52 #define CISS_SCMD_BMIC_READ 0x26 53 #define CISS_SCMD_BMIC_WRITE 0x27 54 55 /* 56 * CISS Messages 57 * 58 * The CISS specification describes several directives that do not behave like 59 * SCSI commands. They are sent in requests of type CISS_TYPE_MSG. 60 * 61 * The Abort, Reset, and Nop, messages are defined in "8. Messages" in the CISS 62 * Specification. 63 */ 64 #define CISS_MSG_ABORT 0x0 65 #define CISS_ABORT_TASK 0x0 66 #define CISS_ABORT_TASKSET 0x1 67 68 #define CISS_MSG_RESET 0x1 69 #define CISS_RESET_CTLR 0x0 70 #define CISS_RESET_BUS 0x1 71 #define CISS_RESET_TGT 0x3 72 #define CISS_RESET_LUN 0x4 73 74 #define CISS_MSG_NOP 0x3 75 76 /* 77 * BMIC Commands 78 * 79 * These commands allow for the use of non-standard facilities specific to the 80 * Smart Array firmware. They are sent to the controller through a specially 81 * constructed CDB with the CISS_SCMD_BMIC_READ or CISS_SCMD_BMIC_WRITE opcode. 82 */ 83 #define CISS_BMIC_IDENTIFY_CONTROLLER 0x11 84 #define CISS_BMIC_IDENTIFY_PHYSICAL_DEVICE 0x15 85 #define CISS_BMIC_NOTIFY_ON_EVENT 0xD0 86 #define CISS_BMIC_NOTIFY_ON_EVENT_CANCEL 0xD1 87 88 /* 89 * Device and Phy type codes. These are used across many commands, including 90 * IDENTIFY PHYSICAL DEVICE and the REPORT PHYSICAL LUN extended reporting. 91 */ 92 #define SMRT_DTYPE_PSCSI 0x00 93 #define SMRT_DTYPE_SATA 0x01 94 #define SMRT_DTYPE_SAS 0x02 95 #define SMRT_DTYPE_SATA_BW 0x03 96 #define SMRT_DTYPE_SAS_BW 0x04 97 #define SMRT_DTYPE_EXPANDER 0x05 98 #define SMRT_DTYPE_SES 0x06 99 #define SMRT_DTYPE_CONTROLLER 0x07 100 #define SMRT_DTYPE_SGPIO 0x08 101 #define SMRT_DTYPE_NVME 0x09 102 #define SMRT_DTYPE_NOPHY 0xFF 103 104 /* 105 * The following packed structures are used to ease the manipulation of SCSI 106 * and BMIC commands sent to, and status information returned from, the 107 * controller. 108 */ 109 #pragma pack(1) 110 111 typedef struct smrt_report_logical_lun_ent { 112 LogDevAddr_t smrle_addr; 113 } smrt_report_logical_lun_ent_t; 114 115 typedef struct smrt_report_logical_lun_extent { 116 LogDevAddr_t smrle_addr; 117 uint8_t smrle_wwn[16]; 118 } smrt_report_logical_lun_extent_t; 119 120 typedef struct smrt_report_logical_lun { 121 uint32_t smrll_datasize; /* Big Endian */ 122 uint8_t smrll_extflag; 123 uint8_t smrll_reserved1[3]; 124 union { 125 smrt_report_logical_lun_ent_t ents[SMRT_MAX_LOGDRV]; 126 smrt_report_logical_lun_extent_t extents[SMRT_MAX_LOGDRV]; 127 } smrll_data; 128 } smrt_report_logical_lun_t; 129 130 typedef struct smrt_report_logical_lun_req { 131 uint8_t smrllr_opcode; 132 uint8_t smrllr_extflag; 133 uint8_t smrllr_reserved1[4]; 134 uint32_t smrllr_datasize; /* Big Endian */ 135 uint8_t smrllr_reserved2; 136 uint8_t smrllr_control; 137 } smrt_report_logical_lun_req_t; 138 139 typedef struct smrt_report_physical_lun_ent { 140 PhysDevAddr_t srple_addr; 141 } smrt_report_physical_lun_ent_t; 142 143 /* 144 * This structure represents the 'physical node identifier' extended option for 145 * REPORT PHYSICAL LUNS. This is triggered when the extended flags is set to 146 * 0x1. Note that for SAS the other structure should always be used. 147 */ 148 typedef struct smrt_report_physical_pnid { 149 uint8_t srpp_node[8]; 150 uint8_t srpp_port[8]; 151 } smrt_report_physical_pnid_t; 152 153 /* 154 * This structure represents the 'other physical device info' extended option 155 * for report physical luns. This is triggered when the extended flags is set 156 * to 0x2. 157 */ 158 typedef struct smrt_report_physical_opdi { 159 uint8_t srpo_wwid[8]; 160 uint8_t srpo_dtype; 161 uint8_t srpo_flags; 162 uint8_t srpo_multilun; 163 uint8_t srpo_paths; 164 uint32_t srpo_iohdl; 165 } smrt_report_physical_opdi_t; 166 167 typedef struct smrt_report_physical_lun_extent { 168 PhysDevAddr_t srple_addr; 169 union { 170 smrt_report_physical_pnid_t srple_pnid; 171 smrt_report_physical_opdi_t srple_opdi; 172 } srple_extdata; 173 } smrt_report_physical_lun_extent_t; 174 175 /* 176 * Values that can be ORed together into smrllr_extflag. smprl_extflag indicates 177 * if any extended processing was done or not. 178 */ 179 #define SMRT_REPORT_PHYSICAL_LUN_EXT_NONE 0x00 180 #define SMRT_REPORT_PHYSICAL_LUN_EXT_PNID 0x01 181 #define SMRT_REPORT_PHYSICAL_LUN_EXT_OPDI 0x02 182 #define SMRT_REPORT_PHYSICAL_LUN_EXT_MASK 0x0f 183 #define SMRT_REPORT_PHYSICAL_LUN_CTRL_ONLY (1 << 6) 184 #define SMRT_REPORT_PHYSICAL_LUN_ALL_PATHS (1 << 7) 185 186 typedef struct smrt_report_physical_lun { 187 uint32_t smrpl_datasize; /* Big Endian */ 188 uint8_t smrpl_extflag; 189 uint8_t smrpl_reserved1[3]; 190 union { 191 smrt_report_physical_lun_ent_t ents[SMRT_MAX_PHYSDEV]; 192 smrt_report_physical_lun_extent_t extents[SMRT_MAX_PHYSDEV]; 193 } smrpl_data; 194 } smrt_report_physical_lun_t; 195 196 197 typedef struct smrt_report_physical_lun_req { 198 uint8_t smrplr_opcode; 199 uint8_t smrplr_extflag; 200 uint8_t smrplr_reserved[1]; 201 uint32_t smrplr_datasize; /* Big Endian */ 202 uint8_t smrplr_reserved2; 203 uint8_t smrplr_control; 204 } smrt_report_physical_lun_req_t; 205 206 /* 207 * Request structure for the BMIC command IDENTIFY CONTROLLER. This structure 208 * is written into the CDB with the CISS_SCMD_BMIC_READ SCSI opcode. Reserved 209 * fields should be filled with zeroes. 210 */ 211 typedef struct smrt_identify_controller_req { 212 uint8_t smicr_opcode; 213 uint8_t smicr_lun; 214 uint8_t smicr_reserved1[4]; 215 uint8_t smicr_command; 216 uint8_t smicr_reserved2[2]; 217 uint8_t smicr_reserved3[1]; 218 uint8_t smicr_reserved4[6]; 219 } smrt_identify_controller_req_t; 220 221 /* 222 * Response structure for IDENTIFY CONTROLLER. This structure is used to 223 * interpret the response the controller will write into the data buffer. 224 */ 225 typedef struct smrt_identify_controller { 226 uint8_t smic_logical_drive_count; 227 uint32_t smic_config_signature; 228 uint8_t smic_firmware_rev[4]; 229 uint8_t smic_recovery_rev[4]; 230 uint8_t smic_hardware_version; 231 uint8_t smic_bootblock_rev[4]; 232 233 /* 234 * These are obsolete for SAS controllers: 235 */ 236 uint32_t smic_drive_present_map; 237 uint32_t smic_external_drive_map; 238 239 uint32_t smic_board_id; 240 } smrt_identify_controller_t; 241 242 /* 243 * Request structure for IDENTIFY PHYSICAL DEVICE. This structure is written 244 * into the CDB with the CISS_SCMD_BMIC_READ SCSI opcode. Reserved fields 245 * should be filled with zeroes. Note, the lower 8 bits of the BMIC ID are in 246 * index1, whereas the upper 8 bites are in index2; however, the controller may 247 * only support 8 bits worth of devices (and this driver does not support that 248 * many devices). 249 */ 250 typedef struct smrt_identify_physical_drive_req { 251 uint8_t sipdr_opcode; 252 uint8_t sipdr_lun; 253 uint8_t sipdr_bmic_index1; 254 uint8_t sipdr_reserved1[3]; 255 uint8_t sipdr_command; 256 uint8_t sipdr_reserved2[2]; 257 uint8_t sipdr_bmic_index2; 258 uint8_t sipdr_reserved4[6]; 259 } smrt_identify_physical_drive_req_t; 260 261 /* 262 * Relevant values for the sipd_more_flags member. 263 */ 264 #define SMRT_MORE_FLAGS_LOGVOL (1 << 5) 265 #define SMRT_MORE_FLAGS_SPARE (1 << 6) 266 267 /* 268 * Response structure for IDENTIFY PHYSICAL DEVICE. This structure is used to 269 * describe aspects of a physical drive. Note, not all fields are valid in all 270 * firmware revisions. 271 */ 272 typedef struct smrt_identify_physical_drive { 273 uint8_t sipd_scsi_bus; /* Invalid for SAS */ 274 uint8_t sipd_scsi_id; /* Invalid for SAS */ 275 uint16_t sipd_lblk_size; 276 uint32_t sipd_nblocks; 277 uint32_t sipd_rsrvd_blocsk; 278 uint8_t sipd_model[40]; 279 uint8_t sipd_serial[40]; 280 uint8_t sipd_firmware[8]; 281 uint8_t sipd_scsi_inquiry; 282 uint8_t sipd_compaq_stamp; 283 uint8_t sipd_last_failure; 284 uint8_t sipd_flags; 285 uint8_t sipd_more_flags; 286 uint8_t sipd_scsi_lun; /* Invalid for SAS */ 287 uint8_t sipd_yet_more_flags; 288 uint8_t sipd_even_more_flags; 289 uint32_t sipd_spi_speed_rules; 290 uint8_t sipd_phys_connector[2]; 291 uint8_t sipd_phys_box_on_bus; 292 uint8_t sipd_phys_bay_in_box; 293 uint32_t sipd_rpm; 294 uint8_t sipd_device_type; 295 uint8_t sipd_sata_version; 296 uint64_t sipd_big_nblocks; 297 uint64_t sipd_ris_slba; 298 uint32_t sipd_ris_size; 299 uint8_t sipd_wwid[20]; 300 uint8_t sipd_controller_phy_map[32]; 301 uint16_t sipd_phy_count; 302 uint8_t sipd_phy_connected_dev_type[256]; 303 uint8_t sipd_phy_to_drive_bay[256]; 304 uint16_t sipd_phy_to_attached_dev[256]; 305 uint8_t sipd_box_index; 306 uint8_t sipd_drive_support; 307 uint16_t sipd_extra_flags; 308 uint8_t sipd_neogiated_link_rate[256]; 309 uint8_t sipd_phy_to_phy_map[256]; 310 uint8_t sipd_pad[312]; 311 } smrt_identify_physical_drive_t; 312 313 /* 314 * Note that this structure describes the CISS version of the command. There 315 * also exists a BMIC version, but it has a slightly different structure. This 316 * structure is also used for the cancellation request; however, in that case, 317 * the senr_flags field is reserved. 318 */ 319 typedef struct smrt_event_notify_req { 320 uint8_t senr_opcode; 321 uint8_t senr_subcode; 322 uint8_t senr_reserved1[2]; 323 uint32_t senr_flags; /* Big Endian */ 324 uint32_t senr_size; /* Big Endian */ 325 uint8_t senr_control; 326 } smrt_event_notify_req_t; 327 328 /* 329 * When receiving event notifications, the buffer size must be 512 bytes large. 330 * We make sure that we always allocate a buffer of this size, even though we 331 * define a structure that is much shorter and only uses the fields that we end 332 * up caring about. This size requirement comes from the specification. 333 */ 334 #define SMRT_EVENT_NOTIFY_BUFLEN 512 335 336 #define SMRT_EVENT_CLASS_PROTOCOL 0 337 #define SMRT_EVENT_PROTOCOL_SUBCLASS_ERROR 1 338 339 #define SMRT_EVENT_CLASS_HOTPLUG 1 340 #define SMRT_EVENT_HOTPLUG_SUBCLASS_DRIVE 0 341 342 #define SMRT_EVENT_CLASS_HWERROR 2 343 #define SMRT_EVENT_CLASS_ENVIRONMENT 3 344 345 #define SMRT_EVENT_CLASS_PHYS 4 346 #define SMRT_EVENT_PHYS_SUBCLASS_STATE 0 347 348 #define SMRT_EVENT_CLASS_LOGVOL 5 349 350 typedef struct smrt_event_notify { 351 uint32_t sen_timestamp; 352 uint16_t sen_class; 353 uint16_t sen_subclass; 354 uint16_t sen_detail; 355 uint8_t sen_data[64]; 356 char sen_message[80]; 357 uint32_t sen_tag; 358 uint16_t sen_date; 359 uint16_t sen_year; 360 uint32_t sen_time; 361 uint16_t sen_pre_power_time; 362 LUNAddr_t sen_addr; 363 } smrt_event_notify_t; 364 365 #pragma pack() 366 367 #ifdef __cplusplus 368 } 369 #endif 370 371 #endif /* _SMRT_SCSI_H */ 372