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