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 */