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