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 /*
  23  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 
  27 #ifndef _T10_SPC_H
  28 #define _T10_SPC_H
  29 
  30 #pragma ident   "%Z%%M% %I%     %E% SMI"
  31 
  32 #ifdef __cplusplus
  33 extern "C" {
  34 #endif
  35 
  36 /*
  37  * []------------------------------------------------------------------[]
  38  * | SPC-3                                                              |
  39  * []------------------------------------------------------------------[]
  40  */
  41 
  42 /*
  43  * FIXED_SENSE_ADDL_INFO_LEN is the length of INFORMATION field
  44  * in fixed format sense data
  45  */
  46 #define FIXED_SENSE_ADDL_INFO_LEN 0xFFFFFFFF
  47 #define INFORMATION_SENSE_DESCR sizeof (struct scsi_information_sense_descr)
  48 
  49 #include <sys/scsi/generic/inquiry.h>
  50 #include <sys/scsi/generic/mode.h>
  51 
  52 /*
  53  * SPC Command Functions
  54  */
  55 void spc_tur(struct t10_cmd *cmd, uint8_t *cdb, size_t cdb_len);
  56 void spc_request_sense(struct t10_cmd *cmd, uint8_t *cdb, size_t cdb_len);
  57 void spc_unsupported(struct t10_cmd *cmd, uint8_t *cdb, size_t cdb_len);
  58 void spc_inquiry(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len);
  59 void spc_mselect(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len);
  60 void spc_mselect_data(t10_cmd_t *cmd, emul_handle_t id, size_t offset,
  61     char *data, size_t data_len);
  62 void spc_report_luns(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len);
  63 void spc_report_tpgs(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len);
  64 void spc_msense(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len);
  65 void spc_startstop(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len);
  66 void spc_send_diag(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len);
  67 
  68 /*
  69  * SPC Support Functions
  70  */
  71 void spc_cmd_offline(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len);
  72 void spc_sense_create(struct t10_cmd *cmd, int sense_key, int addl_sense_len);
  73 void spc_sense_ascq(struct t10_cmd *cmd, int asc, int ascq);
  74 void spc_sense_info(t10_cmd_t *cmd, uint64_t info);
  75 void spc_sense_flags(t10_cmd_t *cmd, int flags);
  76 void spc_sense_raw(t10_cmd_t *cmd, uchar_t *sense_buf, size_t sense_len);
  77 Boolean_t spc_decode_lu_addr(uint8_t *buf, int len, uint32_t *val);
  78 Boolean_t spc_encode_lu_addr(uint8_t *buf, int select_field, uint32_t lun);
  79 
  80 /*
  81  * SPC flags to use when setting various sense code flags
  82  */
  83 #define SPC_SENSE_EOM   0x01
  84 #define SPC_SENSE_FM    0x02
  85 #define SPC_SENSE_ILI   0x04
  86 
  87 #ifdef _BIG_ENDIAN
  88 #define htonll(x)   (x)
  89 #define ntohll(x)   (x)
  90 #else
  91 #define htonll(x)   ((((unsigned long long)htonl(x & 0xffffffff)) << 32) + \
  92                     htonl(x >> 32))
  93 #define ntohll(x)   ((((unsigned long long)ntohl(x)) << 32) + ntohl(x >> 32))
  94 #endif
  95 
  96 /*
  97  * []------------------------------------------------------------------[]
  98  * | SPC-3, revision 21c -- ASC/ASCQ values                             |
  99  * | The full tables can be found in Appendix D (numerical order) or    |
 100  * | section 4.5.6 (alphabetical order). There are close to fifteen     |
 101  * | pages of values which will not be included here. Only those used   |
 102  * | by the code.                                                       |
 103  * []------------------------------------------------------------------[]
 104  */
 105 #define SPC_ASC_FM_DETECTED     0x00 /* file-mark detected */
 106 #define SPC_ASCQ_FM_DETECTED    0x01
 107 
 108 #define SPC_ASC_EOP             0x00 /* end-of-partition/medium detected */
 109 #define SPC_ASCQ_EOP            0x02
 110 
 111 #define SPC_ASC_IN_PROG         0x04
 112 #define SPC_ASCQ_IN_PROG        0x07
 113 
 114 #define SPC_ASC_WRITE_ERROR     0x0c
 115 #define SPC_ASCQ_WRITE_ERROR    0x00
 116 
 117 #define SPC_ASC_PARAM_LIST_LEN  0x1a /* Parameter List Length Error */
 118 #define SPC_ASCQ_PARAM_LIST_LEN 0x00
 119 
 120 #define SPC_ASC_MISCOMPARE      0x1d
 121 #define SPC_ASCQ_MISCOMPARE     0x00
 122 
 123 #define SPC_ASC_INVALID_LU      0x20
 124 #define SPC_ASCQ_INVALID_LU     0x09
 125 
 126 #define SPC_ASC_BLOCK_RANGE     0x21
 127 #define SPC_ASCQ_BLOCK_RANGE    0x00
 128 
 129 #define SPC_ASC_INVALID_FIELD_IN_PARAMETER_LIST         0x26
 130 #define SPC_ASCQ_INVALID_FIELD_IN_PARAMETER_LIST        0x00
 131 
 132 #define SPC_ASC_INVALID_CDB     0x24
 133 #define SPC_ASCQ_INVALID_CDB    0x00
 134 
 135 #define SPC_ASC_PARAMETERS_CHANGED      0x2a
 136 #define SPC_ASCQ_RES_PREEMPTED  0x03
 137 #define SPC_ASCQ_RES_RELEASED   0x04
 138 
 139 #define SPC_ASC_PWR_RESET       0x29
 140 #define SPC_ASCQ_PWR_RESET      0x00
 141 
 142 #define SPC_ASC_PWR_ON          0x29
 143 #define SPC_ASCQ_PWR_ON         0x01
 144 
 145 #define SPC_ASC_BUS_RESET       0x29
 146 #define SPC_ASCQ_BUS_RESET      0x02
 147 
 148 #define SPC_ASC_CAP_CHANGE      0x2a
 149 #define SPC_ASCQ_CAP_CHANGE     0x09
 150 
 151 #define SPC_ASC_DATA_PATH       0x41
 152 #define SPC_ASCQ_DATA_PATH      0x00
 153 
 154 #define SPC_ASC_MEMORY_OUT_OF   0x55 /* Auxillary Memory Out Of Space */
 155 #define SPC_ASCQ_MEMORY_OUT_OF  0x00
 156 #define SPC_ASCQ_RESERVATION_FAIL 0x02
 157 
 158 
 159 /*
 160  * []------------------------------------------------------------------[]
 161  * | SAM-3, revision 14, section 5.2 - Command descriptor block (CDB)   |
 162  * |                                                                    |
 163  * | "All CDBs shall contain a CONTROL byte (see table 21). The         |
 164  * | location of the CONTROL byte within a CDB depends on the CDB       |
 165  * | format (see SPC-3)."                                               |
 166  * |                                                                    |
 167  * | bits       meaning                                                 |
 168  * | 6-7        vendor specific (we don't use so must be zero)          |
 169  * | 3-5        reserved must be zero                                   |
 170  * | 2          NACA (currently we don't support so must be zero)       |
 171  * | 1          Obsolete                                                |
 172  * | 0          Link (currently we don't support so must be zero)       |
 173  * |                                                                    |
 174  * | So, this means the control byte must be zero and therefore if      |
 175  * | this macro returns a non-zero value the emulation code should      |
 176  * | return a CHECK CONDITION with status set to ILLEGAL REQUEST        |
 177  * | and the additional sense code set to INVALID FIELD IN CDB.         |
 178  * |                                                                    |
 179  * | In the future this will likely change with support routines        |
 180  * | added for dealing with NACA and Linked commands.                   |
 181  * []------------------------------------------------------------------[]
 182  */
 183 #define SAM_CONTROL_BYTE_RESERVED(byte) (byte)
 184 
 185 /* ---- Disable Block Descriptors ---- */
 186 #define SPC_MODE_SENSE_DBD      0x8
 187 
 188 #define SPC_GROUP4_SERVICE_ACTION_MASK  0x1f
 189 
 190 #define SPC_SEND_DIAG_SELFTEST  0x04
 191 
 192 /*
 193  * []------------------------------------------------------------------[]
 194  * | SPC-3 revision 21c, section 6.4 -- INQUIRY                         |
 195  * | Various defines. The structure for the inquiry command can be      |
 196  * | found in /usr/include/sys/scsi/generic/inquiry.h                   |
 197  * []------------------------------------------------------------------[]
 198  */
 199 #define SPC_INQUIRY_CODE_SET_BINARY     1
 200 #define SPC_INQUIRY_CODE_SET_ASCII      2
 201 #define SPC_INQUIRY_CODE_SET_UTF8       3
 202 
 203 /* ---- Table 82: Inquiry Version ----  */
 204 #define SPC_INQ_VERS_NONE       0x00
 205 #define SPC_INQ_VERS_OBSOLETE   0x02
 206 #define SPC_INQ_VERS_SPC_1      0x03
 207 #define SPC_INQ_VERS_SPC_2      0x04
 208 #define SPC_INQ_VERS_SPC_3      0x05
 209 
 210 /* ---- INQUIRY Response Data Format field ---- */
 211 #define SPC_INQ_RDF             0x02    /* all other values are OBSOLETE */
 212 
 213 /*
 214  * Table 85 -- Version descriptor values
 215  * There are many, many different values available, so we'll only include
 216  * those that we actually use.
 217  */
 218 #define SPC_INQ_VD_SAM3         0x0076
 219 #define SPC_INQ_VD_SPC3         0x0307
 220 #define SPC_INQ_VD_SBC2         0x0322
 221 #define SPC_INQ_VD_SSC3         0x0400
 222 #define SPC_INQ_VD_OSD          0x0355
 223 
 224 /* --- Version Descriptor length details --- */
 225 #define SPC_INQ_VD_IDX          0x3A
 226 #define SPC_INQ_VD_LEN          0x10
 227 
 228 #define SPC_INQ_PAGE0           0x00
 229 #define SPC_INQ_PAGE80          0x80
 230 #define SPC_INQ_PAGE83          0x83
 231 #define SPC_INQ_PAGE86          0x86
 232 
 233 /* ---- REPORT LUNS select report has valid values of 0, 1, or 2 ---- */
 234 #define SPC_RPT_LUNS_SELECT_MASK        0x03
 235 
 236 /* ---- Table 293: IDENTIFIER TYPE field ---- */
 237 #define SPC_INQUIRY_ID_TYPE_T10ID       1       /* ref 7.6.4.3 */
 238 #define SPC_INQUIRY_ID_TYPE_EUI         2       /* ref 7.6.4.4 */
 239 #define SPC_INQUIRY_ID_TYPE_NAA         3       /* ref 7.6.4.5 */
 240 #define SPC_INQUIRY_ID_TYPE_RELATIVE    4       /* ref 7.6.4.6 */
 241 #define SPC_INQUIRY_ID_TYPE_TARG_PORT   5       /* ref 7.6.4.7 */
 242 #define SPC_INQUIRY_ID_TYPE_LUN         6       /* ref 7.6.4.8 */
 243 #define SPC_INQUIRY_ID_TYPE_MD5         7       /* ref 7.6.4.9 */
 244 #define SPC_INQUIRY_ID_TYPE_SCSI        8       /* ref 7.6.4.10 */
 245 
 246 /* ---- Table 292: ASSOCIATION field ----  */
 247 #define SPC_INQUIRY_ASSOC_LUN           0
 248 #define SPC_INQUIRY_ASSOC_TARGPORT      1
 249 #define SPC_INQUIRY_ASSOC_TARG          2
 250 
 251 /* ---- Table 80: Peripheral qualifier ---- */
 252 #define SPC_INQUIRY_PERIPH_CONN         0
 253 #define SPC_INQUIRY_PERIPH_DISCONN      1
 254 #define SPC_INQUIRY_PERIPH_INVALID      3
 255 
 256 /* ---- Table 256: PROTOCOL IDENTIFIER values ---- */
 257 #define SPC_INQUIRY_PROTOCOL_FC         0
 258 #define SPC_INQUIRY_PROTOCOL_PSCSI      1
 259 #define SPC_INQUIRY_PROTOCOL_SSA        2
 260 #define SPC_INQUIRY_PROTOCOL_IEEE1394   3
 261 #define SPC_INQUIRY_PROTOCOL_SCSIRDMA   4
 262 #define SPC_INQUIRY_PROTOCOL_ISCSI      5
 263 #define SPC_INQUIRY_PROTOCOL_SAS        6
 264 #define SPC_INQUIRY_PROTOCOL_ADT        7
 265 #define SPC_INQUIRY_PROTOCOL_ATA        8
 266 
 267 #define SPC_DEFAULT_TPG 1
 268 
 269 /*
 270  * SPC-3, revision 21c, section 7.6.5
 271  * Extended INQUIRY Data VPD page
 272  */
 273 typedef struct extended_inq_data {
 274         struct vpd_hdr  ei_hdr;
 275 #if defined(_BIT_FIELDS_LTOH)
 276         uchar_t         ei_ref_chk      : 1,
 277                         ei_app_chk      : 1,
 278                         ei_grd_chk      : 1,
 279                         ei_rto          : 1,
 280                         ei_rsvd1        : 4;
 281         uchar_t         ei_simpsup      : 1,
 282                         ei_ordsup       : 1,
 283                         ei_headsup      : 1,
 284                         ei_prior_sup    : 1,
 285                         ei_group_sup    : 1,
 286                         ei_rsvd2        : 3;
 287         uchar_t         ei_v_sup        : 1,
 288                         ei_nv_sup       : 1,
 289                         ei_rsvd3        : 6;
 290 #elif defined(_BIT_FIELDS_HTOL)
 291         uchar_t         ei_ref_rsvd1    : 4,
 292                         ei_rto          : 1,
 293                         ei_grd_chk      : 1,
 294                         ei_app_chk      : 1,
 295                         ei_ref_chk      : 1;
 296         uchar_t         ei_rsvd2        : 2,
 297                         ei_group_sup    : 1,
 298                         ei_prior_sup    : 1,
 299                         ei_headsup      : 1,
 300                         ei_ordsup       : 1,
 301                         ei_simpsup      : 1;
 302         uchar_t         ei_rsvd3        : 6,
 303                         ei_nv_sup       : 1,
 304                         ei_v_sup        : 1;
 305 #else
 306 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
 307 #endif
 308         uchar_t         ei_rsv4[57];
 309 } extended_inq_data_t;
 310 
 311 
 312 /*
 313  * []------------------------------------------------------------------[]
 314  * | SPC-4 revision 1a, section 6.25 -- REPORT TARGET PORT GROUPS       |
 315  * | Structures and defines                                             |
 316  * []------------------------------------------------------------------[]
 317  */
 318 /*
 319  * The service action must be set to 0x0A. This command is really a
 320  * MAINTENANCE_IN command with a specific service action.
 321  */
 322 #define SPC_MI_SVC_MASK         0x1f
 323 #define SPC_MI_SVC_RTPG         0x0a
 324 
 325 /* ---- Table 167: Target port descriptor format ---- */
 326 typedef struct rtpg_targ_desc {
 327         uchar_t         obsolete[2],
 328                         rel_tpi[2];
 329 } rtpg_targ_desc_t;
 330 
 331 /* ---- Table 164: Target port group descript format ---- */
 332 typedef struct rtpg_desc {
 333 #if defined(_BIT_FIELDS_LTOH)
 334         uchar_t access_state    : 4,
 335                                 : 3,
 336                 pref            : 1;
 337         uchar_t ao_sup          : 1,
 338                 an_sup          : 1,
 339                 s_sup           : 1,
 340                 u_sup           : 1,
 341                                 : 3,
 342                 t_sup           : 1;
 343 #elif defined(_BIT_FIELDS_HTOL)
 344         uchar_t pref            : 1,
 345                                 : 3,
 346                 access_state    : 4;
 347         uchar_t t_sup           : 1,
 348                                 : 3,
 349                 u_sup           : 1,
 350                 s_sup           : 1,
 351                 an_sup          : 1,
 352                 ao_sup          : 1;
 353 #else
 354 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
 355 #endif
 356         uchar_t                 tpg[2],
 357                                 reserve_1,
 358                                 status_code,
 359                                 vendor_spec,
 360                                 tpg_cnt;
 361         rtpg_targ_desc_t        targ_list[1];
 362 } rtpg_desc_t;
 363 
 364 /* ---- Table 163: parameter data format. ---- */
 365 typedef struct rtpg_data {
 366         uchar_t         len[4];
 367         rtpg_desc_t     desc_list[1];
 368 } rtpg_hdr_t;
 369 
 370 /*
 371  * []------------------------------------------------------------------[]
 372  * | SPC-3, revision 21c, section 6.6 -- LOG_SENSE                      |
 373  * | Structure and defines                                              |
 374  * []------------------------------------------------------------------[]
 375  */
 376 #define SSC_LOG_SP              0x01 /* save parameters */
 377 #define SSC_LOG_PPC             0x02 /* parameter pointer control */
 378 #define SPC_LOG_PAGE_MASK       0x3f
 379 
 380 /* ---- section 7.2.1, Table 192: Log Parameter ---- */
 381 typedef struct spc_log_select_param {
 382         char    param_code[2];
 383 #if defined(_BIT_FIELDS_LTOH)
 384         char    lp      : 1,    /* list parameter */
 385                 lbin    : 1,
 386                 tmc     : 2,    /* threshold met criteria */
 387                 etc     : 1,    /* enable threshold comparison */
 388                 tsd     : 1,    /* target save disable */
 389                 ds      : 1,    /* disable save */
 390                 du      : 1;    /* disable update */
 391 #elif defined(_BIT_FIELDS_HTOL)
 392         char    du      : 1,    /* disable update */
 393                 ds      : 1,    /* disable save */
 394                 tsd     : 1,    /* target save disable */
 395                 etc     : 1,    /* enable threshold comparison */
 396                 tmc     : 2,    /* threshold met criteria */
 397                 lbin    : 1,
 398                 lp      : 1;    /* list parameter */
 399 #else
 400 #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
 401 #endif
 402         char    len;            /* length of bytes to follow */
 403 } spc_log_select_param_t;
 404 
 405 /* ---- section 7.2.12, table 218: Supported log pages ---- */
 406 typedef struct spc_log_supported_pages {
 407         char    page_code,
 408                 resvd,
 409                 length[2],
 410                 list[1];
 411 } spc_log_supported_pages_t;
 412 
 413 /*
 414  * []------------------------------------------------------------------[]
 415  * | SPC-3, revision 21c, section 6.9 -- MODE_SENSE                     |
 416  * | Structures and defines                                             |
 417  * []------------------------------------------------------------------[]
 418  */
 419 /* ---- Section 7.4.6, Table 241: Queue Algorithm Modifer field ---- */
 420 #define SPC_QUEUE_RESTRICTED            0x00
 421 #define SPC_QUEUE_UNRESTRICTED          0x01
 422 
 423 /* ---- Section 7.4.11, Table 250: Information Controller Page ---- */
 424 struct mode_info_ctrl {
 425         struct mode_page        mode_page;
 426         /*
 427          * Currently we don't sent any of this information and it's set
 428          * to zero's. We only care about the size.
 429          */
 430         char                    info_data[10];
 431 };
 432 
 433 #define MODE_SENSE_PAGE3_CODE           0x03
 434 #define MODE_SENSE_PAGE4_CODE           0x04
 435 #define MODE_SENSE_CACHE                0x08
 436 #define MODE_SENSE_CONTROL              0x0a
 437 #define MODE_SENSE_COMPRESSION          0x0f
 438 #define MODE_SENSE_DEV_CONFIG           0x10
 439 #define MODE_SENSE_INFO_CTRL            0x1c
 440 #define MODE_SENSE_SEND_ALL             0x3f
 441 
 442 /* -- Page Control Mask for Mode Sense -- */
 443 #define SPC_MODE_SENSE_PAGE_CODE_MASK   0x3f
 444 #define SPC_MODE_SENSE_PC_MASK          0xc0
 445 #define SPC_MODE_SENSE_PC_SHIFT         6
 446 
 447 #define SPC_PC_CURRENT_VALUES           0
 448 #define SPC_PC_MODIFIABLE_VALUES        1
 449 #define SPC_PC_DEFAULT_VALUES           2
 450 #define SPC_PC_SAVED_VALUES             3
 451 
 452 #define SCSI_REPORTLUNS_ADDRESS_SIZE                    8
 453 #define SCSI_REPORTLUNS_ADDRESS_MASK                    0xC0
 454 #define SCSI_REPORTLUNS_ADDRESS_PERIPHERAL              0x00
 455 #define SCSI_REPORTLUNS_ADDRESS_FLAT_SPACE              0x40
 456 #define SCSI_REPORTLUNS_ADDRESS_LOGICAL_UNIT            0x80
 457 #define SCSI_REPORTLUNS_ADDRESS_EXTENDED_UNIT           0xC0
 458 #define SCSI_REPORTLUNS_ADDRESS_EXTENDED_2B             0x00
 459 #define SCSI_REPORTLUNS_ADDRESS_EXTENDED_4B             0x10
 460 #define SCSI_REPORTLUNS_ADDRESS_EXTENDED_6B             0x20
 461 #define SCSI_REPORTLUNS_ADDRESS_EXTENDED_8B             0x30
 462 #define SCSI_REPORTLUNS_ADDRESS_EXTENDED_MASK           0x30
 463 #define SCSI_REPORTLUNS_SELECT_ALL                      0x02
 464 
 465 #ifdef __cplusplus
 466 }
 467 #endif
 468 
 469 #endif /* _T10_SPC_H */