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 2009 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 * Copyright 2017 Nexenta Systems, Inc.
26 */
27
28#ifndef	_SYS_SCSI_GENERIC_MODE_H
29#define	_SYS_SCSI_GENERIC_MODE_H
30
31#ifdef	__cplusplus
32extern "C" {
33#endif
34
35/*
36 *
37 * Defines and Structures for SCSI Mode Sense/Select data - generic
38 *
39 */
40
41/*
42 * Structures and defines common for all device types
43 */
44
45/*
46 * Mode Sense/Select Header - Group 0 (6-byte).
47 *
48 * Mode Sense/Select data consists of a header, followed by zero or more
49 * block descriptors, followed by zero or more mode pages.
50 *
51 */
52
53struct mode_header {
54	uchar_t length;		/* number of bytes following */
55	uchar_t medium_type;	/* device specific */
56	uchar_t device_specific;	/* device specific parameters */
57	uchar_t bdesc_length;	/* length of block descriptor(s), if any */
58};
59
60#define	MODE_HEADER_LENGTH	(sizeof (struct mode_header))
61
62/*
63 * Mode Sense/Select Header - Group 1 (10-bytes)
64 */
65
66struct mode_header_g1 {
67	ushort_t	length;		/* number of bytes following */
68	uchar_t		medium_type;	/* device specific */
69	uchar_t		device_specific;	/* device specific parameters */
70	uchar_t		reserved[2];	/* device specific parameters */
71	ushort_t	bdesc_length;	/* len of block descriptor(s), if any */
72};
73
74#define	MODE_HEADER_LENGTH_G1	(sizeof (struct mode_header_g1))
75
76/*
77 * Block Descriptor. Zero, one, or more may normally follow the mode header.
78 *
79 * The density code is device specific.
80 *
81 * The 24-bit value described by blks_{hi, mid, lo} describes the number of
82 * blocks which this block descriptor applies to. A value of zero means
83 * 'the rest of the blocks on the device'.
84 *
85 * The 24-bit value described by blksize_{hi, mid, lo} describes the blocksize
86 * (in bytes) applicable for this block descriptor. For Sequential Access
87 * devices, if this value is zero, the block size will be derived from
88 * the transfer length in I/O operations.
89 *
90 */
91
92struct block_descriptor {
93	uchar_t density_code;	/* device specific */
94	uchar_t blks_hi;	/* hi  */
95	uchar_t blks_mid;	/* mid */
96	uchar_t blks_lo;	/* low */
97	uchar_t reserved;	/* reserved */
98	uchar_t blksize_hi;	/* hi  */
99	uchar_t blksize_mid;	/* mid */
100	uchar_t blksize_lo;	/* low */
101};
102
103#define	MODE_BLK_DESC_LENGTH	(sizeof (struct block_descriptor))
104#define	MODE_PARAM_LENGTH 	(MODE_HEADER_LENGTH + MODE_BLK_DESC_LENGTH)
105
106/*
107 * Define a macro to take an address of a mode header to the address
108 * of the nth (0..n) block_descriptor, or NULL if there either aren't any
109 * block descriptors or the nth block descriptor doesn't exist.
110 */
111
112#define	BLOCK_DESCRIPTOR_ADDR(mhdr, bdnum) \
113	((mhdr)->bdesc_length && ((unsigned)(bdnum)) < \
114	((mhdr)->bdesc_length/(sizeof (struct block_descriptor)))) ? \
115	((struct block_descriptor *)(((ulong_t)(mhdr))+MODE_HEADER_LENGTH+ \
116	((bdnum) * sizeof (struct block_descriptor)))) : \
117	((struct block_descriptor *)0)
118
119/*
120 * Mode page header. Zero or more Mode Pages follow either the block
121 * descriptors (if any), or the Mode Header.
122 *
123 * The 'ps' bit must be zero for mode select operations.
124 *
125 */
126
127struct mode_page {
128#if defined(_BIT_FIELDS_LTOH)
129	uchar_t	code	:6,	/* page code number */
130			:1,	/* reserved */
131		ps	:1;	/* 'Parameter Saveable' bit */
132#elif defined(_BIT_FIELDS_HTOL)
133	uchar_t	ps	:1,	/* 'Parameter Saveable' bit */
134			:1,	/* reserved */
135		code	:6;	/* page code number */
136#else
137#error	One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
138#endif	/* _BIT_FIELDS_LTOH */
139	uchar_t	length;		/* length of bytes to follow */
140	/*
141	 * Mode Page specific data follows right after this...
142	 */
143};
144
145/*
146 * Define a macro to retrieve the first mode page. Could be more
147 * general (for multiple mode pages).
148 */
149
150#define	MODE_PAGE_ADDR(mhdr, type)	\
151	((type *)(((ulong_t)(mhdr))+MODE_HEADER_LENGTH+(mhdr)->bdesc_length))
152
153/*
154 * Page Control field (bits 7 and 6) follows the following specification:
155 *
156 * 	Value			Meaning
157 * 	----------------------------------------------------------------------
158 * 	00b			current values
159 * 	01b			changeable values
160 * 	10b			default values
161 * 	11b			saved values
162 */
163
164#define	MODEPAGE_CURRENT	0x00
165#define	MODEPAGE_CHANGEABLE	0x40
166#define	MODEPAGE_DEFAULT	0x80
167#define	MODEPAGE_SAVED		0xC0
168
169/*
170 * Page codes follow the following specification:
171 *
172 *	Code Value(s)		What
173 *	----------------------------------------------------------------------
174 *	0x00			Vendor Unique (does not require page format)
175 *
176 *	0x02, 0x09, 0x0A	pages for all Device Types
177 *	0x1A, 0x1C
178 *
179 *	0x01, 0x03-0x08,	pages for specific Device Type
180 *	0x0B-0x19, 0x1B,
181 *	0x1D-0x1F
182 *
183 *	0x20-0x3E		Vendor Unique (requires page format)
184 *
185 *	0x3F			Return all pages (valid for Mode Sense only)
186 *
187 */
188
189/*
190 * Page codes and page length values (all device types)
191 */
192
193#define	MODEPAGE_DISCO_RECO	0x02
194#define	MODEPAGE_FORMAT		0x03
195#define	MODEPAGE_GEOMETRY	0x04
196#define	MODEPAGE_CACHING	0x08
197#define	MODEPAGE_PDEVICE	0x09
198#define	MODEPAGE_CTRL_MODE	0x0A
199#define	MODEPAGE_POWER_COND	0x1A
200#define	MODEPAGE_INFO_EXCPT	0x1C
201
202#define	MODEPAGE_ALLPAGES	0x3F
203
204/*
205 * Mode Select/Sense page structures (for all device types)
206 */
207
208/*
209 * Disconnect/Reconnect Page
210 */
211
212struct mode_disco_reco {
213	struct	mode_page mode_page;	/* common mode page header */
214	uchar_t	buffer_full_ratio;	/* write, how full before reconnect? */
215	uchar_t	buffer_empty_ratio;	/* read, how full before reconnect? */
216	ushort_t bus_inactivity_limit;	/* how much bus quiet time for BSY- */
217	ushort_t disconect_time_limit;	/* min to remain disconnected */
218	ushort_t connect_time_limit;	/* min to remain connected */
219	ushort_t max_burst_size;	/* max data burst size */
220#if defined(_BIT_FIELDS_LTOH)
221	uchar_t		dtdc	: 3,	/* data transfer disconenct control */
222			dimm	: 1,	/* disconnect immediate */
223			fastat	: 1,	/* fair for status */
224			fawrt	: 1,	/* fair for write */
225			fard	: 1,	/* fair for read */
226			emdp	: 1;	/* enable modify data pointers */
227#elif defined(_BIT_FIELDS_HTOL)
228	uchar_t		emdp	: 1,	/* enable modify data pointers */
229			fard	: 1,	/* fair for read */
230			fawrt	: 1,	/* fair for write */
231			fastat	: 1,	/* fair for status */
232			dimm	: 1,	/* disconnect immediate */
233			dtdc	: 3;	/* data transfer disconenct control */
234#else
235#error	One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
236#endif	/* _BIT_FIELDS_LTOH */
237	uchar_t	reserved;
238	ushort_t first_burst_sz;	/* first burst size */
239};
240
241#define	DTDC_DATADONE	0x01
242					/*
243					 * Target may not disconnect once
244					 * data transfer is started until
245					 * all data successfully transferred.
246					 */
247
248#define	DTDC_CMDDONE	0x03
249					/*
250					 * Target may not disconnect once
251					 * data transfer is started until
252					 * command completed.
253					 */
254/*
255 * Caching Page
256 */
257
258struct mode_caching {
259	struct	mode_page mode_page;	/* common mode page header */
260#if defined(_BIT_FIELDS_LTOH)
261	uchar_t	rcd		: 1,	/* Read Cache Disable */
262		mf		: 1,	/* Multiplication Factor */
263		wce		: 1,	/* Write Cache Enable */
264				: 5;	/* Reserved */
265	uchar_t	write_ret_prio	: 4,	/* Write Retention Priority */
266		dmd_rd_ret_prio	: 4;	/* Demand Read Retention Priority */
267#elif defined(_BIT_FIELDS_HTOL)
268	uchar_t			: 5,	/* Reserved */
269		wce		: 1,	/* Write Cache Enable */
270		mf		: 1,	/* Multiplication Factor */
271		rcd		: 1;	/* Read Cache Disable */
272	uchar_t	dmd_rd_ret_prio	: 4,	/* Demand Read Retention Priority */
273		write_ret_prio	: 4;	/* Write Retention Priority */
274#else
275#error	One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
276#endif	/* _BIT_FIELDS_LTOH */
277	ushort_t pf_dsbl_trans_len;	/* Disable prefetch transfer length */
278	ushort_t min_prefetch;		/* Minimum Prefetch */
279	ushort_t max_prefetch;		/* Maximum Prefetch */
280	ushort_t max_prefetch_ceiling;	/* Maximum Prefetch Ceiling */
281};
282
283/*
284 * Peripheral Device Page
285 */
286
287struct mode_pdevice {
288	struct	mode_page mode_page;	/* common mode page header */
289	ushort_t if_ident;		/* interface identifier */
290	uchar_t	reserved[4];		/* reserved */
291	uchar_t	vendor_uniqe[1];	/* vendor unique data */
292};
293
294#define	PDEV_SCSI	0x0000		/* scsi interface */
295#define	PDEV_SMD	0x0001		/* SMD interface */
296#define	PDEV_ESDI	0x0002		/* ESDI interface */
297#define	PDEV_IPI2	0x0003		/* IPI-2 interface */
298#define	PDEV_IPI3	0x0004		/* IPI-3 interface */
299
300/*
301 * Control Mode Page
302 *
303 * Note:	This structure is incompatible with previous SCSI
304 *		implementations. See <scsi/impl/mode.h> for an
305 *		alternative form of this structure. They can be
306 *		distinguished by the length of data returned
307 *		from a MODE SENSE command.
308 */
309
310#define	PAGELENGTH_MODE_CONTROL_SCSI3	0x0A
311
312struct mode_control_scsi3 {
313	struct	mode_page mode_page;	/* common mode page header */
314#if defined(_BIT_FIELDS_LTOH)
315	uchar_t		rlec	: 1,	/* Report Log Exception bit */
316			gltsd	: 1,	/* global logging target save disable */
317			d_sense	: 1,	/* Use descriptor sense data (SPC-3) */
318				: 5;
319	uchar_t		qdisable: 1,	/* Queue disable */
320			que_err	: 1,	/* Queue error */
321				: 2,
322			que_mod : 4;    /* Queue algorithm modifier */
323	uchar_t		eanp	: 1,	/* Enable AEN permission */
324			uaaenp  : 1,	/* Unit attention AEN permission */
325			raenp   : 1,	/* Ready AEN permission */
326				: 1,
327			bybths	: 1,	/* By both RESET signal */
328			byprtm	: 1,	/* By port message */
329			rac	: 1,	/* report a check */
330			eeca	: 1;	/* enable extended contingent */
331					/* allegiance (only pre-SCSI-3) */
332#elif defined(_BIT_FIELDS_HTOL)
333	uchar_t			: 5,
334			d_sense	: 1,	/* Use descriptor sense data (SPC-3) */
335			gltsd	: 1,	/* global logging target save disable */
336			rlec	: 1;	/* Report Log Exception bit */
337	uchar_t		que_mod	: 4,	/* Queue algorithm modifier */
338				: 2,
339			que_err	: 1,	/* Queue error */
340			qdisable: 1;	/* Queue disable */
341	uchar_t		eeca	: 1,	/* enable extended contingent */
342					/* allegiance (only pre-SCSI-3) */
343			rac	: 1,	/* report a check */
344			byprtm	: 1,	/* By port message */
345			bybths	: 1,	/* By both RESET signal */
346				: 1,
347			raenp   : 1,	/* Ready AEN permission */
348			uaaenp  : 1,	/* Unit attention AEN permission */
349			eanp	: 1;	/* Enable AEN permission */
350#else
351#error	One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
352#endif	/* _BIT_FIELDS_LTOH */
353	uchar_t	reserved;
354	ushort_t ready_aen_holdoff;	/* Ready AEN holdoff period */
355	ushort_t busy_timeout;		/* Busy timeout period */
356	uchar_t	reserved_2[2];
357};
358
359#ifdef __lock_lint
360_NOTE(SCHEME_PROTECTS_DATA("Unshared SCSI payload", \
361	mode_control_scsi3))
362#endif
363
364#define	CTRL_QMOD_RESTRICT	0x0
365#define	CTRL_QMOD_UNRESTRICT	0x1
366
367/*
368 * Informational Exceptions Control Mode Page
369 */
370
371#define	PAGELENGTH_INFO_EXCPT	0x0A
372
373struct mode_info_excpt_page {
374	struct	mode_page mode_page;	/* common mode page header */
375#if defined(_BIT_FIELDS_LTOH)
376	uchar_t		log_err	: 1;	/* log errors */
377	uchar_t			: 1;	/* reserved */
378	uchar_t		test	: 1;	/* create test failure */
379	uchar_t		dexcpt	: 1;	/* disable exception */
380	uchar_t		ewasc	: 1;	/* enable warning */
381	uchar_t		ebf	: 1;	/* enable background function */
382	uchar_t			: 1;	/* reserved */
383	uchar_t		perf	: 1;	/* performance */
384	uchar_t		mrie	: 4;	/* method of reporting info. excpts. */
385	uchar_t			: 4;	/* reserved */
386#elif defined(_BIT_FIELDS_HTOL)
387	uchar_t		perf	: 1;	/* performance */
388	uchar_t			: 1;	/* reserved */
389	uchar_t		ebf	: 1;	/* enable background function */
390	uchar_t		ewasc	: 1;	/* enable warning */
391	uchar_t		dexcpt	: 1;	/* disable exception */
392	uchar_t		test	: 1;	/* create test failure */
393	uchar_t			: 1;	/* reserved */
394	uchar_t		log_err	: 1;	/* log errors */
395	uchar_t			: 4;	/* reserved */
396	uchar_t		mrie	: 4;	/* method of reporting info. excpts. */
397#else
398#error	One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
399#endif
400	uchar_t	interval_timer[4];	/* interval timer */
401	uchar_t	report_count[4];	/* report count */
402};
403
404#define	MRIE_NO_REPORT		0x0
405#define	MRIE_ASYNCH		0x1
406#define	MRIE_UNIT_ATTN		0x2
407#define	MRIE_COND_RECVD_ERR	0x3
408#define	MRIE_UNCOND_RECVD_ERR	0x4
409#define	MRIE_NO_SENSE		0x5
410#define	MRIE_ONLY_ON_REQUEST	0x6
411
412struct mode_info_power_cond {
413	struct mode_page mode_page;	/* common mode page header */
414	uchar_t reserved;
415#if defined(_BIT_FIELDS_LTOH)
416	uchar_t standby	:1,	/* standby bit */
417		idle	:1,	/* idle bit */
418			:6;	/* reserved */
419#elif defined(_BIT_FIELDS_HTOL)
420	uchar_t		:6,	/* reserved */
421		idle	:1,	/* idle bit */
422		standby	:1;	/* standby bit */
423#else
424#error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
425#endif
426	uchar_t	idle_cond_timer_high;
427	uchar_t idle_cond_timer_low;
428	uchar_t standby_cond_timer[4];
429};
430
431struct parameter_control {
432#if defined(_BIT_FIELDS_LTOH)
433	uchar_t fmt_link:2,	/* format and link bit */
434		tmc	:2,	/* tmc bit */
435		etc	:1,	/* etc bit */
436		tsd	:1,	/* tsd bit */
437		reserv	:1,	/* obsolete */
438		du	:1;	/* du bit */
439#elif defined(_BIT_FIELDS_HTOL)
440	uchar_t	du	:1,	/* du bit */
441		reserv	:1,	/* obsolete */
442		tsd	:1,	/* tsd bit */
443		etc	:1,	/* etc bit */
444		tmc	:2,	/* tmc bit */
445		fmt_link:2;	/* format and link bit */
446#else
447#error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
448#endif
449};
450
451struct start_stop_cycle_counter_log {
452#if defined(_BIT_FIELDS_LTOH)
453	uchar_t code	:6,	/* page code bit */
454		spf	:1,	/* spf bit */
455		ds	:1;	/* ds bit */
456#elif defined(_BIT_FIELDS_HTOL)
457	uchar_t	ds	:1,	/* ds bit */
458		spf	:1,	/* spf bit */
459		code	:6;	/* page code bit */
460#else
461#error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
462#endif
463	uchar_t			sub_page_code;
464	uchar_t			page_len_high;
465	uchar_t			page_len_low;
466
467	uchar_t			manufactor_date_high;
468	uchar_t			manufactor_date_low;
469	struct parameter_control param_1;
470	uchar_t			param_len_1;
471	uchar_t			year_manu[4];
472	uchar_t			week_manu[2];
473
474	uchar_t			account_date_high;
475	uchar_t			account_date_low;
476	struct parameter_control param_2;
477	uchar_t			param_len_2;
478	uchar_t			year_account[4];
479	uchar_t			week_account[2];
480
481	uchar_t			lifetime_code_high;
482	uchar_t			lifetime_code_low;
483	struct parameter_control param_3;
484	uchar_t			param_len_3;
485	uchar_t			cycle_lifetime[4];
486
487	uchar_t			cycle_code_high;
488	uchar_t			cycle_code_low;
489	struct parameter_control param_4;
490	uchar_t			param_len_4;
491	uchar_t			cycle_accumulated[4];
492};
493
494
495#ifdef	__cplusplus
496}
497#endif
498
499/*
500 * Include known generic device specific mode definitions and structures
501 */
502
503#include <sys/scsi/generic/dad_mode.h>
504
505/*
506 * Include implementation specific mode information
507 */
508
509#include <sys/scsi/impl/mode.h>
510
511#endif	/* _SYS_SCSI_GENERIC_MODE_H */
512