summaryrefslogtreecommitdiff
path: root/usr/src/lib/fm/libdiskstatus/common/ds_scsi.h
blob: db4ee6d591cba8d12df226ece6c25b53d517b1f4 (plain)
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 */