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