1 /* 2 * Implementation of Utility functions for all SCSI device types. 3 * 4 * Copyright (c) 1997, 1998 Justin T. Gibbs. 5 * Copyright (c) 1997, 1998 Kenneth D. Merry. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions, and the following disclaimer, 13 * without modification, immediately at the beginning of the file. 14 * 2. The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 21 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 * $FreeBSD: src/sys/cam/scsi/scsi_all.c,v 1.14.2.11 2003/10/30 15:06:35 thomas Exp $ 30 * $DragonFly: src/sys/bus/cam/scsi/scsi_all.c,v 1.7 2006/12/22 23:12:16 swildner Exp $ 31 */ 32 33 #include <sys/param.h> 34 35 #ifdef _KERNEL 36 37 #include <opt_scsi.h> 38 #include <sys/systm.h> 39 40 #else 41 42 #include <errno.h> 43 #include <stdio.h> 44 #include <string.h> 45 46 #define ksnprintf snprintf /* ick, userland uses us too */ 47 #define kprintf printf 48 #endif 49 50 #include "../cam.h" 51 #include "../cam_ccb.h" 52 #include "../cam_xpt.h" 53 #include "../cam_xpt_periph.h" 54 #include "scsi_all.h" 55 #ifndef _KERNEL 56 #include <sys/camlib.h> 57 58 #ifndef FALSE 59 #define FALSE 0 60 #endif /* FALSE */ 61 #ifndef TRUE 62 #define TRUE 1 63 #endif /* TRUE */ 64 #define ERESTART -1 /* restart syscall */ 65 #define EJUSTRETURN -2 /* don't modify regs, just return */ 66 #endif /* !_KERNEL */ 67 68 const char *scsi_sense_key_text[] = 69 { 70 "NO SENSE", 71 "RECOVERED ERROR", 72 "NOT READY", 73 "MEDIUM ERROR", 74 "HARDWARE FAILURE", 75 "ILLEGAL REQUEST", 76 "UNIT ATTENTION", 77 "DATA PROTECT", 78 "BLANK CHECK", 79 "Vendor Specific", 80 "COPY ABORTED", 81 "ABORTED COMMAND", 82 "EQUAL", 83 "VOLUME OVERFLOW", 84 "MISCOMPARE", 85 "RESERVED" 86 }; 87 88 #if !defined(SCSI_NO_OP_STRINGS) 89 90 #define D 0x001 91 #define T 0x002 92 #define L 0x004 93 #define P 0x008 94 #define W 0x010 95 #define R 0x020 96 #define S 0x040 97 #define O 0x080 98 #define M 0x100 99 #define C 0x200 100 #define A 0x400 101 #define E 0x800 102 103 #define ALL 0xFFF 104 105 /* 106 * WARNING: You must update the num_ops field below for this quirk table 107 * entry if you add more entries. 108 */ 109 static struct op_table_entry plextor_cd_ops[] = { 110 {0xD8, R, "CD-DA READ"} 111 }; 112 113 static struct scsi_op_quirk_entry scsi_op_quirk_table[] = { 114 { 115 /* 116 * I believe that 0xD8 is the Plextor proprietary command 117 * to read CD-DA data. I'm not sure which Plextor CDROM 118 * models support the command, though. I know for sure 119 * that the 4X, 8X, and 12X models do, and presumably the 120 * 12-20X does. I don't know about any earlier models, 121 * though. If anyone has any more complete information, 122 * feel free to change this quirk entry. 123 */ 124 {T_CDROM, SIP_MEDIA_REMOVABLE, "PLEXTOR", "CD-ROM PX*", "*"}, 125 1, /* number of vendor-specific opcodes for this entry */ 126 plextor_cd_ops 127 } 128 }; 129 130 static struct op_table_entry scsi_op_codes[] = { 131 /* 132 * From: ftp://ftp.symbios.com/pub/standards/io/t10/drafts/spc/op-num.txt 133 * Modifications by Kenneth Merry (ken@FreeBSD.ORG) 134 * 135 * Note: order is important in this table, scsi_op_desc() currently 136 * depends on the opcodes in the table being in order to save search time. 137 */ 138 /* 139 * File: OP-NUM.TXT 140 * 141 * SCSI Operation Codes 142 * Numeric Sorted Listing 143 * as of 11/13/96 144 * 145 * D - DIRECT ACCESS DEVICE (SBC) device column key 146 * .T - SEQUENTIAL ACCESS DEVICE (SSC) ------------------- 147 * . L - PRINTER DEVICE (SSC) M = Mandatory 148 * . P - PROCESSOR DEVICE (SPC) O = Optional 149 * . .W - WRITE ONCE READ MULTIPLE DEVICE (SBC) V = Vendor specific 150 * . . R - CD DEVICE (MMC) R = Reserved 151 * . . S - SCANNER DEVICE (SGC) Z = Obsolete 152 * . . .O - OPTICAL MEMORY DEVICE (SBC) 153 * . . . M - MEDIA CHANGER DEVICE (SMC) 154 * . . . C - COMMUNICATION DEVICE (SSC) 155 * . . . .A - STORAGE ARRAY DEVICE (SCC) 156 * . . . . E - ENCLOSURE SERVICES DEVICE (SES) 157 * OP DTLPWRSOMCAE Description 158 * -- ------------ ---------------------------------------------------- */ 159 /* 00 MMMMMMMMMMMM TEST UNIT READY */ 160 {0x00, ALL, "TEST UNIT READY"}, 161 162 /* 01 M REWIND */ 163 {0x01, T, "REWIND"}, 164 /* 01 Z V ZO ZO REZERO UNIT */ 165 {0x01, D|L|W|O|M, "REZERO UNIT"}, 166 167 /* 02 VVVVVV V */ 168 169 /* 03 MMMMMMMMMMMM REQUEST SENSE */ 170 {0x03, ALL, "REQUEST SENSE"}, 171 172 /* 04 M O O FORMAT UNIT */ 173 {0x04, D|R|O, "FORMAT UNIT"}, 174 /* 04 O FORMAT MEDIUM */ 175 {0x04, T, "FORMAT MEDIUM"}, 176 /* 04 O FORMAT */ 177 {0x04, L, "FORMAT"}, 178 179 /* 05 VMVVVV V READ BLOCK LIMITS */ 180 {0x05, T, "READ BLOCK LIMITS"}, 181 182 /* 06 VVVVVV V */ 183 184 /* 07 OVV O OV REASSIGN BLOCKS */ 185 {0x07, D|W|O, "REASSIGN BLOCKS"}, 186 /* 07 O INITIALIZE ELEMENT STATUS */ 187 {0x07, M, "INITIALIZE ELEMENT STATUS"}, 188 189 /* 08 OMV OO OV READ(06) */ 190 {0x08, D|T|W|R|O, "READ(06)"}, 191 /* 08 O RECEIVE */ 192 {0x08, P, "RECEIVE"}, 193 /* 08 M GET MESSAGE(06) */ 194 {0x08, C, "GET MESSAGE(06)"}, 195 196 /* 09 VVVVVV V */ 197 198 /* 0A OM O OV WRITE(06) */ 199 {0x0A, D|T|W|O, "WRITE(06)"}, 200 /* 0A M SEND(06) */ 201 {0x0A, P, "SEND(06)"}, 202 /* 0A M SEND MESSAGE(06) */ 203 {0x0A, C, "SEND MESSAGE(06)"}, 204 /* 0A M PRINT */ 205 {0x0A, L, "PRINT"}, 206 207 /* 0B Z ZO ZV SEEK(06) */ 208 {0x0B, D|W|R|O, "SEEK(06)"}, 209 /* 0B O SLEW AND PRINT */ 210 {0x0B, L, "SLEW AND PRINT"}, 211 212 /* 0C VVVVVV V */ 213 /* 0D VVVVVV V */ 214 /* 0E VVVVVV V */ 215 /* 0F VOVVVV V READ REVERSE */ 216 {0x0F, T, "READ REVERSE"}, 217 218 /* 10 VM VVV WRITE FILEMARKS */ 219 {0x10, T, "WRITE FILEMARKS"}, 220 /* 10 O O SYNCHRONIZE BUFFER */ 221 {0x10, L|W, "SYNCHRONIZE BUFFER"}, 222 223 /* 11 VMVVVV SPACE */ 224 {0x11, T, "SPACE"}, 225 226 /* 12 MMMMMMMMMMMM INQUIRY */ 227 {0x12, ALL, "INQUIRY"}, 228 229 /* 13 VOVVVV VERIFY(06) */ 230 {0x13, T, "VERIFY(06)"}, 231 232 /* 14 VOOVVV RECOVER BUFFERED DATA */ 233 {0x14, T|L, "RECOVER BUFFERED DATA"}, 234 235 /* 15 OMO OOOOOOOO MODE SELECT(06) */ 236 {0x15, ALL & ~(P), "MODE SELECT(06)"}, 237 238 /* 16 MMMOMMMM O RESERVE(06) */ 239 {0x16, D|T|L|P|W|R|S|O|E, "RESERVE(06)"}, 240 /* 16 M RESERVE ELEMENT(06) */ 241 {0x16, M, "RESERVE ELEMENT(06)"}, 242 243 /* 17 MMMOMMMM O RELEASE(06) */ 244 {0x17, ALL & ~(M|C|A), "RELEASE(06)"}, 245 /* 17 M RELEASE ELEMENT(06) */ 246 {0x17, M, "RELEASE ELEMENT(06)"}, 247 248 /* 18 OOOOOOOO COPY */ 249 {0x18, ALL & ~(M|C|A|E), "COPY"}, 250 251 /* 19 VMVVVV ERASE */ 252 {0x19, T, "ERASE"}, 253 254 /* 1A OMO OOOOOOOO MODE SENSE(06) */ 255 {0x1A, ALL & ~(P), "MODE SENSE(06)"}, 256 257 /* 1B O OM O STOP START UNIT */ 258 {0x1B, D|W|R|O, "STOP START UNIT"}, 259 /* 1B O LOAD UNLOAD */ 260 {0x1B, T, "LOAD UNLOAD"}, 261 /* 1B O SCAN */ 262 {0x1B, S, "SCAN"}, 263 /* 1B O STOP PRINT */ 264 {0x1B, L, "STOP PRINT"}, 265 266 /* 1C OOOOOOOOOO M RECEIVE DIAGNOSTIC RESULTS */ 267 {0x1C, ALL & ~(A), "RECEIVE DIAGNOSTIC RESULTS"}, 268 269 /* 1D MMMMMMMMMMMM SEND DIAGNOSTIC */ 270 {0x1D, ALL, "SEND DIAGNOSTIC"}, 271 272 /* 1E OO OM OO PREVENT ALLOW MEDIUM REMOVAL */ 273 {0x1E, D|T|W|R|O|M, "PREVENT ALLOW MEDIUM REMOVAL"}, 274 275 /* 1F */ 276 /* 20 V VV V */ 277 /* 21 V VV V */ 278 /* 22 V VV V */ 279 /* 23 V VV V */ 280 281 /* 24 V VVM SET WINDOW */ 282 {0x24, S, "SET WINDOW"}, 283 284 /* 25 M M M READ CAPACITY */ 285 {0x25, D|W|O, "READ CAPACITY"}, 286 /* 25 M READ CD RECORDED CAPACITY */ 287 {0x25, R, "READ CD RECORDED CAPACITY"}, 288 /* 25 O GET WINDOW */ 289 {0x25, S, "GET WINDOW"}, 290 291 /* 26 V VV */ 292 /* 27 V VV */ 293 294 /* 28 M MMMM READ(10) */ 295 {0x28, D|W|R|S|O, "READ(10)"}, 296 /* 28 O GET MESSAGE(10) */ 297 {0x28, C, "GET MESSAGE(10)"}, 298 299 /* 29 V VV O READ GENERATION */ 300 {0x29, O, "READ GENERATION"}, 301 302 /* 2A M MM M WRITE(10) */ 303 {0x2A, D|W|R|O, "WRITE(10)"}, 304 /* 2A O SEND(10) */ 305 {0x2A, S, "SEND(10)"}, 306 /* 2A O SEND MESSAGE(10) */ 307 {0x2A, C, "SEND MESSAGE(10)"}, 308 309 /* 2B O OM O SEEK(10) */ 310 {0x2B, D|W|R|O, "SEEK(10)"}, 311 /* 2B O LOCATE */ 312 {0x2B, T, "LOCATE"}, 313 /* 2B O POSITION TO ELEMENT */ 314 {0x2B, M, "POSITION TO ELEMENT"}, 315 316 /* 2C V O ERASE(10) */ 317 {0x2C, O, "ERASE(10)"}, 318 319 /* 2D V O O READ UPDATED BLOCK */ 320 {0x2D, W|O, "READ UPDATED BLOCK"}, 321 322 /* 2E O O O WRITE AND VERIFY(10) */ 323 {0x2E, D|W|O, "WRITE AND VERIFY(10)"}, 324 325 /* 2F O OO O VERIFY(10) */ 326 {0x2F, D|W|R|O, "VERIFY(10)"}, 327 328 /* 30 Z ZO Z SEARCH DATA HIGH(10) */ 329 {0x30, D|W|R|O, "SEARCH DATA HIGH(10)"}, 330 331 /* 31 Z ZO Z SEARCH DATA EQUAL(10) */ 332 {0x31, D|W|R|O, "SEARCH DATA EQUAL(10)"}, 333 /* 31 O OBJECT POSITION */ 334 {0x31, S, "OBJECT POSITION"}, 335 336 /* 32 Z ZO Z SEARCH DATA LOW(10) */ 337 {0x32, D|W|R|O, "SEARCH DATA LOW(10"}, 338 339 /* 33 O OO O SET LIMITS(10) */ 340 {0x33, D|W|R|O, "SET LIMITS(10)"}, 341 342 /* 34 O OO O PRE-FETCH */ 343 {0x34, D|W|R|O, "PRE-FETCH"}, 344 /* 34 O READ POSITION */ 345 {0x34, T, "READ POSITION"}, 346 /* 34 O GET DATA BUFFER STATUS */ 347 {0x34, S, "GET DATA BUFFER STATUS"}, 348 349 /* 35 O OM O SYNCHRONIZE CACHE */ 350 {0x35, D|W|R|O, "SYNCHRONIZE CACHE"}, 351 352 /* 36 O OO O LOCK UNLOCK CACHE */ 353 {0x36, D|W|R|O, "LOCK UNLOCK CACHE"}, 354 355 /* 37 O O READ DEFECT DATA(10) */ 356 {0x37, D|O, "READ DEFECT DATA(10)"}, 357 358 /* 38 O O MEDIUM SCAN */ 359 {0x38, W|O, "MEDIUM SCAN"}, 360 361 /* 39 OOOOOOOO COMPARE */ 362 {0x39, ALL & ~(M|C|A|E), "COMPARE"}, 363 364 /* 3A OOOOOOOO COPY AND VERIFY */ 365 {0x3A, ALL & ~(M|C|A|E), "COPY AND VERIFY"}, 366 367 /* 3B OOOOOOOOOO O WRITE BUFFER */ 368 {0x3B, ALL & ~(A), "WRITE BUFFER"}, 369 370 /* 3C OOOOOOOOOO READ BUFFER */ 371 {0x3C, ALL & ~(A|E),"READ BUFFER"}, 372 373 /* 3D O O UPDATE BLOCK */ 374 {0x3D, W|O, "UPDATE BLOCK"}, 375 376 /* 3E O OO O READ LONG */ 377 {0x3E, D|W|R|O, "READ LONG"}, 378 379 /* 3F O O O WRITE LONG */ 380 {0x3F, D|W|O, "WRITE LONG"}, 381 382 /* 40 OOOOOOOOOO CHANGE DEFINITION */ 383 {0x40, ALL & ~(A|E),"CHANGE DEFINITION"}, 384 385 /* 41 O WRITE SAME */ 386 {0x41, D, "WRITE SAME"}, 387 388 /* 42 M READ SUB-CHANNEL */ 389 {0x42, R, "READ SUB-CHANNEL"}, 390 391 /* 43 M READ TOC/PMA/ATIP {MMC Proposed} */ 392 {0x43, R, "READ TOC/PMA/ATIP {MMC Proposed}"}, 393 394 /* 44 M REPORT DENSITY SUPPORT */ 395 {0x44, T, "REPORT DENSITY SUPPORT"}, 396 /* 44 M READ HEADER */ 397 {0x44, R, "READ HEADER"}, 398 399 /* 45 O PLAY AUDIO(10) */ 400 {0x45, R, "PLAY AUDIO(10)"}, 401 402 /* 46 */ 403 404 /* 47 O PLAY AUDIO MSF */ 405 {0x47, R, "PLAY AUDIO MSF"}, 406 407 /* 48 O PLAY AUDIO TRACK INDEX */ 408 {0x48, R, "PLAY AUDIO TRACK INDEX"}, 409 410 /* 49 O PLAY TRACK RELATIVE(10) */ 411 {0x49, R, "PLAY TRACK RELATIVE(10)"}, 412 413 /* 4A */ 414 415 /* 4B O PAUSE/RESUME */ 416 {0x4B, R, "PAUSE/RESUME"}, 417 418 /* 4C OOOOOOOOOOO LOG SELECT */ 419 {0x4C, ALL & ~(E), "LOG SELECT"}, 420 421 /* 4D OOOOOOOOOOO LOG SENSE */ 422 {0x4D, ALL & ~(E), "LOG SENSE"}, 423 424 /* 4E O STOP PLAY/SCAN {MMC Proposed} */ 425 {0x4E, R, "STOP PLAY/SCAN {MMC Proposed}"}, 426 427 /* 4F */ 428 429 /* 50 O XDWRITE(10) */ 430 {0x50, D, "XDWRITE(10)"}, 431 432 /* 51 O XPWRITE(10) */ 433 {0x51, D, "XPWRITE(10)"}, 434 /* 51 M READ DISC INFORMATION {MMC Proposed} */ 435 {0x51, R, "READ DISC INFORMATION {MMC Proposed}"}, 436 437 /* 52 O XDREAD(10) */ 438 {0x52, D, "XDREAD(10)"}, 439 /* 52 M READ TRACK INFORMATION {MMC Proposed} */ 440 {0x52, R, "READ TRACK INFORMATION {MMC Proposed}"}, 441 442 /* 53 M RESERVE TRACK {MMC Proposed} */ 443 {0x53, R, "RESERVE TRACK {MMC Proposed}"}, 444 445 /* 54 O SEND OPC INFORMATION {MMC Proposed} */ 446 {0x54, R, "SEND OPC INFORMATION {MMC Proposed}"}, 447 448 /* 55 OOO OOOOOOOO MODE SELECT(10) */ 449 {0x55, ALL & ~(P), "MODE SELECT(10)"}, 450 451 /* 56 MMMOMMMM O RESERVE(10) */ 452 {0x56, ALL & ~(M|C|A), "RESERVE(10)"}, 453 /* 56 M RESERVE ELEMENT(10) */ 454 {0x56, M, "RESERVE ELEMENT(10)"}, 455 456 /* 57 MMMOMMMM O RELEASE(10) */ 457 {0x57, ALL & ~(M|C|A), "RELEASE(10"}, 458 /* 57 M RELEASE ELEMENT(10) */ 459 {0x57, M, "RELEASE ELEMENT(10)"}, 460 461 /* 58 O REPAIR TRACK {MMC Proposed} */ 462 {0x58, R, "REPAIR TRACK {MMC Proposed}"}, 463 464 /* 59 O READ MASTER CUE {MMC Proposed} */ 465 {0x59, R, "READ MASTER CUE {MMC Proposed}"}, 466 467 /* 5A OOO OOOOOOOO MODE SENSE(10) */ 468 {0x5A, ALL & ~(P), "MODE SENSE(10)"}, 469 470 /* 5B M CLOSE TRACK/SESSION {MMC Proposed} */ 471 {0x5B, R, "CLOSE TRACK/SESSION {MMC Proposed}"}, 472 473 /* 5C O READ BUFFER CAPACITY {MMC Proposed} */ 474 {0x5C, R, "READ BUFFER CAPACITY {MMC Proposed}"}, 475 476 /* 5D O SEND CUE SHEET {MMC Proposed} */ 477 {0x5D, R, "SEND CUE SHEET {MMC Proposed}"}, 478 479 /* 5E OOOOOOOOO O PERSISTENT RESERVE IN */ 480 {0x5E, ALL & ~(C|A),"PERSISTENT RESERVE IN"}, 481 482 /* 5F OOOOOOOOO O PERSISTENT RESERVE OUT */ 483 {0x5F, ALL & ~(C|A),"PERSISTENT RESERVE OUT"}, 484 485 /* 80 O XDWRITE EXTENDED(16) */ 486 {0x80, D, "XDWRITE EXTENDED(16)"}, 487 488 /* 81 O REBUILD(16) */ 489 {0x81, D, "REBUILD(16)"}, 490 491 /* 82 O REGENERATE(16) */ 492 {0x82, D, "REGENERATE(16)"}, 493 494 /* 83 */ 495 /* 84 */ 496 /* 85 */ 497 /* 86 */ 498 /* 87 */ 499 /* 88 */ 500 /* 89 */ 501 /* 8A */ 502 /* 8B */ 503 /* 8C */ 504 /* 8D */ 505 /* 8E */ 506 /* 8F */ 507 /* 90 */ 508 /* 91 */ 509 /* 92 */ 510 /* 93 */ 511 /* 94 */ 512 /* 95 */ 513 /* 96 */ 514 /* 97 */ 515 /* 98 */ 516 /* 99 */ 517 /* 9A */ 518 /* 9B */ 519 /* 9C */ 520 /* 9D */ 521 /* 9E */ 522 /* 9F */ 523 524 /* A0 OOOOOOOOOOO REPORT LUNS */ 525 {0xA0, ALL & ~(E), "REPORT LUNS"}, 526 527 /* A1 O BLANK {MMC Proposed} */ 528 {0xA1, R, "BLANK {MMC Proposed}"}, 529 530 /* A2 O WRITE CD MSF {MMC Proposed} */ 531 {0xA2, R, "WRITE CD MSF {MMC Proposed}"}, 532 533 /* A3 M MAINTENANCE (IN) */ 534 {0xA3, A, "MAINTENANCE (IN)"}, 535 536 /* A4 O MAINTENANCE (OUT) */ 537 {0xA4, A, "MAINTENANCE (OUT)"}, 538 539 /* A5 O M MOVE MEDIUM */ 540 {0xA5, T|M, "MOVE MEDIUM"}, 541 /* A5 O PLAY AUDIO(12) */ 542 {0xA5, R, "PLAY AUDIO(12)"}, 543 544 /* A6 O EXCHANGE MEDIUM */ 545 {0xA6, M, "EXCHANGE MEDIUM"}, 546 /* A6 O LOAD/UNLOAD CD {MMC Proposed} */ 547 {0xA6, R, "LOAD/UNLOAD CD {MMC Proposed}"}, 548 549 /* A7 OO OO OO MOVE MEDIUM ATTACHED */ 550 {0xA7, D|T|W|R|O|M, "MOVE MEDIUM ATTACHED"}, 551 552 /* A8 OM O READ(12) */ 553 {0xA8, W|R|O, "READ(12)"}, 554 /* A8 O GET MESSAGE(12) */ 555 {0xA8, C, "GET MESSAGE(12)"}, 556 557 /* A9 O PLAY TRACK RELATIVE(12) */ 558 {0xA9, R, "PLAY TRACK RELATIVE(12)"}, 559 560 /* AA O O WRITE(12) */ 561 {0xAA, W|O, "WRITE(12)"}, 562 /* AA O WRITE CD(12) {MMC Proposed} */ 563 {0xAA, R, "WRITE CD(12) {MMC Proposed}"}, 564 /* AA O SEND MESSAGE(12) */ 565 {0xAA, C, "SEND MESSAGE(12)"}, 566 567 /* AB */ 568 569 /* AC O ERASE(12) */ 570 {0xAC, O, "ERASE(12)"}, 571 572 /* AD */ 573 574 /* AE O O WRITE AND VERIFY(12) */ 575 {0xAE, W|O, "WRITE AND VERIFY(12)"}, 576 577 /* AF OO O VERIFY(12) */ 578 {0xAF, W|R|O, "VERIFY(12)"}, 579 580 /* B0 ZO Z SEARCH DATA HIGH(12) */ 581 {0xB0, W|R|O, "SEARCH DATA HIGH(12)"}, 582 583 /* B1 ZO Z SEARCH DATA EQUAL(12) */ 584 {0xB1, W|R|O, "SEARCH DATA EQUAL(12)"}, 585 586 /* B2 ZO Z SEARCH DATA LOW(12) */ 587 {0xB2, W|R|O, "SEARCH DATA LOW(12)"}, 588 589 /* B3 OO O SET LIMITS(12) */ 590 {0xB3, W|R|O, "SET LIMITS(12)"}, 591 592 /* B4 OO OO OO READ ELEMENT STATUS ATTACHED */ 593 {0xB4, D|T|W|R|O|M, "READ ELEMENT STATUS ATTACHED"}, 594 595 /* B5 O REQUEST VOLUME ELEMENT ADDRESS */ 596 {0xB5, M, "REQUEST VOLUME ELEMENT ADDRESS"}, 597 598 /* B6 O SEND VOLUME TAG */ 599 {0xB6, M, "SEND VOLUME TAG"}, 600 601 /* B7 O READ DEFECT DATA(12) */ 602 {0xB7, O, "READ DEFECT DATA(12)"}, 603 604 /* B8 O M READ ELEMENT STATUS */ 605 {0xB8, T|M, "READ ELEMENT STATUS"}, 606 /* B8 O SET CD SPEED {MMC Proposed} */ 607 {0xB8, R, "SET CD SPEED {MMC Proposed}"}, 608 609 /* B9 M READ CD MSF {MMC Proposed} */ 610 {0xB9, R, "READ CD MSF {MMC Proposed}"}, 611 612 /* BA O SCAN {MMC Proposed} */ 613 {0xBA, R, "SCAN {MMC Proposed}"}, 614 /* BA M REDUNDANCY GROUP (IN) */ 615 {0xBA, A, "REDUNDANCY GROUP (IN)"}, 616 617 /* BB O SET CD-ROM SPEED {proposed} */ 618 {0xBB, R, "SET CD-ROM SPEED {proposed}"}, 619 /* BB O REDUNDANCY GROUP (OUT) */ 620 {0xBB, A, "REDUNDANCY GROUP (OUT)"}, 621 622 /* BC O PLAY CD {MMC Proposed} */ 623 {0xBC, R, "PLAY CD {MMC Proposed}"}, 624 /* BC M SPARE (IN) */ 625 {0xBC, A, "SPARE (IN)"}, 626 627 /* BD M MECHANISM STATUS {MMC Proposed} */ 628 {0xBD, R, "MECHANISM STATUS {MMC Proposed}"}, 629 /* BD O SPARE (OUT) */ 630 {0xBD, A, "SPARE (OUT)"}, 631 632 /* BE O READ CD {MMC Proposed} */ 633 {0xBE, R, "READ CD {MMC Proposed}"}, 634 /* BE M VOLUME SET (IN) */ 635 {0xBE, A, "VOLUME SET (IN)"}, 636 637 /* BF O VOLUME SET (OUT) */ 638 {0xBF, A, "VOLUME SET (OUT)"} 639 }; 640 641 const char * 642 scsi_op_desc(u_int16_t opcode, struct scsi_inquiry_data *inq_data) 643 { 644 caddr_t match; 645 int i, j; 646 u_int16_t opmask; 647 u_int16_t pd_type; 648 int num_ops[2]; 649 struct op_table_entry *table[2]; 650 int num_tables; 651 652 pd_type = SID_TYPE(inq_data); 653 654 match = cam_quirkmatch((caddr_t)inq_data, 655 (caddr_t)scsi_op_quirk_table, 656 sizeof(scsi_op_quirk_table)/ 657 sizeof(*scsi_op_quirk_table), 658 sizeof(*scsi_op_quirk_table), 659 scsi_inquiry_match); 660 661 if (match != NULL) { 662 table[0] = ((struct scsi_op_quirk_entry *)match)->op_table; 663 num_ops[0] = ((struct scsi_op_quirk_entry *)match)->num_ops; 664 table[1] = scsi_op_codes; 665 num_ops[1] = sizeof(scsi_op_codes)/sizeof(scsi_op_codes[0]); 666 num_tables = 2; 667 } else { 668 /* 669 * If this is true, we have a vendor specific opcode that 670 * wasn't covered in the quirk table. 671 */ 672 if ((opcode > 0xBF) || ((opcode > 0x5F) && (opcode < 0x80))) 673 return("Vendor Specific Command"); 674 675 table[0] = scsi_op_codes; 676 num_ops[0] = sizeof(scsi_op_codes)/sizeof(scsi_op_codes[0]); 677 num_tables = 1; 678 } 679 680 /* RBC is 'Simplified' Direct Access Device */ 681 if (pd_type == T_RBC) 682 pd_type = T_DIRECT; 683 684 opmask = 1 << pd_type; 685 686 for (j = 0; j < num_tables; j++) { 687 for (i = 0;i < num_ops[j] && table[j][i].opcode <= opcode; i++){ 688 if ((table[j][i].opcode == opcode) 689 && ((table[j][i].opmask & opmask) != 0)) 690 return(table[j][i].desc); 691 } 692 } 693 694 /* 695 * If we can't find a match for the command in the table, we just 696 * assume it's a vendor specifc command. 697 */ 698 return("Vendor Specific Command"); 699 700 } 701 702 #else /* SCSI_NO_OP_STRINGS */ 703 704 const char * 705 scsi_op_desc(u_int16_t opcode, struct scsi_inquiry_data *inq_data) 706 { 707 return(""); 708 } 709 710 #endif 711 712 713 #include <sys/param.h> 714 715 716 #if !defined(SCSI_NO_SENSE_STRINGS) 717 #define SST(asc, ascq, action, desc) \ 718 asc, ascq, action, desc 719 #else 720 #define SST(asc, ascq, action, desc) \ 721 asc, ascq, action 722 #endif 723 724 static const char quantum[] = "QUANTUM"; 725 726 /* 727 * WARNING: You must update the num_ascs field below for this quirk table 728 * entry if you add more entries. 729 */ 730 static struct asc_table_entry quantum_fireball_entries[] = { 731 {SST(0x04, 0x0b, SS_START|SSQ_DECREMENT_COUNT|ENXIO, 732 "Logical unit not ready, initializing cmd. required")} 733 }; 734 735 static struct scsi_sense_quirk_entry asc_quirk_table[] = { 736 { 737 /* 738 * The Quantum Fireball ST and SE like to return 0x04 0x0b when 739 * they really should return 0x04 0x02. 0x04,0x0b isn't 740 * defined in any SCSI spec, and it isn't mentioned in the 741 * hardware manual for these drives. 742 */ 743 {T_DIRECT, SIP_MEDIA_FIXED, "QUANTUM", "FIREBALL S*", "*"}, 744 1, /* number of vendor-specific sense codes for this entry */ 745 quantum_fireball_entries 746 } 747 }; 748 749 static struct asc_table_entry asc_text[] = { 750 /* 751 * From File: ASC-NUM.TXT 752 * SCSI ASC/ASCQ Assignments 753 * Numeric Sorted Listing 754 * as of 5/12/97 755 * 756 * D - DIRECT ACCESS DEVICE (SBC) device column key 757 * .T - SEQUENTIAL ACCESS DEVICE (SSC) ------------------- 758 * . L - PRINTER DEVICE (SSC) blank = reserved 759 * . P - PROCESSOR DEVICE (SPC) not blank = allowed 760 * . .W - WRITE ONCE READ MULTIPLE DEVICE (SBC) 761 * . . R - CD DEVICE (MMC) 762 * . . S - SCANNER DEVICE (SGC) 763 * . . .O - OPTICAL MEMORY DEVICE (SBC) 764 * . . . M - MEDIA CHANGER DEVICE (SMC) 765 * . . . C - COMMUNICATION DEVICE (SSC) 766 * . . . .A - STORAGE ARRAY DEVICE (SCC) 767 * . . . . E - ENCLOSURE SERVICES DEVICE (SES) 768 * DTLPWRSOMCAE ASC ASCQ Action Description 769 * ------------ ---- ---- ------ -----------------------------------*/ 770 /* DTLPWRSOMCAE */{SST(0x00, 0x00, SS_NEPDEF, 771 "No additional sense information") }, 772 /* T S */{SST(0x00, 0x01, SS_DEF, 773 "Filemark detected") }, 774 /* T S */{SST(0x00, 0x02, SS_DEF, 775 "End-of-partition/medium detected") }, 776 /* T */{SST(0x00, 0x03, SS_DEF, 777 "Setmark detected") }, 778 /* T S */{SST(0x00, 0x04, SS_DEF, 779 "Beginning-of-partition/medium detected") }, 780 /* T S */{SST(0x00, 0x05, SS_DEF, 781 "End-of-data detected") }, 782 /* DTLPWRSOMCAE */{SST(0x00, 0x06, SS_DEF, 783 "I/O process terminated") }, 784 /* R */{SST(0x00, 0x11, SS_NEDEF|EBUSY, 785 "Audio play operation in progress") }, 786 /* R */{SST(0x00, 0x12, SS_NEDEF, 787 "Audio play operation paused") }, 788 /* R */{SST(0x00, 0x13, SS_NEDEF, 789 "Audio play operation successfully completed") }, 790 /* R */{SST(0x00, 0x14, SS_DEF, 791 "Audio play operation stopped due to error") }, 792 /* R */{SST(0x00, 0x15, SS_DEF, 793 "No current audio status to return") }, 794 /* DTLPWRSOMCAE */{SST(0x00, 0x16, SS_NEDEF|EBUSY, 795 "Operation in progress") }, 796 /* DTL WRSOM AE */{SST(0x00, 0x17, SS_DEF, 797 "Cleaning requested") }, 798 /* D W O */{SST(0x01, 0x00, SS_DEF, 799 "No index/sector signal") }, 800 /* D WR OM */{SST(0x02, 0x00, SS_DEF, 801 "No seek complete") }, 802 /* DTL W SO */{SST(0x03, 0x00, SS_DEF, 803 "Peripheral device write fault") }, 804 /* T */{SST(0x03, 0x01, SS_DEF, 805 "No write current") }, 806 /* T */{SST(0x03, 0x02, SS_DEF, 807 "Excessive write errors") }, 808 /* DTLPWRSOMCAE */{SST(0x04, 0x00, SS_TUR|SSQ_MANY|SSQ_DECREMENT_COUNT|EIO, 809 "Logical unit not ready, cause not reportable") }, 810 /* DTLPWRSOMCAE */{SST(0x04, 0x01, SS_TUR|SSQ_MANY|SSQ_DECREMENT_COUNT|EBUSY, 811 "Logical unit is in process of becoming ready") }, 812 /* DTLPWRSOMCAE */{SST(0x04, 0x02, SS_START|SSQ_DECREMENT_COUNT|ENXIO, 813 "Logical unit not ready, initializing cmd. required") }, 814 /* DTLPWRSOMCAE */{SST(0x04, 0x03, SS_NEDEF|ENXIO, 815 "Logical unit not ready, manual intervention required")}, 816 /* DTL O */{SST(0x04, 0x04, SS_NEDEF|EBUSY, 817 "Logical unit not ready, format in progress") }, 818 /* DT W OMCA */{SST(0x04, 0x05, SS_NEDEF|EBUSY, 819 "Logical unit not ready, rebuild in progress") }, 820 /* DT W OMCA */{SST(0x04, 0x06, SS_NEDEF|EBUSY, 821 "Logical unit not ready, recalculation in progress") }, 822 /* DTLPWRSOMCAE */{SST(0x04, 0x07, SS_NEDEF|EBUSY, 823 "Logical unit not ready, operation in progress") }, 824 /* R */{SST(0x04, 0x08, SS_NEDEF|EBUSY, 825 "Logical unit not ready, long write in progress") }, 826 /* DTL WRSOMCAE */{SST(0x05, 0x00, SS_DEF, 827 "Logical unit does not respond to selection") }, 828 /* D WR OM */{SST(0x06, 0x00, SS_DEF, 829 "No reference position found") }, 830 /* DTL WRSOM */{SST(0x07, 0x00, SS_DEF, 831 "Multiple peripheral devices selected") }, 832 /* DTL WRSOMCAE */{SST(0x08, 0x00, SS_DEF, 833 "Logical unit communication failure") }, 834 /* DTL WRSOMCAE */{SST(0x08, 0x01, SS_DEF, 835 "Logical unit communication time-out") }, 836 /* DTL WRSOMCAE */{SST(0x08, 0x02, SS_DEF, 837 "Logical unit communication parity error") }, 838 /* DT R OM */{SST(0x08, 0x03, SS_DEF, 839 "Logical unit communication crc error (ultra-dma/32)")}, 840 /* DT WR O */{SST(0x09, 0x00, SS_DEF, 841 "Track following error") }, 842 /* WR O */{SST(0x09, 0x01, SS_DEF, 843 "Tracking servo failure") }, 844 /* WR O */{SST(0x09, 0x02, SS_DEF, 845 "Focus servo failure") }, 846 /* WR O */{SST(0x09, 0x03, SS_DEF, 847 "Spindle servo failure") }, 848 /* DT WR O */{SST(0x09, 0x04, SS_DEF, 849 "Head select fault") }, 850 /* DTLPWRSOMCAE */{SST(0x0A, 0x00, SS_NEDEF|ENOSPC, 851 "Error log overflow") }, 852 /* DTLPWRSOMCAE */{SST(0x0B, 0x00, SS_DEF, 853 "Warning") }, 854 /* DTLPWRSOMCAE */{SST(0x0B, 0x01, SS_DEF, 855 "Specified temperature exceeded") }, 856 /* DTLPWRSOMCAE */{SST(0x0B, 0x02, SS_DEF, 857 "Enclosure degraded") }, 858 /* T RS */{SST(0x0C, 0x00, SS_DEF, 859 "Write error") }, 860 /* D W O */{SST(0x0C, 0x01, SS_NEDEF, 861 "Write error - recovered with auto reallocation") }, 862 /* D W O */{SST(0x0C, 0x02, SS_DEF, 863 "Write error - auto reallocation failed") }, 864 /* D W O */{SST(0x0C, 0x03, SS_DEF, 865 "Write error - recommend reassignment") }, 866 /* DT W O */{SST(0x0C, 0x04, SS_NEPDEF, 867 "Compression check miscompare error") }, 868 /* DT W O */{SST(0x0C, 0x05, SS_DEF, 869 "Data expansion occurred during compression") }, 870 /* DT W O */{SST(0x0C, 0x06, SS_DEF, 871 "Block not compressible") }, 872 /* R */{SST(0x0C, 0x07, SS_DEF, 873 "Write error - recovery needed") }, 874 /* R */{SST(0x0C, 0x08, SS_DEF, 875 "Write error - recovery failed") }, 876 /* R */{SST(0x0C, 0x09, SS_DEF, 877 "Write error - loss of streaming") }, 878 /* R */{SST(0x0C, 0x0A, SS_DEF, 879 "Write error - padding blocks added") }, 880 /* D W O */{SST(0x10, 0x00, SS_DEF, 881 "ID CRC or ECC error") }, 882 /* DT WRSO */{SST(0x11, 0x00, SS_DEF, 883 "Unrecovered read error") }, 884 /* DT W SO */{SST(0x11, 0x01, SS_DEF, 885 "Read retries exhausted") }, 886 /* DT W SO */{SST(0x11, 0x02, SS_DEF, 887 "Error too long to correct") }, 888 /* DT W SO */{SST(0x11, 0x03, SS_DEF, 889 "Multiple read errors") }, 890 /* D W O */{SST(0x11, 0x04, SS_DEF, 891 "Unrecovered read error - auto reallocate failed") }, 892 /* WR O */{SST(0x11, 0x05, SS_DEF, 893 "L-EC uncorrectable error") }, 894 /* WR O */{SST(0x11, 0x06, SS_DEF, 895 "CIRC unrecovered error") }, 896 /* W O */{SST(0x11, 0x07, SS_DEF, 897 "Data re-synchronization error") }, 898 /* T */{SST(0x11, 0x08, SS_DEF, 899 "Incomplete block read") }, 900 /* T */{SST(0x11, 0x09, SS_DEF, 901 "No gap found") }, 902 /* DT O */{SST(0x11, 0x0A, SS_DEF, 903 "Miscorrected error") }, 904 /* D W O */{SST(0x11, 0x0B, SS_DEF, 905 "Unrecovered read error - recommend reassignment") }, 906 /* D W O */{SST(0x11, 0x0C, SS_DEF, 907 "Unrecovered read error - recommend rewrite the data")}, 908 /* DT WR O */{SST(0x11, 0x0D, SS_DEF, 909 "De-compression CRC error") }, 910 /* DT WR O */{SST(0x11, 0x0E, SS_DEF, 911 "Cannot decompress using declared algorithm") }, 912 /* R */{SST(0x11, 0x0F, SS_DEF, 913 "Error reading UPC/EAN number") }, 914 /* R */{SST(0x11, 0x10, SS_DEF, 915 "Error reading ISRC number") }, 916 /* R */{SST(0x11, 0x11, SS_DEF, 917 "Read error - loss of streaming") }, 918 /* D W O */{SST(0x12, 0x00, SS_DEF, 919 "Address mark not found for id field") }, 920 /* D W O */{SST(0x13, 0x00, SS_DEF, 921 "Address mark not found for data field") }, 922 /* DTL WRSO */{SST(0x14, 0x00, SS_DEF, 923 "Recorded entity not found") }, 924 /* DT WR O */{SST(0x14, 0x01, SS_DEF, 925 "Record not found") }, 926 /* T */{SST(0x14, 0x02, SS_DEF, 927 "Filemark or setmark not found") }, 928 /* T */{SST(0x14, 0x03, SS_DEF, 929 "End-of-data not found") }, 930 /* T */{SST(0x14, 0x04, SS_DEF, 931 "Block sequence error") }, 932 /* DT W O */{SST(0x14, 0x05, SS_DEF, 933 "Record not found - recommend reassignment") }, 934 /* DT W O */{SST(0x14, 0x06, SS_DEF, 935 "Record not found - data auto-reallocated") }, 936 /* DTL WRSOM */{SST(0x15, 0x00, SS_DEF, 937 "Random positioning error") }, 938 /* DTL WRSOM */{SST(0x15, 0x01, SS_DEF, 939 "Mechanical positioning error") }, 940 /* DT WR O */{SST(0x15, 0x02, SS_DEF, 941 "Positioning error detected by read of medium") }, 942 /* D W O */{SST(0x16, 0x00, SS_DEF, 943 "Data synchronization mark error") }, 944 /* D W O */{SST(0x16, 0x01, SS_DEF, 945 "Data sync error - data rewritten") }, 946 /* D W O */{SST(0x16, 0x02, SS_DEF, 947 "Data sync error - recommend rewrite") }, 948 /* D W O */{SST(0x16, 0x03, SS_NEDEF, 949 "Data sync error - data auto-reallocated") }, 950 /* D W O */{SST(0x16, 0x04, SS_DEF, 951 "Data sync error - recommend reassignment") }, 952 /* DT WRSO */{SST(0x17, 0x00, SS_NEDEF, 953 "Recovered data with no error correction applied") }, 954 /* DT WRSO */{SST(0x17, 0x01, SS_NEDEF, 955 "Recovered data with retries") }, 956 /* DT WR O */{SST(0x17, 0x02, SS_NEDEF, 957 "Recovered data with positive head offset") }, 958 /* DT WR O */{SST(0x17, 0x03, SS_NEDEF, 959 "Recovered data with negative head offset") }, 960 /* WR O */{SST(0x17, 0x04, SS_NEDEF, 961 "Recovered data with retries and/or CIRC applied") }, 962 /* D WR O */{SST(0x17, 0x05, SS_NEDEF, 963 "Recovered data using previous sector id") }, 964 /* D W O */{SST(0x17, 0x06, SS_NEDEF, 965 "Recovered data without ECC - data auto-reallocated") }, 966 /* D W O */{SST(0x17, 0x07, SS_NEDEF, 967 "Recovered data without ECC - recommend reassignment")}, 968 /* D W O */{SST(0x17, 0x08, SS_NEDEF, 969 "Recovered data without ECC - recommend rewrite") }, 970 /* D W O */{SST(0x17, 0x09, SS_NEDEF, 971 "Recovered data without ECC - data rewritten") }, 972 /* D W O */{SST(0x18, 0x00, SS_NEDEF, 973 "Recovered data with error correction applied") }, 974 /* D WR O */{SST(0x18, 0x01, SS_NEDEF, 975 "Recovered data with error corr. & retries applied") }, 976 /* D WR O */{SST(0x18, 0x02, SS_NEDEF, 977 "Recovered data - data auto-reallocated") }, 978 /* R */{SST(0x18, 0x03, SS_NEDEF, 979 "Recovered data with CIRC") }, 980 /* R */{SST(0x18, 0x04, SS_NEDEF, 981 "Recovered data with L-EC") }, 982 /* D WR O */{SST(0x18, 0x05, SS_NEDEF, 983 "Recovered data - recommend reassignment") }, 984 /* D WR O */{SST(0x18, 0x06, SS_NEDEF, 985 "Recovered data - recommend rewrite") }, 986 /* D W O */{SST(0x18, 0x07, SS_NEDEF, 987 "Recovered data with ECC - data rewritten") }, 988 /* D O */{SST(0x19, 0x00, SS_DEF, 989 "Defect list error") }, 990 /* D O */{SST(0x19, 0x01, SS_DEF, 991 "Defect list not available") }, 992 /* D O */{SST(0x19, 0x02, SS_DEF, 993 "Defect list error in primary list") }, 994 /* D O */{SST(0x19, 0x03, SS_DEF, 995 "Defect list error in grown list") }, 996 /* DTLPWRSOMCAE */{SST(0x1A, 0x00, SS_DEF, 997 "Parameter list length error") }, 998 /* DTLPWRSOMCAE */{SST(0x1B, 0x00, SS_DEF, 999 "Synchronous data transfer error") }, 1000 /* D O */{SST(0x1C, 0x00, SS_DEF, 1001 "Defect list not found") }, 1002 /* D O */{SST(0x1C, 0x01, SS_DEF, 1003 "Primary defect list not found") }, 1004 /* D O */{SST(0x1C, 0x02, SS_DEF, 1005 "Grown defect list not found") }, 1006 /* D W O */{SST(0x1D, 0x00, SS_NEPDEF, 1007 "Miscompare during verify operation" )}, 1008 /* D W O */{SST(0x1E, 0x00, SS_NEDEF, 1009 "Recovered id with ecc correction") }, 1010 /* D O */{SST(0x1F, 0x00, SS_DEF, 1011 "Partial defect list transfer") }, 1012 /* DTLPWRSOMCAE */{SST(0x20, 0x00, SS_DEF, 1013 "Invalid command operation code") }, 1014 /* DT WR OM */{SST(0x21, 0x00, SS_DEF, 1015 "Logical block address out of range" )}, 1016 /* DT WR OM */{SST(0x21, 0x01, SS_DEF, 1017 "Invalid element address") }, 1018 /* D */{SST(0x22, 0x00, SS_DEF, 1019 "Illegal function") }, /* Deprecated. Use 20 00, 24 00, or 26 00 instead */ 1020 /* DTLPWRSOMCAE */{SST(0x24, 0x00, SS_NEDEF|EINVAL, 1021 "Invalid field in CDB") }, 1022 /* DTLPWRSOMCAE */{SST(0x25, 0x00, SS_NEDEF|ENXIO, 1023 "Logical unit not supported") }, 1024 /* DTLPWRSOMCAE */{SST(0x26, 0x00, SS_NEDEF|EINVAL, 1025 "Invalid field in parameter list") }, 1026 /* DTLPWRSOMCAE */{SST(0x26, 0x01, SS_NEDEF|EINVAL, 1027 "Parameter not supported") }, 1028 /* DTLPWRSOMCAE */{SST(0x26, 0x02, SS_NEDEF|EINVAL, 1029 "Parameter value invalid") }, 1030 /* DTLPWRSOMCAE */{SST(0x26, 0x03, SS_DEF, 1031 "Threshold parameters not supported") }, 1032 /* DTLPWRSOMCAE */{SST(0x26, 0x04, SS_DEF, 1033 "Invalid release of active persistent reservation") }, 1034 /* DT W O */{SST(0x27, 0x00, SS_NEDEF|EACCES, 1035 "Write protected") }, 1036 /* DT W O */{SST(0x27, 0x01, SS_NEDEF|EACCES, 1037 "Hardware write protected") }, 1038 /* DT W O */{SST(0x27, 0x02, SS_NEDEF|EACCES, 1039 "Logical unit software write protected") }, 1040 /* T */{SST(0x27, 0x03, SS_NEDEF|EACCES, 1041 "Associated write protect") }, 1042 /* T */{SST(0x27, 0x04, SS_NEDEF|EACCES, 1043 "Persistent write protect") }, 1044 /* T */{SST(0x27, 0x05, SS_NEDEF|EACCES, 1045 "Permanent write protect") }, 1046 /* DTLPWRSOMCAE */{SST(0x28, 0x00, SS_NEDEF|ENXIO, 1047 "Not ready to ready change, medium may have changed") }, 1048 /* DT WR OM */{SST(0x28, 0x01, SS_DEF, 1049 "Import or export element accessed") }, 1050 /* DTLPWRSOMCAE */{SST(0x29, 0x00, SS_NEDEF|ENXIO, 1051 "Power on, reset, or bus device reset occurred") }, 1052 /* DTLPWRSOMCAE */{SST(0x29, 0x01, SS_DEF, 1053 "Power on occurred") }, 1054 /* DTLPWRSOMCAE */{SST(0x29, 0x02, SS_DEF, 1055 "Scsi bus reset occurred") }, 1056 /* DTLPWRSOMCAE */{SST(0x29, 0x03, SS_DEF, 1057 "Bus device reset function occurred") }, 1058 /* DTLPWRSOMCAE */{SST(0x29, 0x04, SS_DEF, 1059 "Device internal reset") }, 1060 /* DTLPWRSOMCAE */{SST(0x29, 0x05, SS_DEF, 1061 "Transceiver mode changed to single-ended") }, 1062 /* DTLPWRSOMCAE */{SST(0x29, 0x06, SS_DEF, 1063 "Transceiver mode changed to LVD") }, 1064 /* DTL WRSOMCAE */{SST(0x2A, 0x00, SS_DEF, 1065 "Parameters changed") }, 1066 /* DTL WRSOMCAE */{SST(0x2A, 0x01, SS_DEF, 1067 "Mode parameters changed") }, 1068 /* DTL WRSOMCAE */{SST(0x2A, 0x02, SS_DEF, 1069 "Log parameters changed") }, 1070 /* DTLPWRSOMCAE */{SST(0x2A, 0x03, SS_DEF, 1071 "Reservations preempted") }, 1072 /* DTLPWRSO C */{SST(0x2B, 0x00, SS_DEF, 1073 "Copy cannot execute since host cannot disconnect") }, 1074 /* DTLPWRSOMCAE */{SST(0x2C, 0x00, SS_DEF, 1075 "Command sequence error") }, 1076 /* S */{SST(0x2C, 0x01, SS_DEF, 1077 "Too many windows specified") }, 1078 /* S */{SST(0x2C, 0x02, SS_DEF, 1079 "Invalid combination of windows specified") }, 1080 /* R */{SST(0x2C, 0x03, SS_DEF, 1081 "Current program area is not empty") }, 1082 /* R */{SST(0x2C, 0x04, SS_DEF, 1083 "Current program area is empty") }, 1084 /* T */{SST(0x2D, 0x00, SS_DEF, 1085 "Overwrite error on update in place") }, 1086 /* DTLPWRSOMCAE */{SST(0x2F, 0x00, SS_DEF, 1087 "Commands cleared by another initiator") }, 1088 /* DT WR OM */{SST(0x30, 0x00, SS_DEF, 1089 "Incompatible medium installed") }, 1090 /* DT WR O */{SST(0x30, 0x01, SS_DEF, 1091 "Cannot read medium - unknown format") }, 1092 /* DT WR O */{SST(0x30, 0x02, SS_DEF, 1093 "Cannot read medium - incompatible format") }, 1094 /* DT */{SST(0x30, 0x03, SS_DEF, 1095 "Cleaning cartridge installed") }, 1096 /* DT WR O */{SST(0x30, 0x04, SS_DEF, 1097 "Cannot write medium - unknown format") }, 1098 /* DT WR O */{SST(0x30, 0x05, SS_DEF, 1099 "Cannot write medium - incompatible format") }, 1100 /* DT W O */{SST(0x30, 0x06, SS_DEF, 1101 "Cannot format medium - incompatible medium") }, 1102 /* DTL WRSOM AE */{SST(0x30, 0x07, SS_DEF, 1103 "Cleaning failure") }, 1104 /* R */{SST(0x30, 0x08, SS_DEF, 1105 "Cannot write - application code mismatch") }, 1106 /* R */{SST(0x30, 0x09, SS_DEF, 1107 "Current session not fixated for append") }, 1108 /* DT WR O */{SST(0x31, 0x00, SS_DEF, 1109 "Medium format corrupted") }, 1110 /* D L R O */{SST(0x31, 0x01, SS_DEF, 1111 "Format command failed") }, 1112 /* D W O */{SST(0x32, 0x00, SS_DEF, 1113 "No defect spare location available") }, 1114 /* D W O */{SST(0x32, 0x01, SS_DEF, 1115 "Defect list update failure") }, 1116 /* T */{SST(0x33, 0x00, SS_DEF, 1117 "Tape length error") }, 1118 /* DTLPWRSOMCAE */{SST(0x34, 0x00, SS_DEF, 1119 "Enclosure failure") }, 1120 /* DTLPWRSOMCAE */{SST(0x35, 0x00, SS_DEF, 1121 "Enclosure services failure") }, 1122 /* DTLPWRSOMCAE */{SST(0x35, 0x01, SS_DEF, 1123 "Unsupported enclosure function") }, 1124 /* DTLPWRSOMCAE */{SST(0x35, 0x02, SS_DEF, 1125 "Enclosure services unavailable") }, 1126 /* DTLPWRSOMCAE */{SST(0x35, 0x03, SS_DEF, 1127 "Enclosure services transfer failure") }, 1128 /* DTLPWRSOMCAE */{SST(0x35, 0x04, SS_DEF, 1129 "Enclosure services transfer refused") }, 1130 /* L */{SST(0x36, 0x00, SS_DEF, 1131 "Ribbon, ink, or toner failure") }, 1132 /* DTL WRSOMCAE */{SST(0x37, 0x00, SS_DEF, 1133 "Rounded parameter") }, 1134 /* DTL WRSOMCAE */{SST(0x39, 0x00, SS_DEF, 1135 "Saving parameters not supported") }, 1136 /* DTL WRSOM */{SST(0x3A, 0x00, SS_NEDEF|ENXIO, 1137 "Medium not present") }, 1138 /* DT WR OM */{SST(0x3A, 0x01, SS_NEDEF|ENXIO, 1139 "Medium not present - tray closed") }, 1140 /* DT WR OM */{SST(0x3A, 0x02, SS_NEDEF|ENXIO, 1141 "Medium not present - tray open") }, 1142 /* TL */{SST(0x3B, 0x00, SS_DEF, 1143 "Sequential positioning error") }, 1144 /* T */{SST(0x3B, 0x01, SS_DEF, 1145 "Tape position error at beginning-of-medium") }, 1146 /* T */{SST(0x3B, 0x02, SS_DEF, 1147 "Tape position error at end-of-medium") }, 1148 /* L */{SST(0x3B, 0x03, SS_DEF, 1149 "Tape or electronic vertical forms unit not ready") }, 1150 /* L */{SST(0x3B, 0x04, SS_DEF, 1151 "Slew failure") }, 1152 /* L */{SST(0x3B, 0x05, SS_DEF, 1153 "Paper jam") }, 1154 /* L */{SST(0x3B, 0x06, SS_DEF, 1155 "Failed to sense top-of-form") }, 1156 /* L */{SST(0x3B, 0x07, SS_DEF, 1157 "Failed to sense bottom-of-form") }, 1158 /* T */{SST(0x3B, 0x08, SS_DEF, 1159 "Reposition error") }, 1160 /* S */{SST(0x3B, 0x09, SS_DEF, 1161 "Read past end of medium") }, 1162 /* S */{SST(0x3B, 0x0A, SS_DEF, 1163 "Read past beginning of medium") }, 1164 /* S */{SST(0x3B, 0x0B, SS_DEF, 1165 "Position past end of medium") }, 1166 /* T S */{SST(0x3B, 0x0C, SS_DEF, 1167 "Position past beginning of medium") }, 1168 /* DT WR OM */{SST(0x3B, 0x0D, SS_NEDEF|ENOSPC, 1169 "Medium destination element full") }, 1170 /* DT WR OM */{SST(0x3B, 0x0E, SS_DEF, 1171 "Medium source element empty") }, 1172 /* R */{SST(0x3B, 0x0F, SS_DEF, 1173 "End of medium reached") }, 1174 /* DT WR OM */{SST(0x3B, 0x11, SS_DEF, 1175 "Medium magazine not accessible") }, 1176 /* DT WR OM */{SST(0x3B, 0x12, SS_DEF, 1177 "Medium magazine removed") }, 1178 /* DT WR OM */{SST(0x3B, 0x13, SS_DEF, 1179 "Medium magazine inserted") }, 1180 /* DT WR OM */{SST(0x3B, 0x14, SS_DEF, 1181 "Medium magazine locked") }, 1182 /* DT WR OM */{SST(0x3B, 0x15, SS_DEF, 1183 "Medium magazine unlocked") }, 1184 /* DTLPWRSOMCAE */{SST(0x3D, 0x00, SS_DEF, 1185 "Invalid bits in identify message") }, 1186 /* DTLPWRSOMCAE */{SST(0x3E, 0x00, SS_DEF, 1187 "Logical unit has not self-configured yet") }, 1188 /* DTLPWRSOMCAE */{SST(0x3E, 0x01, SS_DEF, 1189 "Logical unit failure") }, 1190 /* DTLPWRSOMCAE */{SST(0x3E, 0x02, SS_DEF, 1191 "Timeout on logical unit") }, 1192 /* DTLPWRSOMCAE */{SST(0x3F, 0x00, SS_DEF, 1193 "Target operating conditions have changed") }, 1194 /* DTLPWRSOMCAE */{SST(0x3F, 0x01, SS_DEF, 1195 "Microcode has been changed") }, 1196 /* DTLPWRSOMC */{SST(0x3F, 0x02, SS_DEF, 1197 "Changed operating definition") }, 1198 /* DTLPWRSOMCAE */{SST(0x3F, 0x03, SS_DEF, 1199 "Inquiry data has changed") }, 1200 /* DT WR OMCAE */{SST(0x3F, 0x04, SS_DEF, 1201 "Component device attached") }, 1202 /* DT WR OMCAE */{SST(0x3F, 0x05, SS_DEF, 1203 "Device identifier changed") }, 1204 /* DT WR OMCAE */{SST(0x3F, 0x06, SS_DEF, 1205 "Redundancy group created or modified") }, 1206 /* DT WR OMCAE */{SST(0x3F, 0x07, SS_DEF, 1207 "Redundancy group deleted") }, 1208 /* DT WR OMCAE */{SST(0x3F, 0x08, SS_DEF, 1209 "Spare created or modified") }, 1210 /* DT WR OMCAE */{SST(0x3F, 0x09, SS_DEF, 1211 "Spare deleted") }, 1212 /* DT WR OMCAE */{SST(0x3F, 0x0A, SS_DEF, 1213 "Volume set created or modified") }, 1214 /* DT WR OMCAE */{SST(0x3F, 0x0B, SS_DEF, 1215 "Volume set deleted") }, 1216 /* DT WR OMCAE */{SST(0x3F, 0x0C, SS_DEF, 1217 "Volume set deassigned") }, 1218 /* DT WR OMCAE */{SST(0x3F, 0x0D, SS_DEF, 1219 "Volume set reassigned") }, 1220 /* D */{SST(0x40, 0x00, SS_DEF, 1221 "Ram failure") }, /* deprecated - use 40 NN instead */ 1222 /* DTLPWRSOMCAE */{SST(0x40, 0x80, SS_DEF, 1223 "Diagnostic failure: ASCQ = Component ID") }, 1224 /* DTLPWRSOMCAE */{SST(0x40, 0xFF, SS_DEF|SSQ_RANGE, 1225 NULL) },/* Range 0x80->0xFF */ 1226 /* D */{SST(0x41, 0x00, SS_DEF, 1227 "Data path failure") }, /* deprecated - use 40 NN instead */ 1228 /* D */{SST(0x42, 0x00, SS_DEF, 1229 "Power-on or self-test failure") }, /* deprecated - use 40 NN instead */ 1230 /* DTLPWRSOMCAE */{SST(0x43, 0x00, SS_DEF, 1231 "Message error") }, 1232 /* DTLPWRSOMCAE */{SST(0x44, 0x00, SS_DEF, 1233 "Internal target failure") }, 1234 /* DTLPWRSOMCAE */{SST(0x45, 0x00, SS_DEF, 1235 "Select or reselect failure") }, 1236 /* DTLPWRSOMC */{SST(0x46, 0x00, SS_DEF, 1237 "Unsuccessful soft reset") }, 1238 /* DTLPWRSOMCAE */{SST(0x47, 0x00, SS_DEF, 1239 "SCSI parity error") }, 1240 /* DTLPWRSOMCAE */{SST(0x48, 0x00, SS_DEF, 1241 "Initiator detected error message received") }, 1242 /* DTLPWRSOMCAE */{SST(0x49, 0x00, SS_DEF, 1243 "Invalid message error") }, 1244 /* DTLPWRSOMCAE */{SST(0x4A, 0x00, SS_DEF, 1245 "Command phase error") }, 1246 /* DTLPWRSOMCAE */{SST(0x4B, 0x00, SS_DEF, 1247 "Data phase error") }, 1248 /* DTLPWRSOMCAE */{SST(0x4C, 0x00, SS_DEF, 1249 "Logical unit failed self-configuration") }, 1250 /* DTLPWRSOMCAE */{SST(0x4D, 0x00, SS_DEF, 1251 "Tagged overlapped commands: ASCQ = Queue tag ID") }, 1252 /* DTLPWRSOMCAE */{SST(0x4D, 0xFF, SS_DEF|SSQ_RANGE, 1253 NULL)}, /* Range 0x00->0xFF */ 1254 /* DTLPWRSOMCAE */{SST(0x4E, 0x00, SS_DEF, 1255 "Overlapped commands attempted") }, 1256 /* T */{SST(0x50, 0x00, SS_DEF, 1257 "Write append error") }, 1258 /* T */{SST(0x50, 0x01, SS_DEF, 1259 "Write append position error") }, 1260 /* T */{SST(0x50, 0x02, SS_DEF, 1261 "Position error related to timing") }, 1262 /* T O */{SST(0x51, 0x00, SS_DEF, 1263 "Erase failure") }, 1264 /* T */{SST(0x52, 0x00, SS_DEF, 1265 "Cartridge fault") }, 1266 /* DTL WRSOM */{SST(0x53, 0x00, SS_DEF, 1267 "Media load or eject failed") }, 1268 /* T */{SST(0x53, 0x01, SS_DEF, 1269 "Unload tape failure") }, 1270 /* DT WR OM */{SST(0x53, 0x02, SS_DEF, 1271 "Medium removal prevented") }, 1272 /* P */{SST(0x54, 0x00, SS_DEF, 1273 "Scsi to host system interface failure") }, 1274 /* P */{SST(0x55, 0x00, SS_DEF, 1275 "System resource failure") }, 1276 /* D O */{SST(0x55, 0x01, SS_NEDEF|ENOSPC, 1277 "System buffer full") }, 1278 /* R */{SST(0x57, 0x00, SS_DEF, 1279 "Unable to recover table-of-contents") }, 1280 /* O */{SST(0x58, 0x00, SS_DEF, 1281 "Generation does not exist") }, 1282 /* O */{SST(0x59, 0x00, SS_DEF, 1283 "Updated block read") }, 1284 /* DTLPWRSOM */{SST(0x5A, 0x00, SS_DEF, 1285 "Operator request or state change input") }, 1286 /* DT WR OM */{SST(0x5A, 0x01, SS_DEF, 1287 "Operator medium removal request") }, 1288 /* DT W O */{SST(0x5A, 0x02, SS_DEF, 1289 "Operator selected write protect") }, 1290 /* DT W O */{SST(0x5A, 0x03, SS_DEF, 1291 "Operator selected write permit") }, 1292 /* DTLPWRSOM */{SST(0x5B, 0x00, SS_DEF, 1293 "Log exception") }, 1294 /* DTLPWRSOM */{SST(0x5B, 0x01, SS_DEF, 1295 "Threshold condition met") }, 1296 /* DTLPWRSOM */{SST(0x5B, 0x02, SS_DEF, 1297 "Log counter at maximum") }, 1298 /* DTLPWRSOM */{SST(0x5B, 0x03, SS_DEF, 1299 "Log list codes exhausted") }, 1300 /* D O */{SST(0x5C, 0x00, SS_DEF, 1301 "RPL status change") }, 1302 /* D O */{SST(0x5C, 0x01, SS_NEDEF, 1303 "Spindles synchronized") }, 1304 /* D O */{SST(0x5C, 0x02, SS_DEF, 1305 "Spindles not synchronized") }, 1306 /* DTLPWRSOMCAE */{SST(0x5D, 0x00, SS_DEF, 1307 "Failure prediction threshold exceeded") }, 1308 /* DTLPWRSOMCAE */{SST(0x5D, 0xFF, SS_DEF, 1309 "Failure prediction threshold exceeded (false)") }, 1310 /* DTLPWRSO CA */{SST(0x5E, 0x00, SS_DEF, 1311 "Low power condition on") }, 1312 /* DTLPWRSO CA */{SST(0x5E, 0x01, SS_DEF, 1313 "Idle condition activated by timer") }, 1314 /* DTLPWRSO CA */{SST(0x5E, 0x02, SS_DEF, 1315 "Standby condition activated by timer") }, 1316 /* DTLPWRSO CA */{SST(0x5E, 0x03, SS_DEF, 1317 "Idle condition activated by command") }, 1318 /* DTLPWRSO CA */{SST(0x5E, 0x04, SS_DEF, 1319 "Standby condition activated by command") }, 1320 /* S */{SST(0x60, 0x00, SS_DEF, 1321 "Lamp failure") }, 1322 /* S */{SST(0x61, 0x00, SS_DEF, 1323 "Video acquisition error") }, 1324 /* S */{SST(0x61, 0x01, SS_DEF, 1325 "Unable to acquire video") }, 1326 /* S */{SST(0x61, 0x02, SS_DEF, 1327 "Out of focus") }, 1328 /* S */{SST(0x62, 0x00, SS_DEF, 1329 "Scan head positioning error") }, 1330 /* R */{SST(0x63, 0x00, SS_DEF, 1331 "End of user area encountered on this track") }, 1332 /* R */{SST(0x63, 0x01, SS_NEDEF|ENOSPC, 1333 "Packet does not fit in available space") }, 1334 /* R */{SST(0x64, 0x00, SS_DEF, 1335 "Illegal mode for this track") }, 1336 /* R */{SST(0x64, 0x01, SS_DEF, 1337 "Invalid packet size") }, 1338 /* DTLPWRSOMCAE */{SST(0x65, 0x00, SS_DEF, 1339 "Voltage fault") }, 1340 /* S */{SST(0x66, 0x00, SS_DEF, 1341 "Automatic document feeder cover up") }, 1342 /* S */{SST(0x66, 0x01, SS_DEF, 1343 "Automatic document feeder lift up") }, 1344 /* S */{SST(0x66, 0x02, SS_DEF, 1345 "Document jam in automatic document feeder") }, 1346 /* S */{SST(0x66, 0x03, SS_DEF, 1347 "Document miss feed automatic in document feeder") }, 1348 /* A */{SST(0x67, 0x00, SS_DEF, 1349 "Configuration failure") }, 1350 /* A */{SST(0x67, 0x01, SS_DEF, 1351 "Configuration of incapable logical units failed") }, 1352 /* A */{SST(0x67, 0x02, SS_DEF, 1353 "Add logical unit failed") }, 1354 /* A */{SST(0x67, 0x03, SS_DEF, 1355 "Modification of logical unit failed") }, 1356 /* A */{SST(0x67, 0x04, SS_DEF, 1357 "Exchange of logical unit failed") }, 1358 /* A */{SST(0x67, 0x05, SS_DEF, 1359 "Remove of logical unit failed") }, 1360 /* A */{SST(0x67, 0x06, SS_DEF, 1361 "Attachment of logical unit failed") }, 1362 /* A */{SST(0x67, 0x07, SS_DEF, 1363 "Creation of logical unit failed") }, 1364 /* A */{SST(0x68, 0x00, SS_DEF, 1365 "Logical unit not configured") }, 1366 /* A */{SST(0x69, 0x00, SS_DEF, 1367 "Data loss on logical unit") }, 1368 /* A */{SST(0x69, 0x01, SS_DEF, 1369 "Multiple logical unit failures") }, 1370 /* A */{SST(0x69, 0x02, SS_DEF, 1371 "Parity/data mismatch") }, 1372 /* A */{SST(0x6A, 0x00, SS_DEF, 1373 "Informational, refer to log") }, 1374 /* A */{SST(0x6B, 0x00, SS_DEF, 1375 "State change has occurred") }, 1376 /* A */{SST(0x6B, 0x01, SS_DEF, 1377 "Redundancy level got better") }, 1378 /* A */{SST(0x6B, 0x02, SS_DEF, 1379 "Redundancy level got worse") }, 1380 /* A */{SST(0x6C, 0x00, SS_DEF, 1381 "Rebuild failure occurred") }, 1382 /* A */{SST(0x6D, 0x00, SS_DEF, 1383 "Recalculate failure occurred") }, 1384 /* A */{SST(0x6E, 0x00, SS_DEF, 1385 "Command to logical unit failed") }, 1386 /* T */{SST(0x70, 0x00, SS_DEF, 1387 "Decompression exception short: ASCQ = Algorithm ID") }, 1388 /* T */{SST(0x70, 0xFF, SS_DEF|SSQ_RANGE, 1389 NULL) }, /* Range 0x00 -> 0xFF */ 1390 /* T */{SST(0x71, 0x00, SS_DEF, 1391 "Decompression exception long: ASCQ = Algorithm ID") }, 1392 /* T */{SST(0x71, 0xFF, SS_DEF|SSQ_RANGE, 1393 NULL) }, /* Range 0x00 -> 0xFF */ 1394 /* R */{SST(0x72, 0x00, SS_DEF, 1395 "Session fixation error") }, 1396 /* R */{SST(0x72, 0x01, SS_DEF, 1397 "Session fixation error writing lead-in") }, 1398 /* R */{SST(0x72, 0x02, SS_DEF, 1399 "Session fixation error writing lead-out") }, 1400 /* R */{SST(0x72, 0x03, SS_DEF, 1401 "Session fixation error - incomplete track in session") }, 1402 /* R */{SST(0x72, 0x04, SS_DEF, 1403 "Empty or partially written reserved track") }, 1404 /* R */{SST(0x73, 0x00, SS_DEF, 1405 "CD control error") }, 1406 /* R */{SST(0x73, 0x01, SS_DEF, 1407 "Power calibration area almost full") }, 1408 /* R */{SST(0x73, 0x02, SS_NEDEF|ENOSPC, 1409 "Power calibration area is full") }, 1410 /* R */{SST(0x73, 0x03, SS_DEF, 1411 "Power calibration area error") }, 1412 /* R */{SST(0x73, 0x04, SS_DEF, 1413 "Program memory area update failure") }, 1414 /* R */{SST(0x73, 0x05, SS_DEF, 1415 "program memory area is full") } 1416 }; 1417 1418 #if !defined(SCSI_NO_SENSE_STRINGS) 1419 const char * 1420 scsi_sense_desc(int asc, int ascq, struct scsi_inquiry_data *inq_data) 1421 { 1422 int i, j; 1423 caddr_t match; 1424 struct asc_table_entry *table[2]; 1425 int table_size[2]; 1426 int num_tables; 1427 1428 if (inq_data == NULL) 1429 return(NULL); 1430 1431 match = cam_quirkmatch((caddr_t)inq_data, 1432 (caddr_t)asc_quirk_table, 1433 sizeof(asc_quirk_table)/sizeof(*asc_quirk_table), 1434 sizeof(*asc_quirk_table), scsi_inquiry_match); 1435 1436 if (match != NULL) { 1437 table[0] = ((struct scsi_sense_quirk_entry *)match)->asc_info; 1438 table_size[0] = 1439 ((struct scsi_sense_quirk_entry *)match)->num_ascs; 1440 table[1] = asc_text; 1441 table_size[1] = sizeof(asc_text)/sizeof(asc_text[0]); 1442 num_tables = 2; 1443 } else { 1444 table[0] = asc_text; 1445 table_size[0] = sizeof(asc_text)/sizeof(asc_text[0]); 1446 num_tables = 1; 1447 } 1448 1449 for (j = 0; j < num_tables; j++) { 1450 for (i = 0; i < table_size[j]; i++) { 1451 if (table[j][i].asc == asc) { 1452 1453 /* Check for ranges */ 1454 if ((table[j][i].action & SSQ_RANGE) != 0) { 1455 1456 if (table[j][i].ascq >= ascq 1457 && table[j][i-1].ascq <= ascq) 1458 return table[j][i-1].desc; 1459 1460 continue; 1461 } 1462 1463 if (table[j][i].ascq == ascq) 1464 return table[j][i].desc; 1465 } 1466 } 1467 } 1468 1469 if (asc >= 0x80 && asc <= 0xff) 1470 return "Vendor Specific ASC"; 1471 1472 if (ascq >= 0x80 && ascq <= 0xff) 1473 return "Vendor Specific ASCQ"; 1474 1475 return "Reserved ASC/ASCQ pair"; 1476 } 1477 1478 #else /* SCSI_NO_SENSE_STRINGS */ 1479 const char * 1480 scsi_sense_desc(int asc, int ascq, struct scsi_inquiry_data *inq_data) 1481 { 1482 return (""); 1483 } 1484 #endif 1485 1486 /* 1487 * Given a particular failed CCB and its device type information, return 1488 * the appropriate action from either the sense code quirk table or the 1489 * sense code table. 1490 */ 1491 scsi_sense_action 1492 scsi_error_action(int asc, int ascq, struct scsi_inquiry_data *inq_data) 1493 { 1494 caddr_t match; 1495 struct asc_table_entry *table[2]; 1496 int table_size[2]; 1497 int num_tables; 1498 int i, j; 1499 1500 /* 1501 * If we don't have inquiry data, we can't match against any quirk 1502 * entries. 1503 */ 1504 if (inq_data != NULL) { 1505 match = cam_quirkmatch((caddr_t)inq_data, 1506 (caddr_t)asc_quirk_table, 1507 sizeof(asc_quirk_table) / 1508 sizeof(*asc_quirk_table), 1509 sizeof(*asc_quirk_table), 1510 scsi_inquiry_match); 1511 } else 1512 match = NULL; 1513 1514 if (match != NULL) { 1515 table[0] = ((struct scsi_sense_quirk_entry *)match)->asc_info; 1516 table_size[0] = 1517 ((struct scsi_sense_quirk_entry *)match)->num_ascs; 1518 table[1] = asc_text; 1519 table_size[1] = sizeof(asc_text)/sizeof(asc_text[0]); 1520 num_tables = 2; 1521 } else { 1522 table[0] = asc_text; 1523 table_size[0] = sizeof(asc_text)/sizeof(asc_text[0]); 1524 num_tables = 1; 1525 } 1526 1527 for (j = 0; j < num_tables; j++) { 1528 for (i = 0; i < table_size[j]; i++) { 1529 if (table[j][i].asc == asc) { 1530 1531 /* Check for ranges */ 1532 if ((table[j][i].action & SSQ_RANGE) != 0){ 1533 1534 if (table[j][i].ascq >= ascq 1535 && table[j][i-1].ascq <= ascq) 1536 return table[j][i].action; 1537 1538 continue; 1539 } 1540 1541 /* 1542 * Check to see if we have a match. If the 1543 * current ascq in the table is greater 1544 * than our ascq, and there aren't any more 1545 * tables to search, just return the 1546 * default action. 1547 */ 1548 if (table[j][i].ascq == ascq) 1549 return(table[j][i].action); 1550 else if ((j == (num_tables - 1)) && 1551 (table[j][i].ascq > ascq)) 1552 return(SS_DEF); 1553 } 1554 } 1555 } 1556 /* 1557 * If we get to this point, it's most likely a vendor specific 1558 * ASC and we don't have a quirk entry for it. Oh well, we just 1559 * tell the error handling code to take the default action. 1560 */ 1561 return(SS_DEF); 1562 } 1563 1564 char * 1565 scsi_cdb_string(u_int8_t *cdb_ptr, char *cdb_string, size_t len) 1566 { 1567 u_int8_t cdb_len; 1568 int i; 1569 1570 if (cdb_ptr == NULL) 1571 return(""); 1572 1573 /* Silence warnings */ 1574 cdb_len = 0; 1575 1576 /* 1577 * This is taken from the SCSI-3 draft spec. 1578 * (T10/1157D revision 0.3) 1579 * The top 3 bits of an opcode are the group code. The next 5 bits 1580 * are the command code. 1581 * Group 0: six byte commands 1582 * Group 1: ten byte commands 1583 * Group 2: ten byte commands 1584 * Group 3: reserved 1585 * Group 4: sixteen byte commands 1586 * Group 5: twelve byte commands 1587 * Group 6: vendor specific 1588 * Group 7: vendor specific 1589 */ 1590 switch((*cdb_ptr >> 5) & 0x7) { 1591 case 0: 1592 cdb_len = 6; 1593 break; 1594 case 1: 1595 case 2: 1596 cdb_len = 10; 1597 break; 1598 case 3: 1599 case 6: 1600 case 7: 1601 /* in this case, just print out the opcode */ 1602 cdb_len = 1; 1603 break; 1604 case 4: 1605 cdb_len = 16; 1606 break; 1607 case 5: 1608 cdb_len = 12; 1609 break; 1610 } 1611 *cdb_string = '\0'; 1612 for (i = 0; i < cdb_len; i++) 1613 ksnprintf(cdb_string + strlen(cdb_string), 1614 len - strlen(cdb_string), "%x ", cdb_ptr[i]); 1615 1616 return(cdb_string); 1617 } 1618 /* 1619 * scsi_sense_print will decode the sense data into human 1620 * readable form. Sense handlers can use this to generate 1621 * a report. 1622 */ 1623 /* 1624 * Because scsi_sense_print() utilizes transport layer functions, it will 1625 * only work in the kernel. 1626 */ 1627 #ifdef _KERNEL 1628 1629 void 1630 scsi_sense_print(struct ccb_scsiio *csio) 1631 { 1632 struct scsi_sense_data *sense; 1633 u_int32_t info; 1634 int error_code; 1635 int sense_key; 1636 int asc, ascq; 1637 struct ccb_getdev cgd; 1638 u_int8_t command_print; 1639 1640 sense = &csio->sense_data; 1641 1642 /* 1643 * If the CDB is a physical address, we can't deal with it.. 1644 */ 1645 if ((csio->ccb_h.flags & CAM_CDB_PHYS) != 0) 1646 command_print = 0; 1647 else 1648 command_print = 1; 1649 1650 /* 1651 * Get the device information. 1652 */ 1653 xpt_setup_ccb(&cgd.ccb_h, 1654 csio->ccb_h.path, 1655 /*priority*/ 1); 1656 cgd.ccb_h.func_code = XPT_GDEV_TYPE; 1657 xpt_action((union ccb *)&cgd); 1658 1659 /* 1660 * If the device is unconfigured, just pretend that it is a hard 1661 * drive. scsi_op_desc() needs this. 1662 */ 1663 if (cgd.ccb_h.status == CAM_DEV_NOT_THERE) 1664 cgd.inq_data.device = T_DIRECT; 1665 1666 if (command_print != 0) { 1667 char cdb_str[(SCSI_MAX_CDBLEN * 3) + 1]; 1668 1669 xpt_print_path(csio->ccb_h.path); 1670 1671 if ((csio->ccb_h.flags & CAM_CDB_POINTER) != 0) { 1672 kprintf("%s. CDB: %s\n", 1673 scsi_op_desc(csio->cdb_io.cdb_ptr[0], 1674 &cgd.inq_data), 1675 scsi_cdb_string(csio->cdb_io.cdb_ptr, cdb_str, 1676 sizeof(cdb_str))); 1677 } else { 1678 kprintf("%s. CDB: %s\n", 1679 scsi_op_desc(csio->cdb_io.cdb_bytes[0], 1680 &cgd.inq_data), scsi_cdb_string( 1681 csio->cdb_io.cdb_bytes, cdb_str, 1682 sizeof(cdb_str))); 1683 } 1684 } 1685 1686 /* 1687 * If the sense data is a physical pointer, forget it. 1688 */ 1689 if (csio->ccb_h.flags & CAM_SENSE_PTR) { 1690 if (csio->ccb_h.flags & CAM_SENSE_PHYS) 1691 return; 1692 else { 1693 /* 1694 * XXX KDM this is stupid, but casting the 1695 * structure doesn't work... 1696 */ 1697 bcopy(&csio->sense_data, &sense, 1698 sizeof(struct scsi_sense_data *)); 1699 } 1700 } else { 1701 /* 1702 * If the physical sense flag is set, but the sense pointer 1703 * is not also set, we assume that the user is an idiot and 1704 * return. (Well, okay, it could be that somehow, the 1705 * entire csio is physical, but we would have probably core 1706 * dumped on one of the bogus pointer deferences above 1707 * already.) 1708 */ 1709 if (csio->ccb_h.flags & CAM_SENSE_PHYS) 1710 return; 1711 else 1712 sense = &csio->sense_data; 1713 } 1714 1715 xpt_print_path(csio->ccb_h.path); 1716 error_code = sense->error_code & SSD_ERRCODE; 1717 sense_key = sense->flags & SSD_KEY; 1718 1719 switch (error_code) { 1720 case SSD_DEFERRED_ERROR: 1721 kprintf("Deferred Error: "); 1722 /* FALLTHROUGH */ 1723 case SSD_CURRENT_ERROR: 1724 1725 kprintf("%s", scsi_sense_key_text[sense_key]); 1726 info = scsi_4btoul(sense->info); 1727 1728 if (sense->error_code & SSD_ERRCODE_VALID) { 1729 1730 switch (sense_key) { 1731 case SSD_KEY_NOT_READY: 1732 case SSD_KEY_ILLEGAL_REQUEST: 1733 case SSD_KEY_UNIT_ATTENTION: 1734 case SSD_KEY_DATA_PROTECT: 1735 break; 1736 case SSD_KEY_BLANK_CHECK: 1737 kprintf(" req sz: %d (decimal)", 1738 info); 1739 break; 1740 default: 1741 if (info) { 1742 if (sense->flags & SSD_ILI) { 1743 kprintf(" ILI (length mismatch):" 1744 " %d", info); 1745 } else { 1746 kprintf(" info:%x", info); 1747 } 1748 } 1749 } 1750 } else if (info) 1751 kprintf(" info?:%x", info); 1752 1753 if (sense->extra_len >= 4) { 1754 if (bcmp(sense->cmd_spec_info, "\0\0\0\0", 4)) { 1755 kprintf(" csi:%x,%x,%x,%x", 1756 sense->cmd_spec_info[0], 1757 sense->cmd_spec_info[1], 1758 sense->cmd_spec_info[2], 1759 sense->cmd_spec_info[3]); 1760 } 1761 } 1762 1763 asc = (sense->extra_len >= 5) ? sense->add_sense_code : 0; 1764 ascq = (sense->extra_len >= 6) ? sense->add_sense_code_qual : 0; 1765 1766 if (asc || ascq) { 1767 const char *desc = scsi_sense_desc(asc, ascq, 1768 &cgd.inq_data); 1769 kprintf(" asc:%x,%x\n", asc, ascq); 1770 1771 xpt_print_path(csio->ccb_h.path); 1772 kprintf("%s", desc); 1773 } 1774 1775 if (sense->extra_len >= 7 && sense->fru) { 1776 kprintf(" field replaceable unit: %x", sense->fru); 1777 } 1778 1779 if ((sense->extra_len >= 10) 1780 && (sense->sense_key_spec[0] & SSD_SCS_VALID) != 0) { 1781 kprintf(" sks:%x,%x", sense->sense_key_spec[0], 1782 scsi_2btoul(&sense->sense_key_spec[1])); 1783 } 1784 break; 1785 1786 default: 1787 kprintf("error code %d", 1788 sense->error_code & SSD_ERRCODE); 1789 if (sense->error_code & SSD_ERRCODE_VALID) { 1790 kprintf(" at block no. %d (decimal)", 1791 info = scsi_4btoul(sense->info)); 1792 } 1793 } 1794 1795 kprintf("\n"); 1796 } 1797 1798 #else /* !_KERNEL */ 1799 1800 1801 char * 1802 scsi_sense_string(struct cam_device *device, struct ccb_scsiio *csio, 1803 char *str, int str_len) 1804 { 1805 struct scsi_sense_data *sense; 1806 u_int32_t info; 1807 int error_code; 1808 int sense_key; 1809 int asc, ascq; 1810 u_int8_t command_print; 1811 char path_str[64]; 1812 char tmpstr[2048]; 1813 int tmpstrlen = 2048; 1814 int cur_len = 0, tmplen = 0, retlen; 1815 1816 if ((device == NULL) || (csio == NULL) || (str == NULL)) 1817 return(NULL); 1818 1819 if (str_len <= 0) 1820 return(NULL); 1821 1822 /* 1823 * If the CDB is a physical address, we can't deal with it.. 1824 */ 1825 if ((csio->ccb_h.flags & CAM_CDB_PHYS) != 0) 1826 command_print = 0; 1827 else 1828 command_print = 1; 1829 1830 cam_path_string(device, path_str, 64); 1831 1832 str[0] = '\0'; 1833 1834 sense = NULL; 1835 1836 if (command_print != 0) { 1837 char cdb_str[(SCSI_MAX_CDBLEN * 3) + 1]; 1838 1839 retlen = ksnprintf(tmpstr, tmpstrlen, "%s", path_str); 1840 1841 if ((tmplen = str_len - cur_len - 1) < 0) 1842 goto sst_bailout; 1843 1844 strncat(str, tmpstr, tmplen); 1845 cur_len += retlen; 1846 str[str_len - 1] = '\0'; 1847 1848 if ((csio->ccb_h.flags & CAM_CDB_POINTER) != 0) { 1849 retlen = ksnprintf(tmpstr, tmpstrlen, "%s. CDB: %s\n", 1850 scsi_op_desc(csio->cdb_io.cdb_ptr[0], 1851 &device->inq_data), 1852 scsi_cdb_string(csio->cdb_io.cdb_ptr, 1853 cdb_str, 1854 sizeof(cdb_str))); 1855 } else { 1856 retlen = ksnprintf(tmpstr, tmpstrlen, "%s. CDB: %s\n", 1857 scsi_op_desc(csio->cdb_io.cdb_bytes[0], 1858 &device->inq_data), scsi_cdb_string( 1859 csio->cdb_io.cdb_bytes, cdb_str, 1860 sizeof(cdb_str))); 1861 } 1862 1863 if ((tmplen = str_len - cur_len - 1) < 0) 1864 goto sst_bailout; 1865 1866 strncat(str, tmpstr, tmplen); 1867 cur_len += retlen; 1868 str[str_len - 1] = '\0'; 1869 } 1870 1871 /* 1872 * If the sense data is a physical pointer, forget it. 1873 */ 1874 if (csio->ccb_h.flags & CAM_SENSE_PTR) { 1875 if (csio->ccb_h.flags & CAM_SENSE_PHYS) 1876 return(NULL); 1877 else { 1878 /* 1879 * XXX KDM this is stupid, but casting the 1880 * structure doesn't work... 1881 */ 1882 bcopy(&csio->sense_data, &sense, 1883 sizeof(struct scsi_sense_data *)); 1884 } 1885 } else { 1886 /* 1887 * If the physical sense flag is set, but the sense pointer 1888 * is not also set, we assume that the user is an idiot and 1889 * return. (Well, okay, it could be that somehow, the 1890 * entire csio is physical, but we would have probably core 1891 * dumped on one of the bogus pointer deferences above 1892 * already.) 1893 */ 1894 if (csio->ccb_h.flags & CAM_SENSE_PHYS) 1895 return(NULL); 1896 else 1897 sense = &csio->sense_data; 1898 } 1899 1900 1901 retlen = ksnprintf(tmpstr, tmpstrlen, "%s", path_str); 1902 1903 if ((tmplen = str_len - cur_len - 1) < 0) 1904 goto sst_bailout; 1905 1906 strncat(str, tmpstr, tmplen); 1907 cur_len += retlen; 1908 str[str_len - 1] = '\0'; 1909 1910 error_code = sense->error_code & SSD_ERRCODE; 1911 sense_key = sense->flags & SSD_KEY; 1912 1913 switch (error_code) { 1914 case SSD_DEFERRED_ERROR: 1915 retlen = ksnprintf(tmpstr, tmpstrlen, "Deferred Error: "); 1916 1917 if ((tmplen = str_len - cur_len - 1) < 0) 1918 goto sst_bailout; 1919 1920 strncat(str, tmpstr, tmplen); 1921 cur_len += retlen; 1922 str[str_len - 1] = '\0'; 1923 /* FALLTHROUGH */ 1924 case SSD_CURRENT_ERROR: 1925 1926 retlen = ksnprintf(tmpstr, tmpstrlen, "%s", 1927 scsi_sense_key_text[sense_key]); 1928 1929 if ((tmplen = str_len - cur_len - 1) < 0) 1930 goto sst_bailout; 1931 1932 strncat(str, tmpstr, tmplen); 1933 cur_len += retlen; 1934 str[str_len - 1] = '\0'; 1935 1936 info = scsi_4btoul(sense->info); 1937 1938 if (sense->error_code & SSD_ERRCODE_VALID) { 1939 1940 switch (sense_key) { 1941 case SSD_KEY_NOT_READY: 1942 case SSD_KEY_ILLEGAL_REQUEST: 1943 case SSD_KEY_UNIT_ATTENTION: 1944 case SSD_KEY_DATA_PROTECT: 1945 break; 1946 case SSD_KEY_BLANK_CHECK: 1947 retlen = ksnprintf(tmpstr, tmpstrlen, 1948 " req sz: %d (decimal)", 1949 info); 1950 1951 if ((tmplen = str_len - cur_len - 1) < 0) 1952 goto sst_bailout; 1953 1954 strncat(str, tmpstr, tmplen); 1955 cur_len += retlen; 1956 str[str_len - 1] = '\0'; 1957 break; 1958 default: 1959 if (info) { 1960 if (sense->flags & SSD_ILI) { 1961 retlen = ksnprintf (tmpstr, 1962 tmpstrlen, 1963 " ILI (length " 1964 "mismatch): %d", info); 1965 1966 } else { 1967 retlen = ksnprintf(tmpstr, 1968 tmpstrlen, 1969 " info:%x", 1970 info); 1971 } 1972 1973 if ((tmplen = str_len - cur_len -1) < 0) 1974 goto sst_bailout; 1975 1976 strncat(str, tmpstr, tmplen); 1977 cur_len += retlen; 1978 str[str_len - 1] = '\0'; 1979 } 1980 } 1981 } else if (info) { 1982 retlen = ksnprintf(tmpstr, tmpstrlen," info?:%x", info); 1983 1984 if ((tmplen = str_len - cur_len -1) < 0) 1985 goto sst_bailout; 1986 1987 strncat(str, tmpstr, tmplen); 1988 cur_len += retlen; 1989 str[str_len - 1] = '\0'; 1990 } 1991 1992 if (sense->extra_len >= 4) { 1993 if (bcmp(sense->cmd_spec_info, "\0\0\0\0", 4)) { 1994 retlen = ksnprintf(tmpstr, tmpstrlen, 1995 " csi:%x,%x,%x,%x", 1996 sense->cmd_spec_info[0], 1997 sense->cmd_spec_info[1], 1998 sense->cmd_spec_info[2], 1999 sense->cmd_spec_info[3]); 2000 2001 if ((tmplen = str_len - cur_len -1) < 0) 2002 goto sst_bailout; 2003 2004 strncat(str, tmpstr, tmplen); 2005 cur_len += retlen; 2006 str[str_len - 1] = '\0'; 2007 } 2008 } 2009 2010 asc = (sense->extra_len >= 5) ? sense->add_sense_code : 0; 2011 ascq = (sense->extra_len >= 6) ? sense->add_sense_code_qual : 0; 2012 2013 if (asc || ascq) { 2014 const char *desc = scsi_sense_desc(asc, ascq, 2015 &device->inq_data); 2016 retlen = ksnprintf(tmpstr, tmpstrlen, 2017 " asc:%x,%x\n%s%s", asc, ascq, 2018 path_str, desc); 2019 2020 if ((tmplen = str_len - cur_len -1) < 0) 2021 goto sst_bailout; 2022 2023 strncat(str, tmpstr, tmplen); 2024 cur_len += retlen; 2025 str[str_len - 1] = '\0'; 2026 } 2027 2028 if (sense->extra_len >= 7 && sense->fru) { 2029 retlen = ksnprintf(tmpstr, tmpstrlen, 2030 " field replaceable unit: %x", 2031 sense->fru); 2032 2033 if ((tmplen = str_len - cur_len -1) < 0) 2034 goto sst_bailout; 2035 2036 strncat(str, tmpstr, tmplen); 2037 str[str_len - 1] = '\0'; 2038 cur_len += retlen; 2039 } 2040 2041 if ((sense->extra_len >= 10) 2042 && (sense->sense_key_spec[0] & SSD_SCS_VALID) != 0) { 2043 retlen = ksnprintf(tmpstr, tmpstrlen, " sks:%x,%x", 2044 sense->sense_key_spec[0], 2045 scsi_2btoul(&sense->sense_key_spec[1])); 2046 2047 if ((tmplen = str_len - cur_len -1) < 0) 2048 goto sst_bailout; 2049 2050 strncat(str, tmpstr, tmplen); 2051 str[str_len - 1] = '\0'; 2052 cur_len += retlen; 2053 } 2054 break; 2055 2056 default: 2057 retlen = ksnprintf(tmpstr, tmpstrlen, "error code %d", 2058 sense->error_code & SSD_ERRCODE); 2059 2060 if ((tmplen = str_len - cur_len -1) < 0) 2061 goto sst_bailout; 2062 2063 strncat(str, tmpstr, tmplen); 2064 cur_len += retlen; 2065 str[str_len - 1] = '\0'; 2066 2067 if (sense->error_code & SSD_ERRCODE_VALID) { 2068 retlen = ksnprintf(tmpstr, tmpstrlen, 2069 " at block no. %d (decimal)", 2070 info = scsi_4btoul(sense->info)); 2071 2072 if ((tmplen = str_len - cur_len -1) < 0) 2073 goto sst_bailout; 2074 2075 strncat(str, tmpstr, tmplen); 2076 cur_len += retlen; 2077 str[str_len - 1] = '\0'; 2078 } 2079 } 2080 2081 retlen = ksnprintf(tmpstr, tmpstrlen, "\n"); 2082 2083 if ((tmplen = str_len - cur_len -1) < 0) 2084 goto sst_bailout; 2085 2086 strncat(str, tmpstr, tmplen); 2087 cur_len += retlen; 2088 str[str_len - 1] = '\0'; 2089 2090 sst_bailout: 2091 2092 return(str); 2093 } 2094 2095 void 2096 scsi_sense_print(struct cam_device *device, struct ccb_scsiio *csio, 2097 FILE *ofile) 2098 { 2099 char str[2048]; 2100 2101 if ((device == NULL) || (csio == NULL) || (ofile == NULL)) 2102 return; 2103 2104 fprintf(ofile, "%s", scsi_sense_string(device, csio, str, 2048)); 2105 } 2106 2107 #endif /* _KERNEL/!_KERNEL */ 2108 2109 #ifdef _KERNEL 2110 int 2111 scsi_interpret_sense(union ccb *ccb, u_int32_t sense_flags, 2112 u_int32_t *relsim_flags, u_int32_t *openings, 2113 u_int32_t *timeout, scsi_sense_action error_action) 2114 #else 2115 int 2116 scsi_interpret_sense(struct cam_device *device, union ccb *ccb, 2117 u_int32_t sense_flags, u_int32_t *relsim_flags, 2118 u_int32_t *openings, u_int32_t *timeout, 2119 scsi_sense_action error_action) 2120 #endif 2121 { 2122 struct scsi_sense_data *sense; 2123 int error_code, sense_key, asc, ascq; 2124 int error; 2125 int print_sense; 2126 struct ccb_scsiio *csio; 2127 int retry; 2128 2129 csio = &ccb->csio; 2130 sense = &csio->sense_data; 2131 scsi_extract_sense(sense, &error_code, &sense_key, &asc, &ascq); 2132 2133 #ifdef _KERNEL 2134 if (bootverbose) { 2135 sense_flags |= SF_PRINT_ALWAYS; 2136 print_sense = TRUE; 2137 } else if ((sense_flags & SF_NO_PRINT) == 0) 2138 #else 2139 if ((sense_flags & SF_NO_PRINT) == 0) 2140 #endif 2141 print_sense = TRUE; 2142 else 2143 print_sense = FALSE; 2144 2145 switch (error_code) { 2146 case SSD_DEFERRED_ERROR: 2147 { 2148 /* 2149 * XXX dufault@FreeBSD.org 2150 * This error doesn't relate to the command associated 2151 * with this request sense. A deferred error is an error 2152 * for a command that has already returned GOOD status 2153 * (see 8.2.14.2). 2154 * 2155 * By my reading of that section, it looks like the current 2156 * command has been cancelled, we should now clean things up 2157 * (hopefully recovering any lost data) and then retry the 2158 * current command. There are two easy choices, both wrong: 2159 * 2160 * 1. Drop through (like we had been doing), thus treating 2161 * this as if the error were for the current command and 2162 * return and stop the current command. 2163 * 2164 * 2. Issue a retry (like I made it do) thus hopefully 2165 * recovering the current transfer, and ignoring the 2166 * fact that we've dropped a command. 2167 * 2168 * These should probably be handled in a device specific 2169 * sense handler or punted back up to a user mode daemon 2170 */ 2171 2172 /* decrement the number of retries */ 2173 retry = ccb->ccb_h.retry_count > 0; 2174 if (retry) 2175 ccb->ccb_h.retry_count--; 2176 2177 error = ERESTART; 2178 break; 2179 } 2180 case SSD_CURRENT_ERROR: 2181 { 2182 2183 switch (sense_key) { 2184 case SSD_KEY_NO_SENSE: 2185 /* Why were we called then? Well don't bail now */ 2186 /* FALLTHROUGH */ 2187 case SSD_KEY_EQUAL: 2188 /* These should be filtered by the peripheral drivers */ 2189 print_sense = FALSE; 2190 /* FALLTHROUGH */ 2191 case SSD_KEY_MISCOMPARE: 2192 /* decrement the number of retries */ 2193 retry = ccb->ccb_h.retry_count > 0; 2194 if (retry) { 2195 error = ERESTART; 2196 ccb->ccb_h.retry_count--; 2197 } else { 2198 error = EIO; 2199 } 2200 case SSD_KEY_RECOVERED_ERROR: 2201 error = 0; /* not an error */ 2202 break; 2203 case SSD_KEY_ILLEGAL_REQUEST: 2204 if (((sense_flags & SF_QUIET_IR) != 0) 2205 && ((sense_flags & SF_PRINT_ALWAYS) == 0)) 2206 print_sense = FALSE; 2207 error = EINVAL; 2208 break; 2209 case SSD_KEY_NOT_READY: 2210 case SSD_KEY_DATA_PROTECT: 2211 case SSD_KEY_VOLUME_OVERFLOW: 2212 case SSD_KEY_BLANK_CHECK: /* should be filtered out by 2213 peripheral drivers */ 2214 retry = ccb->ccb_h.retry_count > 0; 2215 if (retry) { 2216 ccb->ccb_h.retry_count--; 2217 error = ERESTART; 2218 print_sense = FALSE; 2219 } else { 2220 if (((error_action & SSQ_PRINT_SENSE) == 0) 2221 && ((sense_flags & SF_PRINT_ALWAYS) == 0)) 2222 print_sense = FALSE; 2223 2224 error = error_action & SS_ERRMASK; 2225 } 2226 2227 break; 2228 case SSD_KEY_UNIT_ATTENTION: 2229 /* 2230 * This should also be filtered out by 2231 * peripheral drivers since each has a different 2232 * concept of what it means to invalidate the media. 2233 */ 2234 if ((sense_flags & SF_RETRY_UA) != 0) { 2235 /* don't decrement retry count */ 2236 error = ERESTART; 2237 print_sense = FALSE; 2238 } else { 2239 /* decrement the number of retries */ 2240 retry = ccb->ccb_h.retry_count > 0; 2241 if (retry) { 2242 ccb->ccb_h.retry_count--; 2243 error = ERESTART; 2244 print_sense = FALSE; 2245 } else { 2246 if (((error_action & 2247 SSQ_PRINT_SENSE) == 0) 2248 && ((sense_flags & 2249 SF_PRINT_ALWAYS) == 0)) 2250 print_sense = FALSE; 2251 2252 error = error_action & SS_ERRMASK; 2253 } 2254 } 2255 break; 2256 case SSD_KEY_ABORTED_COMMAND: 2257 default: 2258 /* decrement the number of retries */ 2259 retry = ccb->ccb_h.retry_count > 0; 2260 if (retry) { 2261 ccb->ccb_h.retry_count--; 2262 error = ERESTART; 2263 print_sense = FALSE; 2264 } else { 2265 if (((error_action & SSQ_PRINT_SENSE) == 0) 2266 && ((sense_flags & SF_PRINT_ALWAYS) == 0)) 2267 print_sense = FALSE; 2268 2269 error = error_action & SS_ERRMASK; 2270 } 2271 /* 2272 * Make sure ABORTED COMMAND errors get 2273 * printed as they're indicative of marginal 2274 * SCSI busses that people should address. 2275 */ 2276 if (sense_key == SSD_KEY_ABORTED_COMMAND) 2277 print_sense = TRUE; 2278 } 2279 break; 2280 } 2281 default: 2282 /* decrement the number of retries */ 2283 retry = ccb->ccb_h.retry_count > 0; 2284 if (retry) { 2285 ccb->ccb_h.retry_count--; 2286 error = ERESTART; 2287 print_sense = FALSE; 2288 } else 2289 error = EIO; 2290 break; 2291 } 2292 2293 if (print_sense) { 2294 #ifdef _KERNEL 2295 scsi_sense_print(csio); 2296 #else 2297 scsi_sense_print(device, csio, stdout); 2298 #endif 2299 } 2300 2301 return (error); 2302 } 2303 2304 /* 2305 * This function currently requires at least 36 bytes, or 2306 * SHORT_INQUIRY_LENGTH, worth of data to function properly. If this 2307 * function needs more or less data in the future, another length should be 2308 * defined in scsi_all.h to indicate the minimum amount of data necessary 2309 * for this routine to function properly. 2310 */ 2311 void 2312 scsi_print_inquiry(struct scsi_inquiry_data *inq_data) 2313 { 2314 u_int8_t type; 2315 char *dtype, *qtype; 2316 char vendor[16], product[48], revision[16], rstr[4]; 2317 2318 type = SID_TYPE(inq_data); 2319 2320 /* 2321 * Figure out basic device type and qualifier. 2322 */ 2323 if (SID_QUAL_IS_VENDOR_UNIQUE(inq_data)) { 2324 qtype = "(vendor-unique qualifier)"; 2325 } else { 2326 switch (SID_QUAL(inq_data)) { 2327 case SID_QUAL_LU_CONNECTED: 2328 qtype = ""; 2329 break; 2330 2331 case SID_QUAL_LU_OFFLINE: 2332 qtype = "(offline)"; 2333 break; 2334 2335 case SID_QUAL_RSVD: 2336 qtype = "(reserved qualifier)"; 2337 break; 2338 default: 2339 case SID_QUAL_BAD_LU: 2340 qtype = "(lun not supported)"; 2341 break; 2342 } 2343 } 2344 2345 switch (type) { 2346 case T_DIRECT: 2347 dtype = "Direct Access"; 2348 break; 2349 case T_SEQUENTIAL: 2350 dtype = "Sequential Access"; 2351 break; 2352 case T_PRINTER: 2353 dtype = "Printer"; 2354 break; 2355 case T_PROCESSOR: 2356 dtype = "Processor"; 2357 break; 2358 case T_CDROM: 2359 dtype = "CD-ROM"; 2360 break; 2361 case T_WORM: 2362 dtype = "Worm"; 2363 break; 2364 case T_SCANNER: 2365 dtype = "Scanner"; 2366 break; 2367 case T_OPTICAL: 2368 dtype = "Optical"; 2369 break; 2370 case T_CHANGER: 2371 dtype = "Changer"; 2372 break; 2373 case T_COMM: 2374 dtype = "Communication"; 2375 break; 2376 case T_STORARRAY: 2377 dtype = "Storage Array"; 2378 break; 2379 case T_ENCLOSURE: 2380 dtype = "Enclosure Services"; 2381 break; 2382 case T_RBC: 2383 dtype = "Simplified Direct Access"; 2384 break; 2385 case T_OCRW: 2386 dtype = "Optical Card Read/Write"; 2387 break; 2388 case T_NODEVICE: 2389 dtype = "Uninstalled"; 2390 default: 2391 dtype = "unknown"; 2392 break; 2393 } 2394 2395 cam_strvis(vendor, inq_data->vendor, sizeof(inq_data->vendor), 2396 sizeof(vendor)); 2397 cam_strvis(product, inq_data->product, sizeof(inq_data->product), 2398 sizeof(product)); 2399 cam_strvis(revision, inq_data->revision, sizeof(inq_data->revision), 2400 sizeof(revision)); 2401 2402 if (SID_ANSI_REV(inq_data) == SCSI_REV_CCS) 2403 bcopy("CCS", rstr, 4); 2404 else 2405 ksnprintf(rstr, sizeof (rstr), "%d", SID_ANSI_REV(inq_data)); 2406 kprintf("<%s %s %s> %s %s SCSI-%s device %s\n", 2407 vendor, product, revision, 2408 SID_IS_REMOVABLE(inq_data) ? "Removable" : "Fixed", 2409 dtype, rstr, qtype); 2410 } 2411 2412 /* 2413 * Table of syncrates that don't follow the "divisible by 4" 2414 * rule. This table will be expanded in future SCSI specs. 2415 */ 2416 static struct { 2417 u_int period_factor; 2418 u_int period; /* in 100ths of ns */ 2419 } scsi_syncrates[] = { 2420 { 0x08, 625 }, /* FAST-160 */ 2421 { 0x09, 1250 }, /* FAST-80 */ 2422 { 0x0a, 2500 }, /* FAST-40 40MHz */ 2423 { 0x0b, 3030 }, /* FAST-40 33MHz */ 2424 { 0x0c, 5000 } /* FAST-20 */ 2425 }; 2426 2427 /* 2428 * Return the frequency in kHz corresponding to the given 2429 * sync period factor. 2430 */ 2431 u_int 2432 scsi_calc_syncsrate(u_int period_factor) 2433 { 2434 int i; 2435 int num_syncrates; 2436 2437 num_syncrates = sizeof(scsi_syncrates) / sizeof(scsi_syncrates[0]); 2438 /* See if the period is in the "exception" table */ 2439 for (i = 0; i < num_syncrates; i++) { 2440 2441 if (period_factor == scsi_syncrates[i].period_factor) { 2442 /* Period in kHz */ 2443 return (100000000 / scsi_syncrates[i].period); 2444 } 2445 } 2446 2447 /* 2448 * Wasn't in the table, so use the standard 2449 * 4 times conversion. 2450 */ 2451 return (10000000 / (period_factor * 4 * 10)); 2452 } 2453 2454 /* 2455 * Return the SCSI sync parameter that corresponsd to 2456 * the passed in period in 10ths of ns. 2457 */ 2458 u_int 2459 scsi_calc_syncparam(u_int period) 2460 { 2461 int i; 2462 int num_syncrates; 2463 2464 if (period == 0) 2465 return (~0); /* Async */ 2466 2467 /* Adjust for exception table being in 100ths. */ 2468 period *= 10; 2469 num_syncrates = sizeof(scsi_syncrates) / sizeof(scsi_syncrates[0]); 2470 /* See if the period is in the "exception" table */ 2471 for (i = 0; i < num_syncrates; i++) { 2472 2473 if (period <= scsi_syncrates[i].period) { 2474 /* Period in 100ths of ns */ 2475 return (scsi_syncrates[i].period_factor); 2476 } 2477 } 2478 2479 /* 2480 * Wasn't in the table, so use the standard 2481 * 1/4 period in ns conversion. 2482 */ 2483 return (period/400); 2484 } 2485 2486 void 2487 scsi_test_unit_ready(struct ccb_scsiio *csio, u_int32_t retries, 2488 void (*cbfcnp)(struct cam_periph *, union ccb *), 2489 u_int8_t tag_action, u_int8_t sense_len, u_int32_t timeout) 2490 { 2491 struct scsi_test_unit_ready *scsi_cmd; 2492 2493 cam_fill_csio(csio, 2494 retries, 2495 cbfcnp, 2496 CAM_DIR_NONE, 2497 tag_action, 2498 /*data_ptr*/NULL, 2499 /*dxfer_len*/0, 2500 sense_len, 2501 sizeof(*scsi_cmd), 2502 timeout); 2503 2504 scsi_cmd = (struct scsi_test_unit_ready *)&csio->cdb_io.cdb_bytes; 2505 bzero(scsi_cmd, sizeof(*scsi_cmd)); 2506 scsi_cmd->opcode = TEST_UNIT_READY; 2507 } 2508 2509 void 2510 scsi_request_sense(struct ccb_scsiio *csio, u_int32_t retries, 2511 void (*cbfcnp)(struct cam_periph *, union ccb *), 2512 void *data_ptr, u_int8_t dxfer_len, u_int8_t tag_action, 2513 u_int8_t sense_len, u_int32_t timeout) 2514 { 2515 struct scsi_request_sense *scsi_cmd; 2516 2517 cam_fill_csio(csio, 2518 retries, 2519 cbfcnp, 2520 CAM_DIR_IN, 2521 tag_action, 2522 data_ptr, 2523 dxfer_len, 2524 sense_len, 2525 sizeof(*scsi_cmd), 2526 timeout); 2527 2528 scsi_cmd = (struct scsi_request_sense *)&csio->cdb_io.cdb_bytes; 2529 bzero(scsi_cmd, sizeof(*scsi_cmd)); 2530 scsi_cmd->opcode = REQUEST_SENSE; 2531 scsi_cmd->length = dxfer_len; 2532 } 2533 2534 void 2535 scsi_inquiry(struct ccb_scsiio *csio, u_int32_t retries, 2536 void (*cbfcnp)(struct cam_periph *, union ccb *), 2537 u_int8_t tag_action, u_int8_t *inq_buf, u_int32_t inq_len, 2538 int evpd, u_int8_t page_code, u_int8_t sense_len, 2539 u_int32_t timeout) 2540 { 2541 struct scsi_inquiry *scsi_cmd; 2542 2543 cam_fill_csio(csio, 2544 retries, 2545 cbfcnp, 2546 /*flags*/CAM_DIR_IN, 2547 tag_action, 2548 /*data_ptr*/inq_buf, 2549 /*dxfer_len*/inq_len, 2550 sense_len, 2551 sizeof(*scsi_cmd), 2552 timeout); 2553 2554 scsi_cmd = (struct scsi_inquiry *)&csio->cdb_io.cdb_bytes; 2555 bzero(scsi_cmd, sizeof(*scsi_cmd)); 2556 scsi_cmd->opcode = INQUIRY; 2557 if (evpd) { 2558 scsi_cmd->byte2 |= SI_EVPD; 2559 scsi_cmd->page_code = page_code; 2560 } 2561 /* 2562 * A 'transfer units' count of 256 is coded as 2563 * zero for all commands with a single byte count 2564 * field. 2565 */ 2566 if (inq_len == 256) 2567 inq_len = 0; 2568 scsi_cmd->length = inq_len; 2569 } 2570 2571 void 2572 scsi_mode_sense(struct ccb_scsiio *csio, u_int32_t retries, 2573 void (*cbfcnp)(struct cam_periph *, union ccb *), 2574 u_int8_t tag_action, int dbd, u_int8_t page_code, 2575 u_int8_t page, u_int8_t *param_buf, u_int32_t param_len, 2576 u_int8_t sense_len, u_int32_t timeout) 2577 { 2578 return(scsi_mode_sense_len(csio, retries, cbfcnp, tag_action, dbd, 2579 page_code, page, param_buf, param_len, 0, 2580 sense_len, timeout)); 2581 } 2582 2583 void 2584 scsi_mode_sense_len(struct ccb_scsiio *csio, u_int32_t retries, 2585 void (*cbfcnp)(struct cam_periph *, union ccb *), 2586 u_int8_t tag_action, int dbd, u_int8_t page_code, 2587 u_int8_t page, u_int8_t *param_buf, u_int32_t param_len, 2588 int minimum_cmd_size, u_int8_t sense_len, u_int32_t timeout) 2589 { 2590 u_int8_t cdb_len; 2591 2592 /* 2593 * Use the smallest possible command to perform the operation. 2594 */ 2595 if ((param_len < 256) && (minimum_cmd_size < 10)) { 2596 /* 2597 * We can fit in a 6 byte cdb. 2598 */ 2599 struct scsi_mode_sense_6 *scsi_cmd; 2600 2601 scsi_cmd = (struct scsi_mode_sense_6 *)&csio->cdb_io.cdb_bytes; 2602 bzero(scsi_cmd, sizeof(*scsi_cmd)); 2603 scsi_cmd->opcode = MODE_SENSE_6; 2604 if (dbd != 0) 2605 scsi_cmd->byte2 |= SMS_DBD; 2606 scsi_cmd->page = page_code | page; 2607 scsi_cmd->length = param_len; 2608 cdb_len = sizeof(*scsi_cmd); 2609 } else { 2610 /* 2611 * Need a 10 byte cdb. 2612 */ 2613 struct scsi_mode_sense_10 *scsi_cmd; 2614 2615 scsi_cmd = (struct scsi_mode_sense_10 *)&csio->cdb_io.cdb_bytes; 2616 bzero(scsi_cmd, sizeof(*scsi_cmd)); 2617 scsi_cmd->opcode = MODE_SENSE_10; 2618 if (dbd != 0) 2619 scsi_cmd->byte2 |= SMS_DBD; 2620 scsi_cmd->page = page_code | page; 2621 scsi_ulto2b(param_len, scsi_cmd->length); 2622 cdb_len = sizeof(*scsi_cmd); 2623 } 2624 cam_fill_csio(csio, 2625 retries, 2626 cbfcnp, 2627 CAM_DIR_IN, 2628 tag_action, 2629 param_buf, 2630 param_len, 2631 sense_len, 2632 cdb_len, 2633 timeout); 2634 } 2635 2636 void 2637 scsi_mode_select(struct ccb_scsiio *csio, u_int32_t retries, 2638 void (*cbfcnp)(struct cam_periph *, union ccb *), 2639 u_int8_t tag_action, int scsi_page_fmt, int save_pages, 2640 u_int8_t *param_buf, u_int32_t param_len, u_int8_t sense_len, 2641 u_int32_t timeout) 2642 { 2643 return(scsi_mode_select_len(csio, retries, cbfcnp, tag_action, 2644 scsi_page_fmt, save_pages, param_buf, 2645 param_len, 0, sense_len, timeout)); 2646 } 2647 2648 void 2649 scsi_mode_select_len(struct ccb_scsiio *csio, u_int32_t retries, 2650 void (*cbfcnp)(struct cam_periph *, union ccb *), 2651 u_int8_t tag_action, int scsi_page_fmt, int save_pages, 2652 u_int8_t *param_buf, u_int32_t param_len, 2653 int minimum_cmd_size, u_int8_t sense_len, 2654 u_int32_t timeout) 2655 { 2656 u_int8_t cdb_len; 2657 2658 /* 2659 * Use the smallest possible command to perform the operation. 2660 */ 2661 if ((param_len < 256) && (minimum_cmd_size < 10)) { 2662 /* 2663 * We can fit in a 6 byte cdb. 2664 */ 2665 struct scsi_mode_select_6 *scsi_cmd; 2666 2667 scsi_cmd = (struct scsi_mode_select_6 *)&csio->cdb_io.cdb_bytes; 2668 bzero(scsi_cmd, sizeof(*scsi_cmd)); 2669 scsi_cmd->opcode = MODE_SELECT_6; 2670 if (scsi_page_fmt != 0) 2671 scsi_cmd->byte2 |= SMS_PF; 2672 if (save_pages != 0) 2673 scsi_cmd->byte2 |= SMS_SP; 2674 scsi_cmd->length = param_len; 2675 cdb_len = sizeof(*scsi_cmd); 2676 } else { 2677 /* 2678 * Need a 10 byte cdb. 2679 */ 2680 struct scsi_mode_select_10 *scsi_cmd; 2681 2682 scsi_cmd = 2683 (struct scsi_mode_select_10 *)&csio->cdb_io.cdb_bytes; 2684 bzero(scsi_cmd, sizeof(*scsi_cmd)); 2685 scsi_cmd->opcode = MODE_SELECT_10; 2686 if (scsi_page_fmt != 0) 2687 scsi_cmd->byte2 |= SMS_PF; 2688 if (save_pages != 0) 2689 scsi_cmd->byte2 |= SMS_SP; 2690 scsi_ulto2b(param_len, scsi_cmd->length); 2691 cdb_len = sizeof(*scsi_cmd); 2692 } 2693 cam_fill_csio(csio, 2694 retries, 2695 cbfcnp, 2696 CAM_DIR_OUT, 2697 tag_action, 2698 param_buf, 2699 param_len, 2700 sense_len, 2701 cdb_len, 2702 timeout); 2703 } 2704 2705 2706 /* XXX allow specification of address and PMI bit and LBA */ 2707 void 2708 scsi_read_capacity(struct ccb_scsiio *csio, u_int32_t retries, 2709 void (*cbfcnp)(struct cam_periph *, union ccb *), 2710 u_int8_t tag_action, 2711 struct scsi_read_capacity_data *rcap_buf, 2712 u_int8_t sense_len, u_int32_t timeout) 2713 { 2714 struct scsi_read_capacity *scsi_cmd; 2715 2716 cam_fill_csio(csio, 2717 retries, 2718 cbfcnp, 2719 /*flags*/CAM_DIR_IN, 2720 tag_action, 2721 /*data_ptr*/(u_int8_t *)rcap_buf, 2722 /*dxfer_len*/sizeof(*rcap_buf), 2723 sense_len, 2724 sizeof(*scsi_cmd), 2725 timeout); 2726 2727 scsi_cmd = (struct scsi_read_capacity *)&csio->cdb_io.cdb_bytes; 2728 bzero(scsi_cmd, sizeof(*scsi_cmd)); 2729 scsi_cmd->opcode = READ_CAPACITY; 2730 } 2731 2732 /* 2733 * Prevent or allow the user to remove the media 2734 */ 2735 void 2736 scsi_prevent(struct ccb_scsiio *csio, u_int32_t retries, 2737 void (*cbfcnp)(struct cam_periph *, union ccb *), 2738 u_int8_t tag_action, u_int8_t action, 2739 u_int8_t sense_len, u_int32_t timeout) 2740 { 2741 struct scsi_prevent *scsi_cmd; 2742 2743 cam_fill_csio(csio, 2744 retries, 2745 cbfcnp, 2746 /*flags*/CAM_DIR_NONE, 2747 tag_action, 2748 /*data_ptr*/NULL, 2749 /*dxfer_len*/0, 2750 sense_len, 2751 sizeof(*scsi_cmd), 2752 timeout); 2753 2754 scsi_cmd = (struct scsi_prevent *)&csio->cdb_io.cdb_bytes; 2755 bzero(scsi_cmd, sizeof(*scsi_cmd)); 2756 scsi_cmd->opcode = PREVENT_ALLOW; 2757 scsi_cmd->how = action; 2758 } 2759 2760 /* 2761 * Syncronize the media to the contents of the cache for 2762 * the given lba/count pair. Specifying 0/0 means sync 2763 * the whole cache. 2764 */ 2765 void 2766 scsi_synchronize_cache(struct ccb_scsiio *csio, u_int32_t retries, 2767 void (*cbfcnp)(struct cam_periph *, union ccb *), 2768 u_int8_t tag_action, u_int32_t begin_lba, 2769 u_int16_t lb_count, u_int8_t sense_len, 2770 u_int32_t timeout) 2771 { 2772 struct scsi_sync_cache *scsi_cmd; 2773 2774 cam_fill_csio(csio, 2775 retries, 2776 cbfcnp, 2777 /*flags*/CAM_DIR_NONE, 2778 tag_action, 2779 /*data_ptr*/NULL, 2780 /*dxfer_len*/0, 2781 sense_len, 2782 sizeof(*scsi_cmd), 2783 timeout); 2784 2785 scsi_cmd = (struct scsi_sync_cache *)&csio->cdb_io.cdb_bytes; 2786 bzero(scsi_cmd, sizeof(*scsi_cmd)); 2787 scsi_cmd->opcode = SYNCHRONIZE_CACHE; 2788 scsi_ulto4b(begin_lba, scsi_cmd->begin_lba); 2789 scsi_ulto2b(lb_count, scsi_cmd->lb_count); 2790 } 2791 2792 void 2793 scsi_read_write(struct ccb_scsiio *csio, u_int32_t retries, 2794 void (*cbfcnp)(struct cam_periph *, union ccb *), 2795 u_int8_t tag_action, int readop, u_int8_t byte2, 2796 int minimum_cmd_size, u_int32_t lba, u_int32_t block_count, 2797 u_int8_t *data_ptr, u_int32_t dxfer_len, u_int8_t sense_len, 2798 u_int32_t timeout) 2799 { 2800 u_int8_t cdb_len; 2801 /* 2802 * Use the smallest possible command to perform the operation 2803 * as some legacy hardware does not support the 10 byte 2804 * commands. If any of the lower 5 bits in byte2 is set, we have 2805 * to go with a larger command. 2806 * 2807 */ 2808 if ((minimum_cmd_size < 10) 2809 && ((lba & 0x1fffff) == lba) 2810 && ((block_count & 0xff) == block_count) 2811 && ((byte2 & 0xe0) == 0)) { 2812 /* 2813 * We can fit in a 6 byte cdb. 2814 */ 2815 struct scsi_rw_6 *scsi_cmd; 2816 2817 scsi_cmd = (struct scsi_rw_6 *)&csio->cdb_io.cdb_bytes; 2818 scsi_cmd->opcode = readop ? READ_6 : WRITE_6; 2819 scsi_ulto3b(lba, scsi_cmd->addr); 2820 scsi_cmd->length = block_count & 0xff; 2821 scsi_cmd->control = 0; 2822 cdb_len = sizeof(*scsi_cmd); 2823 2824 CAM_DEBUG(csio->ccb_h.path, CAM_DEBUG_SUBTRACE, 2825 ("6byte: %x%x%x:%d:%d\n", scsi_cmd->addr[0], 2826 scsi_cmd->addr[1], scsi_cmd->addr[2], 2827 scsi_cmd->length, dxfer_len)); 2828 } else if ((minimum_cmd_size < 12) 2829 && ((block_count & 0xffff) == block_count)) { 2830 /* 2831 * Need a 10 byte cdb. 2832 */ 2833 struct scsi_rw_10 *scsi_cmd; 2834 2835 scsi_cmd = (struct scsi_rw_10 *)&csio->cdb_io.cdb_bytes; 2836 scsi_cmd->opcode = readop ? READ_10 : WRITE_10; 2837 scsi_cmd->byte2 = byte2; 2838 scsi_ulto4b(lba, scsi_cmd->addr); 2839 scsi_cmd->reserved = 0; 2840 scsi_ulto2b(block_count, scsi_cmd->length); 2841 scsi_cmd->control = 0; 2842 cdb_len = sizeof(*scsi_cmd); 2843 2844 CAM_DEBUG(csio->ccb_h.path, CAM_DEBUG_SUBTRACE, 2845 ("10byte: %x%x%x%x:%x%x: %d\n", scsi_cmd->addr[0], 2846 scsi_cmd->addr[1], scsi_cmd->addr[2], 2847 scsi_cmd->addr[3], scsi_cmd->length[0], 2848 scsi_cmd->length[1], dxfer_len)); 2849 } else { 2850 /* 2851 * The block count is too big for a 10 byte CDB, use a 12 2852 * byte CDB. READ/WRITE(12) are currently only defined for 2853 * optical devices. 2854 */ 2855 struct scsi_rw_12 *scsi_cmd; 2856 2857 scsi_cmd = (struct scsi_rw_12 *)&csio->cdb_io.cdb_bytes; 2858 scsi_cmd->opcode = readop ? READ_12 : WRITE_12; 2859 scsi_cmd->byte2 = byte2; 2860 scsi_ulto4b(lba, scsi_cmd->addr); 2861 scsi_cmd->reserved = 0; 2862 scsi_ulto4b(block_count, scsi_cmd->length); 2863 scsi_cmd->control = 0; 2864 cdb_len = sizeof(*scsi_cmd); 2865 2866 CAM_DEBUG(csio->ccb_h.path, CAM_DEBUG_SUBTRACE, 2867 ("12byte: %x%x%x%x:%x%x%x%x: %d\n", scsi_cmd->addr[0], 2868 scsi_cmd->addr[1], scsi_cmd->addr[2], 2869 scsi_cmd->addr[3], scsi_cmd->length[0], 2870 scsi_cmd->length[1], scsi_cmd->length[2], 2871 scsi_cmd->length[3], dxfer_len)); 2872 } 2873 cam_fill_csio(csio, 2874 retries, 2875 cbfcnp, 2876 /*flags*/readop ? CAM_DIR_IN : CAM_DIR_OUT, 2877 tag_action, 2878 data_ptr, 2879 dxfer_len, 2880 sense_len, 2881 cdb_len, 2882 timeout); 2883 } 2884 2885 void 2886 scsi_start_stop(struct ccb_scsiio *csio, u_int32_t retries, 2887 void (*cbfcnp)(struct cam_periph *, union ccb *), 2888 u_int8_t tag_action, int start, int load_eject, 2889 int immediate, u_int8_t sense_len, u_int32_t timeout) 2890 { 2891 struct scsi_start_stop_unit *scsi_cmd; 2892 int extra_flags = 0; 2893 2894 scsi_cmd = (struct scsi_start_stop_unit *)&csio->cdb_io.cdb_bytes; 2895 bzero(scsi_cmd, sizeof(*scsi_cmd)); 2896 scsi_cmd->opcode = START_STOP_UNIT; 2897 if (start != 0) { 2898 scsi_cmd->how |= SSS_START; 2899 /* it takes a lot of power to start a drive */ 2900 extra_flags |= CAM_HIGH_POWER; 2901 } 2902 if (load_eject != 0) 2903 scsi_cmd->how |= SSS_LOEJ; 2904 if (immediate != 0) 2905 scsi_cmd->byte2 |= SSS_IMMED; 2906 2907 cam_fill_csio(csio, 2908 retries, 2909 cbfcnp, 2910 /*flags*/CAM_DIR_NONE | extra_flags, 2911 tag_action, 2912 /*data_ptr*/NULL, 2913 /*dxfer_len*/0, 2914 sense_len, 2915 sizeof(*scsi_cmd), 2916 timeout); 2917 2918 } 2919 2920 2921 /* 2922 * Try make as good a match as possible with 2923 * available sub drivers 2924 */ 2925 int 2926 scsi_inquiry_match(caddr_t inqbuffer, caddr_t table_entry) 2927 { 2928 struct scsi_inquiry_pattern *entry; 2929 struct scsi_inquiry_data *inq; 2930 2931 entry = (struct scsi_inquiry_pattern *)table_entry; 2932 inq = (struct scsi_inquiry_data *)inqbuffer; 2933 2934 if (((SID_TYPE(inq) == entry->type) 2935 || (entry->type == T_ANY)) 2936 && (SID_IS_REMOVABLE(inq) ? entry->media_type & SIP_MEDIA_REMOVABLE 2937 : entry->media_type & SIP_MEDIA_FIXED) 2938 && (cam_strmatch(inq->vendor, entry->vendor, sizeof(inq->vendor)) == 0) 2939 && (cam_strmatch(inq->product, entry->product, 2940 sizeof(inq->product)) == 0) 2941 && (cam_strmatch(inq->revision, entry->revision, 2942 sizeof(inq->revision)) == 0)) { 2943 return (0); 2944 } 2945 return (-1); 2946 } 2947 2948 /* 2949 * Try make as good a match as possible with 2950 * available sub drivers 2951 */ 2952 int 2953 scsi_static_inquiry_match(caddr_t inqbuffer, caddr_t table_entry) 2954 { 2955 struct scsi_static_inquiry_pattern *entry; 2956 struct scsi_inquiry_data *inq; 2957 2958 entry = (struct scsi_static_inquiry_pattern *)table_entry; 2959 inq = (struct scsi_inquiry_data *)inqbuffer; 2960 2961 if (((SID_TYPE(inq) == entry->type) 2962 || (entry->type == T_ANY)) 2963 && (SID_IS_REMOVABLE(inq) ? entry->media_type & SIP_MEDIA_REMOVABLE 2964 : entry->media_type & SIP_MEDIA_FIXED) 2965 && (cam_strmatch(inq->vendor, entry->vendor, sizeof(inq->vendor)) == 0) 2966 && (cam_strmatch(inq->product, entry->product, 2967 sizeof(inq->product)) == 0) 2968 && (cam_strmatch(inq->revision, entry->revision, 2969 sizeof(inq->revision)) == 0)) { 2970 return (0); 2971 } 2972 return (-1); 2973 } 2974