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