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