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