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.9 2002/10/21 05:38:11 simokawa Exp $ 30 * $DragonFly: src/sys/bus/cam/scsi/scsi_all.c,v 1.3 2003/08/07 21:16:44 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 } 2527 2528 void 2529 scsi_inquiry(struct ccb_scsiio *csio, u_int32_t retries, 2530 void (*cbfcnp)(struct cam_periph *, union ccb *), 2531 u_int8_t tag_action, u_int8_t *inq_buf, u_int32_t inq_len, 2532 int evpd, u_int8_t page_code, u_int8_t sense_len, 2533 u_int32_t timeout) 2534 { 2535 struct scsi_inquiry *scsi_cmd; 2536 2537 cam_fill_csio(csio, 2538 retries, 2539 cbfcnp, 2540 /*flags*/CAM_DIR_IN, 2541 tag_action, 2542 /*data_ptr*/inq_buf, 2543 /*dxfer_len*/inq_len, 2544 sense_len, 2545 sizeof(*scsi_cmd), 2546 timeout); 2547 2548 scsi_cmd = (struct scsi_inquiry *)&csio->cdb_io.cdb_bytes; 2549 bzero(scsi_cmd, sizeof(*scsi_cmd)); 2550 scsi_cmd->opcode = INQUIRY; 2551 if (evpd) { 2552 scsi_cmd->byte2 |= SI_EVPD; 2553 scsi_cmd->page_code = page_code; 2554 } 2555 /* 2556 * A 'transfer units' count of 256 is coded as 2557 * zero for all commands with a single byte count 2558 * field. 2559 */ 2560 if (inq_len == 256) 2561 inq_len = 0; 2562 scsi_cmd->length = inq_len; 2563 } 2564 2565 void 2566 scsi_mode_sense(struct ccb_scsiio *csio, u_int32_t retries, 2567 void (*cbfcnp)(struct cam_periph *, union ccb *), 2568 u_int8_t tag_action, int dbd, u_int8_t page_code, 2569 u_int8_t page, u_int8_t *param_buf, u_int32_t param_len, 2570 u_int8_t sense_len, u_int32_t timeout) 2571 { 2572 u_int8_t cdb_len; 2573 2574 /* 2575 * Use the smallest possible command to perform the operation. 2576 */ 2577 if (param_len < 256) { 2578 /* 2579 * We can fit in a 6 byte cdb. 2580 */ 2581 struct scsi_mode_sense_6 *scsi_cmd; 2582 2583 scsi_cmd = (struct scsi_mode_sense_6 *)&csio->cdb_io.cdb_bytes; 2584 bzero(scsi_cmd, sizeof(*scsi_cmd)); 2585 scsi_cmd->opcode = MODE_SENSE_6; 2586 if (dbd != 0) 2587 scsi_cmd->byte2 |= SMS_DBD; 2588 scsi_cmd->page = page_code | page; 2589 scsi_cmd->length = param_len; 2590 cdb_len = sizeof(*scsi_cmd); 2591 } else { 2592 /* 2593 * Need a 10 byte cdb. 2594 */ 2595 struct scsi_mode_sense_10 *scsi_cmd; 2596 2597 scsi_cmd = (struct scsi_mode_sense_10 *)&csio->cdb_io.cdb_bytes; 2598 bzero(scsi_cmd, sizeof(*scsi_cmd)); 2599 scsi_cmd->opcode = MODE_SENSE_10; 2600 if (dbd != 0) 2601 scsi_cmd->byte2 |= SMS_DBD; 2602 scsi_cmd->page = page_code | page; 2603 scsi_ulto2b(param_len, scsi_cmd->length); 2604 cdb_len = sizeof(*scsi_cmd); 2605 } 2606 cam_fill_csio(csio, 2607 retries, 2608 cbfcnp, 2609 CAM_DIR_IN, 2610 tag_action, 2611 param_buf, 2612 param_len, 2613 sense_len, 2614 cdb_len, 2615 timeout); 2616 } 2617 2618 void 2619 scsi_mode_select(struct ccb_scsiio *csio, u_int32_t retries, 2620 void (*cbfcnp)(struct cam_periph *, union ccb *), 2621 u_int8_t tag_action, int scsi_page_fmt, int save_pages, 2622 u_int8_t *param_buf, u_int32_t param_len, u_int8_t sense_len, 2623 u_int32_t timeout) 2624 { 2625 u_int8_t cdb_len; 2626 2627 /* 2628 * Use the smallest possible command to perform the operation. 2629 */ 2630 if (param_len < 256) { 2631 /* 2632 * We can fit in a 6 byte cdb. 2633 */ 2634 struct scsi_mode_select_6 *scsi_cmd; 2635 2636 scsi_cmd = (struct scsi_mode_select_6 *)&csio->cdb_io.cdb_bytes; 2637 bzero(scsi_cmd, sizeof(*scsi_cmd)); 2638 scsi_cmd->opcode = MODE_SELECT_6; 2639 if (scsi_page_fmt != 0) 2640 scsi_cmd->byte2 |= SMS_PF; 2641 if (save_pages != 0) 2642 scsi_cmd->byte2 |= SMS_SP; 2643 scsi_cmd->length = param_len; 2644 cdb_len = sizeof(*scsi_cmd); 2645 } else { 2646 /* 2647 * Need a 10 byte cdb. 2648 */ 2649 struct scsi_mode_select_10 *scsi_cmd; 2650 2651 scsi_cmd = 2652 (struct scsi_mode_select_10 *)&csio->cdb_io.cdb_bytes; 2653 bzero(scsi_cmd, sizeof(*scsi_cmd)); 2654 scsi_cmd->opcode = MODE_SELECT_10; 2655 if (scsi_page_fmt != 0) 2656 scsi_cmd->byte2 |= SMS_PF; 2657 if (save_pages != 0) 2658 scsi_cmd->byte2 |= SMS_SP; 2659 scsi_ulto2b(param_len, scsi_cmd->length); 2660 cdb_len = sizeof(*scsi_cmd); 2661 } 2662 cam_fill_csio(csio, 2663 retries, 2664 cbfcnp, 2665 CAM_DIR_OUT, 2666 tag_action, 2667 param_buf, 2668 param_len, 2669 sense_len, 2670 cdb_len, 2671 timeout); 2672 } 2673 2674 2675 /* XXX allow specification of address and PMI bit and LBA */ 2676 void 2677 scsi_read_capacity(struct ccb_scsiio *csio, u_int32_t retries, 2678 void (*cbfcnp)(struct cam_periph *, union ccb *), 2679 u_int8_t tag_action, 2680 struct scsi_read_capacity_data *rcap_buf, 2681 u_int8_t sense_len, u_int32_t timeout) 2682 { 2683 struct scsi_read_capacity *scsi_cmd; 2684 2685 cam_fill_csio(csio, 2686 retries, 2687 cbfcnp, 2688 /*flags*/CAM_DIR_IN, 2689 tag_action, 2690 /*data_ptr*/(u_int8_t *)rcap_buf, 2691 /*dxfer_len*/sizeof(*rcap_buf), 2692 sense_len, 2693 sizeof(*scsi_cmd), 2694 timeout); 2695 2696 scsi_cmd = (struct scsi_read_capacity *)&csio->cdb_io.cdb_bytes; 2697 bzero(scsi_cmd, sizeof(*scsi_cmd)); 2698 scsi_cmd->opcode = READ_CAPACITY; 2699 } 2700 2701 /* 2702 * Prevent or allow the user to remove the media 2703 */ 2704 void 2705 scsi_prevent(struct ccb_scsiio *csio, u_int32_t retries, 2706 void (*cbfcnp)(struct cam_periph *, union ccb *), 2707 u_int8_t tag_action, u_int8_t action, 2708 u_int8_t sense_len, u_int32_t timeout) 2709 { 2710 struct scsi_prevent *scsi_cmd; 2711 2712 cam_fill_csio(csio, 2713 retries, 2714 cbfcnp, 2715 /*flags*/CAM_DIR_NONE, 2716 tag_action, 2717 /*data_ptr*/NULL, 2718 /*dxfer_len*/0, 2719 sense_len, 2720 sizeof(*scsi_cmd), 2721 timeout); 2722 2723 scsi_cmd = (struct scsi_prevent *)&csio->cdb_io.cdb_bytes; 2724 bzero(scsi_cmd, sizeof(*scsi_cmd)); 2725 scsi_cmd->opcode = PREVENT_ALLOW; 2726 scsi_cmd->how = action; 2727 } 2728 2729 /* 2730 * Syncronize the media to the contents of the cache for 2731 * the given lba/count pair. Specifying 0/0 means sync 2732 * the whole cache. 2733 */ 2734 void 2735 scsi_synchronize_cache(struct ccb_scsiio *csio, u_int32_t retries, 2736 void (*cbfcnp)(struct cam_periph *, union ccb *), 2737 u_int8_t tag_action, u_int32_t begin_lba, 2738 u_int16_t lb_count, u_int8_t sense_len, 2739 u_int32_t timeout) 2740 { 2741 struct scsi_sync_cache *scsi_cmd; 2742 2743 cam_fill_csio(csio, 2744 retries, 2745 cbfcnp, 2746 /*flags*/CAM_DIR_NONE, 2747 tag_action, 2748 /*data_ptr*/NULL, 2749 /*dxfer_len*/0, 2750 sense_len, 2751 sizeof(*scsi_cmd), 2752 timeout); 2753 2754 scsi_cmd = (struct scsi_sync_cache *)&csio->cdb_io.cdb_bytes; 2755 bzero(scsi_cmd, sizeof(*scsi_cmd)); 2756 scsi_cmd->opcode = SYNCHRONIZE_CACHE; 2757 scsi_ulto4b(begin_lba, scsi_cmd->begin_lba); 2758 scsi_ulto2b(lb_count, scsi_cmd->lb_count); 2759 } 2760 2761 void 2762 scsi_read_write(struct ccb_scsiio *csio, u_int32_t retries, 2763 void (*cbfcnp)(struct cam_periph *, union ccb *), 2764 u_int8_t tag_action, int readop, u_int8_t byte2, 2765 int minimum_cmd_size, u_int32_t lba, u_int32_t block_count, 2766 u_int8_t *data_ptr, u_int32_t dxfer_len, u_int8_t sense_len, 2767 u_int32_t timeout) 2768 { 2769 u_int8_t cdb_len; 2770 /* 2771 * Use the smallest possible command to perform the operation 2772 * as some legacy hardware does not support the 10 byte 2773 * commands. If any of the lower 5 bits in byte2 is set, we have 2774 * to go with a larger command. 2775 * 2776 */ 2777 if ((minimum_cmd_size < 10) 2778 && ((lba & 0x1fffff) == lba) 2779 && ((block_count & 0xff) == block_count) 2780 && ((byte2 & 0xe0) == 0)) { 2781 /* 2782 * We can fit in a 6 byte cdb. 2783 */ 2784 struct scsi_rw_6 *scsi_cmd; 2785 2786 scsi_cmd = (struct scsi_rw_6 *)&csio->cdb_io.cdb_bytes; 2787 scsi_cmd->opcode = readop ? READ_6 : WRITE_6; 2788 scsi_ulto3b(lba, scsi_cmd->addr); 2789 scsi_cmd->length = block_count & 0xff; 2790 scsi_cmd->control = 0; 2791 cdb_len = sizeof(*scsi_cmd); 2792 2793 CAM_DEBUG(csio->ccb_h.path, CAM_DEBUG_SUBTRACE, 2794 ("6byte: %x%x%x:%d:%d\n", scsi_cmd->addr[0], 2795 scsi_cmd->addr[1], scsi_cmd->addr[2], 2796 scsi_cmd->length, dxfer_len)); 2797 } else if ((minimum_cmd_size < 12) 2798 && ((block_count & 0xffff) == block_count)) { 2799 /* 2800 * Need a 10 byte cdb. 2801 */ 2802 struct scsi_rw_10 *scsi_cmd; 2803 2804 scsi_cmd = (struct scsi_rw_10 *)&csio->cdb_io.cdb_bytes; 2805 scsi_cmd->opcode = readop ? READ_10 : WRITE_10; 2806 scsi_cmd->byte2 = byte2; 2807 scsi_ulto4b(lba, scsi_cmd->addr); 2808 scsi_cmd->reserved = 0; 2809 scsi_ulto2b(block_count, scsi_cmd->length); 2810 scsi_cmd->control = 0; 2811 cdb_len = sizeof(*scsi_cmd); 2812 2813 CAM_DEBUG(csio->ccb_h.path, CAM_DEBUG_SUBTRACE, 2814 ("10byte: %x%x%x%x:%x%x: %d\n", scsi_cmd->addr[0], 2815 scsi_cmd->addr[1], scsi_cmd->addr[2], 2816 scsi_cmd->addr[3], scsi_cmd->length[0], 2817 scsi_cmd->length[1], dxfer_len)); 2818 } else { 2819 /* 2820 * The block count is too big for a 10 byte CDB, use a 12 2821 * byte CDB. READ/WRITE(12) are currently only defined for 2822 * optical devices. 2823 */ 2824 struct scsi_rw_12 *scsi_cmd; 2825 2826 scsi_cmd = (struct scsi_rw_12 *)&csio->cdb_io.cdb_bytes; 2827 scsi_cmd->opcode = readop ? READ_12 : WRITE_12; 2828 scsi_cmd->byte2 = byte2; 2829 scsi_ulto4b(lba, scsi_cmd->addr); 2830 scsi_cmd->reserved = 0; 2831 scsi_ulto4b(block_count, scsi_cmd->length); 2832 scsi_cmd->control = 0; 2833 cdb_len = sizeof(*scsi_cmd); 2834 2835 CAM_DEBUG(csio->ccb_h.path, CAM_DEBUG_SUBTRACE, 2836 ("12byte: %x%x%x%x:%x%x%x%x: %d\n", scsi_cmd->addr[0], 2837 scsi_cmd->addr[1], scsi_cmd->addr[2], 2838 scsi_cmd->addr[3], scsi_cmd->length[0], 2839 scsi_cmd->length[1], scsi_cmd->length[2], 2840 scsi_cmd->length[3], dxfer_len)); 2841 } 2842 cam_fill_csio(csio, 2843 retries, 2844 cbfcnp, 2845 /*flags*/readop ? CAM_DIR_IN : CAM_DIR_OUT, 2846 tag_action, 2847 data_ptr, 2848 dxfer_len, 2849 sense_len, 2850 cdb_len, 2851 timeout); 2852 } 2853 2854 void 2855 scsi_start_stop(struct ccb_scsiio *csio, u_int32_t retries, 2856 void (*cbfcnp)(struct cam_periph *, union ccb *), 2857 u_int8_t tag_action, int start, int load_eject, 2858 int immediate, u_int8_t sense_len, u_int32_t timeout) 2859 { 2860 struct scsi_start_stop_unit *scsi_cmd; 2861 int extra_flags = 0; 2862 2863 scsi_cmd = (struct scsi_start_stop_unit *)&csio->cdb_io.cdb_bytes; 2864 bzero(scsi_cmd, sizeof(*scsi_cmd)); 2865 scsi_cmd->opcode = START_STOP_UNIT; 2866 if (start != 0) { 2867 scsi_cmd->how |= SSS_START; 2868 /* it takes a lot of power to start a drive */ 2869 extra_flags |= CAM_HIGH_POWER; 2870 } 2871 if (load_eject != 0) 2872 scsi_cmd->how |= SSS_LOEJ; 2873 if (immediate != 0) 2874 scsi_cmd->byte2 |= SSS_IMMED; 2875 2876 cam_fill_csio(csio, 2877 retries, 2878 cbfcnp, 2879 /*flags*/CAM_DIR_NONE | extra_flags, 2880 tag_action, 2881 /*data_ptr*/NULL, 2882 /*dxfer_len*/0, 2883 sense_len, 2884 sizeof(*scsi_cmd), 2885 timeout); 2886 2887 } 2888 2889 2890 /* 2891 * Try make as good a match as possible with 2892 * available sub drivers 2893 */ 2894 int 2895 scsi_inquiry_match(caddr_t inqbuffer, caddr_t table_entry) 2896 { 2897 struct scsi_inquiry_pattern *entry; 2898 struct scsi_inquiry_data *inq; 2899 2900 entry = (struct scsi_inquiry_pattern *)table_entry; 2901 inq = (struct scsi_inquiry_data *)inqbuffer; 2902 2903 if (((SID_TYPE(inq) == entry->type) 2904 || (entry->type == T_ANY)) 2905 && (SID_IS_REMOVABLE(inq) ? entry->media_type & SIP_MEDIA_REMOVABLE 2906 : entry->media_type & SIP_MEDIA_FIXED) 2907 && (cam_strmatch(inq->vendor, entry->vendor, sizeof(inq->vendor)) == 0) 2908 && (cam_strmatch(inq->product, entry->product, 2909 sizeof(inq->product)) == 0) 2910 && (cam_strmatch(inq->revision, entry->revision, 2911 sizeof(inq->revision)) == 0)) { 2912 return (0); 2913 } 2914 return (-1); 2915 } 2916 2917 /* 2918 * Try make as good a match as possible with 2919 * available sub drivers 2920 */ 2921 int 2922 scsi_static_inquiry_match(caddr_t inqbuffer, caddr_t table_entry) 2923 { 2924 struct scsi_static_inquiry_pattern *entry; 2925 struct scsi_inquiry_data *inq; 2926 2927 entry = (struct scsi_static_inquiry_pattern *)table_entry; 2928 inq = (struct scsi_inquiry_data *)inqbuffer; 2929 2930 if (((SID_TYPE(inq) == entry->type) 2931 || (entry->type == T_ANY)) 2932 && (SID_IS_REMOVABLE(inq) ? entry->media_type & SIP_MEDIA_REMOVABLE 2933 : entry->media_type & SIP_MEDIA_FIXED) 2934 && (cam_strmatch(inq->vendor, entry->vendor, sizeof(inq->vendor)) == 0) 2935 && (cam_strmatch(inq->product, entry->product, 2936 sizeof(inq->product)) == 0) 2937 && (cam_strmatch(inq->revision, entry->revision, 2938 sizeof(inq->revision)) == 0)) { 2939 return (0); 2940 } 2941 return (-1); 2942 } 2943