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 */