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