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