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