1 /* $OpenBSD: scsi_base.c,v 1.265 2020/03/12 19:21:01 krw Exp $ */ 2 /* $NetBSD: scsi_base.c,v 1.43 1997/04/02 02:29:36 mycroft Exp $ */ 3 4 /* 5 * Copyright (c) 1994, 1995, 1997 Charles M. Hannum. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by Charles M. Hannum. 18 * 4. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 /* 34 * Originally written by Julian Elischer (julian@dialix.oz.au) 35 * Detailed SCSI error printing Copyright 1997 by Matthew Jacob. 36 */ 37 38 #include <sys/param.h> 39 #include <sys/systm.h> 40 #include <sys/kernel.h> 41 #include <sys/uio.h> 42 #include <sys/errno.h> 43 #include <sys/device.h> 44 #include <sys/pool.h> 45 #include <sys/task.h> 46 47 #include <scsi/scsi_all.h> 48 #include <scsi/scsi_disk.h> 49 #include <scsi/scsiconf.h> 50 51 static __inline void asc2ascii(u_int8_t, u_int8_t ascq, char *result, 52 size_t len); 53 int scsi_xs_error(struct scsi_xfer *); 54 char *scsi_decode_sense(struct scsi_sense_data *, int); 55 56 void scsi_xs_sync_done(struct scsi_xfer *); 57 58 /* Values for flag parameter to scsi_decode_sense. */ 59 #define DECODE_SENSE_KEY 1 60 #define DECODE_ASC_ASCQ 2 61 #define DECODE_SKSV 3 62 63 struct pool scsi_xfer_pool; 64 struct pool scsi_plug_pool; 65 66 struct scsi_plug { 67 struct task task; 68 struct scsibus_softc *sb; 69 int target; 70 int lun; 71 int how; 72 }; 73 74 void scsi_plug_probe(void *); 75 void scsi_plug_detach(void *); 76 77 struct scsi_xfer * scsi_xs_io(struct scsi_link *, void *, int); 78 79 int scsi_ioh_pending(struct scsi_iopool *); 80 struct scsi_iohandler * scsi_ioh_deq(struct scsi_iopool *); 81 82 void scsi_xsh_runqueue(struct scsi_link *); 83 void scsi_xsh_ioh(void *, void *); 84 85 int scsi_link_open(struct scsi_link *); 86 void scsi_link_close(struct scsi_link *); 87 88 void * scsi_iopool_get(struct scsi_iopool *); 89 void scsi_iopool_put(struct scsi_iopool *, void *); 90 91 /* Various helper functions for scsi_do_mode_sense() */ 92 int scsi_mode_sense(struct scsi_link *, int, 93 union scsi_mode_sense_buf *, int); 94 int scsi_mode_sense_big(struct scsi_link *, int, 95 union scsi_mode_sense_buf *, int); 96 void * scsi_mode_sense_page(struct scsi_mode_header *, int, 97 int); 98 void * scsi_mode_sense_big_page(struct scsi_mode_header_big *, 99 int, int); 100 101 /* ioh/xsh queue state */ 102 #define RUNQ_IDLE 0 103 #define RUNQ_LINKQ 1 104 #define RUNQ_POOLQ 2 105 106 /* synchronous api for allocating an io. */ 107 struct scsi_io_mover { 108 struct mutex mtx; 109 void *io; 110 u_int done; 111 }; 112 #define SCSI_IO_MOVER_INITIALIZER { MUTEX_INITIALIZER(IPL_BIO), NULL, 0 } 113 114 void scsi_move(struct scsi_io_mover *); 115 void scsi_move_done(void *, void *); 116 117 void scsi_io_get_done(void *, void *); 118 void scsi_xs_get_done(void *, void *); 119 120 /* 121 * Called when a scsibus is attached to initialize global data. 122 */ 123 void 124 scsi_init(void) 125 { 126 static int scsi_init_done; 127 128 if (scsi_init_done) 129 return; 130 scsi_init_done = 1; 131 132 #if defined(SCSI_DELAY) && SCSI_DELAY > 0 133 /* Historical. Older buses may need a moment to stabilize. */ 134 delay(1000000 * SCSI_DELAY); 135 #endif /* SCSI_DELAY && SCSI_DELAY > 0 */ 136 137 /* Initialize the scsi_xfer pool. */ 138 pool_init(&scsi_xfer_pool, sizeof(struct scsi_xfer), 0, IPL_BIO, 0, 139 "scxspl", NULL); 140 pool_init(&scsi_plug_pool, sizeof(struct scsi_plug), 0, IPL_BIO, 0, 141 "scsiplug", NULL); 142 } 143 144 int 145 scsi_req_probe(struct scsibus_softc *sb, int target, int lun) 146 { 147 struct scsi_plug *p; 148 149 p = pool_get(&scsi_plug_pool, PR_NOWAIT); 150 if (p == NULL) 151 return ENOMEM; 152 153 task_set(&p->task, scsi_plug_probe, p); 154 p->sb = sb; 155 p->target = target; 156 p->lun = lun; 157 158 task_add(systq, &p->task); 159 160 return 0; 161 } 162 163 int 164 scsi_req_detach(struct scsibus_softc *sb, int target, int lun, int how) 165 { 166 struct scsi_plug *p; 167 168 p = pool_get(&scsi_plug_pool, PR_NOWAIT); 169 if (p == NULL) 170 return ENOMEM; 171 172 task_set(&p->task, scsi_plug_detach, p); 173 p->sb = sb; 174 p->target = target; 175 p->lun = lun; 176 p->how = how; 177 178 task_add(systq, &p->task); 179 180 return 0; 181 } 182 183 void 184 scsi_plug_probe(void *xp) 185 { 186 struct scsi_plug *p = xp; 187 struct scsibus_softc *sb = p->sb; 188 int target = p->target, lun = p->lun; 189 190 pool_put(&scsi_plug_pool, p); 191 192 scsi_probe(sb, target, lun); 193 } 194 195 void 196 scsi_plug_detach(void *xp) 197 { 198 struct scsi_plug *p = xp; 199 struct scsibus_softc *sb = p->sb; 200 int target = p->target, lun = p->lun; 201 int how = p->how; 202 203 pool_put(&scsi_plug_pool, p); 204 205 scsi_detach(sb, target, lun, how); 206 } 207 208 int 209 scsi_pending_start(struct mutex *mtx, u_int *running) 210 { 211 int rv = 1; 212 213 mtx_enter(mtx); 214 (*running)++; 215 if ((*running) > 1) 216 rv = 0; 217 mtx_leave(mtx); 218 219 return rv; 220 } 221 222 int 223 scsi_pending_finish(struct mutex *mtx, u_int *running) 224 { 225 int rv = 1; 226 227 mtx_enter(mtx); 228 (*running)--; 229 if ((*running) > 0) { 230 (*running) = 1; 231 rv = 0; 232 } 233 mtx_leave(mtx); 234 235 return rv; 236 } 237 238 void 239 scsi_iopool_init(struct scsi_iopool *iopl, void *iocookie, 240 void *(*io_get)(void *), void (*io_put)(void *, void *)) 241 { 242 iopl->iocookie = iocookie; 243 iopl->io_get = io_get; 244 iopl->io_put = io_put; 245 246 TAILQ_INIT(&iopl->queue); 247 iopl->running = 0; 248 mtx_init(&iopl->mtx, IPL_BIO); 249 } 250 251 void * 252 scsi_iopool_get(struct scsi_iopool *iopl) 253 { 254 void *io; 255 256 KERNEL_LOCK(); 257 io = iopl->io_get(iopl->iocookie); 258 KERNEL_UNLOCK(); 259 260 return io; 261 } 262 263 void 264 scsi_iopool_put(struct scsi_iopool *iopl, void *io) 265 { 266 KERNEL_LOCK(); 267 iopl->io_put(iopl->iocookie, io); 268 KERNEL_UNLOCK(); 269 } 270 271 void 272 scsi_iopool_destroy(struct scsi_iopool *iopl) 273 { 274 struct scsi_runq sleepers = TAILQ_HEAD_INITIALIZER(sleepers); 275 struct scsi_iohandler *ioh = NULL; 276 277 mtx_enter(&iopl->mtx); 278 while ((ioh = TAILQ_FIRST(&iopl->queue)) != NULL) { 279 TAILQ_REMOVE(&iopl->queue, ioh, q_entry); 280 ioh->q_state = RUNQ_IDLE; 281 282 if (ioh->handler == scsi_io_get_done) 283 TAILQ_INSERT_TAIL(&sleepers, ioh, q_entry); 284 #ifdef DIAGNOSTIC 285 else 286 panic("scsi_iopool_destroy: scsi_iohandler on pool"); 287 #endif /* DIAGNOSTIC */ 288 } 289 mtx_leave(&iopl->mtx); 290 291 while ((ioh = TAILQ_FIRST(&sleepers)) != NULL) { 292 TAILQ_REMOVE(&sleepers, ioh, q_entry); 293 ioh->handler(ioh->cookie, NULL); 294 } 295 } 296 297 void * 298 scsi_default_get(void *iocookie) 299 { 300 return SCSI_IOPOOL_POISON; 301 } 302 303 void 304 scsi_default_put(void *iocookie, void *io) 305 { 306 #ifdef DIAGNOSTIC 307 if (io != SCSI_IOPOOL_POISON) 308 panic("unexpected opening returned"); 309 #endif /* DIAGNOSTIC */ 310 } 311 312 /* 313 * public interface to the ioh api. 314 */ 315 316 void 317 scsi_ioh_set(struct scsi_iohandler *ioh, struct scsi_iopool *iopl, 318 void (*handler)(void *, void *), void *cookie) 319 { 320 ioh->q_state = RUNQ_IDLE; 321 ioh->pool = iopl; 322 ioh->handler = handler; 323 ioh->cookie = cookie; 324 } 325 326 int 327 scsi_ioh_add(struct scsi_iohandler *ioh) 328 { 329 struct scsi_iopool *iopl = ioh->pool; 330 int rv = 0; 331 332 mtx_enter(&iopl->mtx); 333 switch (ioh->q_state) { 334 case RUNQ_IDLE: 335 TAILQ_INSERT_TAIL(&iopl->queue, ioh, q_entry); 336 ioh->q_state = RUNQ_POOLQ; 337 rv = 1; 338 break; 339 #ifdef DIAGNOSTIC 340 case RUNQ_POOLQ: 341 break; 342 default: 343 panic("scsi_ioh_add: unexpected state %u", ioh->q_state); 344 #endif /* DIAGNOSTIC */ 345 } 346 mtx_leave(&iopl->mtx); 347 348 /* lets get some io up in the air */ 349 scsi_iopool_run(iopl); 350 351 return rv; 352 } 353 354 int 355 scsi_ioh_del(struct scsi_iohandler *ioh) 356 { 357 struct scsi_iopool *iopl = ioh->pool; 358 int rv = 0; 359 360 mtx_enter(&iopl->mtx); 361 switch (ioh->q_state) { 362 case RUNQ_POOLQ: 363 TAILQ_REMOVE(&iopl->queue, ioh, q_entry); 364 ioh->q_state = RUNQ_IDLE; 365 rv = 1; 366 break; 367 #ifdef DIAGNOSTIC 368 case RUNQ_IDLE: 369 break; 370 default: 371 panic("scsi_ioh_del: unexpected state %u", ioh->q_state); 372 #endif /* DIAGNOSTIC */ 373 } 374 mtx_leave(&iopl->mtx); 375 376 return rv; 377 } 378 379 /* 380 * internal iopool runqueue handling. 381 */ 382 383 struct scsi_iohandler * 384 scsi_ioh_deq(struct scsi_iopool *iopl) 385 { 386 struct scsi_iohandler *ioh = NULL; 387 388 mtx_enter(&iopl->mtx); 389 ioh = TAILQ_FIRST(&iopl->queue); 390 if (ioh != NULL) { 391 TAILQ_REMOVE(&iopl->queue, ioh, q_entry); 392 ioh->q_state = RUNQ_IDLE; 393 } 394 mtx_leave(&iopl->mtx); 395 396 return ioh; 397 } 398 399 int 400 scsi_ioh_pending(struct scsi_iopool *iopl) 401 { 402 int rv; 403 404 mtx_enter(&iopl->mtx); 405 rv = !TAILQ_EMPTY(&iopl->queue); 406 mtx_leave(&iopl->mtx); 407 408 return rv; 409 } 410 411 void 412 scsi_iopool_run(struct scsi_iopool *iopl) 413 { 414 struct scsi_iohandler *ioh; 415 void *io; 416 417 if (!scsi_pending_start(&iopl->mtx, &iopl->running)) 418 return; 419 do { 420 while (scsi_ioh_pending(iopl)) { 421 io = scsi_iopool_get(iopl); 422 if (io == NULL) 423 break; 424 425 ioh = scsi_ioh_deq(iopl); 426 if (ioh == NULL) { 427 scsi_iopool_put(iopl, io); 428 break; 429 } 430 431 ioh->handler(ioh->cookie, io); 432 } 433 } while (!scsi_pending_finish(&iopl->mtx, &iopl->running)); 434 } 435 436 /* 437 * move an io from a runq to a proc thats waiting for an io. 438 */ 439 440 void 441 scsi_move(struct scsi_io_mover *m) 442 { 443 mtx_enter(&m->mtx); 444 while (!m->done) 445 msleep_nsec(m, &m->mtx, PRIBIO, "scsiiomv", INFSLP); 446 mtx_leave(&m->mtx); 447 } 448 449 void 450 scsi_move_done(void *cookie, void *io) 451 { 452 struct scsi_io_mover *m = cookie; 453 454 mtx_enter(&m->mtx); 455 m->io = io; 456 m->done = 1; 457 wakeup_one(m); 458 mtx_leave(&m->mtx); 459 } 460 461 /* 462 * synchronous api for allocating an io. 463 */ 464 465 void * 466 scsi_io_get(struct scsi_iopool *iopl, int flags) 467 { 468 struct scsi_io_mover m = SCSI_IO_MOVER_INITIALIZER; 469 struct scsi_iohandler ioh; 470 void *io; 471 472 /* try and sneak an io off the backend immediately */ 473 io = scsi_iopool_get(iopl); 474 if (io != NULL) 475 return io; 476 else if (ISSET(flags, SCSI_NOSLEEP)) 477 return NULL; 478 479 /* otherwise sleep until we get one */ 480 scsi_ioh_set(&ioh, iopl, scsi_io_get_done, &m); 481 scsi_ioh_add(&ioh); 482 scsi_move(&m); 483 484 return m.io; 485 } 486 487 void 488 scsi_io_get_done(void *cookie, void *io) 489 { 490 scsi_move_done(cookie, io); 491 } 492 493 void 494 scsi_io_put(struct scsi_iopool *iopl, void *io) 495 { 496 scsi_iopool_put(iopl, io); 497 scsi_iopool_run(iopl); 498 } 499 500 /* 501 * public interface to the xsh api. 502 */ 503 504 void 505 scsi_xsh_set(struct scsi_xshandler *xsh, struct scsi_link *link, 506 void (*handler)(struct scsi_xfer *)) 507 { 508 scsi_ioh_set(&xsh->ioh, link->pool, scsi_xsh_ioh, xsh); 509 510 xsh->link = link; 511 xsh->handler = handler; 512 } 513 514 int 515 scsi_xsh_add(struct scsi_xshandler *xsh) 516 { 517 struct scsi_link *link = xsh->link; 518 int rv = 0; 519 520 if (ISSET(link->state, SDEV_S_DYING)) 521 return 0; 522 523 mtx_enter(&link->pool->mtx); 524 if (xsh->ioh.q_state == RUNQ_IDLE) { 525 TAILQ_INSERT_TAIL(&link->queue, &xsh->ioh, q_entry); 526 xsh->ioh.q_state = RUNQ_LINKQ; 527 rv = 1; 528 } 529 mtx_leave(&link->pool->mtx); 530 531 /* lets get some io up in the air */ 532 scsi_xsh_runqueue(link); 533 534 return rv; 535 } 536 537 int 538 scsi_xsh_del(struct scsi_xshandler *xsh) 539 { 540 struct scsi_link *link = xsh->link; 541 int rv = 1; 542 543 mtx_enter(&link->pool->mtx); 544 switch (xsh->ioh.q_state) { 545 case RUNQ_IDLE: 546 rv = 0; 547 break; 548 case RUNQ_LINKQ: 549 TAILQ_REMOVE(&link->queue, &xsh->ioh, q_entry); 550 break; 551 case RUNQ_POOLQ: 552 TAILQ_REMOVE(&link->pool->queue, &xsh->ioh, q_entry); 553 link->pending--; 554 if (ISSET(link->state, SDEV_S_DYING) && link->pending == 0) 555 wakeup_one(&link->pending); 556 break; 557 default: 558 panic("unexpected xsh state %u", xsh->ioh.q_state); 559 } 560 xsh->ioh.q_state = RUNQ_IDLE; 561 mtx_leave(&link->pool->mtx); 562 563 return rv; 564 } 565 566 /* 567 * internal xs runqueue handling. 568 */ 569 570 void 571 scsi_xsh_runqueue(struct scsi_link *link) 572 { 573 struct scsi_iohandler *ioh; 574 int runq; 575 576 if (!scsi_pending_start(&link->pool->mtx, &link->running)) 577 return; 578 do { 579 runq = 0; 580 581 mtx_enter(&link->pool->mtx); 582 while (!ISSET(link->state, SDEV_S_DYING) && 583 link->pending < link->openings && 584 ((ioh = TAILQ_FIRST(&link->queue)) != NULL)) { 585 link->pending++; 586 587 TAILQ_REMOVE(&link->queue, ioh, q_entry); 588 TAILQ_INSERT_TAIL(&link->pool->queue, ioh, q_entry); 589 ioh->q_state = RUNQ_POOLQ; 590 591 runq = 1; 592 } 593 mtx_leave(&link->pool->mtx); 594 595 if (runq) 596 scsi_iopool_run(link->pool); 597 } while (!scsi_pending_finish(&link->pool->mtx, &link->running)); 598 } 599 600 void 601 scsi_xsh_ioh(void *cookie, void *io) 602 { 603 struct scsi_xshandler *xsh = cookie; 604 struct scsi_xfer *xs; 605 606 xs = scsi_xs_io(xsh->link, io, SCSI_NOSLEEP); 607 if (xs == NULL) { 608 /* 609 * in this situation we should queue things waiting for an 610 * xs and then give them xses when they were supposed be to 611 * returned to the pool. 612 */ 613 614 printf("scsi_xfer pool exhausted!\n"); 615 scsi_xsh_add(xsh); 616 return; 617 } 618 619 xsh->handler(xs); 620 } 621 622 /* 623 * Get a scsi transfer structure for the caller. 624 * Go to the iopool backend for an "opening" and then attach an xs to it. 625 */ 626 627 struct scsi_xfer * 628 scsi_xs_get(struct scsi_link *link, int flags) 629 { 630 struct scsi_xshandler xsh; 631 struct scsi_io_mover m = SCSI_IO_MOVER_INITIALIZER; 632 struct scsi_iopool *iopl = link->pool; 633 void *io; 634 635 if (ISSET(link->state, SDEV_S_DYING)) 636 return NULL; 637 638 /* really custom xs handler to avoid scsi_xsh_ioh */ 639 scsi_ioh_set(&xsh.ioh, iopl, scsi_xs_get_done, &m); 640 xsh.link = link; 641 642 if (!scsi_link_open(link)) { 643 if (ISSET(flags, SCSI_NOSLEEP)) 644 return NULL; 645 646 scsi_xsh_add(&xsh); 647 scsi_move(&m); 648 if (m.io == NULL) 649 return NULL; 650 651 io = m.io; 652 } else if ((io = scsi_iopool_get(iopl)) == NULL) { 653 if (ISSET(flags, SCSI_NOSLEEP)) { 654 scsi_link_close(link); 655 return NULL; 656 } 657 658 scsi_ioh_add(&xsh.ioh); 659 scsi_move(&m); 660 if (m.io == NULL) 661 return NULL; 662 663 io = m.io; 664 } 665 666 return scsi_xs_io(link, io, flags); 667 } 668 669 void 670 scsi_xs_get_done(void *cookie, void *io) 671 { 672 scsi_move_done(cookie, io); 673 } 674 675 void 676 scsi_link_shutdown(struct scsi_link *link) 677 { 678 struct scsi_runq sleepers = TAILQ_HEAD_INITIALIZER(sleepers); 679 struct scsi_iopool *iopl = link->pool; 680 struct scsi_iohandler *ioh; 681 struct scsi_xshandler *xsh; 682 683 mtx_enter(&iopl->mtx); 684 while ((ioh = TAILQ_FIRST(&link->queue)) != NULL) { 685 TAILQ_REMOVE(&link->queue, ioh, q_entry); 686 ioh->q_state = RUNQ_IDLE; 687 688 if (ioh->handler == scsi_xs_get_done) 689 TAILQ_INSERT_TAIL(&sleepers, ioh, q_entry); 690 #ifdef DIAGNOSTIC 691 else 692 panic("scsi_link_shutdown: scsi_xshandler on link"); 693 #endif /* DIAGNOSTIC */ 694 } 695 696 ioh = TAILQ_FIRST(&iopl->queue); 697 while (ioh != NULL) { 698 xsh = (struct scsi_xshandler *)ioh; 699 ioh = TAILQ_NEXT(ioh, q_entry); 700 701 #ifdef DIAGNOSTIC 702 if (xsh->ioh.handler == scsi_xsh_ioh && 703 xsh->link == link) 704 panic("scsi_link_shutdown: scsi_xshandler on pool"); 705 #endif /* DIAGNOSTIC */ 706 707 if (xsh->ioh.handler == scsi_xs_get_done && 708 xsh->link == link) { 709 TAILQ_REMOVE(&iopl->queue, &xsh->ioh, q_entry); 710 xsh->ioh.q_state = RUNQ_IDLE; 711 link->pending--; 712 713 TAILQ_INSERT_TAIL(&sleepers, &xsh->ioh, q_entry); 714 } 715 } 716 717 while (link->pending > 0) 718 msleep_nsec(&link->pending, &iopl->mtx, PRIBIO, "pendxs", 719 INFSLP); 720 mtx_leave(&iopl->mtx); 721 722 while ((ioh = TAILQ_FIRST(&sleepers)) != NULL) { 723 TAILQ_REMOVE(&sleepers, ioh, q_entry); 724 ioh->handler(ioh->cookie, NULL); 725 } 726 } 727 728 int 729 scsi_link_open(struct scsi_link *link) 730 { 731 int open = 0; 732 733 mtx_enter(&link->pool->mtx); 734 if (link->pending < link->openings) { 735 link->pending++; 736 open = 1; 737 } 738 mtx_leave(&link->pool->mtx); 739 740 return open; 741 } 742 743 void 744 scsi_link_close(struct scsi_link *link) 745 { 746 mtx_enter(&link->pool->mtx); 747 link->pending--; 748 if (ISSET(link->state, SDEV_S_DYING) && link->pending == 0) 749 wakeup_one(&link->pending); 750 mtx_leave(&link->pool->mtx); 751 752 scsi_xsh_runqueue(link); 753 } 754 755 struct scsi_xfer * 756 scsi_xs_io(struct scsi_link *link, void *io, int flags) 757 { 758 struct scsi_xfer *xs; 759 760 xs = pool_get(&scsi_xfer_pool, PR_ZERO | 761 (ISSET(flags, SCSI_NOSLEEP) ? PR_NOWAIT : PR_WAITOK)); 762 if (xs == NULL) { 763 scsi_io_put(link->pool, io); 764 scsi_link_close(link); 765 } else { 766 xs->flags = flags; 767 xs->sc_link = link; 768 xs->retries = SCSI_RETRIES; 769 xs->timeout = 10000; 770 xs->cmd = &xs->cmdstore; 771 xs->io = io; 772 } 773 774 return xs; 775 } 776 777 void 778 scsi_xs_put(struct scsi_xfer *xs) 779 { 780 struct scsi_link *link = xs->sc_link; 781 void *io = xs->io; 782 783 pool_put(&scsi_xfer_pool, xs); 784 785 scsi_io_put(link->pool, io); 786 scsi_link_close(link); 787 } 788 789 /* 790 * Get scsi driver to send a "are you ready?" command 791 */ 792 int 793 scsi_test_unit_ready(struct scsi_link *link, int retries, int flags) 794 { 795 struct scsi_test_unit_ready *cmd; 796 struct scsi_xfer *xs; 797 int error; 798 799 xs = scsi_xs_get(link, flags); 800 if (xs == NULL) 801 return ENOMEM; 802 xs->cmdlen = sizeof(*cmd); 803 xs->retries = retries; 804 xs->timeout = 10000; 805 806 cmd = (struct scsi_test_unit_ready *)xs->cmd; 807 cmd->opcode = TEST_UNIT_READY; 808 809 error = scsi_xs_sync(xs); 810 scsi_xs_put(xs); 811 812 return error; 813 } 814 815 void 816 scsi_init_inquiry(struct scsi_xfer *xs, u_int8_t flags, u_int8_t pagecode, 817 void *data, size_t len) 818 { 819 struct scsi_inquiry *cmd; 820 821 cmd = (struct scsi_inquiry *)xs->cmd; 822 cmd->opcode = INQUIRY; 823 cmd->flags = flags; 824 cmd->pagecode = pagecode; 825 _lto2b(len, cmd->length); 826 827 xs->cmdlen = sizeof(*cmd); 828 829 SET(xs->flags, SCSI_DATA_IN); 830 xs->data = data; 831 xs->datalen = len; 832 } 833 834 /* 835 * Do a scsi operation asking a device what it is. 836 * Use the scsi_cmd routine in the switch table. 837 */ 838 int 839 scsi_inquire(struct scsi_link *link, struct scsi_inquiry_data *inqbuf, 840 int flags) 841 { 842 struct scsi_xfer *xs; 843 size_t bytes; 844 int error; 845 846 /* 847 * Start by asking for only the basic 36 bytes of SCSI2 inquiry 848 * information. This avoids problems with devices that choke trying to 849 * supply more. 850 */ 851 bytes = 36; 852 853 #ifdef SCSIDEBUG 854 again: 855 #endif /* SCSIDEBUG */ 856 xs = scsi_xs_get(link, flags); 857 if (xs == NULL) 858 return EBUSY; 859 860 scsi_init_inquiry(xs, 0, 0, inqbuf, bytes); 861 862 bzero(inqbuf, sizeof(*inqbuf)); 863 memset(&inqbuf->vendor, ' ', sizeof inqbuf->vendor); 864 memset(&inqbuf->product, ' ', sizeof inqbuf->product); 865 memset(&inqbuf->revision, ' ', sizeof inqbuf->revision); 866 memset(&inqbuf->extra, ' ', sizeof inqbuf->extra); 867 868 error = scsi_xs_sync(xs); 869 870 scsi_xs_put(xs); 871 872 #ifdef SCSIDEBUG 873 sc_print_addr(link); 874 if (bytes > inqbuf->additional_length + 4) 875 bytes = inqbuf->additional_length + 4; 876 printf("got %zu of %u bytes of inquiry data:\n", 877 bytes, inqbuf->additional_length + 4); 878 scsi_show_mem((u_char *)inqbuf, bytes); 879 if (bytes == 36 && bytes < inqbuf->additional_length + 4) { 880 bytes = inqbuf->additional_length + 4; 881 if (bytes > sizeof(*inqbuf)) 882 bytes = sizeof(*inqbuf); 883 goto again; 884 } 885 #endif /* SCSIDEBUG */ 886 return error; 887 } 888 889 /* 890 * Query a VPD inquiry page 891 */ 892 int 893 scsi_inquire_vpd(struct scsi_link *link, void *buf, u_int buflen, 894 u_int8_t page, int flags) 895 { 896 struct scsi_xfer *xs; 897 int error; 898 #ifdef SCSIDEBUG 899 u_int32_t bytes; 900 #endif /* SCSIDEBUG */ 901 902 if (ISSET(link->flags, SDEV_UMASS)) 903 return EJUSTRETURN; 904 905 xs = scsi_xs_get(link, flags | SCSI_DATA_IN | SCSI_SILENT); 906 if (xs == NULL) 907 return ENOMEM; 908 909 xs->retries = 2; 910 xs->timeout = 10000; 911 912 scsi_init_inquiry(xs, SI_EVPD, page, buf, buflen); 913 914 error = scsi_xs_sync(xs); 915 916 scsi_xs_put(xs); 917 #ifdef SCSIDEBUG 918 sc_print_addr(link); 919 if (error == 0) { 920 bytes = sizeof(struct scsi_vpd_hdr) + 921 _2btol(((struct scsi_vpd_hdr *)buf)->page_length); 922 if (bytes < buflen) 923 buflen = bytes; 924 printf("got %u of %u bytes of VPD inquiry page %u data:\n", 925 buflen, bytes, page); 926 scsi_show_mem(buf, buflen); 927 } else { 928 printf("VPD inquiry page %u not available\n", page); 929 } 930 #endif /* SCSIDEBUG */ 931 return error; 932 } 933 934 int 935 scsi_read_cap_10(struct scsi_link *link, struct scsi_read_cap_data *rdcap, 936 int flags) 937 { 938 struct scsi_read_capacity cdb; 939 struct scsi_xfer *xs; 940 int rv; 941 942 xs = scsi_xs_get(link, flags | SCSI_DATA_IN | SCSI_SILENT); 943 if (xs == NULL) 944 return ENOMEM; 945 946 memset(&cdb, 0, sizeof(cdb)); 947 cdb.opcode = READ_CAPACITY; 948 949 memcpy(xs->cmd, &cdb, sizeof(cdb)); 950 xs->cmdlen = sizeof(cdb); 951 xs->data = (void *)rdcap; 952 xs->datalen = sizeof(*rdcap); 953 xs->timeout = 20000; 954 955 rv = scsi_xs_sync(xs); 956 scsi_xs_put(xs); 957 958 #ifdef SCSIDEBUG 959 if (rv == 0) { 960 sc_print_addr(link); 961 printf("read capacity 10 data:\n"); 962 scsi_show_mem((u_char *)rdcap, sizeof(*rdcap)); 963 } 964 #endif /* SCSIDEBUG */ 965 966 return rv; 967 } 968 969 int 970 scsi_read_cap_16(struct scsi_link *link, struct scsi_read_cap_data_16 *rdcap, 971 int flags) 972 { 973 struct scsi_read_capacity_16 cdb; 974 struct scsi_xfer *xs; 975 int rv; 976 977 xs = scsi_xs_get(link, flags | SCSI_DATA_IN | SCSI_SILENT); 978 if (xs == NULL) 979 return ENOMEM; 980 981 memset(&cdb, 0, sizeof(cdb)); 982 cdb.opcode = READ_CAPACITY_16; 983 cdb.byte2 = SRC16_SERVICE_ACTION; 984 _lto4b(sizeof(*rdcap), cdb.length); 985 986 memcpy(xs->cmd, &cdb, sizeof(cdb)); 987 xs->cmdlen = sizeof(cdb); 988 xs->data = (void *)rdcap; 989 xs->datalen = sizeof(*rdcap); 990 xs->timeout = 20000; 991 992 rv = scsi_xs_sync(xs); 993 scsi_xs_put(xs); 994 995 #ifdef SCSIDEBUG 996 if (rv == 0) { 997 sc_print_addr(link); 998 printf("read capacity 16 data:\n"); 999 scsi_show_mem((u_char *)rdcap, sizeof(*rdcap)); 1000 } 1001 #endif /* SCSIDEBUG */ 1002 1003 return rv; 1004 } 1005 1006 /* 1007 * Prevent or allow the user to remove the media 1008 */ 1009 int 1010 scsi_prevent(struct scsi_link *link, int type, int flags) 1011 { 1012 struct scsi_prevent *cmd; 1013 struct scsi_xfer *xs; 1014 int error; 1015 1016 if (ISSET(link->quirks, ADEV_NODOORLOCK)) 1017 return 0; 1018 1019 xs = scsi_xs_get(link, flags); 1020 if (xs == NULL) 1021 return ENOMEM; 1022 xs->cmdlen = sizeof(*cmd); 1023 xs->retries = 2; 1024 xs->timeout = 5000; 1025 1026 cmd = (struct scsi_prevent *)xs->cmd; 1027 cmd->opcode = PREVENT_ALLOW; 1028 cmd->how = type; 1029 1030 error = scsi_xs_sync(xs); 1031 scsi_xs_put(xs); 1032 1033 return error; 1034 } 1035 1036 /* 1037 * Get scsi driver to send a "start up" command 1038 */ 1039 int 1040 scsi_start(struct scsi_link *link, int type, int flags) 1041 { 1042 struct scsi_start_stop *cmd; 1043 struct scsi_xfer *xs; 1044 int error; 1045 1046 xs = scsi_xs_get(link, flags); 1047 if (xs == NULL) 1048 return ENOMEM; 1049 xs->cmdlen = sizeof(*cmd); 1050 xs->retries = 2; 1051 xs->timeout = (type == SSS_START) ? 30000 : 10000; 1052 1053 cmd = (struct scsi_start_stop *)xs->cmd; 1054 cmd->opcode = START_STOP; 1055 cmd->how = type; 1056 1057 error = scsi_xs_sync(xs); 1058 scsi_xs_put(xs); 1059 1060 return error; 1061 } 1062 1063 int 1064 scsi_mode_sense(struct scsi_link *link, int pg_code, 1065 union scsi_mode_sense_buf *data, int flags) 1066 { 1067 struct scsi_mode_sense *cmd; 1068 struct scsi_xfer *xs; 1069 size_t len; 1070 int error; 1071 #ifdef SCSIDEBUG 1072 size_t bytes; 1073 #endif /* SCSIDEBUG */ 1074 1075 len = sizeof(*data); 1076 1077 xs = scsi_xs_get(link, flags | SCSI_DATA_IN); 1078 if (xs == NULL) 1079 return ENOMEM; 1080 xs->cmdlen = sizeof(*cmd); 1081 xs->data = (void *)data; 1082 xs->datalen = len; 1083 xs->timeout = 20000; 1084 1085 /* 1086 * Make sure the sense buffer is clean before we do the mode sense, so 1087 * that checks for bogus values of 0 will work in case the mode sense 1088 * fails. 1089 */ 1090 memset(data, 0, len); 1091 1092 cmd = (struct scsi_mode_sense *)xs->cmd; 1093 cmd->opcode = MODE_SENSE; 1094 cmd->page = pg_code; 1095 1096 if (len > 0xff) 1097 len = 0xff; 1098 cmd->length = len; 1099 1100 error = scsi_xs_sync(xs); 1101 scsi_xs_put(xs); 1102 1103 #ifdef SCSIDEBUG 1104 sc_print_addr(link); 1105 if (error == 0) { 1106 bytes = sizeof(data->hdr.data_length) + data->hdr.data_length; 1107 if (bytes < len) 1108 len = bytes; 1109 printf("got %zu of %zu bytes of mode sense (6) page %d data:\n", 1110 len, bytes, pg_code); 1111 scsi_show_mem((u_char *)data, len); 1112 } else 1113 printf("mode sense (6) page %d not available\n", pg_code); 1114 #endif /* SCSIDEBUG */ 1115 1116 return error; 1117 } 1118 1119 int 1120 scsi_mode_sense_big(struct scsi_link *link, int pg_code, 1121 union scsi_mode_sense_buf *data, int flags) 1122 { 1123 struct scsi_mode_sense_big *cmd; 1124 struct scsi_xfer *xs; 1125 size_t len; 1126 int error; 1127 #ifdef SCSIDEBUG 1128 size_t bytes; 1129 #endif /* SCSIDEBUG */ 1130 1131 len = sizeof(*data); 1132 1133 xs = scsi_xs_get(link, flags | SCSI_DATA_IN); 1134 if (xs == NULL) 1135 return ENOMEM; 1136 xs->cmdlen = sizeof(*cmd); 1137 xs->data = (void *)data; 1138 xs->datalen = len; 1139 xs->timeout = 20000; 1140 1141 /* 1142 * Make sure the sense buffer is clean before we do the mode sense, so 1143 * that checks for bogus values of 0 will work in case the mode sense 1144 * fails. 1145 */ 1146 memset(data, 0, len); 1147 1148 cmd = (struct scsi_mode_sense_big *)xs->cmd; 1149 cmd->opcode = MODE_SENSE_BIG; 1150 cmd->page = pg_code; 1151 1152 if (len > 0xffff) 1153 len = 0xffff; 1154 _lto2b(len, cmd->length); 1155 1156 error = scsi_xs_sync(xs); 1157 scsi_xs_put(xs); 1158 1159 if (_2btol(data->hdr_big.data_length) < 6) 1160 error = EIO; 1161 1162 #ifdef SCSIDEBUG 1163 sc_print_addr(link); 1164 if (error == 0) { 1165 bytes = sizeof(data->hdr_big.data_length) + 1166 _2btol(data->hdr_big.data_length); 1167 if (bytes < len) 1168 len = bytes; 1169 printf("got %zu bytes of %zu bytes of mode sense (10) page %d " 1170 "data:\n", len, bytes, pg_code); 1171 scsi_show_mem((u_char *)data, len); 1172 } else 1173 printf("mode sense (10) page %d not available\n", pg_code); 1174 #endif /* SCSIDEBUG */ 1175 1176 return error; 1177 } 1178 1179 void * 1180 scsi_mode_sense_page(struct scsi_mode_header *hdr, int pg_code, int pg_length) 1181 { 1182 u_int8_t *page; 1183 int total_length, header_length; 1184 1185 total_length = hdr->data_length + sizeof(hdr->data_length); 1186 header_length = sizeof(*hdr) + hdr->blk_desc_len; 1187 page = (u_int8_t *)hdr + header_length; 1188 1189 if ((total_length - header_length) < pg_length) 1190 return NULL; 1191 1192 if ((*page & SMS_PAGE_CODE) != pg_code) 1193 return NULL; 1194 1195 return page; 1196 } 1197 1198 void * 1199 scsi_mode_sense_big_page(struct scsi_mode_header_big *hdr, int pg_code, 1200 int pg_length) 1201 { 1202 u_int8_t *page; 1203 int total_length, header_length; 1204 1205 total_length = _2btol(hdr->data_length) + sizeof(hdr->data_length); 1206 header_length = sizeof(*hdr) + _2btol(hdr->blk_desc_len); 1207 page = (u_int8_t *)hdr + header_length; 1208 1209 if ((total_length - header_length) < pg_length) 1210 return NULL; 1211 1212 if ((*page & SMS_PAGE_CODE) != pg_code) 1213 return NULL; 1214 1215 return page; 1216 } 1217 1218 void 1219 scsi_parse_blkdesc(struct scsi_link *link, union scsi_mode_sense_buf *buf, 1220 int big, u_int32_t *density, u_int64_t *block_count, u_int32_t *block_size) 1221 { 1222 struct scsi_direct_blk_desc *direct; 1223 struct scsi_blk_desc *general; 1224 size_t offset; 1225 unsigned int blk_desc_len; 1226 1227 if (big == 0) { 1228 offset = sizeof(struct scsi_mode_header); 1229 blk_desc_len = buf->hdr.blk_desc_len; 1230 } else { 1231 offset = sizeof(struct scsi_mode_header_big); 1232 blk_desc_len = _2btol(buf->hdr_big.blk_desc_len); 1233 } 1234 1235 /* Both scsi_blk_desc and scsi_direct_blk_desc are 8 bytes. */ 1236 if (blk_desc_len == 0 || (blk_desc_len % 8 != 0)) 1237 return; 1238 1239 switch (link->inqdata.device & SID_TYPE) { 1240 case T_SEQUENTIAL: 1241 /* 1242 * XXX What other device types return general block descriptors? 1243 */ 1244 general = (struct scsi_blk_desc *)&buf->buf[offset]; 1245 if (density != NULL) 1246 *density = general->density; 1247 if (block_size != NULL) 1248 *block_size = _3btol(general->blklen); 1249 if (block_count != NULL) 1250 *block_count = (u_int64_t)_3btol(general->nblocks); 1251 break; 1252 1253 default: 1254 direct = (struct scsi_direct_blk_desc *)&buf->buf[offset]; 1255 if (density != NULL) 1256 *density = direct->density; 1257 if (block_size != NULL) 1258 *block_size = _3btol(direct->blklen); 1259 if (block_count != NULL) 1260 *block_count = (u_int64_t)_4btol(direct->nblocks); 1261 break; 1262 } 1263 } 1264 1265 int 1266 scsi_do_mode_sense(struct scsi_link *link, int pg_code, 1267 union scsi_mode_sense_buf *buf, void **page_data, 1268 int pg_length, int flags, int *big) 1269 { 1270 int error = 0; 1271 1272 *page_data = NULL; 1273 *big = 0; 1274 1275 if (!ISSET(link->flags, SDEV_ATAPI) || 1276 (link->inqdata.device & SID_TYPE) == T_SEQUENTIAL) { 1277 /* 1278 * Try 6 byte mode sense request first. Some devices don't 1279 * distinguish between 6 and 10 byte MODE SENSE commands, 1280 * returning 6 byte data for 10 byte requests. ATAPI tape 1281 * drives use MODE SENSE (6) even though ATAPI uses 10 byte 1282 * everything else. Don't bother with SMS_DBD. Check returned 1283 * data length to ensure that at least a header (3 additional 1284 * bytes) is returned. 1285 */ 1286 error = scsi_mode_sense(link, pg_code, buf, flags); 1287 if (error == 0) { 1288 /* 1289 * Page data may be invalid (e.g. all zeros) but we 1290 * accept the device's word that this is the best it can 1291 * do. Some devices will freak out if their word is not 1292 * accepted and MODE_SENSE_BIG is attempted. 1293 */ 1294 *page_data = scsi_mode_sense_page(&buf->hdr, pg_code, 1295 pg_length); 1296 return 0; 1297 } 1298 } 1299 1300 /* 1301 * non-ATAPI, non-USB devices that don't support SCSI-2 commands 1302 * (i.e. MODE SENSE (10)) are done. 1303 */ 1304 if ((link->flags & (SDEV_ATAPI | SDEV_UMASS)) == 0 && 1305 SID_ANSII_REV(&link->inqdata) < SCSI_REV_2) 1306 return error; 1307 1308 /* 1309 * Try 10 byte mode sense request. 1310 */ 1311 error = scsi_mode_sense_big(link, pg_code, buf, flags); 1312 if (error != 0) 1313 return error; 1314 1315 *big = 1; 1316 *page_data = scsi_mode_sense_big_page(&buf->hdr_big, pg_code, 1317 pg_length); 1318 1319 return 0; 1320 } 1321 1322 int 1323 scsi_mode_select(struct scsi_link *link, int byte2, 1324 struct scsi_mode_header *data, int flags, int timeout) 1325 { 1326 struct scsi_mode_select *cmd; 1327 struct scsi_xfer *xs; 1328 int error; 1329 u_int32_t len; 1330 1331 len = data->data_length + 1; /* 1 == sizeof(data_length) */ 1332 1333 xs = scsi_xs_get(link, flags | SCSI_DATA_OUT); 1334 if (xs == NULL) 1335 return ENOMEM; 1336 xs->cmdlen = sizeof(*cmd); 1337 xs->data = (void *)data; 1338 xs->datalen = len; 1339 xs->timeout = timeout; 1340 1341 cmd = (struct scsi_mode_select *)xs->cmd; 1342 cmd->opcode = MODE_SELECT; 1343 cmd->byte2 = byte2; 1344 cmd->length = len; 1345 1346 /* Length is reserved when doing mode select so zero it. */ 1347 data->data_length = 0; 1348 1349 error = scsi_xs_sync(xs); 1350 scsi_xs_put(xs); 1351 1352 SC_DEBUG(link, SDEV_DB2, ("scsi_mode_select: error = %d\n", error)); 1353 1354 return error; 1355 } 1356 1357 int 1358 scsi_mode_select_big(struct scsi_link *link, int byte2, 1359 struct scsi_mode_header_big *data, int flags, int timeout) 1360 { 1361 struct scsi_mode_select_big *cmd; 1362 struct scsi_xfer *xs; 1363 int error; 1364 u_int32_t len; 1365 1366 len = _2btol(data->data_length) + 2; /* 2 == sizeof data_length */ 1367 1368 xs = scsi_xs_get(link, flags | SCSI_DATA_OUT); 1369 if (xs == NULL) 1370 return ENOMEM; 1371 xs->cmdlen = sizeof(*cmd); 1372 xs->data = (void *)data; 1373 xs->datalen = len; 1374 xs->timeout = timeout; 1375 1376 cmd = (struct scsi_mode_select_big *)xs->cmd; 1377 cmd->opcode = MODE_SELECT_BIG; 1378 cmd->byte2 = byte2; 1379 _lto2b(len, cmd->length); 1380 1381 /* Length is reserved when doing mode select so zero it. */ 1382 _lto2b(0, data->data_length); 1383 1384 error = scsi_xs_sync(xs); 1385 scsi_xs_put(xs); 1386 1387 SC_DEBUG(link, SDEV_DB2, ("scsi_mode_select_big: error = %d\n", 1388 error)); 1389 1390 return error; 1391 } 1392 1393 int 1394 scsi_report_luns(struct scsi_link *link, int selectreport, 1395 struct scsi_report_luns_data *data, u_int32_t datalen, int flags, 1396 int timeout) 1397 { 1398 struct scsi_report_luns *cmd; 1399 struct scsi_xfer *xs; 1400 int error; 1401 1402 xs = scsi_xs_get(link, flags | SCSI_DATA_IN); 1403 if (xs == NULL) 1404 return ENOMEM; 1405 xs->cmdlen = sizeof(*cmd); 1406 xs->data = (void *)data; 1407 xs->datalen = datalen; 1408 xs->timeout = timeout; 1409 1410 bzero(data, datalen); 1411 1412 cmd = (struct scsi_report_luns *)xs->cmd; 1413 cmd->opcode = REPORT_LUNS; 1414 cmd->selectreport = selectreport; 1415 _lto4b(datalen, cmd->length); 1416 1417 error = scsi_xs_sync(xs); 1418 scsi_xs_put(xs); 1419 1420 SC_DEBUG(link, SDEV_DB2, ("scsi_report_luns: error = %d\n", error)); 1421 1422 return error; 1423 } 1424 1425 void 1426 scsi_xs_exec(struct scsi_xfer *xs) 1427 { 1428 xs->error = XS_NOERROR; 1429 xs->resid = xs->datalen; 1430 xs->status = 0; 1431 CLR(xs->flags, ITSDONE); 1432 1433 #ifdef SCSIDEBUG 1434 scsi_show_xs(xs); 1435 #endif /* SCSIDEBUG */ 1436 1437 /* The adapter's scsi_cmd() is responsible for calling scsi_done(). */ 1438 KERNEL_LOCK(); 1439 xs->sc_link->adapter->scsi_cmd(xs); 1440 KERNEL_UNLOCK(); 1441 } 1442 1443 /* 1444 * This routine is called by the adapter when its xs handling is done. 1445 */ 1446 void 1447 scsi_done(struct scsi_xfer *xs) 1448 { 1449 #ifdef SCSIDEBUG 1450 if (ISSET(xs->sc_link->flags, SDEV_DB1)) { 1451 if (xs->datalen && ISSET(xs->flags, SCSI_DATA_IN)) 1452 scsi_show_mem(xs->data, min(64, xs->datalen)); 1453 } 1454 #endif /* SCSIDEBUG */ 1455 1456 SET(xs->flags, ITSDONE); 1457 KERNEL_LOCK(); 1458 xs->done(xs); 1459 KERNEL_UNLOCK(); 1460 } 1461 1462 int 1463 scsi_xs_sync(struct scsi_xfer *xs) 1464 { 1465 struct mutex cookie = MUTEX_INITIALIZER(IPL_BIO); 1466 int error; 1467 1468 #ifdef DIAGNOSTIC 1469 if (xs->cookie != NULL) 1470 panic("xs->cookie != NULL in scsi_xs_sync"); 1471 if (xs->done != NULL) 1472 panic("xs->done != NULL in scsi_xs_sync"); 1473 #endif /* DIAGNOSTIC */ 1474 1475 /* 1476 * If we cant sleep while waiting for completion, get the adapter to 1477 * complete it for us. 1478 */ 1479 if (ISSET(xs->flags, SCSI_NOSLEEP)) 1480 SET(xs->flags, SCSI_POLL); 1481 1482 xs->done = scsi_xs_sync_done; 1483 1484 do { 1485 xs->cookie = &cookie; 1486 1487 scsi_xs_exec(xs); 1488 1489 mtx_enter(&cookie); 1490 while (xs->cookie != NULL) 1491 msleep_nsec(xs, &cookie, PRIBIO, "syncxs", INFSLP); 1492 mtx_leave(&cookie); 1493 1494 error = scsi_xs_error(xs); 1495 } while (error == ERESTART); 1496 1497 return error; 1498 } 1499 1500 void 1501 scsi_xs_sync_done(struct scsi_xfer *xs) 1502 { 1503 struct mutex *cookie = xs->cookie; 1504 1505 if (cookie == NULL) 1506 panic("scsi_done called twice on xs(%p)", xs); 1507 1508 mtx_enter(cookie); 1509 xs->cookie = NULL; 1510 if (!ISSET(xs->flags, SCSI_NOSLEEP)) 1511 wakeup_one(xs); 1512 mtx_leave(cookie); 1513 } 1514 1515 int 1516 scsi_xs_error(struct scsi_xfer *xs) 1517 { 1518 int error = EIO; 1519 1520 SC_DEBUG(xs->sc_link, SDEV_DB3, ("scsi_xs_error,err = 0x%x\n", 1521 xs->error)); 1522 1523 if (ISSET(xs->sc_link->state, SDEV_S_DYING)) 1524 return ENXIO; 1525 1526 switch (xs->error) { 1527 case XS_NOERROR: /* nearly always hit this one */ 1528 error = 0; 1529 break; 1530 1531 case XS_SENSE: 1532 case XS_SHORTSENSE: 1533 SC_DEBUG_SENSE(xs); 1534 error = xs->sc_link->interpret_sense(xs); 1535 SC_DEBUG(xs->sc_link, SDEV_DB3, 1536 ("scsi_interpret_sense returned %#x\n", error)); 1537 break; 1538 1539 case XS_BUSY: 1540 error = scsi_delay(xs, 1); 1541 break; 1542 1543 case XS_TIMEOUT: 1544 case XS_RESET: 1545 error = ERESTART; 1546 break; 1547 1548 case XS_DRIVER_STUFFUP: 1549 case XS_SELTIMEOUT: 1550 break; 1551 1552 default: 1553 sc_print_addr(xs->sc_link); 1554 printf("unknown error category (0x%x) from scsi driver\n", 1555 xs->error); 1556 break; 1557 } 1558 1559 if (error == ERESTART && xs->retries-- < 1) 1560 return EIO; 1561 else 1562 return error; 1563 } 1564 1565 int 1566 scsi_delay(struct scsi_xfer *xs, int seconds) 1567 { 1568 int ret; 1569 1570 switch (xs->flags & (SCSI_POLL | SCSI_NOSLEEP)) { 1571 case SCSI_POLL: 1572 delay(1000000 * seconds); 1573 return ERESTART; 1574 case SCSI_NOSLEEP: 1575 /* Retry the command immediately since we can't delay. */ 1576 return ERESTART; 1577 case (SCSI_POLL | SCSI_NOSLEEP): 1578 /* Invalid combination! */ 1579 return EIO; 1580 } 1581 1582 ret = tsleep_nsec(&ret, PRIBIO|PCATCH, "scbusy", SEC_TO_NSEC(seconds)); 1583 1584 /* Signal == abort xs. */ 1585 if (ret == ERESTART || ret == EINTR) 1586 return EIO; 1587 1588 return ERESTART; 1589 } 1590 1591 /* 1592 * Look at the returned sense and act on the error, determining 1593 * the unix error number to pass back. (0 = report no error) 1594 * 1595 * THIS IS THE DEFAULT ERROR HANDLER 1596 */ 1597 int 1598 scsi_interpret_sense(struct scsi_xfer *xs) 1599 { 1600 struct scsi_sense_data *sense = &xs->sense; 1601 struct scsi_link *link = xs->sc_link; 1602 u_int8_t serr, skey; 1603 int error; 1604 1605 /* Default sense interpretation. */ 1606 serr = sense->error_code & SSD_ERRCODE; 1607 if (serr != SSD_ERRCODE_CURRENT && serr != SSD_ERRCODE_DEFERRED) 1608 skey = 0xff; /* Invalid value, since key is 4 bit value. */ 1609 else 1610 skey = sense->flags & SSD_KEY; 1611 1612 /* 1613 * Interpret the key/asc/ascq information where appropriate. 1614 */ 1615 error = 0; 1616 switch (skey) { 1617 case SKEY_NO_SENSE: 1618 case SKEY_RECOVERED_ERROR: 1619 if (xs->resid == xs->datalen) 1620 xs->resid = 0; /* not short read */ 1621 break; 1622 case SKEY_BLANK_CHECK: 1623 case SKEY_EQUAL: 1624 break; 1625 case SKEY_NOT_READY: 1626 if (ISSET(xs->flags, SCSI_IGNORE_NOT_READY)) 1627 return 0; 1628 error = EIO; 1629 if (xs->retries) { 1630 switch (ASC_ASCQ(sense)) { 1631 case SENSE_NOT_READY_BECOMING_READY: 1632 case SENSE_NOT_READY_FORMAT: 1633 case SENSE_NOT_READY_REBUILD: 1634 case SENSE_NOT_READY_RECALC: 1635 case SENSE_NOT_READY_INPROGRESS: 1636 case SENSE_NOT_READY_LONGWRITE: 1637 case SENSE_NOT_READY_SELFTEST: 1638 case SENSE_NOT_READY_INIT_REQUIRED: 1639 SC_DEBUG(link, SDEV_DB1, 1640 ("not ready (ASC_ASCQ == %#x)\n", 1641 ASC_ASCQ(sense))); 1642 return scsi_delay(xs, 1); 1643 case SENSE_NOMEDIUM: 1644 case SENSE_NOMEDIUM_TCLOSED: 1645 case SENSE_NOMEDIUM_TOPEN: 1646 case SENSE_NOMEDIUM_LOADABLE: 1647 case SENSE_NOMEDIUM_AUXMEM: 1648 CLR(link->flags, SDEV_MEDIA_LOADED); 1649 error = ENOMEDIUM; 1650 break; 1651 default: 1652 break; 1653 } 1654 } 1655 break; 1656 case SKEY_MEDIUM_ERROR: 1657 switch (ASC_ASCQ(sense)) { 1658 case SENSE_NOMEDIUM: 1659 case SENSE_NOMEDIUM_TCLOSED: 1660 case SENSE_NOMEDIUM_TOPEN: 1661 case SENSE_NOMEDIUM_LOADABLE: 1662 case SENSE_NOMEDIUM_AUXMEM: 1663 CLR(link->flags, SDEV_MEDIA_LOADED); 1664 error = ENOMEDIUM; 1665 break; 1666 case SENSE_BAD_MEDIUM: 1667 case SENSE_NR_MEDIUM_UNKNOWN_FORMAT: 1668 case SENSE_NR_MEDIUM_INCOMPATIBLE_FORMAT: 1669 case SENSE_NW_MEDIUM_UNKNOWN_FORMAT: 1670 case SENSE_NW_MEDIUM_INCOMPATIBLE_FORMAT: 1671 case SENSE_NF_MEDIUM_INCOMPATIBLE_FORMAT: 1672 case SENSE_NW_MEDIUM_AC_MISMATCH: 1673 error = EMEDIUMTYPE; 1674 break; 1675 default: 1676 error = EIO; 1677 break; 1678 } 1679 break; 1680 case SKEY_ILLEGAL_REQUEST: 1681 if (ISSET(xs->flags, SCSI_IGNORE_ILLEGAL_REQUEST)) 1682 return 0; 1683 if (ASC_ASCQ(sense) == SENSE_MEDIUM_REMOVAL_PREVENTED) 1684 return EBUSY; 1685 error = EINVAL; 1686 break; 1687 case SKEY_UNIT_ATTENTION: 1688 switch (ASC_ASCQ(sense)) { 1689 case SENSE_POWER_RESET_OR_BUS: 1690 case SENSE_POWER_ON: 1691 case SENSE_BUS_RESET: 1692 case SENSE_BUS_DEVICE_RESET: 1693 case SENSE_DEVICE_INTERNAL_RESET: 1694 case SENSE_TSC_CHANGE_SE: 1695 case SENSE_TSC_CHANGE_LVD: 1696 case SENSE_IT_NEXUS_LOSS: 1697 return scsi_delay(xs, 1); 1698 default: 1699 break; 1700 } 1701 if (ISSET(link->flags, SDEV_REMOVABLE)) 1702 CLR(link->flags, SDEV_MEDIA_LOADED); 1703 if (ISSET(xs->flags, SCSI_IGNORE_MEDIA_CHANGE) || 1704 /* XXX Should reupload any transient state. */ 1705 !ISSET(link->flags, SDEV_REMOVABLE)) { 1706 return scsi_delay(xs, 1); 1707 } 1708 error = EIO; 1709 break; 1710 case SKEY_WRITE_PROTECT: 1711 error = EROFS; 1712 break; 1713 case SKEY_ABORTED_COMMAND: 1714 error = ERESTART; 1715 break; 1716 case SKEY_VOLUME_OVERFLOW: 1717 error = ENOSPC; 1718 break; 1719 case SKEY_HARDWARE_ERROR: 1720 if (ASC_ASCQ(sense) == SENSE_CARTRIDGE_FAULT) 1721 return EMEDIUMTYPE; 1722 error = EIO; 1723 break; 1724 default: 1725 error = EIO; 1726 break; 1727 } 1728 1729 #ifndef SCSIDEBUG 1730 /* SCSIDEBUG would mean it has already been printed. */ 1731 if (skey && !ISSET(xs->flags, SCSI_SILENT)) 1732 scsi_print_sense(xs); 1733 #endif /* ~SCSIDEBUG */ 1734 1735 return error; 1736 } 1737 1738 /* 1739 * Utility routines often used in SCSI stuff 1740 */ 1741 1742 1743 /* 1744 * Print out the scsi_link structure's address info. 1745 */ 1746 void 1747 sc_print_addr(struct scsi_link *link) 1748 { 1749 struct device *adapter_device = link->bus->sc_dev.dv_parent; 1750 1751 printf("%s(%s:%d:%d): ", 1752 link->device_softc ? 1753 ((struct device *)link->device_softc)->dv_xname : "probe", 1754 adapter_device->dv_xname, 1755 link->target, link->lun); 1756 } 1757 1758 static const char *sense_keys[16] = { 1759 "No Additional Sense", 1760 "Soft Error", 1761 "Not Ready", 1762 "Media Error", 1763 "Hardware Error", 1764 "Illegal Request", 1765 "Unit Attention", 1766 "Write Protected", 1767 "Blank Check", 1768 "Vendor Unique", 1769 "Copy Aborted", 1770 "Aborted Command", 1771 "Equal Error", 1772 "Volume Overflow", 1773 "Miscompare Error", 1774 "Reserved" 1775 }; 1776 1777 #ifdef SCSITERSE 1778 static __inline void 1779 asc2ascii(u_int8_t asc, u_int8_t ascq, char *result, size_t len) 1780 { 1781 snprintf(result, len, "ASC 0x%02x ASCQ 0x%02x", asc, ascq); 1782 } 1783 #else 1784 static const struct { 1785 u_int8_t asc, ascq; 1786 char *description; 1787 } adesc[] = { 1788 /* www.t10.org/lists/asc-num.txt as of 11/15/10. */ 1789 { 0x00, 0x00, "No Additional Sense Information" }, 1790 { 0x00, 0x01, "Filemark Detected" }, 1791 { 0x00, 0x02, "End-Of-Partition/Medium Detected" }, 1792 { 0x00, 0x03, "Setmark Detected" }, 1793 { 0x00, 0x04, "Beginning-Of-Partition/Medium Detected" }, 1794 { 0x00, 0x05, "End-Of-Data Detected" }, 1795 { 0x00, 0x06, "I/O Process Terminated" }, 1796 { 0x00, 0x11, "Audio Play Operation In Progress" }, 1797 { 0x00, 0x12, "Audio Play Operation Paused" }, 1798 { 0x00, 0x13, "Audio Play Operation Successfully Completed" }, 1799 { 0x00, 0x14, "Audio Play Operation Stopped Due to Error" }, 1800 { 0x00, 0x15, "No Current Audio Status To Return" }, 1801 { 0x00, 0x16, "Operation In Progress" }, 1802 { 0x00, 0x17, "Cleaning Requested" }, 1803 { 0x00, 0x18, "Erase Operation In Progress" }, 1804 { 0x00, 0x19, "Locate Operation In Progress" }, 1805 { 0x00, 0x1A, "Rewind Operation In Progress" }, 1806 { 0x00, 0x1B, "Set Capacity Operation In Progress" }, 1807 { 0x00, 0x1C, "Verify Operation In Progress" }, 1808 { 0x01, 0x00, "No Index/Sector Signal" }, 1809 { 0x02, 0x00, "No Seek Complete" }, 1810 { 0x03, 0x00, "Peripheral Device Write Fault" }, 1811 { 0x03, 0x01, "No Write Current" }, 1812 { 0x03, 0x02, "Excessive Write Errors" }, 1813 { 0x04, 0x00, "Logical Unit Not Ready, Cause Not Reportable" }, 1814 { 0x04, 0x01, "Logical Unit Is in Process Of Becoming Ready" }, 1815 { 0x04, 0x02, "Logical Unit Not Ready, Initialization Command Required" }, 1816 { 0x04, 0x03, "Logical Unit Not Ready, Manual Intervention Required" }, 1817 { 0x04, 0x04, "Logical Unit Not Ready, Format In Progress" }, 1818 { 0x04, 0x05, "Logical Unit Not Ready, Rebuild In Progress" }, 1819 { 0x04, 0x06, "Logical Unit Not Ready, Recalculation In Progress" }, 1820 { 0x04, 0x07, "Logical Unit Not Ready, Operation In Progress" }, 1821 { 0x04, 0x08, "Logical Unit Not Ready, Long Write In Progress" }, 1822 { 0x04, 0x09, "Logical Unit Not Ready, Self-Test In Progress" }, 1823 { 0x04, 0x0A, "Logical Unit Not Accessible, Asymmetric Access State Transition" }, 1824 { 0x04, 0x0B, "Logical Unit Not Accessible, Target Port In Standby State" }, 1825 { 0x04, 0x0C, "Logical Unit Not Accessible, Target Port In Unavailable State" }, 1826 { 0x04, 0x0D, "Logical Unit Not Ready, Structure Check Required" }, 1827 { 0x04, 0x10, "Logical Unit Not Ready, Auxiliary Memory Not Accessible" }, 1828 { 0x04, 0x11, "Logical Unit Not Ready, Notify (Enable Spinup) Required" }, 1829 { 0x04, 0x12, "Logical Unit Not Ready, Offline" }, 1830 { 0x04, 0x13, "Logical Unit Not Ready, SA Creation In Progress" }, 1831 { 0x04, 0x14, "Logical Unit Not Ready, Space Allocation In Progress" }, 1832 { 0x04, 0x15, "Logical Unit Not Ready, Robotics Disabled" }, 1833 { 0x04, 0x16, "Logical Unit Not Ready, Configuration Required" }, 1834 { 0x04, 0x17, "Logical Unit Not Ready, Calibration Required" }, 1835 { 0x04, 0x18, "Logical Unit Not Ready, A Door Is Open" }, 1836 { 0x04, 0x19, "Logical Unit Not Ready, Operating In Sequential Mode" }, 1837 { 0x04, 0x1A, "Logical Unit Not Ready, Start Stop Unit Command In Progress" }, 1838 { 0x05, 0x00, "Logical Unit Does Not Respond To Selection" }, 1839 { 0x06, 0x00, "No Reference Position Found" }, 1840 { 0x07, 0x00, "Multiple Peripheral Devices Selected" }, 1841 { 0x08, 0x00, "Logical Unit Communication Failure" }, 1842 { 0x08, 0x01, "Logical Unit Communication Timeout" }, 1843 { 0x08, 0x02, "Logical Unit Communication Parity Error" }, 1844 { 0x08, 0x03, "Logical Unit Communication CRC Error (ULTRA-DMA/32)" }, 1845 { 0x08, 0x04, "Unreachable Copy Target" }, 1846 { 0x09, 0x00, "Track Following Error" }, 1847 { 0x09, 0x01, "Tracking Servo Failure" }, 1848 { 0x09, 0x02, "Focus Servo Failure" }, 1849 { 0x09, 0x03, "Spindle Servo Failure" }, 1850 { 0x09, 0x04, "Head Select Fault" }, 1851 { 0x0A, 0x00, "Error Log Overflow" }, 1852 { 0x0B, 0x00, "Warning" }, 1853 { 0x0B, 0x01, "Warning - Specified Temperature Exceeded" }, 1854 { 0x0B, 0x02, "Warning - Enclosure Degraded" }, 1855 { 0x0B, 0x03, "Warning - Background Self-Test Failed" }, 1856 { 0x0B, 0x04, "Warning - Background Pre-Scan Detected Medium Error" }, 1857 { 0x0B, 0x05, "Warning - Background Medium Scan Detected Medium Error" }, 1858 { 0x0B, 0x06, "Warning - Non-Volatile Cache Now Volatile" }, 1859 { 0x0B, 0x07, "Warning - Degraded Power To Non-Volatile Cache" }, 1860 { 0x0B, 0x08, "Warning - Power Loss Expected" }, 1861 { 0x0C, 0x00, "Write Error" }, 1862 { 0x0C, 0x01, "Write Error Recovered with Auto Reallocation" }, 1863 { 0x0C, 0x02, "Write Error - Auto Reallocate Failed" }, 1864 { 0x0C, 0x03, "Write Error - Recommend Reassignment" }, 1865 { 0x0C, 0x04, "Compression Check Miscompare Error" }, 1866 { 0x0C, 0x05, "Data Expansion Occurred During Compression" }, 1867 { 0x0C, 0x06, "Block Not Compressible" }, 1868 { 0x0C, 0x07, "Write Error - Recovery Needed" }, 1869 { 0x0C, 0x08, "Write Error - Recovery Failed" }, 1870 { 0x0C, 0x09, "Write Error - Loss Of Streaming" }, 1871 { 0x0C, 0x0A, "Write Error - Padding Blocks Added" }, 1872 { 0x0C, 0x0B, "Auxiliary Memory Write Error" }, 1873 { 0x0C, 0x0C, "Write Error - Unexpected Unsolicited Data" }, 1874 { 0x0C, 0x0D, "Write Error - Not Enough Unsolicited Data" }, 1875 { 0x0C, 0x0F, "Defects In Error Window" }, 1876 { 0x0D, 0x00, "Error Detected By Third Party Temporary Initiator" }, 1877 { 0x0D, 0x01, "Third Party Device Failure" }, 1878 { 0x0D, 0x02, "Copy Target Device Not Reachable" }, 1879 { 0x0D, 0x03, "Incorrect Copy Target Device Type" }, 1880 { 0x0D, 0x04, "Copy Target Device Data Underrun" }, 1881 { 0x0D, 0x05, "Copy Target Device Data Overrun" }, 1882 { 0x0E, 0x00, "Invalid Information Unit" }, 1883 { 0x0E, 0x01, "Information Unit Too Short" }, 1884 { 0x0E, 0x02, "Information Unit Too Long" }, 1885 { 0x10, 0x00, "ID CRC Or ECC Error" }, 1886 { 0x10, 0x01, "Logical Block Guard Check Failed" }, 1887 { 0x10, 0x02, "Logical Block Application Tag Check Failed" }, 1888 { 0x10, 0x03, "Logical Block Reference Tag Check Failed" }, 1889 { 0x10, 0x04, "Logical Block Protection Error On Recover Buffered Data" }, 1890 { 0x10, 0x05, "Logical Block Protection Method Error" }, 1891 { 0x11, 0x00, "Unrecovered Read Error" }, 1892 { 0x11, 0x01, "Read Retries Exhausted" }, 1893 { 0x11, 0x02, "Error Too Long To Correct" }, 1894 { 0x11, 0x03, "Multiple Read Errors" }, 1895 { 0x11, 0x04, "Unrecovered Read Error - Auto Reallocate Failed" }, 1896 { 0x11, 0x05, "L-EC Uncorrectable Error" }, 1897 { 0x11, 0x06, "CIRC Unrecovered Error" }, 1898 { 0x11, 0x07, "Data Resynchronization Error" }, 1899 { 0x11, 0x08, "Incomplete Block Read" }, 1900 { 0x11, 0x09, "No Gap Found" }, 1901 { 0x11, 0x0A, "Miscorrected Error" }, 1902 { 0x11, 0x0B, "Uncorrected Read Error - Recommend Reassignment" }, 1903 { 0x11, 0x0C, "Uncorrected Read Error - Recommend Rewrite The Data" }, 1904 { 0x11, 0x0D, "De-Compression CRC Error" }, 1905 { 0x11, 0x0E, "Cannot Decompress Using Declared Algorithm" }, 1906 { 0x11, 0x0F, "Error Reading UPC/EAN Number" }, 1907 { 0x11, 0x10, "Error Reading ISRC Number" }, 1908 { 0x11, 0x11, "Read Error - Loss Of Streaming" }, 1909 { 0x11, 0x12, "Auxiliary Memory Read Error" }, 1910 { 0x11, 0x13, "Read Error - Failed Retransmission Request" }, 1911 { 0x11, 0x14, "Read Error - LBA Marked Bad By Application Client" }, 1912 { 0x12, 0x00, "Address Mark Not Found for ID Field" }, 1913 { 0x13, 0x00, "Address Mark Not Found for Data Field" }, 1914 { 0x14, 0x00, "Recorded Entity Not Found" }, 1915 { 0x14, 0x01, "Record Not Found" }, 1916 { 0x14, 0x02, "Filemark or Setmark Not Found" }, 1917 { 0x14, 0x03, "End-Of-Data Not Found" }, 1918 { 0x14, 0x04, "Block Sequence Error" }, 1919 { 0x14, 0x05, "Record Not Found - Recommend Reassignment" }, 1920 { 0x14, 0x06, "Record Not Found - Data Auto-Reallocated" }, 1921 { 0x14, 0x07, "Locate Operation Failure" }, 1922 { 0x15, 0x00, "Random Positioning Error" }, 1923 { 0x15, 0x01, "Mechanical Positioning Error" }, 1924 { 0x15, 0x02, "Positioning Error Detected By Read of Medium" }, 1925 { 0x16, 0x00, "Data Synchronization Mark Error" }, 1926 { 0x16, 0x01, "Data Sync Error - Data Rewritten" }, 1927 { 0x16, 0x02, "Data Sync Error - Recommend Rewrite" }, 1928 { 0x16, 0x03, "Data Sync Error - Data Auto-Reallocated" }, 1929 { 0x16, 0x04, "Data Sync Error - Recommend Reassignment" }, 1930 { 0x17, 0x00, "Recovered Data With No Error Correction Applied" }, 1931 { 0x17, 0x01, "Recovered Data With Retries" }, 1932 { 0x17, 0x02, "Recovered Data With Positive Head Offset" }, 1933 { 0x17, 0x03, "Recovered Data With Negative Head Offset" }, 1934 { 0x17, 0x04, "Recovered Data With Retries and/or CIRC Applied" }, 1935 { 0x17, 0x05, "Recovered Data Using Previous Sector ID" }, 1936 { 0x17, 0x06, "Recovered Data Without ECC - Data Auto-Reallocated" }, 1937 { 0x17, 0x07, "Recovered Data Without ECC - Recommend Reassignment" }, 1938 { 0x17, 0x08, "Recovered Data Without ECC - Recommend Rewrite" }, 1939 { 0x17, 0x09, "Recovered Data Without ECC - Data Rewritten" }, 1940 { 0x18, 0x00, "Recovered Data With Error Correction Applied" }, 1941 { 0x18, 0x01, "Recovered Data With Error Correction & Retries Applied" }, 1942 { 0x18, 0x02, "Recovered Data - Data Auto-Reallocated" }, 1943 { 0x18, 0x03, "Recovered Data With CIRC" }, 1944 { 0x18, 0x04, "Recovered Data With L-EC" }, 1945 { 0x18, 0x05, "Recovered Data - Recommend Reassignment" }, 1946 { 0x18, 0x06, "Recovered Data - Recommend Rewrite" }, 1947 { 0x18, 0x07, "Recovered Data With ECC - Data Rewritten" }, 1948 { 0x18, 0x08, "Recovered Data With Linking" }, 1949 { 0x19, 0x00, "Defect List Error" }, 1950 { 0x19, 0x01, "Defect List Not Available" }, 1951 { 0x19, 0x02, "Defect List Error in Primary List" }, 1952 { 0x19, 0x03, "Defect List Error in Grown List" }, 1953 { 0x1A, 0x00, "Parameter List Length Error" }, 1954 { 0x1B, 0x00, "Synchronous Data Transfer Error" }, 1955 { 0x1C, 0x00, "Defect List Not Found" }, 1956 { 0x1C, 0x01, "Primary Defect List Not Found" }, 1957 { 0x1C, 0x02, "Grown Defect List Not Found" }, 1958 { 0x1D, 0x00, "Miscompare During Verify Operation" }, 1959 { 0x1D, 0x01, "Miscompare Verify Of Unmapped Lba" }, 1960 { 0x1E, 0x00, "Recovered ID with ECC" }, 1961 { 0x1F, 0x00, "Partial Defect List Transfer" }, 1962 { 0x20, 0x00, "Invalid Command Operation Code" }, 1963 { 0x20, 0x01, "Access Denied - Initiator Pending-Enrolled" }, 1964 { 0x20, 0x02, "Access Denied - No Access rights" }, 1965 { 0x20, 0x03, "Access Denied - Invalid Mgmt ID Key" }, 1966 { 0x20, 0x04, "Illegal Command While In Write Capable State" }, 1967 { 0x20, 0x05, "Obsolete" }, 1968 { 0x20, 0x06, "Illegal Command While In Explicit Address Mode" }, 1969 { 0x20, 0x07, "Illegal Command While In Implicit Address Mode" }, 1970 { 0x20, 0x08, "Access Denied - Enrollment Conflict" }, 1971 { 0x20, 0x09, "Access Denied - Invalid LU Identifier" }, 1972 { 0x20, 0x0A, "Access Denied - Invalid Proxy Token" }, 1973 { 0x20, 0x0B, "Access Denied - ACL LUN Conflict" }, 1974 { 0x20, 0x0C, "Illegal Command When Not In Append-Only Mode" }, 1975 { 0x21, 0x00, "Logical Block Address Out of Range" }, 1976 { 0x21, 0x01, "Invalid Element Address" }, 1977 { 0x21, 0x02, "Invalid Address For Write" }, 1978 { 0x21, 0x03, "Invalid Write Crossing Layer Jump" }, 1979 { 0x22, 0x00, "Illegal Function (Should 20 00, 24 00, or 26 00)" }, 1980 { 0x24, 0x00, "Illegal Field in CDB" }, 1981 { 0x24, 0x01, "CDB Decryption Error" }, 1982 { 0x24, 0x02, "Obsolete" }, 1983 { 0x24, 0x03, "Obsolete" }, 1984 { 0x24, 0x04, "Security Audit Value Frozen" }, 1985 { 0x24, 0x05, "Security Working Key Frozen" }, 1986 { 0x24, 0x06, "Nonce Not Unique" }, 1987 { 0x24, 0x07, "Nonce Timestamp Out Of Range" }, 1988 { 0x24, 0x08, "Invalid XCDB" }, 1989 { 0x25, 0x00, "Logical Unit Not Supported" }, 1990 { 0x26, 0x00, "Invalid Field In Parameter List" }, 1991 { 0x26, 0x01, "Parameter Not Supported" }, 1992 { 0x26, 0x02, "Parameter Value Invalid" }, 1993 { 0x26, 0x03, "Threshold Parameters Not Supported" }, 1994 { 0x26, 0x04, "Invalid Release Of Persistent Reservation" }, 1995 { 0x26, 0x05, "Data Decryption Error" }, 1996 { 0x26, 0x06, "Too Many Target Descriptors" }, 1997 { 0x26, 0x07, "Unsupported Target Descriptor Type Code" }, 1998 { 0x26, 0x08, "Too Many Segment Descriptors" }, 1999 { 0x26, 0x09, "Unsupported Segment Descriptor Type Code" }, 2000 { 0x26, 0x0A, "Unexpected Inexact Segment" }, 2001 { 0x26, 0x0B, "Inline Data Length Exceeded" }, 2002 { 0x26, 0x0C, "Invalid Operation For Copy Source Or Destination" }, 2003 { 0x26, 0x0D, "Copy Segment Granularity Violation" }, 2004 { 0x26, 0x0E, "Invalid Parameter While Port Is Enabled" }, 2005 { 0x26, 0x0F, "Invalid Data-Out Buffer Integrity Check Value" }, 2006 { 0x26, 0x10, "Data Decryption Key Fail Limit Reached" }, 2007 { 0x26, 0x11, "Incomplete Key-Associated Data Set" }, 2008 { 0x26, 0x12, "Vendor Specific Key Reference Not Found" }, 2009 { 0x27, 0x00, "Write Protected" }, 2010 { 0x27, 0x01, "Hardware Write Protected" }, 2011 { 0x27, 0x02, "Logical Unit Software Write Protected" }, 2012 { 0x27, 0x03, "Associated Write Protect" }, 2013 { 0x27, 0x04, "Persistent Write Protect" }, 2014 { 0x27, 0x05, "Permanent Write Protect" }, 2015 { 0x27, 0x06, "Conditional Write Protect" }, 2016 { 0x27, 0x07, "Space Allocation Failed Write Protect" }, 2017 { 0x28, 0x00, "Not Ready To Ready Transition (Medium May Have Changed)" }, 2018 { 0x28, 0x01, "Import Or Export Element Accessed" }, 2019 { 0x28, 0x02, "Format-Layer May Have Changed" }, 2020 { 0x28, 0x03, "Import/Export Element Accessed, Medium Changed" }, 2021 { 0x29, 0x00, "Power On, Reset, or Bus Device Reset Occurred" }, 2022 { 0x29, 0x01, "Power On Occurred" }, 2023 { 0x29, 0x02, "SCSI Bus Reset Occurred" }, 2024 { 0x29, 0x03, "Bus Device Reset Function Occurred" }, 2025 { 0x29, 0x04, "Device Internal Reset" }, 2026 { 0x29, 0x05, "Transceiver Mode Changed to Single Ended" }, 2027 { 0x29, 0x06, "Transceiver Mode Changed to LVD" }, 2028 { 0x29, 0x07, "I_T Nexus Loss Occurred" }, 2029 { 0x2A, 0x00, "Parameters Changed" }, 2030 { 0x2A, 0x01, "Mode Parameters Changed" }, 2031 { 0x2A, 0x02, "Log Parameters Changed" }, 2032 { 0x2A, 0x03, "Reservations Preempted" }, 2033 { 0x2A, 0x04, "Reservations Released" }, 2034 { 0x2A, 0x05, "Registrations Preempted" }, 2035 { 0x2A, 0x06, "Asymmetric Access State Changed" }, 2036 { 0x2A, 0x07, "Implicit Asymmetric Access State Transition Failed" }, 2037 { 0x2A, 0x08, "Priority Changed" }, 2038 { 0x2A, 0x09, "Capacity Data Has Changed" }, 2039 { 0x2A, 0x0A, "Error History I_T Nexus Cleared" }, 2040 { 0x2A, 0x0B, "Error History Snapshot Released" }, 2041 { 0x2A, 0x0C, "Error Recovery Attributes Have Changed" }, 2042 { 0x2A, 0x0D, "Data Encryption Capabilities Changed" }, 2043 { 0x2A, 0x10, "Timestamp Changed" }, 2044 { 0x2A, 0x11, "Data Encryption Parameters Changed By Another I_T Nexus" }, 2045 { 0x2A, 0x12, "Data Encryption Parameters Changed By Vendor Specific Event" }, 2046 { 0x2A, 0x13, "Data Encryption Key Instance Counter Has Changed" }, 2047 { 0x2A, 0x14, "SA Creation Capabilities Data Has Changed" }, 2048 { 0x2B, 0x00, "Copy Cannot Execute Since Host Cannot Disconnect" }, 2049 { 0x2C, 0x00, "Command Sequence Error" }, 2050 { 0x2C, 0x01, "Too Many Windows Specified" }, 2051 { 0x2C, 0x02, "Invalid Combination of Windows Specified" }, 2052 { 0x2C, 0x03, "Current Program Area Is Not Empty" }, 2053 { 0x2C, 0x04, "Current Program Area Is Empty" }, 2054 { 0x2C, 0x05, "Illegal Power Condition Request" }, 2055 { 0x2C, 0x06, "Persistent Prevent Conflict" }, 2056 { 0x2C, 0x07, "Previous Busy Status" }, 2057 { 0x2C, 0x08, "Previous Task Set Full Status" }, 2058 { 0x2C, 0x09, "Previous Reservation Conflict Status" }, 2059 { 0x2C, 0x0A, "Partition Or Collection Contains User Objects" }, 2060 { 0x2C, 0x0B, "Not Reserved" }, 2061 { 0x2C, 0x0C, "ORWrite Generation Does Not Match" }, 2062 { 0x2D, 0x00, "Overwrite Error On Update In Place" }, 2063 { 0x2E, 0x00, "Insufficient Time For Operation" }, 2064 { 0x2F, 0x00, "Commands Cleared By Another Initiator" }, 2065 { 0x2F, 0x01, "Commands Cleared By Power Loss Notification" }, 2066 { 0x2F, 0x02, "Commands Cleared By Device Server" }, 2067 { 0x30, 0x00, "Incompatible Medium Installed" }, 2068 { 0x30, 0x01, "Cannot Read Medium - Unknown Format" }, 2069 { 0x30, 0x02, "Cannot Read Medium - Incompatible Format" }, 2070 { 0x30, 0x03, "Cleaning Cartridge Installed" }, 2071 { 0x30, 0x04, "Cannot Write Medium - Unknown Format" }, 2072 { 0x30, 0x05, "Cannot Write Medium - Incompatible Format" }, 2073 { 0x30, 0x06, "Cannot Format Medium - Incompatible Medium" }, 2074 { 0x30, 0x07, "Cleaning Failure" }, 2075 { 0x30, 0x08, "Cannot Write - Application Code Mismatch" }, 2076 { 0x30, 0x09, "Current Session Not Fixated For Append" }, 2077 { 0x30, 0x0A, "Cleaning Request Rejected" }, 2078 { 0x30, 0x10, "Medium Not Formatted" }, 2079 { 0x30, 0x11, "Incompatible Volume Type" }, 2080 { 0x30, 0x12, "Incompatible Volume Qualifier" }, 2081 { 0x30, 0x13, "Cleaning Volume Expired" }, 2082 { 0x31, 0x00, "Medium Format Corrupted" }, 2083 { 0x31, 0x01, "Format Command Failed" }, 2084 { 0x31, 0x02, "Zoned Formatting Failed Due To Spare Linking" }, 2085 { 0x32, 0x00, "No Defect Spare Location Available" }, 2086 { 0x32, 0x01, "Defect List Update Failure" }, 2087 { 0x33, 0x00, "Tape Length Error" }, 2088 { 0x34, 0x00, "Enclosure Failure" }, 2089 { 0x35, 0x00, "Enclosure Services Failure" }, 2090 { 0x35, 0x01, "Unsupported Enclosure Function" }, 2091 { 0x35, 0x02, "Enclosure Services Unavailable" }, 2092 { 0x35, 0x03, "Enclosure Services Transfer Failure" }, 2093 { 0x35, 0x04, "Enclosure Services Transfer Refused" }, 2094 { 0x36, 0x00, "Ribbon, Ink, or Toner Failure" }, 2095 { 0x37, 0x00, "Rounded Parameter" }, 2096 { 0x38, 0x00, "Event Status Notification" }, 2097 { 0x38, 0x02, "ESN - Power Management Class Event" }, 2098 { 0x38, 0x04, "ESN - Media Class Event" }, 2099 { 0x38, 0x06, "ESN - Device Busy Class Event" }, 2100 { 0x39, 0x00, "Saving Parameters Not Supported" }, 2101 { 0x3A, 0x00, "Medium Not Present" }, 2102 { 0x3A, 0x01, "Medium Not Present - Tray Closed" }, 2103 { 0x3A, 0x02, "Medium Not Present - Tray Open" }, 2104 { 0x3A, 0x03, "Medium Not Present - Loadable" }, 2105 { 0x3A, 0x04, "Medium Not Present - Medium Auxiliary Memory Accessible" }, 2106 { 0x3B, 0x00, "Sequential Positioning Error" }, 2107 { 0x3B, 0x01, "Tape Position Error At Beginning-of-Medium" }, 2108 { 0x3B, 0x02, "Tape Position Error At End-of-Medium" }, 2109 { 0x3B, 0x03, "Tape or Electronic Vertical Forms Unit Not Ready" }, 2110 { 0x3B, 0x04, "Slew Failure" }, 2111 { 0x3B, 0x05, "Paper Jam" }, 2112 { 0x3B, 0x06, "Failed To Sense Top-Of-Form" }, 2113 { 0x3B, 0x07, "Failed To Sense Bottom-Of-Form" }, 2114 { 0x3B, 0x08, "Reposition Error" }, 2115 { 0x3B, 0x09, "Read Past End Of Medium" }, 2116 { 0x3B, 0x0A, "Read Past Beginning Of Medium" }, 2117 { 0x3B, 0x0B, "Position Past End Of Medium" }, 2118 { 0x3B, 0x0C, "Position Past Beginning Of Medium" }, 2119 { 0x3B, 0x0D, "Medium Destination Element Full" }, 2120 { 0x3B, 0x0E, "Medium Source Element Empty" }, 2121 { 0x3B, 0x0F, "End Of Medium Reached" }, 2122 { 0x3B, 0x11, "Medium Magazine Not Accessible" }, 2123 { 0x3B, 0x12, "Medium Magazine Removed" }, 2124 { 0x3B, 0x13, "Medium Magazine Inserted" }, 2125 { 0x3B, 0x14, "Medium Magazine Locked" }, 2126 { 0x3B, 0x15, "Medium Magazine Unlocked" }, 2127 { 0x3B, 0x16, "Mechanical Positioning Or Changer Error" }, 2128 { 0x3B, 0x17, "Read Past End Of User Object" }, 2129 { 0x3B, 0x18, "Element Disabled" }, 2130 { 0x3B, 0x19, "Element Enabled" }, 2131 { 0x3B, 0x1A, "Data Transfer Device Removed" }, 2132 { 0x3B, 0x1B, "Data Transfer Device Inserted" }, 2133 { 0x3D, 0x00, "Invalid Bits In IDENTIFY Message" }, 2134 { 0x3E, 0x00, "Logical Unit Has Not Self-Configured Yet" }, 2135 { 0x3E, 0x01, "Logical Unit Failure" }, 2136 { 0x3E, 0x02, "Timeout On Logical Unit" }, 2137 { 0x3E, 0x03, "Logical Unit Failed Self-Test" }, 2138 { 0x3E, 0x04, "Logical Unit Unable To Update Self-Test Log" }, 2139 { 0x3F, 0x00, "Target Operating Conditions Have Changed" }, 2140 { 0x3F, 0x01, "Microcode Has Changed" }, 2141 { 0x3F, 0x02, "Changed Operating Definition" }, 2142 { 0x3F, 0x03, "INQUIRY Data Has Changed" }, 2143 { 0x3F, 0x04, "component Device Attached" }, 2144 { 0x3F, 0x05, "Device Identifier Changed" }, 2145 { 0x3F, 0x06, "Redundancy Group Created Or Modified" }, 2146 { 0x3F, 0x07, "Redundancy Group Deleted" }, 2147 { 0x3F, 0x08, "Spare Created Or Modified" }, 2148 { 0x3F, 0x09, "Spare Deleted" }, 2149 { 0x3F, 0x0A, "Volume Set Created Or Modified" }, 2150 { 0x3F, 0x0B, "Volume Set Deleted" }, 2151 { 0x3F, 0x0C, "Volume Set Deassigned" }, 2152 { 0x3F, 0x0D, "Volume Set Reassigned" }, 2153 { 0x3F, 0x0E, "Reported LUNs Data Has Changed" }, 2154 { 0x3F, 0x0F, "Echo Buffer Overwritten" }, 2155 { 0x3F, 0x10, "Medium Loadable" }, 2156 { 0x3F, 0x11, "Medium Auxiliary Memory Accessible" }, 2157 { 0x3F, 0x12, "iSCSI IP Address Added" }, 2158 { 0x3F, 0x13, "iSCSI IP Address Removed" }, 2159 { 0x3F, 0x14, "iSCSI IP Address Changed" }, 2160 { 0x40, 0x00, "RAM FAILURE (Should Use 40 NN)" }, 2161 /* 2162 * ASC 0x40 also has an ASCQ range from 0x80 to 0xFF. 2163 * 0x40 0xNN DIAGNOSTIC FAILURE ON COMPONENT NN 2164 */ 2165 { 0x41, 0x00, "Data Path FAILURE (Should Use 40 NN)" }, 2166 { 0x42, 0x00, "Power-On or Self-Test FAILURE (Should Use 40 NN)" }, 2167 { 0x43, 0x00, "Message Error" }, 2168 { 0x44, 0x00, "Internal Target Failure" }, 2169 { 0x44, 0x71, "ATA Device Failed Set Features" }, 2170 { 0x45, 0x00, "Select Or Reselect Failure" }, 2171 { 0x46, 0x00, "Unsuccessful Soft Reset" }, 2172 { 0x47, 0x00, "SCSI Parity Error" }, 2173 { 0x47, 0x01, "Data Phase CRC Error Detected" }, 2174 { 0x47, 0x02, "SCSI Parity Error Detected During ST Data Phase" }, 2175 { 0x47, 0x03, "Information Unit iuCRC Error Detected" }, 2176 { 0x47, 0x04, "Asynchronous Information Protection Error Detected" }, 2177 { 0x47, 0x05, "Protocol Service CRC Error" }, 2178 { 0x47, 0x06, "PHY Test Function In Progress" }, 2179 { 0x47, 0x7F, "Some Commands Cleared By iSCSI Protocol Event" }, 2180 { 0x48, 0x00, "Initiator Detected Error Message Received" }, 2181 { 0x49, 0x00, "Invalid Message Error" }, 2182 { 0x4A, 0x00, "Command Phase Error" }, 2183 { 0x4B, 0x00, "Data Phase Error" }, 2184 { 0x4B, 0x01, "Invalid Target Port Transfer Tag Received" }, 2185 { 0x4B, 0x02, "Too Much Write Data" }, 2186 { 0x4B, 0x03, "ACK/NAK Timeout" }, 2187 { 0x4B, 0x04, "NAK Received" }, 2188 { 0x4B, 0x05, "Data Offset Error" }, 2189 { 0x4B, 0x06, "Initiator Response Timeout" }, 2190 { 0x4B, 0x07, "Connection Lost" }, 2191 { 0x4C, 0x00, "Logical Unit Failed Self-Configuration" }, 2192 /* 2193 * ASC 0x4D has an ASCQ range from 0x00 to 0xFF. 2194 * 0x4D 0xNN TAGGED OVERLAPPED COMMANDS (NN = TASK TAG) 2195 */ 2196 { 0x4E, 0x00, "Overlapped Commands Attempted" }, 2197 { 0x50, 0x00, "Write Append Error" }, 2198 { 0x50, 0x01, "Write Append Position Error" }, 2199 { 0x50, 0x02, "Position Error Related To Timing" }, 2200 { 0x51, 0x00, "Erase Failure" }, 2201 { 0x51, 0x01, "Erase Failure - Incomplete Erase Operation Detected" }, 2202 { 0x52, 0x00, "Cartridge Fault" }, 2203 { 0x53, 0x00, "Media Load or Eject Failed" }, 2204 { 0x53, 0x01, "Unload Tape Failure" }, 2205 { 0x53, 0x02, "Medium Removal Prevented" }, 2206 { 0x53, 0x03, "Medium Removal Prevented By Data Transfer Element" }, 2207 { 0x53, 0x04, "Medium Thread Or Unthread Failure" }, 2208 { 0x53, 0x05, "Volume Identifier Invalid" }, 2209 { 0x53, 0x06, "Volume Identifier Missing" }, 2210 { 0x53, 0x07, "Duplicate Volume Identifier" }, 2211 { 0x53, 0x08, "Element Status Unknown" }, 2212 { 0x54, 0x00, "SCSI To Host System Interface Failure" }, 2213 { 0x55, 0x00, "System Resource Failure" }, 2214 { 0x55, 0x01, "System Buffer Full" }, 2215 { 0x55, 0x02, "Insufficient Reservation Resources" }, 2216 { 0x55, 0x03, "Insufficient Resources" }, 2217 { 0x55, 0x04, "Insufficient Registration Resources" }, 2218 { 0x55, 0x05, "Insufficient Access Control Resources" }, 2219 { 0x55, 0x06, "Auxiliary Memory Out Of Space" }, 2220 { 0x55, 0x07, "Quota Error" }, 2221 { 0x55, 0x08, "Maximum Number Of Supplemental Decryption Keys Exceeded" }, 2222 { 0x55, 0x09, "Medium Auxiliary Memory Not Accessible" }, 2223 { 0x55, 0x0A, "Data Currently Unavailable" }, 2224 { 0x55, 0x0B, "Insufficient Power For Operation" }, 2225 { 0x57, 0x00, "Unable To Recover Table-Of-Contents" }, 2226 { 0x58, 0x00, "Generation Does Not Exist" }, 2227 { 0x59, 0x00, "Updated Block Read" }, 2228 { 0x5A, 0x00, "Operator Request or State Change Input" }, 2229 { 0x5A, 0x01, "Operator Medium Removal Requested" }, 2230 { 0x5A, 0x02, "Operator Selected Write Protect" }, 2231 { 0x5A, 0x03, "Operator Selected Write Permit" }, 2232 { 0x5B, 0x00, "Log Exception" }, 2233 { 0x5B, 0x01, "Threshold Condition Met" }, 2234 { 0x5B, 0x02, "Log Counter At Maximum" }, 2235 { 0x5B, 0x03, "Log List Codes Exhausted" }, 2236 { 0x5C, 0x00, "RPL Status Change" }, 2237 { 0x5C, 0x01, "Spindles Synchronized" }, 2238 { 0x5C, 0x02, "Spindles Not Synchronized" }, 2239 { 0x5D, 0x00, "Failure Prediction Threshold Exceeded" }, 2240 { 0x5D, 0x01, "Media Failure Prediction Threshold Exceeded" }, 2241 { 0x5D, 0x02, "Logical Unit Failure Prediction Threshold Exceeded" }, 2242 { 0x5D, 0x03, "Spare Area Exhaustion Prediction Threshold Exceeded" }, 2243 { 0x5D, 0x10, "Hardware Impending Failure General Hard Drive Failure" }, 2244 { 0x5D, 0x11, "Hardware Impending Failure Drive Error Rate Too High" }, 2245 { 0x5D, 0x12, "Hardware Impending Failure Data Error Rate Too High" }, 2246 { 0x5D, 0x13, "Hardware Impending Failure Seek Error Rate Too High" }, 2247 { 0x5D, 0x14, "Hardware Impending Failure Too Many Block Reassigns" }, 2248 { 0x5D, 0x15, "Hardware Impending Failure Access Times Too High" }, 2249 { 0x5D, 0x16, "Hardware Impending Failure Start Unit Times Too High" }, 2250 { 0x5D, 0x17, "Hardware Impending Failure Channel Parametrics" }, 2251 { 0x5D, 0x18, "Hardware Impending Failure Controller Detected" }, 2252 { 0x5D, 0x19, "Hardware Impending Failure Throughput Performance" }, 2253 { 0x5D, 0x1A, "Hardware Impending Failure Seek Time Performance" }, 2254 { 0x5D, 0x1B, "Hardware Impending Failure Spin-Up Retry Count" }, 2255 { 0x5D, 0x1C, "Hardware Impending Failure Drive Calibration Retry Count" }, 2256 { 0x5D, 0x20, "Controller Impending Failure General Hard Drive Failure" }, 2257 { 0x5D, 0x21, "Controller Impending Failure Drive Error Rate Too High" }, 2258 { 0x5D, 0x22, "Controller Impending Failure Data Error Rate Too High" }, 2259 { 0x5D, 0x23, "Controller Impending Failure Seek Error Rate Too High" }, 2260 { 0x5D, 0x24, "Controller Impending Failure Too Many Block Reassigns" }, 2261 { 0x5D, 0x25, "Controller Impending Failure Access Times Too High" }, 2262 { 0x5D, 0x26, "Controller Impending Failure Start Unit Times Too High" }, 2263 { 0x5D, 0x27, "Controller Impending Failure Channel Parametrics" }, 2264 { 0x5D, 0x28, "Controller Impending Failure Controller Detected" }, 2265 { 0x5D, 0x29, "Controller Impending Failure Throughput Performance" }, 2266 { 0x5D, 0x2A, "Controller Impending Failure Seek Time Performance" }, 2267 { 0x5D, 0x2B, "Controller Impending Failure Spin-Up Retry Count" }, 2268 { 0x5D, 0x2C, "Controller Impending Failure Drive Calibration Retry Count" }, 2269 { 0x5D, 0x30, "Data Channel Impending Failure General Hard Drive Failure" }, 2270 { 0x5D, 0x31, "Data Channel Impending Failure Drive Error Rate Too High" }, 2271 { 0x5D, 0x32, "Data Channel Impending Failure Data Error Rate Too High" }, 2272 { 0x5D, 0x33, "Data Channel Impending Failure Seek Error Rate Too High" }, 2273 { 0x5D, 0x34, "Data Channel Impending Failure Too Many Block Reassigns" }, 2274 { 0x5D, 0x35, "Data Channel Impending Failure Access Times Too High" }, 2275 { 0x5D, 0x36, "Data Channel Impending Failure Start Unit Times Too High" }, 2276 { 0x5D, 0x37, "Data Channel Impending Failure Channel Parametrics" }, 2277 { 0x5D, 0x38, "Data Channel Impending Failure Controller Detected" }, 2278 { 0x5D, 0x39, "Data Channel Impending Failure Throughput Performance" }, 2279 { 0x5D, 0x3A, "Data Channel Impending Failure Seek Time Performance" }, 2280 { 0x5D, 0x3B, "Data Channel Impending Failure Spin-Up Retry Count" }, 2281 { 0x5D, 0x3C, "Data Channel Impending Failure Drive Calibration Retry Count" }, 2282 { 0x5D, 0x40, "Servo Impending Failure General Hard Drive Failure" }, 2283 { 0x5D, 0x41, "Servo Impending Failure Drive Error Rate Too High" }, 2284 { 0x5D, 0x42, "Servo Impending Failure Data Error Rate Too High" }, 2285 { 0x5D, 0x43, "Servo Impending Failure Seek Error Rate Too High" }, 2286 { 0x5D, 0x44, "Servo Impending Failure Too Many Block Reassigns" }, 2287 { 0x5D, 0x45, "Servo Impending Failure Access Times Too High" }, 2288 { 0x5D, 0x46, "Servo Impending Failure Start Unit Times Too High" }, 2289 { 0x5D, 0x47, "Servo Impending Failure Channel Parametrics" }, 2290 { 0x5D, 0x48, "Servo Impending Failure Controller Detected" }, 2291 { 0x5D, 0x49, "Servo Impending Failure Throughput Performance" }, 2292 { 0x5D, 0x4A, "Servo Impending Failure Seek Time Performance" }, 2293 { 0x5D, 0x4B, "Servo Impending Failure Spin-Up Retry Count" }, 2294 { 0x5D, 0x4C, "Servo Impending Failure Drive Calibration Retry Count" }, 2295 { 0x5D, 0x50, "Spindle Impending Failure General Hard Drive Failure" }, 2296 { 0x5D, 0x51, "Spindle Impending Failure Drive Error Rate Too High" }, 2297 { 0x5D, 0x52, "Spindle Impending Failure Data Error Rate Too High" }, 2298 { 0x5D, 0x53, "Spindle Impending Failure Seek Error Rate Too High" }, 2299 { 0x5D, 0x54, "Spindle Impending Failure Too Many Block Reassigns" }, 2300 { 0x5D, 0x55, "Spindle Impending Failure Access Times Too High" }, 2301 { 0x5D, 0x56, "Spindle Impending Failure Start Unit Times Too High" }, 2302 { 0x5D, 0x57, "Spindle Impending Failure Channel Parametrics" }, 2303 { 0x5D, 0x58, "Spindle Impending Failure Controller Detected" }, 2304 { 0x5D, 0x59, "Spindle Impending Failure Throughput Performance" }, 2305 { 0x5D, 0x5A, "Spindle Impending Failure Seek Time Performance" }, 2306 { 0x5D, 0x5B, "Spindle Impending Failure Spin-Up Retry Count" }, 2307 { 0x5D, 0x5C, "Spindle Impending Failure Drive Calibration Retry Count" }, 2308 { 0x5D, 0x60, "Firmware Impending Failure General Hard Drive Failure" }, 2309 { 0x5D, 0x61, "Firmware Impending Failure Drive Error Rate Too High" }, 2310 { 0x5D, 0x62, "Firmware Impending Failure Data Error Rate Too High" }, 2311 { 0x5D, 0x63, "Firmware Impending Failure Seek Error Rate Too High" }, 2312 { 0x5D, 0x64, "Firmware Impending Failure Too Many Block Reassigns" }, 2313 { 0x5D, 0x65, "Firmware Impending Failure Access Times Too High" }, 2314 { 0x5D, 0x66, "Firmware Impending Failure Start Unit Times Too High" }, 2315 { 0x5D, 0x67, "Firmware Impending Failure Channel Parametrics" }, 2316 { 0x5D, 0x68, "Firmware Impending Failure Controller Detected" }, 2317 { 0x5D, 0x69, "Firmware Impending Failure Throughput Performance" }, 2318 { 0x5D, 0x6A, "Firmware Impending Failure Seek Time Performance" }, 2319 { 0x5D, 0x6B, "Firmware Impending Failure Spin-Up Retry Count" }, 2320 { 0x5D, 0x6C, "Firmware Impending Failure Drive Calibration Retry Count" }, 2321 { 0x5D, 0xFF, "Failure Prediction Threshold Exceeded (false)" }, 2322 { 0x5E, 0x00, "Low Power Condition On" }, 2323 { 0x5E, 0x01, "Idle Condition Activated By Timer" }, 2324 { 0x5E, 0x02, "Standby Condition Activated By Timer" }, 2325 { 0x5E, 0x03, "Idle Condition Activated By Command" }, 2326 { 0x5E, 0x04, "Standby Condition Activated By Command" }, 2327 { 0x5E, 0x05, "IDLE_B Condition Activated By Timer" }, 2328 { 0x5E, 0x06, "IDLE_B Condition Activated By Command" }, 2329 { 0x5E, 0x07, "IDLE_C Condition Activated By Timer" }, 2330 { 0x5E, 0x08, "IDLE_C Condition Activated By Command" }, 2331 { 0x5E, 0x09, "STANDBY_Y Condition Activated By Timer" }, 2332 { 0x5E, 0x0A, "STANDBY_Y Condition Activated By Command" }, 2333 { 0x5E, 0x41, "Power State Change To Active" }, 2334 { 0x5E, 0x42, "Power State Change To Idle" }, 2335 { 0x5E, 0x43, "Power State Change To Standby" }, 2336 { 0x5E, 0x45, "Power State Change To Sleep" }, 2337 { 0x5E, 0x47, "Power State Change To Device Control" }, 2338 { 0x60, 0x00, "Lamp Failure" }, 2339 { 0x61, 0x00, "Video Acquisition Error" }, 2340 { 0x61, 0x01, "Unable To Acquire Video" }, 2341 { 0x61, 0x02, "Out Of Focus" }, 2342 { 0x62, 0x00, "Scan Head Positioning Error" }, 2343 { 0x63, 0x00, "End Of User Area Encountered On This Track" }, 2344 { 0x63, 0x01, "Packet Does Not Fit In Available Space" }, 2345 { 0x64, 0x00, "Illegal Mode For This Track" }, 2346 { 0x64, 0x01, "Invalid Packet Size" }, 2347 { 0x65, 0x00, "Voltage Fault" }, 2348 { 0x66, 0x00, "Automatic Document Feeder Cover Up" }, 2349 { 0x66, 0x01, "Automatic Document Feeder Lift Up" }, 2350 { 0x66, 0x02, "Document Jam In Automatic Document Feeder" }, 2351 { 0x66, 0x03, "Document Miss Feed Automatic In Document Feeder" }, 2352 { 0x67, 0x00, "Configuration Failure" }, 2353 { 0x67, 0x01, "Configuration Of Incapable Logical Units Failed" }, 2354 { 0x67, 0x02, "Add Logical Unit Failed" }, 2355 { 0x67, 0x03, "Modification Of Logical Unit Failed" }, 2356 { 0x67, 0x04, "Exchange Of Logical Unit Failed" }, 2357 { 0x67, 0x05, "Remove Of Logical Unit Failed" }, 2358 { 0x67, 0x06, "Attachment Of Logical Unit Failed" }, 2359 { 0x67, 0x07, "Creation Of Logical Unit Failed" }, 2360 { 0x67, 0x08, "Assign Failure Occurred" }, 2361 { 0x67, 0x09, "Multiply Assigned Logical Unit" }, 2362 { 0x67, 0x0A, "Set Target Port Groups Command Failed" }, 2363 { 0x67, 0x0B, "ATA Device Feature Not Enabled" }, 2364 { 0x68, 0x00, "Logical Unit Not Configured" }, 2365 { 0x69, 0x00, "Data Loss On Logical Unit" }, 2366 { 0x69, 0x01, "Multiple Logical Unit Failures" }, 2367 { 0x69, 0x02, "Parity/Data Mismatch" }, 2368 { 0x6A, 0x00, "Informational, Refer To Log" }, 2369 { 0x6B, 0x00, "State Change Has Occurred" }, 2370 { 0x6B, 0x01, "Redundancy Level Got Better" }, 2371 { 0x6B, 0x02, "Redundancy Level Got Worse" }, 2372 { 0x6C, 0x00, "Rebuild Failure Occurred" }, 2373 { 0x6D, 0x00, "Recalculate Failure Occurred" }, 2374 { 0x6E, 0x00, "Command To Logical Unit Failed" }, 2375 { 0x6F, 0x00, "Copy Protection Key Exchange Failure - Authentication Failure" }, 2376 { 0x6F, 0x01, "Copy Protection Key Exchange Failure - Key Not Present" }, 2377 { 0x6F, 0x02, "Copy Protection Key Exchange Failure - Key Not Established" }, 2378 { 0x6F, 0x03, "Read Of Scrambled Sector Without Authentication" }, 2379 { 0x6F, 0x04, "Media Region Code Is Mismatched To Logical Unit Region" }, 2380 { 0x6F, 0x05, "Drive Region Must Be Permanent/Region Reset Count Error" }, 2381 /* 2382 * ASC 0x70 has an ASCQ range from 0x00 to 0xFF. 2383 * 0x70 0xNN DECOMPRESSION EXCEPTION SHORT ALGORITHM ID Of NN 2384 */ 2385 { 0x71, 0x00, "Decompression Exception Long Algorithm ID" }, 2386 { 0x72, 0x00, "Session Fixation Error" }, 2387 { 0x72, 0x01, "Session Fixation Error Writing Lead-In" }, 2388 { 0x72, 0x02, "Session Fixation Error Writing Lead-Out" }, 2389 { 0x72, 0x03, "Session Fixation Error - Incomplete Track In Session" }, 2390 { 0x72, 0x04, "Empty Or Partially Written Reserved Track" }, 2391 { 0x72, 0x05, "No More Track Reservations Allowed" }, 2392 { 0x72, 0x06, "RMZ Extension Is Not Allowed" }, 2393 { 0x72, 0x07, "No More Test Zone Extensions Are Allowed" }, 2394 { 0x73, 0x00, "CD Control Error" }, 2395 { 0x73, 0x01, "Power Calibration Area Almost Full" }, 2396 { 0x73, 0x02, "Power Calibration Area Is Full" }, 2397 { 0x73, 0x03, "Power Calibration Area Error" }, 2398 { 0x73, 0x04, "Program Memory Area Update Failure" }, 2399 { 0x73, 0x05, "Program Memory Area Is Full" }, 2400 { 0x73, 0x06, "RMA/PMA Is Almost Full" }, 2401 { 0x73, 0x10, "Current Power Calibration Area Almost Full" }, 2402 { 0x73, 0x11, "Current Power Calibration Area Is Full" }, 2403 { 0x73, 0x17, "RDZ Is Full" }, 2404 { 0x74, 0x00, "Security Error" }, 2405 { 0x74, 0x01, "Unable To Decrypt Data" }, 2406 { 0x74, 0x02, "Unencrypted Data Encountered While Decrypting" }, 2407 { 0x74, 0x03, "Incorrect Data Encryption Key" }, 2408 { 0x74, 0x04, "Cryptographic Integrity Validation Failed" }, 2409 { 0x74, 0x05, "Error Decrypting Data" }, 2410 { 0x74, 0x06, "Unknown Signature Verification Key" }, 2411 { 0x74, 0x07, "Encryption Parameters Not Useable" }, 2412 { 0x74, 0x08, "Digital Signature Validation Failure" }, 2413 { 0x74, 0x09, "Encryption Mode Mismatch On Read" }, 2414 { 0x74, 0x0A, "Encrypted Block Not Raw Read Enabled" }, 2415 { 0x74, 0x0B, "Incorrect Encryption Parameters" }, 2416 { 0x74, 0x0C, "Unable To Decrypt Parameter List" }, 2417 { 0x74, 0x0D, "Encryption Algorithm Disabled" }, 2418 { 0x74, 0x10, "SA Creation Parameter Value Invalid" }, 2419 { 0x74, 0x11, "SA Creation Parameter Value Rejected" }, 2420 { 0x74, 0x12, "Invalid SA Usage" }, 2421 { 0x74, 0x21, "Data Encryption Configuration Prevented" }, 2422 { 0x74, 0x30, "SA Creation Parameter Not Supported" }, 2423 { 0x74, 0x40, "Authentication Failed" }, 2424 { 0x74, 0x61, "External Data Encryption Key Manager Access Error" }, 2425 { 0x74, 0x62, "External Data Encryption Key Manager Error" }, 2426 { 0x74, 0x63, "External Data Encryption Key Not Found" }, 2427 { 0x74, 0x64, "External Data Encryption Request Not Authorized" }, 2428 { 0x74, 0x6E, "External Data Encryption Control Timeout" }, 2429 { 0x74, 0x6F, "External Data Encryption Control Error" }, 2430 { 0x74, 0x71, "Logical Unit Access Not Authorized" }, 2431 { 0x74, 0x79, "Security Conflict In Translated Device" }, 2432 { 0x00, 0x00, NULL } 2433 }; 2434 2435 static __inline void 2436 asc2ascii(u_int8_t asc, u_int8_t ascq, char *result, size_t len) 2437 { 2438 int i; 2439 2440 /* Check for a dynamically built description. */ 2441 switch (asc) { 2442 case 0x40: 2443 if (ascq >= 0x80) { 2444 snprintf(result, len, 2445 "Diagnostic Failure on Component 0x%02x", ascq); 2446 return; 2447 } 2448 break; 2449 case 0x4d: 2450 snprintf(result, len, 2451 "Tagged Overlapped Commands (0x%02x = TASK TAG)", ascq); 2452 return; 2453 case 0x70: 2454 snprintf(result, len, 2455 "Decompression Exception Short Algorithm ID OF 0x%02x", 2456 ascq); 2457 return; 2458 default: 2459 break; 2460 } 2461 2462 /* Check for a fixed description. */ 2463 for (i = 0; adesc[i].description != NULL; i++) { 2464 if (adesc[i].asc == asc && adesc[i].ascq == ascq) { 2465 strlcpy(result, adesc[i].description, len); 2466 return; 2467 } 2468 } 2469 2470 /* Just print out the ASC and ASCQ values as a description. */ 2471 snprintf(result, len, "ASC 0x%02x ASCQ 0x%02x", asc, ascq); 2472 } 2473 #endif /* SCSITERSE */ 2474 2475 void 2476 scsi_print_sense(struct scsi_xfer *xs) 2477 { 2478 struct scsi_sense_data *sense = &xs->sense; 2479 char *sbs; 2480 int32_t info; 2481 u_int8_t serr = sense->error_code & SSD_ERRCODE; 2482 2483 sc_print_addr(xs->sc_link); 2484 2485 /* XXX For error 0x71, current opcode is not the relevant one. */ 2486 printf("%sCheck Condition (error %#x) on opcode 0x%x\n", 2487 (serr == SSD_ERRCODE_DEFERRED) ? "DEFERRED " : "", serr, 2488 xs->cmd->opcode); 2489 2490 if (serr != SSD_ERRCODE_CURRENT && serr != SSD_ERRCODE_DEFERRED) { 2491 if (ISSET(sense->error_code, SSD_ERRCODE_VALID)) { 2492 struct scsi_sense_data_unextended *usense = 2493 (struct scsi_sense_data_unextended *)sense; 2494 printf(" AT BLOCK #: %d (decimal)", 2495 _3btol(usense->block)); 2496 } 2497 return; 2498 } 2499 2500 printf(" SENSE KEY: %s\n", scsi_decode_sense(sense, 2501 DECODE_SENSE_KEY)); 2502 2503 if (sense->flags & (SSD_FILEMARK | SSD_EOM | SSD_ILI)) { 2504 char pad = ' '; 2505 2506 printf(" "); 2507 if (ISSET(sense->flags, SSD_FILEMARK)) { 2508 printf("%c Filemark Detected", pad); 2509 pad = ','; 2510 } 2511 if (ISSET(sense->flags, SSD_EOM)) { 2512 printf("%c EOM Detected", pad); 2513 pad = ','; 2514 } 2515 if (ISSET(sense->flags, SSD_ILI)) 2516 printf("%c Incorrect Length Indicator Set", pad); 2517 printf("\n"); 2518 } 2519 2520 /* 2521 * It is inconvenient to use device type to figure out how to 2522 * format the info fields. So print them as 32 bit integers. 2523 */ 2524 info = _4btol(&sense->info[0]); 2525 if (info) 2526 printf(" INFO: 0x%x (VALID flag %s)\n", info, 2527 ISSET(sense->error_code, SSD_ERRCODE_VALID) ? "on" : "off"); 2528 2529 if (sense->extra_len < 4) 2530 return; 2531 2532 info = _4btol(&sense->cmd_spec_info[0]); 2533 if (info) 2534 printf(" COMMAND INFO: 0x%x\n", info); 2535 sbs = scsi_decode_sense(sense, DECODE_ASC_ASCQ); 2536 if (strlen(sbs) > 0) 2537 printf(" ASC/ASCQ: %s\n", sbs); 2538 if (sense->fru != 0) 2539 printf(" FRU CODE: 0x%x\n", sense->fru); 2540 sbs = scsi_decode_sense(sense, DECODE_SKSV); 2541 if (strlen(sbs) > 0) 2542 printf(" SKSV: %s\n", sbs); 2543 } 2544 2545 char * 2546 scsi_decode_sense(struct scsi_sense_data *sense, int flag) 2547 { 2548 static char rqsbuf[132]; 2549 u_int16_t count; 2550 u_int8_t skey, spec_1; 2551 int len; 2552 2553 bzero(rqsbuf, sizeof(rqsbuf)); 2554 2555 skey = sense->flags & SSD_KEY; 2556 spec_1 = sense->sense_key_spec_1; 2557 count = _2btol(&sense->sense_key_spec_2); 2558 2559 switch (flag) { 2560 case DECODE_SENSE_KEY: 2561 strlcpy(rqsbuf, sense_keys[skey], sizeof(rqsbuf)); 2562 break; 2563 case DECODE_ASC_ASCQ: 2564 asc2ascii(sense->add_sense_code, sense->add_sense_code_qual, 2565 rqsbuf, sizeof(rqsbuf)); 2566 break; 2567 case DECODE_SKSV: 2568 if (sense->extra_len < 9 || !ISSET(spec_1, SSD_SCS_VALID)) 2569 break; 2570 switch (skey) { 2571 case SKEY_ILLEGAL_REQUEST: 2572 len = snprintf(rqsbuf, sizeof rqsbuf, 2573 "Error in %s, Offset %d", 2574 ISSET(spec_1, SSD_SCS_CDB_ERROR) ? "CDB" : 2575 "Parameters", count); 2576 if ((len != -1 && len < sizeof rqsbuf) && 2577 ISSET(spec_1, SSD_SCS_VALID_BIT_INDEX)) 2578 snprintf(rqsbuf+len, sizeof rqsbuf - len, 2579 ", bit %d", spec_1 & SSD_SCS_BIT_INDEX); 2580 break; 2581 case SKEY_RECOVERED_ERROR: 2582 case SKEY_MEDIUM_ERROR: 2583 case SKEY_HARDWARE_ERROR: 2584 snprintf(rqsbuf, sizeof rqsbuf, 2585 "Actual Retry Count: %d", count); 2586 break; 2587 case SKEY_NOT_READY: 2588 snprintf(rqsbuf, sizeof rqsbuf, 2589 "Progress Indicator: %d", count); 2590 break; 2591 default: 2592 break; 2593 } 2594 break; 2595 default: 2596 break; 2597 } 2598 2599 return rqsbuf; 2600 } 2601 2602 void 2603 scsi_cmd_rw_decode(struct scsi_generic *cmd, u_int64_t *blkno, 2604 u_int32_t *nblks) 2605 { 2606 switch (cmd->opcode) { 2607 case READ_COMMAND: 2608 case WRITE_COMMAND: { 2609 struct scsi_rw *rw = (struct scsi_rw *)cmd; 2610 *blkno = _3btol(rw->addr) & (SRW_TOPADDR << 16 | 0xffff); 2611 *nblks = rw->length ? rw->length : 0x100; 2612 break; 2613 } 2614 case READ_BIG: 2615 case WRITE_BIG: { 2616 struct scsi_rw_big *rwb = (struct scsi_rw_big *)cmd; 2617 *blkno = _4btol(rwb->addr); 2618 *nblks = _2btol(rwb->length); 2619 break; 2620 } 2621 case READ_12: 2622 case WRITE_12: { 2623 struct scsi_rw_12 *rw12 = (struct scsi_rw_12 *)cmd; 2624 *blkno = _4btol(rw12->addr); 2625 *nblks = _4btol(rw12->length); 2626 break; 2627 } 2628 case READ_16: 2629 case WRITE_16: { 2630 struct scsi_rw_16 *rw16 = (struct scsi_rw_16 *)cmd; 2631 *blkno = _8btol(rw16->addr); 2632 *nblks = _4btol(rw16->length); 2633 break; 2634 } 2635 default: 2636 panic("scsi_cmd_rw_decode: bad opcode 0x%02x", cmd->opcode); 2637 } 2638 } 2639 2640 #ifdef SCSIDEBUG 2641 u_int32_t scsidebug_buses = SCSIDEBUG_BUSES; 2642 u_int32_t scsidebug_targets = SCSIDEBUG_TARGETS; 2643 u_int32_t scsidebug_luns = SCSIDEBUG_LUNS; 2644 int scsidebug_level = SCSIDEBUG_LEVEL; 2645 2646 const char *flagnames[16] = { 2647 "REMOVABLE", 2648 "MEDIA LOADED", 2649 "READONLY", 2650 "OPEN", 2651 "DB1", 2652 "DB2", 2653 "DB3", 2654 "DB4", 2655 "EJECTING", 2656 "ATAPI", 2657 "2NDBUS", 2658 "UMASS", 2659 "VIRTUAL", 2660 "OWN", 2661 "FLAG0x4000", 2662 "FLAG0x8000" 2663 }; 2664 2665 const char *quirknames[16] = { 2666 "AUTOSAVE", 2667 "NOSYNC", 2668 "NOWIDE", 2669 "NOTAGS", 2670 "QUIRK0x0010", 2671 "QUIRK0x0020", 2672 "QUIRK0x0040", 2673 "QUIRK0x0080", 2674 "NOSYNCCACHE", 2675 "NOSENSE", 2676 "LITTLETOC", 2677 "NOCAPACITY", 2678 "QUIRK0x1000", 2679 "NODOORLOCK", 2680 "ONLYBIG", 2681 "QUIRK0x8000", 2682 }; 2683 2684 const char *devicetypenames[32] = { 2685 "T_DIRECT", 2686 "T_SEQUENTIAL", 2687 "T_PRINTER", 2688 "T_PROCESSOR", 2689 "T_WORM", 2690 "T_CDROM", 2691 "T_SCANNER", 2692 "T_OPTICAL", 2693 "T_CHANGER", 2694 "T_COMM", 2695 "T_ASC0", 2696 "T_ASC1", 2697 "T_STROARRAY", 2698 "T_ENCLOSURE", 2699 "T_RDIRECT", 2700 "T_OCRW", 2701 "T_BCC", 2702 "T_OSD", 2703 "T_ADC", 2704 "T_RESERVED", 2705 "T_RESERVED", 2706 "T_RESERVED", 2707 "T_RESERVED", 2708 "T_RESERVED", 2709 "T_RESERVED", 2710 "T_RESERVED", 2711 "T_RESERVED", 2712 "T_RESERVED", 2713 "T_RESERVED", 2714 "T_RESERVED", 2715 "T_WELL_KNOWN_LU", 2716 "T_NODEVICE" 2717 }; 2718 2719 /* 2720 * Print out sense data details. 2721 */ 2722 void 2723 scsi_show_sense(struct scsi_xfer *xs) 2724 { 2725 struct scsi_sense_data *sense = &xs->sense; 2726 struct scsi_link *link = xs->sc_link; 2727 2728 SC_DEBUG(link, SDEV_DB1, 2729 ("code:%#x valid:%d key:%#x ili:%d eom:%d fmark:%d extra:%d\n", 2730 sense->error_code & SSD_ERRCODE, 2731 sense->error_code & SSD_ERRCODE_VALID ? 1 : 0, 2732 sense->flags & SSD_KEY, 2733 sense->flags & SSD_ILI ? 1 : 0, 2734 sense->flags & SSD_EOM ? 1 : 0, 2735 sense->flags & SSD_FILEMARK ? 1 : 0, 2736 sense->extra_len)); 2737 2738 if (ISSET(xs->sc_link->flags, SDEV_DB1)) 2739 scsi_show_mem((u_char *)&xs->sense, sizeof(xs->sense)); 2740 2741 scsi_print_sense(xs); 2742 } 2743 2744 /* 2745 * Given a scsi_xfer, dump the request, in all its glory 2746 */ 2747 void 2748 scsi_show_xs(struct scsi_xfer *xs) 2749 { 2750 u_char *b = (u_char *)xs->cmd; 2751 int i = 0; 2752 2753 if (!ISSET(xs->sc_link->flags, SDEV_DB1)) 2754 return; 2755 2756 sc_print_addr(xs->sc_link); 2757 printf("xs (%p): ", xs); 2758 2759 printf("flg(0x%x)", xs->flags); 2760 printf("link(%p)", xs->sc_link); 2761 printf("retr(0x%x)", xs->retries); 2762 printf("timo(0x%x)", xs->timeout); 2763 printf("data(%p)", xs->data); 2764 printf("res(0x%zx)", xs->resid); 2765 printf("err(0x%x)", xs->error); 2766 printf("bp(%p)\n", xs->bp); 2767 2768 sc_print_addr(xs->sc_link); 2769 printf("cmd (%p): ", xs->cmd); 2770 2771 if (!ISSET(xs->flags, SCSI_RESET)) { 2772 while (i < xs->cmdlen) { 2773 if (i) 2774 printf(","); 2775 printf("%x", b[i++]); 2776 } 2777 printf("-[%d bytes]\n", xs->datalen); 2778 } else 2779 printf("-RESET-\n"); 2780 2781 if (xs->datalen && ISSET(xs->flags, SCSI_DATA_OUT)) 2782 scsi_show_mem(xs->data, min(64, xs->datalen)); 2783 } 2784 2785 void 2786 scsi_show_mem(u_char *address, int num) 2787 { 2788 int x; 2789 2790 printf("------------------------------"); 2791 for (x = 0; x < num; x++) { 2792 if ((x % 16) == 0) 2793 printf("\n%03d: ", x); 2794 printf("%02x ", *address++); 2795 } 2796 printf("\n------------------------------\n"); 2797 } 2798 2799 void 2800 scsi_show_flags(u_int16_t flags, const char **names) 2801 { 2802 int i, first; 2803 2804 first = 1; 2805 printf("<"); 2806 for (i = 0; i < 16; i++) { 2807 if (ISSET(flags, 1 << i)) { 2808 if (first == 0) 2809 printf(", "); 2810 else 2811 first = 0; 2812 printf("%s", names[i]); 2813 } 2814 } 2815 printf(">"); 2816 } 2817 #endif /* SCSIDEBUG */ 2818