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