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