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