xref: /illumos-gate/usr/src/uts/common/sys/scsi/adapters/scsi_vhci.h (revision 93a18d6d401e844455263f926578e9d2aa6b47ec)
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  */
26 
27 #ifndef	_SYS_SCSI_ADAPTERS_SCSI_VHCI_H
28 #define	_SYS_SCSI_ADAPTERS_SCSI_VHCI_H
29 
30 /*
31  * Multiplexed I/O SCSI vHCI global include
32  */
33 #include <sys/note.h>
34 #include <sys/taskq.h>
35 #include <sys/mhd.h>
36 #include <sys/sunmdi.h>
37 #include <sys/mdi_impldefs.h>
38 #include <sys/scsi/adapters/mpapi_impl.h>
39 #include <sys/scsi/adapters/mpapi_scsi_vhci.h>
40 
41 #ifdef	__cplusplus
42 extern "C" {
43 #endif
44 
45 #if !defined(_BIT_FIELDS_LTOH) && !defined(_BIT_FIELDS_HTOL)
46 #error	One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
47 #endif  /* _BIT_FIELDS_LTOH */
48 
49 #ifdef	_KERNEL
50 
51 #ifdef	UNDEFINED
52 #undef	UNDEFINED
53 #endif
54 #define	UNDEFINED		-1
55 
56 #define	VHCI_STATE_OPEN		0x00000001
57 
58 
59 #define	VH_SLEEP		0x0
60 #define	VH_NOSLEEP		0x1
61 
62 /*
63  * HBA interface macros
64  */
65 
66 #define	TRAN2HBAPRIVATE(tran)	((struct scsi_vhci *)(tran)->tran_hba_private)
67 #define	VHCI_INIT_WAIT_TIMEOUT	60000000
68 #define	VHCI_FOWATCH_INTERVAL	1000000		/* in usecs */
69 #define	VHCI_EXTFO_TIMEOUT	3*60		/* 3 minutes */
70 
71 #define	SCBP_C(pkt)	((*(pkt)->pkt_scbp) & STATUS_MASK)
72 
73 int vhci_do_scsi_cmd(struct scsi_pkt *);
74 /*PRINTFLIKE3*/
75 void vhci_log(int, dev_info_t *, const char *, ...);
76 
77 /*
78  * debugging stuff
79  */
80 
81 #ifdef	DEBUG
82 
83 #ifndef VHCI_DEBUG_DEFAULT_VAL
84 #define	VHCI_DEBUG_DEFAULT_VAL		0
85 #endif	/* VHCI_DEBUG_DEFAULT_VAL */
86 
87 extern int vhci_debug;
88 
89 #include <sys/debug.h>
90 
91 #define	VHCI_DEBUG(level, stmnt) \
92 	    if (vhci_debug >= (level)) vhci_log stmnt
93 
94 #else	/* !DEBUG */
95 
96 #define	VHCI_DEBUG(level, stmnt)
97 
98 #endif	/* !DEBUG */
99 
100 
101 
102 #define	VHCI_PKT_PRIV_SIZE		2
103 
104 #define	ADDR2VHCI(ap)	((struct scsi_vhci *) \
105 			((ap)->a_hba_tran->tran_hba_private))
106 #define	ADDR2VLUN(ap)	(scsi_vhci_lun_t *) \
107 			(scsi_device_hba_private_get(scsi_address_device(ap)))
108 #define	ADDR2DIP(ap)	((dev_info_t *)(scsi_address_device(ap)->sd_dev))
109 
110 #define	HBAPKT2VHCIPKT(pkt) (pkt->pkt_private)
111 #define	TGTPKT2VHCIPKT(pkt) (pkt->pkt_ha_private)
112 #define	VHCIPKT2HBAPKT(pkt) (pkt->pkt_hba_pkt)
113 #define	VHCIPKT2TGTPKT(pkt) (pkt->pkt_tgt_pkt)
114 
115 #define	VHCI_DECR_PATH_CMDCOUNT(svp)	mutex_enter(&(svp)->svp_mutex); \
116 					(svp)->svp_cmds--; \
117 					if ((svp)->svp_cmds == 0)  \
118 						cv_broadcast(&(svp)->svp_cv); \
119 					mutex_exit(&(svp)->svp_mutex);
120 
121 #define	VHCI_INCR_PATH_CMDCOUNT(svp)	mutex_enter(&(svp)->svp_mutex); \
122 					(svp)->svp_cmds++; \
123 					mutex_exit(&(svp)->svp_mutex);
124 
125 /*
126  * When a LUN is HELD it results in new IOs being returned to the target
127  * driver layer with TRAN_BUSY.  Should be used while performing
128  * operations that require prevention of any new IOs to the LUN and
129  * the LUN should be HELD for the duration of such operations.
130  * f can be VH_SLEEP or VH_NOSLEEP.
131  * h is set to 1 to indicate LUN was successfully HELD.
132  * h is set to 0 when f is VH_NOSLEEP and LUN is already HELD.
133  *
134  * Application examples:
135  *
136  * 1) SCSI-II RESERVE: HOLD LUN until it is quiesced and the load balancing
137  * policy is switched to NONE before proceeding with RESERVE handling.
138  *
139  * 2) Failover: HOLD LUN before initiating failover.
140  *
141  * 3) When an externally initiated failover is detected, HOLD LUN until all
142  * path states have been refreshed to reflect the new value.
143  *
144  */
145 #define	VHCI_HOLD_LUN(vlun, f, h) { \
146 	int sleep = (f); \
147 	mutex_enter(&(vlun)->svl_mutex); \
148 	if ((vlun)->svl_transient == 1) { \
149 		if (sleep == VH_SLEEP) { \
150 			while ((vlun)->svl_transient == 1) \
151 				cv_wait(&(vlun)->svl_cv, &(vlun)->svl_mutex); \
152 			(vlun)->svl_transient = 1; \
153 			(h) = 1; \
154 		} else { \
155 			(h) = 0; \
156 		} \
157 	} else { \
158 		(vlun)->svl_transient = 1; \
159 		(h) = 1; \
160 	} \
161 	sleep = (h); \
162 	mutex_exit(&(vlun)->svl_mutex); \
163 }
164 
165 #define	VHCI_RELEASE_LUN(vlun) { \
166 	mutex_enter(&(vlun)->svl_mutex); \
167 	(vlun)->svl_transient = 0; \
168 	cv_broadcast(&(vlun)->svl_cv); \
169 	mutex_exit(&(vlun)->svl_mutex); \
170 }
171 
172 #define	VHCI_LUN_IS_HELD(vlun)	((vlun)->svl_transient == 1)
173 
174 /*
175  * vhci_pkt states
176  */
177 #define	VHCI_PKT_IDLE			0x01
178 #define	VHCI_PKT_ISSUED			0x02
179 #define	VHCI_PKT_ABORTING		0x04
180 #define	VHCI_PKT_STALE_BINDING		0x08
181 /*
182  * Set the first time taskq is dispatched from scsi_start for
183  * a packet.  To ensure vhci_scsi_start recognizes that the scsi_pkt
184  * is being issued from the taskq and not target driver.
185  */
186 #define	VHCI_PKT_THRU_TASKQ		0x20
187 
188 #define	VHCI_PKT_TIMEOUT		30		/* seconds */
189 #define	VHCI_PKT_RETRY_CNT		2
190 #define	VHCI_POLL_TIMEOUT		60		/* seconds */
191 
192 /*
193  * define extended scsi cmd pkt
194  */
195 #define	EXTCMDS_STATUS_SIZE		(sizeof (struct scsi_arq_status))
196 
197 #define	CFLAG_NOWAIT		0x1000	/* don't sleep */
198 #define	CFLAG_DMA_PARTIAL	0x2000	/* Support Partial DMA */
199 
200 /*
201  * Maximum size of SCSI cdb in SCSI command
202  */
203 #define	VHCI_SCSI_CDB_SIZE		16
204 #define	VHCI_SCSI_SCB_SIZE		(sizeof (struct scsi_arq_status))
205 
206 /*
207  * OSD specific definitions
208  */
209 #define	VHCI_SCSI_OSD_CDB_SIZE		224
210 #define	VHCI_SCSI_OSD_PKT_FLAGS		0x100000
211 
212 /*
213  * flag to determine failover support
214  */
215 #define	SCSI_NO_FAILOVER	0x0
216 #define	SCSI_IMPLICIT_FAILOVER	0x1
217 #define	SCSI_EXPLICIT_FAILOVER	0x2
218 #define	SCSI_BOTH_FAILOVER \
219 	(SCSI_IMPLICIT_FAILOVER |  SCSI_EXPLICIT_FAILOVER)
220 
221 struct	scsi_vhci_swarg;
222 
223 #define	VHCI_NUM_RESV_KEYS	8
224 
225 typedef struct vhci_prin_readkeys {
226 	uint32_t		generation;
227 	uint32_t		length;
228 	mhioc_resv_key_t	keylist[VHCI_NUM_RESV_KEYS];
229 } vhci_prin_readkeys_t;
230 
231 #define	VHCI_PROUT_SIZE	\
232 	((sizeof (vhci_prout_t) - 2 * (MHIOC_RESV_KEY_SIZE) * sizeof (char)))
233 
234 typedef struct vhci_prout {
235 	/* PGR register parameters start */
236 	uchar_t		res_key[MHIOC_RESV_KEY_SIZE];
237 	uchar_t		service_key[MHIOC_RESV_KEY_SIZE];
238 	uint32_t	scope_address;
239 
240 #if defined(_BIT_FIELDS_LTOH)
241 	uchar_t		aptpl:1,
242 			reserved:7;
243 #else
244 	uchar_t		reserved:7,
245 			aptpl:1;
246 #endif /* _BIT_FIELDS_LTOH */
247 
248 	uchar_t		reserved_1;
249 	uint16_t	ext_len;
250 	/* PGR register parameters end */
251 
252 	/* Update VHCI_PROUT_SIZE if new fields are added here */
253 
254 	uchar_t		active_res_key[MHIOC_RESV_KEY_SIZE];
255 	uchar_t		active_service_key[MHIOC_RESV_KEY_SIZE];
256 } vhci_prout_t;
257 
258 #define	VHCI_PROUT_REGISTER	0x0
259 #define	VHCI_PROUT_RESERVE	0x1
260 #define	VHCI_PROUT_RELEASE	0x2
261 #define	VHCI_PROUT_CLEAR	0x3
262 #define	VHCI_PROUT_PREEMPT	0x4
263 #define	VHCI_PROUT_P_AND_A	0x5
264 #define	VHCI_PROUT_R_AND_IGNORE	0x6
265 
266 struct vhci_pkt {
267 	struct scsi_pkt			*vpkt_tgt_pkt;
268 	mdi_pathinfo_t			*vpkt_path;	/* path pkt bound to */
269 
270 	/*
271 	 * pHCI packet that does the actual work.
272 	 */
273 	struct scsi_pkt			*vpkt_hba_pkt;
274 
275 	uint_t				vpkt_state;
276 	uint_t				vpkt_flags;
277 
278 	/*
279 	 * copy of vhci_scsi_init_pkt args.  Used when we invoke
280 	 * scsi_init_pkt() of the pHCI corresponding to the path that we
281 	 * bind to
282 	 */
283 	int				vpkt_tgt_init_cdblen;
284 	int				vpkt_tgt_init_scblen;
285 	int				vpkt_tgt_init_pkt_flags;
286 	struct buf			*vpkt_tgt_init_bp;
287 
288 	/*
289 	 * Pointer to original struct vhci_pkt for cmd send by ssd.
290 	 * Saved when the command is being retried internally.
291 	 */
292 	struct vhci_pkt			*vpkt_org_vpkt;
293 };
294 
295 typedef struct scsi_vhci_lun {
296 	kmutex_t		svl_mutex;
297 	kcondvar_t		svl_cv;
298 
299 	/*
300 	 * following three fields are under svl_mutex protection
301 	 */
302 	int			svl_transient;
303 
304 	/*
305 	 * to prevent unnecessary failover when a device is
306 	 * is discovered across a passive path and active path
307 	 * is still comng up
308 	 */
309 	int			svl_waiting_for_activepath;
310 	time_t			svl_wfa_time;
311 
312 	/*
313 	 * for RESERVE/RELEASE support
314 	 */
315 	client_lb_t		svl_lb_policy_save;
316 
317 	/*
318 	 * Failover ops and ops name selected for the lun.
319 	 */
320 	struct scsi_failover_ops	*svl_fops;
321 	char			*svl_fops_name;
322 
323 	void			*svl_fops_ctpriv;
324 
325 	struct scsi_vhci_lun	*svl_hash_next;
326 	char			*svl_lun_wwn;
327 
328 	/*
329 	 * currently active pathclass
330 	 */
331 	char			*svl_active_pclass;
332 
333 	dev_info_t		*svl_dip;
334 	uint32_t		svl_flags;	/* protected by svl_mutex */
335 
336 	/*
337 	 * When SCSI-II reservations are active we set the following pip
338 	 * to point to the path holding the reservation.  As long as
339 	 * the reservation is active this svl_resrv_pip is bound for the
340 	 * transport directly.  We bypass calling mdi_select_path to return
341 	 * a pip.
342 	 * The following pip is only valid when VLUN_RESERVE_ACTIVE_FLG
343 	 * is set.  This pip should not be accessed if this flag is reset.
344 	 */
345 	mdi_pathinfo_t	*svl_resrv_pip;
346 
347 	/*
348 	 * following fields are for PGR support
349 	 */
350 	taskq_t			*svl_taskq;
351 	ksema_t			svl_pgr_sema;	/* PGR serialization */
352 	vhci_prin_readkeys_t	svl_prin;	/* PGR in data */
353 	vhci_prout_t		svl_prout;	/* PGR out data */
354 	uchar_t			svl_cdb[CDB_GROUP4];
355 	int			svl_time;	/* pkt_time */
356 	uint32_t		svl_bcount;	/* amount of data */
357 	int			svl_pgr_active; /* registrations active */
358 	mdi_pathinfo_t		*svl_first_path;
359 
360 	/* external failover */
361 	int			svl_efo_update_path;
362 	struct	scsi_vhci_swarg	*svl_swarg;
363 
364 	uint32_t		svl_support_lun_reset; /* Lun reset support */
365 	int			svl_not_supported;
366 	int			svl_xlf_capable; /* XLF implementation */
367 	int			svl_sector_size;
368 	int			svl_setcap_done;
369 	uint16_t		svl_fo_support;	 /* failover mode */
370 } scsi_vhci_lun_t;
371 
372 #define	VLUN_TASK_D_ALIVE_FLG		0x01
373 
374 /*
375  * This flag is used to monitor the state of SCSI-II RESERVATION on the
376  * lun.  A SCSI-II RESERVE cmd may be accepted by the target on the inactive
377  * path.  This would then cause a subsequent IO to cause the paths to be
378  * updated and be returned with a reservation conflict.  By monitoring this
379  * flag, and sending a reset to the target when needed to clear the reservation,
380  * one can avoid this conflict.
381  */
382 #define	VLUN_RESERVE_ACTIVE_FLG		0x04
383 
384 /*
385  * This flag is set when a SCSI-II RESERVE cmd is received by scsi_vhci
386  * and cleared when the pkt completes in vhci_intr.  It ensures that the
387  * lun remains quiesced for the duration of this pkt.  This is different
388  * from VHCI_HOLD_LUN as this pertains to IOs only.
389  */
390 #define	VLUN_QUIESCED_FLG		0x08
391 
392 /*
393  * This flag is set to tell vhci_update_pathstates to call back
394  * into vhci_mpapi_update_tpg_acc_state.
395  */
396 #define	VLUN_UPDATE_TPG			0x10
397 
398 /*
399  * Various reset recovery depth.
400  */
401 
402 #define	VHCI_DEPTH_ALL		3
403 #define	VHCI_DEPTH_TARGET	2
404 #define	VHCI_DEPTH_LUN		1	/* For the sake completeness */
405 #define	TRUE			(1)
406 #define	FALSE			(0)
407 
408 /*
409  * this is stashed away in the client private area of
410  * pathinfo
411  */
412 typedef struct scsi_vhci_priv {
413 	kmutex_t		svp_mutex;
414 	kcondvar_t		svp_cv;
415 	struct scsi_vhci_lun	*svp_svl;
416 
417 	/*
418 	 * scsi device associated with this
419 	 * pathinfo
420 	 */
421 	struct scsi_device	*svp_psd;
422 
423 	/*
424 	 * number of outstanding commands on this
425 	 * path.  Protected by svp_mutex
426 	 */
427 	int			svp_cmds;
428 
429 	/*
430 	 * following is used to prevent packets completing with the
431 	 * same error reason from flooding the screen
432 	 */
433 	uchar_t			svp_last_pkt_reason;
434 
435 	/* external failover scsi_watch token */
436 	opaque_t		svp_sw_token;
437 
438 	/* any cleanup operations for a newly found path. */
439 	int			svp_new_path;
440 } scsi_vhci_priv_t;
441 
442 /*
443  * argument to scsi_watch callback.  Used for processing
444  * externally initiated failovers
445  */
446 typedef struct scsi_vhci_swarg {
447 	scsi_vhci_priv_t	*svs_svp;
448 	time_t			svs_tos;	/* time of submission */
449 	mdi_pathinfo_t		*svs_pi;	/* pathinfo being "watched" */
450 	int			svs_release_lun;
451 	int			svs_done;
452 } scsi_vhci_swarg_t;
453 
454 /*
455  * scsi_vhci softstate
456  *
457  * vhci_mutex protects
458  *	vhci_state
459  * and	vhci_reset_notify list
460  */
461 struct scsi_vhci {
462 	kmutex_t			vhci_mutex;
463 	dev_info_t			*vhci_dip;
464 	struct scsi_hba_tran		*vhci_tran;
465 	uint32_t			vhci_state;
466 	uint32_t			vhci_instance;
467 	kstat_t				vhci_kstat;
468 	/*
469 	 * This taskq is for general vhci operations like reservations,
470 	 * auto-failback, etc.
471 	 */
472 	taskq_t				*vhci_taskq;
473 	/* Dedicate taskq to handle external failovers */
474 	taskq_t				*vhci_update_pathstates_taskq;
475 	struct scsi_reset_notify_entry	*vhci_reset_notify_listf;
476 	uint16_t			vhci_conf_flags;
477 	mpapi_priv_t			*mp_priv;
478 };
479 
480 /*
481  * vHCI flags for configuration settings, defined in scsi_vhci.conf
482  */
483 #define	VHCI_CONF_FLAGS_AUTO_FAILBACK	0x0001	/* Enables auto failback */
484 
485 typedef enum {
486 	SCSI_PATH_INACTIVE,
487 	SCSI_PATH_ACTIVE,
488 	SCSI_PATH_ACTIVE_NONOPT
489 } scsi_path_state_t;
490 
491 #define	SCSI_MAXPCLASSLEN	25
492 
493 #define	OPINFO_REV	1
494 
495 /*
496  * structure describing operational characteristics of
497  * path
498  */
499 struct scsi_path_opinfo {
500 	int			opinfo_rev;
501 
502 	/*
503 	 * name of pathclass. Eg. "primary", "secondary"
504 	 */
505 	char			opinfo_path_attr[SCSI_MAXPCLASSLEN];
506 
507 	/*
508 	 * path state: ACTIVE/PASSIVE
509 	 */
510 	scsi_path_state_t	opinfo_path_state;
511 
512 	/*
513 	 * the best and worst case time estimates for
514 	 * failover operation to complete
515 	 */
516 	uint_t			opinfo_pswtch_best;
517 	uint_t			opinfo_pswtch_worst;
518 
519 	/* XLF implementation */
520 	int			opinfo_xlf_capable;
521 	uint16_t		opinfo_preferred;
522 	uint16_t		opinfo_mode;
523 
524 };
525 
526 
527 #define	SFO_REV		1
528 
529 /*
530  * vectors for device specific failover related operations
531  */
532 struct scsi_failover_ops {
533 	int	sfo_rev;
534 
535 	/*
536 	 * failover module name, begins with "f_"
537 	 */
538 	char	*sfo_name;
539 
540 	/*
541 	 * devices supported by failover module
542 	 *
543 	 * NOTE: this is an aproximation, sfo_device_probe has the final say.
544 	 */
545 	char	**sfo_devices;
546 
547 	/*
548 	 * initialize the failover module
549 	 */
550 	void	(*sfo_init)();
551 
552 	/*
553 	 * identify device
554 	 */
555 	int	(*sfo_device_probe)(
556 			struct scsi_device	*sd,
557 			struct scsi_inquiry	*stdinq,
558 			void			**ctpriv);
559 
560 	/*
561 	 * housekeeping (free memory etc alloc'ed during probe
562 	 */
563 	void	(*sfo_device_unprobe)(
564 			struct scsi_device	*sd,
565 			void			*ctpriv);
566 
567 	/*
568 	 * bring a path ONLINE (ie make it ACTIVE)
569 	 */
570 	int	(*sfo_path_activate)(
571 			struct scsi_device	*sd,
572 			char			*pathclass,
573 			void			*ctpriv);
574 
575 	/*
576 	 * inverse of above
577 	 */
578 	int	(*sfo_path_deactivate)(
579 			struct scsi_device	*sd,
580 			char			*pathclass,
581 			void			*ctpriv);
582 
583 	/*
584 	 * returns operational characteristics of path
585 	 */
586 	int	(*sfo_path_get_opinfo)(
587 			struct scsi_device	*sd,
588 			struct scsi_path_opinfo *opinfo,
589 			void			*ctpriv);
590 
591 	/*
592 	 * verify path is operational
593 	 */
594 	int	(*sfo_path_ping)(
595 			struct scsi_device	*sd,
596 			void			*ctpriv);
597 
598 	/*
599 	 * analyze SENSE data to detect externally initiated
600 	 * failovers
601 	 */
602 	int	(*sfo_analyze_sense)(
603 			struct scsi_device	*sd,
604 			uint8_t			*sense,
605 			void			*ctpriv);
606 
607 	/*
608 	 * return the next pathclass in order of preference
609 	 * eg. "secondary" comes after "primary"
610 	 */
611 	int	(*sfo_pathclass_next)(
612 			char			*cur,
613 			char			**nxt,
614 			void			*ctpriv);
615 };
616 
617 /*
618  * Names of (too) 'well-known' failover ops.
619  *   NOTE: consumers of these names should look for a better way...
620  */
621 #define	SFO_NAME_SYM		"f_sym"
622 #define	SFO_NAME_TPGS		"f_tpgs"
623 #define	SCSI_FAILOVER_IS_ASYM(svl)	\
624 	((svl) ? ((svl)->svl_fo_support != SCSI_NO_FAILOVER) : 0)
625 #define	SCSI_FAILOVER_IS_TPGS(sfo)	\
626 	((sfo) ? (strcmp((sfo)->sfo_name, SFO_NAME_TPGS) == 0) : 0)
627 
628 /*
629  * Macro to provide plumbing for basic failover module
630  */
631 #define	_SCSI_FAILOVER_OP(sfo_name, local_name, ops_name)		\
632 	static struct modlmisc modlmisc = {				\
633 		&mod_miscops, sfo_name					\
634 	};								\
635 	static struct modlinkage modlinkage = {				\
636 		MODREV_1, (void *)&modlmisc, NULL			\
637 	};								\
638 	int	_init()							\
639 	{								\
640 		return (mod_install(&modlinkage));			\
641 	}								\
642 	int	_fini()							\
643 	{								\
644 		return (mod_remove(&modlinkage));			\
645 	}								\
646 	int	_info(struct modinfo *modinfop)				\
647 	{								\
648 		return (mod_info(&modlinkage, modinfop));		\
649 	}								\
650 	static int	local_name##_device_probe(			\
651 				struct scsi_device *,			\
652 				struct scsi_inquiry *, void **);	\
653 	static void	local_name##_device_unprobe(			\
654 				struct scsi_device *, void *);		\
655 	static int	local_name##_path_activate(			\
656 				struct scsi_device *, char *, void *);	\
657 	static int	local_name##_path_deactivate(			\
658 				struct scsi_device *, char *, void *);	\
659 	static int	local_name##_path_get_opinfo(			\
660 				struct scsi_device *,			\
661 				struct scsi_path_opinfo *, void *);	\
662 	static int	local_name##_path_ping(				\
663 				struct scsi_device *, void *);		\
664 	static int	local_name##_analyze_sense(			\
665 				struct scsi_device *,			\
666 				uint8_t *, void *);			\
667 	static int	local_name##_pathclass_next(			\
668 				char *, char **, void *);		\
669 	struct scsi_failover_ops ops_name##_failover_ops = {		\
670 		SFO_REV,						\
671 		sfo_name,						\
672 		local_name##_dev_table,					\
673 		NULL,							\
674 		local_name##_device_probe,				\
675 		local_name##_device_unprobe,				\
676 		local_name##_path_activate,				\
677 		local_name##_path_deactivate,				\
678 		local_name##_path_get_opinfo,				\
679 		local_name##_path_ping,					\
680 		local_name##_analyze_sense,				\
681 		local_name##_pathclass_next				\
682 	}
683 
684 #ifdef	lint
685 #define	SCSI_FAILOVER_OP(sfo_name, local_name)				\
686 	_SCSI_FAILOVER_OP(sfo_name, local_name, local_name)
687 #else	/* lint */
688 #define	SCSI_FAILOVER_OP(sfo_name, local_name)				\
689 	_SCSI_FAILOVER_OP(sfo_name, local_name, scsi_vhci)
690 #endif	/* lint */
691 
692 /*
693  * Return values for sfo_device_probe
694  */
695 #define	SFO_DEVICE_PROBE_VHCI	1	/* supported under scsi_vhci */
696 #define	SFO_DEVICE_PROBE_PHCI	0	/* not supported under scsi_vhci */
697 
698 /* return values for sfo_analyze_sense() */
699 #define	SCSI_SENSE_NOFAILOVER		0
700 #define	SCSI_SENSE_FAILOVER_INPROG	1
701 #define	SCSI_SENSE_ACT2INACT		2
702 #define	SCSI_SENSE_INACT2ACT		3
703 #define	SCSI_SENSE_INACTIVE		4
704 #define	SCSI_SENSE_UNKNOWN		5
705 #define	SCSI_SENSE_STATE_CHANGED	6
706 #define	SCSI_SENSE_NOT_READY		7
707 
708 /* vhci_intr action codes */
709 #define	JUST_RETURN			0
710 #define	BUSY_RETURN			1
711 #define	PKT_RETURN			2
712 
713 #if	defined(_SYSCALL32)
714 /*
715  * 32 bit variants of sv_path_info_prop_t and sv_path_info_t;
716  * To be used only in the driver and NOT applications
717  */
718 typedef struct sv_path_info_prop32 {
719 	uint32_t	buf_size;	/* user buffer size */
720 	caddr32_t	ret_buf_size;	/* actual buffer needed */
721 	caddr32_t	buf;		/* user space buffer */
722 } sv_path_info_prop32_t;
723 
724 typedef struct sv_path_info32 {
725 	union {
726 		char	ret_ct[MAXPATHLEN];		/* client device */
727 		char	ret_phci[MAXPATHLEN];		/* pHCI device */
728 	} device;
729 
730 	char			ret_addr[MAXNAMELEN];	/* device address */
731 	mdi_pathinfo_state_t	ret_state;		/* state information */
732 	uint32_t		ret_ext_state;		/* Extended State */
733 	sv_path_info_prop32_t	ret_prop;		/* path attributes */
734 } sv_path_info32_t;
735 
736 typedef struct sv_iocdata32 {
737 	caddr32_t	client;		/* client dev devfs path name */
738 	caddr32_t	phci;		/* pHCI dev devfs path name */
739 	caddr32_t	addr;		/* device address */
740 	uint32_t	buf_elem;	/* number of path_info elems */
741 	caddr32_t	ret_buf;	/* addr of array of sv_path_info */
742 	caddr32_t	ret_elem;	/* count of above sv_path_info */
743 } sv_iocdata32_t;
744 
745 typedef struct sv_switch_to_cntlr_iocdata32 {
746 	caddr32_t	client;	/* client device devfs path name */
747 	caddr32_t	class;	/* desired path class to be made active */
748 } sv_switch_to_cntlr_iocdata32_t;
749 
750 #endif	/* _SYSCALL32 */
751 
752 #endif	/* _KERNEL */
753 
754 /*
755  * Userland (Non Kernel) definitions start here.
756  * Multiplexed I/O SCSI vHCI IOCTL Definitions
757  */
758 
759 /*
760  * IOCTL structure for path properties
761  */
762 typedef struct sv_path_info_prop {
763 	uint_t	buf_size;	/* user buffer size */
764 	uint_t	*ret_buf_size;	/* actual buffer needed */
765 	caddr_t	buf;		/* user space buffer */
766 } sv_path_info_prop_t;
767 
768 /*
769  * Max buffer size of getting path properties
770  */
771 #define	SV_PROP_MAX_BUF_SIZE	4096
772 
773 /*
774  * String values for "path-class" property
775  */
776 #define	PCLASS_PRIMARY		"primary"
777 #define	PCLASS_SECONDARY	"secondary"
778 
779 #define	PCLASS_PREFERRED	1
780 #define	PCLASS_NONPREFERRED	0
781 
782 /*
783  * IOCTL structure for path information
784  */
785 typedef struct sv_path_info {
786 	union {
787 		char	ret_ct[MAXPATHLEN];		/* client device */
788 		char	ret_phci[MAXPATHLEN];		/* pHCI device */
789 	} device;
790 
791 	char			ret_addr[MAXNAMELEN];	/* device address */
792 	mdi_pathinfo_state_t	ret_state;		/* state information */
793 	uint32_t		ret_ext_state;		/* Extended State */
794 	sv_path_info_prop_t	ret_prop;		/* path attributes */
795 } sv_path_info_t;
796 
797 /*
798  * IOCTL argument structure
799  */
800 typedef struct sv_iocdata {
801 	caddr_t		client;		/* client dev devfs path name */
802 	caddr_t		phci;		/* pHCI dev devfs path name */
803 	caddr_t		addr;		/* device address */
804 	uint_t		buf_elem;	/* number of path_info elems */
805 	sv_path_info_t	*ret_buf;	/* array of sv_path_info */
806 	uint_t		*ret_elem;	/* count of sv_path_info */
807 } sv_iocdata_t;
808 
809 /*
810  * IOCTL argument structure for switching controllers
811  */
812 typedef struct sv_switch_to_cntlr_iocdata {
813 	caddr_t		client;	/* client device devfs path name */
814 	caddr_t		class;	/* desired path class to be made active */
815 } sv_switch_to_cntlr_iocdata_t;
816 
817 
818 /*
819  * IOCTL definitions
820  */
821 #define	SCSI_VHCI_CTL		('X' << 8)
822 #define	SCSI_VHCI_CTL_CMD	(SCSI_VHCI_CTL | ('S' << 8) | 'P')
823 #define	SCSI_VHCI_CTL_SUB_CMD	('x' << 8)
824 
825 #define	SCSI_VHCI_GET_CLIENT_MULTIPATH_INFO	(SCSI_VHCI_CTL_SUB_CMD + 0x01)
826 #define	SCSI_VHCI_GET_PHCI_MULTIPATH_INFO	(SCSI_VHCI_CTL_SUB_CMD + 0x02)
827 #define	SCSI_VHCI_GET_CLIENT_NAME		(SCSI_VHCI_CTL_SUB_CMD + 0x03)
828 #define	SCSI_VHCI_PATH_ONLINE			(SCSI_VHCI_CTL_SUB_CMD + 0x04)
829 #define	SCSI_VHCI_PATH_OFFLINE			(SCSI_VHCI_CTL_SUB_CMD + 0x05)
830 #define	SCSI_VHCI_PATH_STANDBY			(SCSI_VHCI_CTL_SUB_CMD + 0x06)
831 #define	SCSI_VHCI_PATH_TEST			(SCSI_VHCI_CTL_SUB_CMD + 0x07)
832 #define	SCSI_VHCI_SWITCH_TO_CNTLR		(SCSI_VHCI_CTL_SUB_CMD + 0x08)
833 
834 #ifdef	DEBUG
835 #define	SCSI_VHCI_GET_PHCI_LIST			(SCSI_VHCI_CTL_SUB_CMD + 0x09)
836 #define	SCSI_VHCI_CONFIGURE_PHCI		(SCSI_VHCI_CTL_SUB_CMD + 0x0A)
837 #define	SCSI_VHCI_UNCONFIGURE_PHCI		(SCSI_VHCI_CTL_SUB_CMD + 0x0B)
838 #endif
839 
840 #define	SCSI_VHCI_PATH_DISABLE			(SCSI_VHCI_CTL_SUB_CMD + 0x0C)
841 #define	SCSI_VHCI_PATH_ENABLE			(SCSI_VHCI_CTL_SUB_CMD + 0x0D)
842 #define	SCSI_VHCI_MPAPI				(SCSI_VHCI_CTL_SUB_CMD + 0x0E)
843 
844 #define	SCSI_VHCI_GET_TARGET_LONGNAME		(SCSI_VHCI_CTL_SUB_CMD + 0x0F)
845 
846 #ifdef	__cplusplus
847 }
848 #endif
849 
850 #endif	/* _SYS_SCSI_ADAPTERS_SCSI_VHCI_H */
851