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 * Enclosure Services Device target driver
23 *
24 * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
25 * Use is subject to license terms.
26 */
27
28#ifndef _SYS_SCSI_TARGETS_SES_H
29#define	_SYS_SCSI_TARGETS_SES_H
30
31#include <sys/note.h>
32
33#ifdef	__cplusplus
34extern "C" {
35#endif
36
37
38/*
39 * Useful defines and typedefs
40 */
41#define	EOK			0
42
43#define	INVOP			0x10
44
45#define	BP_PKT(bp)		((struct scsi_pkt *)(bp)->av_back)
46#define	SET_BP_PKT(bp, s)	(bp)->av_back = (struct buf *)(s)
47
48#define	SCBP(pkt)		((struct scsi_status *)(pkt)->pkt_scbp)
49#define	SCBP_C(pkt)		((*(pkt)->pkt_scbp) & STATUS_MASK)
50#define	Scsidevp		struct scsi_device *
51#define	Scsipktp		struct scsi_pkt *
52#define	Uscmd			struct uscsi_cmd
53
54#define	SES_SCSI_DEVP		(un->ses_scsi_devp)
55#define	SES_DEVP(softc)		((softc)->ses_devp)
56#define	SES_DEVINFO(softc)	(SES_DEVP(softc)->sd_dev)
57#define	SES_RQSENSE(softc)	(SES_DEVP(softc)->sd_sense)
58#define	SES_ROUTE(softc)	(&SES_DEVP(softc)->sd_address)
59#define	SES_MUTEX		(&ssc->ses_devp->sd_mutex)
60
61#define	ISOPEN(softc)		((softc)->ses_lyropen || (softc)->ses_oflag)
62#define	UNUSED_PARAMETER(x)	x = x
63
64
65/*
66 * SAF-TE specific defines- Mandatory ones only...
67 */
68
69/*
70 * READ BUFFER ('get' commands) IDs- placed in offset 2 of cdb
71 */
72#define	SAFTE_RD_RDCFG	0x00	/* read enclosure configuration */
73#define	SAFTE_RD_RDESTS	0x01	/* read enclosure status */
74#define	SAFTE_RD_RDDSTS	0x04	/* read drive slot status */
75
76/*
77 * WRITE BUFFER ('set' commands) IDs- placed in offset 0 of databuf
78 */
79#define	SAFTE_WT_DSTAT	0x10	/* write device slot status */
80#define	SAFTE_WT_SLTOP	0x12	/* perform slot operation */
81#define	SAFTE_WT_FANSPD	0x13	/* set fan speed */
82#define	SAFTE_WT_ACTPWS	0x14	/* turn on/off power supply */
83#define	SAFTE_WT_GLOBAL	0x15	/* send global command */
84
85
86/*
87 * Includes
88 */
89#include <sys/scsi/targets/sesio.h>
90
91
92/*
93 * Private info (Device Info. Private)
94 *
95 * Pointed to by the un_private pointer
96 * of one of the SCSI_DEVICE structures.
97 */
98typedef struct ses_softc ses_softc_t;
99
100typedef struct {
101	int (*softc_init)(ses_softc_t *, int);
102	int (*init_enc)(ses_softc_t *);
103	int (*get_encstat)(ses_softc_t *, int);
104	int (*set_encstat)(ses_softc_t *, uchar_t, int);
105	int (*get_objstat)(ses_softc_t *, ses_objarg *, int);
106	int (*set_objstat)(ses_softc_t *, ses_objarg *, int);
107} encvec;
108
109typedef enum { SES_TYPE, SAFT_TYPE, SEN_TYPE } enctyp;
110
111typedef struct {
112	uchar_t		enctype;	/* enclosure type */
113	uchar_t		subenclosure;	/* subenclosure id */
114	ushort_t	svalid	: 1,	/* enclosure information valid */
115			priv	: 15;	/* private data, per object */
116	uchar_t		encstat[4];	/* state && stats */
117} encobj;
118
119#ifndef	__lint				/* no warlock for X86 */
120#ifdef	_KERNEL
121_NOTE(MUTEX_PROTECTS_DATA(scsi_device::sd_mutex, encobj))
122_NOTE(DATA_READABLE_WITHOUT_LOCK(encobj::priv))
123_NOTE(DATA_READABLE_WITHOUT_LOCK(encobj::svalid))
124_NOTE(DATA_READABLE_WITHOUT_LOCK(encobj::enctype))
125_NOTE(DATA_READABLE_WITHOUT_LOCK(encobj::encstat))
126_NOTE(DATA_READABLE_WITHOUT_LOCK(encobj::subenclosure))
127#endif	/* _KERNEL */
128#endif	/* __lint */
129
130
131/*
132 * Overall Status is bits 0..3- status validity reserved at bit 7
133 */
134#define	ENCI_SVALID	0x80
135
136struct ses_softc {
137	enctyp		ses_type;	/* type of enclosure */
138	encvec		ses_vec;	/* vector to handlers */
139	uint_t		ses_nobjects;	/* number of objects */
140	void *		ses_private;	/* private data */
141	encobj *	ses_objmap;	/* objects */
142	uchar_t		ses_encstat;	/* overall status */
143	Scsidevp  	ses_devp;	/* backpointer to owning SCSI device */
144	struct buf 	*ses_rqbp;	/* request sense buf pointer */
145	Scsipktp	ses_rqpkt;	/* SCSI Request Sense Packet */
146	struct buf 	*ses_sbufp;	/* for use in internal io */
147	timeout_id_t	ses_restart_id; /* restart timeout id */
148	kcondvar_t	ses_sbufcv;	/* cv on sbuf */
149	uchar_t		ses_sbufbsy;	/* sbuf busy flag */
150	uchar_t		ses_oflag;	/* nonzero if opened (nonlayered) */
151	uchar_t		ses_present;	/* device present */
152	uchar_t		ses_suspended;	/* nonzero if suspended */
153	uchar_t		ses_arq;	/* auto request sense enabled */
154	uint_t 		ses_lyropen;	/* layered open count */
155	int 		ses_retries;	/* retry count */
156	/*
157	 * Associated storage for the special buf.
158	 * Since we're single threaded on sbuf anyway,
159	 * we might as well save ourselves a pile of
160	 * grief and allocate local uscsicmd and
161	 * ancillary storage here.
162	 */
163	Uscmd		ses_uscsicmd;
164	uchar_t		ses_srqcdb[CDB_SIZE];
165	uchar_t		ses_srqsbuf[MAX_SENSE_LENGTH];
166};
167
168#ifndef	__lint				/* no warlock for X86 */
169#ifdef	_KERNEL
170_NOTE(MUTEX_PROTECTS_DATA(scsi_device::sd_mutex, ses_softc))
171_NOTE(MUTEX_PROTECTS_DATA(scsi_device::sd_mutex, ses_softc::ses_lyropen))
172
173_NOTE(SCHEME_PROTECTS_DATA("not shared", scsi_arq_status))
174_NOTE(SCHEME_PROTECTS_DATA("not shared", ses_softc::ses_restart_id))
175_NOTE(SCHEME_PROTECTS_DATA("not shared", ses_softc::ses_retries))
176_NOTE(SCHEME_PROTECTS_DATA("not shared", ses_softc::ses_present))
177_NOTE(SCHEME_PROTECTS_DATA("not shared", ses_softc::ses_suspended))
178_NOTE(SCHEME_PROTECTS_DATA("stable data",
179	ses_softc::ses_type
180	ses_softc::ses_vec
181	ses_softc::ses_nobjects
182	ses_softc::ses_devp
183	ses_softc::ses_arq))
184
185_NOTE(SCHEME_PROTECTS_DATA("sbufp cv",
186	ses_softc::ses_sbufp
187	ses_softc::ses_rqpkt
188	ses_softc::ses_rqbp
189	ses_softc::ses_sbufbsy
190	ses_softc::ses_uscsicmd
191	ses_softc::ses_srqcdb
192	ses_softc::ses_srqsbuf
193	ses_softc::ses_uscsicmd))
194
195_NOTE(SCHEME_PROTECTS_DATA("unique per pkt", scsi_pkt buf uio scsi_cdb))
196_NOTE(SCHEME_PROTECTS_DATA("unique per pkt", scsi_extended_sense scsi_status))
197_NOTE(SCHEME_PROTECTS_DATA("unique per pkt", uscsi_cmd))
198_NOTE(SCHEME_PROTECTS_DATA("stable data", scsi_device))
199
200_NOTE(DATA_READABLE_WITHOUT_LOCK(ses_softc::ses_encstat))
201_NOTE(DATA_READABLE_WITHOUT_LOCK(ses_softc::ses_objmap))
202_NOTE(DATA_READABLE_WITHOUT_LOCK(ses_softc::ses_private))
203_NOTE(DATA_READABLE_WITHOUT_LOCK(ses_softc::ses_lyropen))
204_NOTE(DATA_READABLE_WITHOUT_LOCK(ses_softc::ses_oflag))
205
206_NOTE(SCHEME_PROTECTS_DATA("absurdities", ses_objarg))
207#endif	/* _KERNEL */
208#endif	/* __lint */
209
210
211/*
212 * Compile options to turn on debugging code
213 */
214#ifdef	DEBUG
215#define	SES_DEBUG
216#endif	/* DEBUG */
217
218#if defined(_KERNEL) || defined(_KMEMUSER)
219
220#define	SES_CE_DEBUG		((1  << 8) | CE_CONT)
221#define	SES_CE_DEBUG1		((2  << 8) | CE_CONT)
222#define	SES_CE_DEBUG2		((3  << 8) | CE_CONT)
223#define	SES_CE_DEBUG3		((4  << 8) | CE_CONT)
224#define	SES_CE_DEBUG4		((5  << 8) | CE_CONT)
225#define	SES_CE_DEBUG5		((6  << 8) | CE_CONT)
226#define	SES_CE_DEBUG6		((7  << 8) | CE_CONT)
227#define	SES_CE_DEBUG7		((8  << 8) | CE_CONT)
228#define	SES_CE_DEBUG8		((9  << 8) | CE_CONT)
229#define	SES_CE_DEBUG9		((10 << 8) | CE_CONT)
230
231#ifndef SES_DEBUG
232#define	ses_debug		0
233#endif	/* SES_DEBUG */
234
235#define	SES_LOG			if (ses_debug) ses_log
236#define	SES_DEBUG_ENTER		if (ses_debug) debug_enter
237
238
239/*
240 * Various I/O timeouts.
241 *
242 * These are hard-coded and not adjustable. The restart macro
243 * time input is in milliseconds with 1 msec. the minimum setting.
244 *
245 */
246#define	SES_IO_TIME		  60 /* standard I/O time (sec.) */
247#define	SES_RESTART_TIME	 100 /* I/O restart time (ms.) */
248#define	SES_BUSY_TIME		500 /* I/O busy restart time (ms.) */
249
250#define	SES_ENABLE_RESTART(ms_time, pkt) { \
251	ssc->ses_restart_id = timeout(ses_restart, (void *) pkt, \
252	    (ms_time)? (drv_usectohz(ms_time * 1000)) : \
253	    drv_usectohz(1000)); \
254}
255
256
257/*
258 * Number of times we'll retry a normal operation.
259 *
260 * Note, retries have differnt weights to max retries.
261 * Unit Attention and request sense have the most retries.
262 * Command retries have the least.
263 *
264 * For no auto-request sense operation, the SES_RETRY_MULTIPLIER
265 * must be greater than the command RETRY_COUNT.  Then the request
266 * sense commands won't impact the command retries.
267 */
268#define	SES_RETRY_COUNT		4
269#define	SES_RETRY_MULTIPLIER	8
270
271#define	SES_CMD_RETRY		SES_RETRY_MULTIPLIER
272#define	SES_NO_RETRY		0
273#define	SES_SENSE_RETRY		1
274#define	SES_BUSY_RETRY		4
275
276/* Retry weight is 1 */
277#define	SES_CMD_RETRY1(retry) \
278	retry += (retry > 0)? (SES_RETRY_MULTIPLIER -1) : 0;
279
280/* Retry weight is 2 */
281#define	SES_CMD_RETRY2(retry) \
282	retry += (retry > 0)? (SES_RETRY_MULTIPLIER -2) : 0;
283
284/* Retry weight is 4 */
285#define	SES_CMD_RETRY4(retry) \
286	retry += (retry > 0)? (SES_RETRY_MULTIPLIER -4) : 0;
287
288
289/*
290 * ses_present definitions
291 */
292#define	SES_CLOSED		0
293#define	SES_OPENING		1
294#define	SES_OPEN		2
295
296
297/*
298 * ses_callback action codes
299 */
300#define	COMMAND_DONE		0
301#define	COMMAND_DONE_ERROR	1
302#define	QUE_COMMAND_NOW		3
303#define	QUE_COMMAND		4
304#define	QUE_SENSE		5
305
306
307/*
308 * PF bit for RECEIVE DIAG command;
309 * needed for RSM first release hw.
310 */
311#define	SCSI_ESI_PF	0x10
312#define	SEN_ID		"UNISYS           SUN_SEN"
313#define	SEN_ID_LEN	24
314
315#define	SET_BP_ERROR(bp, err)	bioerror(bp, err);
316
317/*
318 * Common Driver Functions
319 */
320#if	defined(_KERNEL)
321extern void ses_log(ses_softc_t *, int, const char *, ...);
322extern int ses_runcmd(ses_softc_t *, Uscmd *);
323extern int ses_uscsi_cmd(ses_softc_t *, Uscmd *, int);
324extern int ses_io_time;
325
326#ifdef	DEBUG
327extern int ses_debug;
328#endif /* DEBUG */
329
330#endif	/* defined(_KERNEL) */
331
332
333#endif	/* defined(_KERNEL) || defined(_KMEMUSER) */
334
335#ifdef	__cplusplus
336}
337#endif
338
339#endif	/* _SYS_SCSI_TARGETS_SES_H */
340