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