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