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