2 * Implementation of Utility functions for all SCSI device types.
4 * Copyright (c) 1997, 1998 Justin T. Gibbs.
5 * Copyright (c) 1997, 1998, 2003 Kenneth D. Merry.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
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.
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
29 * $FreeBSD: src/sys/cam/scsi/scsi_all.c,v 1.14.2.11 2003/10/30 15:06:35 thomas Exp $
30 * $DragonFly: src/sys/bus/cam/scsi/scsi_all.c,v 1.9 2007/05/16 20:59:38 dillon Exp $
33 #include <sys/param.h>
38 #include <sys/systm.h>
46 #define ksnprintf snprintf /* ick, userland uses us too */
47 #define kprintf printf
51 #include "../cam_ccb.h"
52 #include "../cam_xpt.h"
53 #include "../cam_xpt_periph.h"
56 #include <sys/camlib.h>
64 #define ERESTART -1 /* restart syscall */
65 #define EJUSTRETURN -2 /* don't modify regs, just return */
68 const char *scsi_sense_key_text[] =
88 #if !defined(SCSI_NO_OP_STRINGS)
106 * WARNING: You must update the num_ops field below for this quirk table
107 * entry if you add more entries.
109 static struct op_table_entry plextor_cd_ops[] = {
110 {0xD8, R, "CD-DA READ"}
113 static struct scsi_op_quirk_entry scsi_op_quirk_table[] = {
116 * I believe that 0xD8 is the Plextor proprietary command
117 * to read CD-DA data. I'm not sure which Plextor CDROM
118 * models support the command, though. I know for sure
119 * that the 4X, 8X, and 12X models do, and presumably the
120 * 12-20X does. I don't know about any earlier models,
121 * though. If anyone has any more complete information,
122 * feel free to change this quirk entry.
124 {T_CDROM, SIP_MEDIA_REMOVABLE, "PLEXTOR", "CD-ROM PX*", "*"},
125 1, /* number of vendor-specific opcodes for this entry */
130 static struct op_table_entry scsi_op_codes[] = {
132 * From: ftp://ftp.symbios.com/pub/standards/io/t10/drafts/spc/op-num.txt
133 * Modifications by Kenneth Merry (ken@FreeBSD.ORG)
135 * Note: order is important in this table, scsi_op_desc() currently
136 * depends on the opcodes in the table being in order to save search time.
141 * SCSI Operation Codes
142 * Numeric Sorted Listing
145 * D - DIRECT ACCESS DEVICE (SBC) device column key
146 * .T - SEQUENTIAL ACCESS DEVICE (SSC) -------------------
147 * . L - PRINTER DEVICE (SSC) M = Mandatory
148 * . P - PROCESSOR DEVICE (SPC) O = Optional
149 * . .W - WRITE ONCE READ MULTIPLE DEVICE (SBC) V = Vendor specific
150 * . . R - CD DEVICE (MMC) R = Reserved
151 * . . S - SCANNER DEVICE (SGC) Z = Obsolete
152 * . . .O - OPTICAL MEMORY DEVICE (SBC)
153 * . . . M - MEDIA CHANGER DEVICE (SMC)
154 * . . . C - COMMUNICATION DEVICE (SSC)
155 * . . . .A - STORAGE ARRAY DEVICE (SCC)
156 * . . . . E - ENCLOSURE SERVICES DEVICE (SES)
157 * OP DTLPWRSOMCAE Description
158 * -- ------------ ---------------------------------------------------- */
159 /* 00 MMMMMMMMMMMM TEST UNIT READY */
160 {0x00, ALL, "TEST UNIT READY"},
164 /* 01 Z V ZO ZO REZERO UNIT */
165 {0x01, D|L|W|O|M, "REZERO UNIT"},
169 /* 03 MMMMMMMMMMMM REQUEST SENSE */
170 {0x03, ALL, "REQUEST SENSE"},
172 /* 04 M O O FORMAT UNIT */
173 {0x04, D|R|O, "FORMAT UNIT"},
174 /* 04 O FORMAT MEDIUM */
175 {0x04, T, "FORMAT MEDIUM"},
179 /* 05 VMVVVV V READ BLOCK LIMITS */
180 {0x05, T, "READ BLOCK LIMITS"},
184 /* 07 OVV O OV REASSIGN BLOCKS */
185 {0x07, D|W|O, "REASSIGN BLOCKS"},
186 /* 07 O INITIALIZE ELEMENT STATUS */
187 {0x07, M, "INITIALIZE ELEMENT STATUS"},
189 /* 08 OMV OO OV READ(06) */
190 {0x08, D|T|W|R|O, "READ(06)"},
192 {0x08, P, "RECEIVE"},
193 /* 08 M GET MESSAGE(06) */
194 {0x08, C, "GET MESSAGE(06)"},
198 /* 0A OM O OV WRITE(06) */
199 {0x0A, D|T|W|O, "WRITE(06)"},
201 {0x0A, P, "SEND(06)"},
202 /* 0A M SEND MESSAGE(06) */
203 {0x0A, C, "SEND MESSAGE(06)"},
207 /* 0B Z ZO ZV SEEK(06) */
208 {0x0B, D|W|R|O, "SEEK(06)"},
209 /* 0B O SLEW AND PRINT */
210 {0x0B, L, "SLEW AND PRINT"},
215 /* 0F VOVVVV V READ REVERSE */
216 {0x0F, T, "READ REVERSE"},
218 /* 10 VM VVV WRITE FILEMARKS */
219 {0x10, T, "WRITE FILEMARKS"},
220 /* 10 O O SYNCHRONIZE BUFFER */
221 {0x10, L|W, "SYNCHRONIZE BUFFER"},
223 /* 11 VMVVVV SPACE */
226 /* 12 MMMMMMMMMMMM INQUIRY */
227 {0x12, ALL, "INQUIRY"},
229 /* 13 VOVVVV VERIFY(06) */
230 {0x13, T, "VERIFY(06)"},
232 /* 14 VOOVVV RECOVER BUFFERED DATA */
233 {0x14, T|L, "RECOVER BUFFERED DATA"},
235 /* 15 OMO OOOOOOOO MODE SELECT(06) */
236 {0x15, ALL & ~(P), "MODE SELECT(06)"},
238 /* 16 MMMOMMMM O RESERVE(06) */
239 {0x16, D|T|L|P|W|R|S|O|E, "RESERVE(06)"},
240 /* 16 M RESERVE ELEMENT(06) */
241 {0x16, M, "RESERVE ELEMENT(06)"},
243 /* 17 MMMOMMMM O RELEASE(06) */
244 {0x17, ALL & ~(M|C|A), "RELEASE(06)"},
245 /* 17 M RELEASE ELEMENT(06) */
246 {0x17, M, "RELEASE ELEMENT(06)"},
248 /* 18 OOOOOOOO COPY */
249 {0x18, ALL & ~(M|C|A|E), "COPY"},
251 /* 19 VMVVVV ERASE */
254 /* 1A OMO OOOOOOOO MODE SENSE(06) */
255 {0x1A, ALL & ~(P), "MODE SENSE(06)"},
257 /* 1B O OM O STOP START UNIT */
258 {0x1B, D|W|R|O, "STOP START UNIT"},
259 /* 1B O LOAD UNLOAD */
260 {0x1B, T, "LOAD UNLOAD"},
263 /* 1B O STOP PRINT */
264 {0x1B, L, "STOP PRINT"},
266 /* 1C OOOOOOOOOO M RECEIVE DIAGNOSTIC RESULTS */
267 {0x1C, ALL & ~(A), "RECEIVE DIAGNOSTIC RESULTS"},
269 /* 1D MMMMMMMMMMMM SEND DIAGNOSTIC */
270 {0x1D, ALL, "SEND DIAGNOSTIC"},
272 /* 1E OO OM OO PREVENT ALLOW MEDIUM REMOVAL */
273 {0x1E, D|T|W|R|O|M, "PREVENT ALLOW MEDIUM REMOVAL"},
281 /* 24 V VVM SET WINDOW */
282 {0x24, S, "SET WINDOW"},
284 /* 25 M M M READ CAPACITY */
285 {0x25, D|W|O, "READ CAPACITY"},
286 /* 25 M READ CD RECORDED CAPACITY */
287 {0x25, R, "READ CD RECORDED CAPACITY"},
288 /* 25 O GET WINDOW */
289 {0x25, S, "GET WINDOW"},
294 /* 28 M MMMM READ(10) */
295 {0x28, D|W|R|S|O, "READ(10)"},
296 /* 28 O GET MESSAGE(10) */
297 {0x28, C, "GET MESSAGE(10)"},
299 /* 29 V VV O READ GENERATION */
300 {0x29, O, "READ GENERATION"},
302 /* 2A M MM M WRITE(10) */
303 {0x2A, D|W|R|O, "WRITE(10)"},
305 {0x2A, S, "SEND(10)"},
306 /* 2A O SEND MESSAGE(10) */
307 {0x2A, C, "SEND MESSAGE(10)"},
309 /* 2B O OM O SEEK(10) */
310 {0x2B, D|W|R|O, "SEEK(10)"},
313 /* 2B O POSITION TO ELEMENT */
314 {0x2B, M, "POSITION TO ELEMENT"},
316 /* 2C V O ERASE(10) */
317 {0x2C, O, "ERASE(10)"},
319 /* 2D V O O READ UPDATED BLOCK */
320 {0x2D, W|O, "READ UPDATED BLOCK"},
322 /* 2E O O O WRITE AND VERIFY(10) */
323 {0x2E, D|W|O, "WRITE AND VERIFY(10)"},
325 /* 2F O OO O VERIFY(10) */
326 {0x2F, D|W|R|O, "VERIFY(10)"},
328 /* 30 Z ZO Z SEARCH DATA HIGH(10) */
329 {0x30, D|W|R|O, "SEARCH DATA HIGH(10)"},
331 /* 31 Z ZO Z SEARCH DATA EQUAL(10) */
332 {0x31, D|W|R|O, "SEARCH DATA EQUAL(10)"},
333 /* 31 O OBJECT POSITION */
334 {0x31, S, "OBJECT POSITION"},
336 /* 32 Z ZO Z SEARCH DATA LOW(10) */
337 {0x32, D|W|R|O, "SEARCH DATA LOW(10"},
339 /* 33 O OO O SET LIMITS(10) */
340 {0x33, D|W|R|O, "SET LIMITS(10)"},
342 /* 34 O OO O PRE-FETCH */
343 {0x34, D|W|R|O, "PRE-FETCH"},
344 /* 34 O READ POSITION */
345 {0x34, T, "READ POSITION"},
346 /* 34 O GET DATA BUFFER STATUS */
347 {0x34, S, "GET DATA BUFFER STATUS"},
349 /* 35 O OM O SYNCHRONIZE CACHE */
350 {0x35, D|W|R|O, "SYNCHRONIZE CACHE"},
352 /* 36 O OO O LOCK UNLOCK CACHE */
353 {0x36, D|W|R|O, "LOCK UNLOCK CACHE"},
355 /* 37 O O READ DEFECT DATA(10) */
356 {0x37, D|O, "READ DEFECT DATA(10)"},
358 /* 38 O O MEDIUM SCAN */
359 {0x38, W|O, "MEDIUM SCAN"},
361 /* 39 OOOOOOOO COMPARE */
362 {0x39, ALL & ~(M|C|A|E), "COMPARE"},
364 /* 3A OOOOOOOO COPY AND VERIFY */
365 {0x3A, ALL & ~(M|C|A|E), "COPY AND VERIFY"},
367 /* 3B OOOOOOOOOO O WRITE BUFFER */
368 {0x3B, ALL & ~(A), "WRITE BUFFER"},
370 /* 3C OOOOOOOOOO READ BUFFER */
371 {0x3C, ALL & ~(A|E),"READ BUFFER"},
373 /* 3D O O UPDATE BLOCK */
374 {0x3D, W|O, "UPDATE BLOCK"},
376 /* 3E O OO O READ LONG */
377 {0x3E, D|W|R|O, "READ LONG"},
379 /* 3F O O O WRITE LONG */
380 {0x3F, D|W|O, "WRITE LONG"},
382 /* 40 OOOOOOOOOO CHANGE DEFINITION */
383 {0x40, ALL & ~(A|E),"CHANGE DEFINITION"},
385 /* 41 O WRITE SAME */
386 {0x41, D, "WRITE SAME"},
388 /* 42 M READ SUB-CHANNEL */
389 {0x42, R, "READ SUB-CHANNEL"},
391 /* 43 M READ TOC/PMA/ATIP {MMC Proposed} */
392 {0x43, R, "READ TOC/PMA/ATIP {MMC Proposed}"},
394 /* 44 M REPORT DENSITY SUPPORT */
395 {0x44, T, "REPORT DENSITY SUPPORT"},
396 /* 44 M READ HEADER */
397 {0x44, R, "READ HEADER"},
399 /* 45 O PLAY AUDIO(10) */
400 {0x45, R, "PLAY AUDIO(10)"},
404 /* 47 O PLAY AUDIO MSF */
405 {0x47, R, "PLAY AUDIO MSF"},
407 /* 48 O PLAY AUDIO TRACK INDEX */
408 {0x48, R, "PLAY AUDIO TRACK INDEX"},
410 /* 49 O PLAY TRACK RELATIVE(10) */
411 {0x49, R, "PLAY TRACK RELATIVE(10)"},
415 /* 4B O PAUSE/RESUME */
416 {0x4B, R, "PAUSE/RESUME"},
418 /* 4C OOOOOOOOOOO LOG SELECT */
419 {0x4C, ALL & ~(E), "LOG SELECT"},
421 /* 4D OOOOOOOOOOO LOG SENSE */
422 {0x4D, ALL & ~(E), "LOG SENSE"},
424 /* 4E O STOP PLAY/SCAN {MMC Proposed} */
425 {0x4E, R, "STOP PLAY/SCAN {MMC Proposed}"},
429 /* 50 O XDWRITE(10) */
430 {0x50, D, "XDWRITE(10)"},
432 /* 51 O XPWRITE(10) */
433 {0x51, D, "XPWRITE(10)"},
434 /* 51 M READ DISC INFORMATION {MMC Proposed} */
435 {0x51, R, "READ DISC INFORMATION {MMC Proposed}"},
437 /* 52 O XDREAD(10) */
438 {0x52, D, "XDREAD(10)"},
439 /* 52 M READ TRACK INFORMATION {MMC Proposed} */
440 {0x52, R, "READ TRACK INFORMATION {MMC Proposed}"},
442 /* 53 M RESERVE TRACK {MMC Proposed} */
443 {0x53, R, "RESERVE TRACK {MMC Proposed}"},
445 /* 54 O SEND OPC INFORMATION {MMC Proposed} */
446 {0x54, R, "SEND OPC INFORMATION {MMC Proposed}"},
448 /* 55 OOO OOOOOOOO MODE SELECT(10) */
449 {0x55, ALL & ~(P), "MODE SELECT(10)"},
451 /* 56 MMMOMMMM O RESERVE(10) */
452 {0x56, ALL & ~(M|C|A), "RESERVE(10)"},
453 /* 56 M RESERVE ELEMENT(10) */
454 {0x56, M, "RESERVE ELEMENT(10)"},
456 /* 57 MMMOMMMM O RELEASE(10) */
457 {0x57, ALL & ~(M|C|A), "RELEASE(10"},
458 /* 57 M RELEASE ELEMENT(10) */
459 {0x57, M, "RELEASE ELEMENT(10)"},
461 /* 58 O REPAIR TRACK {MMC Proposed} */
462 {0x58, R, "REPAIR TRACK {MMC Proposed}"},
464 /* 59 O READ MASTER CUE {MMC Proposed} */
465 {0x59, R, "READ MASTER CUE {MMC Proposed}"},
467 /* 5A OOO OOOOOOOO MODE SENSE(10) */
468 {0x5A, ALL & ~(P), "MODE SENSE(10)"},
470 /* 5B M CLOSE TRACK/SESSION {MMC Proposed} */
471 {0x5B, R, "CLOSE TRACK/SESSION {MMC Proposed}"},
473 /* 5C O READ BUFFER CAPACITY {MMC Proposed} */
474 {0x5C, R, "READ BUFFER CAPACITY {MMC Proposed}"},
476 /* 5D O SEND CUE SHEET {MMC Proposed} */
477 {0x5D, R, "SEND CUE SHEET {MMC Proposed}"},
479 /* 5E OOOOOOOOO O PERSISTENT RESERVE IN */
480 {0x5E, ALL & ~(C|A),"PERSISTENT RESERVE IN"},
482 /* 5F OOOOOOOOO O PERSISTENT RESERVE OUT */
483 {0x5F, ALL & ~(C|A),"PERSISTENT RESERVE OUT"},
485 /* 80 O XDWRITE EXTENDED(16) */
486 {0x80, D, "XDWRITE EXTENDED(16)"},
488 /* 81 O REBUILD(16) */
489 {0x81, D, "REBUILD(16)"},
491 /* 82 O REGENERATE(16) */
492 {0x82, D, "REGENERATE(16)"},
499 /* 88 MM OO O O READ(16) */
500 {0x88, D|T|W|R|O, "READ(16)"},
502 /* 8A OM O O O WRITE(16) */
503 {0x8A, D|T|W|R|O, "WRITE(16)"},
523 /* XXX KDM ALL for these? op-num.txt defines them for none.. */
524 /* 9E SERVICE ACTION IN(16) */
525 {0x9E, ALL, "SERVICE ACTION IN(16)"},
526 /* 9F SERVICE ACTION OUT(16) */
527 {0x9F, ALL, "SERVICE ACTION OUT(16)"},
529 /* A0 OOOOOOOOOOO REPORT LUNS */
530 {0xA0, ALL & ~(E), "REPORT LUNS"},
532 /* A1 O BLANK {MMC Proposed} */
533 {0xA1, R, "BLANK {MMC Proposed}"},
535 /* A2 O WRITE CD MSF {MMC Proposed} */
536 {0xA2, R, "WRITE CD MSF {MMC Proposed}"},
538 /* A3 M MAINTENANCE (IN) */
539 {0xA3, A, "MAINTENANCE (IN)"},
541 /* A4 O MAINTENANCE (OUT) */
542 {0xA4, A, "MAINTENANCE (OUT)"},
544 /* A5 O M MOVE MEDIUM */
545 {0xA5, T|M, "MOVE MEDIUM"},
546 /* A5 O PLAY AUDIO(12) */
547 {0xA5, R, "PLAY AUDIO(12)"},
549 /* A6 O EXCHANGE MEDIUM */
550 {0xA6, M, "EXCHANGE MEDIUM"},
551 /* A6 O LOAD/UNLOAD CD {MMC Proposed} */
552 {0xA6, R, "LOAD/UNLOAD CD {MMC Proposed}"},
554 /* A7 OO OO OO MOVE MEDIUM ATTACHED */
555 {0xA7, D|T|W|R|O|M, "MOVE MEDIUM ATTACHED"},
557 /* A8 O OM O READ(12) */
558 {0xA8,D|W|R|O, "READ(12)"},
559 /* A8 O GET MESSAGE(12) */
560 {0xA8, C, "GET MESSAGE(12)"},
562 /* A9 O PLAY TRACK RELATIVE(12) */
563 {0xA9, R, "PLAY TRACK RELATIVE(12)"},
565 /* AA O O O WRITE(12) */
566 {0xAA,D|W|O, "WRITE(12)"},
567 /* AA O WRITE CD(12) {MMC Proposed} */
568 {0xAA, R, "WRITE CD(12) {MMC Proposed}"},
569 /* AA O SEND MESSAGE(12) */
570 {0xAA, C, "SEND MESSAGE(12)"},
575 {0xAC, O, "ERASE(12)"},
579 /* AE O O WRITE AND VERIFY(12) */
580 {0xAE, W|O, "WRITE AND VERIFY(12)"},
582 /* AF OO O VERIFY(12) */
583 {0xAF, W|R|O, "VERIFY(12)"},
585 /* B0 ZO Z SEARCH DATA HIGH(12) */
586 {0xB0, W|R|O, "SEARCH DATA HIGH(12)"},
588 /* B1 ZO Z SEARCH DATA EQUAL(12) */
589 {0xB1, W|R|O, "SEARCH DATA EQUAL(12)"},
591 /* B2 ZO Z SEARCH DATA LOW(12) */
592 {0xB2, W|R|O, "SEARCH DATA LOW(12)"},
594 /* B3 OO O SET LIMITS(12) */
595 {0xB3, W|R|O, "SET LIMITS(12)"},
597 /* B4 OO OO OO READ ELEMENT STATUS ATTACHED */
598 {0xB4, D|T|W|R|O|M, "READ ELEMENT STATUS ATTACHED"},
600 /* B5 O REQUEST VOLUME ELEMENT ADDRESS */
601 {0xB5, M, "REQUEST VOLUME ELEMENT ADDRESS"},
603 /* B6 O SEND VOLUME TAG */
604 {0xB6, M, "SEND VOLUME TAG"},
606 /* B7 O READ DEFECT DATA(12) */
607 {0xB7, O, "READ DEFECT DATA(12)"},
609 /* B8 O M READ ELEMENT STATUS */
610 {0xB8, T|M, "READ ELEMENT STATUS"},
611 /* B8 O SET CD SPEED {MMC Proposed} */
612 {0xB8, R, "SET CD SPEED {MMC Proposed}"},
614 /* B9 M READ CD MSF {MMC Proposed} */
615 {0xB9, R, "READ CD MSF {MMC Proposed}"},
617 /* BA O SCAN {MMC Proposed} */
618 {0xBA, R, "SCAN {MMC Proposed}"},
619 /* BA M REDUNDANCY GROUP (IN) */
620 {0xBA, A, "REDUNDANCY GROUP (IN)"},
622 /* BB O SET CD-ROM SPEED {proposed} */
623 {0xBB, R, "SET CD-ROM SPEED {proposed}"},
624 /* BB O REDUNDANCY GROUP (OUT) */
625 {0xBB, A, "REDUNDANCY GROUP (OUT)"},
627 /* BC O PLAY CD {MMC Proposed} */
628 {0xBC, R, "PLAY CD {MMC Proposed}"},
629 /* BC M SPARE (IN) */
630 {0xBC, A, "SPARE (IN)"},
632 /* BD M MECHANISM STATUS {MMC Proposed} */
633 {0xBD, R, "MECHANISM STATUS {MMC Proposed}"},
634 /* BD O SPARE (OUT) */
635 {0xBD, A, "SPARE (OUT)"},
637 /* BE O READ CD {MMC Proposed} */
638 {0xBE, R, "READ CD {MMC Proposed}"},
639 /* BE M VOLUME SET (IN) */
640 {0xBE, A, "VOLUME SET (IN)"},
642 /* BF O VOLUME SET (OUT) */
643 {0xBF, A, "VOLUME SET (OUT)"}
647 scsi_op_desc(u_int16_t opcode, struct scsi_inquiry_data *inq_data)
654 struct op_table_entry *table[2];
657 pd_type = SID_TYPE(inq_data);
659 match = cam_quirkmatch((caddr_t)inq_data,
660 (caddr_t)scsi_op_quirk_table,
661 sizeof(scsi_op_quirk_table)/
662 sizeof(*scsi_op_quirk_table),
663 sizeof(*scsi_op_quirk_table),
667 table[0] = ((struct scsi_op_quirk_entry *)match)->op_table;
668 num_ops[0] = ((struct scsi_op_quirk_entry *)match)->num_ops;
669 table[1] = scsi_op_codes;
670 num_ops[1] = sizeof(scsi_op_codes)/sizeof(scsi_op_codes[0]);
674 * If this is true, we have a vendor specific opcode that
675 * wasn't covered in the quirk table.
677 if ((opcode > 0xBF) || ((opcode > 0x5F) && (opcode < 0x80)))
678 return("Vendor Specific Command");
680 table[0] = scsi_op_codes;
681 num_ops[0] = sizeof(scsi_op_codes)/sizeof(scsi_op_codes[0]);
685 /* RBC is 'Simplified' Direct Access Device */
686 if (pd_type == T_RBC)
689 opmask = 1 << pd_type;
691 for (j = 0; j < num_tables; j++) {
692 for (i = 0;i < num_ops[j] && table[j][i].opcode <= opcode; i++){
693 if ((table[j][i].opcode == opcode)
694 && ((table[j][i].opmask & opmask) != 0))
695 return(table[j][i].desc);
700 * If we can't find a match for the command in the table, we just
701 * assume it's a vendor specifc command.
703 return("Vendor Specific Command");
707 #else /* SCSI_NO_OP_STRINGS */
710 scsi_op_desc(u_int16_t opcode, struct scsi_inquiry_data *inq_data)
718 #include <sys/param.h>
721 #if !defined(SCSI_NO_SENSE_STRINGS)
722 #define SST(asc, ascq, action, desc) \
723 asc, ascq, action, desc
725 #define SST(asc, ascq, action, desc) \
729 static const char quantum[] = "QUANTUM";
732 * WARNING: You must update the num_ascs field below for this quirk table
733 * entry if you add more entries.
735 static struct asc_table_entry quantum_fireball_entries[] = {
736 {SST(0x04, 0x0b, SS_START|SSQ_DECREMENT_COUNT|ENXIO,
737 "Logical unit not ready, initializing cmd. required")}
740 static struct scsi_sense_quirk_entry asc_quirk_table[] = {
743 * The Quantum Fireball ST and SE like to return 0x04 0x0b when
744 * they really should return 0x04 0x02. 0x04,0x0b isn't
745 * defined in any SCSI spec, and it isn't mentioned in the
746 * hardware manual for these drives.
748 {T_DIRECT, SIP_MEDIA_FIXED, "QUANTUM", "FIREBALL S*", "*"},
749 1, /* number of vendor-specific sense codes for this entry */
750 quantum_fireball_entries
754 static struct asc_table_entry asc_text[] = {
756 * From File: ASC-NUM.TXT
757 * SCSI ASC/ASCQ Assignments
758 * Numeric Sorted Listing
761 * D - DIRECT ACCESS DEVICE (SBC) device column key
762 * .T - SEQUENTIAL ACCESS DEVICE (SSC) -------------------
763 * . L - PRINTER DEVICE (SSC) blank = reserved
764 * . P - PROCESSOR DEVICE (SPC) not blank = allowed
765 * . .W - WRITE ONCE READ MULTIPLE DEVICE (SBC)
766 * . . R - CD DEVICE (MMC)
767 * . . S - SCANNER DEVICE (SGC)
768 * . . .O - OPTICAL MEMORY DEVICE (SBC)
769 * . . . M - MEDIA CHANGER DEVICE (SMC)
770 * . . . C - COMMUNICATION DEVICE (SSC)
771 * . . . .A - STORAGE ARRAY DEVICE (SCC)
772 * . . . . E - ENCLOSURE SERVICES DEVICE (SES)
773 * DTLPWRSOMCAE ASC ASCQ Action Description
774 * ------------ ---- ---- ------ -----------------------------------*/
775 /* DTLPWRSOMCAE */{SST(0x00, 0x00, SS_NEPDEF,
776 "No additional sense information") },
777 /* T S */{SST(0x00, 0x01, SS_DEF,
778 "Filemark detected") },
779 /* T S */{SST(0x00, 0x02, SS_DEF,
780 "End-of-partition/medium detected") },
781 /* T */{SST(0x00, 0x03, SS_DEF,
782 "Setmark detected") },
783 /* T S */{SST(0x00, 0x04, SS_DEF,
784 "Beginning-of-partition/medium detected") },
785 /* T S */{SST(0x00, 0x05, SS_DEF,
786 "End-of-data detected") },
787 /* DTLPWRSOMCAE */{SST(0x00, 0x06, SS_DEF,
788 "I/O process terminated") },
789 /* R */{SST(0x00, 0x11, SS_NEDEF|EBUSY,
790 "Audio play operation in progress") },
791 /* R */{SST(0x00, 0x12, SS_NEDEF,
792 "Audio play operation paused") },
793 /* R */{SST(0x00, 0x13, SS_NEDEF,
794 "Audio play operation successfully completed") },
795 /* R */{SST(0x00, 0x14, SS_DEF,
796 "Audio play operation stopped due to error") },
797 /* R */{SST(0x00, 0x15, SS_DEF,
798 "No current audio status to return") },
799 /* DTLPWRSOMCAE */{SST(0x00, 0x16, SS_NEDEF|EBUSY,
800 "Operation in progress") },
801 /* DTL WRSOM AE */{SST(0x00, 0x17, SS_DEF,
802 "Cleaning requested") },
803 /* D W O */{SST(0x01, 0x00, SS_DEF,
804 "No index/sector signal") },
805 /* D WR OM */{SST(0x02, 0x00, SS_DEF,
806 "No seek complete") },
807 /* DTL W SO */{SST(0x03, 0x00, SS_DEF,
808 "Peripheral device write fault") },
809 /* T */{SST(0x03, 0x01, SS_DEF,
810 "No write current") },
811 /* T */{SST(0x03, 0x02, SS_DEF,
812 "Excessive write errors") },
813 /* DTLPWRSOMCAE */{SST(0x04, 0x00, SS_TUR|SSQ_MANY|SSQ_DECREMENT_COUNT|EIO,
814 "Logical unit not ready, cause not reportable") },
815 /* DTLPWRSOMCAE */{SST(0x04, 0x01, SS_TUR|SSQ_MANY|SSQ_DECREMENT_COUNT|EBUSY,
816 "Logical unit is in process of becoming ready") },
817 /* DTLPWRSOMCAE */{SST(0x04, 0x02, SS_START|SSQ_DECREMENT_COUNT|ENXIO,
818 "Logical unit not ready, initializing cmd. required") },
819 /* DTLPWRSOMCAE */{SST(0x04, 0x03, SS_NEDEF|ENXIO,
820 "Logical unit not ready, manual intervention required")},
821 /* DTL O */{SST(0x04, 0x04, SS_NEDEF|EBUSY,
822 "Logical unit not ready, format in progress") },
823 /* DT W OMCA */{SST(0x04, 0x05, SS_NEDEF|EBUSY,
824 "Logical unit not ready, rebuild in progress") },
825 /* DT W OMCA */{SST(0x04, 0x06, SS_NEDEF|EBUSY,
826 "Logical unit not ready, recalculation in progress") },
827 /* DTLPWRSOMCAE */{SST(0x04, 0x07, SS_NEDEF|EBUSY,
828 "Logical unit not ready, operation in progress") },
829 /* R */{SST(0x04, 0x08, SS_NEDEF|EBUSY,
830 "Logical unit not ready, long write in progress") },
831 /* DTL WRSOMCAE */{SST(0x05, 0x00, SS_DEF,
832 "Logical unit does not respond to selection") },
833 /* D WR OM */{SST(0x06, 0x00, SS_DEF,
834 "No reference position found") },
835 /* DTL WRSOM */{SST(0x07, 0x00, SS_DEF,
836 "Multiple peripheral devices selected") },
837 /* DTL WRSOMCAE */{SST(0x08, 0x00, SS_DEF,
838 "Logical unit communication failure") },
839 /* DTL WRSOMCAE */{SST(0x08, 0x01, SS_DEF,
840 "Logical unit communication time-out") },
841 /* DTL WRSOMCAE */{SST(0x08, 0x02, SS_DEF,
842 "Logical unit communication parity error") },
843 /* DT R OM */{SST(0x08, 0x03, SS_DEF,
844 "Logical unit communication crc error (ultra-dma/32)")},
845 /* DT WR O */{SST(0x09, 0x00, SS_DEF,
846 "Track following error") },
847 /* WR O */{SST(0x09, 0x01, SS_DEF,
848 "Tracking servo failure") },
849 /* WR O */{SST(0x09, 0x02, SS_DEF,
850 "Focus servo failure") },
851 /* WR O */{SST(0x09, 0x03, SS_DEF,
852 "Spindle servo failure") },
853 /* DT WR O */{SST(0x09, 0x04, SS_DEF,
854 "Head select fault") },
855 /* DTLPWRSOMCAE */{SST(0x0A, 0x00, SS_NEDEF|ENOSPC,
856 "Error log overflow") },
857 /* DTLPWRSOMCAE */{SST(0x0B, 0x00, SS_DEF,
859 /* DTLPWRSOMCAE */{SST(0x0B, 0x01, SS_DEF,
860 "Specified temperature exceeded") },
861 /* DTLPWRSOMCAE */{SST(0x0B, 0x02, SS_DEF,
862 "Enclosure degraded") },
863 /* T RS */{SST(0x0C, 0x00, SS_DEF,
865 /* D W O */{SST(0x0C, 0x01, SS_NEDEF,
866 "Write error - recovered with auto reallocation") },
867 /* D W O */{SST(0x0C, 0x02, SS_DEF,
868 "Write error - auto reallocation failed") },
869 /* D W O */{SST(0x0C, 0x03, SS_DEF,
870 "Write error - recommend reassignment") },
871 /* DT W O */{SST(0x0C, 0x04, SS_NEPDEF,
872 "Compression check miscompare error") },
873 /* DT W O */{SST(0x0C, 0x05, SS_DEF,
874 "Data expansion occurred during compression") },
875 /* DT W O */{SST(0x0C, 0x06, SS_DEF,
876 "Block not compressible") },
877 /* R */{SST(0x0C, 0x07, SS_DEF,
878 "Write error - recovery needed") },
879 /* R */{SST(0x0C, 0x08, SS_DEF,
880 "Write error - recovery failed") },
881 /* R */{SST(0x0C, 0x09, SS_DEF,
882 "Write error - loss of streaming") },
883 /* R */{SST(0x0C, 0x0A, SS_DEF,
884 "Write error - padding blocks added") },
885 /* D W O */{SST(0x10, 0x00, SS_DEF,
886 "ID CRC or ECC error") },
887 /* DT WRSO */{SST(0x11, 0x00, SS_DEF,
888 "Unrecovered read error") },
889 /* DT W SO */{SST(0x11, 0x01, SS_DEF,
890 "Read retries exhausted") },
891 /* DT W SO */{SST(0x11, 0x02, SS_DEF,
892 "Error too long to correct") },
893 /* DT W SO */{SST(0x11, 0x03, SS_DEF,
894 "Multiple read errors") },
895 /* D W O */{SST(0x11, 0x04, SS_DEF,
896 "Unrecovered read error - auto reallocate failed") },
897 /* WR O */{SST(0x11, 0x05, SS_DEF,
898 "L-EC uncorrectable error") },
899 /* WR O */{SST(0x11, 0x06, SS_DEF,
900 "CIRC unrecovered error") },
901 /* W O */{SST(0x11, 0x07, SS_DEF,
902 "Data re-synchronization error") },
903 /* T */{SST(0x11, 0x08, SS_DEF,
904 "Incomplete block read") },
905 /* T */{SST(0x11, 0x09, SS_DEF,
907 /* DT O */{SST(0x11, 0x0A, SS_DEF,
908 "Miscorrected error") },
909 /* D W O */{SST(0x11, 0x0B, SS_DEF,
910 "Unrecovered read error - recommend reassignment") },
911 /* D W O */{SST(0x11, 0x0C, SS_DEF,
912 "Unrecovered read error - recommend rewrite the data")},
913 /* DT WR O */{SST(0x11, 0x0D, SS_DEF,
914 "De-compression CRC error") },
915 /* DT WR O */{SST(0x11, 0x0E, SS_DEF,
916 "Cannot decompress using declared algorithm") },
917 /* R */{SST(0x11, 0x0F, SS_DEF,
918 "Error reading UPC/EAN number") },
919 /* R */{SST(0x11, 0x10, SS_DEF,
920 "Error reading ISRC number") },
921 /* R */{SST(0x11, 0x11, SS_DEF,
922 "Read error - loss of streaming") },
923 /* D W O */{SST(0x12, 0x00, SS_DEF,
924 "Address mark not found for id field") },
925 /* D W O */{SST(0x13, 0x00, SS_DEF,
926 "Address mark not found for data field") },
927 /* DTL WRSO */{SST(0x14, 0x00, SS_DEF,
928 "Recorded entity not found") },
929 /* DT WR O */{SST(0x14, 0x01, SS_DEF,
930 "Record not found") },
931 /* T */{SST(0x14, 0x02, SS_DEF,
932 "Filemark or setmark not found") },
933 /* T */{SST(0x14, 0x03, SS_DEF,
934 "End-of-data not found") },
935 /* T */{SST(0x14, 0x04, SS_DEF,
936 "Block sequence error") },
937 /* DT W O */{SST(0x14, 0x05, SS_DEF,
938 "Record not found - recommend reassignment") },
939 /* DT W O */{SST(0x14, 0x06, SS_DEF,
940 "Record not found - data auto-reallocated") },
941 /* DTL WRSOM */{SST(0x15, 0x00, SS_DEF,
942 "Random positioning error") },
943 /* DTL WRSOM */{SST(0x15, 0x01, SS_DEF,
944 "Mechanical positioning error") },
945 /* DT WR O */{SST(0x15, 0x02, SS_DEF,
946 "Positioning error detected by read of medium") },
947 /* D W O */{SST(0x16, 0x00, SS_DEF,
948 "Data synchronization mark error") },
949 /* D W O */{SST(0x16, 0x01, SS_DEF,
950 "Data sync error - data rewritten") },
951 /* D W O */{SST(0x16, 0x02, SS_DEF,
952 "Data sync error - recommend rewrite") },
953 /* D W O */{SST(0x16, 0x03, SS_NEDEF,
954 "Data sync error - data auto-reallocated") },
955 /* D W O */{SST(0x16, 0x04, SS_DEF,
956 "Data sync error - recommend reassignment") },
957 /* DT WRSO */{SST(0x17, 0x00, SS_NEDEF,
958 "Recovered data with no error correction applied") },
959 /* DT WRSO */{SST(0x17, 0x01, SS_NEDEF,
960 "Recovered data with retries") },
961 /* DT WR O */{SST(0x17, 0x02, SS_NEDEF,
962 "Recovered data with positive head offset") },
963 /* DT WR O */{SST(0x17, 0x03, SS_NEDEF,
964 "Recovered data with negative head offset") },
965 /* WR O */{SST(0x17, 0x04, SS_NEDEF,
966 "Recovered data with retries and/or CIRC applied") },
967 /* D WR O */{SST(0x17, 0x05, SS_NEDEF,
968 "Recovered data using previous sector id") },
969 /* D W O */{SST(0x17, 0x06, SS_NEDEF,
970 "Recovered data without ECC - data auto-reallocated") },
971 /* D W O */{SST(0x17, 0x07, SS_NEDEF,
972 "Recovered data without ECC - recommend reassignment")},
973 /* D W O */{SST(0x17, 0x08, SS_NEDEF,
974 "Recovered data without ECC - recommend rewrite") },
975 /* D W O */{SST(0x17, 0x09, SS_NEDEF,
976 "Recovered data without ECC - data rewritten") },
977 /* D W O */{SST(0x18, 0x00, SS_NEDEF,
978 "Recovered data with error correction applied") },
979 /* D WR O */{SST(0x18, 0x01, SS_NEDEF,
980 "Recovered data with error corr. & retries applied") },
981 /* D WR O */{SST(0x18, 0x02, SS_NEDEF,
982 "Recovered data - data auto-reallocated") },
983 /* R */{SST(0x18, 0x03, SS_NEDEF,
984 "Recovered data with CIRC") },
985 /* R */{SST(0x18, 0x04, SS_NEDEF,
986 "Recovered data with L-EC") },
987 /* D WR O */{SST(0x18, 0x05, SS_NEDEF,
988 "Recovered data - recommend reassignment") },
989 /* D WR O */{SST(0x18, 0x06, SS_NEDEF,
990 "Recovered data - recommend rewrite") },
991 /* D W O */{SST(0x18, 0x07, SS_NEDEF,
992 "Recovered data with ECC - data rewritten") },
993 /* D O */{SST(0x19, 0x00, SS_DEF,
994 "Defect list error") },
995 /* D O */{SST(0x19, 0x01, SS_DEF,
996 "Defect list not available") },
997 /* D O */{SST(0x19, 0x02, SS_DEF,
998 "Defect list error in primary list") },
999 /* D O */{SST(0x19, 0x03, SS_DEF,
1000 "Defect list error in grown list") },
1001 /* DTLPWRSOMCAE */{SST(0x1A, 0x00, SS_DEF,
1002 "Parameter list length error") },
1003 /* DTLPWRSOMCAE */{SST(0x1B, 0x00, SS_DEF,
1004 "Synchronous data transfer error") },
1005 /* D O */{SST(0x1C, 0x00, SS_DEF,
1006 "Defect list not found") },
1007 /* D O */{SST(0x1C, 0x01, SS_DEF,
1008 "Primary defect list not found") },
1009 /* D O */{SST(0x1C, 0x02, SS_DEF,
1010 "Grown defect list not found") },
1011 /* D W O */{SST(0x1D, 0x00, SS_NEPDEF,
1012 "Miscompare during verify operation" )},
1013 /* D W O */{SST(0x1E, 0x00, SS_NEDEF,
1014 "Recovered id with ecc correction") },
1015 /* D O */{SST(0x1F, 0x00, SS_DEF,
1016 "Partial defect list transfer") },
1017 /* DTLPWRSOMCAE */{SST(0x20, 0x00, SS_DEF,
1018 "Invalid command operation code") },
1019 /* DT WR OM */{SST(0x21, 0x00, SS_DEF,
1020 "Logical block address out of range" )},
1021 /* DT WR OM */{SST(0x21, 0x01, SS_DEF,
1022 "Invalid element address") },
1023 /* D */{SST(0x22, 0x00, SS_DEF,
1024 "Illegal function") }, /* Deprecated. Use 20 00, 24 00, or 26 00 instead */
1025 /* DTLPWRSOMCAE */{SST(0x24, 0x00, SS_NEDEF|EINVAL,
1026 "Invalid field in CDB") },
1027 /* DTLPWRSOMCAE */{SST(0x25, 0x00, SS_NEDEF|ENXIO,
1028 "Logical unit not supported") },
1029 /* DTLPWRSOMCAE */{SST(0x26, 0x00, SS_NEDEF|EINVAL,
1030 "Invalid field in parameter list") },
1031 /* DTLPWRSOMCAE */{SST(0x26, 0x01, SS_NEDEF|EINVAL,
1032 "Parameter not supported") },
1033 /* DTLPWRSOMCAE */{SST(0x26, 0x02, SS_NEDEF|EINVAL,
1034 "Parameter value invalid") },
1035 /* DTLPWRSOMCAE */{SST(0x26, 0x03, SS_DEF,
1036 "Threshold parameters not supported") },
1037 /* DTLPWRSOMCAE */{SST(0x26, 0x04, SS_DEF,
1038 "Invalid release of active persistent reservation") },
1039 /* DT W O */{SST(0x27, 0x00, SS_NEDEF|EACCES,
1040 "Write protected") },
1041 /* DT W O */{SST(0x27, 0x01, SS_NEDEF|EACCES,
1042 "Hardware write protected") },
1043 /* DT W O */{SST(0x27, 0x02, SS_NEDEF|EACCES,
1044 "Logical unit software write protected") },
1045 /* T */{SST(0x27, 0x03, SS_NEDEF|EACCES,
1046 "Associated write protect") },
1047 /* T */{SST(0x27, 0x04, SS_NEDEF|EACCES,
1048 "Persistent write protect") },
1049 /* T */{SST(0x27, 0x05, SS_NEDEF|EACCES,
1050 "Permanent write protect") },
1051 /* DTLPWRSOMCAE */{SST(0x28, 0x00, SS_NEDEF|ENXIO,
1052 "Not ready to ready change, medium may have changed") },
1053 /* DT WR OM */{SST(0x28, 0x01, SS_DEF,
1054 "Import or export element accessed") },
1055 /* DTLPWRSOMCAE */{SST(0x29, 0x00, SS_NEDEF|ENXIO,
1056 "Power on, reset, or bus device reset occurred") },
1057 /* DTLPWRSOMCAE */{SST(0x29, 0x01, SS_DEF,
1058 "Power on occurred") },
1059 /* DTLPWRSOMCAE */{SST(0x29, 0x02, SS_DEF,
1060 "Scsi bus reset occurred") },
1061 /* DTLPWRSOMCAE */{SST(0x29, 0x03, SS_DEF,
1062 "Bus device reset function occurred") },
1063 /* DTLPWRSOMCAE */{SST(0x29, 0x04, SS_DEF,
1064 "Device internal reset") },
1065 /* DTLPWRSOMCAE */{SST(0x29, 0x05, SS_DEF,
1066 "Transceiver mode changed to single-ended") },
1067 /* DTLPWRSOMCAE */{SST(0x29, 0x06, SS_DEF,
1068 "Transceiver mode changed to LVD") },
1069 /* DTL WRSOMCAE */{SST(0x2A, 0x00, SS_DEF,
1070 "Parameters changed") },
1071 /* DTL WRSOMCAE */{SST(0x2A, 0x01, SS_DEF,
1072 "Mode parameters changed") },
1073 /* DTL WRSOMCAE */{SST(0x2A, 0x02, SS_DEF,
1074 "Log parameters changed") },
1075 /* DTLPWRSOMCAE */{SST(0x2A, 0x03, SS_DEF,
1076 "Reservations preempted") },
1077 /* DTLPWRSO C */{SST(0x2B, 0x00, SS_DEF,
1078 "Copy cannot execute since host cannot disconnect") },
1079 /* DTLPWRSOMCAE */{SST(0x2C, 0x00, SS_DEF,
1080 "Command sequence error") },
1081 /* S */{SST(0x2C, 0x01, SS_DEF,
1082 "Too many windows specified") },
1083 /* S */{SST(0x2C, 0x02, SS_DEF,
1084 "Invalid combination of windows specified") },
1085 /* R */{SST(0x2C, 0x03, SS_DEF,
1086 "Current program area is not empty") },
1087 /* R */{SST(0x2C, 0x04, SS_DEF,
1088 "Current program area is empty") },
1089 /* T */{SST(0x2D, 0x00, SS_DEF,
1090 "Overwrite error on update in place") },
1091 /* DTLPWRSOMCAE */{SST(0x2F, 0x00, SS_DEF,
1092 "Commands cleared by another initiator") },
1093 /* DT WR OM */{SST(0x30, 0x00, SS_DEF,
1094 "Incompatible medium installed") },
1095 /* DT WR O */{SST(0x30, 0x01, SS_DEF,
1096 "Cannot read medium - unknown format") },
1097 /* DT WR O */{SST(0x30, 0x02, SS_DEF,
1098 "Cannot read medium - incompatible format") },
1099 /* DT */{SST(0x30, 0x03, SS_DEF,
1100 "Cleaning cartridge installed") },
1101 /* DT WR O */{SST(0x30, 0x04, SS_DEF,
1102 "Cannot write medium - unknown format") },
1103 /* DT WR O */{SST(0x30, 0x05, SS_DEF,
1104 "Cannot write medium - incompatible format") },
1105 /* DT W O */{SST(0x30, 0x06, SS_DEF,
1106 "Cannot format medium - incompatible medium") },
1107 /* DTL WRSOM AE */{SST(0x30, 0x07, SS_DEF,
1108 "Cleaning failure") },
1109 /* R */{SST(0x30, 0x08, SS_DEF,
1110 "Cannot write - application code mismatch") },
1111 /* R */{SST(0x30, 0x09, SS_DEF,
1112 "Current session not fixated for append") },
1113 /* DT WR O */{SST(0x31, 0x00, SS_DEF,
1114 "Medium format corrupted") },
1115 /* D L R O */{SST(0x31, 0x01, SS_DEF,
1116 "Format command failed") },
1117 /* D W O */{SST(0x32, 0x00, SS_DEF,
1118 "No defect spare location available") },
1119 /* D W O */{SST(0x32, 0x01, SS_DEF,
1120 "Defect list update failure") },
1121 /* T */{SST(0x33, 0x00, SS_DEF,
1122 "Tape length error") },
1123 /* DTLPWRSOMCAE */{SST(0x34, 0x00, SS_DEF,
1124 "Enclosure failure") },
1125 /* DTLPWRSOMCAE */{SST(0x35, 0x00, SS_DEF,
1126 "Enclosure services failure") },
1127 /* DTLPWRSOMCAE */{SST(0x35, 0x01, SS_DEF,
1128 "Unsupported enclosure function") },
1129 /* DTLPWRSOMCAE */{SST(0x35, 0x02, SS_DEF,
1130 "Enclosure services unavailable") },
1131 /* DTLPWRSOMCAE */{SST(0x35, 0x03, SS_DEF,
1132 "Enclosure services transfer failure") },
1133 /* DTLPWRSOMCAE */{SST(0x35, 0x04, SS_DEF,
1134 "Enclosure services transfer refused") },
1135 /* L */{SST(0x36, 0x00, SS_DEF,
1136 "Ribbon, ink, or toner failure") },
1137 /* DTL WRSOMCAE */{SST(0x37, 0x00, SS_DEF,
1138 "Rounded parameter") },
1139 /* DTL WRSOMCAE */{SST(0x39, 0x00, SS_DEF,
1140 "Saving parameters not supported") },
1141 /* DTL WRSOM */{SST(0x3A, 0x00, SS_NEDEF|ENXIO,
1142 "Medium not present") },
1143 /* DT WR OM */{SST(0x3A, 0x01, SS_NEDEF|ENXIO,
1144 "Medium not present - tray closed") },
1145 /* DT WR OM */{SST(0x3A, 0x02, SS_NEDEF|ENXIO,
1146 "Medium not present - tray open") },
1147 /* TL */{SST(0x3B, 0x00, SS_DEF,
1148 "Sequential positioning error") },
1149 /* T */{SST(0x3B, 0x01, SS_DEF,
1150 "Tape position error at beginning-of-medium") },
1151 /* T */{SST(0x3B, 0x02, SS_DEF,
1152 "Tape position error at end-of-medium") },
1153 /* L */{SST(0x3B, 0x03, SS_DEF,
1154 "Tape or electronic vertical forms unit not ready") },
1155 /* L */{SST(0x3B, 0x04, SS_DEF,
1157 /* L */{SST(0x3B, 0x05, SS_DEF,
1159 /* L */{SST(0x3B, 0x06, SS_DEF,
1160 "Failed to sense top-of-form") },
1161 /* L */{SST(0x3B, 0x07, SS_DEF,
1162 "Failed to sense bottom-of-form") },
1163 /* T */{SST(0x3B, 0x08, SS_DEF,
1164 "Reposition error") },
1165 /* S */{SST(0x3B, 0x09, SS_DEF,
1166 "Read past end of medium") },
1167 /* S */{SST(0x3B, 0x0A, SS_DEF,
1168 "Read past beginning of medium") },
1169 /* S */{SST(0x3B, 0x0B, SS_DEF,
1170 "Position past end of medium") },
1171 /* T S */{SST(0x3B, 0x0C, SS_DEF,
1172 "Position past beginning of medium") },
1173 /* DT WR OM */{SST(0x3B, 0x0D, SS_NEDEF|ENOSPC,
1174 "Medium destination element full") },
1175 /* DT WR OM */{SST(0x3B, 0x0E, SS_DEF,
1176 "Medium source element empty") },
1177 /* R */{SST(0x3B, 0x0F, SS_DEF,
1178 "End of medium reached") },
1179 /* DT WR OM */{SST(0x3B, 0x11, SS_DEF,
1180 "Medium magazine not accessible") },
1181 /* DT WR OM */{SST(0x3B, 0x12, SS_DEF,
1182 "Medium magazine removed") },
1183 /* DT WR OM */{SST(0x3B, 0x13, SS_DEF,
1184 "Medium magazine inserted") },
1185 /* DT WR OM */{SST(0x3B, 0x14, SS_DEF,
1186 "Medium magazine locked") },
1187 /* DT WR OM */{SST(0x3B, 0x15, SS_DEF,
1188 "Medium magazine unlocked") },
1189 /* DTLPWRSOMCAE */{SST(0x3D, 0x00, SS_DEF,
1190 "Invalid bits in identify message") },
1191 /* DTLPWRSOMCAE */{SST(0x3E, 0x00, SS_DEF,
1192 "Logical unit has not self-configured yet") },
1193 /* DTLPWRSOMCAE */{SST(0x3E, 0x01, SS_DEF,
1194 "Logical unit failure") },
1195 /* DTLPWRSOMCAE */{SST(0x3E, 0x02, SS_DEF,
1196 "Timeout on logical unit") },
1197 /* DTLPWRSOMCAE */{SST(0x3F, 0x00, SS_DEF,
1198 "Target operating conditions have changed") },
1199 /* DTLPWRSOMCAE */{SST(0x3F, 0x01, SS_DEF,
1200 "Microcode has been changed") },
1201 /* DTLPWRSOMC */{SST(0x3F, 0x02, SS_DEF,
1202 "Changed operating definition") },
1203 /* DTLPWRSOMCAE */{SST(0x3F, 0x03, SS_DEF,
1204 "Inquiry data has changed") },
1205 /* DT WR OMCAE */{SST(0x3F, 0x04, SS_DEF,
1206 "Component device attached") },
1207 /* DT WR OMCAE */{SST(0x3F, 0x05, SS_DEF,
1208 "Device identifier changed") },
1209 /* DT WR OMCAE */{SST(0x3F, 0x06, SS_DEF,
1210 "Redundancy group created or modified") },
1211 /* DT WR OMCAE */{SST(0x3F, 0x07, SS_DEF,
1212 "Redundancy group deleted") },
1213 /* DT WR OMCAE */{SST(0x3F, 0x08, SS_DEF,
1214 "Spare created or modified") },
1215 /* DT WR OMCAE */{SST(0x3F, 0x09, SS_DEF,
1217 /* DT WR OMCAE */{SST(0x3F, 0x0A, SS_DEF,
1218 "Volume set created or modified") },
1219 /* DT WR OMCAE */{SST(0x3F, 0x0B, SS_DEF,
1220 "Volume set deleted") },
1221 /* DT WR OMCAE */{SST(0x3F, 0x0C, SS_DEF,
1222 "Volume set deassigned") },
1223 /* DT WR OMCAE */{SST(0x3F, 0x0D, SS_DEF,
1224 "Volume set reassigned") },
1225 /* D */{SST(0x40, 0x00, SS_DEF,
1226 "Ram failure") }, /* deprecated - use 40 NN instead */
1227 /* DTLPWRSOMCAE */{SST(0x40, 0x80, SS_DEF,
1228 "Diagnostic failure: ASCQ = Component ID") },
1229 /* DTLPWRSOMCAE */{SST(0x40, 0xFF, SS_DEF|SSQ_RANGE,
1230 NULL) },/* Range 0x80->0xFF */
1231 /* D */{SST(0x41, 0x00, SS_DEF,
1232 "Data path failure") }, /* deprecated - use 40 NN instead */
1233 /* D */{SST(0x42, 0x00, SS_DEF,
1234 "Power-on or self-test failure") }, /* deprecated - use 40 NN instead */
1235 /* DTLPWRSOMCAE */{SST(0x43, 0x00, SS_DEF,
1237 /* DTLPWRSOMCAE */{SST(0x44, 0x00, SS_DEF,
1238 "Internal target failure") },
1239 /* DTLPWRSOMCAE */{SST(0x45, 0x00, SS_DEF,
1240 "Select or reselect failure") },
1241 /* DTLPWRSOMC */{SST(0x46, 0x00, SS_DEF,
1242 "Unsuccessful soft reset") },
1243 /* DTLPWRSOMCAE */{SST(0x47, 0x00, SS_DEF,
1244 "SCSI parity error") },
1245 /* DTLPWRSOMCAE */{SST(0x48, 0x00, SS_DEF,
1246 "Initiator detected error message received") },
1247 /* DTLPWRSOMCAE */{SST(0x49, 0x00, SS_DEF,
1248 "Invalid message error") },
1249 /* DTLPWRSOMCAE */{SST(0x4A, 0x00, SS_DEF,
1250 "Command phase error") },
1251 /* DTLPWRSOMCAE */{SST(0x4B, 0x00, SS_DEF,
1252 "Data phase error") },
1253 /* DTLPWRSOMCAE */{SST(0x4C, 0x00, SS_DEF,
1254 "Logical unit failed self-configuration") },
1255 /* DTLPWRSOMCAE */{SST(0x4D, 0x00, SS_DEF,
1256 "Tagged overlapped commands: ASCQ = Queue tag ID") },
1257 /* DTLPWRSOMCAE */{SST(0x4D, 0xFF, SS_DEF|SSQ_RANGE,
1258 NULL)}, /* Range 0x00->0xFF */
1259 /* DTLPWRSOMCAE */{SST(0x4E, 0x00, SS_DEF,
1260 "Overlapped commands attempted") },
1261 /* T */{SST(0x50, 0x00, SS_DEF,
1262 "Write append error") },
1263 /* T */{SST(0x50, 0x01, SS_DEF,
1264 "Write append position error") },
1265 /* T */{SST(0x50, 0x02, SS_DEF,
1266 "Position error related to timing") },
1267 /* T O */{SST(0x51, 0x00, SS_DEF,
1269 /* T */{SST(0x52, 0x00, SS_DEF,
1270 "Cartridge fault") },
1271 /* DTL WRSOM */{SST(0x53, 0x00, SS_DEF,
1272 "Media load or eject failed") },
1273 /* T */{SST(0x53, 0x01, SS_DEF,
1274 "Unload tape failure") },
1275 /* DT WR OM */{SST(0x53, 0x02, SS_DEF,
1276 "Medium removal prevented") },
1277 /* P */{SST(0x54, 0x00, SS_DEF,
1278 "Scsi to host system interface failure") },
1279 /* P */{SST(0x55, 0x00, SS_DEF,
1280 "System resource failure") },
1281 /* D O */{SST(0x55, 0x01, SS_NEDEF|ENOSPC,
1282 "System buffer full") },
1283 /* R */{SST(0x57, 0x00, SS_DEF,
1284 "Unable to recover table-of-contents") },
1285 /* O */{SST(0x58, 0x00, SS_DEF,
1286 "Generation does not exist") },
1287 /* O */{SST(0x59, 0x00, SS_DEF,
1288 "Updated block read") },
1289 /* DTLPWRSOM */{SST(0x5A, 0x00, SS_DEF,
1290 "Operator request or state change input") },
1291 /* DT WR OM */{SST(0x5A, 0x01, SS_DEF,
1292 "Operator medium removal request") },
1293 /* DT W O */{SST(0x5A, 0x02, SS_DEF,
1294 "Operator selected write protect") },
1295 /* DT W O */{SST(0x5A, 0x03, SS_DEF,
1296 "Operator selected write permit") },
1297 /* DTLPWRSOM */{SST(0x5B, 0x00, SS_DEF,
1299 /* DTLPWRSOM */{SST(0x5B, 0x01, SS_DEF,
1300 "Threshold condition met") },
1301 /* DTLPWRSOM */{SST(0x5B, 0x02, SS_DEF,
1302 "Log counter at maximum") },
1303 /* DTLPWRSOM */{SST(0x5B, 0x03, SS_DEF,
1304 "Log list codes exhausted") },
1305 /* D O */{SST(0x5C, 0x00, SS_DEF,
1306 "RPL status change") },
1307 /* D O */{SST(0x5C, 0x01, SS_NEDEF,
1308 "Spindles synchronized") },
1309 /* D O */{SST(0x5C, 0x02, SS_DEF,
1310 "Spindles not synchronized") },
1311 /* DTLPWRSOMCAE */{SST(0x5D, 0x00, SS_DEF,
1312 "Failure prediction threshold exceeded") },
1313 /* DTLPWRSOMCAE */{SST(0x5D, 0xFF, SS_DEF,
1314 "Failure prediction threshold exceeded (false)") },
1315 /* DTLPWRSO CA */{SST(0x5E, 0x00, SS_DEF,
1316 "Low power condition on") },
1317 /* DTLPWRSO CA */{SST(0x5E, 0x01, SS_DEF,
1318 "Idle condition activated by timer") },
1319 /* DTLPWRSO CA */{SST(0x5E, 0x02, SS_DEF,
1320 "Standby condition activated by timer") },
1321 /* DTLPWRSO CA */{SST(0x5E, 0x03, SS_DEF,
1322 "Idle condition activated by command") },
1323 /* DTLPWRSO CA */{SST(0x5E, 0x04, SS_DEF,
1324 "Standby condition activated by command") },
1325 /* S */{SST(0x60, 0x00, SS_DEF,
1327 /* S */{SST(0x61, 0x00, SS_DEF,
1328 "Video acquisition error") },
1329 /* S */{SST(0x61, 0x01, SS_DEF,
1330 "Unable to acquire video") },
1331 /* S */{SST(0x61, 0x02, SS_DEF,
1333 /* S */{SST(0x62, 0x00, SS_DEF,
1334 "Scan head positioning error") },
1335 /* R */{SST(0x63, 0x00, SS_DEF,
1336 "End of user area encountered on this track") },
1337 /* R */{SST(0x63, 0x01, SS_NEDEF|ENOSPC,
1338 "Packet does not fit in available space") },
1339 /* R */{SST(0x64, 0x00, SS_DEF,
1340 "Illegal mode for this track") },
1341 /* R */{SST(0x64, 0x01, SS_DEF,
1342 "Invalid packet size") },
1343 /* DTLPWRSOMCAE */{SST(0x65, 0x00, SS_DEF,
1345 /* S */{SST(0x66, 0x00, SS_DEF,
1346 "Automatic document feeder cover up") },
1347 /* S */{SST(0x66, 0x01, SS_DEF,
1348 "Automatic document feeder lift up") },
1349 /* S */{SST(0x66, 0x02, SS_DEF,
1350 "Document jam in automatic document feeder") },
1351 /* S */{SST(0x66, 0x03, SS_DEF,
1352 "Document miss feed automatic in document feeder") },
1353 /* A */{SST(0x67, 0x00, SS_DEF,
1354 "Configuration failure") },
1355 /* A */{SST(0x67, 0x01, SS_DEF,
1356 "Configuration of incapable logical units failed") },
1357 /* A */{SST(0x67, 0x02, SS_DEF,
1358 "Add logical unit failed") },
1359 /* A */{SST(0x67, 0x03, SS_DEF,
1360 "Modification of logical unit failed") },
1361 /* A */{SST(0x67, 0x04, SS_DEF,
1362 "Exchange of logical unit failed") },
1363 /* A */{SST(0x67, 0x05, SS_DEF,
1364 "Remove of logical unit failed") },
1365 /* A */{SST(0x67, 0x06, SS_DEF,
1366 "Attachment of logical unit failed") },
1367 /* A */{SST(0x67, 0x07, SS_DEF,
1368 "Creation of logical unit failed") },
1369 /* A */{SST(0x68, 0x00, SS_DEF,
1370 "Logical unit not configured") },
1371 /* A */{SST(0x69, 0x00, SS_DEF,
1372 "Data loss on logical unit") },
1373 /* A */{SST(0x69, 0x01, SS_DEF,
1374 "Multiple logical unit failures") },
1375 /* A */{SST(0x69, 0x02, SS_DEF,
1376 "Parity/data mismatch") },
1377 /* A */{SST(0x6A, 0x00, SS_DEF,
1378 "Informational, refer to log") },
1379 /* A */{SST(0x6B, 0x00, SS_DEF,
1380 "State change has occurred") },
1381 /* A */{SST(0x6B, 0x01, SS_DEF,
1382 "Redundancy level got better") },
1383 /* A */{SST(0x6B, 0x02, SS_DEF,
1384 "Redundancy level got worse") },
1385 /* A */{SST(0x6C, 0x00, SS_DEF,
1386 "Rebuild failure occurred") },
1387 /* A */{SST(0x6D, 0x00, SS_DEF,
1388 "Recalculate failure occurred") },
1389 /* A */{SST(0x6E, 0x00, SS_DEF,
1390 "Command to logical unit failed") },
1391 /* T */{SST(0x70, 0x00, SS_DEF,
1392 "Decompression exception short: ASCQ = Algorithm ID") },
1393 /* T */{SST(0x70, 0xFF, SS_DEF|SSQ_RANGE,
1394 NULL) }, /* Range 0x00 -> 0xFF */
1395 /* T */{SST(0x71, 0x00, SS_DEF,
1396 "Decompression exception long: ASCQ = Algorithm ID") },
1397 /* T */{SST(0x71, 0xFF, SS_DEF|SSQ_RANGE,
1398 NULL) }, /* Range 0x00 -> 0xFF */
1399 /* R */{SST(0x72, 0x00, SS_DEF,
1400 "Session fixation error") },
1401 /* R */{SST(0x72, 0x01, SS_DEF,
1402 "Session fixation error writing lead-in") },
1403 /* R */{SST(0x72, 0x02, SS_DEF,
1404 "Session fixation error writing lead-out") },
1405 /* R */{SST(0x72, 0x03, SS_DEF,
1406 "Session fixation error - incomplete track in session") },
1407 /* R */{SST(0x72, 0x04, SS_DEF,
1408 "Empty or partially written reserved track") },
1409 /* R */{SST(0x73, 0x00, SS_DEF,
1410 "CD control error") },
1411 /* R */{SST(0x73, 0x01, SS_DEF,
1412 "Power calibration area almost full") },
1413 /* R */{SST(0x73, 0x02, SS_NEDEF|ENOSPC,
1414 "Power calibration area is full") },
1415 /* R */{SST(0x73, 0x03, SS_DEF,
1416 "Power calibration area error") },
1417 /* R */{SST(0x73, 0x04, SS_DEF,
1418 "Program memory area update failure") },
1419 /* R */{SST(0x73, 0x05, SS_DEF,
1420 "program memory area is full") }
1423 #if !defined(SCSI_NO_SENSE_STRINGS)
1425 scsi_sense_desc(int asc, int ascq, struct scsi_inquiry_data *inq_data)
1429 struct asc_table_entry *table[2];
1433 if (inq_data == NULL)
1436 match = cam_quirkmatch((caddr_t)inq_data,
1437 (caddr_t)asc_quirk_table,
1438 sizeof(asc_quirk_table)/sizeof(*asc_quirk_table),
1439 sizeof(*asc_quirk_table), scsi_inquiry_match);
1441 if (match != NULL) {
1442 table[0] = ((struct scsi_sense_quirk_entry *)match)->asc_info;
1444 ((struct scsi_sense_quirk_entry *)match)->num_ascs;
1445 table[1] = asc_text;
1446 table_size[1] = sizeof(asc_text)/sizeof(asc_text[0]);
1449 table[0] = asc_text;
1450 table_size[0] = sizeof(asc_text)/sizeof(asc_text[0]);
1454 for (j = 0; j < num_tables; j++) {
1455 for (i = 0; i < table_size[j]; i++) {
1456 if (table[j][i].asc == asc) {
1458 /* Check for ranges */
1459 if ((table[j][i].action & SSQ_RANGE) != 0) {
1461 if (table[j][i].ascq >= ascq
1462 && table[j][i-1].ascq <= ascq)
1463 return table[j][i-1].desc;
1468 if (table[j][i].ascq == ascq)
1469 return table[j][i].desc;
1474 if (asc >= 0x80 && asc <= 0xff)
1475 return "Vendor Specific ASC";
1477 if (ascq >= 0x80 && ascq <= 0xff)
1478 return "Vendor Specific ASCQ";
1480 return "Reserved ASC/ASCQ pair";
1483 #else /* SCSI_NO_SENSE_STRINGS */
1485 scsi_sense_desc(int asc, int ascq, struct scsi_inquiry_data *inq_data)
1492 * Given a particular failed CCB and its device type information, return
1493 * the appropriate action from either the sense code quirk table or the
1497 scsi_error_action(int asc, int ascq, struct scsi_inquiry_data *inq_data)
1500 struct asc_table_entry *table[2];
1506 * If we don't have inquiry data, we can't match against any quirk
1509 if (inq_data != NULL) {
1510 match = cam_quirkmatch((caddr_t)inq_data,
1511 (caddr_t)asc_quirk_table,
1512 sizeof(asc_quirk_table) /
1513 sizeof(*asc_quirk_table),
1514 sizeof(*asc_quirk_table),
1515 scsi_inquiry_match);
1519 if (match != NULL) {
1520 table[0] = ((struct scsi_sense_quirk_entry *)match)->asc_info;
1522 ((struct scsi_sense_quirk_entry *)match)->num_ascs;
1523 table[1] = asc_text;
1524 table_size[1] = sizeof(asc_text)/sizeof(asc_text[0]);
1527 table[0] = asc_text;
1528 table_size[0] = sizeof(asc_text)/sizeof(asc_text[0]);
1532 for (j = 0; j < num_tables; j++) {
1533 for (i = 0; i < table_size[j]; i++) {
1534 if (table[j][i].asc == asc) {
1536 /* Check for ranges */
1537 if ((table[j][i].action & SSQ_RANGE) != 0){
1539 if (table[j][i].ascq >= ascq
1540 && table[j][i-1].ascq <= ascq)
1541 return table[j][i].action;
1547 * Check to see if we have a match. If the
1548 * current ascq in the table is greater
1549 * than our ascq, and there aren't any more
1550 * tables to search, just return the
1553 if (table[j][i].ascq == ascq)
1554 return(table[j][i].action);
1555 else if ((j == (num_tables - 1)) &&
1556 (table[j][i].ascq > ascq))
1562 * If we get to this point, it's most likely a vendor specific
1563 * ASC and we don't have a quirk entry for it. Oh well, we just
1564 * tell the error handling code to take the default action.
1570 scsi_cdb_string(u_int8_t *cdb_ptr, char *cdb_string, size_t len)
1575 if (cdb_ptr == NULL)
1578 /* Silence warnings */
1582 * This is taken from the SCSI-3 draft spec.
1583 * (T10/1157D revision 0.3)
1584 * The top 3 bits of an opcode are the group code. The next 5 bits
1585 * are the command code.
1586 * Group 0: six byte commands
1587 * Group 1: ten byte commands
1588 * Group 2: ten byte commands
1590 * Group 4: sixteen byte commands
1591 * Group 5: twelve byte commands
1592 * Group 6: vendor specific
1593 * Group 7: vendor specific
1595 switch((*cdb_ptr >> 5) & 0x7) {
1606 /* in this case, just print out the opcode */
1617 for (i = 0; i < cdb_len; i++)
1618 ksnprintf(cdb_string + strlen(cdb_string),
1619 len - strlen(cdb_string), "%x ", cdb_ptr[i]);
1624 * scsi_sense_print will decode the sense data into human
1625 * readable form. Sense handlers can use this to generate
1629 * Because scsi_sense_print() utilizes transport layer functions, it will
1630 * only work in the kernel.
1635 scsi_sense_print(struct ccb_scsiio *csio)
1637 struct scsi_sense_data *sense;
1642 struct ccb_getdev cgd;
1643 u_int8_t command_print;
1645 sense = &csio->sense_data;
1648 * If the CDB is a physical address, we can't deal with it..
1650 if ((csio->ccb_h.flags & CAM_CDB_PHYS) != 0)
1656 * Get the device information.
1658 xpt_setup_ccb(&cgd.ccb_h,
1661 cgd.ccb_h.func_code = XPT_GDEV_TYPE;
1662 xpt_action((union ccb *)&cgd);
1665 * If the device is unconfigured, just pretend that it is a hard
1666 * drive. scsi_op_desc() needs this.
1668 if (cgd.ccb_h.status == CAM_DEV_NOT_THERE)
1669 cgd.inq_data.device = T_DIRECT;
1671 if (command_print != 0) {
1672 char cdb_str[(SCSI_MAX_CDBLEN * 3) + 1];
1674 xpt_print_path(csio->ccb_h.path);
1676 if ((csio->ccb_h.flags & CAM_CDB_POINTER) != 0) {
1677 kprintf("%s. CDB: %s\n",
1678 scsi_op_desc(csio->cdb_io.cdb_ptr[0],
1680 scsi_cdb_string(csio->cdb_io.cdb_ptr, cdb_str,
1683 kprintf("%s. CDB: %s\n",
1684 scsi_op_desc(csio->cdb_io.cdb_bytes[0],
1685 &cgd.inq_data), scsi_cdb_string(
1686 csio->cdb_io.cdb_bytes, cdb_str,
1692 * If the sense data is a physical pointer, forget it.
1694 if (csio->ccb_h.flags & CAM_SENSE_PTR) {
1695 if (csio->ccb_h.flags & CAM_SENSE_PHYS)
1699 * XXX KDM this is stupid, but casting the
1700 * structure doesn't work...
1702 bcopy(&csio->sense_data, &sense,
1703 sizeof(struct scsi_sense_data *));
1707 * If the physical sense flag is set, but the sense pointer
1708 * is not also set, we assume that the user is an idiot and
1709 * return. (Well, okay, it could be that somehow, the
1710 * entire csio is physical, but we would have probably core
1711 * dumped on one of the bogus pointer deferences above
1714 if (csio->ccb_h.flags & CAM_SENSE_PHYS)
1717 sense = &csio->sense_data;
1720 xpt_print_path(csio->ccb_h.path);
1721 error_code = sense->error_code & SSD_ERRCODE;
1722 sense_key = sense->flags & SSD_KEY;
1724 switch (error_code) {
1725 case SSD_DEFERRED_ERROR:
1726 kprintf("Deferred Error: ");
1728 case SSD_CURRENT_ERROR:
1730 kprintf("%s", scsi_sense_key_text[sense_key]);
1731 info = scsi_4btoul(sense->info);
1733 if (sense->error_code & SSD_ERRCODE_VALID) {
1735 switch (sense_key) {
1736 case SSD_KEY_NOT_READY:
1737 case SSD_KEY_ILLEGAL_REQUEST:
1738 case SSD_KEY_UNIT_ATTENTION:
1739 case SSD_KEY_DATA_PROTECT:
1741 case SSD_KEY_BLANK_CHECK:
1742 kprintf(" req sz: %d (decimal)",
1747 if (sense->flags & SSD_ILI) {
1748 kprintf(" ILI (length mismatch):"
1751 kprintf(" info:%x", info);
1756 kprintf(" info?:%x", info);
1758 if (sense->extra_len >= 4) {
1759 if (bcmp(sense->cmd_spec_info, "\0\0\0\0", 4)) {
1760 kprintf(" csi:%x,%x,%x,%x",
1761 sense->cmd_spec_info[0],
1762 sense->cmd_spec_info[1],
1763 sense->cmd_spec_info[2],
1764 sense->cmd_spec_info[3]);
1768 asc = (sense->extra_len >= 5) ? sense->add_sense_code : 0;
1769 ascq = (sense->extra_len >= 6) ? sense->add_sense_code_qual : 0;
1772 const char *desc = scsi_sense_desc(asc, ascq,
1774 kprintf(" asc:%x,%x\n", asc, ascq);
1776 xpt_print_path(csio->ccb_h.path);
1777 kprintf("%s", desc);
1780 if (sense->extra_len >= 7 && sense->fru) {
1781 kprintf(" field replaceable unit: %x", sense->fru);
1784 if ((sense->extra_len >= 10)
1785 && (sense->sense_key_spec[0] & SSD_SCS_VALID) != 0) {
1786 kprintf(" sks:%x,%x", sense->sense_key_spec[0],
1787 scsi_2btoul(&sense->sense_key_spec[1]));
1792 kprintf("error code %d",
1793 sense->error_code & SSD_ERRCODE);
1794 if (sense->error_code & SSD_ERRCODE_VALID) {
1795 kprintf(" at block no. %d (decimal)",
1796 info = scsi_4btoul(sense->info));
1803 #else /* !_KERNEL */
1807 scsi_sense_string(struct cam_device *device, struct ccb_scsiio *csio,
1808 char *str, int str_len)
1810 struct scsi_sense_data *sense;
1815 u_int8_t command_print;
1818 int tmpstrlen = 2048;
1819 int cur_len = 0, tmplen = 0, retlen;
1821 if ((device == NULL) || (csio == NULL) || (str == NULL))
1828 * If the CDB is a physical address, we can't deal with it..
1830 if ((csio->ccb_h.flags & CAM_CDB_PHYS) != 0)
1835 cam_path_string(device, path_str, 64);
1841 if (command_print != 0) {
1842 char cdb_str[(SCSI_MAX_CDBLEN * 3) + 1];
1844 retlen = ksnprintf(tmpstr, tmpstrlen, "%s", path_str);
1846 if ((tmplen = str_len - cur_len - 1) < 0)
1849 strncat(str, tmpstr, tmplen);
1851 str[str_len - 1] = '\0';
1853 if ((csio->ccb_h.flags & CAM_CDB_POINTER) != 0) {
1854 retlen = ksnprintf(tmpstr, tmpstrlen, "%s. CDB: %s\n",
1855 scsi_op_desc(csio->cdb_io.cdb_ptr[0],
1857 scsi_cdb_string(csio->cdb_io.cdb_ptr,
1861 retlen = ksnprintf(tmpstr, tmpstrlen, "%s. CDB: %s\n",
1862 scsi_op_desc(csio->cdb_io.cdb_bytes[0],
1863 &device->inq_data), scsi_cdb_string(
1864 csio->cdb_io.cdb_bytes, cdb_str,
1868 if ((tmplen = str_len - cur_len - 1) < 0)
1871 strncat(str, tmpstr, tmplen);
1873 str[str_len - 1] = '\0';
1877 * If the sense data is a physical pointer, forget it.
1879 if (csio->ccb_h.flags & CAM_SENSE_PTR) {
1880 if (csio->ccb_h.flags & CAM_SENSE_PHYS)
1884 * XXX KDM this is stupid, but casting the
1885 * structure doesn't work...
1887 bcopy(&csio->sense_data, &sense,
1888 sizeof(struct scsi_sense_data *));
1892 * If the physical sense flag is set, but the sense pointer
1893 * is not also set, we assume that the user is an idiot and
1894 * return. (Well, okay, it could be that somehow, the
1895 * entire csio is physical, but we would have probably core
1896 * dumped on one of the bogus pointer deferences above
1899 if (csio->ccb_h.flags & CAM_SENSE_PHYS)
1902 sense = &csio->sense_data;
1906 retlen = ksnprintf(tmpstr, tmpstrlen, "%s", path_str);
1908 if ((tmplen = str_len - cur_len - 1) < 0)
1911 strncat(str, tmpstr, tmplen);
1913 str[str_len - 1] = '\0';
1915 error_code = sense->error_code & SSD_ERRCODE;
1916 sense_key = sense->flags & SSD_KEY;
1918 switch (error_code) {
1919 case SSD_DEFERRED_ERROR:
1920 retlen = ksnprintf(tmpstr, tmpstrlen, "Deferred Error: ");
1922 if ((tmplen = str_len - cur_len - 1) < 0)
1925 strncat(str, tmpstr, tmplen);
1927 str[str_len - 1] = '\0';
1929 case SSD_CURRENT_ERROR:
1931 retlen = ksnprintf(tmpstr, tmpstrlen, "%s",
1932 scsi_sense_key_text[sense_key]);
1934 if ((tmplen = str_len - cur_len - 1) < 0)
1937 strncat(str, tmpstr, tmplen);
1939 str[str_len - 1] = '\0';
1941 info = scsi_4btoul(sense->info);
1943 if (sense->error_code & SSD_ERRCODE_VALID) {
1945 switch (sense_key) {
1946 case SSD_KEY_NOT_READY:
1947 case SSD_KEY_ILLEGAL_REQUEST:
1948 case SSD_KEY_UNIT_ATTENTION:
1949 case SSD_KEY_DATA_PROTECT:
1951 case SSD_KEY_BLANK_CHECK:
1952 retlen = ksnprintf(tmpstr, tmpstrlen,
1953 " req sz: %d (decimal)",
1956 if ((tmplen = str_len - cur_len - 1) < 0)
1959 strncat(str, tmpstr, tmplen);
1961 str[str_len - 1] = '\0';
1965 if (sense->flags & SSD_ILI) {
1966 retlen = ksnprintf (tmpstr,
1969 "mismatch): %d", info);
1972 retlen = ksnprintf(tmpstr,
1978 if ((tmplen = str_len - cur_len -1) < 0)
1981 strncat(str, tmpstr, tmplen);
1983 str[str_len - 1] = '\0';
1987 retlen = ksnprintf(tmpstr, tmpstrlen," info?:%x", info);
1989 if ((tmplen = str_len - cur_len -1) < 0)
1992 strncat(str, tmpstr, tmplen);
1994 str[str_len - 1] = '\0';
1997 if (sense->extra_len >= 4) {
1998 if (bcmp(sense->cmd_spec_info, "\0\0\0\0", 4)) {
1999 retlen = ksnprintf(tmpstr, tmpstrlen,
2001 sense->cmd_spec_info[0],
2002 sense->cmd_spec_info[1],
2003 sense->cmd_spec_info[2],
2004 sense->cmd_spec_info[3]);
2006 if ((tmplen = str_len - cur_len -1) < 0)
2009 strncat(str, tmpstr, tmplen);
2011 str[str_len - 1] = '\0';
2015 asc = (sense->extra_len >= 5) ? sense->add_sense_code : 0;
2016 ascq = (sense->extra_len >= 6) ? sense->add_sense_code_qual : 0;
2019 const char *desc = scsi_sense_desc(asc, ascq,
2021 retlen = ksnprintf(tmpstr, tmpstrlen,
2022 " asc:%x,%x\n%s%s", asc, ascq,
2025 if ((tmplen = str_len - cur_len -1) < 0)
2028 strncat(str, tmpstr, tmplen);
2030 str[str_len - 1] = '\0';
2033 if (sense->extra_len >= 7 && sense->fru) {
2034 retlen = ksnprintf(tmpstr, tmpstrlen,
2035 " field replaceable unit: %x",
2038 if ((tmplen = str_len - cur_len -1) < 0)
2041 strncat(str, tmpstr, tmplen);
2042 str[str_len - 1] = '\0';
2046 if ((sense->extra_len >= 10)
2047 && (sense->sense_key_spec[0] & SSD_SCS_VALID) != 0) {
2048 retlen = ksnprintf(tmpstr, tmpstrlen, " sks:%x,%x",
2049 sense->sense_key_spec[0],
2050 scsi_2btoul(&sense->sense_key_spec[1]));
2052 if ((tmplen = str_len - cur_len -1) < 0)
2055 strncat(str, tmpstr, tmplen);
2056 str[str_len - 1] = '\0';
2062 retlen = ksnprintf(tmpstr, tmpstrlen, "error code %d",
2063 sense->error_code & SSD_ERRCODE);
2065 if ((tmplen = str_len - cur_len -1) < 0)
2068 strncat(str, tmpstr, tmplen);
2070 str[str_len - 1] = '\0';
2072 if (sense->error_code & SSD_ERRCODE_VALID) {
2073 retlen = ksnprintf(tmpstr, tmpstrlen,
2074 " at block no. %d (decimal)",
2075 info = scsi_4btoul(sense->info));
2077 if ((tmplen = str_len - cur_len -1) < 0)
2080 strncat(str, tmpstr, tmplen);
2082 str[str_len - 1] = '\0';
2086 retlen = ksnprintf(tmpstr, tmpstrlen, "\n");
2088 if ((tmplen = str_len - cur_len -1) < 0)
2091 strncat(str, tmpstr, tmplen);
2093 str[str_len - 1] = '\0';
2101 scsi_sense_print(struct cam_device *device, struct ccb_scsiio *csio,
2106 if ((device == NULL) || (csio == NULL) || (ofile == NULL))
2109 fprintf(ofile, "%s", scsi_sense_string(device, csio, str, 2048));
2112 #endif /* _KERNEL/!_KERNEL */
2116 scsi_interpret_sense(union ccb *ccb, u_int32_t sense_flags,
2117 u_int32_t *relsim_flags, u_int32_t *openings,
2118 u_int32_t *timeout, scsi_sense_action error_action)
2121 scsi_interpret_sense(struct cam_device *device, union ccb *ccb,
2122 u_int32_t sense_flags, u_int32_t *relsim_flags,
2123 u_int32_t *openings, u_int32_t *timeout,
2124 scsi_sense_action error_action)
2127 struct scsi_sense_data *sense;
2128 int error_code, sense_key, asc, ascq;
2131 struct ccb_scsiio *csio;
2135 sense = &csio->sense_data;
2136 scsi_extract_sense(sense, &error_code, &sense_key, &asc, &ascq);
2140 sense_flags |= SF_PRINT_ALWAYS;
2142 } else if ((sense_flags & SF_NO_PRINT) == 0)
2144 if ((sense_flags & SF_NO_PRINT) == 0)
2148 print_sense = FALSE;
2150 switch (error_code) {
2151 case SSD_DEFERRED_ERROR:
2154 * XXX dufault@FreeBSD.org
2155 * This error doesn't relate to the command associated
2156 * with this request sense. A deferred error is an error
2157 * for a command that has already returned GOOD status
2160 * By my reading of that section, it looks like the current
2161 * command has been cancelled, we should now clean things up
2162 * (hopefully recovering any lost data) and then retry the
2163 * current command. There are two easy choices, both wrong:
2165 * 1. Drop through (like we had been doing), thus treating
2166 * this as if the error were for the current command and
2167 * return and stop the current command.
2169 * 2. Issue a retry (like I made it do) thus hopefully
2170 * recovering the current transfer, and ignoring the
2171 * fact that we've dropped a command.
2173 * These should probably be handled in a device specific
2174 * sense handler or punted back up to a user mode daemon
2177 /* decrement the number of retries */
2178 retry = ccb->ccb_h.retry_count > 0;
2180 ccb->ccb_h.retry_count--;
2185 case SSD_CURRENT_ERROR:
2188 switch (sense_key) {
2189 case SSD_KEY_NO_SENSE:
2190 /* Why were we called then? Well don't bail now */
2193 /* These should be filtered by the peripheral drivers */
2194 print_sense = FALSE;
2196 case SSD_KEY_MISCOMPARE:
2197 /* decrement the number of retries */
2198 retry = ccb->ccb_h.retry_count > 0;
2201 ccb->ccb_h.retry_count--;
2205 case SSD_KEY_RECOVERED_ERROR:
2206 error = 0; /* not an error */
2208 case SSD_KEY_ILLEGAL_REQUEST:
2209 if (((sense_flags & SF_QUIET_IR) != 0)
2210 && ((sense_flags & SF_PRINT_ALWAYS) == 0))
2211 print_sense = FALSE;
2214 case SSD_KEY_NOT_READY:
2215 case SSD_KEY_DATA_PROTECT:
2216 case SSD_KEY_VOLUME_OVERFLOW:
2217 case SSD_KEY_BLANK_CHECK: /* should be filtered out by
2218 peripheral drivers */
2219 retry = ccb->ccb_h.retry_count > 0;
2221 ccb->ccb_h.retry_count--;
2223 print_sense = FALSE;
2225 if (((error_action & SSQ_PRINT_SENSE) == 0)
2226 && ((sense_flags & SF_PRINT_ALWAYS) == 0))
2227 print_sense = FALSE;
2229 error = error_action & SS_ERRMASK;
2233 case SSD_KEY_UNIT_ATTENTION:
2235 * This should also be filtered out by
2236 * peripheral drivers since each has a different
2237 * concept of what it means to invalidate the media.
2239 if ((sense_flags & SF_RETRY_UA) != 0) {
2240 /* don't decrement retry count */
2242 print_sense = FALSE;
2244 /* decrement the number of retries */
2245 retry = ccb->ccb_h.retry_count > 0;
2247 ccb->ccb_h.retry_count--;
2249 print_sense = FALSE;
2251 if (((error_action &
2252 SSQ_PRINT_SENSE) == 0)
2254 SF_PRINT_ALWAYS) == 0))
2255 print_sense = FALSE;
2257 error = error_action & SS_ERRMASK;
2261 case SSD_KEY_ABORTED_COMMAND:
2263 /* decrement the number of retries */
2264 retry = ccb->ccb_h.retry_count > 0;
2266 ccb->ccb_h.retry_count--;
2268 print_sense = FALSE;
2270 if (((error_action & SSQ_PRINT_SENSE) == 0)
2271 && ((sense_flags & SF_PRINT_ALWAYS) == 0))
2272 print_sense = FALSE;
2274 error = error_action & SS_ERRMASK;
2277 * Make sure ABORTED COMMAND errors get
2278 * printed as they're indicative of marginal
2279 * SCSI busses that people should address.
2281 if (sense_key == SSD_KEY_ABORTED_COMMAND)
2287 /* decrement the number of retries */
2288 retry = ccb->ccb_h.retry_count > 0;
2290 ccb->ccb_h.retry_count--;
2292 print_sense = FALSE;
2300 scsi_sense_print(csio);
2302 scsi_sense_print(device, csio, stdout);
2310 * This function currently requires at least 36 bytes, or
2311 * SHORT_INQUIRY_LENGTH, worth of data to function properly. If this
2312 * function needs more or less data in the future, another length should be
2313 * defined in scsi_all.h to indicate the minimum amount of data necessary
2314 * for this routine to function properly.
2317 scsi_print_inquiry(struct scsi_inquiry_data *inq_data)
2320 char *dtype, *qtype;
2321 char vendor[16], product[48], revision[16], rstr[4];
2323 type = SID_TYPE(inq_data);
2326 * Figure out basic device type and qualifier.
2328 if (SID_QUAL_IS_VENDOR_UNIQUE(inq_data)) {
2329 qtype = "(vendor-unique qualifier)";
2331 switch (SID_QUAL(inq_data)) {
2332 case SID_QUAL_LU_CONNECTED:
2336 case SID_QUAL_LU_OFFLINE:
2337 qtype = "(offline)";
2341 qtype = "(reserved qualifier)";
2344 case SID_QUAL_BAD_LU:
2345 qtype = "(lun not supported)";
2352 dtype = "Direct Access";
2355 dtype = "Sequential Access";
2361 dtype = "Processor";
2379 dtype = "Communication";
2382 dtype = "Storage Array";
2385 dtype = "Enclosure Services";
2388 dtype = "Simplified Direct Access";
2391 dtype = "Optical Card Read/Write";
2394 dtype = "Uninstalled";
2400 cam_strvis(vendor, inq_data->vendor, sizeof(inq_data->vendor),
2402 cam_strvis(product, inq_data->product, sizeof(inq_data->product),
2404 cam_strvis(revision, inq_data->revision, sizeof(inq_data->revision),
2407 if (SID_ANSI_REV(inq_data) == SCSI_REV_CCS)
2408 bcopy("CCS", rstr, 4);
2410 ksnprintf(rstr, sizeof (rstr), "%d", SID_ANSI_REV(inq_data));
2411 kprintf("<%s %s %s> %s %s SCSI-%s device %s\n",
2412 vendor, product, revision,
2413 SID_IS_REMOVABLE(inq_data) ? "Removable" : "Fixed",
2414 dtype, rstr, qtype);
2418 * Table of syncrates that don't follow the "divisible by 4"
2419 * rule. This table will be expanded in future SCSI specs.
2422 u_int period_factor;
2423 u_int period; /* in 100ths of ns */
2424 } scsi_syncrates[] = {
2425 { 0x08, 625 }, /* FAST-160 */
2426 { 0x09, 1250 }, /* FAST-80 */
2427 { 0x0a, 2500 }, /* FAST-40 40MHz */
2428 { 0x0b, 3030 }, /* FAST-40 33MHz */
2429 { 0x0c, 5000 } /* FAST-20 */
2433 * Return the frequency in kHz corresponding to the given
2434 * sync period factor.
2437 scsi_calc_syncsrate(u_int period_factor)
2442 num_syncrates = sizeof(scsi_syncrates) / sizeof(scsi_syncrates[0]);
2443 /* See if the period is in the "exception" table */
2444 for (i = 0; i < num_syncrates; i++) {
2446 if (period_factor == scsi_syncrates[i].period_factor) {
2448 return (100000000 / scsi_syncrates[i].period);
2453 * Wasn't in the table, so use the standard
2454 * 4 times conversion.
2456 return (10000000 / (period_factor * 4 * 10));
2460 * Return the SCSI sync parameter that corresponsd to
2461 * the passed in period in 10ths of ns.
2464 scsi_calc_syncparam(u_int period)
2470 return (~0); /* Async */
2472 /* Adjust for exception table being in 100ths. */
2474 num_syncrates = sizeof(scsi_syncrates) / sizeof(scsi_syncrates[0]);
2475 /* See if the period is in the "exception" table */
2476 for (i = 0; i < num_syncrates; i++) {
2478 if (period <= scsi_syncrates[i].period) {
2479 /* Period in 100ths of ns */
2480 return (scsi_syncrates[i].period_factor);
2485 * Wasn't in the table, so use the standard
2486 * 1/4 period in ns conversion.
2488 return (period/400);
2492 scsi_test_unit_ready(struct ccb_scsiio *csio, u_int32_t retries,
2493 void (*cbfcnp)(struct cam_periph *, union ccb *),
2494 u_int8_t tag_action, u_int8_t sense_len, u_int32_t timeout)
2496 struct scsi_test_unit_ready *scsi_cmd;
2509 scsi_cmd = (struct scsi_test_unit_ready *)&csio->cdb_io.cdb_bytes;
2510 bzero(scsi_cmd, sizeof(*scsi_cmd));
2511 scsi_cmd->opcode = TEST_UNIT_READY;
2515 scsi_request_sense(struct ccb_scsiio *csio, u_int32_t retries,
2516 void (*cbfcnp)(struct cam_periph *, union ccb *),
2517 void *data_ptr, u_int8_t dxfer_len, u_int8_t tag_action,
2518 u_int8_t sense_len, u_int32_t timeout)
2520 struct scsi_request_sense *scsi_cmd;
2533 scsi_cmd = (struct scsi_request_sense *)&csio->cdb_io.cdb_bytes;
2534 bzero(scsi_cmd, sizeof(*scsi_cmd));
2535 scsi_cmd->opcode = REQUEST_SENSE;
2536 scsi_cmd->length = dxfer_len;
2540 scsi_inquiry(struct ccb_scsiio *csio, u_int32_t retries,
2541 void (*cbfcnp)(struct cam_periph *, union ccb *),
2542 u_int8_t tag_action, u_int8_t *inq_buf, u_int32_t inq_len,
2543 int evpd, u_int8_t page_code, u_int8_t sense_len,
2546 struct scsi_inquiry *scsi_cmd;
2551 /*flags*/CAM_DIR_IN,
2553 /*data_ptr*/inq_buf,
2554 /*dxfer_len*/inq_len,
2559 scsi_cmd = (struct scsi_inquiry *)&csio->cdb_io.cdb_bytes;
2560 bzero(scsi_cmd, sizeof(*scsi_cmd));
2561 scsi_cmd->opcode = INQUIRY;
2563 scsi_cmd->byte2 |= SI_EVPD;
2564 scsi_cmd->page_code = page_code;
2567 * A 'transfer units' count of 256 is coded as
2568 * zero for all commands with a single byte count
2573 scsi_cmd->length = inq_len;
2577 scsi_mode_sense(struct ccb_scsiio *csio, u_int32_t retries,
2578 void (*cbfcnp)(struct cam_periph *, union ccb *),
2579 u_int8_t tag_action, int dbd, u_int8_t page_code,
2580 u_int8_t page, u_int8_t *param_buf, u_int32_t param_len,
2581 u_int8_t sense_len, u_int32_t timeout)
2583 return(scsi_mode_sense_len(csio, retries, cbfcnp, tag_action, dbd,
2584 page_code, page, param_buf, param_len, 0,
2585 sense_len, timeout));
2589 scsi_mode_sense_len(struct ccb_scsiio *csio, u_int32_t retries,
2590 void (*cbfcnp)(struct cam_periph *, union ccb *),
2591 u_int8_t tag_action, int dbd, u_int8_t page_code,
2592 u_int8_t page, u_int8_t *param_buf, u_int32_t param_len,
2593 int minimum_cmd_size, u_int8_t sense_len, u_int32_t timeout)
2598 * Use the smallest possible command to perform the operation.
2600 if ((param_len < 256) && (minimum_cmd_size < 10)) {
2602 * We can fit in a 6 byte cdb.
2604 struct scsi_mode_sense_6 *scsi_cmd;
2606 scsi_cmd = (struct scsi_mode_sense_6 *)&csio->cdb_io.cdb_bytes;
2607 bzero(scsi_cmd, sizeof(*scsi_cmd));
2608 scsi_cmd->opcode = MODE_SENSE_6;
2610 scsi_cmd->byte2 |= SMS_DBD;
2611 scsi_cmd->page = page_code | page;
2612 scsi_cmd->length = param_len;
2613 cdb_len = sizeof(*scsi_cmd);
2616 * Need a 10 byte cdb.
2618 struct scsi_mode_sense_10 *scsi_cmd;
2620 scsi_cmd = (struct scsi_mode_sense_10 *)&csio->cdb_io.cdb_bytes;
2621 bzero(scsi_cmd, sizeof(*scsi_cmd));
2622 scsi_cmd->opcode = MODE_SENSE_10;
2624 scsi_cmd->byte2 |= SMS_DBD;
2625 scsi_cmd->page = page_code | page;
2626 scsi_ulto2b(param_len, scsi_cmd->length);
2627 cdb_len = sizeof(*scsi_cmd);
2642 scsi_mode_select(struct ccb_scsiio *csio, u_int32_t retries,
2643 void (*cbfcnp)(struct cam_periph *, union ccb *),
2644 u_int8_t tag_action, int scsi_page_fmt, int save_pages,
2645 u_int8_t *param_buf, u_int32_t param_len, u_int8_t sense_len,
2648 return(scsi_mode_select_len(csio, retries, cbfcnp, tag_action,
2649 scsi_page_fmt, save_pages, param_buf,
2650 param_len, 0, sense_len, timeout));
2654 scsi_mode_select_len(struct ccb_scsiio *csio, u_int32_t retries,
2655 void (*cbfcnp)(struct cam_periph *, union ccb *),
2656 u_int8_t tag_action, int scsi_page_fmt, int save_pages,
2657 u_int8_t *param_buf, u_int32_t param_len,
2658 int minimum_cmd_size, u_int8_t sense_len,
2664 * Use the smallest possible command to perform the operation.
2666 if ((param_len < 256) && (minimum_cmd_size < 10)) {
2668 * We can fit in a 6 byte cdb.
2670 struct scsi_mode_select_6 *scsi_cmd;
2672 scsi_cmd = (struct scsi_mode_select_6 *)&csio->cdb_io.cdb_bytes;
2673 bzero(scsi_cmd, sizeof(*scsi_cmd));
2674 scsi_cmd->opcode = MODE_SELECT_6;
2675 if (scsi_page_fmt != 0)
2676 scsi_cmd->byte2 |= SMS_PF;
2677 if (save_pages != 0)
2678 scsi_cmd->byte2 |= SMS_SP;
2679 scsi_cmd->length = param_len;
2680 cdb_len = sizeof(*scsi_cmd);
2683 * Need a 10 byte cdb.
2685 struct scsi_mode_select_10 *scsi_cmd;
2688 (struct scsi_mode_select_10 *)&csio->cdb_io.cdb_bytes;
2689 bzero(scsi_cmd, sizeof(*scsi_cmd));
2690 scsi_cmd->opcode = MODE_SELECT_10;
2691 if (scsi_page_fmt != 0)
2692 scsi_cmd->byte2 |= SMS_PF;
2693 if (save_pages != 0)
2694 scsi_cmd->byte2 |= SMS_SP;
2695 scsi_ulto2b(param_len, scsi_cmd->length);
2696 cdb_len = sizeof(*scsi_cmd);
2711 scsi_read_capacity_16(struct ccb_scsiio *csio, uint32_t retries,
2712 void (*cbfcnp)(struct cam_periph *, union ccb *),
2713 uint8_t tag_action, uint64_t lba, int reladr, int pmi,
2714 struct scsi_read_capacity_data_long *rcap_buf,
2715 uint8_t sense_len, uint32_t timeout)
2717 struct scsi_read_capacity_16 *scsi_cmd;
2722 /*flags*/CAM_DIR_IN,
2724 /*data_ptr*/(u_int8_t *)rcap_buf,
2725 /*dxfer_len*/sizeof(*rcap_buf),
2729 scsi_cmd = (struct scsi_read_capacity_16 *)&csio->cdb_io.cdb_bytes;
2730 bzero(scsi_cmd, sizeof(*scsi_cmd));
2731 scsi_cmd->opcode = SERVICE_ACTION_IN;
2732 scsi_cmd->service_action = SRC16_SERVICE_ACTION;
2733 scsi_u64to8b(lba, scsi_cmd->addr);
2734 scsi_ulto4b(sizeof(*rcap_buf), scsi_cmd->alloc_len);
2736 reladr |= SRC16_PMI;
2738 reladr |= SRC16_RELADR;
2741 /* XXX allow specification of address and PMI bit and LBA */
2743 scsi_read_capacity(struct ccb_scsiio *csio, u_int32_t retries,
2744 void (*cbfcnp)(struct cam_periph *, union ccb *),
2745 u_int8_t tag_action,
2746 struct scsi_read_capacity_data *rcap_buf,
2747 u_int8_t sense_len, u_int32_t timeout)
2749 struct scsi_read_capacity *scsi_cmd;
2754 /*flags*/CAM_DIR_IN,
2756 /*data_ptr*/(u_int8_t *)rcap_buf,
2757 /*dxfer_len*/sizeof(*rcap_buf),
2762 scsi_cmd = (struct scsi_read_capacity *)&csio->cdb_io.cdb_bytes;
2763 bzero(scsi_cmd, sizeof(*scsi_cmd));
2764 scsi_cmd->opcode = READ_CAPACITY;
2768 * Prevent or allow the user to remove the media
2771 scsi_prevent(struct ccb_scsiio *csio, u_int32_t retries,
2772 void (*cbfcnp)(struct cam_periph *, union ccb *),
2773 u_int8_t tag_action, u_int8_t action,
2774 u_int8_t sense_len, u_int32_t timeout)
2776 struct scsi_prevent *scsi_cmd;
2781 /*flags*/CAM_DIR_NONE,
2789 scsi_cmd = (struct scsi_prevent *)&csio->cdb_io.cdb_bytes;
2790 bzero(scsi_cmd, sizeof(*scsi_cmd));
2791 scsi_cmd->opcode = PREVENT_ALLOW;
2792 scsi_cmd->how = action;
2796 * Syncronize the media to the contents of the cache for
2797 * the given lba/count pair. Specifying 0/0 means sync
2801 scsi_synchronize_cache(struct ccb_scsiio *csio, u_int32_t retries,
2802 void (*cbfcnp)(struct cam_periph *, union ccb *),
2803 u_int8_t tag_action, u_int32_t begin_lba,
2804 u_int16_t lb_count, u_int8_t sense_len,
2807 struct scsi_sync_cache *scsi_cmd;
2812 /*flags*/CAM_DIR_NONE,
2820 scsi_cmd = (struct scsi_sync_cache *)&csio->cdb_io.cdb_bytes;
2821 bzero(scsi_cmd, sizeof(*scsi_cmd));
2822 scsi_cmd->opcode = SYNCHRONIZE_CACHE;
2823 scsi_ulto4b(begin_lba, scsi_cmd->begin_lba);
2824 scsi_ulto2b(lb_count, scsi_cmd->lb_count);
2828 scsi_read_write(struct ccb_scsiio *csio, u_int32_t retries,
2829 void (*cbfcnp)(struct cam_periph *, union ccb *),
2830 u_int8_t tag_action, int readop, u_int8_t byte2,
2831 int minimum_cmd_size, u_int64_t lba, u_int32_t block_count,
2832 u_int8_t *data_ptr, u_int32_t dxfer_len, u_int8_t sense_len,
2838 * Use the smallest possible command to perform the operation
2839 * as some legacy hardware does not support the 10 byte
2840 * commands. If any of the lower 5 bits in byte2 is set, we have
2841 * to go with a larger command.
2844 if ((minimum_cmd_size < 10)
2845 && ((lba & 0x1fffff) == lba)
2846 && ((block_count & 0xff) == block_count)
2847 && ((byte2 & 0xe0) == 0)) {
2849 * We can fit in a 6 byte cdb.
2851 struct scsi_rw_6 *scsi_cmd;
2853 scsi_cmd = (struct scsi_rw_6 *)&csio->cdb_io.cdb_bytes;
2854 scsi_cmd->opcode = readop ? READ_6 : WRITE_6;
2855 scsi_ulto3b(lba, scsi_cmd->addr);
2856 scsi_cmd->length = block_count & 0xff;
2857 scsi_cmd->control = 0;
2858 cdb_len = sizeof(*scsi_cmd);
2860 CAM_DEBUG(csio->ccb_h.path, CAM_DEBUG_SUBTRACE,
2861 ("6byte: %x%x%x:%d:%d\n", scsi_cmd->addr[0],
2862 scsi_cmd->addr[1], scsi_cmd->addr[2],
2863 scsi_cmd->length, dxfer_len));
2864 } else if ((minimum_cmd_size < 12)
2865 && ((block_count & 0xffff) == block_count)
2866 && ((lba & 0xffffffffU) == lba)) {
2868 * Need a 10 byte cdb.
2870 struct scsi_rw_10 *scsi_cmd;
2872 scsi_cmd = (struct scsi_rw_10 *)&csio->cdb_io.cdb_bytes;
2873 scsi_cmd->opcode = readop ? READ_10 : WRITE_10;
2874 scsi_cmd->byte2 = byte2;
2875 scsi_ulto4b(lba, scsi_cmd->addr);
2876 scsi_cmd->reserved = 0;
2877 scsi_ulto2b(block_count, scsi_cmd->length);
2878 scsi_cmd->control = 0;
2879 cdb_len = sizeof(*scsi_cmd);
2881 CAM_DEBUG(csio->ccb_h.path, CAM_DEBUG_SUBTRACE,
2882 ("10byte: %x%x%x%x:%x%x: %d\n", scsi_cmd->addr[0],
2883 scsi_cmd->addr[1], scsi_cmd->addr[2],
2884 scsi_cmd->addr[3], scsi_cmd->length[0],
2885 scsi_cmd->length[1], dxfer_len));
2886 } else if ((minimum_cmd_size < 16)
2887 && ((block_count & 0xffffffffU) == block_count)
2888 && ((lba & 0xffffffffU) == lba)) {
2890 * The block count is too big for a 10 byte CDB, use a 12
2893 struct scsi_rw_12 *scsi_cmd;
2895 scsi_cmd = (struct scsi_rw_12 *)&csio->cdb_io.cdb_bytes;
2896 scsi_cmd->opcode = readop ? READ_12 : WRITE_12;
2897 scsi_cmd->byte2 = byte2;
2898 scsi_ulto4b(lba, scsi_cmd->addr);
2899 scsi_cmd->reserved = 0;
2900 scsi_ulto4b(block_count, scsi_cmd->length);
2901 scsi_cmd->control = 0;
2902 cdb_len = sizeof(*scsi_cmd);
2904 CAM_DEBUG(csio->ccb_h.path, CAM_DEBUG_SUBTRACE,
2905 ("12byte: %x%x%x%x:%x%x%x%x: %d\n", scsi_cmd->addr[0],
2906 scsi_cmd->addr[1], scsi_cmd->addr[2],
2907 scsi_cmd->addr[3], scsi_cmd->length[0],
2908 scsi_cmd->length[1], scsi_cmd->length[2],
2909 scsi_cmd->length[3], dxfer_len));
2912 * 16 byte CDB. We'll only get here if the LBA is larger
2913 * than 2^32, or if the user asks for a 16 byte command.
2915 struct scsi_rw_16 *scsi_cmd;
2917 scsi_cmd = (struct scsi_rw_16 *)&csio->cdb_io.cdb_bytes;
2918 scsi_cmd->opcode = readop ? READ_16 : WRITE_16;
2919 scsi_cmd->byte2 = byte2;
2920 scsi_u64to8b(lba, scsi_cmd->addr);
2921 scsi_cmd->reserved = 0;
2922 scsi_ulto4b(block_count, scsi_cmd->length);
2923 scsi_cmd->control = 0;
2924 cdb_len = sizeof(*scsi_cmd);
2929 /*flags*/readop ? CAM_DIR_IN : CAM_DIR_OUT,
2939 scsi_start_stop(struct ccb_scsiio *csio, u_int32_t retries,
2940 void (*cbfcnp)(struct cam_periph *, union ccb *),
2941 u_int8_t tag_action, int start, int load_eject,
2942 int immediate, u_int8_t sense_len, u_int32_t timeout)
2944 struct scsi_start_stop_unit *scsi_cmd;
2945 int extra_flags = 0;
2947 scsi_cmd = (struct scsi_start_stop_unit *)&csio->cdb_io.cdb_bytes;
2948 bzero(scsi_cmd, sizeof(*scsi_cmd));
2949 scsi_cmd->opcode = START_STOP_UNIT;
2951 scsi_cmd->how |= SSS_START;
2952 /* it takes a lot of power to start a drive */
2953 extra_flags |= CAM_HIGH_POWER;
2955 if (load_eject != 0)
2956 scsi_cmd->how |= SSS_LOEJ;
2958 scsi_cmd->byte2 |= SSS_IMMED;
2963 /*flags*/CAM_DIR_NONE | extra_flags,
2975 * Try make as good a match as possible with
2976 * available sub drivers
2979 scsi_inquiry_match(caddr_t inqbuffer, caddr_t table_entry)
2981 struct scsi_inquiry_pattern *entry;
2982 struct scsi_inquiry_data *inq;
2984 entry = (struct scsi_inquiry_pattern *)table_entry;
2985 inq = (struct scsi_inquiry_data *)inqbuffer;
2987 if (((SID_TYPE(inq) == entry->type)
2988 || (entry->type == T_ANY))
2989 && (SID_IS_REMOVABLE(inq) ? entry->media_type & SIP_MEDIA_REMOVABLE
2990 : entry->media_type & SIP_MEDIA_FIXED)
2991 && (cam_strmatch(inq->vendor, entry->vendor, sizeof(inq->vendor)) == 0)
2992 && (cam_strmatch(inq->product, entry->product,
2993 sizeof(inq->product)) == 0)
2994 && (cam_strmatch(inq->revision, entry->revision,
2995 sizeof(inq->revision)) == 0)) {
3002 * Try make as good a match as possible with
3003 * available sub drivers
3006 scsi_static_inquiry_match(caddr_t inqbuffer, caddr_t table_entry)
3008 struct scsi_static_inquiry_pattern *entry;
3009 struct scsi_inquiry_data *inq;
3011 entry = (struct scsi_static_inquiry_pattern *)table_entry;
3012 inq = (struct scsi_inquiry_data *)inqbuffer;
3014 if (((SID_TYPE(inq) == entry->type)
3015 || (entry->type == T_ANY))
3016 && (SID_IS_REMOVABLE(inq) ? entry->media_type & SIP_MEDIA_REMOVABLE
3017 : entry->media_type & SIP_MEDIA_FIXED)
3018 && (cam_strmatch(inq->vendor, entry->vendor, sizeof(inq->vendor)) == 0)
3019 && (cam_strmatch(inq->product, entry->product,
3020 sizeof(inq->product)) == 0)
3021 && (cam_strmatch(inq->revision, entry->revision,
3022 sizeof(inq->revision)) == 0)) {