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