1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 * Copyright 2016 Nexenta Systems, Inc. All rights reserved. 25 */ 26 27 #ifndef _DS_SCSI_H 28 #define _DS_SCSI_H 29 30 #include <sys/types.h> 31 #include <sys/byteorder.h> 32 #include <sys/scsi/scsi.h> 33 34 #include "ds_impl.h" 35 36 #ifdef __cplusplus 37 extern "C" { 38 #endif 39 40 #if !defined(_BIT_FIELDS_LTOH) && !defined(_BIT_FIELDS_HTOL) 41 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined 42 #endif 43 44 /* 45 * Log page structures 46 */ 47 #pragma pack(1) 48 49 typedef struct scsi_log_header { 50 #if defined(_BIT_FIELDS_LTOH) 51 uint8_t lh_code : 6, 52 lh_spf : 1, 53 lh_ds : 1; 54 #else 55 uint8_t lh_ds : 1, 56 lh_spf : 1, 57 lh_code : 6; 58 #endif 59 uint8_t lh_subpage; 60 uint16_t lh_length; 61 } scsi_log_header_t; 62 63 typedef struct scsi_log_parameter_header { 64 uint16_t lph_param; 65 #if defined(_BIT_FIELDS_LTOH) 66 uint8_t lph_lp : 1, 67 lph_lbin : 1, 68 lph_tmc : 2, 69 lph_etc : 1, 70 lph_tsd : 1, 71 lph_ds : 1, 72 lph_du : 1; 73 #else 74 uint8_t lph_du : 1, 75 lph_ds : 1, 76 lph_tsd : 1, 77 lph_etc : 1, 78 lph_tmc : 2, 79 lph_lbin : 1, 80 lph_lp : 1; 81 #endif 82 uint8_t lph_length; 83 } scsi_log_parameter_header_t; 84 85 typedef struct scsi_supported_log_pages { 86 scsi_log_header_t slp_hdr; 87 uchar_t slp_pages[1]; 88 } scsi_supported_log_pages_t; 89 90 typedef struct scsi_ie_log_param { 91 scsi_log_parameter_header_t ie_hdr; 92 uchar_t ie_asc; 93 uchar_t ie_ascq; 94 } scsi_ie_log_param_t; 95 96 /* 97 * The SCSI-3 SPC document states that IE log page (0x2F) parameter 0 98 * must have a length of at least 4 (including the length byte). 99 */ 100 #define LOGPARAM_IE_MIN_LEN 2 /* the asc and ascq fields */ 101 102 #define INVALID_TEMPERATURE 0xff 103 104 #define LOGPARAM_IE 0x0000 105 106 typedef struct scsi_temp_log_param { 107 scsi_log_parameter_header_t t_hdr; 108 uchar_t __reserved; 109 uchar_t t_temp; 110 } scsi_temp_log_param_t; 111 112 typedef struct scsi_selftest_log_param { 113 scsi_log_parameter_header_t st_hdr; 114 #if defined(_BIT_FIELDS_LTOH) 115 uint8_t st_results : 4, 116 __reserved1 : 1, 117 st_testcode : 3; 118 #else 119 uint8_t st_testcode : 3, 120 __reserved1 : 1, 121 st_results : 4; 122 #endif 123 uint8_t st_number; 124 uint16_t st_timestamp; 125 uint64_t st_lba; 126 #if defined(_BIT_FIELDS_LTOH) 127 uint8_t st_sensekey : 4, 128 __reserved2 : 4; 129 #else 130 uint8_t __reserved2 : 4, 131 st_sensekey : 4; 132 #endif 133 uint8_t st_asc; 134 uint8_t st_ascq; 135 uint8_t st_vendor; 136 } scsi_selftest_log_param_t; 137 138 /* The results field of the self-test log parameter */ 139 #define SELFTEST_OK 0x0 140 #define SELFTEST_ABORT_REQUEST 0x1 141 #define SELFTEST_ABORT_OTHER 0x2 142 #define SELFTEST_FAILURE_INCOMPLETE 0x3 143 #define SELFTEST_FAILURE_SEG_UNKNOWN 0x4 144 #define SELFTEST_FAILURE_SEG_FIRST 0x5 145 #define SELFTEST_FAILURE_SEG_SECOND 0x6 146 #define SELFTEST_FAILURE_SEG_OTHER 0x7 147 #define SELFTEST_INPROGRESS 0xf 148 149 #define SELFTEST_COMPLETE(code) \ 150 ((code) == SELFTEST_OK || \ 151 ((code) >= SELFTEST_FAILURE_INCOMPLETE && \ 152 ((code) <= SELFTEST_FAILURE_SEG_OTHER))) 153 154 #define LOGPARAM_TEMP_CURTEMP 0x0000 155 #define LOGPARAM_TEMP_REFTEMP 0x0001 156 157 #define LOGPARAM_TEMP_LEN \ 158 (sizeof (scsi_temp_log_param_t) - \ 159 sizeof (scsi_log_parameter_header_t)) 160 161 /* 162 * Described in SBC3 163 */ 164 typedef struct scsi_ssm_log_param { 165 scsi_log_parameter_header_t ssm_hdr; 166 uint16_t __reserved2; 167 uint8_t __reserved1; 168 uchar_t ssm_prcnt_used; 169 } scsi_ssm_log_param_t; 170 171 #define LOGPARAM_PRCNT_USED 0x0001 172 #define LOGPARAM_PRCNT_USED_PARAM_LEN 0x04 173 #define PRCNT_USED_FAULT_THRSH 90 174 175 /* 176 * Mode sense/select page header information 177 */ 178 typedef struct scsi_ms_header { 179 struct mode_header ms_header; 180 struct block_descriptor ms_descriptor; 181 } scsi_ms_header_t; 182 183 typedef struct scsi_ms_header_g1 { 184 struct mode_header_g1 ms_header; 185 struct block_descriptor ms_descriptor; 186 } scsi_ms_header_g1_t; 187 188 typedef struct scsi_ms_hdrs { 189 int ms_length; 190 union { 191 scsi_ms_header_t g0; 192 scsi_ms_header_g1_t g1; 193 } ms_hdr; 194 } scsi_ms_hdrs_t; 195 196 typedef struct scsi_ie_page { 197 struct mode_page ie_mp; 198 #if defined(_BIT_FIELDS_LTOH) 199 uint8_t ie_logerr : 1, /* Errors should be logged */ 200 __reserved1 : 1, 201 ie_test : 1, /* Enable test gen of IEs */ 202 ie_dexcpt : 1, /* Disable exceptions */ 203 ie_ewasc : 1, /* Enable warning generation */ 204 ie_ebf : 1, /* enable backgrnd functions */ 205 __reserved2 : 1, 206 ie_perf : 1; /* No delays during excptns */ 207 uint8_t ie_mrie : 4, /* Method/reporting excptons */ 208 __reserved3 : 4; 209 #else 210 uint8_t ie_perf : 1, /* No delays during excptons */ 211 __reserved2 : 1, 212 ie_ebf : 1, /* enable background funcs */ 213 ie_ewasc : 1, /* Enable warning generation */ 214 ie_dexcpt : 1, /* Disable exceptions */ 215 ie_test : 1, /* Enable test gen of IEs */ 216 __reserved1 : 1, 217 ie_logerr : 1; /* Errors should be logged */ 218 uint8_t __reserved3 : 4, 219 ie_mrie : 4; /* Method of report excptns */ 220 #endif 221 uint32_t ie_interval_timer; /* reporting interval for IEs */ 222 uint32_t ie_report_count; /* # of times to report an IE */ 223 } scsi_ie_page_t; 224 225 #pragma pack() 226 227 #define MODEPAGE_INFO_EXCPT_LEN (sizeof (scsi_ie_page_t)) 228 229 #define IEC_IE_ENABLED(ies) ((ies).ie_dexcpt == 0) 230 #define IEC_IE_CHANGEABLE(ies) ((ies).ie_dexcpt == 1) 231 #define IEC_MRIE_CHANGEABLE(ies) ((ies).ie_mrie == 0xf) 232 #define IEC_PERF_CHANGEABLE(ies) ((ies).ie_perf == 1) 233 #define IEC_EWASC_CHANGEABLE(ies) ((ies).ie_ewasc == 1) 234 #define IEC_TEST_CHANGEABLE(ies) ((ies).ie_test == 1) 235 #define IEC_RPTCNT_CHANGEABLE(ies) ((ies).ie_report_count == BE_32(0xffffffff)) 236 #define IEC_LOGERR_CHANGEABLE(ies) ((ies).ie_logerr == 1) 237 238 /* 239 * Values for the MRIE field of the informational exceptions control mode page 240 */ 241 #define IE_REPORT_NONE 0 242 #define IE_REPORT_ASYNCH 1 243 #define IE_REPORT_UNIT_ATTN 2 244 #define IE_REPORT_RECOV_ERR_COND 3 245 #define IE_REPORT_RECOV_ERR_ALWAYS 4 246 #define IE_REPORT_NO_SENSE 5 247 #define IE_REPORT_ON_REQUEST 6 248 249 /* 250 * Constants in support of the CONTROL MODE mode page (page 0xA) 251 */ 252 #define MODEPAGE_CTRL_MODE_LEN (sizeof (struct mode_control_scsi3)) 253 #define GLTSD_CHANGEABLE(chg) ((chg).gltsd == 1) 254 255 #define LOGPAGE_SELFTEST_MIN_PARAM_CODE 0x0001 256 #define LOGPAGE_SELFTEST_MAX_PARAM_CODE 0x0014 257 258 #define LOGPAGE_SELFTEST_PARAM_LEN \ 259 ((sizeof (scsi_selftest_log_param_t)) - \ 260 (sizeof (scsi_log_parameter_header_t))) 261 262 /* 263 * Macro to extract the length of a mode sense page 264 * as returned by a target. 265 */ 266 #define MODESENSE_PAGE_LEN(p) (((int)((struct mode_page *)p)->length) + \ 267 sizeof (struct mode_page)) 268 269 /* 270 * Mode Select options 271 */ 272 #define MODE_SELECT_SP 0x01 273 #define MODE_SELECT_PF 0x10 274 275 276 /* 277 * Mode Sense Page Control 278 */ 279 #define PC_CURRENT (0 << 6) 280 #define PC_CHANGEABLE (1 << 6) 281 #define PC_DEFAULT (2 << 6) 282 #define PC_SAVED (3 << 6) 283 284 /* 285 * Log Sense Page Control 286 */ 287 #define PC_CUMULATIVE (1 << 6) 288 289 /* 290 * LOG page codes 291 */ 292 #define LOGPAGE_SUPP_LIST 0x00 293 #define LOGPAGE_TEMP 0x0d 294 #define LOGPAGE_SELFTEST 0x10 295 #define LOGPAGE_IE 0x2f 296 /* Solid State Media log page code */ 297 #define LOGPAGE_SSM 0x11 298 299 /* ASC constants */ 300 #define ASC_INVALID_OPCODE 0x20 301 #define ASC_INVALID_CDB_FIELD 0x24 302 #define ASC_FAILURE_PREDICTION_THRESHOLD_EXCEEDED 0x5d 303 304 /* ASCQ constants */ 305 #define ASCQ_INVALID_OPCODE 0 306 307 /* Error tests */ 308 #define SCSI_INVALID_OPCODE(s, a, aq) \ 309 (((s) == KEY_ILLEGAL_REQUEST) && ((a) == ASC_INVALID_OPCODE) && \ 310 ((aq) == ASCQ_INVALID_OPCODE)) 311 312 #define MODE_PAGE_UNSUPPORTED(s, a, aq) \ 313 (((s) == KEY_ILLEGAL_REQUEST) && ((a) == ASC_INVALID_CDB_FIELD)) 314 315 /* command length to use */ 316 #define MODE_CMD_LEN_UNKNOWN 0 317 #define MODE_CMD_LEN_6 1 318 #define MODE_CMD_LEN_10 2 319 320 /* supported modepages bitmask */ 321 #define MODEPAGE_SUPP_IEC 0x1 322 323 /* supported logpages bitmask */ 324 #define LOGPAGE_SUPP_IE 0x1 325 #define LOGPAGE_SUPP_TEMP 0x2 326 #define LOGPAGE_SUPP_SELFTEST 0x4 327 #define LOGPAGE_SUPP_SSM 0x8 328 329 #define MSG_BUFLEN 256 330 331 /* 332 * For SCSI commands which want to accept arbitrary length responses, we need to 333 * allocate an appropriate sized buffer. The maximum length is USHRT_MAX, 334 * because some devices return nothing if the buffer length is too big. 335 */ 336 #define MAX_BUFLEN(type) (USHRT_MAX - sizeof (type)) 337 338 extern ds_transport_t ds_scsi_uscsi_transport; 339 extern ds_transport_t ds_scsi_sim_transport; 340 341 #ifdef __cplusplus 342 } 343 #endif 344 345 #endif /* _DS_SCSI_H */ 346