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