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