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