xref: /onnv-gate/usr/src/uts/common/sys/emul64var.h (revision 85:1bca8d4eab66)
1*85Scth /*
2*85Scth  * CDDL HEADER START
3*85Scth  *
4*85Scth  * The contents of this file are subject to the terms of the
5*85Scth  * Common Development and Distribution License, Version 1.0 only
6*85Scth  * (the "License").  You may not use this file except in compliance
7*85Scth  * with the License.
8*85Scth  *
9*85Scth  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*85Scth  * or http://www.opensolaris.org/os/licensing.
11*85Scth  * See the License for the specific language governing permissions
12*85Scth  * and limitations under the License.
13*85Scth  *
14*85Scth  * When distributing Covered Code, include this CDDL HEADER in each
15*85Scth  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*85Scth  * If applicable, add the following below this CDDL HEADER, with the
17*85Scth  * fields enclosed by brackets "[]" replaced with your own identifying
18*85Scth  * information: Portions Copyright [yyyy] [name of copyright owner]
19*85Scth  *
20*85Scth  * CDDL HEADER END
21*85Scth  */
22*85Scth /*
23*85Scth  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24*85Scth  * Use is subject to license terms.
25*85Scth  */
26*85Scth 
27*85Scth #ifndef _SYS_SCSI_ADAPTERS_EMUL64VAR_H
28*85Scth #define	_SYS_SCSI_ADAPTERS_EMUL64VAR_H
29*85Scth 
30*85Scth #pragma ident	"%Z%%M%	%I%	%E% SMI"
31*85Scth 
32*85Scth #include <sys/avl.h>
33*85Scth #include <sys/note.h>
34*85Scth #include <sys/emul64.h>
35*85Scth 
36*85Scth #ifdef	__cplusplus
37*85Scth extern "C" {
38*85Scth #endif
39*85Scth 
40*85Scth /*
41*85Scth  * Convenient short hand defines
42*85Scth  */
43*85Scth #define	TRUE			 1
44*85Scth #define	FALSE			 0
45*85Scth #define	UNDEFINED		-1
46*85Scth 
47*85Scth #define	CNUM(emul64)		(ddi_get_instance(emul64->emul64_tran.tran_dev))
48*85Scth 
49*85Scth #define	EMUL64_RETRY_DELAY		5
50*85Scth #define	EMUL64_RETRIES		0	/* retry of selections */
51*85Scth #define	EMUL64_INITIAL_SOFT_SPACE	5 /* Used for the softstate_init func */
52*85Scth 
53*85Scth #define	MSW(x)			(int16_t)(((int32_t)x >> 16) & 0xFFFF)
54*85Scth #define	LSW(x)			(int16_t)((int32_t)x & 0xFFFF)
55*85Scth 
56*85Scth #define	TGT(sp)			(CMD2PKT(sp)->pkt_address.a_target)
57*85Scth #define	LUN(sp)			(CMD2PKT(sp)->pkt_address.a_lun)
58*85Scth 
59*85Scth #define	HW_REV(val)		(((val) >>8) & 0xff)
60*85Scth #define	FW_REV(val)		((val) & 0xff)
61*85Scth 
62*85Scth /*
63*85Scth  * max number of LUNs per target
64*85Scth  */
65*85Scth #define	EMUL64_NLUNS_PER_TARGET	32
66*85Scth 
67*85Scth /*
68*85Scth  * Default emul64 scsi-options
69*85Scth  */
70*85Scth #define	EMUL64_DEFAULT_SCSI_OPTIONS					\
71*85Scth 					SCSI_OPTIONS_PARITY	|	\
72*85Scth 					SCSI_OPTIONS_DR		|	\
73*85Scth 					SCSI_OPTIONS_SYNC	|	\
74*85Scth 					SCSI_OPTIONS_TAG	|	\
75*85Scth 					SCSI_OPTIONS_FAST	|	\
76*85Scth 					SCSI_OPTIONS_WIDE
77*85Scth 
78*85Scth /*
79*85Scth  *	Tag reject
80*85Scth  */
81*85Scth #define	TAG_REJECT	28
82*85Scth /*
83*85Scth  * Interrupt actions returned by emul64_i_flag_event()
84*85Scth  */
85*85Scth #define	ACTION_CONTINUE		0	/* Continue */
86*85Scth #define	ACTION_RETURN		1	/* Exit */
87*85Scth #define	ACTION_IGNORE		2	/* Ignore */
88*85Scth 
89*85Scth /*
90*85Scth  * Reset actions for emul64_i_reset_interface()
91*85Scth  */
92*85Scth #define	EMUL64_RESET_BUS_IF_BUSY	0x01 /* reset scsi bus if it is busy */
93*85Scth #define	EMUL64_FORCE_RESET_BUS	0x02	/* reset scsi bus on error reco */
94*85Scth 
95*85Scth 
96*85Scth /*
97*85Scth  * extracting period and offset from emul64_synch
98*85Scth  */
99*85Scth #define	PERIOD_MASK(val)	((val) & 0xff)
100*85Scth #define	OFFSET_MASK(val)	(((val) >>8) & 0xff)
101*85Scth 
102*85Scth /*
103*85Scth  * timeout values
104*85Scth  */
105*85Scth #define	EMUL64_GRACE		10	/* Timeout margin (sec.) */
106*85Scth #define	EMUL64_TIMEOUT_DELAY(secs, delay)	(secs * (1000000 / delay))
107*85Scth 
108*85Scth /*
109*85Scth  * delay time for polling loops
110*85Scth  */
111*85Scth #define	EMUL64_NOINTR_POLL_DELAY_TIME		1000	/* usecs */
112*85Scth 
113*85Scth /*
114*85Scth  * busy wait delay time after chip reset
115*85Scth  */
116*85Scth #define	EMUL64_CHIP_RESET_BUSY_WAIT_TIME		100	/* usecs */
117*85Scth 
118*85Scth /*
119*85Scth  * timeout for EMUL64 coming out of reset
120*85Scth  */
121*85Scth #define	EMUL64_RESET_WAIT				1000	/* ms */
122*85Scth #define	EMUL64_SOFT_RESET_TIME			1	/* second */
123*85Scth 
124*85Scth /*
125*85Scth  * emul64_softstate flags for introducing hot plug
126*85Scth  */
127*85Scth #define	EMUL64_SS_OPEN		0x01
128*85Scth #define	EMUL64_SS_DRAINING		0x02
129*85Scth #define	EMUL64_SS_QUIESCED		0x04
130*85Scth #define	EMUL64_SS_DRAIN_ERROR	0x08
131*85Scth 
132*85Scth /*
133*85Scth  * ioctl command definitions
134*85Scth  */
135*85Scth #ifndef	EMUL64_RESET_TARGET
136*85Scth #define	EMUL64_RESET_TARGET		(('i' << 8) | 0x03)
137*85Scth #endif
138*85Scth 
139*85Scth 
140*85Scth /*
141*85Scth  * Debugging macros
142*85Scth  */
143*85Scth #define	EMUL64_DEBUG	if (emul64debug) emul64_i_log
144*85Scth #define	EMUL64_DEBUG2	if (emul64debug > 1) emul64_i_log
145*85Scth 
146*85Scth 
147*85Scth #define	REQ_TGT_LUN(tgt, lun)			(((tgt) << 8) | (lun))
148*85Scth 
149*85Scth 
150*85Scth #define	RESP_CQ_FLAGS(resp)	((resp->resp_header.cq_flags_seq) & 0xff)
151*85Scth 
152*85Scth 
153*85Scth #define	EMUL64_NDATASEGS		4
154*85Scth 
155*85Scth 
156*85Scth /*
157*85Scth  * translate scsi_pkt flags into EMUL64 request packet flags
158*85Scth  * It would be illegal if two flags are set; the driver does not
159*85Scth  * check for this. Setting NODISCON and a tag flag is harmless.
160*85Scth  */
161*85Scth #define	EMUL64_SET_PKT_FLAGS(scsa_flags, emul64_flags) {		\
162*85Scth 	emul64_flags = (scsa_flags >> 11) & 0xe; /* tags */		\
163*85Scth 	emul64_flags |= (scsa_flags >> 1) & 0x1; /* no disconnect */	\
164*85Scth }
165*85Scth 
166*85Scth /*
167*85Scth  * throttle values for EMUL64 request queue
168*85Scth  */
169*85Scth #define	SHUTDOWN_THROTTLE	-1	/* do not submit any requests */
170*85Scth #define	CLEAR_THROTTLE		(EMUL64_MAX_REQUESTS -1)
171*85Scth 
172*85Scth 
173*85Scth #define	EMUL64_GET_PKT_STATE(state)	((uint32_t)(state >> 8))
174*85Scth #define	EMUL64_GET_PKT_STATS(stats)	((uint32_t)(stats))
175*85Scth 
176*85Scth #define	EMUL64_STAT_NEGOTIATE	0x0080
177*85Scth 
178*85Scth #define	EMUL64_SET_REASON(sp, reason) { \
179*85Scth 	if ((sp) && CMD2PKT(sp)->pkt_reason == CMD_CMPLT) \
180*85Scth 		CMD2PKT(sp)->pkt_reason = (reason); \
181*85Scth }
182*85Scth 
183*85Scth /*
184*85Scth  * mutex short hands
185*85Scth  */
186*85Scth #define	EMUL64_REQ_MUTEX(emul64)	(&emul64->emul64_request_mutex)
187*85Scth #define	EMUL64_RESP_MUTEX(emul64)	(&emul64->emul64_response_mutex)
188*85Scth #define	EMUL64_HOTPLUG_MUTEX(emul64)	(&emul64->emul64_hotplug_mutex)
189*85Scth 
190*85Scth 
191*85Scth #define	EMUL64_MUTEX_ENTER(emul64) mutex_enter(EMUL64_RESP_MUTEX(emul64)), \
192*85Scth 				mutex_enter(EMUL64_REQ_MUTEX(emul64))
193*85Scth #define	EMUL64_MUTEX_EXIT(emul64)	mutex_exit(EMUL64_RESP_MUTEX(emul64)), \
194*85Scth 				mutex_exit(EMUL64_REQ_MUTEX(emul64))
195*85Scth 
196*85Scth #define	EMUL64_CV(emul64)			(&(emul64)->emul64_cv)
197*85Scth 
198*85Scth /*
199*85Scth  * HBA interface macros
200*85Scth  */
201*85Scth #define	SDEV2TRAN(sd)		((sd)->sd_address.a_hba_tran)
202*85Scth #define	SDEV2ADDR(sd)		(&((sd)->sd_address))
203*85Scth #define	PKT2TRAN(pkt)		((pkt)->pkt_address.a_hba_tran)
204*85Scth #define	ADDR2TRAN(ap)		((ap)->a_hba_tran)
205*85Scth 
206*85Scth #define	TRAN2EMUL64(tran)	((struct emul64 *)(tran)->tran_hba_private)
207*85Scth #define	SDEV2EMUL64(sd)		(TRAN2EMUL64(SDEV2TRAN(sd)))
208*85Scth #define	PKT2EMUL64(pkt)		(TRAN2EMUL64(PKT2TRAN(pkt)))
209*85Scth #define	ADDR2EMUL64(ap)		(TRAN2EMUL64(ADDR2TRAN(ap)))
210*85Scth 
211*85Scth #define	CMD2ADDR(cmd)		(&CMD2PKT(cmd)->pkt_address)
212*85Scth #define	CMD2TRAN(cmd)		(CMD2PKT(cmd)->pkt_address.a_hba_tran)
213*85Scth #define	CMD2EMUL64(cmd)		(TRAN2EMUL64(CMD2TRAN(cmd)))
214*85Scth 
215*85Scth /*
216*85Scth  * Results of checking for range overlap.
217*85Scth  */
218*85Scth typedef enum emul64_rng_overlap {
219*85Scth 	O_NONE,			/* No overlap */
220*85Scth 	O_SAME,			/* Ranges are identical */
221*85Scth 	O_SUBSET,		/* Blocks are contained in range */
222*85Scth 	O_OVERLAP		/* Ranges overlap. */
223*85Scth } emul64_rng_overlap_t;
224*85Scth 
225*85Scth /*
226*85Scth  * Rather than keep the entire image of the disk, we only keep
227*85Scth  * the blocks which have been written with non-zeros.  As the
228*85Scth  * purpose of this driver is to exercise format and perhaps other
229*85Scth  * large-disk management tools, only recording the label for
230*85Scth  * i/o is sufficient
231*85Scth  */
232*85Scth typedef struct blklist {
233*85Scth 	diskaddr_t	bl_blkno;	/* Disk address of the data */
234*85Scth 	uchar_t		*bl_data;	/* Pointer to the data */
235*85Scth 	avl_node_t	bl_node;	/* Our linkage in AVL tree */
236*85Scth } blklist_t;
237*85Scth 
238*85Scth /*
239*85Scth  * Structure to track a range of blocks where writes are to be ignored.
240*85Scth  */
241*85Scth typedef struct emul64_nowrite {
242*85Scth 	struct emul64_nowrite	*emul64_nwnext;	/* next item in list */
243*85Scth 	emul64_range_t		emul64_blocked;	/* range to ignore writes */
244*85Scth } emul64_nowrite_t;
245*85Scth 
246*85Scth typedef struct emul64_tgt {
247*85Scth 	struct scsi_address	emul64_tgt_saddr;
248*85Scth 	struct emul64_tgt	*emul64_tgt_next;	/* Next tgt on ctlr */
249*85Scth 	emul64_nowrite_t	*emul64_tgt_nowrite;	/* List of regions to */
250*85Scth 							/* skip writes */
251*85Scth 	diskaddr_t		emul64_tgt_sectors;	/* # sectors in dev */
252*85Scth 	char 			emul64_tgt_inq[8+16];
253*85Scth 	uint_t			emul64_tgt_dtype;
254*85Scth 	uint_t			emul64_tgt_ncyls;	/* # cylinders in dev */
255*85Scth 	uint_t			emul64_tgt_nheads;	/* # disk heads */
256*85Scth 	uint_t			emul64_tgt_nsect;	/* # sectors */
257*85Scth 	uint64_t		emul64_list_length;	/* # data blks */
258*85Scth 	avl_tree_t		emul64_tgt_data;	/* Tree of data blks */
259*85Scth 	kmutex_t		emul64_tgt_blk_lock;	/* Protect data blks */
260*85Scth 	krwlock_t		emul64_tgt_nw_lock;	/* Guard tgt_nowrite */
261*85Scth } emul64_tgt_t;
262*85Scth 
263*85Scth /*
264*85Scth  * emul64 softstate structure
265*85Scth  */
266*85Scth 
267*85Scth /*
268*85Scth  * deadline slot structure for timeout handling
269*85Scth  */
270*85Scth struct emul64_slot {
271*85Scth 	struct emul64_cmd	*slot_cmd;
272*85Scth 	clock_t		slot_deadline;
273*85Scth };
274*85Scth 
275*85Scth 
276*85Scth /*
277*85Scth  * Record the reset notification requests from target drivers.
278*85Scth  */
279*85Scth struct emul64_reset_notify_entry {
280*85Scth 	struct scsi_address		*ap;
281*85Scth 	void				(*callback)(caddr_t);
282*85Scth 	caddr_t				arg;
283*85Scth 	struct emul64_reset_notify_entry	*next;
284*85Scth };
285*85Scth 
286*85Scth 
287*85Scth struct emul64 {
288*85Scth 
289*85Scth 	/*
290*85Scth 	 * Transport structure for this instance of the hba
291*85Scth 	 */
292*85Scth 	scsi_hba_tran_t		*emul64_tran;
293*85Scth 
294*85Scth 	/*
295*85Scth 	 * dev_info_t reference can be found in the transport structure
296*85Scth 	 */
297*85Scth 	dev_info_t		*emul64_dip;
298*85Scth 
299*85Scth 	/*
300*85Scth 	 * Interrupt block cookie
301*85Scth 	 */
302*85Scth 	ddi_iblock_cookie_t	emul64_iblock;
303*85Scth 
304*85Scth 	/*
305*85Scth 	 * Firmware revision number
306*85Scth 	 */
307*85Scth 	uint16_t		emul64_major_rev;
308*85Scth 	uint16_t		emul64_minor_rev;
309*85Scth 
310*85Scth 	/*
311*85Scth 	 * timeout id
312*85Scth 	 */
313*85Scth 	timeout_id_t		emul64_timeout_id;
314*85Scth 
315*85Scth 	/*
316*85Scth 	 * scsi options, scsi_tag_age_limit  per emul64
317*85Scth 	 */
318*85Scth 	int			emul64_scsi_options;
319*85Scth 	int			emul64_target_scsi_options[NTARGETS_WIDE];
320*85Scth 	int			emul64_scsi_tag_age_limit;
321*85Scth 
322*85Scth 	/*
323*85Scth 	 * scsi_reset_delay per emul64
324*85Scth 	 */
325*85Scth 	clock_t			emul64_scsi_reset_delay;
326*85Scth 
327*85Scth 	/*
328*85Scth 	 * current host ID
329*85Scth 	 */
330*85Scth 	uint8_t			emul64_initiator_id;
331*85Scth 
332*85Scth 	/*
333*85Scth 	 * suspended flag for power management
334*85Scth 	 */
335*85Scth 	uint8_t			emul64_suspended;
336*85Scth 
337*85Scth 	/*
338*85Scth 	 * Host adapter capabilities and offset/period values per target
339*85Scth 	 */
340*85Scth 	uint16_t		emul64_cap[NTARGETS_WIDE];
341*85Scth 	int16_t			emul64_synch[NTARGETS_WIDE];
342*85Scth 
343*85Scth 	/*
344*85Scth 	 * EMUL64 Hardware register pointer.
345*85Scth 	 */
346*85Scth 	struct emul64regs		*emul64_reg;
347*85Scth 
348*85Scth 
349*85Scth 	kmutex_t		emul64_request_mutex;
350*85Scth 	kmutex_t		emul64_response_mutex;
351*85Scth 
352*85Scth 	/*
353*85Scth 	 * for keeping track of the max LUNs per target on this bus
354*85Scth 	 */
355*85Scth 	uchar_t			emul64_max_lun[NTARGETS_WIDE];
356*85Scth 
357*85Scth 	/*
358*85Scth 	 * for keeping track of each target/lun
359*85Scth 	 */
360*85Scth 	int	nt_total_sectors[NTARGETS_WIDE][EMUL64_NLUNS_PER_TARGET];
361*85Scth 
362*85Scth 	struct emul64_reset_notify_entry	*emul64_reset_notify_listf;
363*85Scth 
364*85Scth 	ushort_t		emul64_backoff;
365*85Scth 	uint_t			emul64_softstate; /* flags for hotplug */
366*85Scth 	int			emul64_hotplug_waiting;
367*85Scth 	kcondvar_t		emul64_cv; /* cv for bus quiesce/unquiesce */
368*85Scth 	kmutex_t		emul64_hotplug_mutex; /* Mutex for hotplug */
369*85Scth 	taskq_t			*emul64_taskq;
370*85Scth 	emul64_tgt_t		*emul64_tgt;
371*85Scth };
372*85Scth 
373*85Scth _NOTE(MUTEX_PROTECTS_DATA(emul64::emul64_request_mutex,
374*85Scth 				emul64::emul64_queue_space))
375*85Scth _NOTE(MUTEX_PROTECTS_DATA(emul64::emul64_request_mutex,
376*85Scth 				emul64::emul64_request_in))
377*85Scth _NOTE(MUTEX_PROTECTS_DATA(emul64::emul64_request_mutex,
378*85Scth 				emul64::emul64_request_out))
379*85Scth _NOTE(MUTEX_PROTECTS_DATA(emul64::emul64_request_mutex,
380*85Scth 				emul64::emul64_request_ptr))
381*85Scth _NOTE(MUTEX_PROTECTS_DATA(emul64::emul64_request_mutex,
382*85Scth 				emul64::emul64_mbox))
383*85Scth _NOTE(MUTEX_PROTECTS_DATA(emul64::emul64_request_mutex,
384*85Scth 				emul64::emul64_slots))
385*85Scth 
386*85Scth _NOTE(MUTEX_PROTECTS_DATA(emul64::emul64_response_mutex,
387*85Scth 				emul64::emul64_response_in))
388*85Scth _NOTE(MUTEX_PROTECTS_DATA(emul64::emul64_response_mutex,
389*85Scth 				emul64::emul64_response_out))
390*85Scth _NOTE(MUTEX_PROTECTS_DATA(emul64::emul64_response_mutex,
391*85Scth 				emul64::emul64_response_ptr))
392*85Scth 
393*85Scth extern void emul64_bsd_init();
394*85Scth extern void emul64_bsd_fini();
395*85Scth extern void emul64_bsd_get_props(dev_info_t *);
396*85Scth 
397*85Scth extern emul64_rng_overlap_t emul64_overlap(emul64_range_t *,
398*85Scth 						diskaddr_t, size_t);
399*85Scth extern int emul64_bsd_blkcompare(const void *, const void *);
400*85Scth extern int emul64debug;
401*85Scth extern long emul64_nowrite_count;
402*85Scth extern kmutex_t emul64_stats_mutex;
403*85Scth extern int emul64_collect_stats;
404*85Scth extern uint64_t emul64_taskq_max;
405*85Scth extern int emul64_max_task;
406*85Scth extern int emul64_task_nthreads;
407*85Scth 
408*85Scth #ifdef	__cplusplus
409*85Scth }
410*85Scth #endif
411*85Scth 
412*85Scth #endif	/* _SYS_SCSI_ADAPTERS_EMUL64VAR_H */
413