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