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  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  * Copyright (c) 2011 Bayard G. Bell. All rights reserved.
  25  */
  26 
  27 
  28 /*
  29  * SCSA HBA nexus driver that emulates an HBA connected to SCSI target
  30  * devices (large disks).
  31  */
  32 
  33 #ifdef DEBUG
  34 #define EMUL64DEBUG
  35 #endif
  36 
  37 #include <sys/scsi/scsi.h>
  38 #include <sys/ddi.h>
  39 #include <sys/sunddi.h>
  40 #include <sys/taskq.h>
  41 #include <sys/disp.h>
  42 #include <sys/types.h>
  43 #include <sys/buf.h>
  44 #include <sys/cpuvar.h>
  45 #include <sys/dklabel.h>
  46 
  47 #include <sys/emul64.h>
  48 #include <sys/emul64cmd.h>
  49 #include <sys/emul64var.h>
  50 
  51 int emul64_usetaskq     = 1;    /* set to zero for debugging */
  52 int emul64debug         = 0;
  53 #ifdef  EMUL64DEBUG
  54 static int emul64_cdb_debug     = 0;
  55 #include <sys/debug.h>
  56 #endif
  57 
  58 /*
  59  * cb_ops function prototypes
  60  */
  61 static int emul64_ioctl(dev_t, int cmd, intptr_t arg, int mode,
  62                         cred_t *credp, int *rvalp);
  63 
  64 /*
  65  * dev_ops functions prototypes
  66  */
  67 static int emul64_info(dev_info_t *dip, ddi_info_cmd_t infocmd,
  68     void *arg, void **result);
  69 static int emul64_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
  70 static int emul64_detach(dev_info_t *dip, ddi_detach_cmd_t cmd);
  71 
  72 /*
  73  * Function prototypes
  74  *
  75  * SCSA functions exported by means of the transport table
  76  */
  77 static int emul64_tran_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
  78         scsi_hba_tran_t *tran, struct scsi_device *sd);
  79 static int emul64_scsi_start(struct scsi_address *ap, struct scsi_pkt *pkt);
  80 static void emul64_pkt_comp(void *);
  81 static int emul64_scsi_abort(struct scsi_address *ap, struct scsi_pkt *pkt);
  82 static int emul64_scsi_reset(struct scsi_address *ap, int level);
  83 static int emul64_scsi_getcap(struct scsi_address *ap, char *cap, int whom);
  84 static int emul64_scsi_setcap(struct scsi_address *ap, char *cap, int value,
  85     int whom);
  86 static struct scsi_pkt *emul64_scsi_init_pkt(struct scsi_address *ap,
  87     struct scsi_pkt *pkt, struct buf *bp, int cmdlen, int statuslen,
  88     int tgtlen, int flags, int (*callback)(), caddr_t arg);
  89 static void emul64_scsi_destroy_pkt(struct scsi_address *ap,
  90                                         struct scsi_pkt *pkt);
  91 static void emul64_scsi_dmafree(struct scsi_address *ap, struct scsi_pkt *pkt);
  92 static void emul64_scsi_sync_pkt(struct scsi_address *ap, struct scsi_pkt *pkt);
  93 static int emul64_scsi_reset_notify(struct scsi_address *ap, int flag,
  94     void (*callback)(caddr_t), caddr_t arg);
  95 
  96 /*
  97  * internal functions
  98  */
  99 static void emul64_i_initcap(struct emul64 *emul64);
 100 
 101 static void emul64_i_log(struct emul64 *emul64, int level, char *fmt, ...);
 102 static int emul64_get_tgtrange(struct emul64 *,
 103                                 intptr_t,
 104                                 emul64_tgt_t **,
 105                                 emul64_tgt_range_t *);
 106 static int emul64_write_off(struct emul64 *,
 107                             emul64_tgt_t *,
 108                             emul64_tgt_range_t *);
 109 static int emul64_write_on(struct emul64 *,
 110                                 emul64_tgt_t *,
 111                                 emul64_tgt_range_t *);
 112 static emul64_nowrite_t *emul64_nowrite_alloc(emul64_range_t *);
 113 static void emul64_nowrite_free(emul64_nowrite_t *);
 114 static emul64_nowrite_t *emul64_find_nowrite(emul64_tgt_t *,
 115                                         diskaddr_t start_block,
 116                                         size_t blkcnt,
 117                                         emul64_rng_overlap_t *overlapp,
 118                                         emul64_nowrite_t ***prevp);
 119 
 120 extern emul64_tgt_t *find_tgt(struct emul64 *, ushort_t, ushort_t);
 121 
 122 #ifdef EMUL64DEBUG
 123 static void emul64_debug_dump_cdb(struct scsi_address *ap,
 124                 struct scsi_pkt *pkt);
 125 #endif
 126 
 127 
 128 #ifdef  _DDICT
 129 static int      ddi_in_panic(void);
 130 static int      ddi_in_panic() { return (0); }
 131 #ifndef SCSI_CAP_RESET_NOTIFICATION
 132 #define SCSI_CAP_RESET_NOTIFICATION             14
 133 #endif
 134 #ifndef SCSI_RESET_NOTIFY
 135 #define SCSI_RESET_NOTIFY                       0x01
 136 #endif
 137 #ifndef SCSI_RESET_CANCEL
 138 #define SCSI_RESET_CANCEL                       0x02
 139 #endif
 140 #endif
 141 
 142 /*
 143  * Tunables:
 144  *
 145  * emul64_max_task
 146  *      The taskq facility is used to queue up SCSI start requests on a per
 147  *      controller basis.  If the maximum number of queued tasks is hit,
 148  *      taskq_ent_alloc() delays for a second, which adversely impacts our
 149  *      performance.  This value establishes the maximum number of task
 150  *      queue entries when taskq_create is called.
 151  *
 152  * emul64_task_nthreads
 153  *      Specifies the number of threads that should be used to process a
 154  *      controller's task queue.  Our init function sets this to the number
 155  *      of CPUs on the system, but this can be overridden in emul64.conf.
 156  */
 157 int emul64_max_task = 16;
 158 int emul64_task_nthreads = 1;
 159 
 160 /*
 161  * Local static data
 162  */
 163 static void             *emul64_state = NULL;
 164 
 165 /*
 166  * Character/block operations.
 167  */
 168 static struct cb_ops emul64_cbops = {
 169         scsi_hba_open,          /* cb_open */
 170         scsi_hba_close,         /* cb_close */
 171         nodev,                  /* cb_strategy */
 172         nodev,                  /* cb_print */
 173         nodev,                  /* cb_dump */
 174         nodev,                  /* cb_read */
 175         nodev,                  /* cb_write */
 176         emul64_ioctl,           /* cb_ioctl */
 177         nodev,                  /* cb_devmap */
 178         nodev,                  /* cb_mmap */
 179         nodev,                  /* cb_segmap */
 180         nochpoll,               /* cb_chpoll */
 181         ddi_prop_op,            /* cb_prop_op */
 182         NULL,                   /* cb_str */
 183         D_MP | D_64BIT | D_HOTPLUG, /* cb_flag */
 184         CB_REV,                 /* cb_rev */
 185         nodev,                  /* cb_aread */
 186         nodev                   /* cb_awrite */
 187 };
 188 
 189 /*
 190  * autoconfiguration routines.
 191  */
 192 
 193 static struct dev_ops emul64_ops = {
 194         DEVO_REV,                       /* rev, */
 195         0,                              /* refcnt */
 196         emul64_info,                    /* getinfo */
 197         nulldev,                        /* identify */
 198         nulldev,                        /* probe */
 199         emul64_attach,                  /* attach */
 200         emul64_detach,                  /* detach */
 201         nodev,                          /* reset */
 202         &emul64_cbops,                      /* char/block ops */
 203         NULL,                           /* bus ops */
 204         NULL,                           /* power */
 205         ddi_quiesce_not_needed,                 /* quiesce */
 206 };
 207 
 208 static struct modldrv modldrv = {
 209         &mod_driverops,                     /* module type - driver */
 210         "emul64 SCSI Host Bus Adapter", /* module name */
 211         &emul64_ops,                        /* driver ops */
 212 };
 213 
 214 static struct modlinkage modlinkage = {
 215         MODREV_1,                       /* ml_rev - must be MODREV_1 */
 216         &modldrv,                   /* ml_linkage */
 217         NULL                            /* end of driver linkage */
 218 };
 219 
 220 int
 221 _init(void)
 222 {
 223         int     ret;
 224 
 225         ret = ddi_soft_state_init(&emul64_state, sizeof (struct emul64),
 226             EMUL64_INITIAL_SOFT_SPACE);
 227         if (ret != 0)
 228                 return (ret);
 229 
 230         if ((ret = scsi_hba_init(&modlinkage)) != 0) {
 231                 ddi_soft_state_fini(&emul64_state);
 232                 return (ret);
 233         }
 234 
 235         /* Set the number of task threads to the number of CPUs */
 236         if (boot_max_ncpus == -1) {
 237                 emul64_task_nthreads = max_ncpus;
 238         } else {
 239                 emul64_task_nthreads = boot_max_ncpus;
 240         }
 241 
 242         emul64_bsd_init();
 243 
 244         ret = mod_install(&modlinkage);
 245         if (ret != 0) {
 246                 emul64_bsd_fini();
 247                 scsi_hba_fini(&modlinkage);
 248                 ddi_soft_state_fini(&emul64_state);
 249         }
 250 
 251         return (ret);
 252 }
 253 
 254 int
 255 _fini(void)
 256 {
 257         int     ret;
 258 
 259         if ((ret = mod_remove(&modlinkage)) != 0)
 260                 return (ret);
 261 
 262         emul64_bsd_fini();
 263 
 264         scsi_hba_fini(&modlinkage);
 265 
 266         ddi_soft_state_fini(&emul64_state);
 267 
 268         return (ret);
 269 }
 270 
 271 int
 272 _info(struct modinfo *modinfop)
 273 {
 274         return (mod_info(&modlinkage, modinfop));
 275 }
 276 
 277 /*
 278  * Given the device number return the devinfo pointer
 279  * from the scsi_device structure.
 280  */
 281 /*ARGSUSED*/
 282 static int
 283 emul64_info(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result)
 284 {
 285         struct emul64   *foo;
 286         int             instance = getminor((dev_t)arg);
 287 
 288         switch (cmd) {
 289         case DDI_INFO_DEVT2DEVINFO:
 290                 foo = ddi_get_soft_state(emul64_state, instance);
 291                 if (foo != NULL)
 292                         *result = (void *)foo->emul64_dip;
 293                 else {
 294                         *result = NULL;
 295                         return (DDI_FAILURE);
 296                 }
 297                 break;
 298 
 299         case DDI_INFO_DEVT2INSTANCE:
 300                 *result = (void *)(uintptr_t)instance;
 301                 break;
 302 
 303         default:
 304                 return (DDI_FAILURE);
 305         }
 306 
 307         return (DDI_SUCCESS);
 308 }
 309 
 310 /*
 311  * Attach an instance of an emul64 host adapter.  Allocate data structures,
 312  * initialize the emul64 and we're on the air.
 313  */
 314 /*ARGSUSED*/
 315 static int
 316 emul64_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
 317 {
 318         int             mutex_initted = 0;
 319         struct emul64   *emul64;
 320         int             instance;
 321         scsi_hba_tran_t *tran = NULL;
 322         ddi_dma_attr_t  tmp_dma_attr;
 323 
 324         emul64_bsd_get_props(dip);
 325 
 326         bzero((void *) &tmp_dma_attr, sizeof (tmp_dma_attr));
 327         instance = ddi_get_instance(dip);
 328 
 329         switch (cmd) {
 330         case DDI_ATTACH:
 331                 break;
 332 
 333         case DDI_RESUME:
 334                 tran = (scsi_hba_tran_t *)ddi_get_driver_private(dip);
 335                 if (!tran) {
 336                         return (DDI_FAILURE);
 337                 }
 338                 emul64 = TRAN2EMUL64(tran);
 339 
 340                 return (DDI_SUCCESS);
 341 
 342         default:
 343                 emul64_i_log(NULL, CE_WARN,
 344                     "emul64%d: Cmd != DDI_ATTACH/DDI_RESUME", instance);
 345                 return (DDI_FAILURE);
 346         }
 347 
 348         /*
 349          * Allocate emul64 data structure.
 350          */
 351         if (ddi_soft_state_zalloc(emul64_state, instance) != DDI_SUCCESS) {
 352                 emul64_i_log(NULL, CE_WARN,
 353                     "emul64%d: Failed to alloc soft state",
 354                     instance);
 355                 return (DDI_FAILURE);
 356         }
 357 
 358         emul64 = (struct emul64 *)ddi_get_soft_state(emul64_state, instance);
 359         if (emul64 == (struct emul64 *)NULL) {
 360                 emul64_i_log(NULL, CE_WARN, "emul64%d: Bad soft state",
 361                     instance);
 362                 ddi_soft_state_free(emul64_state, instance);
 363                 return (DDI_FAILURE);
 364         }
 365 
 366 
 367         /*
 368          * Allocate a transport structure
 369          */
 370         tran = scsi_hba_tran_alloc(dip, SCSI_HBA_CANSLEEP);
 371         if (tran == NULL) {
 372                 cmn_err(CE_WARN, "emul64: scsi_hba_tran_alloc failed\n");
 373                 goto fail;
 374         }
 375 
 376         emul64->emul64_tran                  = tran;
 377         emul64->emul64_dip                   = dip;
 378 
 379         tran->tran_hba_private               = emul64;
 380         tran->tran_tgt_private               = NULL;
 381         tran->tran_tgt_init          = emul64_tran_tgt_init;
 382         tran->tran_tgt_probe         = scsi_hba_probe;
 383         tran->tran_tgt_free          = NULL;
 384 
 385         tran->tran_start             = emul64_scsi_start;
 386         tran->tran_abort             = emul64_scsi_abort;
 387         tran->tran_reset             = emul64_scsi_reset;
 388         tran->tran_getcap            = emul64_scsi_getcap;
 389         tran->tran_setcap            = emul64_scsi_setcap;
 390         tran->tran_init_pkt          = emul64_scsi_init_pkt;
 391         tran->tran_destroy_pkt               = emul64_scsi_destroy_pkt;
 392         tran->tran_dmafree           = emul64_scsi_dmafree;
 393         tran->tran_sync_pkt          = emul64_scsi_sync_pkt;
 394         tran->tran_reset_notify      = emul64_scsi_reset_notify;
 395 
 396         tmp_dma_attr.dma_attr_minxfer = 0x1;
 397         tmp_dma_attr.dma_attr_burstsizes = 0x7f;
 398 
 399         /*
 400          * Attach this instance of the hba
 401          */
 402         if (scsi_hba_attach_setup(dip, &tmp_dma_attr, tran,
 403             0) != DDI_SUCCESS) {
 404                 cmn_err(CE_WARN, "emul64: scsi_hba_attach failed\n");
 405                 goto fail;
 406         }
 407 
 408         emul64->emul64_initiator_id = 2;
 409 
 410         /*
 411          * Look up the scsi-options property
 412          */
 413         emul64->emul64_scsi_options =
 414             ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0, "scsi-options",
 415             EMUL64_DEFAULT_SCSI_OPTIONS);
 416         EMUL64_DEBUG(emul64, SCSI_DEBUG, "emul64 scsi-options=%x",
 417             emul64->emul64_scsi_options);
 418 
 419 
 420         /* mutexes to protect the emul64 request and response queue */
 421         mutex_init(EMUL64_REQ_MUTEX(emul64), NULL, MUTEX_DRIVER,
 422             emul64->emul64_iblock);
 423         mutex_init(EMUL64_RESP_MUTEX(emul64), NULL, MUTEX_DRIVER,
 424             emul64->emul64_iblock);
 425 
 426         mutex_initted = 1;
 427 
 428         EMUL64_MUTEX_ENTER(emul64);
 429 
 430         /*
 431          * Initialize the default Target Capabilities and Sync Rates
 432          */
 433         emul64_i_initcap(emul64);
 434 
 435         EMUL64_MUTEX_EXIT(emul64);
 436 
 437 
 438         ddi_report_dev(dip);
 439         emul64->emul64_taskq = taskq_create("emul64_comp",
 440             emul64_task_nthreads, MINCLSYSPRI, 1, emul64_max_task, 0);
 441 
 442         return (DDI_SUCCESS);
 443 
 444 fail:
 445         emul64_i_log(NULL, CE_WARN, "emul64%d: Unable to attach", instance);
 446 
 447         if (mutex_initted) {
 448                 mutex_destroy(EMUL64_REQ_MUTEX(emul64));
 449                 mutex_destroy(EMUL64_RESP_MUTEX(emul64));
 450         }
 451         if (tran) {
 452                 scsi_hba_tran_free(tran);
 453         }
 454         ddi_soft_state_free(emul64_state, instance);
 455         return (DDI_FAILURE);
 456 }
 457 
 458 /*ARGSUSED*/
 459 static int
 460 emul64_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
 461 {
 462         struct emul64   *emul64;
 463         scsi_hba_tran_t *tran;
 464         int             instance = ddi_get_instance(dip);
 465 
 466 
 467         /* get transport structure pointer from the dip */
 468         if (!(tran = (scsi_hba_tran_t *)ddi_get_driver_private(dip))) {
 469                 return (DDI_FAILURE);
 470         }
 471 
 472         /* get soft state from transport structure */
 473         emul64 = TRAN2EMUL64(tran);
 474 
 475         if (!emul64) {
 476                 return (DDI_FAILURE);
 477         }
 478 
 479         EMUL64_DEBUG(emul64, SCSI_DEBUG, "emul64_detach: cmd = %d", cmd);
 480 
 481         switch (cmd) {
 482         case DDI_DETACH:
 483                 EMUL64_MUTEX_ENTER(emul64);
 484 
 485                 taskq_destroy(emul64->emul64_taskq);
 486                 (void) scsi_hba_detach(dip);
 487 
 488                 scsi_hba_tran_free(emul64->emul64_tran);
 489 
 490 
 491                 EMUL64_MUTEX_EXIT(emul64);
 492 
 493                 mutex_destroy(EMUL64_REQ_MUTEX(emul64));
 494                 mutex_destroy(EMUL64_RESP_MUTEX(emul64));
 495 
 496 
 497                 EMUL64_DEBUG(emul64, SCSI_DEBUG, "emul64_detach: done");
 498                 ddi_soft_state_free(emul64_state, instance);
 499 
 500                 return (DDI_SUCCESS);
 501 
 502         case DDI_SUSPEND:
 503                 return (DDI_SUCCESS);
 504 
 505         default:
 506                 return (DDI_FAILURE);
 507         }
 508 }
 509 
 510 /*
 511  * Function name : emul64_tran_tgt_init
 512  *
 513  * Return Values : DDI_SUCCESS if target supported, DDI_FAILURE otherwise
 514  *
 515  */
 516 /*ARGSUSED*/
 517 static int
 518 emul64_tran_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
 519         scsi_hba_tran_t *tran, struct scsi_device *sd)
 520 {
 521         struct emul64   *emul64;
 522         emul64_tgt_t    *tgt;
 523         char            **geo_vidpid = NULL;
 524         char            *geo, *vidpid;
 525         uint32_t        *geoip = NULL;
 526         uint_t          length;
 527         uint_t          length2;
 528         lldaddr_t       sector_count;
 529         char            prop_name[15];
 530         int             ret = DDI_FAILURE;
 531 
 532         emul64 = TRAN2EMUL64(tran);
 533         EMUL64_MUTEX_ENTER(emul64);
 534 
 535         /*
 536          * We get called for each target driver.conf node, multiple
 537          * nodes may map to the same tgt,lun (sd.conf, st.conf, etc).
 538          * Check to see if transport to tgt,lun already established.
 539          */
 540         tgt = find_tgt(emul64, sd->sd_address.a_target, sd->sd_address.a_lun);
 541         if (tgt) {
 542                 ret = DDI_SUCCESS;
 543                 goto out;
 544         }
 545 
 546         /* see if we have driver.conf specified device for this target,lun */
 547         (void) snprintf(prop_name, sizeof (prop_name), "targ_%d_%d",
 548             sd->sd_address.a_target, sd->sd_address.a_lun);
 549         if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, hba_dip,
 550             DDI_PROP_DONTPASS, prop_name,
 551             &geo_vidpid, &length) != DDI_PROP_SUCCESS)
 552                 goto out;
 553         if (length < 2) {
 554                 cmn_err(CE_WARN, "emul64: %s property does not have 2 "
 555                     "elements", prop_name);
 556                 goto out;
 557         }
 558 
 559         /* pick geometry name and vidpid string from string array */
 560         geo = *geo_vidpid;
 561         vidpid = *(geo_vidpid + 1);
 562 
 563         /* lookup geometry property integer array */
 564         if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, hba_dip, DDI_PROP_DONTPASS,
 565             geo, (int **)&geoip, &length2) != DDI_PROP_SUCCESS) {
 566                 cmn_err(CE_WARN, "emul64: didn't get prop '%s'", geo);
 567                 goto out;
 568         }
 569         if (length2 < 6) {
 570                 cmn_err(CE_WARN, "emul64: property %s does not have 6 "
 571                     "elements", *geo_vidpid);
 572                 goto out;
 573         }
 574 
 575         /* allocate and initialize tgt structure for tgt,lun */
 576         tgt = kmem_zalloc(sizeof (emul64_tgt_t), KM_SLEEP);
 577         rw_init(&tgt->emul64_tgt_nw_lock, NULL, RW_DRIVER, NULL);
 578         mutex_init(&tgt->emul64_tgt_blk_lock, NULL, MUTEX_DRIVER, NULL);
 579 
 580         /* create avl for data block storage */
 581         avl_create(&tgt->emul64_tgt_data, emul64_bsd_blkcompare,
 582             sizeof (blklist_t), offsetof(blklist_t, bl_node));
 583 
 584         /* save scsi_address and vidpid */
 585         bcopy(sd, &tgt->emul64_tgt_saddr, sizeof (struct scsi_address));
 586         (void) strncpy(tgt->emul64_tgt_inq, vidpid,
 587             sizeof (emul64->emul64_tgt->emul64_tgt_inq));
 588 
 589         /*
 590          * The high order 4 bytes of the sector count always come first in
 591          * emul64.conf.  They are followed by the low order 4 bytes.  Not
 592          * all CPU types want them in this order, but laddr_t takes care of
 593          * this for us.  We then pick up geometry (ncyl X nheads X nsect).
 594          */
 595         sector_count._p._u      = *(geoip + 0);
 596         sector_count._p._l      = *(geoip + 1);
 597         /*
 598          * On 32-bit platforms, fix block size if it's greater than the
 599          * allowable maximum.
 600          */
 601 #if !defined(_LP64)
 602         if (sector_count._f > DK_MAX_BLOCKS)
 603                 sector_count._f = DK_MAX_BLOCKS;
 604 #endif
 605         tgt->emul64_tgt_sectors = sector_count._f;
 606         tgt->emul64_tgt_dtype        = *(geoip + 2);
 607         tgt->emul64_tgt_ncyls        = *(geoip + 3);
 608         tgt->emul64_tgt_nheads       = *(geoip + 4);
 609         tgt->emul64_tgt_nsect        = *(geoip + 5);
 610 
 611         /* insert target structure into list */
 612         tgt->emul64_tgt_next = emul64->emul64_tgt;
 613         emul64->emul64_tgt = tgt;
 614         ret = DDI_SUCCESS;
 615 
 616 out:    EMUL64_MUTEX_EXIT(emul64);
 617         if (geoip)
 618                 ddi_prop_free(geoip);
 619         if (geo_vidpid)
 620                 ddi_prop_free(geo_vidpid);
 621         return (ret);
 622 }
 623 
 624 /*
 625  * Function name : emul64_i_initcap
 626  *
 627  * Return Values : NONE
 628  * Description   : Initializes the default target capabilities and
 629  *                 Sync Rates.
 630  *
 631  * Context       : Called from the user thread through attach.
 632  *
 633  */
 634 static void
 635 emul64_i_initcap(struct emul64 *emul64)
 636 {
 637         uint16_t        cap, synch;
 638         int             i;
 639 
 640         cap = 0;
 641         synch = 0;
 642         for (i = 0; i < NTARGETS_WIDE; i++) {
 643                 emul64->emul64_cap[i] = cap;
 644                 emul64->emul64_synch[i] = synch;
 645         }
 646         EMUL64_DEBUG(emul64, SCSI_DEBUG, "default cap = 0x%x", cap);
 647 }
 648 
 649 /*
 650  * Function name : emul64_scsi_getcap()
 651  *
 652  * Return Values : current value of capability, if defined
 653  *                 -1 if capability is not defined
 654  * Description   : returns current capability value
 655  *
 656  * Context       : Can be called from different kernel process threads.
 657  *                 Can be called by interrupt thread.
 658  */
 659 static int
 660 emul64_scsi_getcap(struct scsi_address *ap, char *cap, int whom)
 661 {
 662         struct emul64   *emul64 = ADDR2EMUL64(ap);
 663         int             rval = 0;
 664 
 665         /*
 666          * We don't allow inquiring about capabilities for other targets
 667          */
 668         if (cap == NULL || whom == 0) {
 669                 return (-1);
 670         }
 671 
 672         EMUL64_MUTEX_ENTER(emul64);
 673 
 674         switch (scsi_hba_lookup_capstr(cap)) {
 675         case SCSI_CAP_DMA_MAX:
 676                 rval = 1 << 24; /* Limit to 16MB max transfer */
 677                 break;
 678         case SCSI_CAP_MSG_OUT:
 679                 rval = 1;
 680                 break;
 681         case SCSI_CAP_DISCONNECT:
 682                 rval = 1;
 683                 break;
 684         case SCSI_CAP_SYNCHRONOUS:
 685                 rval = 1;
 686                 break;
 687         case SCSI_CAP_WIDE_XFER:
 688                 rval = 1;
 689                 break;
 690         case SCSI_CAP_TAGGED_QING:
 691                 rval = 1;
 692                 break;
 693         case SCSI_CAP_UNTAGGED_QING:
 694                 rval = 1;
 695                 break;
 696         case SCSI_CAP_PARITY:
 697                 rval = 1;
 698                 break;
 699         case SCSI_CAP_INITIATOR_ID:
 700                 rval = emul64->emul64_initiator_id;
 701                 break;
 702         case SCSI_CAP_ARQ:
 703                 rval = 1;
 704                 break;
 705         case SCSI_CAP_LINKED_CMDS:
 706                 break;
 707         case SCSI_CAP_RESET_NOTIFICATION:
 708                 rval = 1;
 709                 break;
 710 
 711         default:
 712                 rval = -1;
 713                 break;
 714         }
 715 
 716         EMUL64_MUTEX_EXIT(emul64);
 717 
 718         return (rval);
 719 }
 720 
 721 /*
 722  * Function name : emul64_scsi_setcap()
 723  *
 724  * Return Values : 1 - capability exists and can be set to new value
 725  *                 0 - capability could not be set to new value
 726  *                -1 - no such capability
 727  *
 728  * Description   : sets a capability for a target
 729  *
 730  * Context       : Can be called from different kernel process threads.
 731  *                 Can be called by interrupt thread.
 732  */
 733 static int
 734 emul64_scsi_setcap(struct scsi_address *ap, char *cap, int value, int whom)
 735 {
 736         struct emul64   *emul64 = ADDR2EMUL64(ap);
 737         int             rval = 0;
 738 
 739         /*
 740          * We don't allow setting capabilities for other targets
 741          */
 742         if (cap == NULL || whom == 0) {
 743                 return (-1);
 744         }
 745 
 746         EMUL64_MUTEX_ENTER(emul64);
 747 
 748         switch (scsi_hba_lookup_capstr(cap)) {
 749         case SCSI_CAP_DMA_MAX:
 750         case SCSI_CAP_MSG_OUT:
 751         case SCSI_CAP_PARITY:
 752         case SCSI_CAP_UNTAGGED_QING:
 753         case SCSI_CAP_LINKED_CMDS:
 754         case SCSI_CAP_RESET_NOTIFICATION:
 755                 /*
 756                  * None of these are settable via
 757                  * the capability interface.
 758                  */
 759                 break;
 760         case SCSI_CAP_DISCONNECT:
 761                 rval = 1;
 762                 break;
 763         case SCSI_CAP_SYNCHRONOUS:
 764                 rval = 1;
 765                 break;
 766         case SCSI_CAP_TAGGED_QING:
 767                 rval = 1;
 768                 break;
 769         case SCSI_CAP_WIDE_XFER:
 770                 rval = 1;
 771                 break;
 772         case SCSI_CAP_INITIATOR_ID:
 773                 rval = -1;
 774                 break;
 775         case SCSI_CAP_ARQ:
 776                 rval = 1;
 777                 break;
 778         case SCSI_CAP_TOTAL_SECTORS:
 779                 emul64->nt_total_sectors[ap->a_target][ap->a_lun] = value;
 780                 rval = TRUE;
 781                 break;
 782         case SCSI_CAP_SECTOR_SIZE:
 783                 rval = TRUE;
 784                 break;
 785         default:
 786                 rval = -1;
 787                 break;
 788         }
 789 
 790 
 791         EMUL64_MUTEX_EXIT(emul64);
 792 
 793         return (rval);
 794 }
 795 
 796 /*
 797  * Function name : emul64_scsi_init_pkt
 798  *
 799  * Return Values : pointer to scsi_pkt, or NULL
 800  * Description   : Called by kernel on behalf of a target driver
 801  *                 calling scsi_init_pkt(9F).
 802  *                 Refer to tran_init_pkt(9E) man page
 803  *
 804  * Context       : Can be called from different kernel process threads.
 805  *                 Can be called by interrupt thread.
 806  */
 807 /* ARGSUSED */
 808 static struct scsi_pkt *
 809 emul64_scsi_init_pkt(struct scsi_address *ap, struct scsi_pkt *pkt,
 810         struct buf *bp, int cmdlen, int statuslen, int tgtlen,
 811         int flags, int (*callback)(), caddr_t arg)
 812 {
 813         struct emul64           *emul64 = ADDR2EMUL64(ap);
 814         struct emul64_cmd       *sp;
 815 
 816         ASSERT(callback == NULL_FUNC || callback == SLEEP_FUNC);
 817 
 818         /*
 819          * First step of emul64_scsi_init_pkt:  pkt allocation
 820          */
 821         if (pkt == NULL) {
 822                 pkt = scsi_hba_pkt_alloc(emul64->emul64_dip, ap, cmdlen,
 823                     statuslen,
 824                     tgtlen, sizeof (struct emul64_cmd), callback, arg);
 825                 if (pkt == NULL) {
 826                         cmn_err(CE_WARN, "emul64_scsi_init_pkt: "
 827                             "scsi_hba_pkt_alloc failed");
 828                         return (NULL);
 829                 }
 830 
 831                 sp = PKT2CMD(pkt);
 832 
 833                 /*
 834                  * Initialize the new pkt - we redundantly initialize
 835                  * all the fields for illustrative purposes.
 836                  */
 837                 sp->cmd_pkt          = pkt;
 838                 sp->cmd_flags                = 0;
 839                 sp->cmd_scblen               = statuslen;
 840                 sp->cmd_cdblen               = cmdlen;
 841                 sp->cmd_emul64               = emul64;
 842                 pkt->pkt_address     = *ap;
 843                 pkt->pkt_comp                = (void (*)())NULL;
 844                 pkt->pkt_flags               = 0;
 845                 pkt->pkt_time                = 0;
 846                 pkt->pkt_resid               = 0;
 847                 pkt->pkt_statistics  = 0;
 848                 pkt->pkt_reason              = 0;
 849 
 850         } else {
 851                 sp = PKT2CMD(pkt);
 852         }
 853 
 854         /*
 855          * Second step of emul64_scsi_init_pkt:  dma allocation/move
 856          */
 857         if (bp && bp->b_bcount != 0) {
 858                 if (bp->b_flags & B_READ) {
 859                         sp->cmd_flags &= ~CFLAG_DMASEND;
 860                 } else {
 861                         sp->cmd_flags |= CFLAG_DMASEND;
 862                 }
 863                 bp_mapin(bp);
 864                 sp->cmd_addr = (unsigned char *) bp->b_un.b_addr;
 865                 sp->cmd_count = bp->b_bcount;
 866                 pkt->pkt_resid = 0;
 867         }
 868 
 869         return (pkt);
 870 }
 871 
 872 
 873 /*
 874  * Function name : emul64_scsi_destroy_pkt
 875  *
 876  * Return Values : none
 877  * Description   : Called by kernel on behalf of a target driver
 878  *                 calling scsi_destroy_pkt(9F).
 879  *                 Refer to tran_destroy_pkt(9E) man page
 880  *
 881  * Context       : Can be called from different kernel process threads.
 882  *                 Can be called by interrupt thread.
 883  */
 884 static void
 885 emul64_scsi_destroy_pkt(struct scsi_address *ap, struct scsi_pkt *pkt)
 886 {
 887         struct emul64_cmd       *sp = PKT2CMD(pkt);
 888 
 889         /*
 890          * emul64_scsi_dmafree inline to make things faster
 891          */
 892         if (sp->cmd_flags & CFLAG_DMAVALID) {
 893                 /*
 894                  * Free the mapping.
 895                  */
 896                 sp->cmd_flags &= ~CFLAG_DMAVALID;
 897         }
 898 
 899         /*
 900          * Free the pkt
 901          */
 902         scsi_hba_pkt_free(ap, pkt);
 903 }
 904 
 905 
 906 /*
 907  * Function name : emul64_scsi_dmafree()
 908  *
 909  * Return Values : none
 910  * Description   : free dvma resources
 911  *
 912  * Context       : Can be called from different kernel process threads.
 913  *                 Can be called by interrupt thread.
 914  */
 915 /*ARGSUSED*/
 916 static void
 917 emul64_scsi_dmafree(struct scsi_address *ap, struct scsi_pkt *pkt)
 918 {
 919 }
 920 
 921 /*
 922  * Function name : emul64_scsi_sync_pkt()
 923  *
 924  * Return Values : none
 925  * Description   : sync dma
 926  *
 927  * Context       : Can be called from different kernel process threads.
 928  *                 Can be called by interrupt thread.
 929  */
 930 /*ARGSUSED*/
 931 static void
 932 emul64_scsi_sync_pkt(struct scsi_address *ap, struct scsi_pkt *pkt)
 933 {
 934 }
 935 
 936 /*
 937  * routine for reset notification setup, to register or cancel.
 938  */
 939 static int
 940 emul64_scsi_reset_notify(struct scsi_address *ap, int flag,
 941 void (*callback)(caddr_t), caddr_t arg)
 942 {
 943         struct emul64                           *emul64 = ADDR2EMUL64(ap);
 944         struct emul64_reset_notify_entry        *p, *beforep;
 945         int                                     rval = DDI_FAILURE;
 946 
 947         mutex_enter(EMUL64_REQ_MUTEX(emul64));
 948 
 949         p = emul64->emul64_reset_notify_listf;
 950         beforep = NULL;
 951 
 952         while (p) {
 953                 if (p->ap == ap)
 954                         break;  /* An entry exists for this target */
 955                 beforep = p;
 956                 p = p->next;
 957         }
 958 
 959         if ((flag & SCSI_RESET_CANCEL) && (p != NULL)) {
 960                 if (beforep == NULL) {
 961                         emul64->emul64_reset_notify_listf = p->next;
 962                 } else {
 963                         beforep->next = p->next;
 964                 }
 965                 kmem_free((caddr_t)p,
 966                     sizeof (struct emul64_reset_notify_entry));
 967                 rval = DDI_SUCCESS;
 968 
 969         } else if ((flag & SCSI_RESET_NOTIFY) && (p == NULL)) {
 970                 p = kmem_zalloc(sizeof (struct emul64_reset_notify_entry),
 971                     KM_SLEEP);
 972                 p->ap = ap;
 973                 p->callback = callback;
 974                 p->arg = arg;
 975                 p->next = emul64->emul64_reset_notify_listf;
 976                 emul64->emul64_reset_notify_listf = p;
 977                 rval = DDI_SUCCESS;
 978         }
 979 
 980         mutex_exit(EMUL64_REQ_MUTEX(emul64));
 981 
 982         return (rval);
 983 }
 984 
 985 /*
 986  * Function name : emul64_scsi_start()
 987  *
 988  * Return Values : TRAN_FATAL_ERROR     - emul64 has been shutdown
 989  *                 TRAN_BUSY            - request queue is full
 990  *                 TRAN_ACCEPT          - pkt has been submitted to emul64
 991  *
 992  * Description   : init pkt, start the request
 993  *
 994  * Context       : Can be called from different kernel process threads.
 995  *                 Can be called by interrupt thread.
 996  */
 997 static int
 998 emul64_scsi_start(struct scsi_address *ap, struct scsi_pkt *pkt)
 999 {
1000         struct emul64_cmd       *sp     = PKT2CMD(pkt);
1001         int                     rval    = TRAN_ACCEPT;
1002         struct emul64           *emul64 = ADDR2EMUL64(ap);
1003         clock_t                 cur_lbolt;
1004         taskqid_t               dispatched;
1005 
1006         ASSERT(mutex_owned(EMUL64_REQ_MUTEX(emul64)) == 0 || ddi_in_panic());
1007         ASSERT(mutex_owned(EMUL64_RESP_MUTEX(emul64)) == 0 || ddi_in_panic());
1008 
1009         EMUL64_DEBUG2(emul64, SCSI_DEBUG, "emul64_scsi_start %x", sp);
1010 
1011         pkt->pkt_reason = CMD_CMPLT;
1012 
1013 #ifdef  EMUL64DEBUG
1014         if (emul64_cdb_debug) {
1015                 emul64_debug_dump_cdb(ap, pkt);
1016         }
1017 #endif  /* EMUL64DEBUG */
1018 
1019         /*
1020          * calculate deadline from pkt_time
1021          * Instead of multiplying by 100 (ie. HZ), we multiply by 128 so
1022          * we can shift and at the same time have a 28% grace period
1023          * we ignore the rare case of pkt_time == 0 and deal with it
1024          * in emul64_i_watch()
1025          */
1026         cur_lbolt = ddi_get_lbolt();
1027         sp->cmd_deadline = cur_lbolt + (pkt->pkt_time * 128);
1028 
1029         if ((emul64_usetaskq == 0) || (pkt->pkt_flags & FLAG_NOINTR) != 0) {
1030                 emul64_pkt_comp((caddr_t)pkt);
1031         } else {
1032                 dispatched = NULL;
1033                 if (emul64_collect_stats) {
1034                         /*
1035                          * If we are collecting statistics, call
1036                          * taskq_dispatch in no sleep mode, so that we can
1037                          * detect if we are exceeding the queue length that
1038                          * was established in the call to taskq_create in
1039                          * emul64_attach.  If the no sleep call fails
1040                          * (returns NULL), the task will be dispatched in
1041                          * sleep mode below.
1042                          */
1043                         dispatched = taskq_dispatch(emul64->emul64_taskq,
1044                             emul64_pkt_comp, (void *)pkt, TQ_NOSLEEP);
1045                         if (dispatched == NULL) {
1046                                 /* Queue was full.  dispatch failed. */
1047                                 mutex_enter(&emul64_stats_mutex);
1048                                 emul64_taskq_max++;
1049                                 mutex_exit(&emul64_stats_mutex);
1050                         }
1051                 }
1052                 if (dispatched == NULL) {
1053                         (void) taskq_dispatch(emul64->emul64_taskq,
1054                             emul64_pkt_comp, (void *)pkt, TQ_SLEEP);
1055                 }
1056         }
1057 
1058 done:
1059         ASSERT(mutex_owned(EMUL64_REQ_MUTEX(emul64)) == 0 || ddi_in_panic());
1060         ASSERT(mutex_owned(EMUL64_RESP_MUTEX(emul64)) == 0 || ddi_in_panic());
1061 
1062         return (rval);
1063 }
1064 
1065 void
1066 emul64_check_cond(struct scsi_pkt *pkt, uchar_t key, uchar_t asc, uchar_t ascq)
1067 {
1068         struct scsi_arq_status *arq =
1069             (struct scsi_arq_status *)pkt->pkt_scbp;
1070 
1071         /* got check, no data transferred and ARQ done */
1072         arq->sts_status.sts_chk = 1;
1073         pkt->pkt_state |= STATE_ARQ_DONE;
1074         pkt->pkt_state &= ~STATE_XFERRED_DATA;
1075 
1076         /* for ARQ */
1077         arq->sts_rqpkt_reason = CMD_CMPLT;
1078         arq->sts_rqpkt_resid = 0;
1079         arq->sts_rqpkt_state = STATE_GOT_BUS | STATE_GOT_TARGET |
1080             STATE_SENT_CMD | STATE_XFERRED_DATA | STATE_GOT_STATUS;
1081         arq->sts_sensedata.es_valid = 1;
1082         arq->sts_sensedata.es_class = 0x7;
1083         arq->sts_sensedata.es_key = key;
1084         arq->sts_sensedata.es_add_code = asc;
1085         arq->sts_sensedata.es_qual_code = ascq;
1086 }
1087 
1088 ushort_t
1089 emul64_error_inject(struct scsi_pkt *pkt)
1090 {
1091         struct emul64_cmd       *sp     = PKT2CMD(pkt);
1092         emul64_tgt_t            *tgt;
1093         struct scsi_arq_status *arq =
1094             (struct scsi_arq_status *)pkt->pkt_scbp;
1095         uint_t                  max_sense_len;
1096 
1097         EMUL64_MUTEX_ENTER(sp->cmd_emul64);
1098         tgt = find_tgt(sp->cmd_emul64,
1099             pkt->pkt_address.a_target, pkt->pkt_address.a_lun);
1100         EMUL64_MUTEX_EXIT(sp->cmd_emul64);
1101 
1102         /*
1103          * If there is no target, skip the error injection and
1104          * let the packet be handled normally.  This would normally
1105          * never happen since a_target and a_lun are setup in
1106          * emul64_scsi_init_pkt.
1107          */
1108         if (tgt == NULL) {
1109                 return (ERR_INJ_DISABLE);
1110         }
1111 
1112         if (tgt->emul64_einj_state != ERR_INJ_DISABLE) {
1113                 arq->sts_status = tgt->emul64_einj_scsi_status;
1114                 pkt->pkt_state = tgt->emul64_einj_pkt_state;
1115                 pkt->pkt_reason = tgt->emul64_einj_pkt_reason;
1116 
1117                 /*
1118                  * Calculate available sense buffer length.  We could just
1119                  * assume sizeof(struct scsi_extended_sense) but hopefully
1120                  * that limitation will go away soon.
1121                  */
1122                 max_sense_len = sp->cmd_scblen  -
1123                     (sizeof (struct scsi_arq_status) -
1124                     sizeof (struct scsi_extended_sense));
1125                 if (max_sense_len > tgt->emul64_einj_sense_length) {
1126                         max_sense_len = tgt->emul64_einj_sense_length;
1127                 }
1128 
1129                 /* for ARQ */
1130                 arq->sts_rqpkt_reason = CMD_CMPLT;
1131                 arq->sts_rqpkt_resid = 0;
1132                 arq->sts_rqpkt_state = STATE_GOT_BUS | STATE_GOT_TARGET |
1133                     STATE_SENT_CMD | STATE_XFERRED_DATA | STATE_GOT_STATUS;
1134 
1135                 /* Copy sense data */
1136                 if (tgt->emul64_einj_sense_data != 0) {
1137                         bcopy(tgt->emul64_einj_sense_data,
1138                             (uint8_t *)&arq->sts_sensedata,
1139                             max_sense_len);
1140                 }
1141         }
1142 
1143         /* Return current error injection state */
1144         return (tgt->emul64_einj_state);
1145 }
1146 
1147 int
1148 emul64_error_inject_req(struct emul64 *emul64, intptr_t arg)
1149 {
1150         emul64_tgt_t            *tgt;
1151         struct emul64_error_inj_data error_inj_req;
1152 
1153         /* Check args */
1154         if (arg == NULL) {
1155                 return (EINVAL);
1156         }
1157 
1158         if (ddi_copyin((void *)arg, &error_inj_req,
1159             sizeof (error_inj_req), 0) != 0) {
1160                 cmn_err(CE_WARN, "emul64: ioctl - inj copyin failed\n");
1161                 return (EFAULT);
1162         }
1163 
1164         EMUL64_MUTEX_ENTER(emul64);
1165         tgt = find_tgt(emul64, error_inj_req.eccd_target,
1166             error_inj_req.eccd_lun);
1167         EMUL64_MUTEX_EXIT(emul64);
1168 
1169         /* Make sure device exists */
1170         if (tgt == NULL) {
1171                 return (ENODEV);
1172         }
1173 
1174         /* Free old sense buffer if we have one */
1175         if (tgt->emul64_einj_sense_data != NULL) {
1176                 ASSERT(tgt->emul64_einj_sense_length != 0);
1177                 kmem_free(tgt->emul64_einj_sense_data,
1178                     tgt->emul64_einj_sense_length);
1179                 tgt->emul64_einj_sense_data = NULL;
1180                 tgt->emul64_einj_sense_length = 0;
1181         }
1182 
1183         /*
1184          * Now handle error injection request.  If error injection
1185          * is requested we will return the sense data provided for
1186          * any I/O to this target until told to stop.
1187          */
1188         tgt->emul64_einj_state = error_inj_req.eccd_inj_state;
1189         tgt->emul64_einj_sense_length = error_inj_req.eccd_sns_dlen;
1190         tgt->emul64_einj_pkt_state = error_inj_req.eccd_pkt_state;
1191         tgt->emul64_einj_pkt_reason = error_inj_req.eccd_pkt_reason;
1192         tgt->emul64_einj_scsi_status = error_inj_req.eccd_scsi_status;
1193         switch (error_inj_req.eccd_inj_state) {
1194         case ERR_INJ_ENABLE:
1195         case ERR_INJ_ENABLE_NODATA:
1196                 if (error_inj_req.eccd_sns_dlen) {
1197                         tgt->emul64_einj_sense_data =
1198                             kmem_alloc(error_inj_req.eccd_sns_dlen, KM_SLEEP);
1199                         /* Copy sense data */
1200                         if (ddi_copyin((void *)(arg + sizeof (error_inj_req)),
1201                             tgt->emul64_einj_sense_data,
1202                             error_inj_req.eccd_sns_dlen, 0) != 0) {
1203                                 cmn_err(CE_WARN,
1204                                     "emul64: sense data copy in failed\n");
1205                                 return (EFAULT);
1206                         }
1207                 }
1208                 break;
1209         case ERR_INJ_DISABLE:
1210         default:
1211                 break;
1212         }
1213 
1214         return (0);
1215 }
1216 
1217 int bsd_scsi_start_stop_unit(struct scsi_pkt *);
1218 int bsd_scsi_test_unit_ready(struct scsi_pkt *);
1219 int bsd_scsi_request_sense(struct scsi_pkt *);
1220 int bsd_scsi_inquiry(struct scsi_pkt *);
1221 int bsd_scsi_format(struct scsi_pkt *);
1222 int bsd_scsi_io(struct scsi_pkt *);
1223 int bsd_scsi_log_sense(struct scsi_pkt *);
1224 int bsd_scsi_mode_sense(struct scsi_pkt *);
1225 int bsd_scsi_mode_select(struct scsi_pkt *);
1226 int bsd_scsi_read_capacity(struct scsi_pkt *);
1227 int bsd_scsi_read_capacity_16(struct scsi_pkt *);
1228 int bsd_scsi_reserve(struct scsi_pkt *);
1229 int bsd_scsi_format(struct scsi_pkt *);
1230 int bsd_scsi_release(struct scsi_pkt *);
1231 int bsd_scsi_read_defect_list(struct scsi_pkt *);
1232 int bsd_scsi_reassign_block(struct scsi_pkt *);
1233 int bsd_freeblkrange(emul64_tgt_t *, emul64_range_t *);
1234 
1235 static void
1236 emul64_handle_cmd(struct scsi_pkt *pkt)
1237 {
1238         if (emul64_error_inject(pkt) == ERR_INJ_ENABLE_NODATA) {
1239                 /*
1240                  * If error injection is configured to return with
1241                  * no data return now without handling the command.
1242                  * This is how normal check conditions work.
1243                  *
1244                  * If the error injection state is ERR_INJ_ENABLE
1245                  * (or if error injection is disabled) continue and
1246                  * handle the command.  This would be used for
1247                  * KEY_RECOVERABLE_ERROR type conditions.
1248                  */
1249                 return;
1250         }
1251 
1252         switch (pkt->pkt_cdbp[0]) {
1253         case SCMD_START_STOP:
1254                 (void) bsd_scsi_start_stop_unit(pkt);
1255                 break;
1256         case SCMD_TEST_UNIT_READY:
1257                 (void) bsd_scsi_test_unit_ready(pkt);
1258                 break;
1259         case SCMD_REQUEST_SENSE:
1260                 (void) bsd_scsi_request_sense(pkt);
1261                 break;
1262         case SCMD_INQUIRY:
1263                 (void) bsd_scsi_inquiry(pkt);
1264                 break;
1265         case SCMD_FORMAT:
1266                 (void) bsd_scsi_format(pkt);
1267                 break;
1268         case SCMD_READ:
1269         case SCMD_WRITE:
1270         case SCMD_READ_G1:
1271         case SCMD_WRITE_G1:
1272         case SCMD_READ_G4:
1273         case SCMD_WRITE_G4:
1274                 (void) bsd_scsi_io(pkt);
1275                 break;
1276         case SCMD_LOG_SENSE_G1:
1277                 (void) bsd_scsi_log_sense(pkt);
1278                 break;
1279         case SCMD_MODE_SENSE:
1280         case SCMD_MODE_SENSE_G1:
1281                 (void) bsd_scsi_mode_sense(pkt);
1282                 break;
1283         case SCMD_MODE_SELECT:
1284         case SCMD_MODE_SELECT_G1:
1285                 (void) bsd_scsi_mode_select(pkt);
1286                 break;
1287         case SCMD_READ_CAPACITY:
1288                 (void) bsd_scsi_read_capacity(pkt);
1289                 break;
1290         case SCMD_SVC_ACTION_IN_G4:
1291                 if (pkt->pkt_cdbp[1] == SSVC_ACTION_READ_CAPACITY_G4) {
1292                         (void) bsd_scsi_read_capacity_16(pkt);
1293                 } else {
1294                         cmn_err(CE_WARN, "emul64: unrecognized G4 service "
1295                             "action 0x%x", pkt->pkt_cdbp[1]);
1296                 }
1297                 break;
1298         case SCMD_RESERVE:
1299         case SCMD_RESERVE_G1:
1300                 (void) bsd_scsi_reserve(pkt);
1301                 break;
1302         case SCMD_RELEASE:
1303         case SCMD_RELEASE_G1:
1304                 (void) bsd_scsi_release(pkt);
1305                 break;
1306         case SCMD_REASSIGN_BLOCK:
1307                 (void) bsd_scsi_reassign_block(pkt);
1308                 break;
1309         case SCMD_READ_DEFECT_LIST:
1310                 (void) bsd_scsi_read_defect_list(pkt);
1311                 break;
1312         case SCMD_PRIN:
1313         case SCMD_PROUT:
1314         case SCMD_REPORT_LUNS:
1315                 /* ASC 0x24 INVALID FIELD IN CDB */
1316                 emul64_check_cond(pkt, KEY_ILLEGAL_REQUEST, 0x24, 0x0);
1317                 break;
1318         default:
1319                 cmn_err(CE_WARN, "emul64: unrecognized "
1320                     "SCSI cmd 0x%x", pkt->pkt_cdbp[0]);
1321                 emul64_check_cond(pkt, KEY_ILLEGAL_REQUEST, 0x24, 0x0);
1322                 break;
1323         case SCMD_GET_CONFIGURATION:
1324         case 0x35:                      /* SCMD_SYNCHRONIZE_CACHE */
1325                 /* Don't complain */
1326                 break;
1327         }
1328 }
1329 
1330 static void
1331 emul64_pkt_comp(void * arg)
1332 {
1333         struct scsi_pkt         *pkt = (struct scsi_pkt *)arg;
1334         struct emul64_cmd       *sp = PKT2CMD(pkt);
1335         emul64_tgt_t            *tgt;
1336 
1337         EMUL64_MUTEX_ENTER(sp->cmd_emul64);
1338         tgt = find_tgt(sp->cmd_emul64,
1339             pkt->pkt_address.a_target, pkt->pkt_address.a_lun);
1340         EMUL64_MUTEX_EXIT(sp->cmd_emul64);
1341         if (!tgt) {
1342                 pkt->pkt_reason = CMD_TIMEOUT;
1343                 pkt->pkt_state = STATE_GOT_BUS | STATE_SENT_CMD;
1344                 pkt->pkt_statistics = STAT_TIMEOUT;
1345         } else {
1346                 pkt->pkt_reason = CMD_CMPLT;
1347                 *pkt->pkt_scbp = STATUS_GOOD;
1348                 pkt->pkt_state = STATE_GOT_BUS | STATE_GOT_TARGET |
1349                     STATE_SENT_CMD | STATE_XFERRED_DATA | STATE_GOT_STATUS;
1350                 pkt->pkt_statistics = 0;
1351                 emul64_handle_cmd(pkt);
1352         }
1353         scsi_hba_pkt_comp(pkt);
1354 }
1355 
1356 /* ARGSUSED */
1357 static int
1358 emul64_scsi_abort(struct scsi_address *ap, struct scsi_pkt *pkt)
1359 {
1360         return (1);
1361 }
1362 
1363 /* ARGSUSED */
1364 static int
1365 emul64_scsi_reset(struct scsi_address *ap, int level)
1366 {
1367         return (1);
1368 }
1369 
1370 static int
1371 emul64_get_tgtrange(struct emul64 *emul64,
1372                     intptr_t arg,
1373                     emul64_tgt_t **tgtp,
1374                     emul64_tgt_range_t *tgtr)
1375 {
1376         if (ddi_copyin((void *)arg, tgtr, sizeof (*tgtr), 0) != 0) {
1377                 cmn_err(CE_WARN, "emul64: ioctl - copy in failed\n");
1378                 return (EFAULT);
1379         }
1380         EMUL64_MUTEX_ENTER(emul64);
1381         *tgtp = find_tgt(emul64, tgtr->emul64_target, tgtr->emul64_lun);
1382         EMUL64_MUTEX_EXIT(emul64);
1383         if (*tgtp == NULL) {
1384                 cmn_err(CE_WARN, "emul64: ioctl - no target for %d,%d on %d",
1385                     tgtr->emul64_target, tgtr->emul64_lun,
1386                     ddi_get_instance(emul64->emul64_dip));
1387                 return (ENXIO);
1388         }
1389         return (0);
1390 }
1391 
1392 static int
1393 emul64_ioctl(dev_t dev,
1394         int cmd,
1395         intptr_t arg,
1396         int mode,
1397         cred_t *credp,
1398         int *rvalp)
1399 {
1400         struct emul64           *emul64;
1401         int                     instance;
1402         int                     rv = 0;
1403         emul64_tgt_range_t      tgtr;
1404         emul64_tgt_t            *tgt;
1405 
1406         instance = MINOR2INST(getminor(dev));
1407         emul64 = (struct emul64 *)ddi_get_soft_state(emul64_state, instance);
1408         if (emul64 == NULL) {
1409                 cmn_err(CE_WARN, "emul64: ioctl - no softstate for %d\n",
1410                     getminor(dev));
1411                 return (ENXIO);
1412         }
1413 
1414         switch (cmd) {
1415         case EMUL64_WRITE_OFF:
1416                 rv = emul64_get_tgtrange(emul64, arg, &tgt, &tgtr);
1417                 if (rv == 0) {
1418                         rv = emul64_write_off(emul64, tgt, &tgtr);
1419                 }
1420                 break;
1421         case EMUL64_WRITE_ON:
1422                 rv = emul64_get_tgtrange(emul64, arg, &tgt, &tgtr);
1423                 if (rv == 0) {
1424                         rv = emul64_write_on(emul64, tgt, &tgtr);
1425                 }
1426                 break;
1427         case EMUL64_ZERO_RANGE:
1428                 rv = emul64_get_tgtrange(emul64, arg, &tgt, &tgtr);
1429                 if (rv == 0) {
1430                         mutex_enter(&tgt->emul64_tgt_blk_lock);
1431                         rv = bsd_freeblkrange(tgt, &tgtr.emul64_blkrange);
1432                         mutex_exit(&tgt->emul64_tgt_blk_lock);
1433                 }
1434                 break;
1435         case EMUL64_ERROR_INJECT:
1436                 rv = emul64_error_inject_req(emul64, arg);
1437                 break;
1438         default:
1439                 rv  = scsi_hba_ioctl(dev, cmd, arg, mode, credp, rvalp);
1440                 break;
1441         }
1442         return (rv);
1443 }
1444 
1445 /* ARGSUSED */
1446 static int
1447 emul64_write_off(struct emul64 *emul64,
1448         emul64_tgt_t *tgt,
1449         emul64_tgt_range_t *tgtr)
1450 {
1451         size_t                  blkcnt = tgtr->emul64_blkrange.emul64_blkcnt;
1452         emul64_nowrite_t        *cur;
1453         emul64_nowrite_t        *nowrite;
1454         emul64_rng_overlap_t    overlap = O_NONE;
1455         emul64_nowrite_t        **prev = NULL;
1456         diskaddr_t              sb = tgtr->emul64_blkrange.emul64_sb;
1457 
1458         nowrite = emul64_nowrite_alloc(&tgtr->emul64_blkrange);
1459 
1460         /* Find spot in list */
1461         rw_enter(&tgt->emul64_tgt_nw_lock, RW_WRITER);
1462         cur = emul64_find_nowrite(tgt, sb, blkcnt, &overlap, &prev);
1463         if (overlap == O_NONE) {
1464                 /* Insert into list */
1465                 *prev = nowrite;
1466                 nowrite->emul64_nwnext = cur;
1467         }
1468         rw_exit(&tgt->emul64_tgt_nw_lock);
1469         if (overlap == O_NONE) {
1470                 if (emul64_collect_stats) {
1471                         mutex_enter(&emul64_stats_mutex);
1472                         emul64_nowrite_count++;
1473                         mutex_exit(&emul64_stats_mutex);
1474                 }
1475         } else {
1476                 cmn_err(CE_WARN, "emul64: EMUL64_WRITE_OFF 0x%llx,0x%"
1477                     PRIx64 "overlaps 0x%llx,0x%" PRIx64 "\n",
1478                     nowrite->emul64_blocked.emul64_sb,
1479                     nowrite->emul64_blocked.emul64_blkcnt,
1480                     cur->emul64_blocked.emul64_sb,
1481                     cur->emul64_blocked.emul64_blkcnt);
1482                 emul64_nowrite_free(nowrite);
1483                 return (EINVAL);
1484         }
1485         return (0);
1486 }
1487 
1488 /* ARGSUSED */
1489 static int
1490 emul64_write_on(struct emul64 *emul64,
1491                 emul64_tgt_t *tgt,
1492                 emul64_tgt_range_t *tgtr)
1493 {
1494         size_t                  blkcnt = tgtr->emul64_blkrange.emul64_blkcnt;
1495         emul64_nowrite_t        *cur;
1496         emul64_rng_overlap_t    overlap = O_NONE;
1497         emul64_nowrite_t        **prev = NULL;
1498         int                     rv = 0;
1499         diskaddr_t              sb = tgtr->emul64_blkrange.emul64_sb;
1500 
1501         /* Find spot in list */
1502         rw_enter(&tgt->emul64_tgt_nw_lock, RW_WRITER);
1503         cur = emul64_find_nowrite(tgt, sb, blkcnt, &overlap, &prev);
1504         if (overlap == O_SAME) {
1505                 /* Remove from list */
1506                 *prev = cur->emul64_nwnext;
1507         }
1508         rw_exit(&tgt->emul64_tgt_nw_lock);
1509 
1510         switch (overlap) {
1511         case O_NONE:
1512                 cmn_err(CE_WARN, "emul64: EMUL64_WRITE_ON 0x%llx,0x%lx "
1513                     "range not found\n", sb, blkcnt);
1514                 rv = ENXIO;
1515                 break;
1516         case O_SAME:
1517                 if (emul64_collect_stats) {
1518                         mutex_enter(&emul64_stats_mutex);
1519                         emul64_nowrite_count--;
1520                         mutex_exit(&emul64_stats_mutex);
1521                 }
1522                 emul64_nowrite_free(cur);
1523                 break;
1524         case O_OVERLAP:
1525         case O_SUBSET:
1526                 cmn_err(CE_WARN, "emul64: EMUL64_WRITE_ON 0x%llx,0x%lx "
1527                     "overlaps 0x%llx,0x%" PRIx64 "\n",
1528                     sb, blkcnt, cur->emul64_blocked.emul64_sb,
1529                     cur->emul64_blocked.emul64_blkcnt);
1530                 rv = EINVAL;
1531                 break;
1532         }
1533         return (rv);
1534 }
1535 
1536 static emul64_nowrite_t *
1537 emul64_find_nowrite(emul64_tgt_t *tgt,
1538                     diskaddr_t sb,
1539                     size_t blkcnt,
1540                     emul64_rng_overlap_t *overlap,
1541                     emul64_nowrite_t ***prevp)
1542 {
1543         emul64_nowrite_t        *cur;
1544         emul64_nowrite_t        **prev;
1545 
1546         /* Find spot in list */
1547         *overlap = O_NONE;
1548         prev = &tgt->emul64_tgt_nowrite;
1549         cur = tgt->emul64_tgt_nowrite;
1550         while (cur != NULL) {
1551                 *overlap = emul64_overlap(&cur->emul64_blocked, sb, blkcnt);
1552                 if (*overlap != O_NONE)
1553                         break;
1554                 prev = &cur->emul64_nwnext;
1555                 cur = cur->emul64_nwnext;
1556         }
1557 
1558         *prevp = prev;
1559         return (cur);
1560 }
1561 
1562 static emul64_nowrite_t *
1563 emul64_nowrite_alloc(emul64_range_t *range)
1564 {
1565         emul64_nowrite_t        *nw;
1566 
1567         nw = kmem_zalloc(sizeof (*nw), KM_SLEEP);
1568         bcopy((void *) range,
1569             (void *) &nw->emul64_blocked,
1570             sizeof (nw->emul64_blocked));
1571         return (nw);
1572 }
1573 
1574 static void
1575 emul64_nowrite_free(emul64_nowrite_t *nw)
1576 {
1577         kmem_free((void *) nw, sizeof (*nw));
1578 }
1579 
1580 emul64_rng_overlap_t
1581 emul64_overlap(emul64_range_t *rng, diskaddr_t sb, size_t cnt)
1582 {
1583 
1584         if (rng->emul64_sb >= sb + cnt)
1585                 return (O_NONE);
1586         if (rng->emul64_sb + rng->emul64_blkcnt <= sb)
1587                 return (O_NONE);
1588         if ((rng->emul64_sb == sb) && (rng->emul64_blkcnt == cnt))
1589                 return (O_SAME);
1590         if ((sb >= rng->emul64_sb) &&
1591             ((sb + cnt) <= (rng->emul64_sb + rng->emul64_blkcnt))) {
1592                 return (O_SUBSET);
1593         }
1594         return (O_OVERLAP);
1595 }
1596 
1597 #include <sys/varargs.h>
1598 
1599 /*
1600  * Error logging, printing, and debug print routines
1601  */
1602 
1603 /*VARARGS3*/
1604 static void
1605 emul64_i_log(struct emul64 *emul64, int level, char *fmt, ...)
1606 {
1607         char    buf[256];
1608         va_list ap;
1609 
1610         va_start(ap, fmt);
1611         (void) vsnprintf(buf, sizeof (buf), fmt, ap);
1612         va_end(ap);
1613 
1614         scsi_log(emul64 ? emul64->emul64_dip : NULL,
1615             "emul64", level, "%s\n", buf);
1616 }
1617 
1618 
1619 #ifdef EMUL64DEBUG
1620 
1621 static void
1622 emul64_debug_dump_cdb(struct scsi_address *ap, struct scsi_pkt *pkt)
1623 {
1624         static char     hex[]   = "0123456789abcdef";
1625         struct emul64   *emul64 = ADDR2EMUL64(ap);
1626         struct emul64_cmd       *sp     = PKT2CMD(pkt);
1627         uint8_t         *cdb    = pkt->pkt_cdbp;
1628         char            buf [256];
1629         char            *p;
1630         int             i;
1631 
1632         (void) snprintf(buf, sizeof (buf), "emul64%d: <%d,%d> ",
1633             ddi_get_instance(emul64->emul64_dip),
1634             ap->a_target, ap->a_lun);
1635 
1636         p = buf + strlen(buf);
1637 
1638         *p++ = '[';
1639         for (i = 0; i < sp->cmd_cdblen; i++, cdb++) {
1640                 if (i != 0)
1641                         *p++ = ' ';
1642                 *p++ = hex[(*cdb >> 4) & 0x0f];
1643                 *p++ = hex[*cdb & 0x0f];
1644         }
1645         *p++ = ']';
1646         *p++ = '\n';
1647         *p = 0;
1648 
1649         cmn_err(CE_CONT, buf);
1650 }
1651 #endif  /* EMUL64DEBUG */