1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Enclosure Services Device target driver
  23  *
  24  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  25  * Use is subject to license terms.
  26  * Copyright (c) 2011 Bayard G. Bell. All rights reserved.
  27  * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
  28  */
  29 
  30 #include <sys/modctl.h>
  31 #include <sys/file.h>
  32 #include <sys/scsi/scsi.h>
  33 #include <sys/scsi/generic/status.h>
  34 #include <sys/scsi/targets/sesio.h>
  35 #include <sys/scsi/targets/ses.h>
  36 
  37 
  38 
  39 /*
  40  * Power management defines (should be in a common include file?)
  41  */
  42 #define PM_HARDWARE_STATE_PROP          "pm-hardware-state"
  43 #define PM_NEEDS_SUSPEND_RESUME         "needs-suspend-resume"
  44 
  45 
  46 /*
  47  * Global Driver Data
  48  */
  49 int ses_io_time = SES_IO_TIME;
  50 
  51 static int ses_retry_count = SES_RETRY_COUNT * SES_RETRY_MULTIPLIER;
  52 
  53 #ifdef  DEBUG
  54 int ses_debug = 0;
  55 #else   /* DEBUG */
  56 #define ses_debug       0
  57 #endif  /* DEBUG */
  58 
  59 
  60 /*
  61  * External Enclosure Functions
  62  */
  63 extern int ses_softc_init(ses_softc_t *, int);
  64 extern int ses_init_enc(ses_softc_t *);
  65 extern int ses_get_encstat(ses_softc_t *, int);
  66 extern int ses_set_encstat(ses_softc_t *, uchar_t, int);
  67 extern int ses_get_objstat(ses_softc_t *, ses_objarg *, int);
  68 extern int ses_set_objstat(ses_softc_t *, ses_objarg *, int);
  69 
  70 extern int safte_softc_init(ses_softc_t *, int);
  71 extern int safte_init_enc(ses_softc_t *);
  72 extern int safte_get_encstat(ses_softc_t *, int);
  73 extern int safte_set_encstat(ses_softc_t *, uchar_t, int);
  74 extern int safte_get_objstat(ses_softc_t *, ses_objarg *, int);
  75 extern int safte_set_objstat(ses_softc_t *, ses_objarg *, int);
  76 
  77 extern int sen_softc_init(ses_softc_t *, int);
  78 extern int sen_init_enc(ses_softc_t *);
  79 extern int sen_get_encstat(ses_softc_t *, int);
  80 extern int sen_set_encstat(ses_softc_t *, uchar_t, int);
  81 extern int sen_get_objstat(ses_softc_t *, ses_objarg *, int);
  82 extern int sen_set_objstat(ses_softc_t *, ses_objarg *, int);
  83 
  84 /*
  85  * Local Function prototypes
  86  */
  87 static int ses_info(dev_info_t *, ddi_info_cmd_t, void *, void **);
  88 static int ses_probe(dev_info_t *);
  89 static int ses_attach(dev_info_t *, ddi_attach_cmd_t);
  90 static int ses_detach(dev_info_t *, ddi_detach_cmd_t);
  91 
  92 static int is_enc_dev(ses_softc_t *, struct scsi_inquiry *, int, enctyp *);
  93 static int ses_doattach(dev_info_t *dip);
  94 
  95 static int  ses_open(dev_t *, int, int, cred_t *);
  96 static int  ses_close(dev_t, int, int, cred_t *);
  97 static int  ses_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
  98 
  99 static encvec vecs[3] = {
 100 {
 101         ses_softc_init, ses_init_enc, ses_get_encstat,
 102         ses_set_encstat, ses_get_objstat, ses_set_objstat
 103 },
 104 {
 105         safte_softc_init, safte_init_enc, safte_get_encstat,
 106         safte_set_encstat, safte_get_objstat, safte_set_objstat,
 107 },
 108 {
 109         sen_softc_init, sen_init_enc, sen_get_encstat,
 110         sen_set_encstat, sen_get_objstat, sen_set_objstat
 111 }
 112 };
 113 
 114 
 115 /*
 116  * Local Functions
 117  */
 118 static int ses_start(struct buf *bp);
 119 static int ses_decode_sense(struct scsi_pkt *pkt, int *err);
 120 
 121 static void ses_get_pkt(struct buf *bp, int (*func)(opaque_t));
 122 static void ses_callback(struct scsi_pkt *pkt);
 123 static void ses_restart(void *arg);
 124 
 125 
 126 /*
 127  * Local Static Data
 128  */
 129 #ifndef D_HOTPLUG
 130 #define D_HOTPLUG       0
 131 #endif /* D_HOTPLUG */
 132 
 133 static struct cb_ops ses_cb_ops = {
 134         ses_open,                       /* open */
 135         ses_close,                      /* close */
 136         nodev,                          /* strategy */
 137         nodev,                          /* print */
 138         nodev,                          /* dump */
 139         nodev,                          /* read */
 140         nodev,                          /* write */
 141         ses_ioctl,                      /* ioctl */
 142         nodev,                          /* devmap */
 143         nodev,                          /* mmap */
 144         nodev,                          /* segmap */
 145         nochpoll,                       /* poll */
 146         ddi_prop_op,                    /* cb_prop_op */
 147         0,                              /* streamtab  */
 148 #if     !defined(CB_REV)
 149         D_MP | D_NEW | D_HOTPLUG        /* Driver compatibility flag */
 150 #else   /* !defined(CB_REV) */
 151         D_MP | D_NEW | D_HOTPLUG,       /* Driver compatibility flag */
 152         CB_REV,                         /* cb_ops version number */
 153         nodev,                          /* aread */
 154         nodev                           /* awrite */
 155 #endif  /* !defined(CB_REV) */
 156 };
 157 
 158 static struct dev_ops ses_dev_ops = {
 159         DEVO_REV,               /* devo_rev, */
 160         0,                      /* refcnt  */
 161         ses_info,               /* info */
 162         nulldev,                /* identify */
 163         ses_probe,              /* probe */
 164         ses_attach,             /* attach */
 165         ses_detach,             /* detach */
 166         nodev,                  /* reset */
 167         &ses_cb_ops,                /* driver operations */
 168         (struct bus_ops *)NULL, /* bus operations */
 169         NULL,                   /* power */
 170         ddi_quiesce_not_needed,         /* quiesce */
 171 };
 172 
 173 static void *estate  = NULL;
 174 static const char *Snm = "ses";
 175 static const char *Str = "%s\n";
 176 static const char *efl = "copyin/copyout EFAULT @ line %d";
 177 static const char *fail_msg = "%stransport failed: reason '%s': %s";
 178 
 179 
 180 
 181 /*
 182  * autoconfiguration routines.
 183  */
 184 
 185 static struct modldrv modldrv = {
 186         &mod_driverops,
 187         "SCSI Enclosure Services",
 188         &ses_dev_ops
 189 };
 190 
 191 static struct modlinkage modlinkage = {
 192         MODREV_1, { &modldrv, NULL }
 193 };
 194 
 195 
 196 int
 197 _init(void)
 198 {
 199         int status;
 200         status = ddi_soft_state_init(&estate, sizeof (ses_softc_t), 0);
 201         if (status == 0) {
 202                 if ((status = mod_install(&modlinkage)) != 0) {
 203                         ddi_soft_state_fini(&estate);
 204                 }
 205         }
 206         return (status);
 207 }
 208 
 209 int
 210 _fini(void)
 211 {
 212         int status;
 213         if ((status = mod_remove(&modlinkage)) != 0) {
 214                 return (status);
 215         }
 216         ddi_soft_state_fini(&estate);
 217         return (status);
 218 }
 219 
 220 int
 221 _info(struct modinfo *modinfop)
 222 {
 223         return (mod_info(&modlinkage, modinfop));
 224 }
 225 
 226 static int
 227 ses_probe(dev_info_t *dip)
 228 {
 229         int                     err;
 230         struct scsi_device      *devp;
 231         enctyp                  ep;
 232 
 233         /*
 234          * I finally figured out why we return success
 235          * on every probe. The devices that we attach to
 236          * don't all report as being the same "device type"
 237          *
 238          * 1) A5x00 -- report as Enclosure Services (0xD) SES
 239          * 2) A1000 -- report as Direct Access (0x0) SES
 240          *    uses the same target as raid controler.
 241          * 3) D1000 -- report as processor (0x3) SAFTE
 242          * 3) D240  -- report as processor (0x3) SAFTE
 243          *
 244          * We also reportedly attach to SEN devices which I
 245          * believe reside in a Tobasco tray.  I have never
 246          * been able to get one to attach.
 247          *
 248          */
 249         if (dip == NULL)
 250                 return (DDI_PROBE_FAILURE);
 251         /* SES_LOG(NULL, SES_CE_DEBUG1, "ses_probe: OK"); */
 252         if (ddi_dev_is_sid(dip) == DDI_SUCCESS) {
 253                 return (DDI_PROBE_DONTCARE);
 254         }
 255 
 256         devp = ddi_get_driver_private(dip);
 257 
 258         /* Legacy: prevent driver.conf specified ses nodes on atapi. */
 259         if (scsi_ifgetcap(&devp->sd_address, "interconnect-type", -1) ==
 260             INTERCONNECT_ATAPI)
 261                 return (DDI_PROBE_FAILURE);
 262 
 263         /*
 264          * XXX: Breakage from the x86 folks.
 265          */
 266         if (strcmp(ddi_get_name(ddi_get_parent(dip)), "ata") == 0) {
 267                 return (DDI_PROBE_FAILURE);
 268         }
 269 
 270         switch (err = scsi_probe(devp, SLEEP_FUNC)) {
 271         case SCSIPROBE_EXISTS:
 272                 if (is_enc_dev(NULL, devp->sd_inq, SUN_INQSIZE, &ep)) {
 273                         break;
 274                 }
 275                 /* FALLTHROUGH */
 276         case SCSIPROBE_NORESP:
 277                 scsi_unprobe(devp);
 278                 return (DDI_PROBE_FAILURE);
 279         default:
 280                 SES_LOG(NULL, SES_CE_DEBUG9,
 281                     "ses_probe: probe error %d", err);
 282                 scsi_unprobe(devp);
 283                 return (DDI_PROBE_FAILURE);
 284         }
 285         scsi_unprobe(devp);
 286         return (DDI_PROBE_SUCCESS);
 287 }
 288 
 289 static int
 290 ses_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
 291 {
 292         int inst, err;
 293         ses_softc_t *ssc;
 294 
 295         inst = ddi_get_instance(dip);
 296         switch (cmd) {
 297         case DDI_ATTACH:
 298                 SES_LOG(NULL, SES_CE_DEBUG9, "ses_attach: DDI_ATTACH ses%d",
 299                     inst);
 300 
 301                 err = ses_doattach(dip);
 302 
 303                 if (err == DDI_FAILURE) {
 304                         return (DDI_FAILURE);
 305                 }
 306                 SES_LOG(NULL, SES_CE_DEBUG4,
 307                     "ses_attach: DDI_ATTACH OK ses%d", inst);
 308                 break;
 309 
 310         case DDI_RESUME:
 311                 if ((ssc = ddi_get_soft_state(estate, inst)) == NULL) {
 312                         return (DDI_FAILURE);
 313                 }
 314                 SES_LOG(ssc, SES_CE_DEBUG1, "ses_attach: DDI_ATTACH ses%d",
 315                     inst);
 316                 ssc->ses_suspended = 0;
 317                 break;
 318 
 319         default:
 320                 return (DDI_FAILURE);
 321         }
 322         return (DDI_SUCCESS);
 323 }
 324 
 325 static int
 326 is_enc_dev(ses_softc_t *ssc, struct scsi_inquiry *inqp, int iqlen, enctyp *ep)
 327 {
 328         uchar_t dt = (inqp->inq_dtype & DTYPE_MASK);
 329         uchar_t *iqd = (uchar_t *)inqp;
 330 
 331         if (dt == DTYPE_ESI) {
 332                 if (strncmp(inqp->inq_vid, SEN_ID, SEN_ID_LEN) == 0) {
 333                         SES_LOG(ssc, SES_CE_DEBUG3, "SEN device found");
 334                         *ep = SEN_TYPE;
 335                 } else if (inqp->inq_rdf == RDF_SCSI2) {
 336                         /*
 337                          * Per SPC4 #6.4.2 Standard Inquiry Data, response
 338                          * data format (RDF) values of 0 and 1 are Obsolete,
 339                          * whereas values greater than 2 are Reserved
 340                          */
 341                         SES_LOG(ssc, SES_CE_DEBUG3, "SES device found");
 342                         *ep = SES_TYPE;
 343                 } else {
 344                         SES_LOG(ssc, SES_CE_DEBUG3, "Pre-SCSI3 SES device");
 345                         *ep = SES_TYPE;
 346                 }
 347                 return (1);
 348         }
 349         if ((iqd[6] & 0x40) && inqp->inq_rdf >= RDF_SCSI2) {
 350                 /*
 351                  * PassThrough Device.
 352                  */
 353                 *ep = SES_TYPE;
 354                 SES_LOG(ssc, SES_CE_DEBUG3, "Passthru SES device");
 355                 return (1);
 356         }
 357 
 358         if (iqlen < 47) {
 359                 SES_LOG(ssc, CE_NOTE,
 360                     "INQUIRY data too short to determine SAF-TE");
 361                 return (0);
 362         }
 363         if (strncmp((char *)&iqd[44], "SAF-TE", 4) == 0) {
 364                 *ep = SAFT_TYPE;
 365                 SES_LOG(ssc, SES_CE_DEBUG3, "SAF-TE device found");
 366                 return (1);
 367         }
 368         return (0);
 369 }
 370 
 371 
 372 /*
 373  * Attach ses device.
 374  *
 375  * XXX:  Power management is NOT supported.  A token framework
 376  *       is provided that will need to be extended assuming we have
 377  *       ses devices we can power down.  Currently, we don't have any.
 378  */
 379 static int
 380 ses_doattach(dev_info_t *dip)
 381 {
 382         int inst, err;
 383         Scsidevp devp;
 384         ses_softc_t *ssc;
 385         enctyp etyp;
 386 
 387         inst = ddi_get_instance(dip);
 388         /*
 389          * Workaround for bug #4154979- for some reason we can
 390          * be called with identical instance numbers but for
 391          * different dev_info_t-s- all but one are bogus.
 392          *
 393          * Bad Dog! No Biscuit!
 394          *
 395          * A quick workaround might be to call ddi_soft_state_zalloc
 396          * unconditionally, as the implementation fails these calls
 397          * if there's an item already allocated. A more reasonable
 398          * and longer term change is to move the allocation past
 399          * the probe for the device's existence as most of these
 400          * 'bogus' calls are for nonexistent devices.
 401          */
 402 
 403         devp  = ddi_get_driver_private(dip);
 404         devp->sd_dev = dip;
 405 
 406         /*
 407          * Determine whether the { i, t, l } we're called
 408          * to start is an enclosure services device.
 409          */
 410 
 411         /*
 412          * Call the scsi_probe routine to see whether
 413          * we actually have an Enclosure Services device at
 414          * this address.
 415          */
 416         err = scsi_probe(devp, SLEEP_FUNC);
 417         if (err != SCSIPROBE_EXISTS) {
 418                 SES_LOG(NULL, SES_CE_DEBUG9,
 419                     "ses_doattach: probe error %d", err);
 420                 scsi_unprobe(devp);
 421                 return (DDI_FAILURE);
 422         }
 423         /* Call is_enc_dev() to get the etyp */
 424         if (!(is_enc_dev(NULL, devp->sd_inq, SUN_INQSIZE, &etyp))) {
 425                 SES_LOG(NULL, CE_WARN,
 426                     "ses_doattach: ses%d: is_enc_dev failure", inst);
 427                 scsi_unprobe(devp);
 428                 return (DDI_FAILURE);
 429         }
 430 
 431         if (ddi_soft_state_zalloc(estate, inst) != DDI_SUCCESS) {
 432                 scsi_unprobe(devp);
 433                 SES_LOG(NULL, CE_NOTE, "ses%d: softalloc fails", inst);
 434                 return (DDI_FAILURE);
 435         }
 436         ssc = ddi_get_soft_state(estate, inst);
 437         if (ssc == NULL) {
 438                 scsi_unprobe(devp);
 439                 SES_LOG(NULL, CE_NOTE, "ses%d: get_soft_state fails", inst);
 440                 return (DDI_FAILURE);
 441         }
 442         devp->sd_private = (opaque_t)ssc;
 443         ssc->ses_devp = devp;
 444         err = ddi_create_minor_node(dip, "0", S_IFCHR, inst,
 445             DDI_NT_SCSI_ENCLOSURE, NULL);
 446         if (err == DDI_FAILURE) {
 447                 ddi_remove_minor_node(dip, NULL);
 448                 SES_LOG(ssc, CE_NOTE, "minor node creation failed");
 449                 ddi_soft_state_free(estate, inst);
 450                 scsi_unprobe(devp);
 451                 return (DDI_FAILURE);
 452         }
 453 
 454         ssc->ses_type = etyp;
 455         ssc->ses_vec = vecs[etyp];
 456 
 457         /* Call SoftC Init Routine A bit later... */
 458 
 459         ssc->ses_rqbp = scsi_alloc_consistent_buf(SES_ROUTE(ssc),
 460             NULL, MAX_SENSE_LENGTH, B_READ, SLEEP_FUNC, NULL);
 461         if (ssc->ses_rqbp != NULL) {
 462                 ssc->ses_rqpkt = scsi_init_pkt(SES_ROUTE(ssc), NULL,
 463                     ssc->ses_rqbp, CDB_GROUP0, 1, 0, PKT_CONSISTENT,
 464                     SLEEP_FUNC, NULL);
 465         }
 466         if (ssc->ses_rqbp == NULL || ssc->ses_rqpkt == NULL) {
 467                 ddi_remove_minor_node(dip, NULL);
 468                 SES_LOG(ssc, CE_NOTE, "scsi_init_pkt of rqbuf failed");
 469                 if (ssc->ses_rqbp != NULL) {
 470                         scsi_free_consistent_buf(ssc->ses_rqbp);
 471                         ssc->ses_rqbp = NULL;
 472                 }
 473                 ddi_soft_state_free(estate, inst);
 474                 scsi_unprobe(devp);
 475                 return (DDI_FAILURE);
 476         }
 477         ssc->ses_rqpkt->pkt_private = (opaque_t)ssc;
 478         ssc->ses_rqpkt->pkt_address = *(SES_ROUTE(ssc));
 479         ssc->ses_rqpkt->pkt_comp = ses_callback;
 480         ssc->ses_rqpkt->pkt_time = ses_io_time;
 481         ssc->ses_rqpkt->pkt_flags = FLAG_NOPARITY|FLAG_NODISCON|FLAG_SENSING;
 482         ssc->ses_rqpkt->pkt_cdbp[0] = SCMD_REQUEST_SENSE;
 483         ssc->ses_rqpkt->pkt_cdbp[1] = 0;
 484         ssc->ses_rqpkt->pkt_cdbp[2] = 0;
 485         ssc->ses_rqpkt->pkt_cdbp[3] = 0;
 486         ssc->ses_rqpkt->pkt_cdbp[4] = MAX_SENSE_LENGTH;
 487         ssc->ses_rqpkt->pkt_cdbp[5] = 0;
 488 
 489         switch (scsi_ifgetcap(SES_ROUTE(ssc), "auto-rqsense", 1)) {
 490         case 1:
 491                 /* if already set, don't reset it */
 492                 ssc->ses_arq = 1;
 493                 break;
 494         case 0:
 495                 /* try and set it */
 496                 ssc->ses_arq = ((scsi_ifsetcap(SES_ROUTE(ssc),
 497                     "auto-rqsense", 1, 1) == 1) ? 1 : 0);
 498                 break;
 499         default:
 500                 /* probably undefined, so zero it out */
 501                 ssc->ses_arq = 0;
 502                 break;
 503         }
 504 
 505         ssc->ses_sbufp = getrbuf(KM_SLEEP);
 506         cv_init(&ssc->ses_sbufcv, NULL, CV_DRIVER, NULL);
 507 
 508         /*
 509          * If the HBA supports wide, tell it to use wide.
 510          */
 511         if (scsi_ifgetcap(SES_ROUTE(ssc), "wide-xfer", 1) != -1) {
 512                 int wd = ((devp->sd_inq->inq_rdf == RDF_SCSI2) &&
 513                     (devp->sd_inq->inq_wbus16 || devp->sd_inq->inq_wbus32))
 514                     ? 1 : 0;
 515                 (void) scsi_ifsetcap(SES_ROUTE(ssc), "wide-xfer", wd, 1);
 516         }
 517 
 518         /*
 519          * Now do ssc init of enclosure specifics.
 520          * At the same time, check to make sure getrbuf
 521          * actually succeeded.
 522          */
 523         if ((*ssc->ses_vec.softc_init)(ssc, 1)) {
 524                 SES_LOG(ssc, SES_CE_DEBUG3, "failed softc init");
 525                 (void) (*ssc->ses_vec.softc_init)(ssc, 0);
 526                 ddi_remove_minor_node(dip, NULL);
 527                 scsi_destroy_pkt(ssc->ses_rqpkt);
 528                 scsi_free_consistent_buf(ssc->ses_rqbp);
 529                 if (ssc->ses_sbufp) {
 530                         freerbuf(ssc->ses_sbufp);
 531                 }
 532                 cv_destroy(&ssc->ses_sbufcv);
 533                 ddi_soft_state_free(estate, inst);
 534                 scsi_unprobe(devp);
 535                 return (DDI_FAILURE);
 536         }
 537 
 538         /*
 539          * create this property so that PM code knows we want
 540          * to be suspended at PM time
 541          */
 542         (void) ddi_prop_update_string(DDI_DEV_T_NONE, dip,
 543             PM_HARDWARE_STATE_PROP, PM_NEEDS_SUSPEND_RESUME);
 544 
 545         /* announce the existence of this device */
 546         ddi_report_dev(dip);
 547         return (DDI_SUCCESS);
 548 }
 549 
 550 
 551 /*
 552  * Detach ses device.
 553  *
 554  * XXX:  Power management is NOT supported.  A token framework
 555  *       is provided that will need to be extended assuming we have
 556  *       ses devices we can power down.  Currently, we don't have any.
 557  */
 558 static int
 559 ses_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
 560 {
 561         ses_softc_t *ssc;
 562         int inst;
 563 
 564         switch (cmd) {
 565         case DDI_DETACH:
 566                 inst = ddi_get_instance(dip);
 567                 ssc = ddi_get_soft_state(estate, inst);
 568                 if (ssc == NULL) {
 569                         cmn_err(CE_NOTE,
 570                             "ses%d: DDI_DETACH, no softstate found", inst);
 571                         return (DDI_FAILURE);
 572                 }
 573                 if (ISOPEN(ssc)) {
 574                         return (DDI_FAILURE);
 575                 }
 576 
 577 #if             !defined(lint)
 578                 /* LINTED */
 579                 _NOTE(COMPETING_THREADS_NOW);
 580 #endif          /* !defined(lint) */
 581 
 582                 if (ssc->ses_vec.softc_init)
 583                         (void) (*ssc->ses_vec.softc_init)(ssc, 0);
 584 
 585 #if             !defined(lint)
 586                 _NOTE(NO_COMPETING_THREADS_NOW);
 587 #endif          /* !defined(lint) */
 588 
 589                 (void) scsi_ifsetcap(SES_ROUTE(ssc), "auto-rqsense", 1, 0);
 590                 scsi_destroy_pkt(ssc->ses_rqpkt);
 591                 scsi_free_consistent_buf(ssc->ses_rqbp);
 592                 freerbuf(ssc->ses_sbufp);
 593                 cv_destroy(&ssc->ses_sbufcv);
 594                 ddi_soft_state_free(estate, inst);
 595                 ddi_prop_remove_all(dip);
 596                 ddi_remove_minor_node(dip, NULL);
 597                 scsi_unprobe(ddi_get_driver_private(dip));
 598                 break;
 599 
 600         case DDI_SUSPEND:
 601                 inst = ddi_get_instance(dip);
 602                 if ((ssc = ddi_get_soft_state(estate, inst)) == NULL) {
 603                         cmn_err(CE_NOTE,
 604                             "ses%d: DDI_SUSPEND, no softstate found", inst);
 605                         return (DDI_FAILURE);
 606                 }
 607 
 608                 /*
 609                  * If driver idle, accept suspend request.
 610                  * If it's busy, reject it.  This keeps things simple!
 611                  */
 612                 mutex_enter(SES_MUTEX);
 613                 if (ssc->ses_sbufbsy) {
 614                         mutex_exit(SES_MUTEX);
 615                         return (DDI_FAILURE);
 616                 }
 617                 ssc->ses_suspended = 1;
 618                 mutex_exit(SES_MUTEX);
 619                 break;
 620 
 621         default:
 622                 return (DDI_FAILURE);
 623         }
 624         return (DDI_SUCCESS);
 625 }
 626 
 627 /* ARGSUSED */
 628 static int
 629 ses_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
 630 {
 631         dev_t dev;
 632         ses_softc_t *ssc;
 633         int inst, error;
 634 
 635         switch (infocmd) {
 636         case DDI_INFO_DEVT2DEVINFO:
 637                 dev = (dev_t)arg;
 638                 inst = getminor(dev);
 639                 if ((ssc = ddi_get_soft_state(estate, inst)) == NULL) {
 640                         return (DDI_FAILURE);
 641                 }
 642                 *result = (void *) ssc->ses_devp->sd_dev;
 643                 error = DDI_SUCCESS;
 644                 break;
 645         case DDI_INFO_DEVT2INSTANCE:
 646                 dev = (dev_t)arg;
 647                 inst = getminor(dev);
 648                 *result = (void *)(uintptr_t)inst;
 649                 error = DDI_SUCCESS;
 650                 break;
 651         default:
 652                 error = DDI_FAILURE;
 653         }
 654         return (error);
 655 }
 656 
 657 
 658 /*
 659  * Unix Entry Points
 660  */
 661 
 662 /* ARGSUSED */
 663 static int
 664 ses_open(dev_t *dev_p, int flag, int otyp, cred_t *cred_p)
 665 {
 666         ses_softc_t *ssc;
 667 
 668         if ((ssc = ddi_get_soft_state(estate, getminor(*dev_p))) == NULL) {
 669                 return (ENXIO);
 670         }
 671 
 672         /*
 673          * If the device is powered down, request it's activation.
 674          * If it can't be activated, fail open.
 675          */
 676         if (ssc->ses_suspended &&
 677             ddi_dev_is_needed(SES_DEVINFO(ssc), 0, 1) != DDI_SUCCESS) {
 678                 return (EIO);
 679         }
 680 
 681         mutex_enter(SES_MUTEX);
 682         if (otyp == OTYP_LYR)
 683                 ssc->ses_lyropen++;
 684         else
 685                 ssc->ses_oflag = 1;
 686 
 687         ssc->ses_present = (ssc->ses_present)? ssc->ses_present: SES_OPENING;
 688         mutex_exit(SES_MUTEX);
 689         return (EOK);
 690 }
 691 
 692 /*ARGSUSED*/
 693 static int
 694 ses_close(dev_t dev, int flag, int otyp, cred_t *cred_p)
 695 {
 696         ses_softc_t *ssc;
 697         if ((ssc = ddi_get_soft_state(estate, getminor(dev))) == NULL) {
 698                 return (ENXIO);
 699         }
 700 
 701         if (ssc->ses_suspended) {
 702                 (void) ddi_dev_is_needed(SES_DEVINFO(ssc), 0, 1);
 703         }
 704 
 705         mutex_enter(SES_MUTEX);
 706         if (otyp == OTYP_LYR)
 707                 ssc->ses_lyropen -= (ssc->ses_lyropen)? 1: 0;
 708         else
 709                 ssc->ses_oflag = 0;
 710         mutex_exit(SES_MUTEX);
 711         return (0);
 712 }
 713 
 714 
 715 /*ARGSUSED3*/
 716 static int
 717 ses_ioctl(dev_t dev, int cmd, intptr_t arg, int flg, cred_t *cred_p, int *rvalp)
 718 {
 719         ses_softc_t *ssc;
 720         ses_object k, *up;
 721         ses_objarg x;
 722         uchar_t t;
 723         uchar_t i;
 724         int rv = 0;
 725 
 726         if ((ssc = ddi_get_soft_state(estate, getminor(dev))) == NULL ||
 727             ssc->ses_present == SES_CLOSED) {
 728                 return (ENXIO);
 729         }
 730 
 731 
 732         switch (cmd) {
 733         case SESIOC_GETNOBJ:
 734                 if (ddi_copyout(&ssc->ses_nobjects, (void *)arg,
 735                     sizeof (int), flg)) {
 736                         rv = EFAULT;
 737                         break;
 738                 }
 739                 break;
 740 
 741         case SESIOC_GETOBJMAP:
 742                 up = (ses_object *) arg;
 743                 mutex_enter(SES_MUTEX);
 744                 for (i = 0; i != ssc->ses_nobjects; i++) {
 745                         k.obj_id = i;
 746                         k.subencid = ssc->ses_objmap[i].subenclosure;
 747                         k.elem_type = ssc->ses_objmap[i].enctype;
 748                         if (ddi_copyout(&k, up, sizeof (k), flg)) {
 749                                 rv = EFAULT;
 750                                 break;
 751                         }
 752                         up++;
 753                 }
 754                 mutex_exit(SES_MUTEX);
 755                 break;
 756 
 757         case SESIOC_INIT:
 758                 if (drv_priv(cred_p) != 0) {
 759                         rv = EPERM;
 760                         break;
 761                 }
 762                 rv = (*ssc->ses_vec.init_enc)(ssc);
 763                 break;
 764 
 765         case SESIOC_GETENCSTAT:
 766                 if ((ssc->ses_encstat & ENCI_SVALID) == 0) {
 767                         rv = (*ssc->ses_vec.get_encstat)(ssc, KM_SLEEP);
 768                         if (rv) {
 769                                 break;
 770                         }
 771                 }
 772                 t = ssc->ses_encstat & 0xf;
 773                 if (ddi_copyout(&t, (void *)arg, sizeof (t), flg))
 774                         rv = EFAULT;
 775                 /*
 776                  * And always invalidate enclosure status on the way out.
 777                  */
 778                 mutex_enter(SES_MUTEX);
 779                 ssc->ses_encstat &= ~ENCI_SVALID;
 780                 mutex_exit(SES_MUTEX);
 781                 break;
 782 
 783         case SESIOC_SETENCSTAT:
 784                 if (drv_priv(cred_p) != 0) {
 785                         rv = EPERM;
 786                         break;
 787                 }
 788                 if (ddi_copyin((void *)arg, &t, sizeof (t), flg))
 789                         rv = EFAULT;
 790                 else
 791                         rv = (*ssc->ses_vec.set_encstat)(ssc, t, KM_SLEEP);
 792                 mutex_enter(SES_MUTEX);
 793                 ssc->ses_encstat &= ~ENCI_SVALID;
 794                 mutex_exit(SES_MUTEX);
 795                 break;
 796 
 797         case SESIOC_GETOBJSTAT:
 798                 if (ddi_copyin((void *)arg, &x, sizeof (x), flg)) {
 799                         rv = EFAULT;
 800                         break;
 801                 }
 802                 if (x.obj_id >= ssc->ses_nobjects) {
 803                         rv = EINVAL;
 804                         break;
 805                 }
 806                 if ((rv = (*ssc->ses_vec.get_objstat)(ssc, &x, KM_SLEEP)) != 0)
 807                         break;
 808                 if (ddi_copyout(&x, (void *)arg, sizeof (x), flg))
 809                         rv = EFAULT;
 810                 else {
 811                         /*
 812                          * Now that we no longer poll, svalid never stays true.
 813                          */
 814                         mutex_enter(SES_MUTEX);
 815                         ssc->ses_objmap[x.obj_id].svalid = 0;
 816                         mutex_exit(SES_MUTEX);
 817                 }
 818                 break;
 819 
 820         case SESIOC_SETOBJSTAT:
 821                 if (drv_priv(cred_p) != 0) {
 822                         rv = EPERM;
 823                         break;
 824                 }
 825                 if (ddi_copyin((void *)arg, &x, sizeof (x), flg)) {
 826                         rv = EFAULT;
 827                         break;
 828                 }
 829                 if (x.obj_id >= ssc->ses_nobjects) {
 830                         rv = EINVAL;
 831                         break;
 832                 }
 833                 rv = (*ssc->ses_vec.set_objstat)(ssc, &x, KM_SLEEP);
 834                 if (rv == 0) {
 835                         mutex_enter(SES_MUTEX);
 836                         ssc->ses_objmap[x.obj_id].svalid = 0;
 837                         mutex_exit(SES_MUTEX);
 838                 }
 839                 break;
 840 
 841         case USCSICMD:
 842                 if (drv_priv(cred_p) != 0) {
 843                         rv = EPERM;
 844                         break;
 845                 }
 846                 rv = ses_uscsi_cmd(ssc, (Uscmd *)arg, flg);
 847                 break;
 848 
 849         default:
 850                 rv = ENOTTY;
 851                 break;
 852         }
 853         return (rv);
 854 }
 855 
 856 
 857 /*
 858  * Loop on running a kernel based command
 859  *
 860  * FIXME:  This routine is not really needed.
 861  */
 862 int
 863 ses_runcmd(ses_softc_t *ssc, Uscmd *lp)
 864 {
 865         int e;
 866 
 867         lp->uscsi_status = 0;
 868         e = ses_uscsi_cmd(ssc, lp, FKIOCTL);
 869 
 870 #ifdef  not
 871         /*
 872          * Debug:  Nice cross-check code for verifying consistent status.
 873          */
 874         if (lp->uscsi_status) {
 875                 if (lp->uscsi_status == STATUS_CHECK) {
 876                         SES_LOG(ssc, CE_NOTE, "runcmd<cdb[0]="
 877                             "0x%x->%s ASC/ASCQ=0x%x/0x%x>",
 878                             lp->uscsi_cdb[0],
 879                             scsi_sname(lp->uscsi_rqbuf[2] & 0xf),
 880                             lp->uscsi_rqbuf[12] & 0xff,
 881                             lp->uscsi_rqbuf[13] & 0xff);
 882                 } else {
 883                         SES_LOG(ssc, CE_NOTE, "runcmd<cdb[0]="
 884                             "0x%x -> Status 0x%x", lp->uscsi_cdb[0],
 885                             lp->uscsi_status);
 886                 }
 887         }
 888 #endif  /* not */
 889         return (e);
 890 }
 891 
 892 
 893 /*
 894  * Run a scsi command.
 895  */
 896 int
 897 ses_uscsi_cmd(ses_softc_t *ssc, Uscmd *Uc, int Uf)
 898 {
 899         Uscmd   *uscmd;
 900         struct buf      *bp;
 901         enum uio_seg    uioseg;
 902         int     err;
 903 
 904         /*
 905          * Grab local 'special' buffer
 906          */
 907         mutex_enter(SES_MUTEX);
 908         while (ssc->ses_sbufbsy) {
 909                 cv_wait(&ssc->ses_sbufcv, &ssc->ses_devp->sd_mutex);
 910         }
 911         ssc->ses_sbufbsy = 1;
 912         mutex_exit(SES_MUTEX);
 913 
 914         /*
 915          * If the device is powered down, request it's activation.
 916          * This check must be done after setting ses_sbufbsy!
 917          */
 918         if (ssc->ses_suspended &&
 919             ddi_dev_is_needed(SES_DEVINFO(ssc), 0, 1) != DDI_SUCCESS) {
 920                 mutex_enter(SES_MUTEX);
 921                 ssc->ses_sbufbsy = 0;
 922                 mutex_exit(SES_MUTEX);
 923                 return (EIO);
 924         }
 925 
 926         err = scsi_uscsi_alloc_and_copyin((intptr_t)Uc, Uf,
 927             SES_ROUTE(ssc), &uscmd);
 928         if (err != 0) {
 929                 SES_LOG(ssc, SES_CE_DEBUG1, "ses_uscsi_cmd: "
 930                     "scsi_uscsi_alloc_and_copyin failed\n");
 931                 mutex_enter(SES_MUTEX);
 932                 ssc->ses_sbufbsy = 0;
 933                 cv_signal(&ssc->ses_sbufcv);
 934                 mutex_exit(SES_MUTEX);
 935                 SES_LOG(ssc, SES_CE_DEBUG2, efl, __LINE__);
 936                 return (err);
 937         }
 938 
 939         /*
 940          * Copy the uscsi command related infos to ssc for use in ses_start()
 941          * and ses_callback().
 942          */
 943         bcopy(uscmd, &ssc->ses_uscsicmd, sizeof (Uscmd));
 944         if (uscmd->uscsi_cdb != NULL) {
 945                 bcopy(uscmd->uscsi_cdb, &ssc->ses_srqcdb,
 946                     (size_t)(uscmd->uscsi_cdblen));
 947         }
 948         ssc->ses_uscsicmd.uscsi_status = 0;
 949 
 950         bp = ssc->ses_sbufp;
 951         bp->av_back = (struct buf *)NULL;
 952         bp->av_forw = (struct buf *)NULL;
 953         bp->b_back = (struct buf *)ssc;
 954         bp->b_edev = NODEV;
 955 
 956         if (uscmd->uscsi_cdb != NULL) {
 957                 if (uscmd->uscsi_cdblen == CDB_GROUP0) {
 958                         SES_LOG(ssc, SES_CE_DEBUG7,
 959                             "scsi_cmd: %x %x %x %x %x %x",
 960                             ((char *)uscmd->uscsi_cdb)[0],
 961                             ((char *)uscmd->uscsi_cdb)[1],
 962                             ((char *)uscmd->uscsi_cdb)[2],
 963                             ((char *)uscmd->uscsi_cdb)[3],
 964                             ((char *)uscmd->uscsi_cdb)[4],
 965                             ((char *)uscmd->uscsi_cdb)[5]);
 966                 } else {
 967                         SES_LOG(ssc, SES_CE_DEBUG7,
 968                             "scsi cmd: %x %x %x %x %x %x %x %x %x %x",
 969                             ((char *)uscmd->uscsi_cdb)[0],
 970                             ((char *)uscmd->uscsi_cdb)[1],
 971                             ((char *)uscmd->uscsi_cdb)[2],
 972                             ((char *)uscmd->uscsi_cdb)[3],
 973                             ((char *)uscmd->uscsi_cdb)[4],
 974                             ((char *)uscmd->uscsi_cdb)[5],
 975                             ((char *)uscmd->uscsi_cdb)[6],
 976                             ((char *)uscmd->uscsi_cdb)[7],
 977                             ((char *)uscmd->uscsi_cdb)[8],
 978                             ((char *)uscmd->uscsi_cdb)[9]);
 979                 }
 980         }
 981 
 982         uioseg = (Uf & FKIOCTL) ? UIO_SYSSPACE : UIO_USERSPACE;
 983         err = scsi_uscsi_handle_cmd(NODEV, uioseg, uscmd,
 984             ses_start, bp, NULL);
 985 
 986         /*
 987          * ses_callback() may set values for ssc->ses_uscsicmd or
 988          * ssc->ses_srqsbuf, so copy them back to uscmd.
 989          */
 990         if (uscmd->uscsi_rqbuf != NULL) {
 991                 bcopy(&ssc->ses_srqsbuf, uscmd->uscsi_rqbuf,
 992                     (size_t)(uscmd->uscsi_rqlen));
 993                 uscmd->uscsi_rqresid = ssc->ses_uscsicmd.uscsi_rqresid;
 994         }
 995         uscmd->uscsi_status = ssc->ses_uscsicmd.uscsi_status;
 996 
 997         (void) scsi_uscsi_copyout_and_free((intptr_t)Uc, uscmd);
 998         mutex_enter(SES_MUTEX);
 999         ssc->ses_sbufbsy = 0;
1000         cv_signal(&ssc->ses_sbufcv);
1001         mutex_exit(SES_MUTEX);
1002 
1003         return (err);
1004 }
1005 
1006 
1007 
1008 /*
1009  * Command start and done functions.
1010  */
1011 static int
1012 ses_start(struct buf *bp)
1013 {
1014         ses_softc_t *ssc = (ses_softc_t *)bp->b_back;
1015 
1016         SES_LOG(ssc, SES_CE_DEBUG9, "ses_start");
1017         if (!BP_PKT(bp)) {
1018                 /*
1019                  * Allocate a packet.
1020                  */
1021                 ses_get_pkt(bp, SLEEP_FUNC);
1022                 if (!BP_PKT(bp)) {
1023                         int err;
1024                         bp->b_resid = bp->b_bcount;
1025                         if (geterror(bp) == 0)
1026                                 SET_BP_ERROR(bp, EIO);
1027                         err = geterror(bp);
1028                         biodone(bp);
1029                         return (err);
1030                 }
1031         }
1032 
1033         /*
1034          * Initialize the transfer residue, error code, and retry count.
1035          */
1036         bp->b_resid = 0;
1037         SET_BP_ERROR(bp, 0);
1038 
1039 #if     !defined(lint)
1040         _NOTE(NO_COMPETING_THREADS_NOW);
1041 #endif  /* !defined(lint) */
1042         ssc->ses_retries = ses_retry_count;
1043 
1044 #if     !defined(lint)
1045         /* LINTED */
1046         _NOTE(COMPETING_THREADS_NOW);
1047 #endif  /* !defined(lint) */
1048 
1049         SES_LOG(ssc, SES_CE_DEBUG9, "ses_start -> scsi_transport");
1050         switch (scsi_transport(BP_PKT(bp))) {
1051         case TRAN_ACCEPT:
1052                 return (0);
1053                 /* break; */
1054 
1055         case TRAN_BUSY:
1056                 SES_LOG(ssc, SES_CE_DEBUG2,
1057                     "ses_start: TRANSPORT BUSY");
1058                 SES_ENABLE_RESTART(SES_RESTART_TIME, BP_PKT(bp));
1059                 return (0);
1060                 /* break; */
1061 
1062         default:
1063                 SES_LOG(ssc, SES_CE_DEBUG2, "TRANSPORT ERROR\n");
1064                 SET_BP_ERROR(bp, EIO);
1065                 scsi_destroy_pkt(BP_PKT(bp));
1066                 SET_BP_PKT(bp, NULL);
1067                 biodone(bp);
1068                 return (EIO);
1069                 /* break; */
1070         }
1071 }
1072 
1073 
1074 static void
1075 ses_get_pkt(struct buf *bp, int (*func)())
1076 {
1077         ses_softc_t *ssc = (ses_softc_t *)bp->b_back;
1078         Uscmd *scmd = &ssc->ses_uscsicmd;
1079         struct scsi_pkt *pkt;
1080         int stat_size = 1;
1081         int flags = 0;
1082 
1083         if ((scmd->uscsi_flags & USCSI_RQENABLE) && ssc->ses_arq) {
1084                 if (scmd->uscsi_rqlen > SENSE_LENGTH) {
1085                         stat_size = (int)(scmd->uscsi_rqlen) +
1086                             sizeof (struct scsi_arq_status) -
1087                             sizeof (struct scsi_extended_sense);
1088                         flags = PKT_XARQ;
1089                 } else {
1090                         stat_size = sizeof (struct scsi_arq_status);
1091                 }
1092         }
1093 
1094         if (bp->b_bcount) {
1095                 pkt = scsi_init_pkt(SES_ROUTE(ssc), NULL, bp,
1096                     scmd->uscsi_cdblen, stat_size, 0, flags,
1097                     func, (caddr_t)ssc);
1098         } else {
1099                 pkt = scsi_init_pkt(SES_ROUTE(ssc), NULL, NULL,
1100                     scmd->uscsi_cdblen, stat_size, 0, flags,
1101                     func, (caddr_t)ssc);
1102         }
1103         SET_BP_PKT(bp, pkt);
1104         if (pkt == (struct scsi_pkt *)NULL)
1105                 return;
1106         bcopy(scmd->uscsi_cdb, pkt->pkt_cdbp, (size_t)scmd->uscsi_cdblen);
1107 
1108         /* Set an upper bound timeout of ses_io_time if zero is passed in */
1109         pkt->pkt_time = (scmd->uscsi_timeout == 0) ?
1110             ses_io_time : scmd->uscsi_timeout;
1111 
1112         pkt->pkt_comp = ses_callback;
1113         pkt->pkt_private = (opaque_t)ssc;
1114 }
1115 
1116 
1117 /*
1118  * Restart ses command.
1119  */
1120 static void
1121 ses_restart(void *arg)
1122 {
1123         struct scsi_pkt *pkt = (struct scsi_pkt *)arg;
1124         ses_softc_t *ssc = (ses_softc_t *)pkt->pkt_private;
1125         struct buf *bp = ssc->ses_sbufp;
1126         SES_LOG(ssc, SES_CE_DEBUG9, "ses_restart");
1127 
1128         ssc->ses_restart_id = NULL;
1129 
1130         switch (scsi_transport(pkt)) {
1131         case TRAN_ACCEPT:
1132                 SES_LOG(ssc, SES_CE_DEBUG9,
1133                     "RESTART %d ok", ssc->ses_retries);
1134                 return;
1135                 /* break; */
1136         case TRAN_BUSY:
1137                 SES_LOG(ssc, SES_CE_DEBUG1,
1138                     "RESTART %d TRANSPORT BUSY\n", ssc->ses_retries);
1139                 if (ssc->ses_retries > SES_NO_RETRY) {
1140                         ssc->ses_retries -= SES_BUSY_RETRY;
1141                         SES_ENABLE_RESTART(SES_RESTART_TIME, pkt);
1142                         return;
1143                 }
1144                 SET_BP_ERROR(bp, EBUSY);
1145                 break;
1146         default:
1147                 SET_BP_ERROR(bp, EIO);
1148                 break;
1149         }
1150         SES_LOG(ssc, SES_CE_DEBUG1,
1151             "RESTART %d TRANSPORT FAILED\n", ssc->ses_retries);
1152 
1153         pkt = (struct scsi_pkt *)bp->av_back;
1154         scsi_destroy_pkt(pkt);
1155         bp->b_resid = bp->b_bcount;
1156         SET_BP_PKT(bp, NULL);
1157         biodone(bp);
1158 }
1159 
1160 
1161 /*
1162  * Command completion processing
1163  */
1164 #define HBA_RESET       (STAT_BUS_RESET|STAT_DEV_RESET|STAT_ABORTED)
1165 static void
1166 ses_callback(struct scsi_pkt *pkt)
1167 {
1168         ses_softc_t *ssc = (ses_softc_t *)pkt->pkt_private;
1169         struct buf *bp;
1170         Uscmd *scmd;
1171         int err;
1172         char action;
1173 
1174         bp = ssc->ses_sbufp;
1175         scmd = &ssc->ses_uscsicmd;
1176         /* SES_LOG(ssc, SES_CE_DEBUG9, "ses_callback"); */
1177 
1178         /*
1179          * Optimization: Normal completion.
1180          */
1181         if (pkt->pkt_reason == CMD_CMPLT &&
1182             !SCBP_C(pkt) &&
1183             !(pkt->pkt_flags & FLAG_SENSING) &&
1184             !pkt->pkt_resid) {
1185                 scsi_destroy_pkt(pkt);
1186                 SET_BP_PKT(bp, NULL);
1187                 biodone(bp);
1188                 return;
1189         }
1190 
1191 
1192         /*
1193          * Abnormal completion.
1194          *
1195          * Assume most common error initially.
1196          */
1197         err = EIO;
1198         action = COMMAND_DONE;
1199         if (scmd->uscsi_flags & USCSI_DIAGNOSE) {
1200                 ssc->ses_retries = SES_NO_RETRY;
1201         }
1202 
1203 CHECK_PKT:
1204         if (pkt->pkt_reason != CMD_CMPLT) {
1205                 /* Process transport errors. */
1206                 switch (pkt->pkt_reason) {
1207                 case CMD_TIMEOUT:
1208                         /*
1209                          * If the transport layer didn't clear the problem,
1210                          * reset the target.
1211                          */
1212                         if (! (pkt->pkt_statistics & HBA_RESET)) {
1213                                 (void) scsi_reset(&pkt->pkt_address,
1214                                     RESET_TARGET);
1215                         }
1216                         err = ETIMEDOUT;
1217                         break;
1218 
1219                 case CMD_INCOMPLETE:
1220                 case CMD_UNX_BUS_FREE:
1221                         /*
1222                          * No response?  If probing, give up.
1223                          * Otherwise, keep trying until retries exhausted.
1224                          * Then lockdown the driver as the device is
1225                          * unplugged.
1226                          */
1227                         if (ssc->ses_retries <= SES_NO_RETRY &&
1228                             !(scmd->uscsi_flags & USCSI_DIAGNOSE)) {
1229                                 ssc->ses_present = SES_CLOSED;
1230                         }
1231                         /* Inhibit retries to speed probe/attach. */
1232                         if (ssc->ses_present < SES_OPEN) {
1233                                 ssc->ses_retries = SES_NO_RETRY;
1234                         }
1235                         /* SES_CMD_RETRY4(ssc->ses_retries); */
1236                         err = ENXIO;
1237                         break;
1238 
1239                 case CMD_DATA_OVR:
1240                         /*
1241                          * XXX: Some HBA's (e.g. Adaptec 1740 and
1242                          *      earlier ISP revs) report a DATA OVERRUN
1243                          *      error instead of a transfer residue.  So,
1244                          *      we convert the error and restart.
1245                          */
1246                         if ((bp->b_bcount - pkt->pkt_resid) > 0) {
1247                                 SES_LOG(ssc, SES_CE_DEBUG6,
1248                                     "ignoring overrun");
1249                                 pkt->pkt_reason = CMD_CMPLT;
1250                                 err = EOK;
1251                                 goto CHECK_PKT;
1252                         }
1253                         ssc->ses_retries = SES_NO_RETRY;
1254                         /* err = EIO; */
1255                         break;
1256 
1257                 case CMD_DMA_DERR:
1258                         ssc->ses_retries = SES_NO_RETRY;
1259                         err = EFAULT;
1260                         break;
1261 
1262                 default:
1263                         /* err = EIO; */
1264                         break;
1265                 }
1266                 if (pkt == ssc->ses_rqpkt) {
1267                         SES_LOG(ssc, CE_WARN, fail_msg,
1268                             "Request Sense ",
1269                             scsi_rname(pkt->pkt_reason),
1270                             (ssc->ses_retries > 0)?
1271                             "retrying": "giving up");
1272                         pkt = (struct scsi_pkt *)bp->av_back;
1273                         action = QUE_SENSE;
1274                 } else {
1275                         SES_LOG(ssc, CE_WARN, fail_msg,
1276                             "", scsi_rname(pkt->pkt_reason),
1277                             (ssc->ses_retries > 0)?
1278                             "retrying": "giving up");
1279                         action = QUE_COMMAND;
1280                 }
1281                 /* Device exists, allow full error recovery. */
1282                 if (ssc->ses_retries > SES_NO_RETRY) {
1283                         ssc->ses_present = SES_OPEN;
1284                 }
1285 
1286 
1287         /*
1288          * Process status and sense data errors.
1289          */
1290         } else {
1291                 ssc->ses_present = SES_OPEN;
1292                 action = ses_decode_sense(pkt, &err);
1293         }
1294 
1295 
1296         /*
1297          * Initiate error recovery action, as needed.
1298          */
1299         switch (action) {
1300         case QUE_COMMAND_NOW:
1301                 /* SES_LOG(ssc, SES_CE_DEBUG1, "retrying cmd now"); */
1302                 if (ssc->ses_retries > SES_NO_RETRY) {
1303                         ssc->ses_retries -= SES_CMD_RETRY;
1304                         scmd->uscsi_status = 0;
1305                         if (ssc->ses_arq)
1306                                 bzero(pkt->pkt_scbp,
1307                                     sizeof (struct scsi_arq_status));
1308 
1309                         if (scsi_transport((struct scsi_pkt *)bp->av_back)
1310                             != TRAN_ACCEPT) {
1311                                 SES_ENABLE_RESTART(SES_RESTART_TIME,
1312                                     (struct scsi_pkt *)bp->av_back);
1313                         }
1314                         return;
1315                 }
1316                 break;
1317 
1318         case QUE_COMMAND:
1319                 SES_LOG(ssc, SES_CE_DEBUG1, "retrying cmd");
1320                 if (ssc->ses_retries > SES_NO_RETRY) {
1321                         ssc->ses_retries -=
1322                             (err == EBUSY)? SES_BUSY_RETRY: SES_CMD_RETRY;
1323                         scmd->uscsi_status = 0;
1324                         if (ssc->ses_arq)
1325                                 bzero(pkt->pkt_scbp,
1326                                     sizeof (struct scsi_arq_status));
1327 
1328                         SES_ENABLE_RESTART(
1329                             (err == EBUSY)? SES_BUSY_TIME: SES_RESTART_TIME,
1330                             (struct scsi_pkt *)bp->av_back);
1331                         return;
1332                 }
1333                 break;
1334 
1335         case QUE_SENSE:
1336                 SES_LOG(ssc, SES_CE_DEBUG1, "retrying sense");
1337                 if (ssc->ses_retries > SES_NO_RETRY) {
1338                         ssc->ses_retries -= SES_SENSE_RETRY;
1339                         scmd->uscsi_status = 0;
1340                         bzero(&ssc->ses_srqsbuf, MAX_SENSE_LENGTH);
1341 
1342                         if (scsi_transport(ssc->ses_rqpkt) != TRAN_ACCEPT) {
1343                                 SES_ENABLE_RESTART(SES_RESTART_TIME,
1344                                     ssc->ses_rqpkt);
1345                         }
1346                         return;
1347                 }
1348                 break;
1349 
1350         case COMMAND_DONE:
1351                 SES_LOG(ssc, SES_CE_DEBUG4, "cmd done");
1352                 pkt = (struct scsi_pkt *)bp->av_back;
1353                 bp->b_resid = pkt->pkt_resid;
1354                 if (bp->b_resid) {
1355                         SES_LOG(ssc, SES_CE_DEBUG6,
1356                             "transfer residue %ld(%ld)",
1357                             bp->b_bcount - bp->b_resid, bp->b_bcount);
1358                 }
1359                 break;
1360         }
1361         pkt = (struct scsi_pkt *)bp->av_back;
1362         if (err) {
1363                 SES_LOG(ssc, SES_CE_DEBUG1, "SES: ERROR %d\n", err);
1364                 SET_BP_ERROR(bp, err);
1365                 bp->b_resid = bp->b_bcount;
1366         }
1367         scsi_destroy_pkt(pkt);
1368         SET_BP_PKT(bp, NULL);
1369         biodone(bp);
1370 }
1371 
1372 
1373 /*
1374  * Check status and sense data and determine recovery.
1375  */
1376 static int
1377 ses_decode_sense(struct scsi_pkt *pkt, int *err)
1378 {
1379         ses_softc_t *ssc = (ses_softc_t *)pkt->pkt_private;
1380         struct  scsi_extended_sense *sense =
1381             (struct scsi_extended_sense *)&ssc->ses_srqsbuf;
1382         Uscmd *scmd = &ssc->ses_uscsicmd;
1383         char sense_flag = 0;
1384         uchar_t status = SCBP_C(pkt) & STATUS_MASK;
1385         char *err_action;
1386         char action;
1387         uchar_t rqlen;
1388         int amt;
1389 
1390         /*
1391          * Process manual request sense.
1392          * Copy manual request sense to sense buffer.
1393          *
1394          * This is done if auto request sense is not enabled.
1395          * Or the auto request sense failed and the request
1396          * sense needs to be retried.
1397          */
1398         if (pkt->pkt_flags & FLAG_SENSING) {
1399                 struct buf *sbp = ssc->ses_rqbp;
1400                 amt = min(MAX_SENSE_LENGTH,
1401                     sbp->b_bcount - sbp->b_resid);
1402                 rqlen = min((uchar_t)amt, scmd->uscsi_rqlen);
1403                 bcopy(sbp->b_un.b_addr, sense, rqlen);
1404                 scmd->uscsi_rqresid = scmd->uscsi_rqlen - rqlen;
1405                 sense_flag = 1;
1406         /*
1407          * Process auto request sense.
1408          * Copy auto request sense to sense buffer.
1409          *
1410          * If auto request sense failed due to transport error,
1411          * retry the command.  Otherwise process the status and
1412          * sense data.
1413          */
1414         } else if (ssc->ses_arq && pkt->pkt_state & STATE_ARQ_DONE) {
1415                 struct scsi_arq_status *arq =
1416                     (struct scsi_arq_status *)(pkt->pkt_scbp);
1417                 uchar_t *arq_status = (uchar_t *)&arq->sts_rqpkt_status;
1418                 if (pkt->pkt_state & STATE_XARQ_DONE) {
1419                         amt = MAX_SENSE_LENGTH - arq->sts_rqpkt_resid;
1420                 } else {
1421                         if (arq->sts_rqpkt_resid > SENSE_LENGTH) {
1422                                 amt = MAX_SENSE_LENGTH - arq->sts_rqpkt_resid;
1423                         } else {
1424                                 amt = SENSE_LENGTH - arq->sts_rqpkt_resid;
1425                         }
1426                 }
1427 
1428                 if (arq->sts_rqpkt_reason != CMD_CMPLT) {
1429                         return (QUE_COMMAND);
1430                 }
1431 
1432                 rqlen = min((uchar_t)amt, scmd->uscsi_rqlen);
1433                 bcopy(&arq->sts_sensedata, sense, rqlen);
1434                 scmd->uscsi_status = status;
1435                 scmd->uscsi_rqresid = scmd->uscsi_rqlen - rqlen;
1436                 status = *arq_status & STATUS_MASK;
1437                 pkt->pkt_state &= ~STATE_ARQ_DONE;
1438                 sense_flag = 1;
1439         }
1440 
1441 
1442         /*
1443          * Check status of REQUEST SENSE or command.
1444          *
1445          * If it's not successful, try retrying the original command
1446          * and hope that it goes away.  If not, we'll eventually run
1447          * out of retries and die.
1448          */
1449         switch (status) {
1450         case STATUS_GOOD:
1451         case STATUS_INTERMEDIATE:
1452         case STATUS_MET:
1453                 /*
1454                  * If the command status is ok, we're done.
1455                  * Otherwise, examine the request sense data.
1456                  */
1457                 if (! sense_flag) {
1458                         *err = EOK;
1459                         return (COMMAND_DONE);
1460                 }
1461                 break;
1462 
1463         case STATUS_CHECK:
1464                 SES_LOG(ssc, SES_CE_DEBUG3, "status decode: check");
1465                 *err = EIO;
1466                 return (QUE_SENSE);
1467                 /* break; */
1468 
1469         case STATUS_BUSY:
1470                 SES_LOG(ssc, SES_CE_DEBUG1, "status decode: busy");
1471                 /* SES_CMD_RETRY2(ssc->ses_retries); */
1472                 *err = EBUSY;
1473                 return (QUE_COMMAND);
1474                 /* break; */
1475 
1476         case STATUS_RESERVATION_CONFLICT:
1477                 SES_LOG(ssc, SES_CE_DEBUG1, "status decode: reserved");
1478                 *err = EACCES;
1479                 return (COMMAND_DONE_ERROR);
1480                 /* break; */
1481 
1482         case STATUS_TERMINATED:
1483                 SES_LOG(ssc, SES_CE_DEBUG1, "status decode: terminated");
1484                 *err = ECANCELED;
1485                 return (COMMAND_DONE_ERROR);
1486                 /* break; */
1487 
1488         default:
1489                 SES_LOG(ssc, SES_CE_DEBUG1, "status 0x%x", status);
1490                 *err = EIO;
1491                 return (QUE_COMMAND);
1492                 /* break; */
1493         }
1494 
1495 
1496         /*
1497          * Check REQUEST SENSE error code.
1498          *
1499          * Either there's no error, a retryable error,
1500          * or it's dead.  SES devices aren't very complex.
1501          */
1502         err_action = "retrying";
1503         switch (sense->es_key) {
1504         case KEY_RECOVERABLE_ERROR:
1505                 *err = EOK;
1506                 err_action = "recovered";
1507                 action = COMMAND_DONE;
1508                 break;
1509 
1510         case KEY_UNIT_ATTENTION:
1511                 /*
1512                  * This is common for RAID!
1513                  */
1514                 /* *err = EIO; */
1515                 SES_CMD_RETRY1(ssc->ses_retries);
1516                 action = QUE_COMMAND_NOW;
1517                 break;
1518 
1519         case KEY_NOT_READY:
1520         case KEY_NO_SENSE:
1521                 /* *err = EIO; */
1522                 action = QUE_COMMAND;
1523                 break;
1524 
1525         default:
1526                 /* *err = EIO; */
1527                 err_action = "fatal";
1528                 action = COMMAND_DONE_ERROR;
1529                 break;
1530         }
1531         SES_LOG(ssc, SES_CE_DEBUG1,
1532             "cdb[0]= 0x%x %s,  key=0x%x, ASC/ASCQ=0x%x/0x%x",
1533             scmd->uscsi_cdb[0], err_action,
1534             sense->es_key, sense->es_add_code, sense->es_qual_code);
1535 
1536 #ifdef  not
1537         /*
1538          * Dump cdb and sense data stat's for manufacturing.
1539          */
1540         if (DEBUGGING_ERR || sd_error_level == SDERR_ALL) {
1541                 auto buf[128];
1542 
1543                 p = pkt->pkt_cdbp;
1544                 if ((j = scsi_cdb_size[CDB_GROUPID(*p)]) == 0)
1545                         j = CDB_SIZE;
1546 
1547                 /* Print cdb */
1548                 (void) sprintf(buf, "cmd:");
1549                 for (i = 0; i < j; i++) {
1550                         (void) sprintf(&buf[strlen(buf)],
1551                             hex, (uchar_t)*p++);
1552                 }
1553                 SES_LOG(ssc, SES_CE_DEBUG3, "%s", buf);
1554 
1555                 /* Suppress trailing zero's in sense data */
1556                 if (amt > 3) {
1557                         p = (char *)devp->sd_sense + amt;
1558                         for (j = amt; j > 3; j--) {
1559                                 if (*(--p))  break;
1560                         }
1561                 } else {
1562                         j = amt;
1563                 }
1564 
1565                 /* Print sense data. */
1566                 (void) sprintf(buf, "sense:");
1567                 p = (char *)devp->sd_sense;
1568                 for (i = 0; i < j; i++) {
1569                         (void) sprintf(&buf[strlen(buf)],
1570                             hex, (uchar_t)*p++);
1571                 }
1572                 SES_LOG(ssc, SES_CE_DEBUG3, "%s", buf);
1573         }
1574 #endif  /* not */
1575         return (action);
1576 }
1577 
1578 
1579 /*PRINTFLIKE3*/
1580 void
1581 ses_log(ses_softc_t *ssc, int level, const char *fmt, ...)
1582 {
1583         va_list ap;
1584         char buf[256];
1585 
1586         va_start(ap, fmt);
1587         (void) vsprintf(buf, fmt, ap);
1588         va_end(ap);
1589 
1590         if (ssc == (ses_softc_t *)NULL) {
1591                 switch (level) {
1592                 case SES_CE_DEBUG1:
1593                         if (ses_debug > 1)
1594                                 cmn_err(CE_NOTE, "%s", buf);
1595                         break;
1596                 case SES_CE_DEBUG2:
1597                         if (ses_debug > 2)
1598                                 cmn_err(CE_NOTE, "%s", buf);
1599                         break;
1600                 case SES_CE_DEBUG3:
1601                         if (ses_debug > 3)
1602                                 cmn_err(CE_NOTE, "%s", buf);
1603                         break;
1604                 case SES_CE_DEBUG4:
1605                         if (ses_debug > 4)
1606                                 cmn_err(CE_NOTE, "%s", buf);
1607                         break;
1608                 case SES_CE_DEBUG5:
1609                         if (ses_debug > 5)
1610                                 cmn_err(CE_NOTE, "%s", buf);
1611                         break;
1612                 case SES_CE_DEBUG6:
1613                         if (ses_debug > 6)
1614                                 cmn_err(CE_NOTE, "%s", buf);
1615                         break;
1616                 case SES_CE_DEBUG7:
1617                         if (ses_debug > 7)
1618                                 cmn_err(CE_NOTE, "%s", buf);
1619                         break;
1620                 case SES_CE_DEBUG8:
1621                         if (ses_debug > 8)
1622                                 cmn_err(CE_NOTE, "%s", buf);
1623                         break;
1624                 case SES_CE_DEBUG9:
1625                         if (ses_debug > 9)
1626                                 cmn_err(CE_NOTE, "%s", buf);
1627                         break;
1628                 case CE_NOTE:
1629                 case CE_WARN:
1630                 case CE_PANIC:
1631                         cmn_err(level, "%s", buf);
1632                         break;
1633                 case SES_CE_DEBUG:
1634                 default:
1635                         cmn_err(CE_NOTE, "%s", buf);
1636                 break;
1637                 }
1638                 return;
1639         }
1640 
1641         switch (level) {
1642         case CE_CONT:
1643         case CE_NOTE:
1644         case CE_WARN:
1645         case CE_PANIC:
1646                 scsi_log(SES_DEVINFO(ssc), (char *)Snm, level, Str, buf);
1647                 break;
1648         case SES_CE_DEBUG1:
1649                 if (ses_debug > 1)
1650                         scsi_log(SES_DEVINFO(ssc), (char *)Snm, SCSI_DEBUG,
1651                             Str, buf);
1652                 break;
1653         case SES_CE_DEBUG2:
1654                 if (ses_debug > 2)
1655                         scsi_log(SES_DEVINFO(ssc), (char *)Snm, SCSI_DEBUG,
1656                             Str, buf);
1657                 break;
1658         case SES_CE_DEBUG3:
1659                 if (ses_debug > 3)
1660                         scsi_log(SES_DEVINFO(ssc), (char *)Snm, SCSI_DEBUG,
1661                             Str, buf);
1662                 break;
1663         case SES_CE_DEBUG4:
1664                 if (ses_debug > 4)
1665                         scsi_log(SES_DEVINFO(ssc), (char *)Snm, SCSI_DEBUG,
1666                             Str, buf);
1667                 break;
1668         case SES_CE_DEBUG5:
1669                 if (ses_debug > 5)
1670                         scsi_log(SES_DEVINFO(ssc), (char *)Snm, SCSI_DEBUG,
1671                             Str, buf);
1672                 break;
1673         case SES_CE_DEBUG6:
1674                 if (ses_debug > 6)
1675                         scsi_log(SES_DEVINFO(ssc), (char *)Snm, SCSI_DEBUG,
1676                             Str, buf);
1677                 break;
1678         case SES_CE_DEBUG7:
1679                 if (ses_debug > 7)
1680                         scsi_log(SES_DEVINFO(ssc), (char *)Snm, SCSI_DEBUG,
1681                             Str, buf);
1682                 break;
1683         case SES_CE_DEBUG8:
1684                 if (ses_debug > 8)
1685                         scsi_log(SES_DEVINFO(ssc), (char *)Snm, SCSI_DEBUG,
1686                             Str, buf);
1687                 break;
1688         case SES_CE_DEBUG9:
1689                 if (ses_debug > 9)
1690                         scsi_log(SES_DEVINFO(ssc), (char *)Snm, SCSI_DEBUG,
1691                             Str, buf);
1692                 break;
1693         case SES_CE_DEBUG:
1694         default:
1695                 scsi_log(SES_DEVINFO(ssc), (char *)Snm, SCSI_DEBUG, Str, buf);
1696                 break;
1697         }
1698 }
1699 /*
1700  * mode: c
1701  * Local variables:
1702  * c-indent-level: 8
1703  * c-brace-imaginary-offset: 0
1704  * c-brace-offset: -8
1705  * c-argdecl-indent: 8
1706  * c-label-offset: -8
1707  * c-continued-statement-offset: 8
1708  * c-continued-brace-offset: 0
1709  * End:
1710  */