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