1db194e27Sadailey /*
2db194e27Sadailey  * CDDL HEADER START
3db194e27Sadailey  *
4db194e27Sadailey  * The contents of this file are subject to the terms of the
5db194e27Sadailey  * Common Development and Distribution License (the "License").
6db194e27Sadailey  * You may not use this file except in compliance with the License.
7db194e27Sadailey  *
8db194e27Sadailey  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9db194e27Sadailey  * or http://www.opensolaris.org/os/licensing.
10db194e27Sadailey  * See the License for the specific language governing permissions
11db194e27Sadailey  * and limitations under the License.
12db194e27Sadailey  *
13db194e27Sadailey  * When distributing Covered Code, include this CDDL HEADER in each
14db194e27Sadailey  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15db194e27Sadailey  * If applicable, add the following below this CDDL HEADER, with the
16db194e27Sadailey  * fields enclosed by brackets "[]" replaced with your own identifying
17db194e27Sadailey  * information: Portions Copyright [yyyy] [name of copyright owner]
18db194e27Sadailey  *
19db194e27Sadailey  * CDDL HEADER END
20db194e27Sadailey  */
219a70fc3bSMark J. Nelson 
227c478bd9Sstevel@tonic-gate /*
2340764c95SVictor Li  * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
247c478bd9Sstevel@tonic-gate  */
25aa6577ebSJosef 'Jeff' Sipek /*
26aa6577ebSJosef 'Jeff' Sipek  * Copyright 2014 Nexenta Systems, Inc.  All rights reserved.
27*28c5054dSJason King  * Copyright 2024 RackTop Systems, Inc.
28aa6577ebSJosef 'Jeff' Sipek  */
297c478bd9Sstevel@tonic-gate 
307c478bd9Sstevel@tonic-gate #ifndef	_SYS_SCSI_ADAPTERS_SCSI_VHCI_H
317c478bd9Sstevel@tonic-gate #define	_SYS_SCSI_ADAPTERS_SCSI_VHCI_H
327c478bd9Sstevel@tonic-gate 
337c478bd9Sstevel@tonic-gate /*
347c478bd9Sstevel@tonic-gate  * Multiplexed I/O SCSI vHCI global include
357c478bd9Sstevel@tonic-gate  */
367c478bd9Sstevel@tonic-gate #include <sys/note.h>
377c478bd9Sstevel@tonic-gate #include <sys/taskq.h>
387c478bd9Sstevel@tonic-gate #include <sys/mhd.h>
397c478bd9Sstevel@tonic-gate #include <sys/sunmdi.h>
407c478bd9Sstevel@tonic-gate #include <sys/mdi_impldefs.h>
418c4f8890Srs #include <sys/scsi/adapters/mpapi_impl.h>
428c4f8890Srs #include <sys/scsi/adapters/mpapi_scsi_vhci.h>
437c478bd9Sstevel@tonic-gate 
447c478bd9Sstevel@tonic-gate #ifdef	__cplusplus
457c478bd9Sstevel@tonic-gate extern "C" {
467c478bd9Sstevel@tonic-gate #endif
477c478bd9Sstevel@tonic-gate 
487c478bd9Sstevel@tonic-gate #if !defined(_BIT_FIELDS_LTOH) && !defined(_BIT_FIELDS_HTOL)
497c478bd9Sstevel@tonic-gate #error	One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined
507c478bd9Sstevel@tonic-gate #endif  /* _BIT_FIELDS_LTOH */
517c478bd9Sstevel@tonic-gate 
527c478bd9Sstevel@tonic-gate #ifdef	_KERNEL
537c478bd9Sstevel@tonic-gate 
547c478bd9Sstevel@tonic-gate #ifdef	UNDEFINED
557c478bd9Sstevel@tonic-gate #undef	UNDEFINED
567c478bd9Sstevel@tonic-gate #endif
577c478bd9Sstevel@tonic-gate #define	UNDEFINED		-1
587c478bd9Sstevel@tonic-gate 
597c478bd9Sstevel@tonic-gate #define	VHCI_STATE_OPEN		0x00000001
607c478bd9Sstevel@tonic-gate 
617c478bd9Sstevel@tonic-gate 
627c478bd9Sstevel@tonic-gate #define	VH_SLEEP		0x0
637c478bd9Sstevel@tonic-gate #define	VH_NOSLEEP		0x1
647c478bd9Sstevel@tonic-gate 
657c478bd9Sstevel@tonic-gate /*
667c478bd9Sstevel@tonic-gate  * HBA interface macros
677c478bd9Sstevel@tonic-gate  */
687c478bd9Sstevel@tonic-gate 
697c478bd9Sstevel@tonic-gate #define	TRAN2HBAPRIVATE(tran)	((struct scsi_vhci *)(tran)->tran_hba_private)
707c478bd9Sstevel@tonic-gate #define	VHCI_INIT_WAIT_TIMEOUT	60000000
717c478bd9Sstevel@tonic-gate #define	VHCI_FOWATCH_INTERVAL	1000000		/* in usecs */
72aa6577ebSJosef 'Jeff' Sipek #define	VHCI_EXTFO_TIMEOUT	(3 * 60 * NANOSEC)	/* 3 minutes in nsec */
737c478bd9Sstevel@tonic-gate 
747c478bd9Sstevel@tonic-gate #define	SCBP_C(pkt)	((*(pkt)->pkt_scbp) & STATUS_MASK)
757c478bd9Sstevel@tonic-gate 
767c478bd9Sstevel@tonic-gate int vhci_do_scsi_cmd(struct scsi_pkt *);
771e1ddd6cScth /*PRINTFLIKE3*/
787c478bd9Sstevel@tonic-gate void vhci_log(int, dev_info_t *, const char *, ...);
797c478bd9Sstevel@tonic-gate 
80*28c5054dSJason King size_t vhci_get_blocksize(dev_info_t *);
81*28c5054dSJason King 
827c478bd9Sstevel@tonic-gate /*
837c478bd9Sstevel@tonic-gate  * debugging stuff
847c478bd9Sstevel@tonic-gate  */
857c478bd9Sstevel@tonic-gate 
867c478bd9Sstevel@tonic-gate #ifdef	DEBUG
877c478bd9Sstevel@tonic-gate 
887c478bd9Sstevel@tonic-gate #ifndef VHCI_DEBUG_DEFAULT_VAL
897c478bd9Sstevel@tonic-gate #define	VHCI_DEBUG_DEFAULT_VAL		0
907c478bd9Sstevel@tonic-gate #endif	/* VHCI_DEBUG_DEFAULT_VAL */
917c478bd9Sstevel@tonic-gate 
927c478bd9Sstevel@tonic-gate extern int vhci_debug;
937c478bd9Sstevel@tonic-gate 
947c478bd9Sstevel@tonic-gate #include <sys/debug.h>
957c478bd9Sstevel@tonic-gate 
967c478bd9Sstevel@tonic-gate #define	VHCI_DEBUG(level, stmnt) \
977c478bd9Sstevel@tonic-gate 	    if (vhci_debug >= (level)) vhci_log stmnt
987c478bd9Sstevel@tonic-gate 
997c478bd9Sstevel@tonic-gate #else	/* !DEBUG */
1007c478bd9Sstevel@tonic-gate 
1017c478bd9Sstevel@tonic-gate #define	VHCI_DEBUG(level, stmnt)
1027c478bd9Sstevel@tonic-gate 
1037c478bd9Sstevel@tonic-gate #endif	/* !DEBUG */
1047c478bd9Sstevel@tonic-gate 
1057c478bd9Sstevel@tonic-gate 
1067c478bd9Sstevel@tonic-gate 
1077c478bd9Sstevel@tonic-gate #define	VHCI_PKT_PRIV_SIZE		2
1087c478bd9Sstevel@tonic-gate 
10953a7b6b6SChris Horne #define	ADDR2VHCI(ap)	((struct scsi_vhci *) \
11053a7b6b6SChris Horne 			((ap)->a_hba_tran->tran_hba_private))
11153a7b6b6SChris Horne #define	ADDR2VLUN(ap)	(scsi_vhci_lun_t *) \
11253a7b6b6SChris Horne 			(scsi_device_hba_private_get(scsi_address_device(ap)))
11353a7b6b6SChris Horne #define	ADDR2DIP(ap)	((dev_info_t *)(scsi_address_device(ap)->sd_dev))
11453a7b6b6SChris Horne 
1157c478bd9Sstevel@tonic-gate #define	HBAPKT2VHCIPKT(pkt) (pkt->pkt_private)
1167c478bd9Sstevel@tonic-gate #define	TGTPKT2VHCIPKT(pkt) (pkt->pkt_ha_private)
1177c478bd9Sstevel@tonic-gate #define	VHCIPKT2HBAPKT(pkt) (pkt->pkt_hba_pkt)
1187c478bd9Sstevel@tonic-gate #define	VHCIPKT2TGTPKT(pkt) (pkt->pkt_tgt_pkt)
1197c478bd9Sstevel@tonic-gate 
12009c4eb3fSMilos Muzik #define	VHCI_DECR_PATH_CMDCOUNT(svp) { \
12109c4eb3fSMilos Muzik 	mutex_enter(&(svp)->svp_mutex); \
12209c4eb3fSMilos Muzik 	(svp)->svp_cmds--; \
12309c4eb3fSMilos Muzik 	if ((svp)->svp_cmds == 0)  \
12409c4eb3fSMilos Muzik 		cv_broadcast(&(svp)->svp_cv); \
12509c4eb3fSMilos Muzik 	mutex_exit(&(svp)->svp_mutex); \
12609c4eb3fSMilos Muzik }
12709c4eb3fSMilos Muzik 
12809c4eb3fSMilos Muzik #define	VHCI_INCR_PATH_CMDCOUNT(svp) { \
12909c4eb3fSMilos Muzik 	mutex_enter(&(svp)->svp_mutex); \
13009c4eb3fSMilos Muzik 	(svp)->svp_cmds++; \
13109c4eb3fSMilos Muzik 	mutex_exit(&(svp)->svp_mutex); \
13209c4eb3fSMilos Muzik }
1337c478bd9Sstevel@tonic-gate 
1347c478bd9Sstevel@tonic-gate /*
1357c478bd9Sstevel@tonic-gate  * When a LUN is HELD it results in new IOs being returned to the target
1367c478bd9Sstevel@tonic-gate  * driver layer with TRAN_BUSY.  Should be used while performing
1377c478bd9Sstevel@tonic-gate  * operations that require prevention of any new IOs to the LUN and
1387c478bd9Sstevel@tonic-gate  * the LUN should be HELD for the duration of such operations.
1397c478bd9Sstevel@tonic-gate  * f can be VH_SLEEP or VH_NOSLEEP.
1407c478bd9Sstevel@tonic-gate  * h is set to 1 to indicate LUN was successfully HELD.
1417c478bd9Sstevel@tonic-gate  * h is set to 0 when f is VH_NOSLEEP and LUN is already HELD.
1427c478bd9Sstevel@tonic-gate  *
1437c478bd9Sstevel@tonic-gate  * Application examples:
1447c478bd9Sstevel@tonic-gate  *
1457c478bd9Sstevel@tonic-gate  * 1) SCSI-II RESERVE: HOLD LUN until it is quiesced and the load balancing
1467c478bd9Sstevel@tonic-gate  * policy is switched to NONE before proceeding with RESERVE handling.
1477c478bd9Sstevel@tonic-gate  *
1487c478bd9Sstevel@tonic-gate  * 2) Failover: HOLD LUN before initiating failover.
1497c478bd9Sstevel@tonic-gate  *
1507c478bd9Sstevel@tonic-gate  * 3) When an externally initiated failover is detected, HOLD LUN until all
1517c478bd9Sstevel@tonic-gate  * path states have been refreshed to reflect the new value.
1527c478bd9Sstevel@tonic-gate  *
1537c478bd9Sstevel@tonic-gate  */
1547c478bd9Sstevel@tonic-gate #define	VHCI_HOLD_LUN(vlun, f, h) { \
1557c478bd9Sstevel@tonic-gate 	int sleep = (f); \
1567c478bd9Sstevel@tonic-gate 	mutex_enter(&(vlun)->svl_mutex); \
1577c478bd9Sstevel@tonic-gate 	if ((vlun)->svl_transient == 1) { \
1587c478bd9Sstevel@tonic-gate 		if (sleep == VH_SLEEP) { \
1597c478bd9Sstevel@tonic-gate 			while ((vlun)->svl_transient == 1) \
1607c478bd9Sstevel@tonic-gate 				cv_wait(&(vlun)->svl_cv, &(vlun)->svl_mutex); \
1617c478bd9Sstevel@tonic-gate 			(vlun)->svl_transient = 1; \
1627c478bd9Sstevel@tonic-gate 			(h) = 1; \
1637c478bd9Sstevel@tonic-gate 		} else { \
1647c478bd9Sstevel@tonic-gate 			(h) = 0; \
1657c478bd9Sstevel@tonic-gate 		} \
1667c478bd9Sstevel@tonic-gate 	} else { \
1677c478bd9Sstevel@tonic-gate 		(vlun)->svl_transient = 1; \
1687c478bd9Sstevel@tonic-gate 		(h) = 1; \
1697c478bd9Sstevel@tonic-gate 	} \
1707c478bd9Sstevel@tonic-gate 	sleep = (h); \
1717c478bd9Sstevel@tonic-gate 	mutex_exit(&(vlun)->svl_mutex); \
1727c478bd9Sstevel@tonic-gate }
1737c478bd9Sstevel@tonic-gate 
1747c478bd9Sstevel@tonic-gate #define	VHCI_RELEASE_LUN(vlun) { \
1757c478bd9Sstevel@tonic-gate 	mutex_enter(&(vlun)->svl_mutex); \
1767c478bd9Sstevel@tonic-gate 	(vlun)->svl_transient = 0; \
1777c478bd9Sstevel@tonic-gate 	cv_broadcast(&(vlun)->svl_cv); \
1787c478bd9Sstevel@tonic-gate 	mutex_exit(&(vlun)->svl_mutex); \
1797c478bd9Sstevel@tonic-gate }
1807c478bd9Sstevel@tonic-gate 
1817c478bd9Sstevel@tonic-gate #define	VHCI_LUN_IS_HELD(vlun)	((vlun)->svl_transient == 1)
1827c478bd9Sstevel@tonic-gate 
1837c478bd9Sstevel@tonic-gate /*
1847c478bd9Sstevel@tonic-gate  * vhci_pkt states
1857c478bd9Sstevel@tonic-gate  */
1867c478bd9Sstevel@tonic-gate #define	VHCI_PKT_IDLE			0x01
1877c478bd9Sstevel@tonic-gate #define	VHCI_PKT_ISSUED			0x02
1887c478bd9Sstevel@tonic-gate #define	VHCI_PKT_ABORTING		0x04
1897c478bd9Sstevel@tonic-gate #define	VHCI_PKT_STALE_BINDING		0x08
1907c478bd9Sstevel@tonic-gate /*
1917c478bd9Sstevel@tonic-gate  * Set the first time taskq is dispatched from scsi_start for
1927c478bd9Sstevel@tonic-gate  * a packet.  To ensure vhci_scsi_start recognizes that the scsi_pkt
1937c478bd9Sstevel@tonic-gate  * is being issued from the taskq and not target driver.
1947c478bd9Sstevel@tonic-gate  */
1957c478bd9Sstevel@tonic-gate #define	VHCI_PKT_THRU_TASKQ		0x20
19640764c95SVictor Li /*
19740764c95SVictor Li  * Set the first time failover is being triggered. To ensure
19840764c95SVictor Li  * failover won't be triggered again when the packet is being
19940764c95SVictor Li  * retried by target driver.
20040764c95SVictor Li  */
20140764c95SVictor Li #define	VHCI_PKT_IN_FAILOVER		0x40
2027c478bd9Sstevel@tonic-gate 
2037c478bd9Sstevel@tonic-gate #define	VHCI_PKT_TIMEOUT		30		/* seconds */
2047c478bd9Sstevel@tonic-gate #define	VHCI_PKT_RETRY_CNT		2
2057c478bd9Sstevel@tonic-gate #define	VHCI_POLL_TIMEOUT		60		/* seconds */
2067c478bd9Sstevel@tonic-gate 
2077c478bd9Sstevel@tonic-gate /*
2087c478bd9Sstevel@tonic-gate  * define extended scsi cmd pkt
2097c478bd9Sstevel@tonic-gate  */
2107c478bd9Sstevel@tonic-gate #define	EXTCMDS_STATUS_SIZE		(sizeof (struct scsi_arq_status))
2117c478bd9Sstevel@tonic-gate 
2127c478bd9Sstevel@tonic-gate #define	CFLAG_NOWAIT		0x1000	/* don't sleep */
2137c478bd9Sstevel@tonic-gate #define	CFLAG_DMA_PARTIAL	0x2000	/* Support Partial DMA */
2147c478bd9Sstevel@tonic-gate 
2157c478bd9Sstevel@tonic-gate /*
2167c478bd9Sstevel@tonic-gate  * Maximum size of SCSI cdb in SCSI command
2177c478bd9Sstevel@tonic-gate  */
2187c478bd9Sstevel@tonic-gate #define	VHCI_SCSI_CDB_SIZE		16
2197c478bd9Sstevel@tonic-gate #define	VHCI_SCSI_SCB_SIZE		(sizeof (struct scsi_arq_status))
2207c478bd9Sstevel@tonic-gate 
221f8404091SRamana.Srikanth /*
222f8404091SRamana.Srikanth  * OSD specific definitions
223f8404091SRamana.Srikanth  */
224f8404091SRamana.Srikanth #define	VHCI_SCSI_OSD_CDB_SIZE		224
225f8404091SRamana.Srikanth #define	VHCI_SCSI_OSD_PKT_FLAGS		0x100000
226f8404091SRamana.Srikanth 
2277c478bd9Sstevel@tonic-gate /*
2287c478bd9Sstevel@tonic-gate  * flag to determine failover support
2297c478bd9Sstevel@tonic-gate  */
2307c478bd9Sstevel@tonic-gate #define	SCSI_NO_FAILOVER	0x0
2317c478bd9Sstevel@tonic-gate #define	SCSI_IMPLICIT_FAILOVER	0x1
2327c478bd9Sstevel@tonic-gate #define	SCSI_EXPLICIT_FAILOVER	0x2
2337c478bd9Sstevel@tonic-gate #define	SCSI_BOTH_FAILOVER \
2347c478bd9Sstevel@tonic-gate 	(SCSI_IMPLICIT_FAILOVER |  SCSI_EXPLICIT_FAILOVER)
2357c478bd9Sstevel@tonic-gate 
2367c478bd9Sstevel@tonic-gate struct	scsi_vhci_swarg;
2377c478bd9Sstevel@tonic-gate 
2383f51917eSrralphs #define	VHCI_NUM_RESV_KEYS	8
2393f51917eSrralphs 
2407c478bd9Sstevel@tonic-gate typedef struct vhci_prin_readkeys {
2417c478bd9Sstevel@tonic-gate 	uint32_t		generation;
2427c478bd9Sstevel@tonic-gate 	uint32_t		length;
2433f51917eSrralphs 	mhioc_resv_key_t	keylist[VHCI_NUM_RESV_KEYS];
2447c478bd9Sstevel@tonic-gate } vhci_prin_readkeys_t;
2457c478bd9Sstevel@tonic-gate 
2467c478bd9Sstevel@tonic-gate #define	VHCI_PROUT_SIZE	\
2477c478bd9Sstevel@tonic-gate 	((sizeof (vhci_prout_t) - 2 * (MHIOC_RESV_KEY_SIZE) * sizeof (char)))
2487c478bd9Sstevel@tonic-gate 
2497c478bd9Sstevel@tonic-gate typedef struct vhci_prout {
2507c478bd9Sstevel@tonic-gate 	/* PGR register parameters start */
2517c478bd9Sstevel@tonic-gate 	uchar_t		res_key[MHIOC_RESV_KEY_SIZE];
2527c478bd9Sstevel@tonic-gate 	uchar_t		service_key[MHIOC_RESV_KEY_SIZE];
2537c478bd9Sstevel@tonic-gate 	uint32_t	scope_address;
2547c478bd9Sstevel@tonic-gate 
2557c478bd9Sstevel@tonic-gate #if defined(_BIT_FIELDS_LTOH)
2567c478bd9Sstevel@tonic-gate 	uchar_t		aptpl:1,
2577c478bd9Sstevel@tonic-gate 			reserved:7;
2587c478bd9Sstevel@tonic-gate #else
2597c478bd9Sstevel@tonic-gate 	uchar_t		reserved:7,
2607c478bd9Sstevel@tonic-gate 			aptpl:1;
2617c478bd9Sstevel@tonic-gate #endif /* _BIT_FIELDS_LTOH */
2627c478bd9Sstevel@tonic-gate 
2637c478bd9Sstevel@tonic-gate 	uchar_t		reserved_1;
2647c478bd9Sstevel@tonic-gate 	uint16_t	ext_len;
2657c478bd9Sstevel@tonic-gate 	/* PGR register parameters end */
2667c478bd9Sstevel@tonic-gate 
2677c478bd9Sstevel@tonic-gate 	/* Update VHCI_PROUT_SIZE if new fields are added here */
2687c478bd9Sstevel@tonic-gate 
2697c478bd9Sstevel@tonic-gate 	uchar_t		active_res_key[MHIOC_RESV_KEY_SIZE];
2707c478bd9Sstevel@tonic-gate 	uchar_t		active_service_key[MHIOC_RESV_KEY_SIZE];
2717c478bd9Sstevel@tonic-gate } vhci_prout_t;
2727c478bd9Sstevel@tonic-gate 
2737c478bd9Sstevel@tonic-gate #define	VHCI_PROUT_REGISTER	0x0
2747c478bd9Sstevel@tonic-gate #define	VHCI_PROUT_RESERVE	0x1
2757c478bd9Sstevel@tonic-gate #define	VHCI_PROUT_RELEASE	0x2
2767c478bd9Sstevel@tonic-gate #define	VHCI_PROUT_CLEAR	0x3
2777c478bd9Sstevel@tonic-gate #define	VHCI_PROUT_PREEMPT	0x4
2787c478bd9Sstevel@tonic-gate #define	VHCI_PROUT_P_AND_A	0x5
2797c478bd9Sstevel@tonic-gate #define	VHCI_PROUT_R_AND_IGNORE	0x6
2807c478bd9Sstevel@tonic-gate 
2817c478bd9Sstevel@tonic-gate struct vhci_pkt {
2827c478bd9Sstevel@tonic-gate 	struct scsi_pkt			*vpkt_tgt_pkt;
2831e1ddd6cScth 	mdi_pathinfo_t			*vpkt_path;	/* path pkt bound to */
2847c478bd9Sstevel@tonic-gate 
2857c478bd9Sstevel@tonic-gate 	/*
2867c478bd9Sstevel@tonic-gate 	 * pHCI packet that does the actual work.
2877c478bd9Sstevel@tonic-gate 	 */
2887c478bd9Sstevel@tonic-gate 	struct scsi_pkt			*vpkt_hba_pkt;
2897c478bd9Sstevel@tonic-gate 
2907c478bd9Sstevel@tonic-gate 	uint_t				vpkt_state;
2917c478bd9Sstevel@tonic-gate 	uint_t				vpkt_flags;
2927c478bd9Sstevel@tonic-gate 
2937c478bd9Sstevel@tonic-gate 	/*
2947c478bd9Sstevel@tonic-gate 	 * copy of vhci_scsi_init_pkt args.  Used when we invoke
2957c478bd9Sstevel@tonic-gate 	 * scsi_init_pkt() of the pHCI corresponding to the path that we
2967c478bd9Sstevel@tonic-gate 	 * bind to
2977c478bd9Sstevel@tonic-gate 	 */
2987c478bd9Sstevel@tonic-gate 	int				vpkt_tgt_init_cdblen;
2997c478bd9Sstevel@tonic-gate 	int				vpkt_tgt_init_scblen;
3007c478bd9Sstevel@tonic-gate 	int				vpkt_tgt_init_pkt_flags;
3017c478bd9Sstevel@tonic-gate 	struct buf			*vpkt_tgt_init_bp;
3029cf90c49Sdh 
3039cf90c49Sdh 	/*
3049cf90c49Sdh 	 * Pointer to original struct vhci_pkt for cmd send by ssd.
3059cf90c49Sdh 	 * Saved when the command is being retried internally.
3069cf90c49Sdh 	 */
3079cf90c49Sdh 	struct vhci_pkt			*vpkt_org_vpkt;
3087c478bd9Sstevel@tonic-gate };
3097c478bd9Sstevel@tonic-gate 
3107c478bd9Sstevel@tonic-gate typedef struct scsi_vhci_lun {
3117c478bd9Sstevel@tonic-gate 	kmutex_t		svl_mutex;
3127c478bd9Sstevel@tonic-gate 	kcondvar_t		svl_cv;
3137c478bd9Sstevel@tonic-gate 
3147c478bd9Sstevel@tonic-gate 	/*
3157c478bd9Sstevel@tonic-gate 	 * following three fields are under svl_mutex protection
3167c478bd9Sstevel@tonic-gate 	 */
3177c478bd9Sstevel@tonic-gate 	int			svl_transient;
3187c478bd9Sstevel@tonic-gate 
3197c478bd9Sstevel@tonic-gate 	/*
3207c478bd9Sstevel@tonic-gate 	 * to prevent unnecessary failover when a device is
3217c478bd9Sstevel@tonic-gate 	 * is discovered across a passive path and active path
3227c478bd9Sstevel@tonic-gate 	 * is still comng up
3237c478bd9Sstevel@tonic-gate 	 */
3247c478bd9Sstevel@tonic-gate 	int			svl_waiting_for_activepath;
325aa6577ebSJosef 'Jeff' Sipek 	hrtime_t		svl_wfa_time;
3267c478bd9Sstevel@tonic-gate 
32740764c95SVictor Li 	/*
32840764c95SVictor Li 	 * to keep the failover status in order to return the
32940764c95SVictor Li 	 * failure status to target driver when targer driver
33040764c95SVictor Li 	 * retries the command which originally triggered the
33140764c95SVictor Li 	 * failover.
33240764c95SVictor Li 	 */
33340764c95SVictor Li 	int			svl_failover_status;
33440764c95SVictor Li 
3357c478bd9Sstevel@tonic-gate 	/*
3367c478bd9Sstevel@tonic-gate 	 * for RESERVE/RELEASE support
3377c478bd9Sstevel@tonic-gate 	 */
3387c478bd9Sstevel@tonic-gate 	client_lb_t		svl_lb_policy_save;
3397c478bd9Sstevel@tonic-gate 
3401e1ddd6cScth 	/*
3411e1ddd6cScth 	 * Failover ops and ops name selected for the lun.
3421e1ddd6cScth 	 */
3437c478bd9Sstevel@tonic-gate 	struct scsi_failover_ops	*svl_fops;
3441e1ddd6cScth 	char			*svl_fops_name;
3451e1ddd6cScth 
3467c478bd9Sstevel@tonic-gate 	void			*svl_fops_ctpriv;
3471e1ddd6cScth 
3487c478bd9Sstevel@tonic-gate 	struct scsi_vhci_lun	*svl_hash_next;
3497c478bd9Sstevel@tonic-gate 	char			*svl_lun_wwn;
3507c478bd9Sstevel@tonic-gate 
3517c478bd9Sstevel@tonic-gate 	/*
3527c478bd9Sstevel@tonic-gate 	 * currently active pathclass
3537c478bd9Sstevel@tonic-gate 	 */
3547c478bd9Sstevel@tonic-gate 	char			*svl_active_pclass;
3557c478bd9Sstevel@tonic-gate 
3567c478bd9Sstevel@tonic-gate 	dev_info_t		*svl_dip;
3577c478bd9Sstevel@tonic-gate 	uint32_t		svl_flags;	/* protected by svl_mutex */
3587c478bd9Sstevel@tonic-gate 
3597c478bd9Sstevel@tonic-gate 	/*
3607c478bd9Sstevel@tonic-gate 	 * When SCSI-II reservations are active we set the following pip
3617c478bd9Sstevel@tonic-gate 	 * to point to the path holding the reservation.  As long as
3627c478bd9Sstevel@tonic-gate 	 * the reservation is active this svl_resrv_pip is bound for the
3637c478bd9Sstevel@tonic-gate 	 * transport directly.  We bypass calling mdi_select_path to return
3647c478bd9Sstevel@tonic-gate 	 * a pip.
3657c478bd9Sstevel@tonic-gate 	 * The following pip is only valid when VLUN_RESERVE_ACTIVE_FLG
3667c478bd9Sstevel@tonic-gate 	 * is set.  This pip should not be accessed if this flag is reset.
3677c478bd9Sstevel@tonic-gate 	 */
3687c478bd9Sstevel@tonic-gate 	mdi_pathinfo_t	*svl_resrv_pip;
3697c478bd9Sstevel@tonic-gate 
3707c478bd9Sstevel@tonic-gate 	/*
3717c478bd9Sstevel@tonic-gate 	 * following fields are for PGR support
3727c478bd9Sstevel@tonic-gate 	 */
3737c478bd9Sstevel@tonic-gate 	taskq_t			*svl_taskq;
3747c478bd9Sstevel@tonic-gate 	ksema_t			svl_pgr_sema;	/* PGR serialization */
3757c478bd9Sstevel@tonic-gate 	vhci_prin_readkeys_t	svl_prin;	/* PGR in data */
3767c478bd9Sstevel@tonic-gate 	vhci_prout_t		svl_prout;	/* PGR out data */
3777c478bd9Sstevel@tonic-gate 	uchar_t			svl_cdb[CDB_GROUP4];
3787c478bd9Sstevel@tonic-gate 	int			svl_time;	/* pkt_time */
3797c478bd9Sstevel@tonic-gate 	uint32_t		svl_bcount;	/* amount of data */
3807c478bd9Sstevel@tonic-gate 	int			svl_pgr_active; /* registrations active */
3817c478bd9Sstevel@tonic-gate 	mdi_pathinfo_t		*svl_first_path;
3827c478bd9Sstevel@tonic-gate 
3837c478bd9Sstevel@tonic-gate 	/* external failover */
3847c478bd9Sstevel@tonic-gate 	int			svl_efo_update_path;
3857c478bd9Sstevel@tonic-gate 	struct	scsi_vhci_swarg	*svl_swarg;
3867c478bd9Sstevel@tonic-gate 
3877c478bd9Sstevel@tonic-gate 	uint32_t		svl_support_lun_reset; /* Lun reset support */
3887c478bd9Sstevel@tonic-gate 	int			svl_not_supported;
3897c478bd9Sstevel@tonic-gate 	int			svl_xlf_capable; /* XLF implementation */
3907c478bd9Sstevel@tonic-gate 	int			svl_sector_size;
3917c478bd9Sstevel@tonic-gate 	int			svl_setcap_done;
3927c478bd9Sstevel@tonic-gate 	uint16_t		svl_fo_support;	 /* failover mode */
3937c478bd9Sstevel@tonic-gate } scsi_vhci_lun_t;
3947c478bd9Sstevel@tonic-gate 
3957c478bd9Sstevel@tonic-gate #define	VLUN_TASK_D_ALIVE_FLG		0x01
3967c478bd9Sstevel@tonic-gate 
3977c478bd9Sstevel@tonic-gate /*
3987c478bd9Sstevel@tonic-gate  * This flag is used to monitor the state of SCSI-II RESERVATION on the
3997c478bd9Sstevel@tonic-gate  * lun.  A SCSI-II RESERVE cmd may be accepted by the target on the inactive
4007c478bd9Sstevel@tonic-gate  * path.  This would then cause a subsequent IO to cause the paths to be
4017c478bd9Sstevel@tonic-gate  * updated and be returned with a reservation conflict.  By monitoring this
4027c478bd9Sstevel@tonic-gate  * flag, and sending a reset to the target when needed to clear the reservation,
4037c478bd9Sstevel@tonic-gate  * one can avoid this conflict.
4047c478bd9Sstevel@tonic-gate  */
4057c478bd9Sstevel@tonic-gate #define	VLUN_RESERVE_ACTIVE_FLG		0x04
4067c478bd9Sstevel@tonic-gate 
4077c478bd9Sstevel@tonic-gate /*
4087c478bd9Sstevel@tonic-gate  * This flag is set when a SCSI-II RESERVE cmd is received by scsi_vhci
4097c478bd9Sstevel@tonic-gate  * and cleared when the pkt completes in vhci_intr.  It ensures that the
4107c478bd9Sstevel@tonic-gate  * lun remains quiesced for the duration of this pkt.  This is different
4117c478bd9Sstevel@tonic-gate  * from VHCI_HOLD_LUN as this pertains to IOs only.
4127c478bd9Sstevel@tonic-gate  */
4137c478bd9Sstevel@tonic-gate #define	VLUN_QUIESCED_FLG		0x08
4147c478bd9Sstevel@tonic-gate 
415ee28b439Scm /*
416ee28b439Scm  * This flag is set to tell vhci_update_pathstates to call back
417ee28b439Scm  * into vhci_mpapi_update_tpg_acc_state.
418ee28b439Scm  */
419ee28b439Scm #define	VLUN_UPDATE_TPG			0x10
420ee28b439Scm 
4217c478bd9Sstevel@tonic-gate /*
4227c478bd9Sstevel@tonic-gate  * Various reset recovery depth.
4237c478bd9Sstevel@tonic-gate  */
4247c478bd9Sstevel@tonic-gate 
4257c478bd9Sstevel@tonic-gate #define	VHCI_DEPTH_ALL		3
4267c478bd9Sstevel@tonic-gate #define	VHCI_DEPTH_TARGET	2
4277c478bd9Sstevel@tonic-gate #define	VHCI_DEPTH_LUN		1	/* For the sake completeness */
4287c478bd9Sstevel@tonic-gate #define	TRUE			(1)
4297c478bd9Sstevel@tonic-gate #define	FALSE			(0)
4307c478bd9Sstevel@tonic-gate 
4317c478bd9Sstevel@tonic-gate /*
4327c478bd9Sstevel@tonic-gate  * this is stashed away in the client private area of
4337c478bd9Sstevel@tonic-gate  * pathinfo
4347c478bd9Sstevel@tonic-gate  */
4357c478bd9Sstevel@tonic-gate typedef struct scsi_vhci_priv {
4367c478bd9Sstevel@tonic-gate 	kmutex_t		svp_mutex;
4377c478bd9Sstevel@tonic-gate 	kcondvar_t		svp_cv;
4387c478bd9Sstevel@tonic-gate 	struct scsi_vhci_lun	*svp_svl;
4397c478bd9Sstevel@tonic-gate 
4407c478bd9Sstevel@tonic-gate 	/*
4417c478bd9Sstevel@tonic-gate 	 * scsi device associated with this
4427c478bd9Sstevel@tonic-gate 	 * pathinfo
4437c478bd9Sstevel@tonic-gate 	 */
4447c478bd9Sstevel@tonic-gate 	struct scsi_device	*svp_psd;
4457c478bd9Sstevel@tonic-gate 
4467c478bd9Sstevel@tonic-gate 	/*
4477c478bd9Sstevel@tonic-gate 	 * number of outstanding commands on this
4487c478bd9Sstevel@tonic-gate 	 * path.  Protected by svp_mutex
4497c478bd9Sstevel@tonic-gate 	 */
4507c478bd9Sstevel@tonic-gate 	int			svp_cmds;
4517c478bd9Sstevel@tonic-gate 
4527c478bd9Sstevel@tonic-gate 	/*
4537c478bd9Sstevel@tonic-gate 	 * following is used to prevent packets completing with the
4547c478bd9Sstevel@tonic-gate 	 * same error reason from flooding the screen
4557c478bd9Sstevel@tonic-gate 	 */
4567c478bd9Sstevel@tonic-gate 	uchar_t			svp_last_pkt_reason;
4577c478bd9Sstevel@tonic-gate 
4587c478bd9Sstevel@tonic-gate 	/* external failover scsi_watch token */
4597c478bd9Sstevel@tonic-gate 	opaque_t		svp_sw_token;
4607c478bd9Sstevel@tonic-gate 
4617c478bd9Sstevel@tonic-gate 	/* any cleanup operations for a newly found path. */
4627c478bd9Sstevel@tonic-gate 	int			svp_new_path;
4637c478bd9Sstevel@tonic-gate } scsi_vhci_priv_t;
4647c478bd9Sstevel@tonic-gate 
4657c478bd9Sstevel@tonic-gate /*
4667c478bd9Sstevel@tonic-gate  * argument to scsi_watch callback.  Used for processing
4677c478bd9Sstevel@tonic-gate  * externally initiated failovers
4687c478bd9Sstevel@tonic-gate  */
4697c478bd9Sstevel@tonic-gate typedef struct scsi_vhci_swarg {
4707c478bd9Sstevel@tonic-gate 	scsi_vhci_priv_t	*svs_svp;
471aa6577ebSJosef 'Jeff' Sipek 	hrtime_t		svs_tos;	/* time of submission */
4727c478bd9Sstevel@tonic-gate 	mdi_pathinfo_t		*svs_pi;	/* pathinfo being "watched" */
4737c478bd9Sstevel@tonic-gate 	int			svs_release_lun;
4747c478bd9Sstevel@tonic-gate 	int			svs_done;
4757c478bd9Sstevel@tonic-gate } scsi_vhci_swarg_t;
4767c478bd9Sstevel@tonic-gate 
4777c478bd9Sstevel@tonic-gate /*
4787c478bd9Sstevel@tonic-gate  * scsi_vhci softstate
4797c478bd9Sstevel@tonic-gate  *
4807c478bd9Sstevel@tonic-gate  * vhci_mutex protects
4817c478bd9Sstevel@tonic-gate  *	vhci_state
4827c478bd9Sstevel@tonic-gate  * and	vhci_reset_notify list
4837c478bd9Sstevel@tonic-gate  */
4847c478bd9Sstevel@tonic-gate struct scsi_vhci {
4857c478bd9Sstevel@tonic-gate 	kmutex_t			vhci_mutex;
4867c478bd9Sstevel@tonic-gate 	dev_info_t			*vhci_dip;
4877c478bd9Sstevel@tonic-gate 	struct scsi_hba_tran		*vhci_tran;
4887c478bd9Sstevel@tonic-gate 	uint32_t			vhci_state;
4897c478bd9Sstevel@tonic-gate 	uint32_t			vhci_instance;
4907c478bd9Sstevel@tonic-gate 	kstat_t				vhci_kstat;
4917c478bd9Sstevel@tonic-gate 	/*
4927c478bd9Sstevel@tonic-gate 	 * This taskq is for general vhci operations like reservations,
4937c478bd9Sstevel@tonic-gate 	 * auto-failback, etc.
4947c478bd9Sstevel@tonic-gate 	 */
4957c478bd9Sstevel@tonic-gate 	taskq_t				*vhci_taskq;
4967c478bd9Sstevel@tonic-gate 	/* Dedicate taskq to handle external failovers */
4977c478bd9Sstevel@tonic-gate 	taskq_t				*vhci_update_pathstates_taskq;
4987c478bd9Sstevel@tonic-gate 	struct scsi_reset_notify_entry	*vhci_reset_notify_listf;
4997c478bd9Sstevel@tonic-gate 	uint16_t			vhci_conf_flags;
5008c4f8890Srs 	mpapi_priv_t			*mp_priv;
5017c478bd9Sstevel@tonic-gate };
5027c478bd9Sstevel@tonic-gate 
5037c478bd9Sstevel@tonic-gate /*
5047c478bd9Sstevel@tonic-gate  * vHCI flags for configuration settings, defined in scsi_vhci.conf
5057c478bd9Sstevel@tonic-gate  */
5067c478bd9Sstevel@tonic-gate #define	VHCI_CONF_FLAGS_AUTO_FAILBACK	0x0001	/* Enables auto failback */
5077c478bd9Sstevel@tonic-gate 
5087c478bd9Sstevel@tonic-gate typedef enum {
5097c478bd9Sstevel@tonic-gate 	SCSI_PATH_INACTIVE,
5107c478bd9Sstevel@tonic-gate 	SCSI_PATH_ACTIVE,
5117c478bd9Sstevel@tonic-gate 	SCSI_PATH_ACTIVE_NONOPT
5127c478bd9Sstevel@tonic-gate } scsi_path_state_t;
5137c478bd9Sstevel@tonic-gate 
5147c478bd9Sstevel@tonic-gate #define	SCSI_MAXPCLASSLEN	25
5157c478bd9Sstevel@tonic-gate 
5167c478bd9Sstevel@tonic-gate #define	OPINFO_REV	1
5177c478bd9Sstevel@tonic-gate 
5187c478bd9Sstevel@tonic-gate /*
5197c478bd9Sstevel@tonic-gate  * structure describing operational characteristics of
5207c478bd9Sstevel@tonic-gate  * path
5217c478bd9Sstevel@tonic-gate  */
5227c478bd9Sstevel@tonic-gate struct scsi_path_opinfo {
5237c478bd9Sstevel@tonic-gate 	int			opinfo_rev;
5247c478bd9Sstevel@tonic-gate 
5257c478bd9Sstevel@tonic-gate 	/*
5267c478bd9Sstevel@tonic-gate 	 * name of pathclass. Eg. "primary", "secondary"
5277c478bd9Sstevel@tonic-gate 	 */
5287c478bd9Sstevel@tonic-gate 	char			opinfo_path_attr[SCSI_MAXPCLASSLEN];
5297c478bd9Sstevel@tonic-gate 
5307c478bd9Sstevel@tonic-gate 	/*
5317c478bd9Sstevel@tonic-gate 	 * path state: ACTIVE/PASSIVE
5327c478bd9Sstevel@tonic-gate 	 */
5337c478bd9Sstevel@tonic-gate 	scsi_path_state_t	opinfo_path_state;
5347c478bd9Sstevel@tonic-gate 
5357c478bd9Sstevel@tonic-gate 	/*
5367c478bd9Sstevel@tonic-gate 	 * the best and worst case time estimates for
5377c478bd9Sstevel@tonic-gate 	 * failover operation to complete
5387c478bd9Sstevel@tonic-gate 	 */
5397c478bd9Sstevel@tonic-gate 	uint_t			opinfo_pswtch_best;
5407c478bd9Sstevel@tonic-gate 	uint_t			opinfo_pswtch_worst;
5417c478bd9Sstevel@tonic-gate 
5427c478bd9Sstevel@tonic-gate 	/* XLF implementation */
5437c478bd9Sstevel@tonic-gate 	int			opinfo_xlf_capable;
5447c478bd9Sstevel@tonic-gate 	uint16_t		opinfo_preferred;
5457c478bd9Sstevel@tonic-gate 	uint16_t		opinfo_mode;
5467c478bd9Sstevel@tonic-gate 
5477c478bd9Sstevel@tonic-gate };
5487c478bd9Sstevel@tonic-gate 
5497c478bd9Sstevel@tonic-gate 
5507c478bd9Sstevel@tonic-gate #define	SFO_REV		1
5517c478bd9Sstevel@tonic-gate 
5527c478bd9Sstevel@tonic-gate /*
5537c478bd9Sstevel@tonic-gate  * vectors for device specific failover related operations
5547c478bd9Sstevel@tonic-gate  */
5557c478bd9Sstevel@tonic-gate struct scsi_failover_ops {
5567c478bd9Sstevel@tonic-gate 	int	sfo_rev;
5577c478bd9Sstevel@tonic-gate 
5581e1ddd6cScth 	/*
5591e1ddd6cScth 	 * failover module name, begins with "f_"
5601e1ddd6cScth 	 */
5611e1ddd6cScth 	char	*sfo_name;
5621e1ddd6cScth 
5631e1ddd6cScth 	/*
5641e1ddd6cScth 	 * devices supported by failover module
5651e1ddd6cScth 	 *
5661e1ddd6cScth 	 * NOTE: this is an aproximation, sfo_device_probe has the final say.
5671e1ddd6cScth 	 */
5681e1ddd6cScth 	char	**sfo_devices;
5691e1ddd6cScth 
5701e1ddd6cScth 	/*
5711e1ddd6cScth 	 * initialize the failover module
5721e1ddd6cScth 	 */
5731e1ddd6cScth 	void	(*sfo_init)();
5741e1ddd6cScth 
5757c478bd9Sstevel@tonic-gate 	/*
5767c478bd9Sstevel@tonic-gate 	 * identify device
5777c478bd9Sstevel@tonic-gate 	 */
5787c478bd9Sstevel@tonic-gate 	int	(*sfo_device_probe)(
5797c478bd9Sstevel@tonic-gate 			struct scsi_device	*sd,
5801e1ddd6cScth 			struct scsi_inquiry	*stdinq,
5811e1ddd6cScth 			void			**ctpriv);
5827c478bd9Sstevel@tonic-gate 
5837c478bd9Sstevel@tonic-gate 	/*
5847c478bd9Sstevel@tonic-gate 	 * housekeeping (free memory etc alloc'ed during probe
5857c478bd9Sstevel@tonic-gate 	 */
5867c478bd9Sstevel@tonic-gate 	void	(*sfo_device_unprobe)(
5871e1ddd6cScth 			struct scsi_device	*sd,
5881e1ddd6cScth 			void			*ctpriv);
5897c478bd9Sstevel@tonic-gate 
5907c478bd9Sstevel@tonic-gate 	/*
5917c478bd9Sstevel@tonic-gate 	 * bring a path ONLINE (ie make it ACTIVE)
5927c478bd9Sstevel@tonic-gate 	 */
5937c478bd9Sstevel@tonic-gate 	int	(*sfo_path_activate)(
5941e1ddd6cScth 			struct scsi_device	*sd,
5951e1ddd6cScth 			char			*pathclass,
5961e1ddd6cScth 			void			*ctpriv);
5977c478bd9Sstevel@tonic-gate 
5987c478bd9Sstevel@tonic-gate 	/*
5997c478bd9Sstevel@tonic-gate 	 * inverse of above
6007c478bd9Sstevel@tonic-gate 	 */
6011e1ddd6cScth 	int	(*sfo_path_deactivate)(
6021e1ddd6cScth 			struct scsi_device	*sd,
6031e1ddd6cScth 			char			*pathclass,
6041e1ddd6cScth 			void			*ctpriv);
6057c478bd9Sstevel@tonic-gate 
6067c478bd9Sstevel@tonic-gate 	/*
6077c478bd9Sstevel@tonic-gate 	 * returns operational characteristics of path
6087c478bd9Sstevel@tonic-gate 	 */
6097c478bd9Sstevel@tonic-gate 	int	(*sfo_path_get_opinfo)(
6101e1ddd6cScth 			struct scsi_device	*sd,
6117c478bd9Sstevel@tonic-gate 			struct scsi_path_opinfo *opinfo,
6121e1ddd6cScth 			void			*ctpriv);
6137c478bd9Sstevel@tonic-gate 
6147c478bd9Sstevel@tonic-gate 	/*
6157c478bd9Sstevel@tonic-gate 	 * verify path is operational
6167c478bd9Sstevel@tonic-gate 	 */
6177c478bd9Sstevel@tonic-gate 	int	(*sfo_path_ping)(
6181e1ddd6cScth 			struct scsi_device	*sd,
6191e1ddd6cScth 			void			*ctpriv);
6207c478bd9Sstevel@tonic-gate 
6217c478bd9Sstevel@tonic-gate 	/*
6227c478bd9Sstevel@tonic-gate 	 * analyze SENSE data to detect externally initiated
6237c478bd9Sstevel@tonic-gate 	 * failovers
6247c478bd9Sstevel@tonic-gate 	 */
6257c478bd9Sstevel@tonic-gate 	int	(*sfo_analyze_sense)(
6260c45178bSwl 			struct scsi_device	*sd,
6270c45178bSwl 			uint8_t			*sense,
6280c45178bSwl 			void			*ctpriv);
6297c478bd9Sstevel@tonic-gate 
6307c478bd9Sstevel@tonic-gate 	/*
6317c478bd9Sstevel@tonic-gate 	 * return the next pathclass in order of preference
6327c478bd9Sstevel@tonic-gate 	 * eg. "secondary" comes after "primary"
6337c478bd9Sstevel@tonic-gate 	 */
6347c478bd9Sstevel@tonic-gate 	int	(*sfo_pathclass_next)(
6351e1ddd6cScth 			char			*cur,
6361e1ddd6cScth 			char			**nxt,
6371e1ddd6cScth 			void			*ctpriv);
6387c478bd9Sstevel@tonic-gate };
6397c478bd9Sstevel@tonic-gate 
6401e1ddd6cScth /*
6411e1ddd6cScth  * Names of (too) 'well-known' failover ops.
6421e1ddd6cScth  *   NOTE: consumers of these names should look for a better way...
6431e1ddd6cScth  */
6441e1ddd6cScth #define	SFO_NAME_SYM		"f_sym"
6451e1ddd6cScth #define	SFO_NAME_TPGS		"f_tpgs"
646860de861Shtk #define	SCSI_FAILOVER_IS_ASYM(svl)	\
647860de861Shtk 	((svl) ? ((svl)->svl_fo_support != SCSI_NO_FAILOVER) : 0)
6481e1ddd6cScth #define	SCSI_FAILOVER_IS_TPGS(sfo)	\
6491e1ddd6cScth 	((sfo) ? (strcmp((sfo)->sfo_name, SFO_NAME_TPGS) == 0) : 0)
6501e1ddd6cScth 
6511e1ddd6cScth /*
6521e1ddd6cScth  * Macro to provide plumbing for basic failover module
6531e1ddd6cScth  */
6549a70fc3bSMark J. Nelson #define	_SCSI_FAILOVER_OP(sfo_name, local_name, ops_name)		\
6551e1ddd6cScth 	static struct modlmisc modlmisc = {				\
6569a70fc3bSMark J. Nelson 		&mod_miscops, sfo_name					\
6571e1ddd6cScth 	};								\
6581e1ddd6cScth 	static struct modlinkage modlinkage = {				\
6591e1ddd6cScth 		MODREV_1, (void *)&modlmisc, NULL			\
6601e1ddd6cScth 	};								\
6611e1ddd6cScth 	int	_init()							\
6621e1ddd6cScth 	{								\
6631e1ddd6cScth 		return (mod_install(&modlinkage));			\
6641e1ddd6cScth 	}								\
6651e1ddd6cScth 	int	_fini()							\
6661e1ddd6cScth 	{								\
6671e1ddd6cScth 		return (mod_remove(&modlinkage));			\
6681e1ddd6cScth 	}								\
6691e1ddd6cScth 	int	_info(struct modinfo *modinfop)				\
6701e1ddd6cScth 	{								\
6711e1ddd6cScth 		return (mod_info(&modlinkage, modinfop));		\
6721e1ddd6cScth 	}								\
6731e1ddd6cScth 	static int	local_name##_device_probe(			\
6741e1ddd6cScth 				struct scsi_device *,			\
6751e1ddd6cScth 				struct scsi_inquiry *, void **);	\
6761e1ddd6cScth 	static void	local_name##_device_unprobe(			\
6771e1ddd6cScth 				struct scsi_device *, void *);		\
6781e1ddd6cScth 	static int	local_name##_path_activate(			\
6791e1ddd6cScth 				struct scsi_device *, char *, void *);	\
6801e1ddd6cScth 	static int	local_name##_path_deactivate(			\
6811e1ddd6cScth 				struct scsi_device *, char *, void *);	\
6821e1ddd6cScth 	static int	local_name##_path_get_opinfo(			\
6831e1ddd6cScth 				struct scsi_device *,			\
6841e1ddd6cScth 				struct scsi_path_opinfo *, void *);	\
6851e1ddd6cScth 	static int	local_name##_path_ping(				\
6861e1ddd6cScth 				struct scsi_device *, void *);		\
6871e1ddd6cScth 	static int	local_name##_analyze_sense(			\
6881e1ddd6cScth 				struct scsi_device *,			\
6890c45178bSwl 				uint8_t *, void *);			\
6901e1ddd6cScth 	static int	local_name##_pathclass_next(			\
6911e1ddd6cScth 				char *, char **, void *);		\
6921e1ddd6cScth 	struct scsi_failover_ops ops_name##_failover_ops = {		\
6931e1ddd6cScth 		SFO_REV,						\
6941e1ddd6cScth 		sfo_name,						\
6951e1ddd6cScth 		local_name##_dev_table,					\
6961e1ddd6cScth 		NULL,							\
6971e1ddd6cScth 		local_name##_device_probe,				\
6981e1ddd6cScth 		local_name##_device_unprobe,				\
6991e1ddd6cScth 		local_name##_path_activate,				\
7001e1ddd6cScth 		local_name##_path_deactivate,				\
7011e1ddd6cScth 		local_name##_path_get_opinfo,				\
7021e1ddd6cScth 		local_name##_path_ping,					\
7031e1ddd6cScth 		local_name##_analyze_sense,				\
7041e1ddd6cScth 		local_name##_pathclass_next				\
7051e1ddd6cScth 	}
7061e1ddd6cScth 
7071e1ddd6cScth #ifdef	lint
7089a70fc3bSMark J. Nelson #define	SCSI_FAILOVER_OP(sfo_name, local_name)				\
7099a70fc3bSMark J. Nelson 	_SCSI_FAILOVER_OP(sfo_name, local_name, local_name)
7101e1ddd6cScth #else	/* lint */
7119a70fc3bSMark J. Nelson #define	SCSI_FAILOVER_OP(sfo_name, local_name)				\
7129a70fc3bSMark J. Nelson 	_SCSI_FAILOVER_OP(sfo_name, local_name, scsi_vhci)
7131e1ddd6cScth #endif	/* lint */
7141e1ddd6cScth 
7151e1ddd6cScth /*
7161e1ddd6cScth  * Return values for sfo_device_probe
7171e1ddd6cScth  */
7181e1ddd6cScth #define	SFO_DEVICE_PROBE_VHCI	1	/* supported under scsi_vhci */
7191e1ddd6cScth #define	SFO_DEVICE_PROBE_PHCI	0	/* not supported under scsi_vhci */
7201e1ddd6cScth 
7217c478bd9Sstevel@tonic-gate /* return values for sfo_analyze_sense() */
7227c478bd9Sstevel@tonic-gate #define	SCSI_SENSE_NOFAILOVER		0
7237c478bd9Sstevel@tonic-gate #define	SCSI_SENSE_FAILOVER_INPROG	1
7247c478bd9Sstevel@tonic-gate #define	SCSI_SENSE_ACT2INACT		2
7257c478bd9Sstevel@tonic-gate #define	SCSI_SENSE_INACT2ACT		3
7267c478bd9Sstevel@tonic-gate #define	SCSI_SENSE_INACTIVE		4
7277c478bd9Sstevel@tonic-gate #define	SCSI_SENSE_UNKNOWN		5
7287c478bd9Sstevel@tonic-gate #define	SCSI_SENSE_STATE_CHANGED	6
72902bd0b09Scm #define	SCSI_SENSE_NOT_READY		7
7307c478bd9Sstevel@tonic-gate 
7317c478bd9Sstevel@tonic-gate /* vhci_intr action codes */
7327c478bd9Sstevel@tonic-gate #define	JUST_RETURN			0
7337c478bd9Sstevel@tonic-gate #define	BUSY_RETURN			1
7347c478bd9Sstevel@tonic-gate #define	PKT_RETURN			2
7357c478bd9Sstevel@tonic-gate 
7367c478bd9Sstevel@tonic-gate #if	defined(_SYSCALL32)
7377c478bd9Sstevel@tonic-gate /*
73830a83a24Scth  * 32 bit variants of sv_path_info_prop_t and sv_path_info_t;
7397c478bd9Sstevel@tonic-gate  * To be used only in the driver and NOT applications
7407c478bd9Sstevel@tonic-gate  */
7417c478bd9Sstevel@tonic-gate typedef struct sv_path_info_prop32 {
7427c478bd9Sstevel@tonic-gate 	uint32_t	buf_size;	/* user buffer size */
7437c478bd9Sstevel@tonic-gate 	caddr32_t	ret_buf_size;	/* actual buffer needed */
7447c478bd9Sstevel@tonic-gate 	caddr32_t	buf;		/* user space buffer */
7457c478bd9Sstevel@tonic-gate } sv_path_info_prop32_t;
7467c478bd9Sstevel@tonic-gate 
7477c478bd9Sstevel@tonic-gate typedef struct sv_path_info32 {
7487c478bd9Sstevel@tonic-gate 	union {
7497c478bd9Sstevel@tonic-gate 		char	ret_ct[MAXPATHLEN];		/* client device */
7507c478bd9Sstevel@tonic-gate 		char	ret_phci[MAXPATHLEN];		/* pHCI device */
7517c478bd9Sstevel@tonic-gate 	} device;
7527c478bd9Sstevel@tonic-gate 
7537c478bd9Sstevel@tonic-gate 	char			ret_addr[MAXNAMELEN];	/* device address */
7547c478bd9Sstevel@tonic-gate 	mdi_pathinfo_state_t	ret_state;		/* state information */
7557c478bd9Sstevel@tonic-gate 	uint32_t		ret_ext_state;		/* Extended State */
7567c478bd9Sstevel@tonic-gate 	sv_path_info_prop32_t	ret_prop;		/* path attributes */
7577c478bd9Sstevel@tonic-gate } sv_path_info32_t;
7587c478bd9Sstevel@tonic-gate 
7597c478bd9Sstevel@tonic-gate typedef struct sv_iocdata32 {
7607c478bd9Sstevel@tonic-gate 	caddr32_t	client;		/* client dev devfs path name */
7617c478bd9Sstevel@tonic-gate 	caddr32_t	phci;		/* pHCI dev devfs path name */
7627c478bd9Sstevel@tonic-gate 	caddr32_t	addr;		/* device address */
7637c478bd9Sstevel@tonic-gate 	uint32_t	buf_elem;	/* number of path_info elems */
7647c478bd9Sstevel@tonic-gate 	caddr32_t	ret_buf;	/* addr of array of sv_path_info */
7657c478bd9Sstevel@tonic-gate 	caddr32_t	ret_elem;	/* count of above sv_path_info */
7667c478bd9Sstevel@tonic-gate } sv_iocdata32_t;
7677c478bd9Sstevel@tonic-gate 
7687c478bd9Sstevel@tonic-gate typedef struct sv_switch_to_cntlr_iocdata32 {
7697c478bd9Sstevel@tonic-gate 	caddr32_t	client;	/* client device devfs path name */
7707c478bd9Sstevel@tonic-gate 	caddr32_t	class;	/* desired path class to be made active */
7717c478bd9Sstevel@tonic-gate } sv_switch_to_cntlr_iocdata32_t;
7727c478bd9Sstevel@tonic-gate 
7737c478bd9Sstevel@tonic-gate #endif	/* _SYSCALL32 */
7747c478bd9Sstevel@tonic-gate 
7757c478bd9Sstevel@tonic-gate #endif	/* _KERNEL */
7767c478bd9Sstevel@tonic-gate 
7777c478bd9Sstevel@tonic-gate /*
7787c478bd9Sstevel@tonic-gate  * Userland (Non Kernel) definitions start here.
7797c478bd9Sstevel@tonic-gate  * Multiplexed I/O SCSI vHCI IOCTL Definitions
7807c478bd9Sstevel@tonic-gate  */
7817c478bd9Sstevel@tonic-gate 
7827c478bd9Sstevel@tonic-gate /*
7837c478bd9Sstevel@tonic-gate  * IOCTL structure for path properties
7847c478bd9Sstevel@tonic-gate  */
7857c478bd9Sstevel@tonic-gate typedef struct sv_path_info_prop {
7867c478bd9Sstevel@tonic-gate 	uint_t	buf_size;	/* user buffer size */
7877c478bd9Sstevel@tonic-gate 	uint_t	*ret_buf_size;	/* actual buffer needed */
7887c478bd9Sstevel@tonic-gate 	caddr_t	buf;		/* user space buffer */
7897c478bd9Sstevel@tonic-gate } sv_path_info_prop_t;
7907c478bd9Sstevel@tonic-gate 
7917c478bd9Sstevel@tonic-gate /*
7927c478bd9Sstevel@tonic-gate  * Max buffer size of getting path properties
7937c478bd9Sstevel@tonic-gate  */
7947c478bd9Sstevel@tonic-gate #define	SV_PROP_MAX_BUF_SIZE	4096
7957c478bd9Sstevel@tonic-gate 
7967c478bd9Sstevel@tonic-gate /*
7977c478bd9Sstevel@tonic-gate  * String values for "path-class" property
7987c478bd9Sstevel@tonic-gate  */
7997c478bd9Sstevel@tonic-gate #define	PCLASS_PRIMARY		"primary"
8007c478bd9Sstevel@tonic-gate #define	PCLASS_SECONDARY	"secondary"
8017c478bd9Sstevel@tonic-gate 
8027c478bd9Sstevel@tonic-gate #define	PCLASS_PREFERRED	1
8037c478bd9Sstevel@tonic-gate #define	PCLASS_NONPREFERRED	0
8047c478bd9Sstevel@tonic-gate 
8057c478bd9Sstevel@tonic-gate /*
8067c478bd9Sstevel@tonic-gate  * IOCTL structure for path information
8077c478bd9Sstevel@tonic-gate  */
8087c478bd9Sstevel@tonic-gate typedef struct sv_path_info {
8097c478bd9Sstevel@tonic-gate 	union {
8107c478bd9Sstevel@tonic-gate 		char	ret_ct[MAXPATHLEN];		/* client device */
8117c478bd9Sstevel@tonic-gate 		char	ret_phci[MAXPATHLEN];		/* pHCI device */
8127c478bd9Sstevel@tonic-gate 	} device;
8137c478bd9Sstevel@tonic-gate 
8147c478bd9Sstevel@tonic-gate 	char			ret_addr[MAXNAMELEN];	/* device address */
8157c478bd9Sstevel@tonic-gate 	mdi_pathinfo_state_t	ret_state;		/* state information */
8167c478bd9Sstevel@tonic-gate 	uint32_t		ret_ext_state;		/* Extended State */
8177c478bd9Sstevel@tonic-gate 	sv_path_info_prop_t	ret_prop;		/* path attributes */
8187c478bd9Sstevel@tonic-gate } sv_path_info_t;
8197c478bd9Sstevel@tonic-gate 
8207c478bd9Sstevel@tonic-gate /*
8217c478bd9Sstevel@tonic-gate  * IOCTL argument structure
8227c478bd9Sstevel@tonic-gate  */
8237c478bd9Sstevel@tonic-gate typedef struct sv_iocdata {
8247c478bd9Sstevel@tonic-gate 	caddr_t		client;		/* client dev devfs path name */
8257c478bd9Sstevel@tonic-gate 	caddr_t		phci;		/* pHCI dev devfs path name */
8267c478bd9Sstevel@tonic-gate 	caddr_t		addr;		/* device address */
8277c478bd9Sstevel@tonic-gate 	uint_t		buf_elem;	/* number of path_info elems */
8287c478bd9Sstevel@tonic-gate 	sv_path_info_t	*ret_buf;	/* array of sv_path_info */
8297c478bd9Sstevel@tonic-gate 	uint_t		*ret_elem;	/* count of sv_path_info */
8307c478bd9Sstevel@tonic-gate } sv_iocdata_t;
8317c478bd9Sstevel@tonic-gate 
8327c478bd9Sstevel@tonic-gate /*
8337c478bd9Sstevel@tonic-gate  * IOCTL argument structure for switching controllers
8347c478bd9Sstevel@tonic-gate  */
8357c478bd9Sstevel@tonic-gate typedef struct sv_switch_to_cntlr_iocdata {
8367c478bd9Sstevel@tonic-gate 	caddr_t		client;	/* client device devfs path name */
8377c478bd9Sstevel@tonic-gate 	caddr_t		class;	/* desired path class to be made active */
8387c478bd9Sstevel@tonic-gate } sv_switch_to_cntlr_iocdata_t;
8397c478bd9Sstevel@tonic-gate 
8407c478bd9Sstevel@tonic-gate 
8417c478bd9Sstevel@tonic-gate /*
8427c478bd9Sstevel@tonic-gate  * IOCTL definitions
8437c478bd9Sstevel@tonic-gate  */
8447c478bd9Sstevel@tonic-gate #define	SCSI_VHCI_CTL		('X' << 8)
8457c478bd9Sstevel@tonic-gate #define	SCSI_VHCI_CTL_CMD	(SCSI_VHCI_CTL | ('S' << 8) | 'P')
8467c478bd9Sstevel@tonic-gate #define	SCSI_VHCI_CTL_SUB_CMD	('x' << 8)
8477c478bd9Sstevel@tonic-gate 
8487c478bd9Sstevel@tonic-gate #define	SCSI_VHCI_GET_CLIENT_MULTIPATH_INFO	(SCSI_VHCI_CTL_SUB_CMD + 0x01)
8497c478bd9Sstevel@tonic-gate #define	SCSI_VHCI_GET_PHCI_MULTIPATH_INFO	(SCSI_VHCI_CTL_SUB_CMD + 0x02)
8507c478bd9Sstevel@tonic-gate #define	SCSI_VHCI_GET_CLIENT_NAME		(SCSI_VHCI_CTL_SUB_CMD + 0x03)
8517c478bd9Sstevel@tonic-gate #define	SCSI_VHCI_PATH_ONLINE			(SCSI_VHCI_CTL_SUB_CMD + 0x04)
8527c478bd9Sstevel@tonic-gate #define	SCSI_VHCI_PATH_OFFLINE			(SCSI_VHCI_CTL_SUB_CMD + 0x05)
8537c478bd9Sstevel@tonic-gate #define	SCSI_VHCI_PATH_STANDBY			(SCSI_VHCI_CTL_SUB_CMD + 0x06)
8547c478bd9Sstevel@tonic-gate #define	SCSI_VHCI_PATH_TEST			(SCSI_VHCI_CTL_SUB_CMD + 0x07)
8557c478bd9Sstevel@tonic-gate #define	SCSI_VHCI_SWITCH_TO_CNTLR		(SCSI_VHCI_CTL_SUB_CMD + 0x08)
8567c478bd9Sstevel@tonic-gate 
8577c478bd9Sstevel@tonic-gate #ifdef	DEBUG
8587c478bd9Sstevel@tonic-gate #define	SCSI_VHCI_GET_PHCI_LIST			(SCSI_VHCI_CTL_SUB_CMD + 0x09)
8597c478bd9Sstevel@tonic-gate #define	SCSI_VHCI_CONFIGURE_PHCI		(SCSI_VHCI_CTL_SUB_CMD + 0x0A)
8607c478bd9Sstevel@tonic-gate #define	SCSI_VHCI_UNCONFIGURE_PHCI		(SCSI_VHCI_CTL_SUB_CMD + 0x0B)
8617c478bd9Sstevel@tonic-gate #endif
8627c478bd9Sstevel@tonic-gate 
8637c478bd9Sstevel@tonic-gate #define	SCSI_VHCI_PATH_DISABLE			(SCSI_VHCI_CTL_SUB_CMD + 0x0C)
8647c478bd9Sstevel@tonic-gate #define	SCSI_VHCI_PATH_ENABLE			(SCSI_VHCI_CTL_SUB_CMD + 0x0D)
8658c4f8890Srs #define	SCSI_VHCI_MPAPI				(SCSI_VHCI_CTL_SUB_CMD + 0x0E)
8667c478bd9Sstevel@tonic-gate 
86737fbbce5Scth #define	SCSI_VHCI_GET_TARGET_LONGNAME		(SCSI_VHCI_CTL_SUB_CMD + 0x0F)
86837fbbce5Scth 
8697c478bd9Sstevel@tonic-gate #ifdef	__cplusplus
8707c478bd9Sstevel@tonic-gate }
8717c478bd9Sstevel@tonic-gate #endif
8727c478bd9Sstevel@tonic-gate 
8737c478bd9Sstevel@tonic-gate #endif	/* _SYS_SCSI_ADAPTERS_SCSI_VHCI_H */
874