Print this page
    
7127  remove -Wno-missing-braces from Makefile.uts
    
      
        | Split | Close | 
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/uts/common/io/scsi/targets/sgen.c
          +++ new/usr/src/uts/common/io/scsi/targets/sgen.c
   1    1  /*
   2    2   * CDDL HEADER START
   3    3   *
   4    4   * The contents of this file are subject to the terms of the
   5    5   * Common Development and Distribution License (the "License").
   6    6   * You may not use this file except in compliance with the License.
   7    7   *
   8    8   * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9    9   * or http://www.opensolaris.org/os/licensing.
  10   10   * See the License for the specific language governing permissions
  11   11   * and limitations under the License.
  12   12   *
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  
  22   22  /*
  23   23   * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  24   24   * Use is subject to license terms.
  25   25   */
  26   26  
  27   27  /*
  28   28   * Copyright Siemens 1999
  29   29   * All rights reserved.
  30   30   */
  31   31  
  32   32  
  33   33  /*
  34   34   * sgen - SCSI generic device driver
  35   35   *
  36   36   * The sgen driver provides user programs access to SCSI devices that
  37   37   * are not supported by other drivers by providing the USCSI(7I) interface.
  38   38   */
  39   39  
  40   40  #include <sys/modctl.h>
  41   41  #include <sys/file.h>
  42   42  #include <sys/scsi/scsi.h>
  43   43  #include <sys/scsi/targets/sgendef.h>
  44   44  
  45   45  /* The name of the driver, established from the module name in _init. */
  46   46  static  char *sgen_label        = NULL;
  47   47  
  48   48  #define DDI_NT_SGEN             "ddi_generic:scsi"
  49   49  
  50   50  static char *sgen_devtypes[] = {
  51   51          "direct",               /* 0x00 -- disks */
  52   52          "sequential",           /* 0x01 */
  53   53          "printer",              /* 0x02 */
  54   54          "processor",            /* 0x03 */
  55   55          "worm",                 /* 0x04 */
  56   56          "rodirect",             /* 0x05 */
  57   57          "scanner",              /* 0x06 */
  58   58          "optical",              /* 0x07 */
  59   59          "changer",              /* 0x08 */
  60   60          "comm",                 /* 0x09 */
  61   61          "prepress1",            /* 0x0a -- reserved for prepress (ASC IT8) */
  62   62          "prepress2",            /* 0x0b -- reserved for prepress (ASC IT8) */
  63   63          "array_ctrl",           /* 0x0c -- storage array */
  64   64          "ses",                  /* 0x0d -- enclosure services */
  65   65          "rbc",                  /* 0x0e -- simplified block */
  66   66          "ocrw",                 /* 0x0f -- optical card read/write */
  67   67          "bridge",               /* 0x10 -- reserved for bridging expanders */
  68   68          "type_0x11",            /* 0x11 */
  69   69          "type_0x12",            /* 0x12 */
  70   70          "type_0x13",            /* 0x13 */
  71   71          "type_0x14",            /* 0x14 */
  72   72          "type_0x15",            /* 0x15 */
  73   73          "type_0x16",            /* 0x16 */
  74   74          "type_0x17",            /* 0x17 */
  75   75          "type_0x18",            /* 0x18 */
  76   76          "type_0x19",            /* 0x19 */
  77   77          "type_0x1a",            /* 0x1a */
  78   78          "type_0x1b",            /* 0x1b */
  79   79          "type_0x1c",            /* 0x1c */
  80   80          "type_0x1d",            /* 0x1d */
  81   81          "type_0x1e",            /* 0x1e */
  82   82          "type_unknown"          /* 0x1f is "no device type" or "unknown" */
  83   83  };
  84   84  
  85   85  #define SGEN_NDEVTYPES ((sizeof (sgen_devtypes) / sizeof (char *)))
  86   86  
  87   87  #define SGEN_INQSTRLEN 24
  88   88  #define SGEN_VENDID_MAX 8
  89   89  #define SGEN_PRODID_MAX 16
  90   90  
  91   91  #define FILL_SCSI1_LUN(devp, pkt)                                       \
  92   92          if ((devp)->sd_inq->inq_ansi == 0x1) {                          \
  93   93                  int _lun;                                               \
  94   94                  _lun = ddi_prop_get_int(DDI_DEV_T_ANY, (devp)->sd_dev,  \
  95   95                      DDI_PROP_DONTPASS, SCSI_ADDR_PROP_LUN, 0);          \
  96   96                  if (_lun > 0) {                                         \
  97   97                          ((union scsi_cdb *)(pkt)->pkt_cdbp)->scc_lun =  \
  98   98                              _lun;                                       \
  99   99                  }                                                       \
 100  100          }
 101  101  
 102  102  #define SGEN_DO_ERRSTATS(sg_state, x)  \
 103  103          if (sg_state->sgen_kstats) { \
 104  104                  struct sgen_errstats *sp; \
 105  105                  sp = (struct sgen_errstats *)sg_state->sgen_kstats->ks_data; \
 106  106                  sp->x.value.ui32++; \
 107  107          }
 108  108  
 109  109  #define SCBP_C(pkt)     ((*(pkt)->pkt_scbp) & STATUS_MASK)
 110  110  
 111  111  /*
 112  112   * Standard entrypoints
 113  113   */
 114  114  static int sgen_attach(dev_info_t *, ddi_attach_cmd_t);
 115  115  static int sgen_detach(dev_info_t *, ddi_detach_cmd_t);
 116  116  static int sgen_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
 117  117  static int sgen_probe(dev_info_t *);
 118  118  static int sgen_open(dev_t *, int, int, cred_t *);
 119  119  static int sgen_close(dev_t, int, int, cred_t *);
 120  120  static int sgen_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
 121  121  
 122  122  /*
 123  123   * Configuration routines
 124  124   */
 125  125  static int sgen_do_attach(dev_info_t *);
 126  126  static int sgen_setup_sense(sgen_state_t *);
 127  127  static void sgen_create_errstats(sgen_state_t *, int);
 128  128  static int sgen_do_suspend(dev_info_t *);
 129  129  static int sgen_do_detach(dev_info_t *);
 130  130  static void sgen_setup_binddb(dev_info_t *);
 131  131  static void sgen_cleanup_binddb();
 132  132  
 133  133  /*
 134  134   * Packet transport routines
 135  135   */
 136  136  static int  sgen_uscsi_cmd(dev_t, struct uscsi_cmd *, int);
 137  137  static int sgen_start(struct buf *);
 138  138  static int sgen_hold_cmdbuf(sgen_state_t *);
 139  139  static void sgen_rele_cmdbuf(sgen_state_t *);
 140  140  static int sgen_make_uscsi_cmd(sgen_state_t *, struct buf *);
 141  141  static void sgen_restart(void *);
 142  142  static void sgen_callback(struct scsi_pkt *);
 143  143  static int sgen_handle_autosense(sgen_state_t *, struct scsi_pkt *);
 144  144  static int sgen_handle_sense(sgen_state_t *);
 145  145  static int sgen_handle_incomplete(sgen_state_t *, struct scsi_pkt *);
 146  146  static int sgen_check_error(sgen_state_t *, struct buf *);
 147  147  static int sgen_initiate_sense(sgen_state_t *, int);
 148  148  static int sgen_scsi_transport(struct scsi_pkt *);
 149  149  static int sgen_tur(dev_t);
 150  150  
 151  151  /*
 152  152   * Logging/debugging routines
 153  153   */
 154  154  static void sgen_log(sgen_state_t  *, int,  const char *, ...);
 155  155  static int sgen_diag_ok(sgen_state_t *, int);
 156  156  static void sgen_dump_cdb(sgen_state_t *, const char *, union scsi_cdb *, int);
 157  157  static void sgen_dump_sense(sgen_state_t *, size_t, uchar_t *);
 158  158  
 159  159  int sgen_diag = 0;
 160  160  int sgen_sporadic_failures = 0;
 161  161  int sgen_force_manual_sense = 0;
 162  162  struct sgen_binddb sgen_binddb;
 163  163  
 164  164  static struct cb_ops sgen_cb_ops = {
 165  165          sgen_open,                      /* open */
 166  166          sgen_close,                     /* close */
 167  167          nodev,                          /* strategy */
 168  168          nodev,                          /* print */
 169  169          nodev,                          /* dump */
 170  170          nodev,                          /* read */
 171  171          nodev,                          /* write */
 172  172          sgen_ioctl,                     /* ioctl */
 173  173          nodev,                          /* devmap */
 174  174          nodev,                          /* mmap */
 175  175          nodev,                          /* segmap */
 176  176          nochpoll,                       /* poll */
 177  177          ddi_prop_op,                    /* cb_prop_op */
 178  178          0,                              /* streamtab  */
 179  179          D_MP | D_NEW | D_HOTPLUG        /* Driver compatibility flag */
 180  180  };
 181  181  
 182  182  static struct dev_ops sgen_dev_ops = {
 183  183          DEVO_REV,               /* devo_rev, */
 184  184          0,                      /* refcnt  */
 185  185          sgen_getinfo,           /* info */
 186  186          nodev,                  /* identify */
 187  187          sgen_probe,             /* probe */
 188  188          sgen_attach,            /* attach */
 189  189          sgen_detach,            /* detach */
 190  190          nodev,                  /* reset */
 191  191          &sgen_cb_ops,           /* driver operations */
 192  192          (struct bus_ops *)0,    /* bus operations */
 193  193          NULL,                   /* power */
  
    | ↓ open down ↓ | 193 lines elided | ↑ open up ↑ | 
 194  194          ddi_quiesce_not_supported,      /* devo_quiesce */
 195  195  };
 196  196  
 197  197  static void *sgen_soft_state = NULL;
 198  198  
 199  199  static struct modldrv modldrv = {
 200  200          &mod_driverops, "SCSI generic driver", &sgen_dev_ops
 201  201  };
 202  202  
 203  203  static struct modlinkage modlinkage = {
 204      -        MODREV_1, &modldrv, NULL
      204 +        MODREV_1, { &modldrv, NULL }
 205  205  };
 206  206  
 207  207  int
 208  208  _init(void)
 209  209  {
 210  210          int err;
 211  211  
 212  212          /* establish driver name from module name */
 213  213          sgen_label = (char *)mod_modname(&modlinkage);
 214  214  
 215  215          sgen_log(NULL, SGEN_DIAG2, "in sgen_init()");
 216  216          if ((err = ddi_soft_state_init(&sgen_soft_state,
 217  217              sizeof (sgen_state_t), SGEN_ESTIMATED_NUM_DEVS)) != 0) {
 218  218                  goto done;
 219  219          }
 220  220  
 221  221          if ((err = mod_install(&modlinkage)) != 0) {
 222  222                  ddi_soft_state_fini(&sgen_soft_state);
 223  223                  goto done;
 224  224          }
 225  225  
 226  226  done:
 227  227          sgen_log(NULL, SGEN_DIAG2, "%s sgen_init()", err ? "failed" : "done");
 228  228          return (err);
 229  229  }
 230  230  
 231  231  int
 232  232  _fini(void)
 233  233  {
 234  234          int err;
 235  235          sgen_log(NULL, SGEN_DIAG2, "in sgen_fini()");
 236  236  
 237  237          if ((err = mod_remove(&modlinkage)) != 0) {
 238  238                  goto done;
 239  239          }
 240  240  
 241  241          ddi_soft_state_fini(&sgen_soft_state);
 242  242          sgen_cleanup_binddb();
 243  243  
 244  244  done:
 245  245          sgen_log(NULL, SGEN_DIAG2, "%s sgen_fini()", err ? "failed" : "done");
 246  246          return (err);
 247  247  }
 248  248  
 249  249  int
 250  250  _info(struct modinfo *modinfop)
 251  251  {
 252  252          return (mod_info(&modlinkage, modinfop));
 253  253  }
 254  254  
 255  255  /*
 256  256   * sgen_typename()
 257  257   *      return a device type's name by looking it up in the sgen_devtypes table.
 258  258   */
 259  259  static char *
 260  260  sgen_typename(uchar_t typeno)
 261  261  {
 262  262          if (typeno >= SGEN_NDEVTYPES)
 263  263                  return ("type_unknown");
 264  264          return (sgen_devtypes[typeno]);
 265  265  }
 266  266  
 267  267  /*
 268  268   * sgen_typenum()
 269  269   *      return a device type's number by looking it up in the sgen_devtypes
 270  270   *      table.
 271  271   */
 272  272  static int
 273  273  sgen_typenum(const char *typename, uchar_t *typenum)
 274  274  {
 275  275          int i;
 276  276          for (i = 0; i < SGEN_NDEVTYPES; i++) {
 277  277                  if (strcasecmp(sgen_devtypes[i], typename) == 0) {
 278  278                          *typenum = (uchar_t)i;
 279  279                          return (0);
 280  280                  }
 281  281          }
 282  282          return (-1);
 283  283  }
 284  284  
 285  285  /*
 286  286   * sgen_setup_binddb()
 287  287   *      initialize a data structure which stores all of the information about
 288  288   *      which devices and device types the driver should bind to.
 289  289   */
 290  290  static void
 291  291  sgen_setup_binddb(dev_info_t *dip)
 292  292  {
 293  293          char **strs = NULL, *cp, *pcp, *vcp;
 294  294          uint_t nelems, pcplen, vcplen, idx;
 295  295  
 296  296          ASSERT(sgen_binddb.sdb_init == 0);
 297  297          ASSERT(MUTEX_HELD(&sgen_binddb.sdb_lock));
 298  298  
 299  299          if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
 300  300              "device-type-config-list", &strs, &nelems) == DDI_PROP_SUCCESS) {
 301  301                  /*
 302  302                   * for each device type specifier make a copy and put it into a
 303  303                   * node in the binddb.
 304  304                   */
 305  305                  for (idx = 0; idx < nelems; idx++) {
 306  306                          sgen_type_node_t *nodep;
 307  307                          uchar_t devtype;
 308  308                          cp = strs[idx];
 309  309                          if (sgen_typenum(cp, &devtype) != 0) {
 310  310                                  sgen_log(NULL, CE_WARN,
 311  311                                      "unknown device type '%s', "
 312  312                                      "device unit-address @%s",
 313  313                                      cp, ddi_get_name_addr(dip));
 314  314                                  continue;
 315  315                          }
 316  316                          nodep = kmem_zalloc(sizeof (sgen_type_node_t),
 317  317                              KM_SLEEP);
 318  318                          nodep->node_type = devtype;
 319  319                          nodep->node_next = sgen_binddb.sdb_type_nodes;
 320  320                          sgen_binddb.sdb_type_nodes = nodep;
 321  321  
 322  322                          sgen_log(NULL, SGEN_DIAG2, "found device type "
 323  323                              "'%s' in device-type-config-list, "
 324  324                              "device unit-address @%s",
 325  325                              cp, ddi_get_name_addr(dip));
 326  326                  }
 327  327                  ddi_prop_free(strs);
 328  328          }
 329  329  
 330  330          /*
 331  331           * for each Vendor/Product inquiry pair, build a node and put it
 332  332           * into the the binddb.
 333  333           */
 334  334          if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
 335  335              "inquiry-config-list", &strs, &nelems) == DDI_PROP_SUCCESS) {
 336  336  
 337  337                  if (nelems % 2 == 1) {
 338  338                          sgen_log(NULL, CE_WARN, "inquiry-config-list must "
 339  339                              "contain Vendor/Product pairs, "
 340  340                              "device unit-address @%s",
 341  341                              ddi_get_name_addr(dip));
 342  342                          nelems--;
 343  343                  }
 344  344                  for (idx = 0; idx < nelems; idx += 2) {
 345  345                          sgen_inq_node_t *nodep;
 346  346                          /*
 347  347                           * Grab vendor and product ID.
 348  348                           */
 349  349                          vcp = strs[idx];
 350  350                          vcplen = strlen(vcp);
 351  351                          if (vcplen == 0 || vcplen > SGEN_VENDID_MAX) {
 352  352                                  sgen_log(NULL, CE_WARN,
 353  353                                      "Invalid vendor ID '%s', "
 354  354                                      "device unit-address @%s",
 355  355                                      vcp, ddi_get_name_addr(dip));
 356  356                                  continue;
 357  357                          }
 358  358  
 359  359                          pcp = strs[idx + 1];
 360  360                          pcplen = strlen(pcp);
 361  361                          if (pcplen == 0 || pcplen > SGEN_PRODID_MAX) {
 362  362                                  sgen_log(NULL, CE_WARN,
 363  363                                      "Invalid product ID '%s', "
 364  364                                      "device unit-address @%s",
 365  365                                      pcp, ddi_get_name_addr(dip));
 366  366                                  continue;
 367  367                          }
 368  368  
 369  369                          nodep = kmem_zalloc(sizeof (sgen_inq_node_t),
 370  370                              KM_SLEEP);
 371  371                          nodep->node_vendor = kmem_alloc(vcplen + 1, KM_SLEEP);
 372  372                          (void) strcpy(nodep->node_vendor, vcp);
 373  373                          nodep->node_product = kmem_alloc(pcplen + 1, KM_SLEEP);
 374  374                          (void) strcpy(nodep->node_product, pcp);
 375  375  
 376  376                          nodep->node_next = sgen_binddb.sdb_inq_nodes;
 377  377                          sgen_binddb.sdb_inq_nodes = nodep;
 378  378  
 379  379                          sgen_log(NULL, SGEN_DIAG2, "found inquiry string "
 380  380                              "'%s' '%s' in device-type-config-list, "
 381  381                              "device unit-address @%s",
 382  382                              nodep->node_vendor, nodep->node_product,
 383  383                              ddi_get_name_addr(dip));
 384  384                  }
 385  385                  ddi_prop_free(strs);
 386  386          }
 387  387  
 388  388          sgen_binddb.sdb_init = 1;
 389  389  }
 390  390  
 391  391  /*
 392  392   * sgen_cleanup_binddb()
 393  393   *      deallocate data structures for binding database.
 394  394   */
 395  395  static void
 396  396  sgen_cleanup_binddb()
 397  397  {
 398  398          sgen_inq_node_t *inqp, *inqnextp;
 399  399          sgen_type_node_t *typep, *typenextp;
 400  400  
 401  401          mutex_enter(&sgen_binddb.sdb_lock);
 402  402          if (sgen_binddb.sdb_init == 0) {
 403  403                  mutex_exit(&sgen_binddb.sdb_lock);
 404  404                  return;
 405  405          }
 406  406  
 407  407          for (inqp = sgen_binddb.sdb_inq_nodes; inqp != NULL; inqp = inqnextp) {
 408  408                  inqnextp = inqp->node_next;
 409  409                  ASSERT(inqp->node_vendor && inqp->node_product);
 410  410                  kmem_free(inqp->node_vendor,
 411  411                      strlen(inqp->node_vendor) + 1);
 412  412                  kmem_free(inqp->node_product,
 413  413                      strlen(inqp->node_product) + 1);
 414  414                  kmem_free(inqp, sizeof (sgen_inq_node_t));
 415  415          }
 416  416  
 417  417          for (typep = sgen_binddb.sdb_type_nodes; typep != NULL;
 418  418              typep = typenextp) {
 419  419                  typenextp = typep->node_next;
 420  420                  kmem_free(typep, sizeof (sgen_type_node_t));
 421  421          }
 422  422          mutex_exit(&sgen_binddb.sdb_lock);
 423  423  }
 424  424  
 425  425  /*
 426  426   * sgen_bind_byinq()
 427  427   *      lookup a device in the binding database by its inquiry data.
 428  428   */
 429  429  static int
 430  430  sgen_bind_byinq(dev_info_t *dip)
 431  431  {
 432  432          sgen_inq_node_t *nodep;
 433  433          char vend_str[SGEN_VENDID_MAX+1];
 434  434          char prod_str[SGEN_PRODID_MAX+1];
 435  435          struct scsi_device *scsidevp;
 436  436  
 437  437          scsidevp = ddi_get_driver_private(dip);
 438  438  
 439  439          /*
 440  440           * inq_vid and inq_pid are laid out by the protocol in order in the
 441  441           * inquiry structure, and are not delimited by \0.
 442  442           */
 443  443          bcopy(scsidevp->sd_inq->inq_vid, vend_str, SGEN_VENDID_MAX);
 444  444          vend_str[SGEN_VENDID_MAX] = '\0';
 445  445          bcopy(scsidevp->sd_inq->inq_pid, prod_str, SGEN_PRODID_MAX);
 446  446          prod_str[SGEN_PRODID_MAX] = '\0';
 447  447  
 448  448          for (nodep = sgen_binddb.sdb_inq_nodes; nodep != NULL;
 449  449              nodep = nodep->node_next) {
 450  450                  /*
 451  451                   * Allow the "*" wildcard to match all vendor IDs.
 452  452                   */
 453  453                  if (strcmp(nodep->node_vendor, "*") != 0) {
 454  454                          if (strncasecmp(nodep->node_vendor, vend_str,
 455  455                              strlen(nodep->node_vendor)) != 0) {
 456  456                                  continue;
 457  457                          }
 458  458                  }
 459  459  
 460  460                  /*
 461  461                   * Using strncasecmp() with the key length allows substring
 462  462                   * matching for product data.
 463  463                   */
 464  464                  if (strncasecmp(nodep->node_product, prod_str,
 465  465                      strlen(nodep->node_product)) == 0) {
 466  466                          return (0);
 467  467                  }
 468  468          }
 469  469          return (-1);
 470  470  }
 471  471  
 472  472  /*
 473  473   * sgen_bind_bytype()
 474  474   *      lookup a device type in the binding database; if found, return a
 475  475   *      format string corresponding to the string in the .conf file.
 476  476   */
 477  477  static int
 478  478  sgen_bind_bytype(dev_info_t *dip)
 479  479  {
 480  480          sgen_type_node_t *nodep;
 481  481          struct scsi_device *scsidevp;
 482  482  
 483  483          scsidevp = ddi_get_driver_private(dip);
 484  484  
 485  485          for (nodep = sgen_binddb.sdb_type_nodes; nodep != NULL;
 486  486              nodep = nodep->node_next) {
 487  487                  if (nodep->node_type == scsidevp->sd_inq->inq_dtype) {
 488  488                          return (0);
 489  489                  }
 490  490          }
 491  491          return (-1);
 492  492  }
 493  493  
 494  494  /*
 495  495   * sgen_get_binding()
 496  496   *      Check to see if the device in question matches the criteria for
 497  497   *      sgen to bind.
 498  498   *
 499  499   *      Either the .conf file must specify a device_type entry which
 500  500   *      matches the SCSI device type of this device, or the inquiry
 501  501   *      string provided by the device must match an inquiry string specified
 502  502   *      in the .conf file.  Inquiry data is matched first.
 503  503   */
 504  504  static int
 505  505  sgen_get_binding(dev_info_t *dip)
 506  506  {
 507  507          int retval = 0;
 508  508  
 509  509          mutex_enter(&sgen_binddb.sdb_lock);
 510  510          if (sgen_binddb.sdb_init == 0)
 511  511                  sgen_setup_binddb(dip);
 512  512          mutex_exit(&sgen_binddb.sdb_lock);
 513  513  
 514  514  
 515  515          /*
 516  516           * Check device-type-config-list for a match by device type.
 517  517           */
 518  518          if (sgen_bind_bytype(dip) == 0)
 519  519                  goto done;
 520  520  
 521  521          /*
 522  522           * Check inquiry-config-list for a match by Vendor/Product ID.
 523  523           */
 524  524          if (sgen_bind_byinq(dip) == 0)
 525  525                  goto done;
 526  526  
 527  527          retval = -1;
 528  528  done:
 529  529          return (retval);
 530  530  }
 531  531  
 532  532  /*
 533  533   * sgen_attach()
 534  534   *      attach(9e) entrypoint.
 535  535   */
 536  536  static int
 537  537  sgen_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
 538  538  {
 539  539          int err;
 540  540  
 541  541          sgen_log(NULL, SGEN_DIAG2, "in sgen_attach(), device unit-address @%s",
 542  542              ddi_get_name_addr(dip));
 543  543  
 544  544          switch (cmd) {
 545  545          case DDI_ATTACH:
 546  546                  err = sgen_do_attach(dip);
 547  547                  break;
 548  548          case DDI_RESUME:
 549  549                  err = DDI_SUCCESS;
 550  550                  break;
 551  551          case DDI_PM_RESUME:
 552  552          default:
 553  553                  err = DDI_FAILURE;
 554  554                  break;
 555  555          }
 556  556  
 557  557  done:
 558  558          sgen_log(NULL, SGEN_DIAG2, "%s sgen_attach(), device unit-address @%s",
 559  559              err == DDI_SUCCESS ? "done" : "failed", ddi_get_name_addr(dip));
 560  560          return (err);
 561  561  }
 562  562  
 563  563  /*
 564  564   * sgen_do_attach()
 565  565   *      handle the nitty details of attach.
 566  566   */
 567  567  static int
 568  568  sgen_do_attach(dev_info_t *dip)
 569  569  {
 570  570          int instance;
 571  571          struct scsi_device *scsidevp;
 572  572          sgen_state_t *sg_state;
 573  573          uchar_t devtype;
 574  574          struct scsi_inquiry *inq;
 575  575  
 576  576          instance = ddi_get_instance(dip);
 577  577  
 578  578          scsidevp = ddi_get_driver_private(dip);
 579  579          ASSERT(scsidevp);
 580  580  
 581  581          sgen_log(NULL, SGEN_DIAG2, "sgen_do_attach: instance = %d, "
 582  582              "device unit-address @%s", instance, ddi_get_name_addr(dip));
 583  583  
 584  584          /*
 585  585           * Probe the device in order to get its device type to name the minor
 586  586           * node.
 587  587           */
 588  588          if (scsi_probe(scsidevp, NULL_FUNC) != SCSIPROBE_EXISTS) {
 589  589                  scsi_unprobe(scsidevp);
 590  590                  return (DDI_FAILURE);
 591  591          }
 592  592  
 593  593          if (ddi_soft_state_zalloc(sgen_soft_state, instance) != DDI_SUCCESS) {
 594  594                  sgen_log(NULL, SGEN_DIAG1,
 595  595                      "sgen_do_attach: failed to allocate softstate, "
 596  596                      "device unit-address @%s", ddi_get_name_addr(dip));
 597  597                  scsi_unprobe(scsidevp);
 598  598                  return (DDI_FAILURE);
 599  599          }
 600  600  
 601  601          inq = scsidevp->sd_inq;         /* valid while device is probed... */
 602  602          devtype = inq->inq_dtype;
 603  603  
 604  604          sg_state = ddi_get_soft_state(sgen_soft_state, instance);
 605  605          sg_state->sgen_scsidev = scsidevp;
 606  606          scsidevp->sd_dev = dip;
 607  607  
 608  608          /*
 609  609           * Now that sg_state->sgen_scsidev is initialized, it's ok to
 610  610           * call sgen_log with sg_state instead of NULL.
 611  611           */
 612  612  
 613  613          /*
 614  614           * If the user specified the sgen_diag property, override the global
 615  615           * sgen_diag setting by setting sg_state's sgen_diag value.  If the
 616  616           * user gave a value out of range, default to '0'.
 617  617           */
 618  618          sg_state->sgen_diag = ddi_getprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
 619  619              "sgen-diag", -1);
 620  620  
 621  621          if (sg_state->sgen_diag != -1) {
 622  622                  if (sg_state->sgen_diag < 0 || sg_state->sgen_diag > 3)
 623  623                          sg_state->sgen_diag = 0;
 624  624          }
 625  625  
 626  626          sgen_log(sg_state, SGEN_DIAG2,
 627  627              "sgen_do_attach: sgen_soft_state=0x%p, instance=%d, "
 628  628              "device unit-address @%s",
 629  629              sgen_soft_state, instance, ddi_get_name_addr(dip));
 630  630  
 631  631          /*
 632  632           * For simplicity, the minor number == the instance number
 633  633           */
 634  634          if (ddi_create_minor_node(dip, sgen_typename(devtype), S_IFCHR,
 635  635              instance, DDI_NT_SGEN, NULL) == DDI_FAILURE) {
 636  636                  scsi_unprobe(scsidevp);
 637  637                  ddi_prop_remove_all(dip);
 638  638                  sgen_log(sg_state, SGEN_DIAG1,
 639  639                      "sgen_do_attach: minor node creation failed, "
 640  640                      "device unit-address @%s", ddi_get_name_addr(dip));
 641  641                  ddi_soft_state_free(sgen_soft_state, instance);
 642  642                  return (DDI_FAILURE);
 643  643          }
 644  644  
 645  645          /*
 646  646           * Allocate the command buffer, then create a condition variable for
 647  647           * managing it; mark the command buffer as free.
 648  648           */
 649  649          sg_state->sgen_cmdbuf = getrbuf(KM_SLEEP);
 650  650          cv_init(&sg_state->sgen_cmdbuf_cv, NULL, CV_DRIVER, NULL);
 651  651  
 652  652          SGEN_CLR_BUSY(sg_state);
 653  653          SGEN_CLR_OPEN(sg_state);
 654  654          SGEN_CLR_SUSP(sg_state);
 655  655  
 656  656          /*
 657  657           * If the hba and the target both support wide xfers, enable them.
 658  658           */
 659  659          if (scsi_ifgetcap(&sg_state->sgen_scsiaddr, "wide-xfer", 1) != -1) {
 660  660                  int wide = 0;
 661  661                  if ((inq->inq_rdf == RDF_SCSI2) &&
 662  662                      (inq->inq_wbus16 || inq->inq_wbus32))
 663  663                          wide = 1;
 664  664                  if (scsi_ifsetcap(&sg_state->sgen_scsiaddr, "wide-xfer",
 665  665                      wide, 1) == 1) {
 666  666                          sgen_log(sg_state, SGEN_DIAG1,
 667  667                              "sgen_attach: wide xfer %s, "
 668  668                              "device unit-address @%s",
 669  669                              wide ? "enabled" : "disabled",
 670  670                              ddi_get_name_addr(dip));
 671  671                  }
 672  672          }
 673  673  
 674  674          /*
 675  675           * This is a little debugging code-- since the codepath for auto-sense
 676  676           * and 'manual' sense is split, toggling this variable will make
 677  677           * sgen act as though the adapter in question can't do auto-sense.
 678  678           */
 679  679          if (sgen_force_manual_sense) {
 680  680                  if (scsi_ifsetcap(&sg_state->sgen_scsiaddr, "auto-rqsense",
 681  681                      0, 1) == 1) {
 682  682                          sg_state->sgen_arq_enabled = 0;
 683  683                  } else {
 684  684                          sg_state->sgen_arq_enabled = 1;
 685  685                  }
 686  686          } else {
 687  687                  /*
 688  688                   * Enable autorequest sense, if supported
 689  689                   */
 690  690                  if (scsi_ifgetcap(&sg_state->sgen_scsiaddr,
 691  691                      "auto-rqsense", 1) != 1) {
 692  692                          if (scsi_ifsetcap(&sg_state->sgen_scsiaddr,
 693  693                              "auto-rqsense", 1, 1) == 1) {
 694  694                                  sg_state->sgen_arq_enabled = 1;
 695  695                                  sgen_log(sg_state, SGEN_DIAG1,
 696  696                                      "sgen_attach: auto-request-sense enabled, "
 697  697                                      "device unit-address @%s",
 698  698                                      ddi_get_name_addr(dip));
 699  699                          } else {
 700  700                                  sg_state->sgen_arq_enabled = 0;
 701  701                                  sgen_log(sg_state, SGEN_DIAG1,
 702  702                                      "sgen_attach: auto-request-sense disabled, "
 703  703                                      "device unit-address @%s",
 704  704                                      ddi_get_name_addr(dip));
 705  705                          }
 706  706                  } else {
 707  707                          sg_state->sgen_arq_enabled = 1; /* already enabled */
 708  708                          sgen_log(sg_state, SGEN_DIAG1,
 709  709                              "sgen_attach: auto-request-sense enabled, "
 710  710                              "device unit-address @%s", ddi_get_name_addr(dip));
 711  711                  }
 712  712          }
 713  713  
 714  714          /*
 715  715           * Allocate plumbing for manually fetching sense.
 716  716           */
 717  717          if (sgen_setup_sense(sg_state) != 0) {
 718  718                  freerbuf(sg_state->sgen_cmdbuf);
 719  719                  ddi_prop_remove_all(dip);
 720  720                  ddi_remove_minor_node(dip, NULL);
 721  721                  scsi_unprobe(scsidevp);
 722  722                  sgen_log(sg_state, SGEN_DIAG1,
 723  723                      "sgen_do_attach: failed to setup request-sense, "
 724  724                      "device unit-address @%s", ddi_get_name_addr(dip));
 725  725                  ddi_soft_state_free(sgen_soft_state, instance);
 726  726                  return (DDI_FAILURE);
 727  727          }
 728  728  
 729  729          sgen_create_errstats(sg_state, instance);
 730  730  
 731  731          ddi_report_dev(dip);
 732  732  
 733  733          return (DDI_SUCCESS);
 734  734  }
 735  735  
 736  736  /*
 737  737   * sgen_setup_sense()
 738  738   *      Allocate a request sense packet so that if sgen needs to fetch sense
 739  739   *      data for the user, it will have a pkt ready to send.
 740  740   */
 741  741  static int
 742  742  sgen_setup_sense(sgen_state_t *sg_state)
 743  743  {
 744  744          struct buf *bp;
 745  745          struct scsi_pkt *rqpkt;
 746  746  
 747  747          if ((bp = scsi_alloc_consistent_buf(&sg_state->sgen_scsiaddr, NULL,
 748  748              MAX_SENSE_LENGTH, B_READ, SLEEP_FUNC, NULL)) == NULL) {
 749  749                  return (-1);
 750  750          }
 751  751  
 752  752          if ((rqpkt = scsi_init_pkt(&sg_state->sgen_scsiaddr, NULL, bp,
 753  753              CDB_GROUP0, 1, 0, PKT_CONSISTENT, SLEEP_FUNC, NULL)) == NULL) {
 754  754                  scsi_free_consistent_buf(bp);
 755  755                  return (-1);
 756  756          }
 757  757  
 758  758          /*
 759  759           * Make the results of running a SENSE available by filling out the
 760  760           * sd_sense field of the scsi device (sgen_sense is just an alias).
 761  761           */
 762  762          sg_state->sgen_sense = (struct scsi_extended_sense *)bp->b_un.b_addr;
 763  763  
 764  764          (void) scsi_setup_cdb((union scsi_cdb *)rqpkt->pkt_cdbp,
 765  765              SCMD_REQUEST_SENSE, 0, MAX_SENSE_LENGTH, 0);
 766  766          FILL_SCSI1_LUN(sg_state->sgen_scsidev, rqpkt);
 767  767  
 768  768          rqpkt->pkt_comp = sgen_callback;
 769  769          rqpkt->pkt_time = SGEN_IO_TIME;
 770  770          rqpkt->pkt_flags |= FLAG_SENSING;
 771  771          rqpkt->pkt_private = sg_state;
 772  772  
 773  773          sg_state->sgen_rqspkt = rqpkt;
 774  774          sg_state->sgen_rqsbuf = bp;
 775  775  
 776  776          return (0);
 777  777  }
 778  778  
 779  779  /*
 780  780   * sgen_create_errstats()
 781  781   *      create named kstats for tracking occurrence of errors.
 782  782   */
 783  783  static void
 784  784  sgen_create_errstats(sgen_state_t *sg_state, int instance)
 785  785  {
 786  786          char kstatname[KSTAT_STRLEN];
 787  787          struct sgen_errstats *stp;
 788  788  
 789  789          (void) snprintf(kstatname, KSTAT_STRLEN, "%s%d,err",
 790  790              sgen_label, instance);
 791  791          sg_state->sgen_kstats = kstat_create("sgenerr", instance,
 792  792              kstatname, "device_error", KSTAT_TYPE_NAMED,
 793  793              sizeof (struct sgen_errstats) / sizeof (kstat_named_t),
 794  794              KSTAT_FLAG_PERSISTENT);
 795  795  
 796  796          if (sg_state->sgen_kstats == NULL)
 797  797                  return;
 798  798  
 799  799          stp = (struct sgen_errstats *)sg_state->sgen_kstats->ks_data;
 800  800          kstat_named_init(&stp->sgen_trans_err, "transport_errors",
 801  801              KSTAT_DATA_UINT32);
 802  802          kstat_named_init(&stp->sgen_restart, "command_restarts",
 803  803              KSTAT_DATA_UINT32);
 804  804          kstat_named_init(&stp->sgen_incmp_err, "incomplete_commands",
 805  805              KSTAT_DATA_UINT32);
 806  806          kstat_named_init(&stp->sgen_autosen_rcv, "autosense_occurred",
 807  807              KSTAT_DATA_UINT32);
 808  808          kstat_named_init(&stp->sgen_autosen_bad, "autosense_undecipherable",
 809  809              KSTAT_DATA_UINT32);
 810  810          kstat_named_init(&stp->sgen_sense_rcv, "sense_fetches",
 811  811              KSTAT_DATA_UINT32);
 812  812          kstat_named_init(&stp->sgen_sense_bad, "sense_data_undecipherable",
 813  813              KSTAT_DATA_UINT32);
 814  814          kstat_named_init(&stp->sgen_recov_err, "recoverable_error",
 815  815              KSTAT_DATA_UINT32);
 816  816          kstat_named_init(&stp->sgen_nosen_err, "NO_SENSE_sense_key",
 817  817              KSTAT_DATA_UINT32);
 818  818          kstat_named_init(&stp->sgen_unrecov_err, "unrecoverable_sense_error",
 819  819              KSTAT_DATA_UINT32);
 820  820          sg_state->sgen_kstats->ks_private = sg_state;
 821  821          sg_state->sgen_kstats->ks_update = nulldev;
 822  822          kstat_install(sg_state->sgen_kstats);
 823  823  }
 824  824  
 825  825  /*
 826  826   * sgen_detach()
 827  827   *      detach(9E) entrypoint
 828  828   */
 829  829  static int
 830  830  sgen_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
 831  831  {
 832  832          int instance;
 833  833          sgen_state_t *sg_state;
 834  834  
 835  835          instance = ddi_get_instance(dip);
 836  836          sg_state = ddi_get_soft_state(sgen_soft_state, instance);
 837  837  
 838  838          sgen_log(sg_state, SGEN_DIAG2, "in sgen_detach(), "
 839  839              "device unit-address @%s", ddi_get_name_addr(dip));
 840  840  
 841  841          if (sg_state == NULL) {
 842  842                  sgen_log(NULL, SGEN_DIAG1,
 843  843                      "sgen_detach: failed, no softstate found (%d), "
 844  844                      "device unit-address @%s",
 845  845                      instance, ddi_get_name_addr(dip));
 846  846                  return (DDI_FAILURE);
 847  847          }
 848  848  
 849  849          switch (cmd) {
 850  850          case DDI_DETACH:
 851  851                  return (sgen_do_detach(dip));
 852  852          case DDI_SUSPEND:
 853  853                  return (sgen_do_suspend(dip));
 854  854          case DDI_PM_SUSPEND:
 855  855          default:
 856  856                  return (DDI_FAILURE);
 857  857          }
 858  858  }
 859  859  
 860  860  /*
 861  861   * sgen_do_detach()
 862  862   *      detach the driver, tearing down resources.
 863  863   */
 864  864  static int
 865  865  sgen_do_detach(dev_info_t *dip)
 866  866  {
 867  867          int instance;
 868  868          sgen_state_t *sg_state;
 869  869          struct scsi_device *devp;
 870  870  
 871  871          instance = ddi_get_instance(dip);
 872  872          sg_state = ddi_get_soft_state(sgen_soft_state, instance);
 873  873          ASSERT(sg_state);
 874  874  
 875  875          sgen_log(sg_state, SGEN_DIAG2, "in sgen_do_detach(), "
 876  876              "device unit-address @%s", ddi_get_name_addr(dip));
 877  877          devp = ddi_get_driver_private(dip);
 878  878  
 879  879          mutex_enter(&sg_state->sgen_mutex);
 880  880          if (SGEN_IS_BUSY(sg_state)) {
 881  881                  mutex_exit(&sg_state->sgen_mutex);
 882  882                  sgen_log(sg_state, SGEN_DIAG1, "sgen_do_detach: failed because "
 883  883                      "device is busy, device unit-address @%s",
 884  884                      ddi_get_name_addr(dip));
 885  885                  return (DDI_FAILURE);
 886  886          }
 887  887          mutex_exit(&sg_state->sgen_mutex);
 888  888  
 889  889          /*
 890  890           * Final approach for detach.  Free data allocated by scsi_probe()
 891  891           * in attach.
 892  892           */
 893  893          if (sg_state->sgen_restart_timeid)
 894  894                  (void) untimeout(sg_state->sgen_restart_timeid);
 895  895          sg_state->sgen_restart_timeid = 0;
 896  896          scsi_unprobe(devp);
 897  897  
 898  898          /*
 899  899           * Free auto-request plumbing.
 900  900           */
 901  901          scsi_free_consistent_buf(sg_state->sgen_rqsbuf);
 902  902          scsi_destroy_pkt(sg_state->sgen_rqspkt);
 903  903  
 904  904          if (sg_state->sgen_kstats) {
 905  905                  kstat_delete(sg_state->sgen_kstats);
 906  906                  sg_state->sgen_kstats = NULL;
 907  907          }
 908  908  
 909  909          /*
 910  910           * Free command buffer and clean up
 911  911           */
 912  912          freerbuf(sg_state->sgen_cmdbuf);
 913  913          cv_destroy(&sg_state->sgen_cmdbuf_cv);
 914  914  
 915  915          sgen_log(sg_state, SGEN_DIAG2, "done sgen_do_detach(), "
 916  916              "device unit-address @%s", ddi_get_name_addr(dip));
 917  917  
 918  918          ddi_soft_state_free(sgen_soft_state, instance);
 919  919          ddi_prop_remove_all(dip);
 920  920          ddi_remove_minor_node(dip, NULL);
 921  921          return (DDI_SUCCESS);
 922  922  }
 923  923  
 924  924  /*
 925  925   * sgen_do_suspend()
 926  926   *      suspend the driver.  This sets the "suspend" bit for this target if it
 927  927   *      is currently open; once resumed, the suspend bit will cause
 928  928   *      subsequent I/Os to fail.  We want user programs to close and
 929  929   *      reopen the device to acknowledge that they need to reexamine its
 930  930   *      state and do the right thing.
 931  931   */
 932  932  static int
 933  933  sgen_do_suspend(dev_info_t *dip)
 934  934  {
 935  935          int instance;
 936  936          sgen_state_t *sg_state;
 937  937  
 938  938          instance = ddi_get_instance(dip);
 939  939          sg_state = ddi_get_soft_state(sgen_soft_state, instance);
 940  940          ASSERT(sg_state);
 941  941  
 942  942          sgen_log(sg_state, SGEN_DIAG2, "in sgen_do_suspend(), "
 943  943              "device unit-address @%s", ddi_get_name_addr(dip));
 944  944  
 945  945          if (sg_state->sgen_restart_timeid) {
 946  946                  (void) untimeout(sg_state->sgen_restart_timeid);
 947  947          }
 948  948          sg_state->sgen_restart_timeid = 0;
 949  949  
 950  950          mutex_enter(&sg_state->sgen_mutex);
 951  951          if (SGEN_IS_OPEN(sg_state))
 952  952                  SGEN_SET_SUSP(sg_state);
 953  953          mutex_exit(&sg_state->sgen_mutex);
 954  954  
 955  955          sgen_log(sg_state, SGEN_DIAG2, "done sgen_do_suspend(), "
 956  956              "device unit-address @%s", ddi_get_name_addr(dip));
 957  957          return (DDI_SUCCESS);
 958  958  }
 959  959  
 960  960  /*
 961  961   * sgen_getinfo()
 962  962   *      getinfo(9e) entrypoint.
 963  963   */
 964  964  /*ARGSUSED*/
 965  965  static int
 966  966  sgen_getinfo(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
 967  967  {
 968  968          dev_t dev;
 969  969          sgen_state_t *sg_state;
 970  970          int instance, error;
 971  971          switch (infocmd) {
 972  972          case DDI_INFO_DEVT2DEVINFO:
 973  973                  dev = (dev_t)arg;
 974  974                  instance = getminor(dev);
 975  975                  if ((sg_state = ddi_get_soft_state(sgen_soft_state, instance))
 976  976                      == NULL)
 977  977                          return (DDI_FAILURE);
 978  978                  *result = (void *) sg_state->sgen_scsidev->sd_dev;
 979  979                  error = DDI_SUCCESS;
 980  980                  break;
 981  981          case DDI_INFO_DEVT2INSTANCE:
 982  982                  dev = (dev_t)arg;
 983  983                  instance = getminor(dev);
 984  984                  *result = (void *)(uintptr_t)instance;
 985  985                  error = DDI_SUCCESS;
 986  986                  break;
 987  987          default:
 988  988                  error = DDI_FAILURE;
 989  989          }
 990  990          return (error);
 991  991  }
 992  992  
 993  993  /*
 994  994   * sgen_probe()
 995  995   *      probe(9e) entrypoint.  sgen *never* returns DDI_PROBE_PARTIAL, in
 996  996   *      order to avoid leaving around extra devinfos.  If sgen's binding
 997  997   *      rules indicate that it should bind, it returns DDI_PROBE_SUCCESS.
 998  998   */
 999  999  static int
1000 1000  sgen_probe(dev_info_t *dip)
1001 1001  {
1002 1002          struct scsi_device *scsidevp;
1003 1003          int instance;
1004 1004          int rval;
1005 1005  
1006 1006          scsidevp = ddi_get_driver_private(dip);
1007 1007          instance = ddi_get_instance(dip);
1008 1008          sgen_log(NULL, SGEN_DIAG2, "in sgen_probe(): instance = %d, "
1009 1009              "device unit-address @%s", instance, ddi_get_name_addr(dip));
1010 1010  
1011 1011          if (ddi_dev_is_sid(dip) == DDI_SUCCESS)
1012 1012                  return (DDI_PROBE_DONTCARE);
1013 1013  
1014 1014          if (ddi_get_soft_state(sgen_soft_state, instance) != NULL)
1015 1015                  return (DDI_PROBE_FAILURE);
1016 1016  
1017 1017          mutex_enter(&sgen_binddb.sdb_lock);
1018 1018          if (sgen_binddb.sdb_init == 0) {
1019 1019                  sgen_setup_binddb(dip);
1020 1020          }
1021 1021          mutex_exit(&sgen_binddb.sdb_lock);
1022 1022  
1023 1023          /*
1024 1024           * A small optimization: if it's impossible for sgen to bind to
1025 1025           * any devices, don't bother probing, just fail.
1026 1026           */
1027 1027          if ((sgen_binddb.sdb_inq_nodes == NULL) &&
1028 1028              (sgen_binddb.sdb_type_nodes == NULL)) {
1029 1029                  return (DDI_PROBE_FAILURE);
1030 1030          }
1031 1031  
1032 1032          if (scsi_probe(scsidevp, NULL_FUNC) == SCSIPROBE_EXISTS) {
1033 1033                  if (sgen_get_binding(dip) == 0) {
1034 1034                          rval = DDI_PROBE_SUCCESS;
1035 1035                  }
1036 1036          } else {
1037 1037                  rval = DDI_PROBE_FAILURE;
1038 1038          }
1039 1039          scsi_unprobe(scsidevp);
1040 1040  
1041 1041          sgen_log(NULL, SGEN_DIAG2, "sgen_probe() %s, device unit-address @%s",
1042 1042              rval == DDI_PROBE_SUCCESS ? "succeeded" : "failed",
1043 1043              ddi_get_name_addr(dip));
1044 1044          return (rval);
1045 1045  }
1046 1046  
1047 1047  /*
1048 1048   * sgen_open()
1049 1049   *      open(9e) entrypoint.  sgen enforces a strict exclusive open policy per
1050 1050   *      target.
1051 1051   */
1052 1052  /*ARGSUSED1*/
1053 1053  static int
1054 1054  sgen_open(dev_t *dev_p, int flag, int otyp, cred_t *cred_p)
1055 1055  {
1056 1056          dev_t dev = *dev_p;
1057 1057          sgen_state_t *sg_state;
1058 1058          int instance;
1059 1059  
1060 1060          instance = getminor(dev);
1061 1061  
1062 1062          if ((sg_state = ddi_get_soft_state(sgen_soft_state, instance)) == NULL)
1063 1063                  return (ENXIO);
1064 1064  
1065 1065          sgen_log(sg_state, SGEN_DIAG2, "in sgen_open(): instance = %d",
1066 1066              instance);
1067 1067  
1068 1068          mutex_enter(&sg_state->sgen_mutex);
1069 1069  
1070 1070          /*
1071 1071           * Don't allow new opens of a suspended device until the last close has
1072 1072           * happened.  This is rather simplistic, but keeps the implementation
1073 1073           * straightforward.
1074 1074           */
1075 1075          if (SGEN_IS_SUSP(sg_state)) {
1076 1076                  mutex_exit(&sg_state->sgen_mutex);
1077 1077                  return (EIO);
1078 1078          }
1079 1079  
1080 1080          /*
1081 1081           * Enforce exclusive access.
1082 1082           */
1083 1083          if (SGEN_IS_EXCL(sg_state) ||
1084 1084              (SGEN_IS_OPEN(sg_state) && (flag & FEXCL))) {
1085 1085                  mutex_exit(&sg_state->sgen_mutex);
1086 1086                  return (EBUSY);
1087 1087          }
1088 1088  
1089 1089          if (flag & FEXCL)
1090 1090                  SGEN_SET_EXCL(sg_state);
1091 1091  
1092 1092          SGEN_SET_OPEN(sg_state);
1093 1093  
1094 1094          mutex_exit(&sg_state->sgen_mutex);
1095 1095  
1096 1096          return (0);
1097 1097  }
1098 1098  
1099 1099  /*
1100 1100   * sgen_close()
1101 1101   *      close(9e) entrypoint.
1102 1102   */
1103 1103  /*ARGSUSED1*/
1104 1104  static int
1105 1105  sgen_close(dev_t dev, int flag, int otyp, cred_t *cred_p)
1106 1106  {
1107 1107          sgen_state_t *sg_state;
1108 1108          int instance;
1109 1109  
1110 1110          instance = getminor(dev);
1111 1111  
1112 1112          if ((sg_state = ddi_get_soft_state(sgen_soft_state, instance)) == NULL)
1113 1113                  return (ENXIO);
1114 1114  
1115 1115          sgen_log(sg_state, SGEN_DIAG2, "in sgen_close(): instance = %d",
1116 1116              instance);
1117 1117  
1118 1118          mutex_enter(&sg_state->sgen_mutex);
1119 1119          SGEN_CLR_OPEN(sg_state);
1120 1120          SGEN_CLR_EXCL(sg_state);
1121 1121          SGEN_CLR_SUSP(sg_state); /* closing clears the 'I was suspended' bit */
1122 1122          mutex_exit(&sg_state->sgen_mutex);
1123 1123  
1124 1124          sgen_log(sg_state, SGEN_DIAG2, "done sgen_close()");
1125 1125  
1126 1126          return (0);
1127 1127  }
1128 1128  
1129 1129  /*
1130 1130   * sgen_ioctl()
1131 1131   *      sgen supports the USCSI(7I) ioctl interface.
1132 1132   */
1133 1133  /*ARGSUSED4*/
1134 1134  static int
1135 1135  sgen_ioctl(dev_t dev,
1136 1136      int cmd, intptr_t arg, int flag, cred_t *cred_p, int *rval_p)
1137 1137  {
1138 1138          int retval = 0;
1139 1139          sgen_state_t *sg_state;
1140 1140          int instance;
1141 1141  
1142 1142          instance = getminor(dev);
1143 1143  
1144 1144          if ((sg_state = ddi_get_soft_state(sgen_soft_state, instance)) == NULL)
1145 1145                  return (ENXIO);
1146 1146  
1147 1147          sgen_log(sg_state, SGEN_DIAG2, "in sgen_ioctl(): instance = %d",
1148 1148              instance);
1149 1149  
1150 1150          /*
1151 1151           * If the driver has been suspended since the last open, fail all
1152 1152           * subsequent IO's so that the userland consumer reinitializes state.
1153 1153           */
1154 1154          mutex_enter(&sg_state->sgen_mutex);
1155 1155          if (SGEN_IS_SUSP(sg_state)) {
1156 1156                  mutex_exit(&sg_state->sgen_mutex);
1157 1157                  sgen_log(sg_state, SGEN_DIAG1, "sgen_ioctl: returning EIO: "
1158 1158                      "driver instance %d was previously suspended", instance);
1159 1159                  return (EIO);
1160 1160          }
1161 1161          mutex_exit(&sg_state->sgen_mutex);
1162 1162  
1163 1163          switch (cmd) {
1164 1164          case SGEN_IOC_DIAG: {
1165 1165                  if (arg > 3) {
1166 1166                          arg = 0;
1167 1167                  }
1168 1168                  sg_state->sgen_diag = (int)arg;
1169 1169                  retval = 0;
1170 1170                  break;
1171 1171          }
1172 1172  
1173 1173          case SGEN_IOC_READY: {
1174 1174                  if (sgen_tur(dev) != 0) {
1175 1175                          retval = EIO;
1176 1176                  } else {
1177 1177                          retval = 0;
1178 1178                  }
1179 1179                  break;
1180 1180          }
1181 1181  
1182 1182          case USCSICMD:
1183 1183                  retval = sgen_uscsi_cmd(dev, (struct uscsi_cmd *)arg, flag);
1184 1184                  break;
1185 1185  
1186 1186          default:
1187 1187                  retval = ENOTTY;
1188 1188          }
1189 1189  
1190 1190          sgen_log(sg_state, SGEN_DIAG2, "done sgen_ioctl(), returning %d",
1191 1191              retval);
1192 1192  
1193 1193          return (retval);
1194 1194  }
1195 1195  
1196 1196  /*
1197 1197   * sgen_uscsi_cmd()
1198 1198   *      Setup, configuration and teardown for a uscsi(7I) command
1199 1199   */
1200 1200  /*ARGSUSED*/
1201 1201  static int
1202 1202  sgen_uscsi_cmd(dev_t dev, struct uscsi_cmd *ucmd, int flag)
1203 1203  {
1204 1204          struct uscsi_cmd        *uscmd;
1205 1205          struct buf      *bp;
1206 1206          sgen_state_t    *sg_state;
1207 1207          enum uio_seg    uioseg;
1208 1208          int     instance;
1209 1209          int     flags;
1210 1210          int     err;
1211 1211  
1212 1212          instance = getminor(dev);
1213 1213  
1214 1214          sg_state = ddi_get_soft_state(sgen_soft_state, instance);
1215 1215          ASSERT(sg_state);
1216 1216  
1217 1217          sgen_log(sg_state, SGEN_DIAG2, "in sgen_uscsi_cmd(): instance = %d",
1218 1218              instance);
1219 1219  
1220 1220          /*
1221 1221           * At this point, we start affecting state relevant to the target,
1222 1222           * so access needs to be serialized.
1223 1223           */
1224 1224          if (sgen_hold_cmdbuf(sg_state) != 0) {
1225 1225                  sgen_log(sg_state, SGEN_DIAG1, "sgen_uscsi_cmd: interrupted");
1226 1226                  return (EINTR);
1227 1227          }
1228 1228  
1229 1229          err = scsi_uscsi_alloc_and_copyin((intptr_t)ucmd, flag,
1230 1230              &sg_state->sgen_scsiaddr, &uscmd);
1231 1231          if (err != 0) {
1232 1232                  sgen_rele_cmdbuf(sg_state);
1233 1233                  sgen_log(sg_state, SGEN_DIAG1, "sgen_uscsi_cmd: "
1234 1234                      "scsi_uscsi_alloc_and_copyin failed\n");
1235 1235                  return (err);
1236 1236          }
1237 1237  
1238 1238          /*
1239 1239           * Clear out undesirable command flags
1240 1240           */
1241 1241          flags = (uscmd->uscsi_flags & ~(USCSI_NOINTR | USCSI_NOPARITY |
1242 1242              USCSI_OTAG | USCSI_HTAG | USCSI_HEAD));
1243 1243          if (flags != uscmd->uscsi_flags) {
1244 1244                  sgen_log(sg_state, SGEN_DIAG1, "sgen_uscsi_cmd: cleared "
1245 1245                      "unsafe uscsi_flags 0x%x", uscmd->uscsi_flags & ~flags);
1246 1246                  uscmd->uscsi_flags = flags;
1247 1247          }
1248 1248  
1249 1249          if (uscmd->uscsi_cdb != NULL) {
1250 1250                  sgen_dump_cdb(sg_state, "sgen_uscsi_cmd: ",
1251 1251                      (union scsi_cdb *)uscmd->uscsi_cdb, uscmd->uscsi_cdblen);
1252 1252          }
1253 1253  
1254 1254          /*
1255 1255           * Stash the sense buffer into sgen_rqs_sen for convenience.
1256 1256           */
1257 1257          sg_state->sgen_rqs_sen = uscmd->uscsi_rqbuf;
1258 1258  
1259 1259          bp = sg_state->sgen_cmdbuf;
1260 1260          bp->av_back = NULL;
1261 1261          bp->av_forw = NULL;
1262 1262          bp->b_private = (struct buf *)uscmd;
1263 1263          uioseg = (flag & FKIOCTL) ? UIO_SYSSPACE : UIO_USERSPACE;
1264 1264  
1265 1265          err = scsi_uscsi_handle_cmd(dev, uioseg, uscmd, sgen_start, bp, NULL);
1266 1266  
1267 1267          if (sg_state->sgen_cmdpkt != NULL) {
1268 1268                  uscmd->uscsi_status = SCBP_C(sg_state->sgen_cmdpkt);
1269 1269          } else {
1270 1270                  uscmd->uscsi_status = 0;
1271 1271          }
1272 1272  
1273 1273          sgen_log(sg_state, SGEN_DIAG3, "sgen_uscsi_cmd: awake from waiting "
1274 1274              "for command.  Status is 0x%x", uscmd->uscsi_status);
1275 1275  
1276 1276          if (uscmd->uscsi_rqbuf != NULL) {
1277 1277                  int rqlen = uscmd->uscsi_rqlen - uscmd->uscsi_rqresid;
1278 1278                  sgen_dump_sense(sg_state, rqlen,
1279 1279                      (uchar_t *)uscmd->uscsi_rqbuf);
1280 1280          }
1281 1281  
1282 1282          (void) scsi_uscsi_copyout_and_free((intptr_t)ucmd, uscmd);
1283 1283  
1284 1284          if (sg_state->sgen_cmdpkt != NULL) {
1285 1285                  scsi_destroy_pkt(sg_state->sgen_cmdpkt);
1286 1286                  sg_state->sgen_cmdpkt = NULL;
1287 1287          }
1288 1288  
1289 1289          /*
1290 1290           * After this point, we can't touch per-target state.
1291 1291           */
1292 1292          sgen_rele_cmdbuf(sg_state);
1293 1293  
1294 1294          sgen_log(sg_state, SGEN_DIAG2, "done sgen_uscsi_cmd()");
1295 1295  
1296 1296          return (err);
1297 1297  }
1298 1298  
1299 1299  /*
1300 1300   * sgen_hold_cmdbuf()
1301 1301   *      Acquire a lock on the command buffer for the given target.  Returns
1302 1302   *      non-zero if interrupted.
1303 1303   */
1304 1304  static int
1305 1305  sgen_hold_cmdbuf(sgen_state_t *sg_state)
1306 1306  {
1307 1307          mutex_enter(&sg_state->sgen_mutex);
1308 1308          while (SGEN_IS_BUSY(sg_state)) {
1309 1309                  if (!cv_wait_sig(&sg_state->sgen_cmdbuf_cv,
1310 1310                      &sg_state->sgen_mutex)) {
1311 1311                          mutex_exit(&sg_state->sgen_mutex);
1312 1312                          return (-1);
1313 1313                  }
1314 1314          }
1315 1315          SGEN_SET_BUSY(sg_state);
1316 1316          mutex_exit(&sg_state->sgen_mutex);
1317 1317          return (0);
1318 1318  }
1319 1319  
1320 1320  /*
1321 1321   * sgen_rele_cmdbuf()
1322 1322   *      release the command buffer for a particular target.
1323 1323   */
1324 1324  static void
1325 1325  sgen_rele_cmdbuf(sgen_state_t *sg_state)
1326 1326  {
1327 1327          mutex_enter(&sg_state->sgen_mutex);
1328 1328          SGEN_CLR_BUSY(sg_state);
1329 1329          cv_signal(&sg_state->sgen_cmdbuf_cv);
1330 1330          mutex_exit(&sg_state->sgen_mutex);
1331 1331  }
1332 1332  
1333 1333  /*
1334 1334   * sgen_start()
1335 1335   *      Transport a uscsi command; this is invoked by physio() or directly
1336 1336   *      by sgen_uscsi_cmd().
1337 1337   */
1338 1338  static int
1339 1339  sgen_start(struct buf *bp)
1340 1340  {
1341 1341          sgen_state_t *sg_state;
1342 1342          dev_t dev = bp->b_edev;
1343 1343          int trans_err;
1344 1344  
1345 1345          if ((sg_state = ddi_get_soft_state(sgen_soft_state,
1346 1346              getminor(dev))) == NULL) {
1347 1347                  bp->b_resid = bp->b_bcount;
1348 1348                  bioerror(bp, ENXIO);
1349 1349                  biodone(bp);
1350 1350                  return (ENXIO);
1351 1351          }
1352 1352  
1353 1353          /*
1354 1354           * Sanity checks - command should not be complete, no packet should
1355 1355           * be allocated, and there ought to be a uscsi cmd in b_private
1356 1356           */
1357 1357          ASSERT(bp == sg_state->sgen_cmdbuf && sg_state->sgen_cmdpkt == NULL);
1358 1358          ASSERT((bp->b_flags & B_DONE) == 0);
1359 1359          ASSERT(bp->b_private);
1360 1360          if (sgen_make_uscsi_cmd(sg_state, bp) != 0) {
1361 1361                  bp->b_resid = bp->b_bcount;
1362 1362                  bioerror(bp, EFAULT);
1363 1363                  biodone(bp);
1364 1364                  return (EFAULT);
1365 1365          }
1366 1366  
1367 1367          ASSERT(sg_state->sgen_cmdpkt != NULL);
1368 1368  
1369 1369          /*
1370 1370           * Clear out the residual and error fields
1371 1371           */
1372 1372          bp->b_resid = 0;
1373 1373          bp->b_error = 0;
1374 1374  
1375 1375          trans_err = sgen_scsi_transport(sg_state->sgen_cmdpkt);
1376 1376          switch (trans_err) {
1377 1377          case TRAN_ACCEPT:
1378 1378                  break;
1379 1379          case TRAN_BUSY:
1380 1380                  sgen_log(sg_state, SGEN_DIAG2,
1381 1381                      "sgen_start: scsi_transport() returned TRAN_BUSY");
1382 1382                  sg_state->sgen_restart_timeid = timeout(sgen_restart, sg_state,
1383 1383                      SGEN_BSY_TIMEOUT);
1384 1384                  break;
1385 1385          default:
1386 1386                  /*
1387 1387                   * Indicate there has been an I/O transfer error.
1388 1388                   * Be done with the command.
1389 1389                   */
1390 1390                  mutex_enter(&sg_state->sgen_mutex);
1391 1391                  SGEN_DO_ERRSTATS(sg_state, sgen_trans_err);
1392 1392                  mutex_exit(&sg_state->sgen_mutex);
1393 1393                  sgen_log(sg_state, SGEN_DIAG2, "sgen_start: scsi_transport() "
1394 1394                      "returned %d", trans_err);
1395 1395                  bioerror(bp, EIO);
1396 1396                  biodone(bp);
1397 1397                  return (EIO);
1398 1398          }
1399 1399          sgen_log(sg_state, SGEN_DIAG2, "sgen_start: b_flags 0x%x", bp->b_flags);
1400 1400          return (0);
1401 1401  }
1402 1402  
1403 1403  /*
1404 1404   * sgen_scsi_transport()
1405 1405   *      a simple scsi_transport() wrapper which can be configured to inject
1406 1406   *      sporadic errors for testing.
1407 1407   */
1408 1408  static int
1409 1409  sgen_scsi_transport(struct scsi_pkt *pkt)
1410 1410  {
1411 1411          int trans_err;
1412 1412          static int cnt = 0;
1413 1413          sgen_state_t *sg_state = pkt->pkt_private;
1414 1414  
1415 1415          if (sgen_sporadic_failures == 0) {
1416 1416                  return (scsi_transport(pkt));
1417 1417          }
1418 1418  
1419 1419          cnt = (cnt * 2416 + 374441) % 1771875;  /* borrowed from kmem.c */
1420 1420          if (cnt % 40 == 1) {
1421 1421                  sgen_log(sg_state, SGEN_DIAG1, "sgen_scsi_transport: "
1422 1422                      "injecting sporadic BUSY");
1423 1423                  trans_err = TRAN_BUSY;
1424 1424          } else if (cnt % 40 == 2) {
1425 1425                  sgen_log(sg_state, SGEN_DIAG1, "sgen_scsi_transport: "
1426 1426                      "injecting sporadic BADPKT");
1427 1427                  trans_err = TRAN_BADPKT;
1428 1428          } else {
1429 1429                  /*
1430 1430                   * Most of the time we take the normal path
1431 1431                   */
1432 1432                  trans_err = scsi_transport(pkt);
1433 1433          }
1434 1434          return (trans_err);
1435 1435  }
1436 1436  
1437 1437  /*
1438 1438   * sgen_make_uscsi_cmd()
1439 1439   *      Initialize a SCSI packet usable for USCSI.
1440 1440   */
1441 1441  static int
1442 1442  sgen_make_uscsi_cmd(sgen_state_t *sg_state, struct buf *bp)
1443 1443  {
1444 1444          struct scsi_pkt *pkt;
1445 1445          struct uscsi_cmd *ucmd;
1446 1446          int stat_size = 1;
1447 1447          int flags = 0;
1448 1448  
1449 1449          ASSERT(bp);
1450 1450  
1451 1451          sgen_log(sg_state, SGEN_DIAG2, "in sgen_make_uscsi_cmd()");
1452 1452  
1453 1453          ucmd = (struct uscsi_cmd *)bp->b_private;
1454 1454  
1455 1455          if (ucmd->uscsi_flags & USCSI_RQENABLE) {
1456 1456                  if (ucmd->uscsi_rqlen > SENSE_LENGTH) {
1457 1457                          stat_size = (int)(ucmd->uscsi_rqlen) +
1458 1458                              sizeof (struct scsi_arq_status) -
1459 1459                              sizeof (struct scsi_extended_sense);
1460 1460                          flags = PKT_XARQ;
1461 1461                  } else {
1462 1462                          stat_size = sizeof (struct scsi_arq_status);
1463 1463                  }
1464 1464          }
1465 1465  
1466 1466          sgen_log(sg_state, SGEN_DIAG3, "sgen_make_uscsi_cmd: b_bcount = %ld",
1467 1467              bp->b_bcount);
1468 1468          pkt = scsi_init_pkt(&sg_state->sgen_scsiaddr,
1469 1469              NULL,                       /* in_pkt - null so it'll be alloc'd */
1470 1470              bp->b_bcount ? bp : NULL,   /* buf structure for data xfer */
1471 1471              ucmd->uscsi_cdblen,         /* cmdlen */
1472 1472              stat_size,                  /* statuslen */
1473 1473              0,                          /* privatelen */
1474 1474              flags,                      /* flags */
1475 1475              SLEEP_FUNC,                 /* callback */
1476 1476              (caddr_t)sg_state);         /* callback_arg */
1477 1477  
1478 1478          if (pkt == NULL) {
1479 1479                  sgen_log(sg_state, SGEN_DIAG2, "failed sgen_make_uscsi_cmd()");
1480 1480                  return (-1);
1481 1481          }
1482 1482  
1483 1483          pkt->pkt_comp = sgen_callback;
1484 1484          pkt->pkt_private = sg_state;
1485 1485          sg_state->sgen_cmdpkt = pkt;
1486 1486  
1487 1487          /*
1488 1488           * We *don't* call scsi_setup_cdb here, as is customary, since the
1489 1489           * user could specify a command from one group, but pass cdblen
1490 1490           * as something totally different.  If cdblen is smaller than expected,
1491 1491           * this results in scsi_setup_cdb writing past the end of the cdb.
1492 1492           */
1493 1493          bcopy(ucmd->uscsi_cdb, pkt->pkt_cdbp, ucmd->uscsi_cdblen);
1494 1494          if (ucmd->uscsi_cdblen >= CDB_GROUP0) {
1495 1495                  FILL_SCSI1_LUN(sg_state->sgen_scsidev, pkt);
1496 1496          }
1497 1497  
1498 1498          if (ucmd->uscsi_timeout > 0)
1499 1499                  pkt->pkt_time = ucmd->uscsi_timeout;
1500 1500          else
1501 1501                  pkt->pkt_time = SGEN_IO_TIME;
1502 1502  
1503 1503          /*
1504 1504           * Set packet options
1505 1505           */
1506 1506          if (ucmd->uscsi_flags & USCSI_SILENT)
1507 1507                  pkt->pkt_flags |= FLAG_SILENT;
1508 1508          if (ucmd->uscsi_flags & USCSI_ISOLATE)
1509 1509                  pkt->pkt_flags |= FLAG_ISOLATE;
1510 1510          if (ucmd->uscsi_flags & USCSI_DIAGNOSE)
1511 1511                  pkt->pkt_flags |= FLAG_DIAGNOSE;
1512 1512          if (ucmd->uscsi_flags & USCSI_RENEGOT) {
1513 1513                  pkt->pkt_flags |= FLAG_RENEGOTIATE_WIDE_SYNC;
1514 1514          }
1515 1515  
1516 1516          /* Transfer uscsi information to scsi_pkt */
1517 1517          (void) scsi_uscsi_pktinit(ucmd, pkt);
1518 1518  
1519 1519          sgen_log(sg_state, SGEN_DIAG2, "done sgen_make_uscsi_cmd()");
1520 1520          return (0);
1521 1521  }
1522 1522  
1523 1523  
1524 1524  /*
1525 1525   * sgen_restart()
1526 1526   *      sgen_restart() is called after a timeout, when a command has been
1527 1527   *      postponed due to a TRAN_BUSY response from the HBA.
1528 1528   */
1529 1529  static void
1530 1530  sgen_restart(void *arg)
1531 1531  {
1532 1532          sgen_state_t *sg_state = (sgen_state_t *)arg;
1533 1533          struct scsi_pkt *pkt;
1534 1534          struct buf *bp;
1535 1535  
1536 1536          sgen_log(sg_state, SGEN_DIAG2, "in sgen_restart()");
1537 1537  
1538 1538          bp = sg_state->sgen_cmdbuf;
1539 1539          pkt = sg_state->sgen_cmdpkt;
1540 1540          ASSERT(bp && pkt);
1541 1541  
1542 1542          SGEN_DO_ERRSTATS(sg_state, sgen_restart);
1543 1543  
1544 1544          /*
1545 1545           * If the packet is marked with the sensing flag, sgen is off running
1546 1546           * a request sense, and *that packet* is what needs to be restarted.
1547 1547           */
1548 1548          if (pkt->pkt_flags & FLAG_SENSING) {
1549 1549                  sgen_log(sg_state, SGEN_DIAG3,
1550 1550                      "sgen_restart: restarting REQUEST SENSE");
1551 1551                  pkt = sg_state->sgen_rqspkt;
1552 1552          }
1553 1553  
1554 1554          if (sgen_scsi_transport(pkt) != TRAN_ACCEPT) {
1555 1555                  bp->b_resid = bp->b_bcount;
1556 1556                  bioerror(bp, EIO);
1557 1557                  biodone(bp);
1558 1558          }
1559 1559  }
1560 1560  
1561 1561  /*
1562 1562   * sgen_callback()
1563 1563   *      Command completion processing
1564 1564   *
1565 1565   *      sgen's completion processing is very pessimistic-- it does not retry
1566 1566   *      failed commands; instead, it allows the user application to make
1567 1567   *      decisions about what has gone wrong.
1568 1568   */
1569 1569  static void
1570 1570  sgen_callback(struct scsi_pkt *pkt)
1571 1571  {
1572 1572          sgen_state_t *sg_state;
1573 1573          struct uscsi_cmd *ucmd;
1574 1574          struct buf *bp;
1575 1575          int action;
1576 1576  
1577 1577          sg_state = pkt->pkt_private;
1578 1578          /*
1579 1579           * bp should always be the command buffer regardless of whether
1580 1580           * this is a command completion or a request-sense completion.
1581 1581           * This is because there is no need to biodone() the sense buf
1582 1582           * when it completes-- we want to biodone() the actual command buffer!
1583 1583           */
1584 1584          bp = sg_state->sgen_cmdbuf;
1585 1585          if (pkt->pkt_flags & FLAG_SENSING) {
1586 1586                  ASSERT(pkt == sg_state->sgen_rqspkt);
1587 1587                  sgen_log(sg_state, SGEN_DIAG2,
1588 1588                      "in sgen_callback() (SENSE completion callback)");
1589 1589          } else {
1590 1590                  ASSERT(pkt == sg_state->sgen_cmdpkt);
1591 1591                  sgen_log(sg_state, SGEN_DIAG2,
1592 1592                      "in sgen_callback() (command completion callback)");
1593 1593          }
1594 1594          ucmd = (struct uscsi_cmd *)bp->b_private;
1595 1595  
1596 1596          sgen_log(sg_state, SGEN_DIAG3, "sgen_callback: reason=0x%x resid=%ld "
1597 1597              "state=0x%x", pkt->pkt_reason, pkt->pkt_resid, pkt->pkt_state);
1598 1598  
1599 1599          /* Transfer scsi_pkt information to uscsi */
1600 1600          (void) scsi_uscsi_pktfini(pkt, ucmd);
1601 1601  
1602 1602          if (pkt->pkt_reason != CMD_CMPLT) {
1603 1603                  /*
1604 1604                   * The command did not complete.
1605 1605                   */
1606 1606                  sgen_log(sg_state, SGEN_DIAG3,
1607 1607                      "sgen_callback: command did not complete");
1608 1608                  action = sgen_handle_incomplete(sg_state, pkt);
1609 1609          } else if (sg_state->sgen_arq_enabled &&
1610 1610              (pkt->pkt_state & STATE_ARQ_DONE)) {
1611 1611                  /*
1612 1612                   * The auto-rqsense happened, and the packet has a filled-in
1613 1613                   * scsi_arq_status structure, pointed to by pkt_scbp.
1614 1614                   */
1615 1615                  sgen_log(sg_state, SGEN_DIAG3,
1616 1616                      "sgen_callback: received auto-requested sense");
1617 1617                  action = sgen_handle_autosense(sg_state, pkt);
1618 1618                  ASSERT(action != FETCH_SENSE);
1619 1619          } else if (pkt->pkt_flags & FLAG_SENSING) {
1620 1620                  /*
1621 1621                   * sgen was running a REQUEST SENSE. Decode the sense data and
1622 1622                   * decide what to do next.
1623 1623                   *
1624 1624                   * Clear FLAG_SENSING on the original packet for completeness.
1625 1625                   */
1626 1626                  sgen_log(sg_state, SGEN_DIAG3, "sgen_callback: received sense");
1627 1627                  sg_state->sgen_cmdpkt->pkt_flags &= ~FLAG_SENSING;
1628 1628                  action = sgen_handle_sense(sg_state);
1629 1629                  ASSERT(action != FETCH_SENSE);
1630 1630          } else {
1631 1631                  /*
1632 1632                   * Command completed and we're not getting sense. Check for
1633 1633                   * errors and decide what to do next.
1634 1634                   */
1635 1635                  sgen_log(sg_state, SGEN_DIAG3,
1636 1636                      "sgen_callback: command appears complete");
1637 1637                  action = sgen_check_error(sg_state, bp);
1638 1638          }
1639 1639  
1640 1640          switch (action) {
1641 1641          case FETCH_SENSE:
1642 1642                  /*
1643 1643                   * If there is sense to fetch, break out to prevent biodone'ing
1644 1644                   * until the sense fetch is complete.
1645 1645                   */
1646 1646                  if (sgen_initiate_sense(sg_state,
1647 1647                      scsi_pkt_allocated_correctly(pkt) ?
1648 1648                      pkt->pkt_path_instance : 0) == 0)
1649 1649                          break;
1650 1650                  /*FALLTHROUGH*/
1651 1651          case COMMAND_DONE_ERROR:
1652 1652                  bp->b_resid = bp->b_bcount;
1653 1653                  bioerror(bp, EIO);
1654 1654                  /*FALLTHROUGH*/
1655 1655          case COMMAND_DONE:
1656 1656                  biodone(bp);
1657 1657                  break;
1658 1658          default:
1659 1659                  ASSERT(0);
1660 1660                  break;
1661 1661          }
1662 1662  
1663 1663          sgen_log(sg_state, SGEN_DIAG2, "done sgen_callback()");
1664 1664  }
1665 1665  
1666 1666  /*
1667 1667   * sgen_initiate_sense()
1668 1668   *      Send the sgen_rqspkt to the target, thereby requesting sense data.
1669 1669   */
1670 1670  static int
1671 1671  sgen_initiate_sense(sgen_state_t *sg_state, int path_instance)
1672 1672  {
1673 1673          /* use same path_instance as command */
1674 1674          if (scsi_pkt_allocated_correctly(sg_state->sgen_rqspkt))
1675 1675                  sg_state->sgen_rqspkt->pkt_path_instance = path_instance;
1676 1676  
1677 1677          switch (sgen_scsi_transport(sg_state->sgen_rqspkt)) {
1678 1678          case TRAN_ACCEPT:
1679 1679                  sgen_log(sg_state, SGEN_DIAG3, "sgen_initiate_sense: "
1680 1680                      "sense fetch transport accepted.");
1681 1681                  return (0);
1682 1682          case TRAN_BUSY:
1683 1683                  sgen_log(sg_state, SGEN_DIAG2, "sgen_initiate_sense: "
1684 1684                      "sense fetch transport busy, setting timeout.");
1685 1685                  sg_state->sgen_restart_timeid = timeout(sgen_restart, sg_state,
1686 1686                      SGEN_BSY_TIMEOUT);
1687 1687                  return (0);
1688 1688          default:
1689 1689                  sgen_log(sg_state, SGEN_DIAG2, "sgen_initiate_sense: "
1690 1690                      "sense fetch transport failed or busy.");
1691 1691                  return (-1);
1692 1692          }
1693 1693  }
1694 1694  
1695 1695  /*
1696 1696   * sgen_handle_incomplete()
1697 1697   *      sgen is pessimistic, but also careful-- it doesn't try to retry
1698 1698   *      incomplete commands, but it also doesn't go resetting devices;
1699 1699   *      it is hard to tell if the device will be tolerant of that sort
1700 1700   *      of prodding.
1701 1701   *
1702 1702   *      This routine has been left as a guide for the future--- the
1703 1703   *      current administration's hands-off policy may need modification.
1704 1704   */
1705 1705  /*ARGSUSED*/
1706 1706  static int
1707 1707  sgen_handle_incomplete(sgen_state_t *sg_state, struct scsi_pkt *pkt)
1708 1708  {
1709 1709          SGEN_DO_ERRSTATS(sg_state, sgen_incmp_err);
1710 1710          return (COMMAND_DONE_ERROR);
1711 1711  }
1712 1712  
1713 1713  /*
1714 1714   * sgen_handle_autosense()
1715 1715   *      Deal with SENSE data acquired automatically via the auto-request-sense
1716 1716   *      facility.
1717 1717   *
1718 1718   *      Sgen takes a pessimistic view of things-- it doesn't retry commands,
1719 1719   *      and unless the device recovered from the problem, this routine returns
1720 1720   *      COMMAND_DONE_ERROR.
1721 1721   */
1722 1722  static int
1723 1723  sgen_handle_autosense(sgen_state_t *sg_state, struct scsi_pkt *pkt)
1724 1724  {
1725 1725          struct scsi_arq_status *arqstat;
1726 1726          struct uscsi_cmd *ucmd =
1727 1727              (struct uscsi_cmd *)sg_state->sgen_cmdbuf->b_private;
1728 1728          int amt;
1729 1729  
1730 1730          arqstat = (struct scsi_arq_status *)(pkt->pkt_scbp);
1731 1731  
1732 1732          SGEN_DO_ERRSTATS(sg_state, sgen_autosen_rcv);
1733 1733  
1734 1734          if (arqstat->sts_rqpkt_reason != CMD_CMPLT) {
1735 1735                  sgen_log(sg_state, SGEN_DIAG1, "sgen_handle_autosense: ARQ"
1736 1736                      "failed to complete.");
1737 1737                  SGEN_DO_ERRSTATS(sg_state, sgen_autosen_bad);
1738 1738                  return (COMMAND_DONE_ERROR);
1739 1739          }
1740 1740  
1741 1741          if (pkt->pkt_state & STATE_XARQ_DONE) {
1742 1742                  amt = MAX_SENSE_LENGTH - arqstat->sts_rqpkt_resid;
1743 1743          } else {
1744 1744                  if (arqstat->sts_rqpkt_resid > SENSE_LENGTH) {
1745 1745                          amt = MAX_SENSE_LENGTH - arqstat->sts_rqpkt_resid;
1746 1746                  } else {
1747 1747                          amt = SENSE_LENGTH - arqstat->sts_rqpkt_resid;
1748 1748                  }
1749 1749          }
1750 1750  
1751 1751          if (ucmd->uscsi_flags & USCSI_RQENABLE) {
1752 1752                  ucmd->uscsi_rqstatus = *((char *)&arqstat->sts_rqpkt_status);
1753 1753                  uchar_t rqlen = min((uchar_t)amt, ucmd->uscsi_rqlen);
1754 1754                  ucmd->uscsi_rqresid = ucmd->uscsi_rqlen - rqlen;
1755 1755                  ASSERT(ucmd->uscsi_rqlen && sg_state->sgen_rqs_sen);
1756 1756                  bcopy(&(arqstat->sts_sensedata), sg_state->sgen_rqs_sen, rqlen);
1757 1757                  sgen_log(sg_state, SGEN_DIAG2, "sgen_handle_autosense: "
1758 1758                      "uscsi_rqstatus=0x%x uscsi_rqresid=%d\n",
1759 1759                      ucmd->uscsi_rqstatus, ucmd->uscsi_rqresid);
1760 1760          }
1761 1761  
1762 1762          if (arqstat->sts_rqpkt_status.sts_chk) {
1763 1763                  sgen_log(sg_state, SGEN_DIAG1, "sgen_handle_autosense: got "
1764 1764                      "check condition on auto request sense!");
1765 1765                  SGEN_DO_ERRSTATS(sg_state, sgen_autosen_bad);
1766 1766                  return (COMMAND_DONE_ERROR);
1767 1767          }
1768 1768  
1769 1769          if (((arqstat->sts_rqpkt_state & STATE_XFERRED_DATA) == 0) ||
1770 1770              (amt == 0)) {
1771 1771                  sgen_log(sg_state, SGEN_DIAG1, "sgen_handle_autosense: got "
1772 1772                      "auto-sense, but it contains no data!");
1773 1773                  SGEN_DO_ERRSTATS(sg_state, sgen_autosen_bad);
1774 1774                  return (COMMAND_DONE_ERROR);
1775 1775          }
1776 1776  
1777 1777          /*
1778 1778           * Stuff the sense data pointer into sgen_sense for later retrieval
1779 1779           */
1780 1780          sg_state->sgen_sense = &arqstat->sts_sensedata;
1781 1781  
1782 1782          /*
1783 1783           * Now, check to see whether we got enough sense data to make any
1784 1784           * sense out if it (heh-heh).
1785 1785           */
1786 1786          if (amt < SUN_MIN_SENSE_LENGTH) {
1787 1787                  sgen_log(sg_state, SGEN_DIAG1, "sgen_handle_autosense: not "
1788 1788                      "enough auto sense data");
1789 1789                  return (COMMAND_DONE_ERROR);
1790 1790          }
1791 1791  
1792 1792          switch (arqstat->sts_sensedata.es_key) {
1793 1793          case KEY_RECOVERABLE_ERROR:
1794 1794                  SGEN_DO_ERRSTATS(sg_state, sgen_recov_err);
1795 1795                  break;
1796 1796          case KEY_NO_SENSE:
1797 1797                  SGEN_DO_ERRSTATS(sg_state, sgen_nosen_err);
1798 1798                  break;
1799 1799          default:
1800 1800                  SGEN_DO_ERRSTATS(sg_state, sgen_unrecov_err);
1801 1801                  break;
1802 1802          }
1803 1803  
1804 1804          return (COMMAND_DONE);
1805 1805  }
1806 1806  
1807 1807  /*
1808 1808   * sgen_handle_sense()
1809 1809   *      Examine sense data that was manually fetched from the target.
1810 1810   */
1811 1811  static int
1812 1812  sgen_handle_sense(sgen_state_t *sg_state)
1813 1813  {
1814 1814          struct scsi_pkt *rqpkt = sg_state->sgen_rqspkt;
1815 1815          struct scsi_status *rqstatus = (struct scsi_status *)rqpkt->pkt_scbp;
1816 1816          struct uscsi_cmd *ucmd =
1817 1817              (struct uscsi_cmd *)sg_state->sgen_cmdbuf->b_private;
1818 1818          int amt;
1819 1819  
1820 1820          SGEN_DO_ERRSTATS(sg_state, sgen_sense_rcv);
1821 1821  
1822 1822          amt = MAX_SENSE_LENGTH - rqpkt->pkt_resid;
1823 1823  
1824 1824          if (ucmd->uscsi_flags & USCSI_RQENABLE) {
1825 1825                  ucmd->uscsi_rqstatus = *((char *)rqstatus);
1826 1826                  uchar_t rqlen = min((uchar_t)amt, ucmd->uscsi_rqlen);
1827 1827                  ucmd->uscsi_rqresid = ucmd->uscsi_rqlen - rqlen;
1828 1828                  ASSERT(ucmd->uscsi_rqlen && sg_state->sgen_rqs_sen);
1829 1829                  bcopy(sg_state->sgen_sense, sg_state->sgen_rqs_sen, rqlen);
1830 1830                  sgen_log(sg_state, SGEN_DIAG2, "sgen_handle_sense: "
1831 1831                      "uscsi_rqstatus=0x%x uscsi_rqresid=%d\n",
1832 1832                      ucmd->uscsi_rqstatus, ucmd->uscsi_rqresid);
1833 1833          }
1834 1834  
1835 1835          if (rqstatus->sts_busy) {
1836 1836                  sgen_log(sg_state, SGEN_DIAG1, "sgen_handle_sense: got busy "
1837 1837                      "on request sense");
1838 1838                  SGEN_DO_ERRSTATS(sg_state, sgen_sense_bad);
1839 1839                  return (COMMAND_DONE_ERROR);
1840 1840          }
1841 1841  
1842 1842          if (rqstatus->sts_chk) {
1843 1843                  sgen_log(sg_state, SGEN_DIAG1, "sgen_handle_sense: got check "
1844 1844                      "condition on request sense!");
1845 1845                  SGEN_DO_ERRSTATS(sg_state, sgen_sense_bad);
1846 1846                  return (COMMAND_DONE_ERROR);
1847 1847          }
1848 1848  
1849 1849          if ((rqpkt->pkt_state & STATE_XFERRED_DATA) == 0 || amt == 0) {
1850 1850                  sgen_log(sg_state, SGEN_DIAG1, "sgen_handle_sense: got "
1851 1851                      "sense, but it contains no data");
1852 1852                  SGEN_DO_ERRSTATS(sg_state, sgen_sense_bad);
1853 1853                  return (COMMAND_DONE_ERROR);
1854 1854          }
1855 1855  
1856 1856          /*
1857 1857           * Now, check to see whether we got enough sense data to make any
1858 1858           * sense out if it (heh-heh).
1859 1859           */
1860 1860          if (amt < SUN_MIN_SENSE_LENGTH) {
1861 1861                  sgen_log(sg_state, SGEN_DIAG1, "sgen_handle_sense: not "
1862 1862                      "enough sense data");
1863 1863                  SGEN_DO_ERRSTATS(sg_state, sgen_sense_bad);
1864 1864                  return (COMMAND_DONE_ERROR);
1865 1865          }
1866 1866  
1867 1867          /*
1868 1868           * Decode the sense data-- this was deposited here for us by the
1869 1869           * setup in sgen_do_attach(). (note that sgen_sense is an alias for
1870 1870           * the sd_sense field in the scsi_device).
1871 1871           */
1872 1872          sgen_log(sg_state, SGEN_DIAG1, "Sense key is %s [0x%x]",
1873 1873              scsi_sname(sg_state->sgen_sense->es_key),
1874 1874              sg_state->sgen_sense->es_key);
1875 1875          switch (sg_state->sgen_sense->es_key) {
1876 1876          case KEY_RECOVERABLE_ERROR:
1877 1877                  SGEN_DO_ERRSTATS(sg_state, sgen_recov_err);
1878 1878                  break;
1879 1879          case KEY_NO_SENSE:
1880 1880                  SGEN_DO_ERRSTATS(sg_state, sgen_nosen_err);
1881 1881                  break;
1882 1882          default:
1883 1883                  SGEN_DO_ERRSTATS(sg_state, sgen_unrecov_err);
1884 1884                  break;
1885 1885          }
1886 1886  
1887 1887          return (COMMAND_DONE);
1888 1888  }
1889 1889  
1890 1890  /*
1891 1891   * sgen_check_error()
1892 1892   *      examine the command packet for abnormal completion.
1893 1893   *
1894 1894   *      sgen_check_error should only be called at the completion of the
1895 1895   *      command packet.
1896 1896   */
1897 1897  static int
1898 1898  sgen_check_error(sgen_state_t *sg_state, struct buf *bp)
1899 1899  {
1900 1900          struct scsi_pkt *pkt = sg_state->sgen_cmdpkt;
1901 1901          struct scsi_status *status = (struct scsi_status *)pkt->pkt_scbp;
1902 1902          struct uscsi_cmd *ucmd =
1903 1903              (struct uscsi_cmd *)sg_state->sgen_cmdbuf->b_private;
1904 1904  
1905 1905          if (status->sts_busy) {
1906 1906                  sgen_log(sg_state, SGEN_DIAG1,
1907 1907                      "sgen_check_error: target is busy");
1908 1908                  return (COMMAND_DONE_ERROR);
1909 1909          }
1910 1910  
1911 1911          /*
1912 1912           * pkt_resid will reflect, at this point, a residual of how many bytes
1913 1913           * were not transferred; a non-zero pkt_resid is an error.
1914 1914           */
1915 1915          if (pkt->pkt_resid) {
1916 1916                  bp->b_resid += pkt->pkt_resid;
1917 1917          }
1918 1918  
1919 1919          if (status->sts_chk) {
1920 1920                  if (ucmd->uscsi_flags & USCSI_RQENABLE) {
1921 1921                          if (sg_state->sgen_arq_enabled) {
1922 1922                                  sgen_log(sg_state, SGEN_DIAG1,
1923 1923                                      "sgen_check_error: strange: target "
1924 1924                                      "indicates CHECK CONDITION with auto-sense "
1925 1925                                      "enabled.");
1926 1926                          }
1927 1927                          sgen_log(sg_state, SGEN_DIAG2, "sgen_check_error: "
1928 1928                              "target ready for sense fetch");
1929 1929                          return (FETCH_SENSE);
1930 1930                  } else {
1931 1931                          sgen_log(sg_state, SGEN_DIAG2, "sgen_check_error: "
1932 1932                              "target indicates CHECK CONDITION");
1933 1933                  }
1934 1934          }
1935 1935  
1936 1936          return (COMMAND_DONE);
1937 1937  }
1938 1938  
1939 1939  /*
1940 1940   * sgen_tur()
1941 1941   *      test if a target is ready to operate by sending it a TUR command.
1942 1942   */
1943 1943  static int
1944 1944  sgen_tur(dev_t dev)
1945 1945  {
1946 1946          char cmdblk[CDB_GROUP0];
1947 1947          struct uscsi_cmd scmd;
1948 1948  
1949 1949          bzero(&scmd, sizeof (scmd));
1950 1950          scmd.uscsi_bufaddr = 0;
1951 1951          scmd.uscsi_buflen = 0;
1952 1952          bzero(cmdblk, CDB_GROUP0);
1953 1953          cmdblk[0] = (char)SCMD_TEST_UNIT_READY;
1954 1954          scmd.uscsi_flags = USCSI_DIAGNOSE | USCSI_SILENT | USCSI_WRITE;
1955 1955          scmd.uscsi_cdb = cmdblk;
1956 1956          scmd.uscsi_cdblen = CDB_GROUP0;
1957 1957  
1958 1958          return (sgen_uscsi_cmd(dev, &scmd, FKIOCTL));
1959 1959  }
1960 1960  
1961 1961  /*
1962 1962   * sgen_diag_ok()
1963 1963   *      given an sg_state and a desired diagnostic level, return true if
1964 1964   *      it is acceptable to output a message.
1965 1965   */
1966 1966  /*ARGSUSED*/
1967 1967  static int
1968 1968  sgen_diag_ok(sgen_state_t *sg_state, int level)
1969 1969  {
1970 1970          int diag_lvl;
1971 1971  
1972 1972          switch (level) {
1973 1973          case CE_WARN:
1974 1974          case CE_NOTE:
1975 1975          case CE_CONT:
1976 1976          case CE_PANIC:
1977 1977                  return (1);
1978 1978          case SGEN_DIAG1:
1979 1979          case SGEN_DIAG2:
1980 1980          case SGEN_DIAG3:
1981 1981                  if (sg_state) {
1982 1982                          /*
1983 1983                           * Check to see if user overrode the diagnostics level
1984 1984                           * for this instance (either via SGEN_IOC_DIAG or via
1985 1985                           * .conf file).  If not, fall back to the global diag
1986 1986                           * level.
1987 1987                           */
1988 1988                          if (sg_state->sgen_diag != -1)
1989 1989                                  diag_lvl = sg_state->sgen_diag;
1990 1990                          else
1991 1991                                  diag_lvl = sgen_diag;
1992 1992                  } else {
1993 1993                          diag_lvl = sgen_diag;
1994 1994                  }
1995 1995                  if (((diag_lvl << 8) | CE_CONT) >= level) {
1996 1996                          return (1);
1997 1997                  } else {
1998 1998                          return (0);
1999 1999                  }
2000 2000          default:
2001 2001                  return (1);
2002 2002          }
2003 2003  }
2004 2004  
2005 2005  /*PRINTFLIKE3*/
2006 2006  static void
2007 2007  sgen_log(sgen_state_t *sg_state, int level, const char *fmt, ...)
2008 2008  {
2009 2009          va_list ap;
2010 2010          char buf[256];
2011 2011  
2012 2012          if (!sgen_diag_ok(sg_state, level))
2013 2013                  return;
2014 2014  
2015 2015          va_start(ap, fmt);
2016 2016          (void) vsnprintf(buf, sizeof (buf), fmt, ap);
2017 2017          va_end(ap);
2018 2018  
2019 2019          switch (level) {
2020 2020          case CE_NOTE:
2021 2021          case CE_CONT:
2022 2022          case CE_WARN:
2023 2023          case CE_PANIC:
2024 2024                  if (sg_state == (sgen_state_t *)NULL) {
2025 2025                          cmn_err(level, "%s", buf);
2026 2026                  } else {
2027 2027                          scsi_log(sg_state->sgen_devinfo, sgen_label, level,
2028 2028                              "%s", buf);
2029 2029                  }
2030 2030                  break;
2031 2031          case SGEN_DIAG1:
2032 2032          case SGEN_DIAG2:
2033 2033          case SGEN_DIAG3:
2034 2034          default:
2035 2035                  if (sg_state == (sgen_state_t *)NULL) {
2036 2036                          scsi_log(NULL, sgen_label, CE_CONT, "%s", buf);
2037 2037                  } else {
2038 2038                          scsi_log(sg_state->sgen_devinfo, sgen_label, CE_CONT,
2039 2039                              "%s", buf);
2040 2040                  }
2041 2041          }
2042 2042  }
2043 2043  
2044 2044  /*
2045 2045   * sgen_dump_cdb()
2046 2046   *      dump out the contents of a cdb.  Take care that 'label' is not too
2047 2047   *      large, or 'buf' could overflow.
2048 2048   */
2049 2049  static void
2050 2050  sgen_dump_cdb(sgen_state_t *sg_state, const char *label,
2051 2051      union scsi_cdb *cdb, int cdblen)
2052 2052  {
2053 2053          static char hex[] = "0123456789abcdef";
2054 2054          char *buf, *p;
2055 2055          size_t nbytes;
2056 2056          int i;
2057 2057          uchar_t *cdbp = (uchar_t *)cdb;
2058 2058  
2059 2059          /*
2060 2060           * fastpath-- if we're not able to print out, don't do all of this
2061 2061           * extra work.
2062 2062           */
2063 2063          if (!sgen_diag_ok(sg_state, SGEN_DIAG3))
2064 2064                  return;
2065 2065  
2066 2066          /*
2067 2067           * 3 characters for each byte (because of the ' '), plus the size of
2068 2068           * the label, plus the trailing ']' and the null character.
2069 2069           */
2070 2070          nbytes = 3 * cdblen + strlen(label) + strlen(" CDB = [") + 2;
2071 2071          buf = kmem_alloc(nbytes, KM_SLEEP);
2072 2072          (void) sprintf(buf, "%s CDB = [", label);
2073 2073          p = &buf[strlen(buf)];
2074 2074          for (i = 0; i < cdblen; i++, cdbp++) {
2075 2075                  if (i > 0)
2076 2076                          *p++ = ' ';
2077 2077                  *p++ = hex[(*cdbp >> 4) & 0x0f];
2078 2078                  *p++ = hex[*cdbp & 0x0f];
2079 2079          }
2080 2080          *p++ = ']';
2081 2081          *p = 0;
2082 2082          sgen_log(sg_state, SGEN_DIAG3, buf);
2083 2083          kmem_free(buf, nbytes);
2084 2084  }
2085 2085  
2086 2086  static void
2087 2087  sgen_dump_sense(sgen_state_t *sg_state, size_t rqlen, uchar_t *rqbuf)
2088 2088  {
2089 2089          static char hex[] = "0123456789abcdef";
2090 2090          char *buf, *p;
2091 2091          size_t nbytes;
2092 2092          int i;
2093 2093  
2094 2094          /*
2095 2095           * fastpath-- if we're not able to print out, don't do all of this
2096 2096           * extra work.
2097 2097           */
2098 2098          if (!sgen_diag_ok(sg_state, SGEN_DIAG3))
2099 2099                  return;
2100 2100  
2101 2101          /*
2102 2102           * 3 characters for each byte (because of the ' '), plus the size of
2103 2103           * the label, plus the trailing ']' and the null character.
2104 2104           */
2105 2105          nbytes = 3 * rqlen + strlen(" SENSE = [") + 2;
2106 2106          buf = kmem_alloc(nbytes, KM_SLEEP);
2107 2107          (void) sprintf(buf, "SENSE = [");
2108 2108          p = &buf[strlen(buf)];
2109 2109          for (i = 0; i < rqlen; i++, rqbuf++) {
2110 2110                  if (i > 0)
2111 2111                          *p++ = ' ';
2112 2112                  *p++ = hex[(*rqbuf >> 4) & 0x0f];
2113 2113                  *p++ = hex[*rqbuf & 0x0f];
2114 2114          }
2115 2115          *p++ = ']';
2116 2116          *p = 0;
2117 2117          sgen_log(sg_state, SGEN_DIAG3, buf);
2118 2118          kmem_free(buf, nbytes);
2119 2119  }
  
    | ↓ open down ↓ | 1905 lines elided | ↑ open up ↑ | 
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX