/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. */ /* * Copyright 2014 Nexenta Systems, Inc. All rights reserved. * Copyright 2024 RackTop Systems, Inc. */ #ifndef _SYS_SCSI_ADAPTERS_SCSI_VHCI_H #define _SYS_SCSI_ADAPTERS_SCSI_VHCI_H /* * Multiplexed I/O SCSI vHCI global include */ #include #include #include #include #include #include #include #ifdef __cplusplus extern "C" { #endif #if !defined(_BIT_FIELDS_LTOH) && !defined(_BIT_FIELDS_HTOL) #error One of _BIT_FIELDS_LTOH or _BIT_FIELDS_HTOL must be defined #endif /* _BIT_FIELDS_LTOH */ #ifdef _KERNEL #ifdef UNDEFINED #undef UNDEFINED #endif #define UNDEFINED -1 #define VHCI_STATE_OPEN 0x00000001 #define VH_SLEEP 0x0 #define VH_NOSLEEP 0x1 /* * HBA interface macros */ #define TRAN2HBAPRIVATE(tran) ((struct scsi_vhci *)(tran)->tran_hba_private) #define VHCI_INIT_WAIT_TIMEOUT 60000000 #define VHCI_FOWATCH_INTERVAL 1000000 /* in usecs */ #define VHCI_EXTFO_TIMEOUT (3 * 60 * NANOSEC) /* 3 minutes in nsec */ #define SCBP_C(pkt) ((*(pkt)->pkt_scbp) & STATUS_MASK) int vhci_do_scsi_cmd(struct scsi_pkt *); /*PRINTFLIKE3*/ void vhci_log(int, dev_info_t *, const char *, ...); size_t vhci_get_blocksize(dev_info_t *); /* * debugging stuff */ #ifdef DEBUG #ifndef VHCI_DEBUG_DEFAULT_VAL #define VHCI_DEBUG_DEFAULT_VAL 0 #endif /* VHCI_DEBUG_DEFAULT_VAL */ extern int vhci_debug; #include #define VHCI_DEBUG(level, stmnt) \ if (vhci_debug >= (level)) vhci_log stmnt #else /* !DEBUG */ #define VHCI_DEBUG(level, stmnt) #endif /* !DEBUG */ #define VHCI_PKT_PRIV_SIZE 2 #define ADDR2VHCI(ap) ((struct scsi_vhci *) \ ((ap)->a_hba_tran->tran_hba_private)) #define ADDR2VLUN(ap) (scsi_vhci_lun_t *) \ (scsi_device_hba_private_get(scsi_address_device(ap))) #define ADDR2DIP(ap) ((dev_info_t *)(scsi_address_device(ap)->sd_dev)) #define HBAPKT2VHCIPKT(pkt) (pkt->pkt_private) #define TGTPKT2VHCIPKT(pkt) (pkt->pkt_ha_private) #define VHCIPKT2HBAPKT(pkt) (pkt->pkt_hba_pkt) #define VHCIPKT2TGTPKT(pkt) (pkt->pkt_tgt_pkt) #define VHCI_DECR_PATH_CMDCOUNT(svp) { \ mutex_enter(&(svp)->svp_mutex); \ (svp)->svp_cmds--; \ if ((svp)->svp_cmds == 0) \ cv_broadcast(&(svp)->svp_cv); \ mutex_exit(&(svp)->svp_mutex); \ } #define VHCI_INCR_PATH_CMDCOUNT(svp) { \ mutex_enter(&(svp)->svp_mutex); \ (svp)->svp_cmds++; \ mutex_exit(&(svp)->svp_mutex); \ } /* * When a LUN is HELD it results in new IOs being returned to the target * driver layer with TRAN_BUSY. Should be used while performing * operations that require prevention of any new IOs to the LUN and * the LUN should be HELD for the duration of such operations. * f can be VH_SLEEP or VH_NOSLEEP. * h is set to 1 to indicate LUN was successfully HELD. * h is set to 0 when f is VH_NOSLEEP and LUN is already HELD. * * Application examples: * * 1) SCSI-II RESERVE: HOLD LUN until it is quiesced and the load balancing * policy is switched to NONE before proceeding with RESERVE handling. * * 2) Failover: HOLD LUN before initiating failover. * * 3) When an externally initiated failover is detected, HOLD LUN until all * path states have been refreshed to reflect the new value. * */ #define VHCI_HOLD_LUN(vlun, f, h) { \ int sleep = (f); \ mutex_enter(&(vlun)->svl_mutex); \ if ((vlun)->svl_transient == 1) { \ if (sleep == VH_SLEEP) { \ while ((vlun)->svl_transient == 1) \ cv_wait(&(vlun)->svl_cv, &(vlun)->svl_mutex); \ (vlun)->svl_transient = 1; \ (h) = 1; \ } else { \ (h) = 0; \ } \ } else { \ (vlun)->svl_transient = 1; \ (h) = 1; \ } \ sleep = (h); \ mutex_exit(&(vlun)->svl_mutex); \ } #define VHCI_RELEASE_LUN(vlun) { \ mutex_enter(&(vlun)->svl_mutex); \ (vlun)->svl_transient = 0; \ cv_broadcast(&(vlun)->svl_cv); \ mutex_exit(&(vlun)->svl_mutex); \ } #define VHCI_LUN_IS_HELD(vlun) ((vlun)->svl_transient == 1) /* * vhci_pkt states */ #define VHCI_PKT_IDLE 0x01 #define VHCI_PKT_ISSUED 0x02 #define VHCI_PKT_ABORTING 0x04 #define VHCI_PKT_STALE_BINDING 0x08 /* * Set the first time taskq is dispatched from scsi_start for * a packet. To ensure vhci_scsi_start recognizes that the scsi_pkt * is being issued from the taskq and not target driver. */ #define VHCI_PKT_THRU_TASKQ 0x20 /* * Set the first time failover is being triggered. To ensure * failover won't be triggered again when the packet is being * retried by target driver. */ #define VHCI_PKT_IN_FAILOVER 0x40 #define VHCI_PKT_TIMEOUT 30 /* seconds */ #define VHCI_PKT_RETRY_CNT 2 #define VHCI_POLL_TIMEOUT 60 /* seconds */ /* * define extended scsi cmd pkt */ #define EXTCMDS_STATUS_SIZE (sizeof (struct scsi_arq_status)) #define CFLAG_NOWAIT 0x1000 /* don't sleep */ #define CFLAG_DMA_PARTIAL 0x2000 /* Support Partial DMA */ /* * Maximum size of SCSI cdb in SCSI command */ #define VHCI_SCSI_CDB_SIZE 16 #define VHCI_SCSI_SCB_SIZE (sizeof (struct scsi_arq_status)) /* * OSD specific definitions */ #define VHCI_SCSI_OSD_CDB_SIZE 224 #define VHCI_SCSI_OSD_PKT_FLAGS 0x100000 /* * flag to determine failover support */ #define SCSI_NO_FAILOVER 0x0 #define SCSI_IMPLICIT_FAILOVER 0x1 #define SCSI_EXPLICIT_FAILOVER 0x2 #define SCSI_BOTH_FAILOVER \ (SCSI_IMPLICIT_FAILOVER | SCSI_EXPLICIT_FAILOVER) struct scsi_vhci_swarg; #define VHCI_NUM_RESV_KEYS 8 typedef struct vhci_prin_readkeys { uint32_t generation; uint32_t length; mhioc_resv_key_t keylist[VHCI_NUM_RESV_KEYS]; } vhci_prin_readkeys_t; #define VHCI_PROUT_SIZE \ ((sizeof (vhci_prout_t) - 2 * (MHIOC_RESV_KEY_SIZE) * sizeof (char))) typedef struct vhci_prout { /* PGR register parameters start */ uchar_t res_key[MHIOC_RESV_KEY_SIZE]; uchar_t service_key[MHIOC_RESV_KEY_SIZE]; uint32_t scope_address; #if defined(_BIT_FIELDS_LTOH) uchar_t aptpl:1, reserved:7; #else uchar_t reserved:7, aptpl:1; #endif /* _BIT_FIELDS_LTOH */ uchar_t reserved_1; uint16_t ext_len; /* PGR register parameters end */ /* Update VHCI_PROUT_SIZE if new fields are added here */ uchar_t active_res_key[MHIOC_RESV_KEY_SIZE]; uchar_t active_service_key[MHIOC_RESV_KEY_SIZE]; } vhci_prout_t; #define VHCI_PROUT_REGISTER 0x0 #define VHCI_PROUT_RESERVE 0x1 #define VHCI_PROUT_RELEASE 0x2 #define VHCI_PROUT_CLEAR 0x3 #define VHCI_PROUT_PREEMPT 0x4 #define VHCI_PROUT_P_AND_A 0x5 #define VHCI_PROUT_R_AND_IGNORE 0x6 struct vhci_pkt { struct scsi_pkt *vpkt_tgt_pkt; mdi_pathinfo_t *vpkt_path; /* path pkt bound to */ /* * pHCI packet that does the actual work. */ struct scsi_pkt *vpkt_hba_pkt; uint_t vpkt_state; uint_t vpkt_flags; /* * copy of vhci_scsi_init_pkt args. Used when we invoke * scsi_init_pkt() of the pHCI corresponding to the path that we * bind to */ int vpkt_tgt_init_cdblen; int vpkt_tgt_init_scblen; int vpkt_tgt_init_pkt_flags; struct buf *vpkt_tgt_init_bp; /* * Pointer to original struct vhci_pkt for cmd send by ssd. * Saved when the command is being retried internally. */ struct vhci_pkt *vpkt_org_vpkt; }; typedef struct scsi_vhci_lun { kmutex_t svl_mutex; kcondvar_t svl_cv; /* * following three fields are under svl_mutex protection */ int svl_transient; /* * to prevent unnecessary failover when a device is * is discovered across a passive path and active path * is still comng up */ int svl_waiting_for_activepath; hrtime_t svl_wfa_time; /* * to keep the failover status in order to return the * failure status to target driver when targer driver * retries the command which originally triggered the * failover. */ int svl_failover_status; /* * for RESERVE/RELEASE support */ client_lb_t svl_lb_policy_save; /* * Failover ops and ops name selected for the lun. */ struct scsi_failover_ops *svl_fops; char *svl_fops_name; void *svl_fops_ctpriv; struct scsi_vhci_lun *svl_hash_next; char *svl_lun_wwn; /* * currently active pathclass */ char *svl_active_pclass; dev_info_t *svl_dip; uint32_t svl_flags; /* protected by svl_mutex */ /* * When SCSI-II reservations are active we set the following pip * to point to the path holding the reservation. As long as * the reservation is active this svl_resrv_pip is bound for the * transport directly. We bypass calling mdi_select_path to return * a pip. * The following pip is only valid when VLUN_RESERVE_ACTIVE_FLG * is set. This pip should not be accessed if this flag is reset. */ mdi_pathinfo_t *svl_resrv_pip; /* * following fields are for PGR support */ taskq_t *svl_taskq; ksema_t svl_pgr_sema; /* PGR serialization */ vhci_prin_readkeys_t svl_prin; /* PGR in data */ vhci_prout_t svl_prout; /* PGR out data */ uchar_t svl_cdb[CDB_GROUP4]; int svl_time; /* pkt_time */ uint32_t svl_bcount; /* amount of data */ int svl_pgr_active; /* registrations active */ mdi_pathinfo_t *svl_first_path; /* external failover */ int svl_efo_update_path; struct scsi_vhci_swarg *svl_swarg; uint32_t svl_support_lun_reset; /* Lun reset support */ int svl_not_supported; int svl_xlf_capable; /* XLF implementation */ int svl_sector_size; int svl_setcap_done; uint16_t svl_fo_support; /* failover mode */ } scsi_vhci_lun_t; #define VLUN_TASK_D_ALIVE_FLG 0x01 /* * This flag is used to monitor the state of SCSI-II RESERVATION on the * lun. A SCSI-II RESERVE cmd may be accepted by the target on the inactive * path. This would then cause a subsequent IO to cause the paths to be * updated and be returned with a reservation conflict. By monitoring this * flag, and sending a reset to the target when needed to clear the reservation, * one can avoid this conflict. */ #define VLUN_RESERVE_ACTIVE_FLG 0x04 /* * This flag is set when a SCSI-II RESERVE cmd is received by scsi_vhci * and cleared when the pkt completes in vhci_intr. It ensures that the * lun remains quiesced for the duration of this pkt. This is different * from VHCI_HOLD_LUN as this pertains to IOs only. */ #define VLUN_QUIESCED_FLG 0x08 /* * This flag is set to tell vhci_update_pathstates to call back * into vhci_mpapi_update_tpg_acc_state. */ #define VLUN_UPDATE_TPG 0x10 /* * Various reset recovery depth. */ #define VHCI_DEPTH_ALL 3 #define VHCI_DEPTH_TARGET 2 #define VHCI_DEPTH_LUN 1 /* For the sake completeness */ #define TRUE (1) #define FALSE (0) /* * this is stashed away in the client private area of * pathinfo */ typedef struct scsi_vhci_priv { kmutex_t svp_mutex; kcondvar_t svp_cv; struct scsi_vhci_lun *svp_svl; /* * scsi device associated with this * pathinfo */ struct scsi_device *svp_psd; /* * number of outstanding commands on this * path. Protected by svp_mutex */ int svp_cmds; /* * following is used to prevent packets completing with the * same error reason from flooding the screen */ uchar_t svp_last_pkt_reason; /* external failover scsi_watch token */ opaque_t svp_sw_token; /* any cleanup operations for a newly found path. */ int svp_new_path; } scsi_vhci_priv_t; /* * argument to scsi_watch callback. Used for processing * externally initiated failovers */ typedef struct scsi_vhci_swarg { scsi_vhci_priv_t *svs_svp; hrtime_t svs_tos; /* time of submission */ mdi_pathinfo_t *svs_pi; /* pathinfo being "watched" */ int svs_release_lun; int svs_done; } scsi_vhci_swarg_t; /* * scsi_vhci softstate * * vhci_mutex protects * vhci_state * and vhci_reset_notify list */ struct scsi_vhci { kmutex_t vhci_mutex; dev_info_t *vhci_dip; struct scsi_hba_tran *vhci_tran; uint32_t vhci_state; uint32_t vhci_instance; kstat_t vhci_kstat; /* * This taskq is for general vhci operations like reservations, * auto-failback, etc. */ taskq_t *vhci_taskq; /* Dedicate taskq to handle external failovers */ taskq_t *vhci_update_pathstates_taskq; struct scsi_reset_notify_entry *vhci_reset_notify_listf; uint16_t vhci_conf_flags; mpapi_priv_t *mp_priv; }; /* * vHCI flags for configuration settings, defined in scsi_vhci.conf */ #define VHCI_CONF_FLAGS_AUTO_FAILBACK 0x0001 /* Enables auto failback */ typedef enum { SCSI_PATH_INACTIVE, SCSI_PATH_ACTIVE, SCSI_PATH_ACTIVE_NONOPT } scsi_path_state_t; #define SCSI_MAXPCLASSLEN 25 #define OPINFO_REV 1 /* * structure describing operational characteristics of * path */ struct scsi_path_opinfo { int opinfo_rev; /* * name of pathclass. Eg. "primary", "secondary" */ char opinfo_path_attr[SCSI_MAXPCLASSLEN]; /* * path state: ACTIVE/PASSIVE */ scsi_path_state_t opinfo_path_state; /* * the best and worst case time estimates for * failover operation to complete */ uint_t opinfo_pswtch_best; uint_t opinfo_pswtch_worst; /* XLF implementation */ int opinfo_xlf_capable; uint16_t opinfo_preferred; uint16_t opinfo_mode; }; #define SFO_REV 1 /* * vectors for device specific failover related operations */ struct scsi_failover_ops { int sfo_rev; /* * failover module name, begins with "f_" */ char *sfo_name; /* * devices supported by failover module * * NOTE: this is an aproximation, sfo_device_probe has the final say. */ char **sfo_devices; /* * initialize the failover module */ void (*sfo_init)(); /* * identify device */ int (*sfo_device_probe)( struct scsi_device *sd, struct scsi_inquiry *stdinq, void **ctpriv); /* * housekeeping (free memory etc alloc'ed during probe */ void (*sfo_device_unprobe)( struct scsi_device *sd, void *ctpriv); /* * bring a path ONLINE (ie make it ACTIVE) */ int (*sfo_path_activate)( struct scsi_device *sd, char *pathclass, void *ctpriv); /* * inverse of above */ int (*sfo_path_deactivate)( struct scsi_device *sd, char *pathclass, void *ctpriv); /* * returns operational characteristics of path */ int (*sfo_path_get_opinfo)( struct scsi_device *sd, struct scsi_path_opinfo *opinfo, void *ctpriv); /* * verify path is operational */ int (*sfo_path_ping)( struct scsi_device *sd, void *ctpriv); /* * analyze SENSE data to detect externally initiated * failovers */ int (*sfo_analyze_sense)( struct scsi_device *sd, uint8_t *sense, void *ctpriv); /* * return the next pathclass in order of preference * eg. "secondary" comes after "primary" */ int (*sfo_pathclass_next)( char *cur, char **nxt, void *ctpriv); }; /* * Names of (too) 'well-known' failover ops. * NOTE: consumers of these names should look for a better way... */ #define SFO_NAME_SYM "f_sym" #define SFO_NAME_TPGS "f_tpgs" #define SCSI_FAILOVER_IS_ASYM(svl) \ ((svl) ? ((svl)->svl_fo_support != SCSI_NO_FAILOVER) : 0) #define SCSI_FAILOVER_IS_TPGS(sfo) \ ((sfo) ? (strcmp((sfo)->sfo_name, SFO_NAME_TPGS) == 0) : 0) /* * Macro to provide plumbing for basic failover module */ #define _SCSI_FAILOVER_OP(sfo_name, local_name, ops_name) \ static struct modlmisc modlmisc = { \ &mod_miscops, sfo_name \ }; \ static struct modlinkage modlinkage = { \ MODREV_1, (void *)&modlmisc, NULL \ }; \ int _init() \ { \ return (mod_install(&modlinkage)); \ } \ int _fini() \ { \ return (mod_remove(&modlinkage)); \ } \ int _info(struct modinfo *modinfop) \ { \ return (mod_info(&modlinkage, modinfop)); \ } \ static int local_name##_device_probe( \ struct scsi_device *, \ struct scsi_inquiry *, void **); \ static void local_name##_device_unprobe( \ struct scsi_device *, void *); \ static int local_name##_path_activate( \ struct scsi_device *, char *, void *); \ static int local_name##_path_deactivate( \ struct scsi_device *, char *, void *); \ static int local_name##_path_get_opinfo( \ struct scsi_device *, \ struct scsi_path_opinfo *, void *); \ static int local_name##_path_ping( \ struct scsi_device *, void *); \ static int local_name##_analyze_sense( \ struct scsi_device *, \ uint8_t *, void *); \ static int local_name##_pathclass_next( \ char *, char **, void *); \ struct scsi_failover_ops ops_name##_failover_ops = { \ SFO_REV, \ sfo_name, \ local_name##_dev_table, \ NULL, \ local_name##_device_probe, \ local_name##_device_unprobe, \ local_name##_path_activate, \ local_name##_path_deactivate, \ local_name##_path_get_opinfo, \ local_name##_path_ping, \ local_name##_analyze_sense, \ local_name##_pathclass_next \ } #ifdef lint #define SCSI_FAILOVER_OP(sfo_name, local_name) \ _SCSI_FAILOVER_OP(sfo_name, local_name, local_name) #else /* lint */ #define SCSI_FAILOVER_OP(sfo_name, local_name) \ _SCSI_FAILOVER_OP(sfo_name, local_name, scsi_vhci) #endif /* lint */ /* * Return values for sfo_device_probe */ #define SFO_DEVICE_PROBE_VHCI 1 /* supported under scsi_vhci */ #define SFO_DEVICE_PROBE_PHCI 0 /* not supported under scsi_vhci */ /* return values for sfo_analyze_sense() */ #define SCSI_SENSE_NOFAILOVER 0 #define SCSI_SENSE_FAILOVER_INPROG 1 #define SCSI_SENSE_ACT2INACT 2 #define SCSI_SENSE_INACT2ACT 3 #define SCSI_SENSE_INACTIVE 4 #define SCSI_SENSE_UNKNOWN 5 #define SCSI_SENSE_STATE_CHANGED 6 #define SCSI_SENSE_NOT_READY 7 /* vhci_intr action codes */ #define JUST_RETURN 0 #define BUSY_RETURN 1 #define PKT_RETURN 2 #if defined(_SYSCALL32) /* * 32 bit variants of sv_path_info_prop_t and sv_path_info_t; * To be used only in the driver and NOT applications */ typedef struct sv_path_info_prop32 { uint32_t buf_size; /* user buffer size */ caddr32_t ret_buf_size; /* actual buffer needed */ caddr32_t buf; /* user space buffer */ } sv_path_info_prop32_t; typedef struct sv_path_info32 { union { char ret_ct[MAXPATHLEN]; /* client device */ char ret_phci[MAXPATHLEN]; /* pHCI device */ } device; char ret_addr[MAXNAMELEN]; /* device address */ mdi_pathinfo_state_t ret_state; /* state information */ uint32_t ret_ext_state; /* Extended State */ sv_path_info_prop32_t ret_prop; /* path attributes */ } sv_path_info32_t; typedef struct sv_iocdata32 { caddr32_t client; /* client dev devfs path name */ caddr32_t phci; /* pHCI dev devfs path name */ caddr32_t addr; /* device address */ uint32_t buf_elem; /* number of path_info elems */ caddr32_t ret_buf; /* addr of array of sv_path_info */ caddr32_t ret_elem; /* count of above sv_path_info */ } sv_iocdata32_t; typedef struct sv_switch_to_cntlr_iocdata32 { caddr32_t client; /* client device devfs path name */ caddr32_t class; /* desired path class to be made active */ } sv_switch_to_cntlr_iocdata32_t; #endif /* _SYSCALL32 */ #endif /* _KERNEL */ /* * Userland (Non Kernel) definitions start here. * Multiplexed I/O SCSI vHCI IOCTL Definitions */ /* * IOCTL structure for path properties */ typedef struct sv_path_info_prop { uint_t buf_size; /* user buffer size */ uint_t *ret_buf_size; /* actual buffer needed */ caddr_t buf; /* user space buffer */ } sv_path_info_prop_t; /* * Max buffer size of getting path properties */ #define SV_PROP_MAX_BUF_SIZE 4096 /* * String values for "path-class" property */ #define PCLASS_PRIMARY "primary" #define PCLASS_SECONDARY "secondary" #define PCLASS_PREFERRED 1 #define PCLASS_NONPREFERRED 0 /* * IOCTL structure for path information */ typedef struct sv_path_info { union { char ret_ct[MAXPATHLEN]; /* client device */ char ret_phci[MAXPATHLEN]; /* pHCI device */ } device; char ret_addr[MAXNAMELEN]; /* device address */ mdi_pathinfo_state_t ret_state; /* state information */ uint32_t ret_ext_state; /* Extended State */ sv_path_info_prop_t ret_prop; /* path attributes */ } sv_path_info_t; /* * IOCTL argument structure */ typedef struct sv_iocdata { caddr_t client; /* client dev devfs path name */ caddr_t phci; /* pHCI dev devfs path name */ caddr_t addr; /* device address */ uint_t buf_elem; /* number of path_info elems */ sv_path_info_t *ret_buf; /* array of sv_path_info */ uint_t *ret_elem; /* count of sv_path_info */ } sv_iocdata_t; /* * IOCTL argument structure for switching controllers */ typedef struct sv_switch_to_cntlr_iocdata { caddr_t client; /* client device devfs path name */ caddr_t class; /* desired path class to be made active */ } sv_switch_to_cntlr_iocdata_t; /* * IOCTL definitions */ #define SCSI_VHCI_CTL ('X' << 8) #define SCSI_VHCI_CTL_CMD (SCSI_VHCI_CTL | ('S' << 8) | 'P') #define SCSI_VHCI_CTL_SUB_CMD ('x' << 8) #define SCSI_VHCI_GET_CLIENT_MULTIPATH_INFO (SCSI_VHCI_CTL_SUB_CMD + 0x01) #define SCSI_VHCI_GET_PHCI_MULTIPATH_INFO (SCSI_VHCI_CTL_SUB_CMD + 0x02) #define SCSI_VHCI_GET_CLIENT_NAME (SCSI_VHCI_CTL_SUB_CMD + 0x03) #define SCSI_VHCI_PATH_ONLINE (SCSI_VHCI_CTL_SUB_CMD + 0x04) #define SCSI_VHCI_PATH_OFFLINE (SCSI_VHCI_CTL_SUB_CMD + 0x05) #define SCSI_VHCI_PATH_STANDBY (SCSI_VHCI_CTL_SUB_CMD + 0x06) #define SCSI_VHCI_PATH_TEST (SCSI_VHCI_CTL_SUB_CMD + 0x07) #define SCSI_VHCI_SWITCH_TO_CNTLR (SCSI_VHCI_CTL_SUB_CMD + 0x08) #ifdef DEBUG #define SCSI_VHCI_GET_PHCI_LIST (SCSI_VHCI_CTL_SUB_CMD + 0x09) #define SCSI_VHCI_CONFIGURE_PHCI (SCSI_VHCI_CTL_SUB_CMD + 0x0A) #define SCSI_VHCI_UNCONFIGURE_PHCI (SCSI_VHCI_CTL_SUB_CMD + 0x0B) #endif #define SCSI_VHCI_PATH_DISABLE (SCSI_VHCI_CTL_SUB_CMD + 0x0C) #define SCSI_VHCI_PATH_ENABLE (SCSI_VHCI_CTL_SUB_CMD + 0x0D) #define SCSI_VHCI_MPAPI (SCSI_VHCI_CTL_SUB_CMD + 0x0E) #define SCSI_VHCI_GET_TARGET_LONGNAME (SCSI_VHCI_CTL_SUB_CMD + 0x0F) #ifdef __cplusplus } #endif #endif /* _SYS_SCSI_ADAPTERS_SCSI_VHCI_H */