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