2 * Implementation of Utility functions for all SCSI device types.
4 * Copyright (c) 1997, 1998 Justin T. Gibbs.
5 * Copyright (c) 1997, 1998 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.9 2002/10/21 05:38:11 simokawa Exp $
32 #include <sys/param.h>
37 #include <sys/systm.h>
45 #include <cam/cam_ccb.h>
46 #include <cam/cam_xpt.h>
47 #include <cam/cam_xpt_periph.h>
48 #include <cam/scsi/scsi_all.h>
58 #define ERESTART -1 /* restart syscall */
59 #define EJUSTRETURN -2 /* don't modify regs, just return */
62 const char *scsi_sense_key_text[] =
82 #if !defined(SCSI_NO_OP_STRINGS)
100 * WARNING: You must update the num_ops field below for this quirk table
101 * entry if you add more entries.
103 static struct op_table_entry plextor_cd_ops[] = {
104 {0xD8, R, "CD-DA READ"}
107 static struct scsi_op_quirk_entry scsi_op_quirk_table[] = {
110 * I believe that 0xD8 is the Plextor proprietary command
111 * to read CD-DA data. I'm not sure which Plextor CDROM
112 * models support the command, though. I know for sure
113 * that the 4X, 8X, and 12X models do, and presumably the
114 * 12-20X does. I don't know about any earlier models,
115 * though. If anyone has any more complete information,
116 * feel free to change this quirk entry.
118 {T_CDROM, SIP_MEDIA_REMOVABLE, "PLEXTOR", "CD-ROM PX*", "*"},
119 1, /* number of vendor-specific opcodes for this entry */
124 static struct op_table_entry scsi_op_codes[] = {
126 * From: ftp://ftp.symbios.com/pub/standards/io/t10/drafts/spc/op-num.txt
127 * Modifications by Kenneth Merry (ken@FreeBSD.ORG)
129 * Note: order is important in this table, scsi_op_desc() currently
130 * depends on the opcodes in the table being in order to save search time.
135 * SCSI Operation Codes
136 * Numeric Sorted Listing
139 * D - DIRECT ACCESS DEVICE (SBC) device column key
140 * .T - SEQUENTIAL ACCESS DEVICE (SSC) -------------------
141 * . L - PRINTER DEVICE (SSC) M = Mandatory
142 * . P - PROCESSOR DEVICE (SPC) O = Optional
143 * . .W - WRITE ONCE READ MULTIPLE DEVICE (SBC) V = Vendor specific
144 * . . R - CD DEVICE (MMC) R = Reserved
145 * . . S - SCANNER DEVICE (SGC) Z = Obsolete
146 * . . .O - OPTICAL MEMORY DEVICE (SBC)
147 * . . . M - MEDIA CHANGER DEVICE (SMC)
148 * . . . C - COMMUNICATION DEVICE (SSC)
149 * . . . .A - STORAGE ARRAY DEVICE (SCC)
150 * . . . . E - ENCLOSURE SERVICES DEVICE (SES)
151 * OP DTLPWRSOMCAE Description
152 * -- ------------ ---------------------------------------------------- */
153 /* 00 MMMMMMMMMMMM TEST UNIT READY */
154 {0x00, ALL, "TEST UNIT READY"},
158 /* 01 Z V ZO ZO REZERO UNIT */
159 {0x01, D|L|W|O|M, "REZERO UNIT"},
163 /* 03 MMMMMMMMMMMM REQUEST SENSE */
164 {0x03, ALL, "REQUEST SENSE"},
166 /* 04 M O O FORMAT UNIT */
167 {0x04, D|R|O, "FORMAT UNIT"},
168 /* 04 O FORMAT MEDIUM */
169 {0x04, T, "FORMAT MEDIUM"},
173 /* 05 VMVVVV V READ BLOCK LIMITS */
174 {0x05, T, "READ BLOCK LIMITS"},
178 /* 07 OVV O OV REASSIGN BLOCKS */
179 {0x07, D|W|O, "REASSIGN BLOCKS"},
180 /* 07 O INITIALIZE ELEMENT STATUS */
181 {0x07, M, "INITIALIZE ELEMENT STATUS"},
183 /* 08 OMV OO OV READ(06) */
184 {0x08, D|T|W|R|O, "READ(06)"},
186 {0x08, P, "RECEIVE"},
187 /* 08 M GET MESSAGE(06) */
188 {0x08, C, "GET MESSAGE(06)"},
192 /* 0A OM O OV WRITE(06) */
193 {0x0A, D|T|W|O, "WRITE(06)"},
195 {0x0A, P, "SEND(06)"},
196 /* 0A M SEND MESSAGE(06) */
197 {0x0A, C, "SEND MESSAGE(06)"},
201 /* 0B Z ZO ZV SEEK(06) */
202 {0x0B, D|W|R|O, "SEEK(06)"},
203 /* 0B O SLEW AND PRINT */
204 {0x0B, L, "SLEW AND PRINT"},
209 /* 0F VOVVVV V READ REVERSE */
210 {0x0F, T, "READ REVERSE"},
212 /* 10 VM VVV WRITE FILEMARKS */
213 {0x10, T, "WRITE FILEMARKS"},
214 /* 10 O O SYNCHRONIZE BUFFER */
215 {0x10, L|W, "SYNCHRONIZE BUFFER"},
217 /* 11 VMVVVV SPACE */
220 /* 12 MMMMMMMMMMMM INQUIRY */
221 {0x12, ALL, "INQUIRY"},
223 /* 13 VOVVVV VERIFY(06) */
224 {0x13, T, "VERIFY(06)"},
226 /* 14 VOOVVV RECOVER BUFFERED DATA */
227 {0x14, T|L, "RECOVER BUFFERED DATA"},
229 /* 15 OMO OOOOOOOO MODE SELECT(06) */
230 {0x15, ALL & ~(P), "MODE SELECT(06)"},
232 /* 16 MMMOMMMM O RESERVE(06) */
233 {0x16, D|T|L|P|W|R|S|O|E, "RESERVE(06)"},
234 /* 16 M RESERVE ELEMENT(06) */
235 {0x16, M, "RESERVE ELEMENT(06)"},
237 /* 17 MMMOMMMM O RELEASE(06) */
238 {0x17, ALL & ~(M|C|A), "RELEASE(06)"},
239 /* 17 M RELEASE ELEMENT(06) */
240 {0x17, M, "RELEASE ELEMENT(06)"},
242 /* 18 OOOOOOOO COPY */
243 {0x18, ALL & ~(M|C|A|E), "COPY"},
245 /* 19 VMVVVV ERASE */
248 /* 1A OMO OOOOOOOO MODE SENSE(06) */
249 {0x1A, ALL & ~(P), "MODE SENSE(06)"},
251 /* 1B O OM O STOP START UNIT */
252 {0x1B, D|W|R|O, "STOP START UNIT"},
253 /* 1B O LOAD UNLOAD */
254 {0x1B, T, "LOAD UNLOAD"},
257 /* 1B O STOP PRINT */
258 {0x1B, L, "STOP PRINT"},
260 /* 1C OOOOOOOOOO M RECEIVE DIAGNOSTIC RESULTS */
261 {0x1C, ALL & ~(A), "RECEIVE DIAGNOSTIC RESULTS"},
263 /* 1D MMMMMMMMMMMM SEND DIAGNOSTIC */
264 {0x1D, ALL, "SEND DIAGNOSTIC"},
266 /* 1E OO OM OO PREVENT ALLOW MEDIUM REMOVAL */
267 {0x1E, D|T|W|R|O|M, "PREVENT ALLOW MEDIUM REMOVAL"},
275 /* 24 V VVM SET WINDOW */
276 {0x24, S, "SET WINDOW"},
278 /* 25 M M M READ CAPACITY */
279 {0x25, D|W|O, "READ CAPACITY"},
280 /* 25 M READ CD RECORDED CAPACITY */
281 {0x25, R, "READ CD RECORDED CAPACITY"},
282 /* 25 O GET WINDOW */
283 {0x25, S, "GET WINDOW"},
288 /* 28 M MMMM READ(10) */
289 {0x28, D|W|R|S|O, "READ(10)"},
290 /* 28 O GET MESSAGE(10) */
291 {0x28, C, "GET MESSAGE(10)"},
293 /* 29 V VV O READ GENERATION */
294 {0x29, O, "READ GENERATION"},
296 /* 2A M MM M WRITE(10) */
297 {0x2A, D|W|R|O, "WRITE(10)"},
299 {0x2A, S, "SEND(10)"},
300 /* 2A O SEND MESSAGE(10) */
301 {0x2A, C, "SEND MESSAGE(10)"},
303 /* 2B O OM O SEEK(10) */
304 {0x2B, D|W|R|O, "SEEK(10)"},
307 /* 2B O POSITION TO ELEMENT */
308 {0x2B, M, "POSITION TO ELEMENT"},
310 /* 2C V O ERASE(10) */
311 {0x2C, O, "ERASE(10)"},
313 /* 2D V O O READ UPDATED BLOCK */
314 {0x2D, W|O, "READ UPDATED BLOCK"},
316 /* 2E O O O WRITE AND VERIFY(10) */
317 {0x2E, D|W|O, "WRITE AND VERIFY(10)"},
319 /* 2F O OO O VERIFY(10) */
320 {0x2F, D|W|R|O, "VERIFY(10)"},
322 /* 30 Z ZO Z SEARCH DATA HIGH(10) */
323 {0x30, D|W|R|O, "SEARCH DATA HIGH(10)"},
325 /* 31 Z ZO Z SEARCH DATA EQUAL(10) */
326 {0x31, D|W|R|O, "SEARCH DATA EQUAL(10)"},
327 /* 31 O OBJECT POSITION */
328 {0x31, S, "OBJECT POSITION"},
330 /* 32 Z ZO Z SEARCH DATA LOW(10) */
331 {0x32, D|W|R|O, "SEARCH DATA LOW(10"},
333 /* 33 O OO O SET LIMITS(10) */
334 {0x33, D|W|R|O, "SET LIMITS(10)"},
336 /* 34 O OO O PRE-FETCH */
337 {0x34, D|W|R|O, "PRE-FETCH"},
338 /* 34 O READ POSITION */
339 {0x34, T, "READ POSITION"},
340 /* 34 O GET DATA BUFFER STATUS */
341 {0x34, S, "GET DATA BUFFER STATUS"},
343 /* 35 O OM O SYNCHRONIZE CACHE */
344 {0x35, D|W|R|O, "SYNCHRONIZE CACHE"},
346 /* 36 O OO O LOCK UNLOCK CACHE */
347 {0x36, D|W|R|O, "LOCK UNLOCK CACHE"},
349 /* 37 O O READ DEFECT DATA(10) */
350 {0x37, D|O, "READ DEFECT DATA(10)"},
352 /* 38 O O MEDIUM SCAN */
353 {0x38, W|O, "MEDIUM SCAN"},
355 /* 39 OOOOOOOO COMPARE */
356 {0x39, ALL & ~(M|C|A|E), "COMPARE"},
358 /* 3A OOOOOOOO COPY AND VERIFY */
359 {0x3A, ALL & ~(M|C|A|E), "COPY AND VERIFY"},
361 /* 3B OOOOOOOOOO O WRITE BUFFER */
362 {0x3B, ALL & ~(A), "WRITE BUFFER"},
364 /* 3C OOOOOOOOOO READ BUFFER */
365 {0x3C, ALL & ~(A|E),"READ BUFFER"},
367 /* 3D O O UPDATE BLOCK */
368 {0x3D, W|O, "UPDATE BLOCK"},
370 /* 3E O OO O READ LONG */
371 {0x3E, D|W|R|O, "READ LONG"},
373 /* 3F O O O WRITE LONG */
374 {0x3F, D|W|O, "WRITE LONG"},
376 /* 40 OOOOOOOOOO CHANGE DEFINITION */
377 {0x40, ALL & ~(A|E),"CHANGE DEFINITION"},
379 /* 41 O WRITE SAME */
380 {0x41, D, "WRITE SAME"},
382 /* 42 M READ SUB-CHANNEL */
383 {0x42, R, "READ SUB-CHANNEL"},
385 /* 43 M READ TOC/PMA/ATIP {MMC Proposed} */
386 {0x43, R, "READ TOC/PMA/ATIP {MMC Proposed}"},
388 /* 44 M REPORT DENSITY SUPPORT */
389 {0x44, T, "REPORT DENSITY SUPPORT"},
390 /* 44 M READ HEADER */
391 {0x44, R, "READ HEADER"},
393 /* 45 O PLAY AUDIO(10) */
394 {0x45, R, "PLAY AUDIO(10)"},
398 /* 47 O PLAY AUDIO MSF */
399 {0x47, R, "PLAY AUDIO MSF"},
401 /* 48 O PLAY AUDIO TRACK INDEX */
402 {0x48, R, "PLAY AUDIO TRACK INDEX"},
404 /* 49 O PLAY TRACK RELATIVE(10) */
405 {0x49, R, "PLAY TRACK RELATIVE(10)"},
409 /* 4B O PAUSE/RESUME */
410 {0x4B, R, "PAUSE/RESUME"},
412 /* 4C OOOOOOOOOOO LOG SELECT */
413 {0x4C, ALL & ~(E), "LOG SELECT"},
415 /* 4D OOOOOOOOOOO LOG SENSE */
416 {0x4D, ALL & ~(E), "LOG SENSE"},
418 /* 4E O STOP PLAY/SCAN {MMC Proposed} */
419 {0x4E, R, "STOP PLAY/SCAN {MMC Proposed}"},
423 /* 50 O XDWRITE(10) */
424 {0x50, D, "XDWRITE(10)"},
426 /* 51 O XPWRITE(10) */
427 {0x51, D, "XPWRITE(10)"},
428 /* 51 M READ DISC INFORMATION {MMC Proposed} */
429 {0x51, R, "READ DISC INFORMATION {MMC Proposed}"},
431 /* 52 O XDREAD(10) */
432 {0x52, D, "XDREAD(10)"},
433 /* 52 M READ TRACK INFORMATION {MMC Proposed} */
434 {0x52, R, "READ TRACK INFORMATION {MMC Proposed}"},
436 /* 53 M RESERVE TRACK {MMC Proposed} */
437 {0x53, R, "RESERVE TRACK {MMC Proposed}"},
439 /* 54 O SEND OPC INFORMATION {MMC Proposed} */
440 {0x54, R, "SEND OPC INFORMATION {MMC Proposed}"},
442 /* 55 OOO OOOOOOOO MODE SELECT(10) */
443 {0x55, ALL & ~(P), "MODE SELECT(10)"},
445 /* 56 MMMOMMMM O RESERVE(10) */
446 {0x56, ALL & ~(M|C|A), "RESERVE(10)"},
447 /* 56 M RESERVE ELEMENT(10) */
448 {0x56, M, "RESERVE ELEMENT(10)"},
450 /* 57 MMMOMMMM O RELEASE(10) */
451 {0x57, ALL & ~(M|C|A), "RELEASE(10"},
452 /* 57 M RELEASE ELEMENT(10) */
453 {0x57, M, "RELEASE ELEMENT(10)"},
455 /* 58 O REPAIR TRACK {MMC Proposed} */
456 {0x58, R, "REPAIR TRACK {MMC Proposed}"},
458 /* 59 O READ MASTER CUE {MMC Proposed} */
459 {0x59, R, "READ MASTER CUE {MMC Proposed}"},
461 /* 5A OOO OOOOOOOO MODE SENSE(10) */
462 {0x5A, ALL & ~(P), "MODE SENSE(10)"},
464 /* 5B M CLOSE TRACK/SESSION {MMC Proposed} */
465 {0x5B, R, "CLOSE TRACK/SESSION {MMC Proposed}"},
467 /* 5C O READ BUFFER CAPACITY {MMC Proposed} */
468 {0x5C, R, "READ BUFFER CAPACITY {MMC Proposed}"},
470 /* 5D O SEND CUE SHEET {MMC Proposed} */
471 {0x5D, R, "SEND CUE SHEET {MMC Proposed}"},
473 /* 5E OOOOOOOOO O PERSISTENT RESERVE IN */
474 {0x5E, ALL & ~(C|A),"PERSISTENT RESERVE IN"},
476 /* 5F OOOOOOOOO O PERSISTENT RESERVE OUT */
477 {0x5F, ALL & ~(C|A),"PERSISTENT RESERVE OUT"},
479 /* 80 O XDWRITE EXTENDED(16) */
480 {0x80, D, "XDWRITE EXTENDED(16)"},
482 /* 81 O REBUILD(16) */
483 {0x81, D, "REBUILD(16)"},
485 /* 82 O REGENERATE(16) */
486 {0x82, D, "REGENERATE(16)"},
518 /* A0 OOOOOOOOOOO REPORT LUNS */
519 {0xA0, ALL & ~(E), "REPORT LUNS"},
521 /* A1 O BLANK {MMC Proposed} */
522 {0xA1, R, "BLANK {MMC Proposed}"},
524 /* A2 O WRITE CD MSF {MMC Proposed} */
525 {0xA2, R, "WRITE CD MSF {MMC Proposed}"},
527 /* A3 M MAINTENANCE (IN) */
528 {0xA3, A, "MAINTENANCE (IN)"},
530 /* A4 O MAINTENANCE (OUT) */
531 {0xA4, A, "MAINTENANCE (OUT)"},
533 /* A5 O M MOVE MEDIUM */
534 {0xA5, T|M, "MOVE MEDIUM"},
535 /* A5 O PLAY AUDIO(12) */
536 {0xA5, R, "PLAY AUDIO(12)"},
538 /* A6 O EXCHANGE MEDIUM */
539 {0xA6, M, "EXCHANGE MEDIUM"},
540 /* A6 O LOAD/UNLOAD CD {MMC Proposed} */
541 {0xA6, R, "LOAD/UNLOAD CD {MMC Proposed}"},
543 /* A7 OO OO OO MOVE MEDIUM ATTACHED */
544 {0xA7, D|T|W|R|O|M, "MOVE MEDIUM ATTACHED"},
546 /* A8 OM O READ(12) */
547 {0xA8, W|R|O, "READ(12)"},
548 /* A8 O GET MESSAGE(12) */
549 {0xA8, C, "GET MESSAGE(12)"},
551 /* A9 O PLAY TRACK RELATIVE(12) */
552 {0xA9, R, "PLAY TRACK RELATIVE(12)"},
554 /* AA O O WRITE(12) */
555 {0xAA, W|O, "WRITE(12)"},
556 /* AA O WRITE CD(12) {MMC Proposed} */
557 {0xAA, R, "WRITE CD(12) {MMC Proposed}"},
558 /* AA O SEND MESSAGE(12) */
559 {0xAA, C, "SEND MESSAGE(12)"},
564 {0xAC, O, "ERASE(12)"},
568 /* AE O O WRITE AND VERIFY(12) */
569 {0xAE, W|O, "WRITE AND VERIFY(12)"},
571 /* AF OO O VERIFY(12) */
572 {0xAF, W|R|O, "VERIFY(12)"},
574 /* B0 ZO Z SEARCH DATA HIGH(12) */
575 {0xB0, W|R|O, "SEARCH DATA HIGH(12)"},
577 /* B1 ZO Z SEARCH DATA EQUAL(12) */
578 {0xB1, W|R|O, "SEARCH DATA EQUAL(12)"},
580 /* B2 ZO Z SEARCH DATA LOW(12) */
581 {0xB2, W|R|O, "SEARCH DATA LOW(12)"},
583 /* B3 OO O SET LIMITS(12) */
584 {0xB3, W|R|O, "SET LIMITS(12)"},
586 /* B4 OO OO OO READ ELEMENT STATUS ATTACHED */
587 {0xB4, D|T|W|R|O|M, "READ ELEMENT STATUS ATTACHED"},
589 /* B5 O REQUEST VOLUME ELEMENT ADDRESS */
590 {0xB5, M, "REQUEST VOLUME ELEMENT ADDRESS"},
592 /* B6 O SEND VOLUME TAG */
593 {0xB6, M, "SEND VOLUME TAG"},
595 /* B7 O READ DEFECT DATA(12) */
596 {0xB7, O, "READ DEFECT DATA(12)"},
598 /* B8 O M READ ELEMENT STATUS */
599 {0xB8, T|M, "READ ELEMENT STATUS"},
600 /* B8 O SET CD SPEED {MMC Proposed} */
601 {0xB8, R, "SET CD SPEED {MMC Proposed}"},
603 /* B9 M READ CD MSF {MMC Proposed} */
604 {0xB9, R, "READ CD MSF {MMC Proposed}"},
606 /* BA O SCAN {MMC Proposed} */
607 {0xBA, R, "SCAN {MMC Proposed}"},
608 /* BA M REDUNDANCY GROUP (IN) */
609 {0xBA, A, "REDUNDANCY GROUP (IN)"},
611 /* BB O SET CD-ROM SPEED {proposed} */
612 {0xBB, R, "SET CD-ROM SPEED {proposed}"},
613 /* BB O REDUNDANCY GROUP (OUT) */
614 {0xBB, A, "REDUNDANCY GROUP (OUT)"},
616 /* BC O PLAY CD {MMC Proposed} */
617 {0xBC, R, "PLAY CD {MMC Proposed}"},
618 /* BC M SPARE (IN) */
619 {0xBC, A, "SPARE (IN)"},
621 /* BD M MECHANISM STATUS {MMC Proposed} */
622 {0xBD, R, "MECHANISM STATUS {MMC Proposed}"},
623 /* BD O SPARE (OUT) */
624 {0xBD, A, "SPARE (OUT)"},
626 /* BE O READ CD {MMC Proposed} */
627 {0xBE, R, "READ CD {MMC Proposed}"},
628 /* BE M VOLUME SET (IN) */
629 {0xBE, A, "VOLUME SET (IN)"},
631 /* BF O VOLUME SET (OUT) */
632 {0xBF, A, "VOLUME SET (OUT)"}
636 scsi_op_desc(u_int16_t opcode, struct scsi_inquiry_data *inq_data)
643 struct op_table_entry *table[2];
646 pd_type = SID_TYPE(inq_data);
648 match = cam_quirkmatch((caddr_t)inq_data,
649 (caddr_t)scsi_op_quirk_table,
650 sizeof(scsi_op_quirk_table)/
651 sizeof(*scsi_op_quirk_table),
652 sizeof(*scsi_op_quirk_table),
656 table[0] = ((struct scsi_op_quirk_entry *)match)->op_table;
657 num_ops[0] = ((struct scsi_op_quirk_entry *)match)->num_ops;
658 table[1] = scsi_op_codes;
659 num_ops[1] = sizeof(scsi_op_codes)/sizeof(scsi_op_codes[0]);
663 * If this is true, we have a vendor specific opcode that
664 * wasn't covered in the quirk table.
666 if ((opcode > 0xBF) || ((opcode > 0x5F) && (opcode < 0x80)))
667 return("Vendor Specific Command");
669 table[0] = scsi_op_codes;
670 num_ops[0] = sizeof(scsi_op_codes)/sizeof(scsi_op_codes[0]);
674 /* RBC is 'Simplified' Direct Access Device */
675 if (pd_type == T_RBC)
678 opmask = 1 << pd_type;
680 for (j = 0; j < num_tables; j++) {
681 for (i = 0;i < num_ops[j] && table[j][i].opcode <= opcode; i++){
682 if ((table[j][i].opcode == opcode)
683 && ((table[j][i].opmask & opmask) != 0))
684 return(table[j][i].desc);
689 * If we can't find a match for the command in the table, we just
690 * assume it's a vendor specifc command.
692 return("Vendor Specific Command");
696 #else /* SCSI_NO_OP_STRINGS */
699 scsi_op_desc(u_int16_t opcode, struct scsi_inquiry_data *inq_data)
707 #include <sys/param.h>
710 #if !defined(SCSI_NO_SENSE_STRINGS)
711 #define SST(asc, ascq, action, desc) \
712 asc, ascq, action, desc
714 #define SST(asc, ascq, action, desc) \
718 static const char quantum[] = "QUANTUM";
721 * WARNING: You must update the num_ascs field below for this quirk table
722 * entry if you add more entries.
724 static struct asc_table_entry quantum_fireball_entries[] = {
725 {SST(0x04, 0x0b, SS_START|SSQ_DECREMENT_COUNT|ENXIO,
726 "Logical unit not ready, initializing cmd. required")}
729 static struct scsi_sense_quirk_entry asc_quirk_table[] = {
732 * The Quantum Fireball ST and SE like to return 0x04 0x0b when
733 * they really should return 0x04 0x02. 0x04,0x0b isn't
734 * defined in any SCSI spec, and it isn't mentioned in the
735 * hardware manual for these drives.
737 {T_DIRECT, SIP_MEDIA_FIXED, "QUANTUM", "FIREBALL S*", "*"},
738 1, /* number of vendor-specific sense codes for this entry */
739 quantum_fireball_entries
743 static struct asc_table_entry asc_text[] = {
745 * From File: ASC-NUM.TXT
746 * SCSI ASC/ASCQ Assignments
747 * Numeric Sorted Listing
750 * D - DIRECT ACCESS DEVICE (SBC) device column key
751 * .T - SEQUENTIAL ACCESS DEVICE (SSC) -------------------
752 * . L - PRINTER DEVICE (SSC) blank = reserved
753 * . P - PROCESSOR DEVICE (SPC) not blank = allowed
754 * . .W - WRITE ONCE READ MULTIPLE DEVICE (SBC)
755 * . . R - CD DEVICE (MMC)
756 * . . S - SCANNER DEVICE (SGC)
757 * . . .O - OPTICAL MEMORY DEVICE (SBC)
758 * . . . M - MEDIA CHANGER DEVICE (SMC)
759 * . . . C - COMMUNICATION DEVICE (SSC)
760 * . . . .A - STORAGE ARRAY DEVICE (SCC)
761 * . . . . E - ENCLOSURE SERVICES DEVICE (SES)
762 * DTLPWRSOMCAE ASC ASCQ Action Description
763 * ------------ ---- ---- ------ -----------------------------------*/
764 /* DTLPWRSOMCAE */{SST(0x00, 0x00, SS_NEPDEF,
765 "No additional sense information") },
766 /* T S */{SST(0x00, 0x01, SS_DEF,
767 "Filemark detected") },
768 /* T S */{SST(0x00, 0x02, SS_DEF,
769 "End-of-partition/medium detected") },
770 /* T */{SST(0x00, 0x03, SS_DEF,
771 "Setmark detected") },
772 /* T S */{SST(0x00, 0x04, SS_DEF,
773 "Beginning-of-partition/medium detected") },
774 /* T S */{SST(0x00, 0x05, SS_DEF,
775 "End-of-data detected") },
776 /* DTLPWRSOMCAE */{SST(0x00, 0x06, SS_DEF,
777 "I/O process terminated") },
778 /* R */{SST(0x00, 0x11, SS_NEDEF|EBUSY,
779 "Audio play operation in progress") },
780 /* R */{SST(0x00, 0x12, SS_NEDEF,
781 "Audio play operation paused") },
782 /* R */{SST(0x00, 0x13, SS_NEDEF,
783 "Audio play operation successfully completed") },
784 /* R */{SST(0x00, 0x14, SS_DEF,
785 "Audio play operation stopped due to error") },
786 /* R */{SST(0x00, 0x15, SS_DEF,
787 "No current audio status to return") },
788 /* DTLPWRSOMCAE */{SST(0x00, 0x16, SS_NEDEF|EBUSY,
789 "Operation in progress") },
790 /* DTL WRSOM AE */{SST(0x00, 0x17, SS_DEF,
791 "Cleaning requested") },
792 /* D W O */{SST(0x01, 0x00, SS_DEF,
793 "No index/sector signal") },
794 /* D WR OM */{SST(0x02, 0x00, SS_DEF,
795 "No seek complete") },
796 /* DTL W SO */{SST(0x03, 0x00, SS_DEF,
797 "Peripheral device write fault") },
798 /* T */{SST(0x03, 0x01, SS_DEF,
799 "No write current") },
800 /* T */{SST(0x03, 0x02, SS_DEF,
801 "Excessive write errors") },
802 /* DTLPWRSOMCAE */{SST(0x04, 0x00, SS_TUR|SSQ_MANY|SSQ_DECREMENT_COUNT|EIO,
803 "Logical unit not ready, cause not reportable") },
804 /* DTLPWRSOMCAE */{SST(0x04, 0x01, SS_TUR|SSQ_MANY|SSQ_DECREMENT_COUNT|EBUSY,
805 "Logical unit is in process of becoming ready") },
806 /* DTLPWRSOMCAE */{SST(0x04, 0x02, SS_START|SSQ_DECREMENT_COUNT|ENXIO,
807 "Logical unit not ready, initializing cmd. required") },
808 /* DTLPWRSOMCAE */{SST(0x04, 0x03, SS_NEDEF|ENXIO,
809 "Logical unit not ready, manual intervention required")},
810 /* DTL O */{SST(0x04, 0x04, SS_NEDEF|EBUSY,
811 "Logical unit not ready, format in progress") },
812 /* DT W OMCA */{SST(0x04, 0x05, SS_NEDEF|EBUSY,
813 "Logical unit not ready, rebuild in progress") },
814 /* DT W OMCA */{SST(0x04, 0x06, SS_NEDEF|EBUSY,
815 "Logical unit not ready, recalculation in progress") },
816 /* DTLPWRSOMCAE */{SST(0x04, 0x07, SS_NEDEF|EBUSY,
817 "Logical unit not ready, operation in progress") },
818 /* R */{SST(0x04, 0x08, SS_NEDEF|EBUSY,
819 "Logical unit not ready, long write in progress") },
820 /* DTL WRSOMCAE */{SST(0x05, 0x00, SS_DEF,
821 "Logical unit does not respond to selection") },
822 /* D WR OM */{SST(0x06, 0x00, SS_DEF,
823 "No reference position found") },
824 /* DTL WRSOM */{SST(0x07, 0x00, SS_DEF,
825 "Multiple peripheral devices selected") },
826 /* DTL WRSOMCAE */{SST(0x08, 0x00, SS_DEF,
827 "Logical unit communication failure") },
828 /* DTL WRSOMCAE */{SST(0x08, 0x01, SS_DEF,
829 "Logical unit communication time-out") },
830 /* DTL WRSOMCAE */{SST(0x08, 0x02, SS_DEF,
831 "Logical unit communication parity error") },
832 /* DT R OM */{SST(0x08, 0x03, SS_DEF,
833 "Logical unit communication crc error (ultra-dma/32)")},
834 /* DT WR O */{SST(0x09, 0x00, SS_DEF,
835 "Track following error") },
836 /* WR O */{SST(0x09, 0x01, SS_DEF,
837 "Tracking servo failure") },
838 /* WR O */{SST(0x09, 0x02, SS_DEF,
839 "Focus servo failure") },
840 /* WR O */{SST(0x09, 0x03, SS_DEF,
841 "Spindle servo failure") },
842 /* DT WR O */{SST(0x09, 0x04, SS_DEF,
843 "Head select fault") },
844 /* DTLPWRSOMCAE */{SST(0x0A, 0x00, SS_NEDEF|ENOSPC,
845 "Error log overflow") },
846 /* DTLPWRSOMCAE */{SST(0x0B, 0x00, SS_DEF,
848 /* DTLPWRSOMCAE */{SST(0x0B, 0x01, SS_DEF,
849 "Specified temperature exceeded") },
850 /* DTLPWRSOMCAE */{SST(0x0B, 0x02, SS_DEF,
851 "Enclosure degraded") },
852 /* T RS */{SST(0x0C, 0x00, SS_DEF,
854 /* D W O */{SST(0x0C, 0x01, SS_NEDEF,
855 "Write error - recovered with auto reallocation") },
856 /* D W O */{SST(0x0C, 0x02, SS_DEF,
857 "Write error - auto reallocation failed") },
858 /* D W O */{SST(0x0C, 0x03, SS_DEF,
859 "Write error - recommend reassignment") },
860 /* DT W O */{SST(0x0C, 0x04, SS_NEPDEF,
861 "Compression check miscompare error") },
862 /* DT W O */{SST(0x0C, 0x05, SS_DEF,
863 "Data expansion occurred during compression") },
864 /* DT W O */{SST(0x0C, 0x06, SS_DEF,
865 "Block not compressible") },
866 /* R */{SST(0x0C, 0x07, SS_DEF,
867 "Write error - recovery needed") },
868 /* R */{SST(0x0C, 0x08, SS_DEF,
869 "Write error - recovery failed") },
870 /* R */{SST(0x0C, 0x09, SS_DEF,
871 "Write error - loss of streaming") },
872 /* R */{SST(0x0C, 0x0A, SS_DEF,
873 "Write error - padding blocks added") },
874 /* D W O */{SST(0x10, 0x00, SS_DEF,
875 "ID CRC or ECC error") },
876 /* DT WRSO */{SST(0x11, 0x00, SS_DEF,
877 "Unrecovered read error") },
878 /* DT W SO */{SST(0x11, 0x01, SS_DEF,
879 "Read retries exhausted") },
880 /* DT W SO */{SST(0x11, 0x02, SS_DEF,
881 "Error too long to correct") },
882 /* DT W SO */{SST(0x11, 0x03, SS_DEF,
883 "Multiple read errors") },
884 /* D W O */{SST(0x11, 0x04, SS_DEF,
885 "Unrecovered read error - auto reallocate failed") },
886 /* WR O */{SST(0x11, 0x05, SS_DEF,
887 "L-EC uncorrectable error") },
888 /* WR O */{SST(0x11, 0x06, SS_DEF,
889 "CIRC unrecovered error") },
890 /* W O */{SST(0x11, 0x07, SS_DEF,
891 "Data re-synchronization error") },
892 /* T */{SST(0x11, 0x08, SS_DEF,
893 "Incomplete block read") },
894 /* T */{SST(0x11, 0x09, SS_DEF,
896 /* DT O */{SST(0x11, 0x0A, SS_DEF,
897 "Miscorrected error") },
898 /* D W O */{SST(0x11, 0x0B, SS_DEF,
899 "Unrecovered read error - recommend reassignment") },
900 /* D W O */{SST(0x11, 0x0C, SS_DEF,
901 "Unrecovered read error - recommend rewrite the data")},
902 /* DT WR O */{SST(0x11, 0x0D, SS_DEF,
903 "De-compression CRC error") },
904 /* DT WR O */{SST(0x11, 0x0E, SS_DEF,
905 "Cannot decompress using declared algorithm") },
906 /* R */{SST(0x11, 0x0F, SS_DEF,
907 "Error reading UPC/EAN number") },
908 /* R */{SST(0x11, 0x10, SS_DEF,
909 "Error reading ISRC number") },
910 /* R */{SST(0x11, 0x11, SS_DEF,
911 "Read error - loss of streaming") },
912 /* D W O */{SST(0x12, 0x00, SS_DEF,
913 "Address mark not found for id field") },
914 /* D W O */{SST(0x13, 0x00, SS_DEF,
915 "Address mark not found for data field") },
916 /* DTL WRSO */{SST(0x14, 0x00, SS_DEF,
917 "Recorded entity not found") },
918 /* DT WR O */{SST(0x14, 0x01, SS_DEF,
919 "Record not found") },
920 /* T */{SST(0x14, 0x02, SS_DEF,
921 "Filemark or setmark not found") },
922 /* T */{SST(0x14, 0x03, SS_DEF,
923 "End-of-data not found") },
924 /* T */{SST(0x14, 0x04, SS_DEF,
925 "Block sequence error") },
926 /* DT W O */{SST(0x14, 0x05, SS_DEF,
927 "Record not found - recommend reassignment") },
928 /* DT W O */{SST(0x14, 0x06, SS_DEF,
929 "Record not found - data auto-reallocated") },
930 /* DTL WRSOM */{SST(0x15, 0x00, SS_DEF,
931 "Random positioning error") },
932 /* DTL WRSOM */{SST(0x15, 0x01, SS_DEF,
933 "Mechanical positioning error") },
934 /* DT WR O */{SST(0x15, 0x02, SS_DEF,
935 "Positioning error detected by read of medium") },
936 /* D W O */{SST(0x16, 0x00, SS_DEF,
937 "Data synchronization mark error") },
938 /* D W O */{SST(0x16, 0x01, SS_DEF,
939 "Data sync error - data rewritten") },
940 /* D W O */{SST(0x16, 0x02, SS_DEF,
941 "Data sync error - recommend rewrite") },
942 /* D W O */{SST(0x16, 0x03, SS_NEDEF,
943 "Data sync error - data auto-reallocated") },
944 /* D W O */{SST(0x16, 0x04, SS_DEF,
945 "Data sync error - recommend reassignment") },
946 /* DT WRSO */{SST(0x17, 0x00, SS_NEDEF,
947 "Recovered data with no error correction applied") },
948 /* DT WRSO */{SST(0x17, 0x01, SS_NEDEF,
949 "Recovered data with retries") },
950 /* DT WR O */{SST(0x17, 0x02, SS_NEDEF,
951 "Recovered data with positive head offset") },
952 /* DT WR O */{SST(0x17, 0x03, SS_NEDEF,
953 "Recovered data with negative head offset") },
954 /* WR O */{SST(0x17, 0x04, SS_NEDEF,
955 "Recovered data with retries and/or CIRC applied") },
956 /* D WR O */{SST(0x17, 0x05, SS_NEDEF,
957 "Recovered data using previous sector id") },
958 /* D W O */{SST(0x17, 0x06, SS_NEDEF,
959 "Recovered data without ECC - data auto-reallocated") },
960 /* D W O */{SST(0x17, 0x07, SS_NEDEF,
961 "Recovered data without ECC - recommend reassignment")},
962 /* D W O */{SST(0x17, 0x08, SS_NEDEF,
963 "Recovered data without ECC - recommend rewrite") },
964 /* D W O */{SST(0x17, 0x09, SS_NEDEF,
965 "Recovered data without ECC - data rewritten") },
966 /* D W O */{SST(0x18, 0x00, SS_NEDEF,
967 "Recovered data with error correction applied") },
968 /* D WR O */{SST(0x18, 0x01, SS_NEDEF,
969 "Recovered data with error corr. & retries applied") },
970 /* D WR O */{SST(0x18, 0x02, SS_NEDEF,
971 "Recovered data - data auto-reallocated") },
972 /* R */{SST(0x18, 0x03, SS_NEDEF,
973 "Recovered data with CIRC") },
974 /* R */{SST(0x18, 0x04, SS_NEDEF,
975 "Recovered data with L-EC") },
976 /* D WR O */{SST(0x18, 0x05, SS_NEDEF,
977 "Recovered data - recommend reassignment") },
978 /* D WR O */{SST(0x18, 0x06, SS_NEDEF,
979 "Recovered data - recommend rewrite") },
980 /* D W O */{SST(0x18, 0x07, SS_NEDEF,
981 "Recovered data with ECC - data rewritten") },
982 /* D O */{SST(0x19, 0x00, SS_DEF,
983 "Defect list error") },
984 /* D O */{SST(0x19, 0x01, SS_DEF,
985 "Defect list not available") },
986 /* D O */{SST(0x19, 0x02, SS_DEF,
987 "Defect list error in primary list") },
988 /* D O */{SST(0x19, 0x03, SS_DEF,
989 "Defect list error in grown list") },
990 /* DTLPWRSOMCAE */{SST(0x1A, 0x00, SS_DEF,
991 "Parameter list length error") },
992 /* DTLPWRSOMCAE */{SST(0x1B, 0x00, SS_DEF,
993 "Synchronous data transfer error") },
994 /* D O */{SST(0x1C, 0x00, SS_DEF,
995 "Defect list not found") },
996 /* D O */{SST(0x1C, 0x01, SS_DEF,
997 "Primary defect list not found") },
998 /* D O */{SST(0x1C, 0x02, SS_DEF,
999 "Grown defect list not found") },
1000 /* D W O */{SST(0x1D, 0x00, SS_NEPDEF,
1001 "Miscompare during verify operation" )},
1002 /* D W O */{SST(0x1E, 0x00, SS_NEDEF,
1003 "Recovered id with ecc correction") },
1004 /* D O */{SST(0x1F, 0x00, SS_DEF,
1005 "Partial defect list transfer") },
1006 /* DTLPWRSOMCAE */{SST(0x20, 0x00, SS_DEF,
1007 "Invalid command operation code") },
1008 /* DT WR OM */{SST(0x21, 0x00, SS_DEF,
1009 "Logical block address out of range" )},
1010 /* DT WR OM */{SST(0x21, 0x01, SS_DEF,
1011 "Invalid element address") },
1012 /* D */{SST(0x22, 0x00, SS_DEF,
1013 "Illegal function") }, /* Deprecated. Use 20 00, 24 00, or 26 00 instead */
1014 /* DTLPWRSOMCAE */{SST(0x24, 0x00, SS_NEDEF|EINVAL,
1015 "Invalid field in CDB") },
1016 /* DTLPWRSOMCAE */{SST(0x25, 0x00, SS_NEDEF|ENXIO,
1017 "Logical unit not supported") },
1018 /* DTLPWRSOMCAE */{SST(0x26, 0x00, SS_NEDEF|EINVAL,
1019 "Invalid field in parameter list") },
1020 /* DTLPWRSOMCAE */{SST(0x26, 0x01, SS_NEDEF|EINVAL,
1021 "Parameter not supported") },
1022 /* DTLPWRSOMCAE */{SST(0x26, 0x02, SS_NEDEF|EINVAL,
1023 "Parameter value invalid") },
1024 /* DTLPWRSOMCAE */{SST(0x26, 0x03, SS_DEF,
1025 "Threshold parameters not supported") },
1026 /* DTLPWRSOMCAE */{SST(0x26, 0x04, SS_DEF,
1027 "Invalid release of active persistent reservation") },
1028 /* DT W O */{SST(0x27, 0x00, SS_NEDEF|EACCES,
1029 "Write protected") },
1030 /* DT W O */{SST(0x27, 0x01, SS_NEDEF|EACCES,
1031 "Hardware write protected") },
1032 /* DT W O */{SST(0x27, 0x02, SS_NEDEF|EACCES,
1033 "Logical unit software write protected") },
1034 /* T */{SST(0x27, 0x03, SS_NEDEF|EACCES,
1035 "Associated write protect") },
1036 /* T */{SST(0x27, 0x04, SS_NEDEF|EACCES,
1037 "Persistent write protect") },
1038 /* T */{SST(0x27, 0x05, SS_NEDEF|EACCES,
1039 "Permanent write protect") },
1040 /* DTLPWRSOMCAE */{SST(0x28, 0x00, SS_NEDEF|ENXIO,
1041 "Not ready to ready change, medium may have changed") },
1042 /* DT WR OM */{SST(0x28, 0x01, SS_DEF,
1043 "Import or export element accessed") },
1044 /* DTLPWRSOMCAE */{SST(0x29, 0x00, SS_NEDEF|ENXIO,
1045 "Power on, reset, or bus device reset occurred") },
1046 /* DTLPWRSOMCAE */{SST(0x29, 0x01, SS_DEF,
1047 "Power on occurred") },
1048 /* DTLPWRSOMCAE */{SST(0x29, 0x02, SS_DEF,
1049 "Scsi bus reset occurred") },
1050 /* DTLPWRSOMCAE */{SST(0x29, 0x03, SS_DEF,
1051 "Bus device reset function occurred") },
1052 /* DTLPWRSOMCAE */{SST(0x29, 0x04, SS_DEF,
1053 "Device internal reset") },
1054 /* DTLPWRSOMCAE */{SST(0x29, 0x05, SS_DEF,
1055 "Transceiver mode changed to single-ended") },
1056 /* DTLPWRSOMCAE */{SST(0x29, 0x06, SS_DEF,
1057 "Transceiver mode changed to LVD") },
1058 /* DTL WRSOMCAE */{SST(0x2A, 0x00, SS_DEF,
1059 "Parameters changed") },
1060 /* DTL WRSOMCAE */{SST(0x2A, 0x01, SS_DEF,
1061 "Mode parameters changed") },
1062 /* DTL WRSOMCAE */{SST(0x2A, 0x02, SS_DEF,
1063 "Log parameters changed") },
1064 /* DTLPWRSOMCAE */{SST(0x2A, 0x03, SS_DEF,
1065 "Reservations preempted") },
1066 /* DTLPWRSO C */{SST(0x2B, 0x00, SS_DEF,
1067 "Copy cannot execute since host cannot disconnect") },
1068 /* DTLPWRSOMCAE */{SST(0x2C, 0x00, SS_DEF,
1069 "Command sequence error") },
1070 /* S */{SST(0x2C, 0x01, SS_DEF,
1071 "Too many windows specified") },
1072 /* S */{SST(0x2C, 0x02, SS_DEF,
1073 "Invalid combination of windows specified") },
1074 /* R */{SST(0x2C, 0x03, SS_DEF,
1075 "Current program area is not empty") },
1076 /* R */{SST(0x2C, 0x04, SS_DEF,
1077 "Current program area is empty") },
1078 /* T */{SST(0x2D, 0x00, SS_DEF,
1079 "Overwrite error on update in place") },
1080 /* DTLPWRSOMCAE */{SST(0x2F, 0x00, SS_DEF,
1081 "Commands cleared by another initiator") },
1082 /* DT WR OM */{SST(0x30, 0x00, SS_DEF,
1083 "Incompatible medium installed") },
1084 /* DT WR O */{SST(0x30, 0x01, SS_DEF,
1085 "Cannot read medium - unknown format") },
1086 /* DT WR O */{SST(0x30, 0x02, SS_DEF,
1087 "Cannot read medium - incompatible format") },
1088 /* DT */{SST(0x30, 0x03, SS_DEF,
1089 "Cleaning cartridge installed") },
1090 /* DT WR O */{SST(0x30, 0x04, SS_DEF,
1091 "Cannot write medium - unknown format") },
1092 /* DT WR O */{SST(0x30, 0x05, SS_DEF,
1093 "Cannot write medium - incompatible format") },
1094 /* DT W O */{SST(0x30, 0x06, SS_DEF,
1095 "Cannot format medium - incompatible medium") },
1096 /* DTL WRSOM AE */{SST(0x30, 0x07, SS_DEF,
1097 "Cleaning failure") },
1098 /* R */{SST(0x30, 0x08, SS_DEF,
1099 "Cannot write - application code mismatch") },
1100 /* R */{SST(0x30, 0x09, SS_DEF,
1101 "Current session not fixated for append") },
1102 /* DT WR O */{SST(0x31, 0x00, SS_DEF,
1103 "Medium format corrupted") },
1104 /* D L R O */{SST(0x31, 0x01, SS_DEF,
1105 "Format command failed") },
1106 /* D W O */{SST(0x32, 0x00, SS_DEF,
1107 "No defect spare location available") },
1108 /* D W O */{SST(0x32, 0x01, SS_DEF,
1109 "Defect list update failure") },
1110 /* T */{SST(0x33, 0x00, SS_DEF,
1111 "Tape length error") },
1112 /* DTLPWRSOMCAE */{SST(0x34, 0x00, SS_DEF,
1113 "Enclosure failure") },
1114 /* DTLPWRSOMCAE */{SST(0x35, 0x00, SS_DEF,
1115 "Enclosure services failure") },
1116 /* DTLPWRSOMCAE */{SST(0x35, 0x01, SS_DEF,
1117 "Unsupported enclosure function") },
1118 /* DTLPWRSOMCAE */{SST(0x35, 0x02, SS_DEF,
1119 "Enclosure services unavailable") },
1120 /* DTLPWRSOMCAE */{SST(0x35, 0x03, SS_DEF,
1121 "Enclosure services transfer failure") },
1122 /* DTLPWRSOMCAE */{SST(0x35, 0x04, SS_DEF,
1123 "Enclosure services transfer refused") },
1124 /* L */{SST(0x36, 0x00, SS_DEF,
1125 "Ribbon, ink, or toner failure") },
1126 /* DTL WRSOMCAE */{SST(0x37, 0x00, SS_DEF,
1127 "Rounded parameter") },
1128 /* DTL WRSOMCAE */{SST(0x39, 0x00, SS_DEF,
1129 "Saving parameters not supported") },
1130 /* DTL WRSOM */{SST(0x3A, 0x00, SS_NEDEF|ENXIO,
1131 "Medium not present") },
1132 /* DT WR OM */{SST(0x3A, 0x01, SS_NEDEF|ENXIO,
1133 "Medium not present - tray closed") },
1134 /* DT WR OM */{SST(0x3A, 0x02, SS_NEDEF|ENXIO,
1135 "Medium not present - tray open") },
1136 /* TL */{SST(0x3B, 0x00, SS_DEF,
1137 "Sequential positioning error") },
1138 /* T */{SST(0x3B, 0x01, SS_DEF,
1139 "Tape position error at beginning-of-medium") },
1140 /* T */{SST(0x3B, 0x02, SS_DEF,
1141 "Tape position error at end-of-medium") },
1142 /* L */{SST(0x3B, 0x03, SS_DEF,
1143 "Tape or electronic vertical forms unit not ready") },
1144 /* L */{SST(0x3B, 0x04, SS_DEF,
1146 /* L */{SST(0x3B, 0x05, SS_DEF,
1148 /* L */{SST(0x3B, 0x06, SS_DEF,
1149 "Failed to sense top-of-form") },
1150 /* L */{SST(0x3B, 0x07, SS_DEF,
1151 "Failed to sense bottom-of-form") },
1152 /* T */{SST(0x3B, 0x08, SS_DEF,
1153 "Reposition error") },
1154 /* S */{SST(0x3B, 0x09, SS_DEF,
1155 "Read past end of medium") },
1156 /* S */{SST(0x3B, 0x0A, SS_DEF,
1157 "Read past beginning of medium") },
1158 /* S */{SST(0x3B, 0x0B, SS_DEF,
1159 "Position past end of medium") },
1160 /* T S */{SST(0x3B, 0x0C, SS_DEF,
1161 "Position past beginning of medium") },
1162 /* DT WR OM */{SST(0x3B, 0x0D, SS_NEDEF|ENOSPC,
1163 "Medium destination element full") },
1164 /* DT WR OM */{SST(0x3B, 0x0E, SS_DEF,
1165 "Medium source element empty") },
1166 /* R */{SST(0x3B, 0x0F, SS_DEF,
1167 "End of medium reached") },
1168 /* DT WR OM */{SST(0x3B, 0x11, SS_DEF,
1169 "Medium magazine not accessible") },
1170 /* DT WR OM */{SST(0x3B, 0x12, SS_DEF,
1171 "Medium magazine removed") },
1172 /* DT WR OM */{SST(0x3B, 0x13, SS_DEF,
1173 "Medium magazine inserted") },
1174 /* DT WR OM */{SST(0x3B, 0x14, SS_DEF,
1175 "Medium magazine locked") },
1176 /* DT WR OM */{SST(0x3B, 0x15, SS_DEF,
1177 "Medium magazine unlocked") },
1178 /* DTLPWRSOMCAE */{SST(0x3D, 0x00, SS_DEF,
1179 "Invalid bits in identify message") },
1180 /* DTLPWRSOMCAE */{SST(0x3E, 0x00, SS_DEF,
1181 "Logical unit has not self-configured yet") },
1182 /* DTLPWRSOMCAE */{SST(0x3E, 0x01, SS_DEF,
1183 "Logical unit failure") },
1184 /* DTLPWRSOMCAE */{SST(0x3E, 0x02, SS_DEF,
1185 "Timeout on logical unit") },
1186 /* DTLPWRSOMCAE */{SST(0x3F, 0x00, SS_DEF,
1187 "Target operating conditions have changed") },
1188 /* DTLPWRSOMCAE */{SST(0x3F, 0x01, SS_DEF,
1189 "Microcode has been changed") },
1190 /* DTLPWRSOMC */{SST(0x3F, 0x02, SS_DEF,
1191 "Changed operating definition") },
1192 /* DTLPWRSOMCAE */{SST(0x3F, 0x03, SS_DEF,
1193 "Inquiry data has changed") },
1194 /* DT WR OMCAE */{SST(0x3F, 0x04, SS_DEF,
1195 "Component device attached") },
1196 /* DT WR OMCAE */{SST(0x3F, 0x05, SS_DEF,
1197 "Device identifier changed") },
1198 /* DT WR OMCAE */{SST(0x3F, 0x06, SS_DEF,
1199 "Redundancy group created or modified") },
1200 /* DT WR OMCAE */{SST(0x3F, 0x07, SS_DEF,
1201 "Redundancy group deleted") },
1202 /* DT WR OMCAE */{SST(0x3F, 0x08, SS_DEF,
1203 "Spare created or modified") },
1204 /* DT WR OMCAE */{SST(0x3F, 0x09, SS_DEF,
1206 /* DT WR OMCAE */{SST(0x3F, 0x0A, SS_DEF,
1207 "Volume set created or modified") },
1208 /* DT WR OMCAE */{SST(0x3F, 0x0B, SS_DEF,
1209 "Volume set deleted") },
1210 /* DT WR OMCAE */{SST(0x3F, 0x0C, SS_DEF,
1211 "Volume set deassigned") },
1212 /* DT WR OMCAE */{SST(0x3F, 0x0D, SS_DEF,
1213 "Volume set reassigned") },
1214 /* D */{SST(0x40, 0x00, SS_DEF,
1215 "Ram failure") }, /* deprecated - use 40 NN instead */
1216 /* DTLPWRSOMCAE */{SST(0x40, 0x80, SS_DEF,
1217 "Diagnostic failure: ASCQ = Component ID") },
1218 /* DTLPWRSOMCAE */{SST(0x40, 0xFF, SS_DEF|SSQ_RANGE,
1219 NULL) },/* Range 0x80->0xFF */
1220 /* D */{SST(0x41, 0x00, SS_DEF,
1221 "Data path failure") }, /* deprecated - use 40 NN instead */
1222 /* D */{SST(0x42, 0x00, SS_DEF,
1223 "Power-on or self-test failure") }, /* deprecated - use 40 NN instead */
1224 /* DTLPWRSOMCAE */{SST(0x43, 0x00, SS_DEF,
1226 /* DTLPWRSOMCAE */{SST(0x44, 0x00, SS_DEF,
1227 "Internal target failure") },
1228 /* DTLPWRSOMCAE */{SST(0x45, 0x00, SS_DEF,
1229 "Select or reselect failure") },
1230 /* DTLPWRSOMC */{SST(0x46, 0x00, SS_DEF,
1231 "Unsuccessful soft reset") },
1232 /* DTLPWRSOMCAE */{SST(0x47, 0x00, SS_DEF,
1233 "SCSI parity error") },
1234 /* DTLPWRSOMCAE */{SST(0x48, 0x00, SS_DEF,
1235 "Initiator detected error message received") },
1236 /* DTLPWRSOMCAE */{SST(0x49, 0x00, SS_DEF,
1237 "Invalid message error") },
1238 /* DTLPWRSOMCAE */{SST(0x4A, 0x00, SS_DEF,
1239 "Command phase error") },
1240 /* DTLPWRSOMCAE */{SST(0x4B, 0x00, SS_DEF,
1241 "Data phase error") },
1242 /* DTLPWRSOMCAE */{SST(0x4C, 0x00, SS_DEF,
1243 "Logical unit failed self-configuration") },
1244 /* DTLPWRSOMCAE */{SST(0x4D, 0x00, SS_DEF,
1245 "Tagged overlapped commands: ASCQ = Queue tag ID") },
1246 /* DTLPWRSOMCAE */{SST(0x4D, 0xFF, SS_DEF|SSQ_RANGE,
1247 NULL)}, /* Range 0x00->0xFF */
1248 /* DTLPWRSOMCAE */{SST(0x4E, 0x00, SS_DEF,
1249 "Overlapped commands attempted") },
1250 /* T */{SST(0x50, 0x00, SS_DEF,
1251 "Write append error") },
1252 /* T */{SST(0x50, 0x01, SS_DEF,
1253 "Write append position error") },
1254 /* T */{SST(0x50, 0x02, SS_DEF,
1255 "Position error related to timing") },
1256 /* T O */{SST(0x51, 0x00, SS_DEF,
1258 /* T */{SST(0x52, 0x00, SS_DEF,
1259 "Cartridge fault") },
1260 /* DTL WRSOM */{SST(0x53, 0x00, SS_DEF,
1261 "Media load or eject failed") },
1262 /* T */{SST(0x53, 0x01, SS_DEF,
1263 "Unload tape failure") },
1264 /* DT WR OM */{SST(0x53, 0x02, SS_DEF,
1265 "Medium removal prevented") },
1266 /* P */{SST(0x54, 0x00, SS_DEF,
1267 "Scsi to host system interface failure") },
1268 /* P */{SST(0x55, 0x00, SS_DEF,
1269 "System resource failure") },
1270 /* D O */{SST(0x55, 0x01, SS_NEDEF|ENOSPC,
1271 "System buffer full") },
1272 /* R */{SST(0x57, 0x00, SS_DEF,
1273 "Unable to recover table-of-contents") },
1274 /* O */{SST(0x58, 0x00, SS_DEF,
1275 "Generation does not exist") },
1276 /* O */{SST(0x59, 0x00, SS_DEF,
1277 "Updated block read") },
1278 /* DTLPWRSOM */{SST(0x5A, 0x00, SS_DEF,
1279 "Operator request or state change input") },
1280 /* DT WR OM */{SST(0x5A, 0x01, SS_DEF,
1281 "Operator medium removal request") },
1282 /* DT W O */{SST(0x5A, 0x02, SS_DEF,
1283 "Operator selected write protect") },
1284 /* DT W O */{SST(0x5A, 0x03, SS_DEF,
1285 "Operator selected write permit") },
1286 /* DTLPWRSOM */{SST(0x5B, 0x00, SS_DEF,
1288 /* DTLPWRSOM */{SST(0x5B, 0x01, SS_DEF,
1289 "Threshold condition met") },
1290 /* DTLPWRSOM */{SST(0x5B, 0x02, SS_DEF,
1291 "Log counter at maximum") },
1292 /* DTLPWRSOM */{SST(0x5B, 0x03, SS_DEF,
1293 "Log list codes exhausted") },
1294 /* D O */{SST(0x5C, 0x00, SS_DEF,
1295 "RPL status change") },
1296 /* D O */{SST(0x5C, 0x01, SS_NEDEF,
1297 "Spindles synchronized") },
1298 /* D O */{SST(0x5C, 0x02, SS_DEF,
1299 "Spindles not synchronized") },
1300 /* DTLPWRSOMCAE */{SST(0x5D, 0x00, SS_DEF,
1301 "Failure prediction threshold exceeded") },
1302 /* DTLPWRSOMCAE */{SST(0x5D, 0xFF, SS_DEF,
1303 "Failure prediction threshold exceeded (false)") },
1304 /* DTLPWRSO CA */{SST(0x5E, 0x00, SS_DEF,
1305 "Low power condition on") },
1306 /* DTLPWRSO CA */{SST(0x5E, 0x01, SS_DEF,
1307 "Idle condition activated by timer") },
1308 /* DTLPWRSO CA */{SST(0x5E, 0x02, SS_DEF,
1309 "Standby condition activated by timer") },
1310 /* DTLPWRSO CA */{SST(0x5E, 0x03, SS_DEF,
1311 "Idle condition activated by command") },
1312 /* DTLPWRSO CA */{SST(0x5E, 0x04, SS_DEF,
1313 "Standby condition activated by command") },
1314 /* S */{SST(0x60, 0x00, SS_DEF,
1316 /* S */{SST(0x61, 0x00, SS_DEF,
1317 "Video acquisition error") },
1318 /* S */{SST(0x61, 0x01, SS_DEF,
1319 "Unable to acquire video") },
1320 /* S */{SST(0x61, 0x02, SS_DEF,
1322 /* S */{SST(0x62, 0x00, SS_DEF,
1323 "Scan head positioning error") },
1324 /* R */{SST(0x63, 0x00, SS_DEF,
1325 "End of user area encountered on this track") },
1326 /* R */{SST(0x63, 0x01, SS_NEDEF|ENOSPC,
1327 "Packet does not fit in available space") },
1328 /* R */{SST(0x64, 0x00, SS_DEF,
1329 "Illegal mode for this track") },
1330 /* R */{SST(0x64, 0x01, SS_DEF,
1331 "Invalid packet size") },
1332 /* DTLPWRSOMCAE */{SST(0x65, 0x00, SS_DEF,
1334 /* S */{SST(0x66, 0x00, SS_DEF,
1335 "Automatic document feeder cover up") },
1336 /* S */{SST(0x66, 0x01, SS_DEF,
1337 "Automatic document feeder lift up") },
1338 /* S */{SST(0x66, 0x02, SS_DEF,
1339 "Document jam in automatic document feeder") },
1340 /* S */{SST(0x66, 0x03, SS_DEF,
1341 "Document miss feed automatic in document feeder") },
1342 /* A */{SST(0x67, 0x00, SS_DEF,
1343 "Configuration failure") },
1344 /* A */{SST(0x67, 0x01, SS_DEF,
1345 "Configuration of incapable logical units failed") },
1346 /* A */{SST(0x67, 0x02, SS_DEF,
1347 "Add logical unit failed") },
1348 /* A */{SST(0x67, 0x03, SS_DEF,
1349 "Modification of logical unit failed") },
1350 /* A */{SST(0x67, 0x04, SS_DEF,
1351 "Exchange of logical unit failed") },
1352 /* A */{SST(0x67, 0x05, SS_DEF,
1353 "Remove of logical unit failed") },
1354 /* A */{SST(0x67, 0x06, SS_DEF,
1355 "Attachment of logical unit failed") },
1356 /* A */{SST(0x67, 0x07, SS_DEF,
1357 "Creation of logical unit failed") },
1358 /* A */{SST(0x68, 0x00, SS_DEF,
1359 "Logical unit not configured") },
1360 /* A */{SST(0x69, 0x00, SS_DEF,
1361 "Data loss on logical unit") },
1362 /* A */{SST(0x69, 0x01, SS_DEF,
1363 "Multiple logical unit failures") },
1364 /* A */{SST(0x69, 0x02, SS_DEF,
1365 "Parity/data mismatch") },
1366 /* A */{SST(0x6A, 0x00, SS_DEF,
1367 "Informational, refer to log") },
1368 /* A */{SST(0x6B, 0x00, SS_DEF,
1369 "State change has occurred") },
1370 /* A */{SST(0x6B, 0x01, SS_DEF,
1371 "Redundancy level got better") },
1372 /* A */{SST(0x6B, 0x02, SS_DEF,
1373 "Redundancy level got worse") },
1374 /* A */{SST(0x6C, 0x00, SS_DEF,
1375 "Rebuild failure occurred") },
1376 /* A */{SST(0x6D, 0x00, SS_DEF,
1377 "Recalculate failure occurred") },
1378 /* A */{SST(0x6E, 0x00, SS_DEF,
1379 "Command to logical unit failed") },
1380 /* T */{SST(0x70, 0x00, SS_DEF,
1381 "Decompression exception short: ASCQ = Algorithm ID") },
1382 /* T */{SST(0x70, 0xFF, SS_DEF|SSQ_RANGE,
1383 NULL) }, /* Range 0x00 -> 0xFF */
1384 /* T */{SST(0x71, 0x00, SS_DEF,
1385 "Decompression exception long: ASCQ = Algorithm ID") },
1386 /* T */{SST(0x71, 0xFF, SS_DEF|SSQ_RANGE,
1387 NULL) }, /* Range 0x00 -> 0xFF */
1388 /* R */{SST(0x72, 0x00, SS_DEF,
1389 "Session fixation error") },
1390 /* R */{SST(0x72, 0x01, SS_DEF,
1391 "Session fixation error writing lead-in") },
1392 /* R */{SST(0x72, 0x02, SS_DEF,
1393 "Session fixation error writing lead-out") },
1394 /* R */{SST(0x72, 0x03, SS_DEF,
1395 "Session fixation error - incomplete track in session") },
1396 /* R */{SST(0x72, 0x04, SS_DEF,
1397 "Empty or partially written reserved track") },
1398 /* R */{SST(0x73, 0x00, SS_DEF,
1399 "CD control error") },
1400 /* R */{SST(0x73, 0x01, SS_DEF,
1401 "Power calibration area almost full") },
1402 /* R */{SST(0x73, 0x02, SS_NEDEF|ENOSPC,
1403 "Power calibration area is full") },
1404 /* R */{SST(0x73, 0x03, SS_DEF,
1405 "Power calibration area error") },
1406 /* R */{SST(0x73, 0x04, SS_DEF,
1407 "Program memory area update failure") },
1408 /* R */{SST(0x73, 0x05, SS_DEF,
1409 "program memory area is full") }
1412 #if !defined(SCSI_NO_SENSE_STRINGS)
1414 scsi_sense_desc(int asc, int ascq, struct scsi_inquiry_data *inq_data)
1418 struct asc_table_entry *table[2];
1422 if (inq_data == NULL)
1425 match = cam_quirkmatch((caddr_t)inq_data,
1426 (caddr_t)asc_quirk_table,
1427 sizeof(asc_quirk_table)/sizeof(*asc_quirk_table),
1428 sizeof(*asc_quirk_table), scsi_inquiry_match);
1430 if (match != NULL) {
1431 table[0] = ((struct scsi_sense_quirk_entry *)match)->asc_info;
1433 ((struct scsi_sense_quirk_entry *)match)->num_ascs;
1434 table[1] = asc_text;
1435 table_size[1] = sizeof(asc_text)/sizeof(asc_text[0]);
1438 table[0] = asc_text;
1439 table_size[0] = sizeof(asc_text)/sizeof(asc_text[0]);
1443 for (j = 0; j < num_tables; j++) {
1444 for (i = 0; i < table_size[j]; i++) {
1445 if (table[j][i].asc == asc) {
1447 /* Check for ranges */
1448 if ((table[j][i].action & SSQ_RANGE) != 0) {
1450 if (table[j][i].ascq >= ascq
1451 && table[j][i-1].ascq <= ascq)
1452 return table[j][i-1].desc;
1457 if (table[j][i].ascq == ascq)
1458 return table[j][i].desc;
1463 if (asc >= 0x80 && asc <= 0xff)
1464 return "Vendor Specific ASC";
1466 if (ascq >= 0x80 && ascq <= 0xff)
1467 return "Vendor Specific ASCQ";
1469 return "Reserved ASC/ASCQ pair";
1472 #else /* SCSI_NO_SENSE_STRINGS */
1474 scsi_sense_desc(int asc, int ascq, struct scsi_inquiry_data *inq_data)
1481 * Given a particular failed CCB and its device type information, return
1482 * the appropriate action from either the sense code quirk table or the
1486 scsi_error_action(int asc, int ascq, struct scsi_inquiry_data *inq_data)
1489 struct asc_table_entry *table[2];
1495 * If we don't have inquiry data, we can't match against any quirk
1498 if (inq_data != NULL) {
1499 match = cam_quirkmatch((caddr_t)inq_data,
1500 (caddr_t)asc_quirk_table,
1501 sizeof(asc_quirk_table) /
1502 sizeof(*asc_quirk_table),
1503 sizeof(*asc_quirk_table),
1504 scsi_inquiry_match);
1508 if (match != NULL) {
1509 table[0] = ((struct scsi_sense_quirk_entry *)match)->asc_info;
1511 ((struct scsi_sense_quirk_entry *)match)->num_ascs;
1512 table[1] = asc_text;
1513 table_size[1] = sizeof(asc_text)/sizeof(asc_text[0]);
1516 table[0] = asc_text;
1517 table_size[0] = sizeof(asc_text)/sizeof(asc_text[0]);
1521 for (j = 0; j < num_tables; j++) {
1522 for (i = 0; i < table_size[j]; i++) {
1523 if (table[j][i].asc == asc) {
1525 /* Check for ranges */
1526 if ((table[j][i].action & SSQ_RANGE) != 0){
1528 if (table[j][i].ascq >= ascq
1529 && table[j][i-1].ascq <= ascq)
1530 return table[j][i].action;
1536 * Check to see if we have a match. If the
1537 * current ascq in the table is greater
1538 * than our ascq, and there aren't any more
1539 * tables to search, just return the
1542 if (table[j][i].ascq == ascq)
1543 return(table[j][i].action);
1544 else if ((j == (num_tables - 1)) &&
1545 (table[j][i].ascq > ascq))
1551 * If we get to this point, it's most likely a vendor specific
1552 * ASC and we don't have a quirk entry for it. Oh well, we just
1553 * tell the error handling code to take the default action.
1559 scsi_cdb_string(u_int8_t *cdb_ptr, char *cdb_string, size_t len)
1564 if (cdb_ptr == NULL)
1567 /* Silence warnings */
1571 * This is taken from the SCSI-3 draft spec.
1572 * (T10/1157D revision 0.3)
1573 * The top 3 bits of an opcode are the group code. The next 5 bits
1574 * are the command code.
1575 * Group 0: six byte commands
1576 * Group 1: ten byte commands
1577 * Group 2: ten byte commands
1579 * Group 4: sixteen byte commands
1580 * Group 5: twelve byte commands
1581 * Group 6: vendor specific
1582 * Group 7: vendor specific
1584 switch((*cdb_ptr >> 5) & 0x7) {
1595 /* in this case, just print out the opcode */
1606 for (i = 0; i < cdb_len; i++)
1607 snprintf(cdb_string + strlen(cdb_string),
1608 len - strlen(cdb_string), "%x ", cdb_ptr[i]);
1613 * scsi_sense_print will decode the sense data into human
1614 * readable form. Sense handlers can use this to generate
1618 * Because scsi_sense_print() utilizes transport layer functions, it will
1619 * only work in the kernel.
1624 scsi_sense_print(struct ccb_scsiio *csio)
1626 struct scsi_sense_data *sense;
1631 struct ccb_getdev cgd;
1632 u_int8_t command_print;
1634 sense = &csio->sense_data;
1637 * If the CDB is a physical address, we can't deal with it..
1639 if ((csio->ccb_h.flags & CAM_CDB_PHYS) != 0)
1645 * Get the device information.
1647 xpt_setup_ccb(&cgd.ccb_h,
1650 cgd.ccb_h.func_code = XPT_GDEV_TYPE;
1651 xpt_action((union ccb *)&cgd);
1654 * If the device is unconfigured, just pretend that it is a hard
1655 * drive. scsi_op_desc() needs this.
1657 if (cgd.ccb_h.status == CAM_DEV_NOT_THERE)
1658 cgd.inq_data.device = T_DIRECT;
1660 if (command_print != 0) {
1661 char cdb_str[(SCSI_MAX_CDBLEN * 3) + 1];
1663 xpt_print_path(csio->ccb_h.path);
1665 if ((csio->ccb_h.flags & CAM_CDB_POINTER) != 0) {
1666 printf("%s. CDB: %s\n",
1667 scsi_op_desc(csio->cdb_io.cdb_ptr[0],
1669 scsi_cdb_string(csio->cdb_io.cdb_ptr, cdb_str,
1672 printf("%s. CDB: %s\n",
1673 scsi_op_desc(csio->cdb_io.cdb_bytes[0],
1674 &cgd.inq_data), scsi_cdb_string(
1675 csio->cdb_io.cdb_bytes, cdb_str,
1681 * If the sense data is a physical pointer, forget it.
1683 if (csio->ccb_h.flags & CAM_SENSE_PTR) {
1684 if (csio->ccb_h.flags & CAM_SENSE_PHYS)
1688 * XXX KDM this is stupid, but casting the
1689 * structure doesn't work...
1691 bcopy(&csio->sense_data, sense,
1692 sizeof(struct scsi_sense_data *));
1696 * If the physical sense flag is set, but the sense pointer
1697 * is not also set, we assume that the user is an idiot and
1698 * return. (Well, okay, it could be that somehow, the
1699 * entire csio is physical, but we would have probably core
1700 * dumped on one of the bogus pointer deferences above
1703 if (csio->ccb_h.flags & CAM_SENSE_PHYS)
1706 sense = &csio->sense_data;
1709 xpt_print_path(csio->ccb_h.path);
1710 error_code = sense->error_code & SSD_ERRCODE;
1711 sense_key = sense->flags & SSD_KEY;
1713 switch (error_code) {
1714 case SSD_DEFERRED_ERROR:
1715 printf("Deferred Error: ");
1717 case SSD_CURRENT_ERROR:
1719 printf("%s", scsi_sense_key_text[sense_key]);
1720 info = scsi_4btoul(sense->info);
1722 if (sense->error_code & SSD_ERRCODE_VALID) {
1724 switch (sense_key) {
1725 case SSD_KEY_NOT_READY:
1726 case SSD_KEY_ILLEGAL_REQUEST:
1727 case SSD_KEY_UNIT_ATTENTION:
1728 case SSD_KEY_DATA_PROTECT:
1730 case SSD_KEY_BLANK_CHECK:
1731 printf(" req sz: %d (decimal)",
1736 if (sense->flags & SSD_ILI) {
1737 printf(" ILI (length mismatch):"
1740 printf(" info:%x", info);
1745 printf(" info?:%x", info);
1747 if (sense->extra_len >= 4) {
1748 if (bcmp(sense->cmd_spec_info, "\0\0\0\0", 4)) {
1749 printf(" csi:%x,%x,%x,%x",
1750 sense->cmd_spec_info[0],
1751 sense->cmd_spec_info[1],
1752 sense->cmd_spec_info[2],
1753 sense->cmd_spec_info[3]);
1757 asc = (sense->extra_len >= 5) ? sense->add_sense_code : 0;
1758 ascq = (sense->extra_len >= 6) ? sense->add_sense_code_qual : 0;
1761 const char *desc = scsi_sense_desc(asc, ascq,
1763 printf(" asc:%x,%x\n", asc, ascq);
1765 xpt_print_path(csio->ccb_h.path);
1769 if (sense->extra_len >= 7 && sense->fru) {
1770 printf(" field replaceable unit: %x", sense->fru);
1773 if ((sense->extra_len >= 10)
1774 && (sense->sense_key_spec[0] & SSD_SCS_VALID) != 0) {
1775 printf(" sks:%x,%x", sense->sense_key_spec[0],
1776 scsi_2btoul(&sense->sense_key_spec[1]));
1781 printf("error code %d",
1782 sense->error_code & SSD_ERRCODE);
1783 if (sense->error_code & SSD_ERRCODE_VALID) {
1784 printf(" at block no. %d (decimal)",
1785 info = scsi_4btoul(sense->info));
1792 #else /* !_KERNEL */
1796 scsi_sense_string(struct cam_device *device, struct ccb_scsiio *csio,
1797 char *str, int str_len)
1799 struct scsi_sense_data *sense;
1804 u_int8_t command_print;
1807 int tmpstrlen = 2048;
1808 int cur_len = 0, tmplen = 0, retlen;
1810 if ((device == NULL) || (csio == NULL) || (str == NULL))
1817 * If the CDB is a physical address, we can't deal with it..
1819 if ((csio->ccb_h.flags & CAM_CDB_PHYS) != 0)
1824 cam_path_string(device, path_str, 64);
1830 if (command_print != 0) {
1831 char cdb_str[(SCSI_MAX_CDBLEN * 3) + 1];
1833 retlen = snprintf(tmpstr, tmpstrlen, "%s", path_str);
1835 if ((tmplen = str_len - cur_len - 1) < 0)
1838 strncat(str, tmpstr, tmplen);
1840 str[str_len - 1] = '\0';
1842 if ((csio->ccb_h.flags & CAM_CDB_POINTER) != 0) {
1843 retlen = snprintf(tmpstr, tmpstrlen, "%s. CDB: %s\n",
1844 scsi_op_desc(csio->cdb_io.cdb_ptr[0],
1846 scsi_cdb_string(csio->cdb_io.cdb_ptr,
1850 retlen = snprintf(tmpstr, tmpstrlen, "%s. CDB: %s\n",
1851 scsi_op_desc(csio->cdb_io.cdb_bytes[0],
1852 &device->inq_data), scsi_cdb_string(
1853 csio->cdb_io.cdb_bytes, cdb_str,
1857 if ((tmplen = str_len - cur_len - 1) < 0)
1860 strncat(str, tmpstr, tmplen);
1862 str[str_len - 1] = '\0';
1866 * If the sense data is a physical pointer, forget it.
1868 if (csio->ccb_h.flags & CAM_SENSE_PTR) {
1869 if (csio->ccb_h.flags & CAM_SENSE_PHYS)
1873 * XXX KDM this is stupid, but casting the
1874 * structure doesn't work...
1876 bcopy(&csio->sense_data, sense,
1877 sizeof(struct scsi_sense_data *));
1881 * If the physical sense flag is set, but the sense pointer
1882 * is not also set, we assume that the user is an idiot and
1883 * return. (Well, okay, it could be that somehow, the
1884 * entire csio is physical, but we would have probably core
1885 * dumped on one of the bogus pointer deferences above
1888 if (csio->ccb_h.flags & CAM_SENSE_PHYS)
1891 sense = &csio->sense_data;
1895 retlen = snprintf(tmpstr, tmpstrlen, "%s", path_str);
1897 if ((tmplen = str_len - cur_len - 1) < 0)
1900 strncat(str, tmpstr, tmplen);
1902 str[str_len - 1] = '\0';
1904 error_code = sense->error_code & SSD_ERRCODE;
1905 sense_key = sense->flags & SSD_KEY;
1907 switch (error_code) {
1908 case SSD_DEFERRED_ERROR:
1909 retlen = snprintf(tmpstr, tmpstrlen, "Deferred Error: ");
1911 if ((tmplen = str_len - cur_len - 1) < 0)
1914 strncat(str, tmpstr, tmplen);
1916 str[str_len - 1] = '\0';
1918 case SSD_CURRENT_ERROR:
1920 retlen = snprintf(tmpstr, tmpstrlen, "%s",
1921 scsi_sense_key_text[sense_key]);
1923 if ((tmplen = str_len - cur_len - 1) < 0)
1926 strncat(str, tmpstr, tmplen);
1928 str[str_len - 1] = '\0';
1930 info = scsi_4btoul(sense->info);
1932 if (sense->error_code & SSD_ERRCODE_VALID) {
1934 switch (sense_key) {
1935 case SSD_KEY_NOT_READY:
1936 case SSD_KEY_ILLEGAL_REQUEST:
1937 case SSD_KEY_UNIT_ATTENTION:
1938 case SSD_KEY_DATA_PROTECT:
1940 case SSD_KEY_BLANK_CHECK:
1941 retlen = snprintf(tmpstr, tmpstrlen,
1942 " req sz: %d (decimal)",
1945 if ((tmplen = str_len - cur_len - 1) < 0)
1948 strncat(str, tmpstr, tmplen);
1950 str[str_len - 1] = '\0';
1954 if (sense->flags & SSD_ILI) {
1955 retlen = snprintf (tmpstr,
1958 "mismatch): %d", info);
1961 retlen = snprintf(tmpstr,
1967 if ((tmplen = str_len - cur_len -1) < 0)
1970 strncat(str, tmpstr, tmplen);
1972 str[str_len - 1] = '\0';
1976 retlen = snprintf(tmpstr, tmpstrlen," info?:%x", info);
1978 if ((tmplen = str_len - cur_len -1) < 0)
1981 strncat(str, tmpstr, tmplen);
1983 str[str_len - 1] = '\0';
1986 if (sense->extra_len >= 4) {
1987 if (bcmp(sense->cmd_spec_info, "\0\0\0\0", 4)) {
1988 retlen = snprintf(tmpstr, tmpstrlen,
1990 sense->cmd_spec_info[0],
1991 sense->cmd_spec_info[1],
1992 sense->cmd_spec_info[2],
1993 sense->cmd_spec_info[3]);
1995 if ((tmplen = str_len - cur_len -1) < 0)
1998 strncat(str, tmpstr, tmplen);
2000 str[str_len - 1] = '\0';
2004 asc = (sense->extra_len >= 5) ? sense->add_sense_code : 0;
2005 ascq = (sense->extra_len >= 6) ? sense->add_sense_code_qual : 0;
2008 const char *desc = scsi_sense_desc(asc, ascq,
2010 retlen = snprintf(tmpstr, tmpstrlen,
2011 " asc:%x,%x\n%s%s", asc, ascq,
2014 if ((tmplen = str_len - cur_len -1) < 0)
2017 strncat(str, tmpstr, tmplen);
2019 str[str_len - 1] = '\0';
2022 if (sense->extra_len >= 7 && sense->fru) {
2023 retlen = snprintf(tmpstr, tmpstrlen,
2024 " field replaceable unit: %x",
2027 if ((tmplen = str_len - cur_len -1) < 0)
2030 strncat(str, tmpstr, tmplen);
2031 str[str_len - 1] = '\0';
2035 if ((sense->extra_len >= 10)
2036 && (sense->sense_key_spec[0] & SSD_SCS_VALID) != 0) {
2037 retlen = snprintf(tmpstr, tmpstrlen, " sks:%x,%x",
2038 sense->sense_key_spec[0],
2039 scsi_2btoul(&sense->sense_key_spec[1]));
2041 if ((tmplen = str_len - cur_len -1) < 0)
2044 strncat(str, tmpstr, tmplen);
2045 str[str_len - 1] = '\0';
2051 retlen = snprintf(tmpstr, tmpstrlen, "error code %d",
2052 sense->error_code & SSD_ERRCODE);
2054 if ((tmplen = str_len - cur_len -1) < 0)
2057 strncat(str, tmpstr, tmplen);
2059 str[str_len - 1] = '\0';
2061 if (sense->error_code & SSD_ERRCODE_VALID) {
2062 retlen = snprintf(tmpstr, tmpstrlen,
2063 " at block no. %d (decimal)",
2064 info = scsi_4btoul(sense->info));
2066 if ((tmplen = str_len - cur_len -1) < 0)
2069 strncat(str, tmpstr, tmplen);
2071 str[str_len - 1] = '\0';
2075 retlen = snprintf(tmpstr, tmpstrlen, "\n");
2077 if ((tmplen = str_len - cur_len -1) < 0)
2080 strncat(str, tmpstr, tmplen);
2082 str[str_len - 1] = '\0';
2090 scsi_sense_print(struct cam_device *device, struct ccb_scsiio *csio,
2095 if ((device == NULL) || (csio == NULL) || (ofile == NULL))
2098 fprintf(ofile, "%s", scsi_sense_string(device, csio, str, 2048));
2101 #endif /* _KERNEL/!_KERNEL */
2105 scsi_interpret_sense(union ccb *ccb, u_int32_t sense_flags,
2106 u_int32_t *relsim_flags, u_int32_t *openings,
2107 u_int32_t *timeout, scsi_sense_action error_action)
2110 scsi_interpret_sense(struct cam_device *device, union ccb *ccb,
2111 u_int32_t sense_flags, u_int32_t *relsim_flags,
2112 u_int32_t *openings, u_int32_t *timeout,
2113 scsi_sense_action error_action)
2116 struct scsi_sense_data *sense;
2117 int error_code, sense_key, asc, ascq;
2120 struct ccb_scsiio *csio;
2124 sense = &csio->sense_data;
2125 scsi_extract_sense(sense, &error_code, &sense_key, &asc, &ascq);
2129 sense_flags |= SF_PRINT_ALWAYS;
2131 } else if ((sense_flags & SF_NO_PRINT) == 0)
2133 if ((sense_flags & SF_NO_PRINT) == 0)
2137 print_sense = FALSE;
2139 switch (error_code) {
2140 case SSD_DEFERRED_ERROR:
2143 * XXX dufault@FreeBSD.org
2144 * This error doesn't relate to the command associated
2145 * with this request sense. A deferred error is an error
2146 * for a command that has already returned GOOD status
2149 * By my reading of that section, it looks like the current
2150 * command has been cancelled, we should now clean things up
2151 * (hopefully recovering any lost data) and then retry the
2152 * current command. There are two easy choices, both wrong:
2154 * 1. Drop through (like we had been doing), thus treating
2155 * this as if the error were for the current command and
2156 * return and stop the current command.
2158 * 2. Issue a retry (like I made it do) thus hopefully
2159 * recovering the current transfer, and ignoring the
2160 * fact that we've dropped a command.
2162 * These should probably be handled in a device specific
2163 * sense handler or punted back up to a user mode daemon
2166 /* decrement the number of retries */
2167 retry = ccb->ccb_h.retry_count > 0;
2169 ccb->ccb_h.retry_count--;
2174 case SSD_CURRENT_ERROR:
2177 switch (sense_key) {
2178 case SSD_KEY_NO_SENSE:
2179 /* Why were we called then? Well don't bail now */
2182 /* These should be filtered by the peripheral drivers */
2183 print_sense = FALSE;
2185 case SSD_KEY_MISCOMPARE:
2186 /* decrement the number of retries */
2187 retry = ccb->ccb_h.retry_count > 0;
2190 ccb->ccb_h.retry_count--;
2194 case SSD_KEY_RECOVERED_ERROR:
2195 error = 0; /* not an error */
2197 case SSD_KEY_ILLEGAL_REQUEST:
2198 if (((sense_flags & SF_QUIET_IR) != 0)
2199 && ((sense_flags & SF_PRINT_ALWAYS) == 0))
2200 print_sense = FALSE;
2203 case SSD_KEY_NOT_READY:
2204 case SSD_KEY_DATA_PROTECT:
2205 case SSD_KEY_VOLUME_OVERFLOW:
2206 case SSD_KEY_BLANK_CHECK: /* should be filtered out by
2207 peripheral drivers */
2208 retry = ccb->ccb_h.retry_count > 0;
2210 ccb->ccb_h.retry_count--;
2212 print_sense = FALSE;
2214 if (((error_action & SSQ_PRINT_SENSE) == 0)
2215 && ((sense_flags & SF_PRINT_ALWAYS) == 0))
2216 print_sense = FALSE;
2218 error = error_action & SS_ERRMASK;
2222 case SSD_KEY_UNIT_ATTENTION:
2224 * This should also be filtered out by
2225 * peripheral drivers since each has a different
2226 * concept of what it means to invalidate the media.
2228 if ((sense_flags & SF_RETRY_UA) != 0) {
2229 /* don't decrement retry count */
2231 print_sense = FALSE;
2233 /* decrement the number of retries */
2234 retry = ccb->ccb_h.retry_count > 0;
2236 ccb->ccb_h.retry_count--;
2238 print_sense = FALSE;
2240 if (((error_action &
2241 SSQ_PRINT_SENSE) == 0)
2243 SF_PRINT_ALWAYS) == 0))
2244 print_sense = FALSE;
2246 error = error_action & SS_ERRMASK;
2250 case SSD_KEY_ABORTED_COMMAND:
2252 /* decrement the number of retries */
2253 retry = ccb->ccb_h.retry_count > 0;
2255 ccb->ccb_h.retry_count--;
2257 print_sense = FALSE;
2259 if (((error_action & SSQ_PRINT_SENSE) == 0)
2260 && ((sense_flags & SF_PRINT_ALWAYS) == 0))
2261 print_sense = FALSE;
2263 error = error_action & SS_ERRMASK;
2266 * Make sure ABORTED COMMAND errors get
2267 * printed as they're indicative of marginal
2268 * SCSI busses that people should address.
2270 if (sense_key == SSD_KEY_ABORTED_COMMAND)
2276 /* decrement the number of retries */
2277 retry = ccb->ccb_h.retry_count > 0;
2279 ccb->ccb_h.retry_count--;
2281 print_sense = FALSE;
2289 scsi_sense_print(csio);
2291 scsi_sense_print(device, csio, stdout);
2299 * This function currently requires at least 36 bytes, or
2300 * SHORT_INQUIRY_LENGTH, worth of data to function properly. If this
2301 * function needs more or less data in the future, another length should be
2302 * defined in scsi_all.h to indicate the minimum amount of data necessary
2303 * for this routine to function properly.
2306 scsi_print_inquiry(struct scsi_inquiry_data *inq_data)
2309 char *dtype, *qtype;
2310 char vendor[16], product[48], revision[16], rstr[4];
2312 type = SID_TYPE(inq_data);
2315 * Figure out basic device type and qualifier.
2317 if (SID_QUAL_IS_VENDOR_UNIQUE(inq_data)) {
2318 qtype = "(vendor-unique qualifier)";
2320 switch (SID_QUAL(inq_data)) {
2321 case SID_QUAL_LU_CONNECTED:
2325 case SID_QUAL_LU_OFFLINE:
2326 qtype = "(offline)";
2330 qtype = "(reserved qualifier)";
2333 case SID_QUAL_BAD_LU:
2334 qtype = "(lun not supported)";
2341 dtype = "Direct Access";
2344 dtype = "Sequential Access";
2350 dtype = "Processor";
2368 dtype = "Communication";
2371 dtype = "Storage Array";
2374 dtype = "Enclosure Services";
2377 dtype = "Simplified Direct Access";
2380 dtype = "Optical Card Read/Write";
2383 dtype = "Uninstalled";
2389 cam_strvis(vendor, inq_data->vendor, sizeof(inq_data->vendor),
2391 cam_strvis(product, inq_data->product, sizeof(inq_data->product),
2393 cam_strvis(revision, inq_data->revision, sizeof(inq_data->revision),
2396 if (SID_ANSI_REV(inq_data) == SCSI_REV_CCS)
2397 bcopy("CCS", rstr, 4);
2399 snprintf(rstr, sizeof (rstr), "%d", SID_ANSI_REV(inq_data));
2400 printf("<%s %s %s> %s %s SCSI-%s device %s\n",
2401 vendor, product, revision,
2402 SID_IS_REMOVABLE(inq_data) ? "Removable" : "Fixed",
2403 dtype, rstr, qtype);
2407 * Table of syncrates that don't follow the "divisible by 4"
2408 * rule. This table will be expanded in future SCSI specs.
2411 u_int period_factor;
2412 u_int period; /* in 100ths of ns */
2413 } scsi_syncrates[] = {
2414 { 0x08, 625 }, /* FAST-160 */
2415 { 0x09, 1250 }, /* FAST-80 */
2416 { 0x0a, 2500 }, /* FAST-40 40MHz */
2417 { 0x0b, 3030 }, /* FAST-40 33MHz */
2418 { 0x0c, 5000 } /* FAST-20 */
2422 * Return the frequency in kHz corresponding to the given
2423 * sync period factor.
2426 scsi_calc_syncsrate(u_int period_factor)
2431 num_syncrates = sizeof(scsi_syncrates) / sizeof(scsi_syncrates[0]);
2432 /* See if the period is in the "exception" table */
2433 for (i = 0; i < num_syncrates; i++) {
2435 if (period_factor == scsi_syncrates[i].period_factor) {
2437 return (100000000 / scsi_syncrates[i].period);
2442 * Wasn't in the table, so use the standard
2443 * 4 times conversion.
2445 return (10000000 / (period_factor * 4 * 10));
2449 * Return the SCSI sync parameter that corresponsd to
2450 * the passed in period in 10ths of ns.
2453 scsi_calc_syncparam(u_int period)
2459 return (~0); /* Async */
2461 /* Adjust for exception table being in 100ths. */
2463 num_syncrates = sizeof(scsi_syncrates) / sizeof(scsi_syncrates[0]);
2464 /* See if the period is in the "exception" table */
2465 for (i = 0; i < num_syncrates; i++) {
2467 if (period <= scsi_syncrates[i].period) {
2468 /* Period in 100ths of ns */
2469 return (scsi_syncrates[i].period_factor);
2474 * Wasn't in the table, so use the standard
2475 * 1/4 period in ns conversion.
2477 return (period/400);
2481 scsi_test_unit_ready(struct ccb_scsiio *csio, u_int32_t retries,
2482 void (*cbfcnp)(struct cam_periph *, union ccb *),
2483 u_int8_t tag_action, u_int8_t sense_len, u_int32_t timeout)
2485 struct scsi_test_unit_ready *scsi_cmd;
2498 scsi_cmd = (struct scsi_test_unit_ready *)&csio->cdb_io.cdb_bytes;
2499 bzero(scsi_cmd, sizeof(*scsi_cmd));
2500 scsi_cmd->opcode = TEST_UNIT_READY;
2504 scsi_request_sense(struct ccb_scsiio *csio, u_int32_t retries,
2505 void (*cbfcnp)(struct cam_periph *, union ccb *),
2506 void *data_ptr, u_int8_t dxfer_len, u_int8_t tag_action,
2507 u_int8_t sense_len, u_int32_t timeout)
2509 struct scsi_request_sense *scsi_cmd;
2522 scsi_cmd = (struct scsi_request_sense *)&csio->cdb_io.cdb_bytes;
2523 bzero(scsi_cmd, sizeof(*scsi_cmd));
2524 scsi_cmd->opcode = REQUEST_SENSE;
2528 scsi_inquiry(struct ccb_scsiio *csio, u_int32_t retries,
2529 void (*cbfcnp)(struct cam_periph *, union ccb *),
2530 u_int8_t tag_action, u_int8_t *inq_buf, u_int32_t inq_len,
2531 int evpd, u_int8_t page_code, u_int8_t sense_len,
2534 struct scsi_inquiry *scsi_cmd;
2539 /*flags*/CAM_DIR_IN,
2541 /*data_ptr*/inq_buf,
2542 /*dxfer_len*/inq_len,
2547 scsi_cmd = (struct scsi_inquiry *)&csio->cdb_io.cdb_bytes;
2548 bzero(scsi_cmd, sizeof(*scsi_cmd));
2549 scsi_cmd->opcode = INQUIRY;
2551 scsi_cmd->byte2 |= SI_EVPD;
2552 scsi_cmd->page_code = page_code;
2555 * A 'transfer units' count of 256 is coded as
2556 * zero for all commands with a single byte count
2561 scsi_cmd->length = inq_len;
2565 scsi_mode_sense(struct ccb_scsiio *csio, u_int32_t retries,
2566 void (*cbfcnp)(struct cam_periph *, union ccb *),
2567 u_int8_t tag_action, int dbd, u_int8_t page_code,
2568 u_int8_t page, u_int8_t *param_buf, u_int32_t param_len,
2569 u_int8_t sense_len, u_int32_t timeout)
2574 * Use the smallest possible command to perform the operation.
2576 if (param_len < 256) {
2578 * We can fit in a 6 byte cdb.
2580 struct scsi_mode_sense_6 *scsi_cmd;
2582 scsi_cmd = (struct scsi_mode_sense_6 *)&csio->cdb_io.cdb_bytes;
2583 bzero(scsi_cmd, sizeof(*scsi_cmd));
2584 scsi_cmd->opcode = MODE_SENSE_6;
2586 scsi_cmd->byte2 |= SMS_DBD;
2587 scsi_cmd->page = page_code | page;
2588 scsi_cmd->length = param_len;
2589 cdb_len = sizeof(*scsi_cmd);
2592 * Need a 10 byte cdb.
2594 struct scsi_mode_sense_10 *scsi_cmd;
2596 scsi_cmd = (struct scsi_mode_sense_10 *)&csio->cdb_io.cdb_bytes;
2597 bzero(scsi_cmd, sizeof(*scsi_cmd));
2598 scsi_cmd->opcode = MODE_SENSE_10;
2600 scsi_cmd->byte2 |= SMS_DBD;
2601 scsi_cmd->page = page_code | page;
2602 scsi_ulto2b(param_len, scsi_cmd->length);
2603 cdb_len = sizeof(*scsi_cmd);
2618 scsi_mode_select(struct ccb_scsiio *csio, u_int32_t retries,
2619 void (*cbfcnp)(struct cam_periph *, union ccb *),
2620 u_int8_t tag_action, int scsi_page_fmt, int save_pages,
2621 u_int8_t *param_buf, u_int32_t param_len, u_int8_t sense_len,
2627 * Use the smallest possible command to perform the operation.
2629 if (param_len < 256) {
2631 * We can fit in a 6 byte cdb.
2633 struct scsi_mode_select_6 *scsi_cmd;
2635 scsi_cmd = (struct scsi_mode_select_6 *)&csio->cdb_io.cdb_bytes;
2636 bzero(scsi_cmd, sizeof(*scsi_cmd));
2637 scsi_cmd->opcode = MODE_SELECT_6;
2638 if (scsi_page_fmt != 0)
2639 scsi_cmd->byte2 |= SMS_PF;
2640 if (save_pages != 0)
2641 scsi_cmd->byte2 |= SMS_SP;
2642 scsi_cmd->length = param_len;
2643 cdb_len = sizeof(*scsi_cmd);
2646 * Need a 10 byte cdb.
2648 struct scsi_mode_select_10 *scsi_cmd;
2651 (struct scsi_mode_select_10 *)&csio->cdb_io.cdb_bytes;
2652 bzero(scsi_cmd, sizeof(*scsi_cmd));
2653 scsi_cmd->opcode = MODE_SELECT_10;
2654 if (scsi_page_fmt != 0)
2655 scsi_cmd->byte2 |= SMS_PF;
2656 if (save_pages != 0)
2657 scsi_cmd->byte2 |= SMS_SP;
2658 scsi_ulto2b(param_len, scsi_cmd->length);
2659 cdb_len = sizeof(*scsi_cmd);
2674 /* XXX allow specification of address and PMI bit and LBA */
2676 scsi_read_capacity(struct ccb_scsiio *csio, u_int32_t retries,
2677 void (*cbfcnp)(struct cam_periph *, union ccb *),
2678 u_int8_t tag_action,
2679 struct scsi_read_capacity_data *rcap_buf,
2680 u_int8_t sense_len, u_int32_t timeout)
2682 struct scsi_read_capacity *scsi_cmd;
2687 /*flags*/CAM_DIR_IN,
2689 /*data_ptr*/(u_int8_t *)rcap_buf,
2690 /*dxfer_len*/sizeof(*rcap_buf),
2695 scsi_cmd = (struct scsi_read_capacity *)&csio->cdb_io.cdb_bytes;
2696 bzero(scsi_cmd, sizeof(*scsi_cmd));
2697 scsi_cmd->opcode = READ_CAPACITY;
2701 * Prevent or allow the user to remove the media
2704 scsi_prevent(struct ccb_scsiio *csio, u_int32_t retries,
2705 void (*cbfcnp)(struct cam_periph *, union ccb *),
2706 u_int8_t tag_action, u_int8_t action,
2707 u_int8_t sense_len, u_int32_t timeout)
2709 struct scsi_prevent *scsi_cmd;
2714 /*flags*/CAM_DIR_NONE,
2722 scsi_cmd = (struct scsi_prevent *)&csio->cdb_io.cdb_bytes;
2723 bzero(scsi_cmd, sizeof(*scsi_cmd));
2724 scsi_cmd->opcode = PREVENT_ALLOW;
2725 scsi_cmd->how = action;
2729 * Syncronize the media to the contents of the cache for
2730 * the given lba/count pair. Specifying 0/0 means sync
2734 scsi_synchronize_cache(struct ccb_scsiio *csio, u_int32_t retries,
2735 void (*cbfcnp)(struct cam_periph *, union ccb *),
2736 u_int8_t tag_action, u_int32_t begin_lba,
2737 u_int16_t lb_count, u_int8_t sense_len,
2740 struct scsi_sync_cache *scsi_cmd;
2745 /*flags*/CAM_DIR_NONE,
2753 scsi_cmd = (struct scsi_sync_cache *)&csio->cdb_io.cdb_bytes;
2754 bzero(scsi_cmd, sizeof(*scsi_cmd));
2755 scsi_cmd->opcode = SYNCHRONIZE_CACHE;
2756 scsi_ulto4b(begin_lba, scsi_cmd->begin_lba);
2757 scsi_ulto2b(lb_count, scsi_cmd->lb_count);
2761 scsi_read_write(struct ccb_scsiio *csio, u_int32_t retries,
2762 void (*cbfcnp)(struct cam_periph *, union ccb *),
2763 u_int8_t tag_action, int readop, u_int8_t byte2,
2764 int minimum_cmd_size, u_int32_t lba, u_int32_t block_count,
2765 u_int8_t *data_ptr, u_int32_t dxfer_len, u_int8_t sense_len,
2770 * Use the smallest possible command to perform the operation
2771 * as some legacy hardware does not support the 10 byte
2772 * commands. If any of the lower 5 bits in byte2 is set, we have
2773 * to go with a larger command.
2776 if ((minimum_cmd_size < 10)
2777 && ((lba & 0x1fffff) == lba)
2778 && ((block_count & 0xff) == block_count)
2779 && ((byte2 & 0xe0) == 0)) {
2781 * We can fit in a 6 byte cdb.
2783 struct scsi_rw_6 *scsi_cmd;
2785 scsi_cmd = (struct scsi_rw_6 *)&csio->cdb_io.cdb_bytes;
2786 scsi_cmd->opcode = readop ? READ_6 : WRITE_6;
2787 scsi_ulto3b(lba, scsi_cmd->addr);
2788 scsi_cmd->length = block_count & 0xff;
2789 scsi_cmd->control = 0;
2790 cdb_len = sizeof(*scsi_cmd);
2792 CAM_DEBUG(csio->ccb_h.path, CAM_DEBUG_SUBTRACE,
2793 ("6byte: %x%x%x:%d:%d\n", scsi_cmd->addr[0],
2794 scsi_cmd->addr[1], scsi_cmd->addr[2],
2795 scsi_cmd->length, dxfer_len));
2796 } else if ((minimum_cmd_size < 12)
2797 && ((block_count & 0xffff) == block_count)) {
2799 * Need a 10 byte cdb.
2801 struct scsi_rw_10 *scsi_cmd;
2803 scsi_cmd = (struct scsi_rw_10 *)&csio->cdb_io.cdb_bytes;
2804 scsi_cmd->opcode = readop ? READ_10 : WRITE_10;
2805 scsi_cmd->byte2 = byte2;
2806 scsi_ulto4b(lba, scsi_cmd->addr);
2807 scsi_cmd->reserved = 0;
2808 scsi_ulto2b(block_count, scsi_cmd->length);
2809 scsi_cmd->control = 0;
2810 cdb_len = sizeof(*scsi_cmd);
2812 CAM_DEBUG(csio->ccb_h.path, CAM_DEBUG_SUBTRACE,
2813 ("10byte: %x%x%x%x:%x%x: %d\n", scsi_cmd->addr[0],
2814 scsi_cmd->addr[1], scsi_cmd->addr[2],
2815 scsi_cmd->addr[3], scsi_cmd->length[0],
2816 scsi_cmd->length[1], dxfer_len));
2819 * The block count is too big for a 10 byte CDB, use a 12
2820 * byte CDB. READ/WRITE(12) are currently only defined for
2823 struct scsi_rw_12 *scsi_cmd;
2825 scsi_cmd = (struct scsi_rw_12 *)&csio->cdb_io.cdb_bytes;
2826 scsi_cmd->opcode = readop ? READ_12 : WRITE_12;
2827 scsi_cmd->byte2 = byte2;
2828 scsi_ulto4b(lba, scsi_cmd->addr);
2829 scsi_cmd->reserved = 0;
2830 scsi_ulto4b(block_count, scsi_cmd->length);
2831 scsi_cmd->control = 0;
2832 cdb_len = sizeof(*scsi_cmd);
2834 CAM_DEBUG(csio->ccb_h.path, CAM_DEBUG_SUBTRACE,
2835 ("12byte: %x%x%x%x:%x%x%x%x: %d\n", scsi_cmd->addr[0],
2836 scsi_cmd->addr[1], scsi_cmd->addr[2],
2837 scsi_cmd->addr[3], scsi_cmd->length[0],
2838 scsi_cmd->length[1], scsi_cmd->length[2],
2839 scsi_cmd->length[3], dxfer_len));
2844 /*flags*/readop ? CAM_DIR_IN : CAM_DIR_OUT,
2854 scsi_start_stop(struct ccb_scsiio *csio, u_int32_t retries,
2855 void (*cbfcnp)(struct cam_periph *, union ccb *),
2856 u_int8_t tag_action, int start, int load_eject,
2857 int immediate, u_int8_t sense_len, u_int32_t timeout)
2859 struct scsi_start_stop_unit *scsi_cmd;
2860 int extra_flags = 0;
2862 scsi_cmd = (struct scsi_start_stop_unit *)&csio->cdb_io.cdb_bytes;
2863 bzero(scsi_cmd, sizeof(*scsi_cmd));
2864 scsi_cmd->opcode = START_STOP_UNIT;
2866 scsi_cmd->how |= SSS_START;
2867 /* it takes a lot of power to start a drive */
2868 extra_flags |= CAM_HIGH_POWER;
2870 if (load_eject != 0)
2871 scsi_cmd->how |= SSS_LOEJ;
2873 scsi_cmd->byte2 |= SSS_IMMED;
2878 /*flags*/CAM_DIR_NONE | extra_flags,
2890 * Try make as good a match as possible with
2891 * available sub drivers
2894 scsi_inquiry_match(caddr_t inqbuffer, caddr_t table_entry)
2896 struct scsi_inquiry_pattern *entry;
2897 struct scsi_inquiry_data *inq;
2899 entry = (struct scsi_inquiry_pattern *)table_entry;
2900 inq = (struct scsi_inquiry_data *)inqbuffer;
2902 if (((SID_TYPE(inq) == entry->type)
2903 || (entry->type == T_ANY))
2904 && (SID_IS_REMOVABLE(inq) ? entry->media_type & SIP_MEDIA_REMOVABLE
2905 : entry->media_type & SIP_MEDIA_FIXED)
2906 && (cam_strmatch(inq->vendor, entry->vendor, sizeof(inq->vendor)) == 0)
2907 && (cam_strmatch(inq->product, entry->product,
2908 sizeof(inq->product)) == 0)
2909 && (cam_strmatch(inq->revision, entry->revision,
2910 sizeof(inq->revision)) == 0)) {
2917 * Try make as good a match as possible with
2918 * available sub drivers
2921 scsi_static_inquiry_match(caddr_t inqbuffer, caddr_t table_entry)
2923 struct scsi_static_inquiry_pattern *entry;
2924 struct scsi_inquiry_data *inq;
2926 entry = (struct scsi_static_inquiry_pattern *)table_entry;
2927 inq = (struct scsi_inquiry_data *)inqbuffer;
2929 if (((SID_TYPE(inq) == entry->type)
2930 || (entry->type == T_ANY))
2931 && (SID_IS_REMOVABLE(inq) ? entry->media_type & SIP_MEDIA_REMOVABLE
2932 : entry->media_type & SIP_MEDIA_FIXED)
2933 && (cam_strmatch(inq->vendor, entry->vendor, sizeof(inq->vendor)) == 0)
2934 && (cam_strmatch(inq->product, entry->product,
2935 sizeof(inq->product)) == 0)
2936 && (cam_strmatch(inq->revision, entry->revision,
2937 sizeof(inq->revision)) == 0)) {