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