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