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