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