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